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;
}
Exemplo n.º 2
0
// 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;
}