bool ArchiveDataClient::getValues(int key, stdVector<stdString> &names,
                                  const epicsTime &start, const epicsTime &end,
                                  int count, int how,
                                  value_callback callback, void *callback_arg)
{
    xmlrpc_value *name_array, *result, *element;
    size_t n;
    name_array = xmlrpc_build_value(&env, "()");
    if (log_fault())
        return false;
     for (n=0; n<names.size(); ++n)
    {
        element = xmlrpc_build_value(&env, "s", names[n].c_str());
        if (log_fault())
            return false;
        xmlrpc_array_append_item(&env, name_array, element);
        if (log_fault())
            return false;
        xmlrpc_DECREF(element);
    }
    xmlrpc_int32 start_sec, start_nano, end_sec, end_nano;
    epicsTime2pieces(start, start_sec, start_nano);
    epicsTime2pieces(end, end_sec, end_nano);
    result = xmlrpc_client_call(&env, (char *)URL,
                                "archiver.values", "(iViiiiii)",
                                (xmlrpc_int32)key, name_array,
                                start_sec, start_nano, end_sec, end_nano,
                                (xmlrpc_int32)count, (xmlrpc_int32)how);
    if (log_fault())
        return false;
    xmlrpc_DECREF(name_array);
    size_t channel_count = xmlrpc_array_size(&env, result);
    xmlrpc_value *channel_result;
    for (n=0; n<channel_count; ++n)
    {
        channel_result = xmlrpc_array_get_item(&env, result, n);
        if (log_fault())
            return false;
        if (!decode_channel(channel_result, n, callback, callback_arg))
            return false;
    }
    xmlrpc_DECREF(result);
    return true;
}
Esempio n. 2
0
    // "visitor" for BinaryTree of channel names
    static void add_name_to_result(const ChannelInfo &info, void *arg)
    {
        UserArg *user_arg = (UserArg *)arg;
        xmlrpc_int32 ss, sn, es, en;
        epicsTime2pieces(info.start, ss, sn);
        epicsTime2pieces(info.end, es, en);        

        LOG_MSG("Found name '%s'\n", info.name.c_str());

        AutoXmlRpcValue channel(xmlrpc_build_value(
                                    user_arg->env,
                                    "{s:s,s:i,s:i,s:i,s:i}",
                                    "name", info.name.c_str(),
                                    "start_sec", ss, "start_nano", sn,
                                    "end_sec", es,   "end_nano", en));
        if (user_arg->env->fault_occurred)
            return;
        xmlrpc_array_append_item(user_arg->env, user_arg->result, channel);
    }
Esempio n. 3
0
// Given a raw sample dbr_type/count/time/data,
// map it onto xml_type/count and add to values.
// Handles the special case data == 0,
// which happens for undefined cells in a SpreadsheetReader.
void encode_value(xmlrpc_env *env,
                  DbrType dbr_type, DbrCount dbr_count,
                  const epicsTime &time, const RawValue::Data *data,
                  xmlrpc_int32 xml_type, xmlrpc_int32 xml_count,
                  xmlrpc_value *values)
{
    if (xml_count > dbr_count)
        xml_count = dbr_count;
    AutoXmlRpcValue val_array(xmlrpc_build_value(env, "()"));
    if (env->fault_occurred)
        return;
    int i;
    switch (xml_type)
    {
        case XML_STRING:
        {
            stdString txt;
            if (data)
                RawValue::getValueString(txt, dbr_type, dbr_count, data, 0);
            AutoXmlRpcValue element(xmlrpc_build_value(env, "s#",
                                                       txt.c_str(), txt.length()));
            xmlrpc_array_append_item(env, val_array, element);
        }
        break;
        case XML_INT:
        case XML_ENUM:
        {
            long l;
            for (i=0; i < xml_count; ++i)
            {
                if (!data  ||
                    !RawValue::getLong(dbr_type, dbr_count, data, l, i))
                    l = 0;
                AutoXmlRpcValue element(xmlrpc_build_value(env, "i", (xmlrpc_int32)l));
                xmlrpc_array_append_item(env, val_array, element);
            }
        }
        break;
        case XML_DOUBLE:
        {
            double d;
            for (i=0; i < xml_count; ++i)
            {
                if (data  &&
                    RawValue::getDouble(dbr_type, dbr_count, data, d, i))
                
                {   /* XML-RPC, being XML, sends all numbers as strings.
                     * Unfortunately, XML-RPC also insists in the simple 'dot'
                     * notation and prohibits exponential notation.
                     * A number like 1e-300 would turn into
                     * "0.0000000..." with 300 zeroes,
                     * which is too long for the internal print buffer of
                     * the xml-rpc C library.
                     * Since such huge and tiny numbers can't be transferred,
                     * they are replaced by 0 with stat/sevr UDF/INVALID.
                     *
                     * The cut-off point is somewhat arbitrary.
                     * The XML-RPC library uses an internal print buffer
                     * of about 120 characters.
                     * Since PVs are usually scaled to be human-readable,
                     * with only vacuum readings using exp. notation for
                     * data like "1e-8 Torr", exponents of +-50 seemed
                     * reasonable.
                     */
                    if (d > 0.0)
                    {
                        if (d < 1e-50  ||  d > 1e50)   { d = 0.0; data = 0; }
                    }
                    else if (d < 0.0)
                    {  
                        if (d > -1e-50  ||  d < -1e50) { d = 0.0; data = 0; }
                    }
                } 
                else
                    d = 0.0;
                AutoXmlRpcValue element(xmlrpc_build_value(env, "d", d));
                xmlrpc_array_append_item(env, val_array, element);
            }
        }
    }
    xmlrpc_int32 secs, nano;
    epicsTime2pieces(time, secs, nano);
    AutoXmlRpcValue value;
    if (data)
        value.set(xmlrpc_build_value(
                      env, "{s:i,s:i,s:i,s:i,s:V}",
                      "stat", (xmlrpc_int32)RawValue::getStat(data),
                      "sevr", (xmlrpc_int32)RawValue::getSevr(data),
                      "secs", secs,
                      "nano", nano,
                      "value", (xmlrpc_value *)val_array));
    else
        value.set(xmlrpc_build_value(
                      env, "{s:i,s:i,s:i,s:i,s:V}",
                      "stat", (xmlrpc_int32)UDF_ALARM,
                      "sevr", (xmlrpc_int32)INVALID_ALARM,
                      "secs", secs,
                      "nano", nano,
                      "value",  (xmlrpc_value *)val_array));    
    xmlrpc_array_append_item(env, values, value);
}