bool ArchiveDataClient::getNames(int key, const stdString &pattern, stdVector<NameInfo> &names) { xmlrpc_value *result, *element; const char *name; xmlrpc_int32 start_sec, start_nano, end_sec, end_nano; size_t count, i, len; NameInfo info; result = xmlrpc_client_call(&env, (char *)URL, "archiver.names", "(is)", (xmlrpc_int32) key, pattern.c_str()); if (log_fault()) return false; count = xmlrpc_array_size(&env, result); names.reserve(count); for (i=0; i<count; ++i) { element = xmlrpc_array_get_item(&env, result, i); if (log_fault()) return false; xmlrpc_parse_value(&env, element, "{s:s#,s:i,s:i,s:i,s:i,*}", "name", &name, &len, "start_sec", &start_sec, "start_nano", &start_nano, "end_sec", &end_sec, "end_nano", &end_nano); if (log_fault()) return false; info.name.assign(name, len); pieces2epicsTime(start_sec, start_nano, info.start); pieces2epicsTime(end_sec, end_nano, info.end); names.push_back(info); } xmlrpc_DECREF(result); return true; }
// very_complex_array = archiver.values(key, names[], start, end, ...) xmlrpc_value *get_values(xmlrpc_env *env, xmlrpc_value *args, void *user) { #ifdef LOGFILE LOG_MSG("archiver.get_values\n"); #endif xmlrpc_value *names; xmlrpc_int32 key, start_sec, start_nano, end_sec, end_nano, count, how; xmlrpc_int32 actual_count; // Extract arguments xmlrpc_parse_value(env, args, "(iAiiiiii)", &key, &names, &start_sec, &start_nano, &end_sec, &end_nano, &count, &how); if (env->fault_occurred) return 0; #ifdef LOGFILE LOG_MSG("how=%d, count=%d\n", (int) how, (int) count); #endif if (count <= 1) count = 1; actual_count = count; if (count > 10000) // Upper limit to avoid outrageous requests. actual_count = 10000; // Build start/end epicsTime start, end; pieces2epicsTime(start_sec, start_nano, start); pieces2epicsTime(end_sec, end_nano, end); // Pull names into vector for SpreadsheetReader and just because. xmlrpc_value *name_val; char *name; int i; xmlrpc_int32 name_count = xmlrpc_array_size(env, names); stdVector<stdString> name_vector; name_vector.reserve(name_count); for (i=0; i<name_count; ++i) { // no new ref! name_val = xmlrpc_array_get_item(env, names, i); if (env->fault_occurred) return 0; xmlrpc_parse_value(env, name_val, "s", &name); if (env->fault_occurred) return 0; name_vector.push_back(stdString(name)); } // Build results switch (how) { case HOW_RAW: return get_channel_data(env, key, name_vector, start, end, actual_count, ReaderFactory::Raw, 0.0); case HOW_SHEET: return get_sheet_data(env, key, name_vector, start, end, actual_count, ReaderFactory::Raw, 0.0); case HOW_AVERAGE: return get_sheet_data(env, key, name_vector, start, end, actual_count, ReaderFactory::Average, (end-start)/count); case HOW_PLOTBIN: // 'count' = # of bins, resulting in up to 4*count samples return get_channel_data(env, key, name_vector, start, end, actual_count*4, ReaderFactory::Plotbin, (end-start)/count); case HOW_LINEAR: return get_sheet_data(env, key, name_vector, start, end, actual_count, ReaderFactory::Linear, (end-start)/count); } xmlrpc_env_set_fault_formatted(env, ARCH_DAT_ARG_ERROR, "Invalid how=%d", how); return 0; }
bool ArchiveDataClient::decode_data(const char *name, xmlrpc_int32 type, xmlrpc_int32 count, xmlrpc_value *data_array, CtrlInfo &ctrlinfo, size_t n, value_callback callback, void *callback_arg) { size_t i, num, v, v_num; xmlrpc_int32 stat, sevr, secs, nano; xmlrpc_value *data, *value_array, *value; epicsTime stamp; DbrType dbr_type; RawValue::Data *raw_value; switch (type) { case XML_STRING: dbr_type = DBR_TIME_STRING; break; case XML_ENUM: dbr_type = DBR_TIME_ENUM; break; case XML_INT: dbr_type = DBR_TIME_LONG; break; case XML_DOUBLE: dbr_type = DBR_TIME_DOUBLE; break; default: LOG_MSG("Cannot decode data type %d\n", type); return false; } raw_value = RawValue::allocate(dbr_type, count, 1); num = xmlrpc_array_size(&env, data_array); if (log_fault()) return false; for (i=0; i<num; ++i) { data = xmlrpc_array_get_item(&env, data_array, i); xmlrpc_parse_value(&env, data, "{s:i,s:i,s:i,s:i,s:A,*}", "stat", &stat, "sevr", &sevr, "secs", &secs, "nano", &nano, "value", &value_array); if (log_fault()) return false; pieces2epicsTime(secs, nano, stamp); RawValue::setStatus(raw_value, stat, sevr); RawValue::setTime(raw_value, stamp); v_num = xmlrpc_array_size(&env, value_array); if (log_fault()) return false; if (v_num != (size_t)count) { LOG_MSG("value size discrepancy, %zu != %zu\n", v_num, (size_t)count); return false; } for (v=0; v<v_num; ++v) { value = xmlrpc_array_get_item(&env, value_array, v); if (log_fault()) return false; switch (dbr_type) { case DBR_TIME_STRING: { if (v > 0) break; const char *txt; size_t len; xmlrpc_parse_value(&env, value, "s#", &txt, &len); if (len >= MAX_STRING_SIZE) len = MAX_STRING_SIZE-1; memcpy(((dbr_time_string *)raw_value)->value, txt, len); ((dbr_time_string *)raw_value)->value[len] = '\0'; } break; case DBR_TIME_ENUM: { dbr_enum_t *val = &((dbr_time_enum *)raw_value)->value; xmlrpc_int32 ival; xmlrpc_parse_value(&env, value, "i", &ival); val[v] = ival; if (log_fault()) return false; } break; case DBR_TIME_LONG: { dbr_long_t *val = &((dbr_time_long *)raw_value)->value; xmlrpc_int32 ival; xmlrpc_parse_value(&env, value, "i", &ival); val[v] = ival; if (log_fault()) return false; } break; case DBR_TIME_DOUBLE: { double *val = &((dbr_time_double *)raw_value)->value; xmlrpc_parse_value(&env, value, "d", &val[v]); if (log_fault()) return false; } break; } } if (!callback(callback_arg, name, n, i, ctrlinfo, dbr_type, count, raw_value)) break; } RawValue::free(raw_value); return true; }