MIDAS
Loading...
Searching...
No Matches
mjsonrpc.cxx File Reference
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <map>
#include "mjson.h"
#include "midas.h"
#include "msystem.h"
#include "mstrlcpy.h"
#include "mjsonrpc.h"
#include <mutex>
#include "history.h"
Include dependency graph for mjsonrpc.cxx:

Go to the source code of this file.

Classes

class  JsonHistoryBuffer
 
class  BinaryHistoryBuffer
 
struct  EventStashEntry
 
struct  MethodsTableEntry
 
struct  NestedLine
 
class  NestedOutput
 

Typedefs

typedef std::map< std::string, MidasHistoryInterface * > MhiMap
 
typedef std::map< std::string, MethodsTableEntryMethodsTable
 
typedef MethodsTable::iterator MethodsTableIterator
 

Functions

static double GetTimeSec ()
 
MJsonNode * mjsonrpc_make_error (int code, const char *message, const char *data)
 
MJsonNode * mjsonrpc_make_result (MJsonNode *node)
 
MJsonNode * mjsonrpc_make_result (const char *name, MJsonNode *value, const char *name2, MJsonNode *value2, const char *name3, MJsonNode *value3)
 
MJsonNode * mjsonrpc_make_result (const char *name, MJsonNode *value, const char *name2, MJsonNode *value2, const char *name3, MJsonNode *value3, const char *name4, MJsonNode *value4)
 
const MJsonNode * mjsonrpc_get_param (const MJsonNode *params, const char *name, MJsonNode **error)
 
const MJsonNodeVector * mjsonrpc_get_param_array (const MJsonNode *params, const char *name, MJsonNode **error)
 
static std::string remove (const std::string s, char c)
 
static MJsonNode * xnull (const MJsonNode *params)
 
static MJsonNode * js_cm_exist (const MJsonNode *params)
 
static MJsonNode * js_cm_shutdown (const MJsonNode *params)
 
static MJsonNode * start_program (const MJsonNode *params)
 
static MJsonNode * exec_script (const MJsonNode *params)
 
static int parse_array_index_list (const char *method, const char *path, std::vector< unsigned > *list)
 
static MJsonNode * js_db_get_values (const MJsonNode *params)
 
static MJsonNode * js_db_ls (const MJsonNode *params)
 
static MJsonNode * js_db_copy (const MJsonNode *params)
 
static MJsonNode * js_db_paste (const MJsonNode *params)
 
static MJsonNode * js_db_create (const MJsonNode *params)
 
static MJsonNode * js_db_delete (const MJsonNode *params)
 
static MJsonNode * js_db_resize (const MJsonNode *params)
 
static MJsonNode * js_db_resize_string (const MJsonNode *params)
 
static MJsonNode * js_db_key (const MJsonNode *params)
 
static MJsonNode * js_db_rename (const MJsonNode *params)
 
static MJsonNode * js_db_link (const MJsonNode *params)
 
static MJsonNode * js_db_reorder (const MJsonNode *params)
 
static MJsonNode * js_db_sor (const MJsonNode *params)
 
static MJsonNode * js_db_scl (const MJsonNode *params)
 
static MJsonNode * js_cm_msg_facilities (const MJsonNode *params)
 
static MJsonNode * js_cm_msg1 (const MJsonNode *params)
 
static MJsonNode * js_cm_msg_retrieve (const MJsonNode *params)
 
static MJsonNode * js_al_reset_alarm (const MJsonNode *params)
 
static MJsonNode * js_al_trigger_alarm (const MJsonNode *params)
 
static MJsonNode * js_al_trigger_class (const MJsonNode *params)
 
static MJsonNode * js_hs_get_active_events (const MJsonNode *params)
 
static MidasHistoryInterfaceGetHistory (const char *name)
 
static void js_hs_exit ()
 
static MJsonNode * js_hs_get_channels (const MJsonNode *params)
 
static MJsonNode * js_hs_get_events (const MJsonNode *params)
 
static MJsonNode * js_hs_reopen (const MJsonNode *params)
 
static MJsonNode * js_hs_get_tags (const MJsonNode *params)
 
static MJsonNode * js_hs_get_last_written (const MJsonNode *params)
 
static MJsonNode * js_hs_read (const MJsonNode *params)
 
static MJsonNode * js_hs_read_binned (const MJsonNode *params)
 
static MJsonNode * js_hs_read_arraybuffer (const MJsonNode *params)
 
static MJsonNode * js_hs_read_binned_arraybuffer (const MJsonNode *params)
 
static MJsonNode * js_hs_image_retrieve (const MJsonNode *params)
 
static MJsonNode * js_el_retrieve (const MJsonNode *params)
 
static MJsonNode * js_el_query (const MJsonNode *params)
 
static MJsonNode * js_el_delete (const MJsonNode *params)
 
static MJsonNode * jrpc (const MJsonNode *params)
 
static MJsonNode * brpc (const MJsonNode *params)
 
static MJsonNode * js_cm_transition (const MJsonNode *params)
 
static const EVENT_HEADERCopyEvent (const EVENT_HEADER *pevent)
 
static void StashEvent (const std::string buffer_name, int event_id, int trigger_mask, const EVENT_HEADER *pevent)
 
static void MatchEvent (const std::string buffer_name, const EVENT_HEADER *pevent)
 
static void DeleteEventStash ()
 
static const EVENT_HEADERFindEvent (const std::string buffer_name, int event_id, int trigger_mask, int last_event_id, int last_trigger_mask, DWORD last_serial_number, DWORD last_time_stamp)
 
static MJsonNode * js_bm_receive_event (const MJsonNode *params)
 
static MJsonNode * js_ss_millitime (const MJsonNode *params)
 
static MJsonNode * get_alarms (const MJsonNode *params)
 
static MJsonNode * js_make_subdir (const MJsonNode *params)
 
static MJsonNode * js_ext_list_files (const MJsonNode *params)
 
static MJsonNode * js_ext_save_file (const MJsonNode *params)
 
static MJsonNode * js_ext_read_file (const MJsonNode *params)
 
static MJsonNode * js_read_binary_file (const MJsonNode *params)
 
static MJsonNode * get_debug (const MJsonNode *params)
 
static MJsonNode * set_debug (const MJsonNode *params)
 
static MJsonNode * get_sleep (const MJsonNode *params)
 
static MJsonNode * set_sleep (const MJsonNode *params)
 
static MJsonNode * get_time (const MJsonNode *params)
 
static MJsonNode * set_time (const MJsonNode *params)
 
static MJsonNode * get_schema (const MJsonNode *params)
 
static MJsonNode * js_get_timezone (const MJsonNode *params)
 
void mjsonrpc_add_handler (const char *method, mjsonrpc_handler_t *handler, bool needs_locking)
 
void mjsonrpc_set_std_mutex (void *mutex)
 
void mjsonrpc_init ()
 
void mjsonrpc_exit ()
 
static MJsonNode * mjsonrpc_make_schema (MethodsTable *h)
 
MJsonNode * mjsonrpc_get_schema ()
 
static std::string indent (int x, const char *p=" ")
 
static std::string mjsonrpc_schema_to_html_anything (const MJsonNode *schema, int nest_level, NestedOutput *o)
 
static std::string mjsonrpc_schema_to_html_object (const MJsonNode *schema, int nest_level, NestedOutput *o)
 
static std::string mjsonrpc_schema_to_html_array (const MJsonNode *schema, int nest_level, NestedOutput *o)
 
std::string mjsonrpc_schema_to_text (const MJsonNode *schema)
 
static void add (std::string *s, const char *text)
 
static MJsonNode * mjsonrpc_handle_request (const MJsonNode *request)
 
MJsonNode * mjsonrpc_decode_post_data (const char *post_data)
 

Variables

int mjsonrpc_debug = 0
 
static int mjsonrpc_sleep = 0
 
static int mjsonrpc_time = 0
 
static MJsonNode * gNullNode = NULL
 
static MhiMap gHistoryChannels
 
static std::mutex gEventStashMutex
 
static std::vector< EventStashEntry * > gEventStash
 
static MethodsTable gMethodsTable
 
static std::mutex * gMutex = NULL
 

Typedef Documentation

◆ MethodsTable

typedef std::map<std::string, MethodsTableEntry> MethodsTable

Definition at line 4638 of file mjsonrpc.cxx.

◆ MethodsTableIterator

typedef MethodsTable::iterator MethodsTableIterator

Definition at line 4639 of file mjsonrpc.cxx.

◆ MhiMap

typedef std::map<std::string,MidasHistoryInterface*> MhiMap

Definition at line 1685 of file mjsonrpc.cxx.

Function Documentation

◆ add()

static void add ( std::string *  s,
const char *  text 
)
static

Definition at line 5102 of file mjsonrpc.cxx.

5103{
5104 assert(s != NULL);
5105 if (s->length() > 0)
5106 *s += ", ";
5107 *s += text;
5108}

◆ brpc()

static MJsonNode * brpc ( const MJsonNode *  params)
static

Definition at line 3419 of file mjsonrpc.cxx.

3420{
3421 if (!params) {
3422 MJSO* doc = MJSO::I();
3423 doc->D("make RPC call into frontend program via RPC_BRPC");
3424 doc->P("client_name", MJSON_STRING, "Connect to this MIDAS client, see cm_connect_client()");
3425 doc->P("cmd", MJSON_STRING, "Command passed to client");
3426 doc->P("args", MJSON_STRING, "Parameters passed to client as a string, could be JSON encoded");
3427 doc->P("max_reply_length?", MJSON_INT, "Optional maximum length of client reply. MIDAS RPC does not support returning data of arbitrary length, maximum length has to be known ahead of time.");
3428 doc->R("reply", MJSON_STRING, "Reply from client as a string, could be JSON encoded");
3429 doc->R("status", MJSON_INT, "return status of cm_connect_client() and rpc_client_call()");
3430 return doc;
3431 }
3432
3433 MJsonNode* error = NULL;
3434
3435 std::string name = mjsonrpc_get_param(params, "client_name", &error)->GetString(); if (error) return error;
3436 std::string cmd = mjsonrpc_get_param(params, "cmd", &error)->GetString(); if (error) return error;
3437 std::string args = mjsonrpc_get_param(params, "args", &error)->GetString(); if (error) return error;
3438 int max_reply_length = mjsonrpc_get_param(params, "max_reply_length", NULL)->GetInt();
3439
3440 int status;
3441
3442 int buf_length = 1024;
3443
3444 if (max_reply_length > buf_length)
3445 buf_length = max_reply_length;
3446
3447 char* buf = (char*)malloc(buf_length);
3448
3449 if (buf == NULL) {
3450 return mjsonrpc_make_error(-32602, "Invalid params", msprintf("malloc(%d) failed, likely invalid max_reply_length value %d", buf_length, max_reply_length).c_str());
3451 }
3452
3453 buf[0] = 0;
3454
3455 HNDLE hconn;
3456
3457 status = cm_connect_client(name.c_str(), &hconn);
3458
3459 if (status != RPC_SUCCESS) {
3460 free(buf);
3461 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
3462 }
3463
3464 status = rpc_client_call(hconn, RPC_BRPC, cmd.c_str(), args.c_str(), buf, &buf_length);
3465
3466 // disconnect return status ignored on purpose.
3467 // disconnect not needed, there is no limit on number
3468 // of connections. dead and closed connections are reaped
3469 // automatically. K.O. Feb 2021.
3470 // cm_disconnect_client(hconn, FALSE);
3471
3472 if (status != RPC_SUCCESS) {
3473 free(buf);
3474 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
3475 }
3476
3477 return MJsonNode::MakeArrayBuffer(buf, buf_length);
3478}
INT cm_connect_client(const char *client_name, HNDLE *hConn)
Definition midas.cxx:2781
#define RPC_SUCCESS
Definition midas.h:699
void D(const char *description)
Definition mjsonrpc.cxx:303
void P(const char *name, int mjson_type, const char *description)
Definition mjsonrpc.cxx:340
MJsonNode * mjsonrpc_make_result(MJsonNode *node)
Definition mjsonrpc.cxx:135
static MJSO * I()
Definition mjsonrpc.cxx:298
MJsonNode * mjsonrpc_make_error(int code, const char *message, const char *data)
Definition mjsonrpc.cxx:123
const MJsonNode * mjsonrpc_get_param(const MJsonNode *params, const char *name, MJsonNode **error)
Definition mjsonrpc.cxx:178
void R(const char *name, int mjson_type, const char *description)
Definition mjsonrpc.cxx:348
#define RPC_BRPC
Definition mrpc.h:131
INT rpc_client_call(HNDLE hConn, DWORD routine_id,...)
Definition midas.cxx:13497
std::string msprintf(const char *format,...)
Definition midas.cxx:419
INT HNDLE
Definition midas.h:132
#define name(x)
Definition midas_macro.h:24
DWORD status
Definition odbhist.cxx:39
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CopyEvent()

static const EVENT_HEADER * CopyEvent ( const EVENT_HEADER pevent)
static

Definition at line 3546 of file mjsonrpc.cxx.

3547{
3548 size_t event_size = sizeof(EVENT_HEADER) + pevent->data_size;
3549 //size_t total_size = ALIGN8(event_size);
3550 EVENT_HEADER* ptr = (EVENT_HEADER*)malloc(event_size);
3551 assert(ptr);
3552 memcpy(ptr, pevent, event_size);
3553 return ptr;
3554}
int event_size
Definition msysmon.cxx:527
DWORD data_size
Definition midas.h:857
Here is the caller graph for this function:

◆ DeleteEventStash()

static void DeleteEventStash ( )
static

Definition at line 3634 of file mjsonrpc.cxx.

3635{
3636 std::lock_guard<std::mutex> guard(gEventStashMutex);
3637 for (size_t i=0; i<gEventStash.size(); i++) {
3638 if (gEventStash[i]) {
3639 delete gEventStash[i];
3640 gEventStash[i] = NULL;
3641 }
3642 }
3643}
INT i
Definition mdump.cxx:32
static std::vector< EventStashEntry * > gEventStash
static std::mutex gEventStashMutex
Here is the caller graph for this function:

◆ exec_script()

static MJsonNode * exec_script ( const MJsonNode *  params)
static

Definition at line 519 of file mjsonrpc.cxx.

520{
521 if (!params) {
522 MJSO* doc = MJSO::I();
523 doc->D("execute custom script defined in ODB /Script (scripts show in the menu) or /CustomScript (scripts from custom pages)");
524 doc->P("script?", MJSON_STRING, "Execute ODB /Script/xxx");
525 doc->P("customscript?", MJSON_STRING, "Execute ODB /CustomScript/xxx");
526 doc->R("status", MJSON_INT, "return status of cm_exec_script()");
527 return doc;
528 }
529
530 std::string script = mjsonrpc_get_param(params, "script", NULL)->GetString();
531 std::string customscript = mjsonrpc_get_param(params, "customscript", NULL)->GetString();
532
533 std::string path;
534
535 if (script.length() > 0) {
536 path += "/Script";
537 path += "/";
538 path += script;
539 } else if (customscript.length() > 0) {
540 path += "/CustomScript";
541 path += "/";
542 path += customscript;
543 }
544
545 int status = 0;
546
547 if (path.length() > 0) {
548 status = cm_exec_script(path.c_str());
549 }
550
551 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
552}
int cm_exec_script(const char *odb_path_to_script)
Definition midas.cxx:5478
Here is the call graph for this function:
Here is the caller graph for this function:

◆ FindEvent()

static const EVENT_HEADER * FindEvent ( const std::string  buffer_name,
int  event_id,
int  trigger_mask,
int  last_event_id,
int  last_trigger_mask,
DWORD  last_serial_number,
DWORD  last_time_stamp 
)
static

Definition at line 3645 of file mjsonrpc.cxx.

3646{
3647 std::lock_guard<std::mutex> guard(gEventStashMutex);
3648 for (EventStashEntry* s : gEventStash) {
3649 if (s->buffer_name != buffer_name)
3650 continue;
3651 if (bm_match_event(event_id, trigger_mask, s->pevent)) {
3652 if (s->pevent->event_id == last_event_id
3653 && s->pevent->trigger_mask == last_trigger_mask
3654 && s->pevent->serial_number == last_serial_number
3655 && s->pevent->time_stamp == last_time_stamp) {
3656 //s->Print(); printf(", already sent for %d,0x%x\n", event_id, trigger_mask);
3657 return NULL;
3658 } else {
3659 //s->Print(); printf(", serving for %d,0x%x\n", event_id, trigger_mask);
3660 return CopyEvent(s->pevent);
3661 }
3662 }
3663 }
3664 return NULL;
3665}
INT bm_match_event(short int event_id, short int trigger_mask, const EVENT_HEADER *pevent)
Definition midas.cxx:6032
char buffer_name[NAME_LENGTH]
Definition mevb.cxx:45
#define trigger_mask
#define event_id
static const EVENT_HEADER * CopyEvent(const EVENT_HEADER *pevent)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_alarms()

static MJsonNode * get_alarms ( const MJsonNode *  params)
static

Definition at line 3853 of file mjsonrpc.cxx.

3854{
3855 if (!params) {
3856 MJSO* doc = MJSO::I();
3857 doc->D("get alarm data");
3858 doc->P("get_all?", MJSON_BOOL, "get all alarms, even in alarm system not active and alarms not triggered");
3859 doc->R("status", MJSON_INT, "return status of midas library calls");
3860 doc->R("alarm_system_active", MJSON_BOOL, "value of ODB \"/Alarms/alarm system active\"");
3861 doc->R("alarms", MJSON_OBJECT, "alarm data, keyed by alarm name");
3862 doc->R("alarms[].triggered", MJSON_BOOL, "alarm is triggered");
3863 doc->R("alarms[].active", MJSON_BOOL, "alarm is enabled");
3864 doc->R("alarms[].class", MJSON_STRING, "alarm class");
3865 doc->R("alarms[].type", MJSON_INT, "alarm type AT_xxx");
3866 doc->R("alarms[].bgcolor", MJSON_STRING, "display background color");
3867 doc->R("alarms[].fgcolor", MJSON_STRING, "display foreground color");
3868 doc->R("alarms[].message", MJSON_STRING, "alarm ODB message field");
3869 doc->R("alarms[].condition", MJSON_STRING, "alarm ODB condition field");
3870 doc->R("alarms[].evaluated_value?", MJSON_STRING, "evaluated alarm condition (AT_EVALUATED alarms only)");
3871 doc->R("alarms[].periodic_next_time?", MJSON_STRING, "next time the periodic alarm will fire (AT_PERIODIC alarms only)");
3872 doc->R("alarms[].time_triggered_first", MJSON_STRING, "time when alarm was triggered");
3873 doc->R("alarms[].show_to_user", MJSON_STRING, "final alarm text shown to user by mhttpd");
3874 return doc;
3875 }
3876
3877 //MJsonNode* error = NULL;
3878
3879 bool get_all = mjsonrpc_get_param(params, "get_all", NULL)->GetBool();
3880
3881 int status;
3882 HNDLE hDB;
3883
3885
3886 if (status != DB_SUCCESS) {
3887 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
3888 }
3889
3890 int flag;
3891 int size;
3892 int alarm_system_active = 0;
3893
3894 /* check global alarm flag */
3895 flag = TRUE;
3896 size = sizeof(flag);
3897 status = db_get_value(hDB, 0, "/Alarms/Alarm System active", &flag, &size, TID_BOOL, TRUE);
3898
3899 if (status != DB_SUCCESS) {
3900 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
3901 }
3902
3903 alarm_system_active = flag;
3904
3905 if (!alarm_system_active)
3906 if (!get_all) {
3907 return mjsonrpc_make_result("status", MJsonNode::MakeInt(SUCCESS),
3908 "alarm_system_active", MJsonNode::MakeBool(alarm_system_active!=0),
3909 "alarms", MJsonNode::MakeObject());
3910 }
3911
3912 /* go through all alarms */
3913 HNDLE hkey;
3914 status = db_find_key(hDB, 0, "/Alarms/Alarms", &hkey);
3915
3916 if (status != DB_SUCCESS) {
3917 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
3918 }
3919
3920 MJsonNode* alarms = MJsonNode::MakeObject();
3921
3922 for (int i = 0;; i++) {
3923 HNDLE hsubkey;
3924 KEY key;
3925
3926 db_enum_link(hDB, hkey, i, &hsubkey);
3927
3928 if (!hsubkey)
3929 break;
3930
3931 status = db_get_key(hDB, hsubkey, &key);
3932
3933 const char* name = key.name;
3934
3935 flag = 0;
3936 size = sizeof(flag);
3937 status = db_get_value(hDB, hsubkey, "Triggered", &flag, &size, TID_INT, TRUE);
3938
3939 // skip un-triggered alarms
3940 if (!flag)
3941 if (!get_all)
3942 continue;
3943
3944 MJsonNode* a = MJsonNode::MakeObject();
3945
3946 a->AddToObject("triggered", MJsonNode::MakeBool(flag!=0));
3947
3948 flag = 1;
3949 size = sizeof(BOOL);
3950 status = db_get_value(hDB, hsubkey, "Active", &flag, &size, TID_BOOL, TRUE);
3951
3952 a->AddToObject("active", MJsonNode::MakeBool(flag!=0));
3953
3954 char alarm_class[NAME_LENGTH];
3955 strcpy(alarm_class, "Alarm");
3956 size = sizeof(alarm_class);
3957 status = db_get_value(hDB, hsubkey, "Alarm Class", alarm_class, &size, TID_STRING, TRUE);
3958
3959 ss_repair_utf8(alarm_class);
3960 a->AddToObject("class", MJsonNode::MakeString(alarm_class));
3961
3962 int atype = 0;
3963 size = sizeof(atype);
3964 status = db_get_value(hDB, hsubkey, "Type", &atype, &size, TID_INT, TRUE);
3965
3966 a->AddToObject("type", MJsonNode::MakeInt(atype));
3967
3968 char str[256];
3969
3970 char bgcol[256];
3971 strcpy(bgcol, "red");
3972
3973 if (strlen(alarm_class) > 0) {
3974 sprintf(str, "/Alarms/Classes/%s/Display BGColor", alarm_class);
3975 size = sizeof(bgcol);
3976 status = db_get_value(hDB, 0, str, bgcol, &size, TID_STRING, TRUE);
3977 }
3978
3979 ss_repair_utf8(bgcol);
3980 a->AddToObject("bgcolor", MJsonNode::MakeString(bgcol));
3981
3982 char fgcol[256];
3983 strcpy(fgcol, "black");
3984
3985 if (strlen(alarm_class) > 0) {
3986 sprintf(str, "/Alarms/Classes/%s/Display FGColor", alarm_class);
3987 size = sizeof(fgcol);
3988 status = db_get_value(hDB, 0, str, fgcol, &size, TID_STRING, TRUE);
3989 }
3990
3991 ss_repair_utf8(fgcol);
3992 a->AddToObject("fgcolor", MJsonNode::MakeString(fgcol));
3993
3994 flag = 1;
3995 if (strlen(alarm_class) > 0) {
3996 size = sizeof(BOOL);
3997 sprintf(str, "/Alarms/Classes/%s/Alarm sound", alarm_class);
3998 status = db_get_value(hDB, 0, str, &flag, &size, TID_BOOL, TRUE);
3999 }
4000 a->AddToObject("alarm_sound", MJsonNode::MakeBool(flag!=0));
4001
4002 char msg[256];
4003 msg[0] = 0;
4004 size = sizeof(msg);
4005 status = db_get_value(hDB, hsubkey, "Alarm Message", msg, &size, TID_STRING, TRUE);
4006
4007 ss_repair_utf8(msg);
4008 a->AddToObject("message", MJsonNode::MakeString(msg));
4009
4010 char cond[256];
4011 cond[0] = 0;
4012 size = sizeof(cond);
4013 status = db_get_value(hDB, hsubkey, "Condition", cond, &size, TID_STRING, TRUE);
4014
4015 ss_repair_utf8(cond);
4016 a->AddToObject("condition", MJsonNode::MakeString(cond));
4017
4018 std::string show_to_user;
4019
4020 if (atype == AT_EVALUATED) {
4021 /* retrieve value */
4022 std::string value;
4024 show_to_user = msprintf(msg, value.c_str());
4026 a->AddToObject("evaluated_value", MJsonNode::MakeString(value.c_str()));
4027 } else
4028 show_to_user = msg;
4029
4030 ss_repair_utf8(show_to_user);
4031 a->AddToObject("show_to_user", MJsonNode::MakeString(show_to_user.c_str()));
4032
4033 str[0] = 0;
4034 size = sizeof(str);
4035 status = db_get_value(hDB, hsubkey, "Time triggered first", str, &size, TID_STRING, TRUE);
4036
4038 a->AddToObject("time_triggered_first", MJsonNode::MakeString(str));
4039
4040 if (atype == AT_PERIODIC) {
4041 DWORD last = 0;
4042 size = sizeof(last);
4043 db_get_value(hDB, hsubkey, "Checked last", &last, &size, TID_DWORD, TRUE);
4044
4045 if (last == 0) {
4046 last = ss_time();
4047 db_set_value(hDB, hsubkey, "Checked last", &last, size, 1, TID_DWORD);
4048 }
4049
4050 int interval = 0;
4051 size = sizeof(interval);
4052 db_get_value(hDB, hsubkey, "Check interval", &interval, &size, TID_INT, TRUE);
4053
4054 time_t tnext = last + interval;
4055
4056 char ctimebuf[32];
4057 ctime_r(&tnext, ctimebuf);
4058
4059 //ss_repair_utf8(ctimebuf); redundant!
4060 a->AddToObject("periodic_next_time", MJsonNode::MakeString(ctimebuf));
4061 }
4062
4063 alarms->AddToObject(name, a);
4064 }
4065
4066 return mjsonrpc_make_result("status", MJsonNode::MakeInt(SUCCESS),
4067 "alarm_system_active", MJsonNode::MakeBool(alarm_system_active!=0),
4068 "alarms", alarms);
4069}
BOOL al_evaluate_condition(const char *alarm_name, const char *condition, std::string *pvalue)
Definition alarm.cxx:41
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition midas.cxx:3026
#define DB_SUCCESS
Definition midas.h:632
unsigned int DWORD
Definition mcstd.h:51
#define SUCCESS
Definition mcstd.h:54
#define TID_BOOL
Definition midas.h:340
#define TID_STRING
Definition midas.h:346
#define TID_INT
Definition midas.h:338
#define TID_DWORD
Definition midas.h:336
DWORD ss_time()
Definition system.cxx:3534
bool ss_repair_utf8(char *string)
Definition system.cxx:8229
INT db_get_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, void *data, INT *buf_size, DWORD type, BOOL create)
Definition odb.cxx:5185
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
Definition odb.cxx:6043
INT db_enum_link(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition odb.cxx:5495
INT db_set_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type)
Definition odb.cxx:5028
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition odb.cxx:4256
HNDLE hDB
main ODB handle
Definition mana.cxx:207
KEY key
Definition mdump.cxx:34
DWORD BOOL
Definition midas.h:105
#define AT_PERIODIC
Definition midas.h:1444
#define TRUE
Definition midas.h:182
#define AT_EVALUATED
Definition midas.h:1443
#define NAME_LENGTH
Definition midas.h:272
double value[100]
Definition odbhist.cxx:42
char str[256]
Definition odbhist.cxx:33
Definition midas.h:1027
char name[NAME_LENGTH]
Definition midas.h:1030
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_debug()

static MJsonNode * get_debug ( const MJsonNode *  params)
static

Definition at line 4509 of file mjsonrpc.cxx.

4510{
4511 if (!params) {
4512 MJSO *doc = MJSO::I();
4513 doc->D("get current value of mjsonrpc_debug");
4514 doc->P(NULL, 0, "there are no input parameters");
4515 doc->R(NULL, MJSON_INT, "current value of mjsonrpc_debug");
4516 return doc;
4517 }
4518
4519 return mjsonrpc_make_result("debug", MJsonNode::MakeInt(mjsonrpc_debug));
4520}
int mjsonrpc_debug
Definition mjsonrpc.cxx:112
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_schema()

static MJsonNode * get_schema ( const MJsonNode *  params)
static

Definition at line 4590 of file mjsonrpc.cxx.

4591{
4592 if (!params) {
4593 MJSO* doc = MJSO::I();
4594 doc->D("Get the MIDAS JSON-RPC schema JSON object");
4595 doc->P(NULL, 0, "there are no input parameters");
4596 doc->R(NULL, MJSON_OBJECT, "returns the MIDAS JSON-RPC schema JSON object");
4597 return doc;
4598 }
4599
4601}
MJsonNode * mjsonrpc_get_schema()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_sleep()

static MJsonNode * get_sleep ( const MJsonNode *  params)
static

Definition at line 4536 of file mjsonrpc.cxx.

4537{
4538 if (!params) {
4539 MJSO *doc = MJSO::I();
4540 doc->D("get current value of mjsonrpc_sleep");
4541 doc->P(NULL, 0, "there are no input parameters");
4542 doc->R(NULL, MJSON_INT, "current value of mjsonrpc_sleep");
4543 return doc;
4544 }
4545
4546 return mjsonrpc_make_result("sleep", MJsonNode::MakeInt(mjsonrpc_sleep));
4547}
static int mjsonrpc_sleep
Definition mjsonrpc.cxx:113
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_time()

static MJsonNode * get_time ( const MJsonNode *  params)
static

Definition at line 4563 of file mjsonrpc.cxx.

4564{
4565 if (!params) {
4566 MJSO *doc = MJSO::I();
4567 doc->D("get current value of mjsonrpc_time");
4568 doc->P(NULL, 0, "there are no input parameters");
4569 doc->R(NULL, MJSON_INT, "current value of mjsonrpc_time");
4570 return doc;
4571 }
4572
4573 return mjsonrpc_make_result("time", MJsonNode::MakeInt(mjsonrpc_time));
4574}
static int mjsonrpc_time
Definition mjsonrpc.cxx:114
Here is the call graph for this function:

◆ GetHistory()

static MidasHistoryInterface * GetHistory ( const char *  name)
static

Definition at line 1689 of file mjsonrpc.cxx.

1690{
1691 // empty name means use the default reader channel
1692
1693 MhiMap::iterator ci = gHistoryChannels.find(name);
1694 if (ci != gHistoryChannels.end()) {
1695 return ci->second;
1696 };
1697
1698 int verbose = 0;
1699
1700 HNDLE hDB;
1702
1703 HNDLE hKey = 0;
1704
1705 if (strlen(name) < 1) {
1707 if (status != HS_SUCCESS) {
1708 return NULL;
1709 }
1710 } else {
1711 HNDLE hKeyChan;
1712 int status = db_find_key(hDB, 0, "/Logger/History", &hKeyChan);
1713 if (status != DB_SUCCESS) {
1714 return NULL;
1715 }
1716 status = db_find_key(hDB, hKeyChan, name, &hKey);
1717 if (status != DB_SUCCESS) {
1718 return NULL;
1719 }
1720 }
1721
1722 MidasHistoryInterface* mh = NULL;
1723
1725 if (status != HS_SUCCESS || mh==NULL) {
1726 cm_msg(MERROR, "GetHistory", "Cannot configure history, hs_get_history() status %d", status);
1727 return NULL;
1728 }
1729
1730 //printf("hs_get_history: \"%s\" -> mh %p\n", name, mh);
1731
1733
1734 // cm_msg(MINFO, "GetHistory", "Reading history channel \"%s\" from channel \'%s\' type \'%s\'", name, mh->name, mh->type);
1735
1736 return mh;
1737}
#define HS_SUCCESS
Definition midas.h:728
#define MERROR
Definition midas.h:559
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
Definition midas.cxx:930
#define HS_GET_INACTIVE
Definition history.h:37
#define HS_GET_READER
Definition history.h:35
int hs_find_reader_channel(HNDLE hDB, HNDLE *hKeyOut, int debug_flag)
int hs_get_history(HNDLE hDB, HNDLE hKey, int flags, int debug_flag, MidasHistoryInterface **mh)
HNDLE hKey
BOOL verbose
Definition mana.cxx:255
MidasHistoryInterface * mh
static MhiMap gHistoryChannels
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetTimeSec()

static double GetTimeSec ( )
static

Definition at line 116 of file mjsonrpc.cxx.

117{
118 struct timeval tv;
119 gettimeofday(&tv, NULL);
120 return tv.tv_sec*1.0 + tv.tv_usec/1000000.0;
121}
int gettimeofday(struct timeval *tp, void *tzp)
timeval tv
Definition msysmon.cxx:1095
Here is the call graph for this function:
Here is the caller graph for this function:

◆ indent()

static std::string indent ( int  x,
const char *  p = " " 
)
static

Definition at line 4796 of file mjsonrpc.cxx.

4797{
4798 if (x<1)
4799 return "";
4800 std::string s;
4801 for (int i=0; i<x; i++)
4802 s += p;
4803 return s;
4804}
Here is the caller graph for this function:

◆ jrpc()

static MJsonNode * jrpc ( const MJsonNode *  params)
static

Definition at line 3348 of file mjsonrpc.cxx.

3349{
3350 if (!params) {
3351 MJSO* doc = MJSO::I();
3352 doc->D("make RPC call into frontend program via RPC_JRPC");
3353 doc->P("client_name", MJSON_STRING, "Connect to this MIDAS client, see cm_connect_client()");
3354 doc->P("cmd", MJSON_STRING, "Command passed to client");
3355 doc->P("args", MJSON_STRING, "Parameters passed to client as a string, could be JSON encoded");
3356 doc->P("max_reply_length?", MJSON_INT, "Optional maximum length of client reply. MIDAS RPC does not support returning strings of arbitrary length, maximum length has to be known ahead of time.");
3357 doc->R("reply", MJSON_STRING, "Reply from client as a string, could be JSON encoded");
3358 doc->R("status", MJSON_INT, "return status of cm_connect_client() and rpc_client_call()");
3359 return doc;
3360 }
3361
3362 MJsonNode* error = NULL;
3363
3364 std::string name = mjsonrpc_get_param(params, "client_name", &error)->GetString(); if (error) return error;
3365 std::string cmd = mjsonrpc_get_param(params, "cmd", &error)->GetString(); if (error) return error;
3366 std::string args = mjsonrpc_get_param(params, "args", &error)->GetString(); if (error) return error;
3367 int max_reply_length = mjsonrpc_get_param(params, "max_reply_length", NULL)->GetInt();
3368
3369 int status;
3370
3371 int buf_length = 1024;
3372
3373 if (max_reply_length > buf_length)
3374 buf_length = max_reply_length;
3375
3376 char* buf = (char*)malloc(buf_length);
3377
3378 if (buf == NULL) {
3379 return mjsonrpc_make_error(-32602, "Invalid params", msprintf("malloc(%d) failed, likely invalid max_reply_length value %d", buf_length, max_reply_length).c_str());
3380 }
3381
3382 buf[0] = 0;
3383
3384 HNDLE hconn;
3385
3386 status = cm_connect_client(name.c_str(), &hconn);
3387
3388 if (status != RPC_SUCCESS) {
3389 free(buf);
3390 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
3391 }
3392
3393 status = rpc_client_call(hconn, RPC_JRPC, cmd.c_str(), args.c_str(), buf, buf_length);
3394
3395 // disconnect return status ignored on purpose.
3396 // disconnect not needed, there is no limit on number
3397 // of connections. dead and closed connections are reaped
3398 // automatically. K.O. Feb 2021.
3399 // cm_disconnect_client(hconn, FALSE);
3400
3401 if (status != RPC_SUCCESS) {
3402 free(buf);
3403 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
3404 }
3405
3406 ss_repair_utf8(buf);
3407 MJsonNode* reply = MJsonNode::MakeString(buf);
3408 free(buf);
3409
3410 return mjsonrpc_make_result("reply", reply, "status", MJsonNode::MakeInt(SUCCESS));
3411}
#define RPC_JRPC
Definition mrpc.h:130
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_al_reset_alarm()

static MJsonNode * js_al_reset_alarm ( const MJsonNode *  params)
static

Definition at line 1579 of file mjsonrpc.cxx.

1580{
1581 if (!params) {
1582 MJSO* doc = MJSO::I();
1583 doc->D("reset alarms");
1584 doc->P("alarms[]", MJSON_STRING, "array of alarm names");
1585 doc->R("status[]", MJSON_INT, "return status of al_reset_alarm() for each alarm");
1586 return doc;
1587 }
1588
1589 MJsonNode* error = NULL;
1590
1591 const MJsonNodeVector* alarms = mjsonrpc_get_param_array(params, "alarms", &error); if (error) return error;
1592
1593 MJsonNode* sresult = MJsonNode::MakeArray();
1594
1595 for (unsigned i=0; i<alarms->size(); i++) {
1596 int status = al_reset_alarm((*alarms)[i]->GetString().c_str());
1597 sresult->AddToArray(MJsonNode::MakeInt(status));
1598 }
1599
1600 return mjsonrpc_make_result("status", sresult);
1601}
INT al_reset_alarm(const char *alarm_name)
Definition alarm.cxx:525
const MJsonNodeVector * mjsonrpc_get_param_array(const MJsonNode *params, const char *name, MJsonNode **error)
Definition mjsonrpc.cxx:201
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_al_trigger_alarm()

static MJsonNode * js_al_trigger_alarm ( const MJsonNode *  params)
static

Definition at line 1603 of file mjsonrpc.cxx.

1604{
1605 if (!params) {
1606 MJSO* doc = MJSO::I();
1607 doc->D("trigger an alarm");
1608 doc->P("name", MJSON_STRING, "alarm name");
1609 doc->P("message", MJSON_STRING, "alarm message");
1610 doc->P("class", MJSON_STRING, "alarm class");
1611 doc->P("condition", MJSON_STRING, "alarm condition");
1612 doc->P("type", MJSON_INT, "alarm type (AT_xxx)");
1613 doc->R("status", MJSON_INT, "return status of al_trigger_alarm()");
1614 return doc;
1615 }
1616
1617 MJsonNode* error = NULL;
1618
1619 std::string name = mjsonrpc_get_param(params, "name", &error)->GetString(); if (error) return error;
1620 std::string message = mjsonrpc_get_param(params, "message", &error)->GetString(); if (error) return error;
1621 std::string xclass = mjsonrpc_get_param(params, "class", &error)->GetString(); if (error) return error;
1622 std::string condition = mjsonrpc_get_param(params, "condition", &error)->GetString(); if (error) return error;
1623 int type = mjsonrpc_get_param(params, "type", &error)->GetInt(); if (error) return error;
1624
1625 int status = al_trigger_alarm(name.c_str(), message.c_str(), xclass.c_str(), condition.c_str(), type);
1626
1627 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
1628}
INT al_trigger_alarm(const char *alarm_name, const char *alarm_message, const char *default_class, const char *cond_str, INT type)
Definition alarm.cxx:283
INT type
Definition mana.cxx:269
#define message(type, str)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_al_trigger_class()

static MJsonNode * js_al_trigger_class ( const MJsonNode *  params)
static

Definition at line 1630 of file mjsonrpc.cxx.

1631{
1632 if (!params) {
1633 MJSO* doc = MJSO::I();
1634 doc->D("trigger an alarm");
1635 doc->P("class", MJSON_STRING, "alarm class");
1636 doc->P("message", MJSON_STRING, "alarm message");
1637 doc->P("first?", MJSON_BOOL, "see al_trigger_class() in midas.c");
1638 doc->R("status", MJSON_INT, "return status of al_trigger_class()");
1639 return doc;
1640 }
1641
1642 MJsonNode* error = NULL;
1643
1644 std::string xclass = mjsonrpc_get_param(params, "class", &error)->GetString(); if (error) return error;
1645 std::string message = mjsonrpc_get_param(params, "message", &error)->GetString(); if (error) return error;
1646 bool first = mjsonrpc_get_param(params, "first", NULL)->GetBool();
1647
1648 int status = al_trigger_class(xclass.c_str(), message.c_str(), first);
1649
1650 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
1651}
INT al_trigger_class(const char *alarm_class, const char *alarm_message, BOOL first)
Definition alarm.cxx:413
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_bm_receive_event()

static MJsonNode * js_bm_receive_event ( const MJsonNode *  params)
static

Definition at line 3667 of file mjsonrpc.cxx.

3668{
3669 if (!params) {
3670 MJSO* doc = MJSO::I();
3671 doc->D("read event buffers");
3672 doc->P("buffer_name", MJSON_STRING, "name of event buffer");
3673 doc->P("event_id?", MJSON_INT, "requested event id, -1 means any event id");
3674 doc->P("trigger_mask?", MJSON_INT, "requested trigger mask, -1 means any trigger mask");
3675 doc->P("get_recent?", MJSON_BOOL, "get last available event that matches this event request");
3676 doc->P("last_event_header[]?", MJSON_INT, "do not resend an event we already received: event header of last received event [event_id,trigger_mask,serial_number,time_stamp]");
3677 doc->P("timeout_millisec?", MJSON_NUMBER, "how long to wait for an event");
3678 doc->R("binary data", MJSON_ARRAYBUFFER, "binary event data");
3679 doc->R("status", MJSON_INT, "return status of bm_open_buffer(), bm_request_event(), bm_set_cache_size(), bm_receive_alloc()");
3680 return doc;
3681 }
3682
3683 MJsonNode* error = NULL;
3684
3685 std::string buffer_name = mjsonrpc_get_param(params, "buffer_name", &error)->GetString(); if (error) return error;
3686 int event_id = mjsonrpc_get_param(params, "event_id", NULL)->GetInt();
3687 int trigger_mask = mjsonrpc_get_param(params, "trigger_mask", NULL)->GetInt();
3688 bool get_recent = mjsonrpc_get_param(params, "get_recent", NULL)->GetBool();
3689 const MJsonNodeVector* last_event_header = mjsonrpc_get_param(params, "last_event_header", NULL)->GetArray();
3690 int timeout_millisec = mjsonrpc_get_param(params, "timeout_millisec", NULL)->GetInt();
3691
3692 int last_event_id = 0;
3693 int last_trigger_mask = 0;
3694 int last_serial_number = 0;
3695 int last_time_stamp = 0;
3696
3697 if (last_event_header && last_event_header->size() > 0) {
3698 if (last_event_header->size() != 4) {
3699 return mjsonrpc_make_error(-32602, "Invalid params", "last_event_header should be an array with 4 elements");
3700 }
3701
3702 last_event_id = (*last_event_header)[0]->GetInt();
3703 last_trigger_mask = (*last_event_header)[1]->GetInt();
3704 last_serial_number = (*last_event_header)[2]->GetInt();
3705 last_time_stamp = (*last_event_header)[3]->GetInt();
3706 }
3707
3708 //printf("last event header: %d %d %d %d\n", last_event_id, last_trigger_mask, last_serial_number, last_time_stamp);
3709
3710 if (event_id == 0)
3712
3713 if (trigger_mask == 0)
3715
3716 //printf("js_bm_receive_event: buffer \"%s\", event_id %d, trigger_mask 0x%04x\n", buffer_name.c_str(), event_id, trigger_mask);
3717
3718 int status;
3719
3720 HNDLE buffer_handle = 0;
3721
3722 status = bm_get_buffer_handle(buffer_name.c_str(), &buffer_handle);
3723
3724 if (status != BM_SUCCESS) {
3725 // if buffer not already open, we need to open it,
3726 // but we must hold a lock in case multiple RPC handler threads
3727 // try to open it at the same time. K.O.
3728 static std::mutex gMutex;
3729 std::lock_guard<std::mutex> lock_guard(gMutex); // lock the mutex
3730
3731 // we have the lock. now we check if some other thread
3732 // opened the buffer while we were waiting for the lock. K.O.
3733 status = bm_get_buffer_handle(buffer_name.c_str(), &buffer_handle);
3734
3735 if (status != BM_SUCCESS) {
3736 status = bm_open_buffer(buffer_name.c_str(), 0, &buffer_handle);
3737 if (status != BM_SUCCESS && status != BM_CREATED) {
3738 MJsonNode* result = MJsonNode::MakeObject();
3739 result->AddToObject("status", MJsonNode::MakeInt(status));
3740 return mjsonrpc_make_result(result);
3741 }
3742 status = bm_set_cache_size(buffer_handle, 0, 0);
3743 if (status != BM_SUCCESS) {
3744 MJsonNode* result = MJsonNode::MakeObject();
3745 result->AddToObject("status", MJsonNode::MakeInt(status));
3746 return mjsonrpc_make_result(result);
3747 }
3748 int request_id = 0;
3749 status = bm_request_event(buffer_handle, EVENTID_ALL, TRIGGER_ALL, GET_NONBLOCKING, &request_id, NULL);
3750 if (status != BM_SUCCESS) {
3751 MJsonNode* result = MJsonNode::MakeObject();
3752 result->AddToObject("status", MJsonNode::MakeInt(status));
3753 return mjsonrpc_make_result(result);
3754 }
3755 }
3756 }
3757
3758 if (timeout_millisec <= 0)
3759 timeout_millisec = 100.0;
3760
3761 double start_time = ss_time_sec();
3762 double end_time = start_time + timeout_millisec/1000.0;
3763
3764 // in "GET_RECENT" mode, we read all avialable events from the event buffer
3765 // and save them in the event stash (MatchEvent()), after we empty the event
3766 // buffer (BM_ASYNC_RETURN), we send the last saved event. K.O.
3767
3768 while (1) {
3769 EVENT_HEADER* pevent = NULL;
3770
3771 status = bm_receive_event_alloc(buffer_handle, &pevent, BM_NO_WAIT);
3772
3773 if (status == BM_SUCCESS) {
3774 //printf("got event_id %d, trigger_mask 0x%04x\n", pevent->event_id, pevent->trigger_mask);
3775
3776 if (get_recent) {
3777 if (bm_match_event(event_id, trigger_mask, pevent)) {
3779 } else {
3780 MatchEvent(buffer_name, pevent);
3781 }
3782 free(pevent);
3783 pevent = NULL;
3784 } else {
3785 if (bm_match_event(event_id, trigger_mask, pevent)) {
3787
3788 size_t event_size = sizeof(EVENT_HEADER) + pevent->data_size;
3789 //size_t total_size = ALIGN8(event_size);
3790 return MJsonNode::MakeArrayBuffer((char*)pevent, event_size);
3791 }
3792
3793 MatchEvent(buffer_name, pevent);
3794
3795 free(pevent);
3796 pevent = NULL;
3797 }
3798 } else if (status == BM_ASYNC_RETURN) {
3799 if (get_recent) {
3800 //printf("bm_async_return!\n");
3801 break;
3802 }
3803 ss_sleep(10);
3804 } else {
3805 MJsonNode* result = MJsonNode::MakeObject();
3806 result->AddToObject("status", MJsonNode::MakeInt(status));
3807 return mjsonrpc_make_result(result);
3808 }
3809
3810 if (ss_time_sec() > end_time) {
3811 //printf("timeout!\n");
3812 break;
3813 }
3814 }
3815
3816 const EVENT_HEADER* pevent = FindEvent(buffer_name, event_id, trigger_mask, last_event_id, last_trigger_mask, last_serial_number, last_time_stamp);
3817 if (pevent) {
3818 size_t event_size = sizeof(EVENT_HEADER) + pevent->data_size;
3819 //size_t total_size = ALIGN8(event_size);
3820 return MJsonNode::MakeArrayBuffer((char*)pevent, event_size);
3821 }
3822
3823 MJsonNode* result = MJsonNode::MakeObject();
3824 result->AddToObject("status", MJsonNode::MakeInt(BM_ASYNC_RETURN));
3825 return mjsonrpc_make_result(result);
3826}
INT bm_open_buffer(const char *buffer_name, INT buffer_size, INT *buffer_handle)
Definition midas.cxx:6727
INT bm_request_event(HNDLE buffer_handle, short int event_id, short int trigger_mask, INT sampling_type, HNDLE *request_id, EVENT_HANDLER *func)
Definition midas.cxx:8475
INT bm_set_cache_size(INT buffer_handle, size_t read_size, size_t write_size)
Definition midas.cxx:8150
INT bm_get_buffer_handle(const char *buffer_name, INT *buffer_handle)
Definition midas.cxx:7085
INT bm_receive_event_alloc(INT buffer_handle, EVENT_HEADER **ppevent, int timeout_msec)
Definition midas.cxx:10756
#define BM_ASYNC_RETURN
Definition midas.h:613
#define BM_SUCCESS
Definition midas.h:605
#define BM_CREATED
Definition midas.h:606
#define GET_NONBLOCKING
Definition midas.h:322
#define TRIGGER_ALL
Definition midas.h:538
#define BM_NO_WAIT
Definition midas.h:366
#define EVENTID_ALL
Definition midas.h:537
double ss_time_sec()
Definition system.cxx:3539
INT ss_sleep(INT millisec)
Definition system.cxx:3700
static void StashEvent(const std::string buffer_name, int event_id, int trigger_mask, const EVENT_HEADER *pevent)
static std::mutex * gMutex
static const EVENT_HEADER * FindEvent(const std::string buffer_name, int event_id, int trigger_mask, int last_event_id, int last_trigger_mask, DWORD last_serial_number, DWORD last_time_stamp)
static void MatchEvent(const std::string buffer_name, const EVENT_HEADER *pevent)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_cm_exist()

static MJsonNode * js_cm_exist ( const MJsonNode *  params)
static

Definition at line 432 of file mjsonrpc.cxx.

433{
434 if (!params) {
435 MJSO* doc = MJSO::I();
436 doc->D("calls MIDAS cm_exist() to check if given MIDAS program is running");
437 doc->P("name", MJSON_STRING, "name of the program, corresponding to ODB /Programs/name");
438 doc->P("unique?", MJSON_BOOL, "bUnique argument to cm_exist()");
439 doc->R("status", MJSON_INT, "return status of cm_exist()");
440 return doc;
441 }
442
443 MJsonNode* error = NULL;
444
445 std::string name = mjsonrpc_get_param(params, "name", &error)->GetString();
446 if (error)
447 return error;
448
449 int unique = mjsonrpc_get_param(params, "unique", NULL)->GetBool();
450
451 int status = cm_exist(name.c_str(), unique);
452
453 if (mjsonrpc_debug)
454 printf("cm_exist(%s,%d) -> %d\n", name.c_str(), unique, status);
455
456 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
457}
INT cm_exist(const char *name, BOOL bUnique)
Definition midas.cxx:7530
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_cm_msg1()

static MJsonNode * js_cm_msg1 ( const MJsonNode *  params)
static

Definition at line 1500 of file mjsonrpc.cxx.

1501{
1502 if (!params) {
1503 MJSO *doc = MJSO::I();
1504 doc->D("Generate a midas message using cm_msg1()");
1505 doc->P("facility?", MJSON_STRING, "message facility, default is \"midas\"");
1506 doc->P("user?", MJSON_STRING, "message user, default is \"javascript_commands\"");
1507 doc->P("type?", MJSON_INT, "message type, MT_xxx from midas.h, default is MT_INFO");
1508 doc->P("message", MJSON_STRING, "message text");
1509 doc->R("status", MJSON_INT, "return status of cm_msg1()");
1510 return doc;
1511 }
1512
1513 MJsonNode* error = NULL;
1514
1515 std::string facility = mjsonrpc_get_param(params, "facility", NULL)->GetString();
1516 std::string user = mjsonrpc_get_param(params, "user", NULL)->GetString();
1517 int type = mjsonrpc_get_param(params, "type", NULL)->GetInt();
1518 std::string message = mjsonrpc_get_param(params, "message", &error)->GetString(); if (error) return error;
1519
1520 if (facility.size() <1)
1521 facility = "midas";
1522 if (user.size()<1)
1523 user = "javascript_commands";
1524 if (type == 0)
1525 type = MT_INFO;
1526
1527 int status = cm_msg1(type, __FILE__, __LINE__, facility.c_str(), user.c_str(), "%s", message.c_str());
1528
1529 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
1530}
#define MT_INFO
Definition midas.h:543
INT cm_msg1(INT message_type, const char *filename, INT line, const char *facility, const char *routine, const char *format,...)
Definition midas.cxx:988
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_cm_msg_facilities()

static MJsonNode * js_cm_msg_facilities ( const MJsonNode *  params)
static

Definition at line 1475 of file mjsonrpc.cxx.

1476{
1477 if (!params) {
1478 MJSO* doc = MJSO::I();
1479 doc->D("get message facilities using cm_msg_facilities()");
1480 doc->R("status", MJSON_INT, "return status of cm_msg_facilities()");
1481 doc->R("facilities[]", MJSON_STRING, "array of facility names");
1482 return doc;
1483 }
1484
1486
1488
1489 MJsonNode* facilities = MJsonNode::MakeArray();
1490
1491 for (unsigned i=0; i<list.size(); i++) {
1493 facilities->AddToArray(MJsonNode::MakeString(list[i].c_str()));
1494 }
1495
1496 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status),
1497 "facilities", facilities);
1498}
INT EXPRT cm_msg_facilities(STRING_LIST *list)
Definition midas.cxx:517
std::vector< std::string > STRING_LIST
Definition midas.h:246
static te_expr * list(state *s)
Definition tinyexpr.c:567
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_cm_msg_retrieve()

static MJsonNode * js_cm_msg_retrieve ( const MJsonNode *  params)
static

Definition at line 1532 of file mjsonrpc.cxx.

1533{
1534 if (!params) {
1535 MJSO *doc = MJSO::I();
1536 doc->D("Retrieve midas messages using cm_msg_retrieve2()");
1537 doc->P("facility?", MJSON_STRING, "message facility, default is \"midas\"");
1538 doc->P("min_messages?", MJSON_INT, "get at least this many messages, default is 1");
1539 doc->P("time?", MJSON_NUMBER, "start from given timestamp, value 0 means give me newest messages, default is 0");
1540 doc->R("num_messages", MJSON_INT, "number of messages returned");
1541 doc->R("messages", MJSON_STRING, "messages separated by \\n");
1542 doc->R("status", MJSON_INT, "return status of cm_msg_retrieve2()");
1543 return doc;
1544 }
1545
1546 std::string facility = mjsonrpc_get_param(params, "facility", NULL)->GetString();
1547 int min_messages = mjsonrpc_get_param(params, "min_messages", NULL)->GetInt();
1548 double time = mjsonrpc_get_param(params, "time", NULL)->GetDouble();
1549
1550 if (facility.size() < 1)
1551 facility = "midas";
1552
1553 int num_messages = 0;
1554 char* messages = NULL;
1555
1556 int status = cm_msg_retrieve2(facility.c_str(), (time_t)time, min_messages, &messages, &num_messages);
1557
1558 MJsonNode* result = MJsonNode::MakeObject();
1559
1560 result->AddToObject("status", MJsonNode::MakeInt(status));
1561 result->AddToObject("num_messages", MJsonNode::MakeInt(num_messages));
1562
1563 if (messages) {
1564 ss_repair_utf8(messages);
1565 result->AddToObject("messages", MJsonNode::MakeString(messages));
1566 free(messages);
1567 messages = NULL;
1568 }
1569
1570 return mjsonrpc_make_result(result);
1571}
INT cm_msg_retrieve2(const char *facility, time_t t, INT n_message, char **messages, int *num_messages)
Definition midas.cxx:1279
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_cm_shutdown()

static MJsonNode * js_cm_shutdown ( const MJsonNode *  params)
static

Definition at line 459 of file mjsonrpc.cxx.

460{
461 if (!params) {
462 MJSO *doc = MJSO::I();
463 doc->D("calls MIDAS cm_shutdown() to stop given MIDAS program");
464 doc->P("name", MJSON_STRING, "name of the program, corresponding to ODB /Programs/name");
465 doc->P("unique?", MJSON_BOOL, "bUnique argument to cm_shutdown()");
466 doc->R("status", MJSON_INT, "return status of cm_shutdown()");
467 return doc;
468 }
469
470 MJsonNode* error = NULL;
471
472 std::string name = mjsonrpc_get_param(params, "name", &error)->GetString();
473 if (error)
474 return error;
475
476 int unique = mjsonrpc_get_param(params, "unique", NULL)->GetBool();
477
478 int status = cm_shutdown(name.c_str(), unique);
479
480 if (mjsonrpc_debug)
481 printf("cm_shutdown(%s,%d) -> %d\n", name.c_str(), unique, status);
482
483 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
484}
INT cm_shutdown(const char *name, BOOL bUnique)
Definition midas.cxx:7410
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_cm_transition()

static MJsonNode * js_cm_transition ( const MJsonNode *  params)
static

Definition at line 3486 of file mjsonrpc.cxx.

3487{
3488 if (!params) {
3489 MJSO* doc = MJSO::I();
3490 doc->D("start and stop runs");
3491 doc->P("transition", MJSON_STRING, "requested transition: TR_START, TR_STOP, TR_PAUSE, TR_RESUME");
3492 doc->P("run_number?", MJSON_INT, "New run number, value 0 means /runinfo/run_number + 1, default is 0");
3493 doc->P("async_flag?", MJSON_INT, "Transition type. Default is multithreaded transition TR_MTHREAD");
3494 doc->P("debug_flag?", MJSON_INT, "See cm_transition(), value 1: trace to stdout, value 2: trace to midas.log");
3495 doc->R("status", MJSON_INT, "return status of cm_transition()");
3496 doc->R("error_string?", MJSON_STRING, "return error string from cm_transition()");
3497 return doc;
3498 }
3499
3500 MJsonNode* error = NULL;
3501
3502 std::string xtransition = mjsonrpc_get_param(params, "transition", &error)->GetString(); if (error) return error;
3503 int run_number = mjsonrpc_get_param(params, "run_number", NULL)->GetInt();
3504 int async_flag = mjsonrpc_get_param(params, "async_flag", NULL)->GetInt();
3505 int debug_flag = mjsonrpc_get_param(params, "debug_flag", NULL)->GetInt();
3506
3507 int status;
3508
3509 int transition = 0;
3510
3511 if (xtransition == "TR_START")
3513 else if (xtransition == "TR_STOP")
3515 else if (xtransition == "TR_PAUSE")
3517 else if (xtransition == "TR_RESUME")
3519 else {
3520 return mjsonrpc_make_error(15, "invalid value of \"transition\"", xtransition.c_str());
3521 }
3522
3523 if (async_flag == 0)
3524 async_flag = TR_MTHREAD;
3525
3526 char error_str[1024];
3527
3528 status = cm_transition(transition, run_number, error_str, sizeof(error_str), async_flag, debug_flag);
3529
3530 MJsonNode* result = MJsonNode::MakeObject();
3531
3532 result->AddToObject("status", MJsonNode::MakeInt(status));
3533 if (strlen(error_str) > 0) {
3534 ss_repair_utf8(error_str);
3535 result->AddToObject("error_string", MJsonNode::MakeString(error_str));
3536 }
3537 return mjsonrpc_make_result(result);
3538}
INT transition(INT run_number, char *error)
Definition consume.cxx:35
INT cm_transition(INT transition, INT run_number, char *errstr, INT errstr_size, INT async_flag, INT debug_flag)
Definition midas.cxx:5303
#define TR_RESUME
Definition midas.h:408
#define TR_PAUSE
Definition midas.h:407
#define TR_START
Definition midas.h:405
#define TR_MTHREAD
Definition midas.h:361
#define TR_STOP
Definition midas.h:406
INT run_number[2]
Definition mana.cxx:246
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_db_copy()

static MJsonNode * js_db_copy ( const MJsonNode *  params)
static

Definition at line 860 of file mjsonrpc.cxx.

861{
862 if (!params) {
863 MJSO* doc = MJSO::I();
864 doc->D("get complete ODB data in the \"save\" json encoding, suitable for reloading with odbedit command \"load\"");
865 doc->P("paths[]", MJSON_STRING, "array of ODB subtree paths");
866 doc->R("data[]", MJSON_OBJECT, "keys and values of ODB data for each path");
867 doc->R("status[]", MJSON_INT, "return status of db_copy_json_save() for each path");
868 return doc;
869 }
870
871 MJsonNode* error = NULL;
872
873 const MJsonNodeVector* paths = mjsonrpc_get_param_array(params, "paths", &error); if (error) return error;
874
875 MJsonNode* dresult = MJsonNode::MakeArray();
876 MJsonNode* sresult = MJsonNode::MakeArray();
877
878 HNDLE hDB;
880
881 for (unsigned i=0; i<paths->size(); i++) {
882 int status = 0;
883 HNDLE hkey;
884 std::string path = (*paths)[i]->GetString();
885
886 status = db_find_key(hDB, 0, path.c_str(), &hkey);
887 if (status != DB_SUCCESS) {
888 dresult->AddToArray(MJsonNode::MakeNull());
889 sresult->AddToArray(MJsonNode::MakeInt(status));
890 continue;
891 }
892
893 char* buf = NULL;
894 int bufsize = 0;
895 int end = 0;
896
897 status = db_copy_json_save(hDB, hkey, &buf, &bufsize, &end);
898
899 if (status == DB_SUCCESS) {
900 ss_repair_utf8(buf);
901 dresult->AddToArray(MJsonNode::MakeJSON(buf));
902 sresult->AddToArray(MJsonNode::MakeInt(status));
903 } else {
904 dresult->AddToArray(MJsonNode::MakeNull());
905 sresult->AddToArray(MJsonNode::MakeInt(status));
906 }
907
908 if (buf)
909 free(buf);
910 }
911
912 return mjsonrpc_make_result("data", dresult, "status", sresult);
913}
INT db_copy_json_save(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end)
Definition odb.cxx:10496
#define end
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_db_create()

static MJsonNode * js_db_create ( const MJsonNode *  params)
static

Definition at line 1030 of file mjsonrpc.cxx.

1031{
1032 if (!params) {
1033 MJSO* doc = MJSO::I();
1034 doc->D("Create new ODB entries");
1035 MJSO* o = doc->PA("array of ODB paths to be created")->AddObject("", "arguments to db_create_key() and db_set_num_values()");
1036 o->Add("path", MJSON_STRING, "ODB path to be created");
1037 o->Add("type", MJSON_INT, "MIDAS TID_xxx type");
1038 o->Add("array_length?", MJSON_INT, "optional array length, default is 1");
1039 o->Add("string_length?", MJSON_INT, "for TID_STRING, optional string length, default is NAME_LENGTH");
1040 doc->R("status[]", MJSON_INT, "return status of db_create_key(), db_set_num_values() and db_set_data() (for TID_STRING) for each path");
1041 return doc;
1042 }
1043
1044 MJsonNode* sresult = MJsonNode::MakeArray();
1045
1046 const MJsonNodeVector* pp = params->GetArray();
1047
1048 if (!pp) {
1049 delete sresult;
1050 return mjsonrpc_make_error(-32602, "Invalid params", "parameters must be an array of objects");
1051 }
1052
1053 HNDLE hDB;
1055
1056 for (unsigned i=0; i<pp->size(); i++) {
1057 const MJsonNode* p = (*pp)[i];
1058 std::string path = mjsonrpc_get_param(p, "path", NULL)->GetString();
1059 int type = mjsonrpc_get_param(p, "type", NULL)->GetInt();
1060 int array_length = mjsonrpc_get_param(p, "array_length", NULL)->GetInt();
1061 int string_length = mjsonrpc_get_param(p, "string_length", NULL)->GetInt();
1062
1063 //printf("create odb [%s], type %d, array %d, string %d\n", path.c_str(), type, array_length, string_length);
1064
1065 if (string_length == 0)
1066 string_length = NAME_LENGTH;
1067
1068 int status = db_create_key(hDB, 0, path.c_str(), type);
1069
1070 if (status == DB_SUCCESS && string_length > 0 && type == TID_STRING) {
1071 HNDLE hKey;
1072 status = db_find_key(hDB, 0, path.c_str(), &hKey);
1073 if (status == DB_SUCCESS) {
1074 char* buf = (char*)calloc(1, string_length);
1075 assert(buf != NULL);
1076 int size = string_length;
1077 status = db_set_data(hDB, hKey, buf, size, 1, TID_STRING);
1078 free(buf);
1079 }
1080 }
1081
1082 if (status == DB_SUCCESS && array_length > 1) {
1083 HNDLE hKey;
1084 status = db_find_key(hDB, 0, path.c_str(), &hKey);
1085 if (status == DB_SUCCESS)
1086 status = db_set_num_values(hDB, hKey, array_length);
1087 }
1088
1089 sresult->AddToArray(MJsonNode::MakeInt(status));
1090 }
1091
1092 return mjsonrpc_make_result("status", sresult);
1093}
MJSO * AddObject(const char *name, const char *description)
Definition mjsonrpc.cxx:385
void Add(const char *name, int mjson_type, const char *description)
Definition mjsonrpc.cxx:356
MJSO * PA(const char *description)
Definition mjsonrpc.cxx:326
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
Definition odb.cxx:3392
INT db_set_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
Definition odb.cxx:7239
INT db_set_num_values(HNDLE hDB, HNDLE hKey, INT num_values)
Definition odb.cxx:7523
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_db_delete()

static MJsonNode * js_db_delete ( const MJsonNode *  params)
static

Definition at line 1095 of file mjsonrpc.cxx.

1096{
1097 if (!params) {
1098 MJSO* doc = MJSO::I();
1099 doc->D("delete ODB keys");
1100 doc->P("paths[]", MJSON_STRING, "array of ODB paths to delete");
1101 doc->R("status[]", MJSON_INT, "return status of db_delete_key() for each path");
1102 return doc;
1103 }
1104
1105 MJsonNode* error = NULL;
1106
1107 const MJsonNodeVector* paths = mjsonrpc_get_param_array(params, "paths", &error); if (error) return error;
1108
1109 MJsonNode* sresult = MJsonNode::MakeArray();
1110
1111 HNDLE hDB;
1113
1114 for (unsigned i=0; i<paths->size(); i++) {
1115 std::string path = (*paths)[i]->GetString();
1116 int status = db_delete(hDB, 0, path.c_str());
1117 sresult->AddToArray(MJsonNode::MakeInt(status));
1118 }
1119
1120 return mjsonrpc_make_result("status", sresult);
1121}
INT db_delete(HNDLE hDB, HNDLE hKeyRoot, const char *odb_path)
Definition odb.cxx:3999
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_db_get_values()

static MJsonNode * js_db_get_values ( const MJsonNode *  params)
static

Definition at line 640 of file mjsonrpc.cxx.

641{
642 if (!params) {
643 MJSO* doc = MJSO::I();
644 doc->D("get values of ODB data from given subtrees");
645 doc->P("paths[]", MJSON_STRING, "array of ODB subtree paths, see note on array indices");
646 doc->P("omit_names?", MJSON_BOOL, "omit the /name entries");
647 doc->P("omit_last_written?", MJSON_BOOL, "omit the /last_written entries and the last_written[] result");
648 doc->P("omit_tid?", MJSON_BOOL, "omit the tid[] result");
649 doc->P("omit_old_timestamp?", MJSON_NUMBER, "omit data older than given ODB timestamp");
650 doc->P("preserve_case?", MJSON_BOOL, "preserve the capitalization of ODB key names (WARNING: ODB is not case sensitive); note that this will also have side effect of setting the omit_names option");
651 doc->R("data[]", 0, "values of ODB data for each path, all key names are in lower case, all symlinks are followed");
652 doc->R("status[]", MJSON_INT, "return status of db_copy_json_values() or db_copy_json_index() for each path");
653 doc->R("tid?[]", MJSON_INT, "odb type id for each path, absent if omit_tid is true");
654 doc->R("last_written?[]", MJSON_NUMBER, "last_written value of the ODB subtree for each path, absent if omit_last_written is true");
655 return doc;
656 }
657
658 MJsonNode* error = NULL;
659
660 const MJsonNodeVector* paths = mjsonrpc_get_param_array(params, "paths", &error); if (error) return error;
661
662 bool omit_names = mjsonrpc_get_param(params, "omit_names", NULL)->GetBool();
663 bool omit_last_written = mjsonrpc_get_param(params, "omit_last_written", NULL)->GetBool();
664 bool omit_tid = mjsonrpc_get_param(params, "omit_tid", NULL)->GetBool();
665 double xomit_old_timestamp = mjsonrpc_get_param(params, "omit_old_timestamp", NULL)->GetDouble();
666 time_t omit_old_timestamp = (time_t)xomit_old_timestamp;
667 bool preserve_case = mjsonrpc_get_param(params, "preserve_case", NULL)->GetBool();
668
669 MJsonNode* dresult = MJsonNode::MakeArray();
670 MJsonNode* sresult = MJsonNode::MakeArray();
671 MJsonNode* tresult = MJsonNode::MakeArray();
672 MJsonNode* lwresult = MJsonNode::MakeArray();
673
674 HNDLE hDB;
676
677 for (unsigned i=0; i<paths->size(); i++) {
678 int status = 0;
679 HNDLE hkey;
680 KEY key;
681 std::string path = (*paths)[i]->GetString();
682
683 status = db_find_key(hDB, 0, path.c_str(), &hkey);
684 if (status != DB_SUCCESS) {
685 dresult->AddToArray(MJsonNode::MakeNull());
686 sresult->AddToArray(MJsonNode::MakeInt(status));
687 tresult->AddToArray(MJsonNode::MakeNull());
688 lwresult->AddToArray(MJsonNode::MakeNull());
689 continue;
690 }
691
692 status = db_get_key(hDB, hkey, &key);
693 if (status != DB_SUCCESS) {
694 dresult->AddToArray(MJsonNode::MakeNull());
695 sresult->AddToArray(MJsonNode::MakeInt(status));
696 tresult->AddToArray(MJsonNode::MakeNull());
697 lwresult->AddToArray(MJsonNode::MakeNull());
698 continue;
699 }
700
701 if (path.find("[") != std::string::npos) {
702 std::vector<unsigned> list;
703 status = parse_array_index_list("js_db_get_values", path.c_str(), &list);
704
705 if (status != SUCCESS) {
706 dresult->AddToArray(MJsonNode::MakeNull());
707 sresult->AddToArray(MJsonNode::MakeInt(status));
708 tresult->AddToArray(MJsonNode::MakeInt(key.type));
709 lwresult->AddToArray(MJsonNode::MakeInt(key.last_written));
710 continue;
711 }
712
713 if (list.size() > 1) {
714 MJsonNode *ddresult = MJsonNode::MakeArray();
715 MJsonNode *ssresult = MJsonNode::MakeArray();
716
717 for (unsigned i=0; i<list.size(); i++) {
718 char* buf = NULL;
719 int bufsize = 0;
720 int end = 0;
721
722 status = db_copy_json_index(hDB, hkey, list[i], &buf, &bufsize, &end);
723 if (status == DB_SUCCESS) {
724 ss_repair_utf8(buf);
725 ddresult->AddToArray(MJsonNode::MakeJSON(buf));
726 ssresult->AddToArray(MJsonNode::MakeInt(status));
727 } else {
728 ddresult->AddToArray(MJsonNode::MakeNull());
729 ssresult->AddToArray(MJsonNode::MakeInt(status));
730 }
731
732 if (buf)
733 free(buf);
734 }
735
736 dresult->AddToArray(ddresult);
737 sresult->AddToArray(ssresult);
738 tresult->AddToArray(MJsonNode::MakeInt(key.type));
739 lwresult->AddToArray(MJsonNode::MakeInt(key.last_written));
740
741 } else {
742 char* buf = NULL;
743 int bufsize = 0;
744 int end = 0;
745
746 status = db_copy_json_index(hDB, hkey, list[0], &buf, &bufsize, &end);
747 if (status == DB_SUCCESS) {
748 ss_repair_utf8(buf);
749 dresult->AddToArray(MJsonNode::MakeJSON(buf));
750 sresult->AddToArray(MJsonNode::MakeInt(status));
751 tresult->AddToArray(MJsonNode::MakeInt(key.type));
752 lwresult->AddToArray(MJsonNode::MakeInt(key.last_written));
753 } else {
754 dresult->AddToArray(MJsonNode::MakeNull());
755 sresult->AddToArray(MJsonNode::MakeInt(status));
756 tresult->AddToArray(MJsonNode::MakeInt(key.type));
757 lwresult->AddToArray(MJsonNode::MakeInt(key.last_written));
758 }
759
760 if (buf)
761 free(buf);
762 }
763 } else {
764 char* buf = NULL;
765 int bufsize = 0;
766 int end = 0;
767
768 status = db_copy_json_values(hDB, hkey, &buf, &bufsize, &end, omit_names,
769 omit_last_written, omit_old_timestamp, preserve_case);
770
771 if (status == DB_SUCCESS) {
772 ss_repair_utf8(buf);
773 dresult->AddToArray(MJsonNode::MakeJSON(buf));
774 sresult->AddToArray(MJsonNode::MakeInt(status));
775 tresult->AddToArray(MJsonNode::MakeInt(key.type));
776 lwresult->AddToArray(MJsonNode::MakeInt(key.last_written));
777 } else {
778 dresult->AddToArray(MJsonNode::MakeNull());
779 sresult->AddToArray(MJsonNode::MakeInt(status));
780 tresult->AddToArray(MJsonNode::MakeInt(key.type));
781 lwresult->AddToArray(MJsonNode::MakeInt(key.last_written));
782 }
783
784 if (buf)
785 free(buf);
786 }
787 }
788
789 MJsonNode* result = MJsonNode::MakeObject();
790
791 result->AddToObject("data", dresult);
792 result->AddToObject("status", sresult);
793 if (!omit_tid)
794 result->AddToObject("tid", tresult);
795 else
796 delete tresult;
797 if (!omit_last_written)
798 result->AddToObject("last_written", lwresult);
799 else
800 delete lwresult;
801
802 return mjsonrpc_make_result(result);
803}
INT db_copy_json_index(HNDLE hDB, HNDLE hKey, int index, char **buffer, int *buffer_size, int *buffer_end)
Definition odb.cxx:10242
INT db_copy_json_values(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end, int omit_names, int omit_last_written, time_t omit_old_timestamp, int preserve_case)
Definition odb.cxx:10464
static int parse_array_index_list(const char *method, const char *path, std::vector< unsigned > *list)
Definition mjsonrpc.cxx:560
DWORD type
Definition midas.h:1028
INT last_written
Definition midas.h:1038
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_db_key()

static MJsonNode * js_db_key ( const MJsonNode *  params)
static

Definition at line 1225 of file mjsonrpc.cxx.

1226{
1227 if (!params) {
1228 MJSO* doc = MJSO::I();
1229 doc->D("get ODB keys");
1230 doc->P("paths[]", MJSON_STRING, "array of ODB paths");
1231 doc->R("status[]", MJSON_INT, "return status of db_key() for each path");
1232 doc->R("keys[]", MJSON_OBJECT, "key data for each path");
1233 doc->R("keys[].type", MJSON_INT, "key type TID_xxx");
1234 doc->R("keys[].num_values", MJSON_INT, "array length, 1 for normal entries");
1235 doc->R("keys[].name", MJSON_STRING, "key name");
1236 doc->R("keys[].total_size", MJSON_INT, "data total size in bytes");
1237 doc->R("keys[].item_size", MJSON_INT, "array element size, string length for TID_STRING");
1238 doc->R("keys[].access_mode", MJSON_INT, "access mode bitmap of MODE_xxx");
1239 doc->R("keys[].notify_count", MJSON_INT, "number of hotlinks attached to this key");
1240 doc->R("keys[].last_written", MJSON_INT, "timestamp when data was last updated");
1241 return doc;
1242 }
1243
1244 MJsonNode* error = NULL;
1245
1246 const MJsonNodeVector* paths = mjsonrpc_get_param_array(params, "paths", &error); if (error) return error;
1247
1248 MJsonNode* kresult = MJsonNode::MakeArray();
1249 MJsonNode* sresult = MJsonNode::MakeArray();
1250
1251 HNDLE hDB;
1253
1254 for (unsigned i=0; i<paths->size(); i++) {
1255 int status = 0;
1256 HNDLE hkey;
1257 KEY key;
1258 std::string path = (*paths)[i]->GetString();
1259
1260 status = db_find_key(hDB, 0, path.c_str(), &hkey);
1261 if (status != DB_SUCCESS) {
1262 kresult->AddToArray(MJsonNode::MakeNull());
1263 sresult->AddToArray(MJsonNode::MakeInt(status));
1264 continue;
1265 }
1266
1267 status = db_get_key(hDB, hkey, &key);
1268 if (status != DB_SUCCESS) {
1269 kresult->AddToArray(MJsonNode::MakeNull());
1270 sresult->AddToArray(MJsonNode::MakeInt(status));
1271 continue;
1272 }
1273
1274 MJsonNode* jkey = MJsonNode::MakeObject();
1275
1276 jkey->AddToObject("type", MJsonNode::MakeInt(key.type));
1277 jkey->AddToObject("num_values", MJsonNode::MakeInt(key.num_values));
1279 jkey->AddToObject("name", MJsonNode::MakeString(key.name));
1280 jkey->AddToObject("total_size", MJsonNode::MakeInt(key.total_size));
1281 jkey->AddToObject("item_size", MJsonNode::MakeInt(key.item_size));
1282 jkey->AddToObject("access_mode", MJsonNode::MakeInt(key.access_mode));
1283 jkey->AddToObject("notify_count", MJsonNode::MakeInt(key.notify_count));
1284 jkey->AddToObject("last_written", MJsonNode::MakeInt(key.last_written));
1285
1286 kresult->AddToArray(jkey);
1287 sresult->AddToArray(MJsonNode::MakeInt(status));
1288 }
1289
1290 return mjsonrpc_make_result("keys", kresult, "status", sresult);
1291}
INT num_values
Definition midas.h:1029
WORD notify_count
Definition midas.h:1035
INT total_size
Definition midas.h:1032
WORD access_mode
Definition midas.h:1034
INT item_size
Definition midas.h:1033
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_db_link()

static MJsonNode * js_db_link ( const MJsonNode *  params)
static

Definition at line 1343 of file mjsonrpc.cxx.

1344{
1345 if (!params) {
1346 MJSO* doc = MJSO::I();
1347 doc->D("Create ODB symlinks");
1348 doc->P("new_links[]", MJSON_STRING, "array of new symlinks to be created");
1349 doc->P("target_paths[]", MJSON_STRING, "array of existing ODB paths for each link");
1350 doc->R("status[]", MJSON_INT, "return status of db_create_link() for each path");
1351 return doc;
1352 }
1353
1354 MJsonNode* error = NULL;
1355
1356 const MJsonNodeVector* target_paths = mjsonrpc_get_param_array(params, "target_paths", &error); if (error) return error;
1357 const MJsonNodeVector* new_links = mjsonrpc_get_param_array(params, "new_links", &error); if (error) return error;
1358
1359 if (target_paths->size() != new_links->size()) {
1360 return mjsonrpc_make_error(-32602, "Invalid params", "arrays \"target_paths\" and \"new_links\" should have the same length");
1361 }
1362
1363 MJsonNode* sresult = MJsonNode::MakeArray();
1364
1365 HNDLE hDB;
1367
1368 for (unsigned i=0; i<new_links->size(); i++) {
1369 int status = 0;
1370 std::string target_path = (*target_paths)[i]->GetString();
1371 std::string new_link = (*new_links)[i]->GetString();
1372 if (new_link.length() < 1) {
1373 sresult->AddToArray(MJsonNode::MakeInt(DB_INVALID_PARAM));
1374 continue;
1375 }
1376
1377 status = db_create_link(hDB, 0, new_link.c_str(), target_path.c_str());
1378
1379 sresult->AddToArray(MJsonNode::MakeInt(status));
1380 }
1381
1382 return mjsonrpc_make_result("status", sresult);
1383}
#define DB_INVALID_PARAM
Definition midas.h:640
INT db_create_link(HNDLE hDB, HNDLE hKey, const char *link_name, const char *destination)
Definition odb.cxx:3688
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_db_ls()

static MJsonNode * js_db_ls ( const MJsonNode *  params)
static

Definition at line 805 of file mjsonrpc.cxx.

806{
807 if (!params) {
808 MJSO* doc = MJSO::I();
809 doc->D("get contents of given ODB subdirectory in the \"ls\" json encoding - similar to odbedit command \"ls -l\"");
810 doc->P("paths[]", MJSON_STRING, "array of ODB subtree paths");
811 doc->R("data[]", MJSON_OBJECT, "keys and values of ODB data for each path");
812 doc->R("status[]", MJSON_INT, "return status of db_copy_json_ls() for each path");
813 return doc;
814 }
815
816 MJsonNode* error = NULL;
817
818 const MJsonNodeVector* paths = mjsonrpc_get_param_array(params, "paths", &error); if (error) return error;
819
820 MJsonNode* dresult = MJsonNode::MakeArray();
821 MJsonNode* sresult = MJsonNode::MakeArray();
822
823 HNDLE hDB;
825
826 for (unsigned i=0; i<paths->size(); i++) {
827 int status = 0;
828 HNDLE hkey;
829 std::string path = (*paths)[i]->GetString();
830
831 status = db_find_key(hDB, 0, path.c_str(), &hkey);
832 if (status != DB_SUCCESS) {
833 dresult->AddToArray(MJsonNode::MakeNull());
834 sresult->AddToArray(MJsonNode::MakeInt(status));
835 continue;
836 }
837
838 char* buf = NULL;
839 int bufsize = 0;
840 int end = 0;
841
842 status = db_copy_json_ls(hDB, hkey, &buf, &bufsize, &end);
843
844 if (status == DB_SUCCESS) {
845 ss_repair_utf8(buf);
846 dresult->AddToArray(MJsonNode::MakeJSON(buf));
847 sresult->AddToArray(MJsonNode::MakeInt(status));
848 } else {
849 dresult->AddToArray(MJsonNode::MakeNull());
850 sresult->AddToArray(MJsonNode::MakeInt(status));
851 }
852
853 if (buf)
854 free(buf);
855 }
856
857 return mjsonrpc_make_result("data", dresult, "status", sresult);
858}
INT db_copy_json_ls(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end)
Definition odb.cxx:10442
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_db_paste()

static MJsonNode * js_db_paste ( const MJsonNode *  params)
static

Definition at line 915 of file mjsonrpc.cxx.

916{
917 if (!params) {
918 MJSO* doc = MJSO::I();
919 doc->D("write data into ODB");
920 doc->P("paths[]", MJSON_STRING, "array of ODB subtree paths, see note on array indices");
921 doc->P("values[]", 0, "array of data values written to ODB via db_paste_json() for each path");
922 doc->R("status[]", MJSON_INT, "array of return status of db_paste_json() for each path");
923 return doc;
924 }
925
926 MJsonNode* error = NULL;
927
928 const MJsonNodeVector* paths = mjsonrpc_get_param_array(params, "paths", &error); if (error) return error;
929 const MJsonNodeVector* values = mjsonrpc_get_param_array(params, "values", &error); if (error) return error;
930
931 if (paths->size() != values->size()) {
932 return mjsonrpc_make_error(-32602, "Invalid params", "paths and values should have the same length");
933 }
934
935 MJsonNode* sresult = MJsonNode::MakeArray();
936
937 HNDLE hDB;
939
940 for (unsigned i=0; i<paths->size(); i++) {
941 int status = 0;
942 HNDLE hkey;
943 std::string path = (*paths)[i]->GetString();
944
945 status = db_find_key(hDB, 0, path.c_str(), &hkey);
946 if (status != DB_SUCCESS) {
947 sresult->AddToArray(MJsonNode::MakeInt(status));
948 continue;
949 }
950
951 const MJsonNode* v = (*values)[i];
952 assert(v != NULL);
953
954 if (path.find("[*]") != std::string::npos) {
955
956 KEY key;
957 db_get_key(hDB, hkey, &key);
958 for (int j=0 ; j<key.num_values ; j++)
959 status = db_paste_json_node(hDB, hkey, j, v);
960
961 } else if (path.find("[") != std::string::npos) {
962 std::vector<unsigned> list;
963 status = parse_array_index_list("js_db_paste", path.c_str(), &list);
964
965 if (status != SUCCESS) {
966 sresult->AddToArray(MJsonNode::MakeInt(status));
967 continue;
968 }
969
970 // supported permutations of array indices and data values:
971 // single index: intarray[1] -> data should be a single value: MJSON_ARRAY is rejected right here, MJSON_OBJECT is rejected by db_paste
972 // multiple index intarray[1,2,3] -> data should be an array of equal length, or
973 // multiple index intarray[1,2,3] -> if data is a single value, all array elements are set to this same value
974
975 if (list.size() < 1) {
976 cm_msg(MERROR, "js_db_paste", "invalid array indices for array path \"%s\"", path.c_str());
977 sresult->AddToArray(MJsonNode::MakeInt(DB_TYPE_MISMATCH));
978 continue;
979 } else if (list.size() == 1) {
980 if (v->GetType() == MJSON_ARRAY) {
981 cm_msg(MERROR, "js_db_paste", "unexpected array of values for array path \"%s\"", path.c_str());
982 sresult->AddToArray(MJsonNode::MakeInt(DB_TYPE_MISMATCH));
983 continue;
984 }
985
986 status = db_paste_json_node(hDB, hkey, list[0], v);
987 sresult->AddToArray(MJsonNode::MakeInt(status));
988 } else if ((list.size() > 1) && (v->GetType() == MJSON_ARRAY)) {
989 const MJsonNodeVector* vvalues = v->GetArray();
990
991 if (list.size() != vvalues->size()) {
992 cm_msg(MERROR, "js_db_paste", "length of values array %d should be same as number of indices %d for array path \"%s\"", (int)vvalues->size(), (int)list.size(), path.c_str());
993 sresult->AddToArray(MJsonNode::MakeInt(DB_TYPE_MISMATCH));
994 continue;
995 }
996
997 MJsonNode *ssresult = MJsonNode::MakeArray();
998
999 for (unsigned j =0; j <list.size(); j++) {
1000 const MJsonNode* vv = (*vvalues)[j];
1001
1002 if (vv == NULL) {
1003 cm_msg(MERROR, "js_db_paste", "internal error: NULL array value at index %d for array path \"%s\"", j, path.c_str());
1004 sresult->AddToArray(MJsonNode::MakeInt(DB_TYPE_MISMATCH));
1005 continue;
1006 }
1007
1008 status = db_paste_json_node(hDB, hkey, list[j], vv);
1009 ssresult->AddToArray(MJsonNode::MakeInt(status));
1010 }
1011
1012 sresult->AddToArray(ssresult);
1013 } else {
1014 MJsonNode *ssresult = MJsonNode::MakeArray();
1015 for (unsigned j =0; j <list.size(); j++) {
1016 status = db_paste_json_node(hDB, hkey, list[j], v);
1017 ssresult->AddToArray(MJsonNode::MakeInt(status));
1018 }
1019 sresult->AddToArray(ssresult);
1020 }
1021 } else {
1022 status = db_paste_json_node(hDB, hkey, 0, v);
1023 sresult->AddToArray(MJsonNode::MakeInt(status));
1024 }
1025 }
1026
1027 return mjsonrpc_make_result("status", sresult);
1028}
#define DB_TYPE_MISMATCH
Definition midas.h:646
INT EXPRT db_paste_json_node(HNDLE hDB, HNDLE hKeyRoot, int index, const MJsonNode *node)
INT j
Definition odbhist.cxx:40
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_db_rename()

static MJsonNode * js_db_rename ( const MJsonNode *  params)
static

Definition at line 1293 of file mjsonrpc.cxx.

1294{
1295 if (!params) {
1296 MJSO* doc = MJSO::I();
1297 doc->D("Change size of ODB arrays");
1298 doc->P("paths[]", MJSON_STRING, "array of ODB paths to rename");
1299 doc->P("new_names[]", MJSON_STRING, "array of new names for each ODB path");
1300 doc->R("status[]", MJSON_INT, "return status of db_rename_key() for each path");
1301 return doc;
1302 }
1303
1304 MJsonNode* error = NULL;
1305
1306 const MJsonNodeVector* paths = mjsonrpc_get_param_array(params, "paths", &error); if (error) return error;
1307 const MJsonNodeVector* names = mjsonrpc_get_param_array(params, "new_names", &error); if (error) return error;
1308
1309 if (paths->size() != names->size()) {
1310 return mjsonrpc_make_error(-32602, "Invalid params", "arrays \"paths\" and \"new_names\" should have the same length");
1311 }
1312
1313 MJsonNode* sresult = MJsonNode::MakeArray();
1314
1315 HNDLE hDB;
1317
1318 for (unsigned i=0; i<paths->size(); i++) {
1319 int status = 0;
1320 HNDLE hkey;
1321 std::string path = (*paths)[i]->GetString();
1322
1323 status = db_find_link(hDB, 0, path.c_str(), &hkey);
1324 if (status != DB_SUCCESS) {
1325 sresult->AddToArray(MJsonNode::MakeInt(status));
1326 continue;
1327 }
1328
1329 std::string new_name = (*names)[i]->GetString();
1330 if (new_name.length() < 1) {
1331 sresult->AddToArray(MJsonNode::MakeInt(DB_INVALID_PARAM));
1332 continue;
1333 }
1334
1335 status = db_rename_key(hDB, hkey, new_name.c_str());
1336
1337 sresult->AddToArray(MJsonNode::MakeInt(status));
1338 }
1339
1340 return mjsonrpc_make_result("status", sresult);
1341}
INT db_find_link(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition odb.cxx:4293
INT db_rename_key(HNDLE hDB, HNDLE hKey, const char *name)
Definition odb.cxx:6285
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_db_reorder()

static MJsonNode * js_db_reorder ( const MJsonNode *  params)
static

Definition at line 1385 of file mjsonrpc.cxx.

1386{
1387 if (!params) {
1388 MJSO* doc = MJSO::I();
1389 doc->D("Change order of ODB keys in a subdirectory");
1390 doc->P("paths[]", MJSON_STRING, "array of new symlinks to be created");
1391 doc->P("indices[]", MJSON_INT, "array of existing ODB paths for each link");
1392 doc->R("status[]", MJSON_INT, "return status of db_reorder_key() for each path");
1393 return doc;
1394 }
1395
1396 MJsonNode* error = NULL;
1397
1398 const MJsonNodeVector* paths = mjsonrpc_get_param_array(params, "paths", &error); if (error) return error;
1399 const MJsonNodeVector* indices = mjsonrpc_get_param_array(params, "indices", &error); if (error) return error;
1400
1401 if (paths->size() != indices->size()) {
1402 return mjsonrpc_make_error(-32602, "Invalid params", "arrays \"paths\" and \"indices\" should have the same length");
1403 }
1404
1405 MJsonNode* sresult = MJsonNode::MakeArray();
1406
1407 HNDLE hDB;
1409
1410 for (unsigned i=0; i<paths->size(); i++) {
1411 int status = 0;
1412 HNDLE hkey;
1413 std::string path = (*paths)[i]->GetString();
1414 int index = (*indices)[i]->GetInt();
1415
1416 status = db_find_key(hDB, 0, path.c_str(), &hkey);
1417 if (status != DB_SUCCESS) {
1418 sresult->AddToArray(MJsonNode::MakeInt(status));
1419 continue;
1420 }
1421
1422 status = db_reorder_key(hDB, hkey, index);
1423
1424 sresult->AddToArray(MJsonNode::MakeInt(status));
1425 }
1426
1427 return mjsonrpc_make_result("status", sresult);
1428}
INT db_reorder_key(HNDLE hDB, HNDLE hKey, INT idx)
Definition odb.cxx:6385
INT index
Definition mana.cxx:271
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_db_resize()

static MJsonNode * js_db_resize ( const MJsonNode *  params)
static

Definition at line 1123 of file mjsonrpc.cxx.

1124{
1125 if (!params) {
1126 MJSO* doc = MJSO::I();
1127 doc->D("Change size of ODB arrays");
1128 doc->P("paths[]", MJSON_STRING, "array of ODB paths to resize");
1129 doc->P("new_lengths[]", MJSON_INT, "array of new lengths for each ODB path");
1130 doc->R("status[]", MJSON_INT, "return status of db_set_num_values() for each path");
1131 return doc;
1132 }
1133
1134 MJsonNode* error = NULL;
1135
1136 const MJsonNodeVector* paths = mjsonrpc_get_param_array(params, "paths", &error); if (error) return error;
1137 const MJsonNodeVector* lengths = mjsonrpc_get_param_array(params, "new_lengths", &error); if (error) return error;
1138
1139 if (paths->size() != lengths->size()) {
1140 return mjsonrpc_make_error(-32602, "Invalid params", "arrays \"paths\" and \"new_lengths\" should have the same length");
1141 }
1142
1143 MJsonNode* sresult = MJsonNode::MakeArray();
1144
1145 HNDLE hDB;
1147
1148 for (unsigned i=0; i<paths->size(); i++) {
1149 int status = 0;
1150 HNDLE hkey;
1151 std::string path = (*paths)[i]->GetString();
1152
1153 status = db_find_key(hDB, 0, path.c_str(), &hkey);
1154 if (status != DB_SUCCESS) {
1155 sresult->AddToArray(MJsonNode::MakeInt(status));
1156 continue;
1157 }
1158
1159 int length = (*lengths)[i]->GetInt();
1160 if (length < 1) {
1161 sresult->AddToArray(MJsonNode::MakeInt(DB_INVALID_PARAM));
1162 continue;
1163 }
1164
1165 status = db_set_num_values(hDB, hkey, length);
1166 sresult->AddToArray(MJsonNode::MakeInt(status));
1167 }
1168
1169 return mjsonrpc_make_result("status", sresult);
1170}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_db_resize_string()

static MJsonNode * js_db_resize_string ( const MJsonNode *  params)
static

Definition at line 1172 of file mjsonrpc.cxx.

1173{
1174 if (!params) {
1175 MJSO* doc = MJSO::I();
1176 doc->D("Change size of ODB string arrays");
1177 doc->P("paths[]", MJSON_STRING, "array of ODB paths to resize");
1178 doc->P("new_lengths[]", MJSON_INT, "array of new lengths for each ODB path");
1179 doc->P("new_string_lengths[]", MJSON_INT, "array of new string lengths for each ODB path");
1180 doc->R("status[]", MJSON_INT, "return status of db_resize_string() for each path");
1181 return doc;
1182 }
1183
1184 MJsonNode* error = NULL;
1185
1186 const MJsonNodeVector* paths = mjsonrpc_get_param_array(params, "paths", &error); if (error) return error;
1187 const MJsonNodeVector* lengths = mjsonrpc_get_param_array(params, "new_lengths", &error); if (error) return error;
1188 const MJsonNodeVector* string_lengths = mjsonrpc_get_param_array(params, "new_string_lengths", &error); if (error) return error;
1189
1190 if (paths->size() != lengths->size()) {
1191 return mjsonrpc_make_error(-32602, "Invalid params", "arrays \"paths\" and \"new_lengths\" should have the same length");
1192 }
1193
1194 if (paths->size() != string_lengths->size()) {
1195 return mjsonrpc_make_error(-32602, "Invalid params", "arrays \"paths\" and \"new_string_lengths\" should have the same length");
1196 }
1197
1198 MJsonNode* sresult = MJsonNode::MakeArray();
1199
1200 HNDLE hDB;
1202
1203 for (unsigned i=0; i<paths->size(); i++) {
1204 std::string path = (*paths)[i]->GetString();
1205
1206 int length = (*lengths)[i]->GetInt();
1207 if (length < 0) {
1208 sresult->AddToArray(MJsonNode::MakeInt(DB_INVALID_PARAM));
1209 continue;
1210 }
1211
1212 int string_length = (*string_lengths)[i]->GetInt();
1213 if (length < 0) {
1214 sresult->AddToArray(MJsonNode::MakeInt(DB_INVALID_PARAM));
1215 continue;
1216 }
1217
1218 int status = db_resize_string(hDB, 0, path.c_str(), length, string_length);
1219 sresult->AddToArray(MJsonNode::MakeInt(status));
1220 }
1221
1222 return mjsonrpc_make_result("status", sresult);
1223}
INT EXPRT db_resize_string(HNDLE hdb, HNDLE hKeyRoot, const char *key_name, int num_values, int max_string_length)
Definition odb.cxx:14058
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_db_scl()

static MJsonNode * js_db_scl ( const MJsonNode *  params)
static

Definition at line 1452 of file mjsonrpc.cxx.

1453{
1454 if (!params) {
1455 MJSO* doc = MJSO::I();
1456 doc->D("Show ODB clients");
1457 doc->R("scl", MJSON_JSON, "return value of db_scl()");
1458 return doc;
1459 }
1460
1461 HNDLE hDB;
1463
1464 MJsonNode* scl = db_scl(hDB);
1465
1466 return mjsonrpc_make_result("scl", scl);
1467}
MJsonNode * db_scl(HNDLE hDB)
Definition odb.cxx:14144
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_db_sor()

static MJsonNode * js_db_sor ( const MJsonNode *  params)
static

Definition at line 1430 of file mjsonrpc.cxx.

1431{
1432 if (!params) {
1433 MJSO* doc = MJSO::I();
1434 doc->D("Show ODB open records starting from given ODB path");
1435 doc->P("path?", MJSON_STRING, "ODB path");
1436 doc->R("sor", MJSON_JSON, "return value of db_sor()");
1437 return doc;
1438 }
1439
1440 MJsonNode* error = NULL;
1441
1442 std::string path = mjsonrpc_get_param(params, "path", NULL)->GetString(); if (error) return error;
1443
1444 HNDLE hDB;
1446
1447 MJsonNode* sor = db_sor(hDB, path.c_str());
1448
1449 return mjsonrpc_make_result("sor", sor);
1450}
MJsonNode * db_sor(HNDLE hDB, const char *root_path)
Definition odb.cxx:14194
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_el_delete()

static MJsonNode * js_el_delete ( const MJsonNode *  params)
static

Definition at line 3325 of file mjsonrpc.cxx.

3326{
3327 if (!params) {
3328 MJSO* doc = MJSO::I();
3329 doc->D("Delete elog message");
3330 doc->P("tag", MJSON_STRING, "tag of message to delete");
3331 doc->R("status", MJSON_INT, "return status of el_delete");
3332 return doc;
3333 }
3334
3335 MJsonNode* error = NULL;
3336 std::string tag = mjsonrpc_get_param(params, "tag", &error)->GetString(); if (error) return error;
3337 int status = el_delete_message(tag.c_str());
3338 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
3339}
INT el_delete_message(const char *tag)
Definition elog.cxx:1014
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_el_query()

static MJsonNode * js_el_query ( const MJsonNode *  params)
static

Definition at line 3050 of file mjsonrpc.cxx.

3051{
3052 if (!params) {
3053 MJSO* doc = MJSO::I();
3054 doc->D("Query elog messages");
3055 doc->P("last_n_hours?", MJSON_INT, "return messages from the last N hours");
3056 doc->R("status", MJSON_INT, "return status of el_retrieve");
3057 doc->R("msg[].tag", MJSON_STRING, "message tag");
3058 return doc;
3059 }
3060
3061 //MJsonNode* error = NULL;
3062
3063 //int last_n = mjsonrpc_get_param(params, "last_n_hours", &error)->GetInt(); if (error) return error;
3064 int last_n = mjsonrpc_get_param(params, "last_n_hours", NULL)->GetInt();
3065
3066 std::string pd1 = mjsonrpc_get_param(params, "d1", NULL)->GetString();
3067 std::string pm1 = mjsonrpc_get_param(params, "m1", NULL)->GetString();
3068 std::string py1 = mjsonrpc_get_param(params, "y1", NULL)->GetString();
3069
3070 std::string pd2 = mjsonrpc_get_param(params, "d2", NULL)->GetString();
3071 std::string pm2 = mjsonrpc_get_param(params, "m2", NULL)->GetString();
3072 std::string py2 = mjsonrpc_get_param(params, "y2", NULL)->GetString();
3073
3074 std::string pr1 = mjsonrpc_get_param(params, "r1", NULL)->GetString();
3075 std::string pr2 = mjsonrpc_get_param(params, "r2", NULL)->GetString();
3076
3077 std::string ptype = mjsonrpc_get_param(params, "type", NULL)->GetString();
3078 std::string psystem = mjsonrpc_get_param(params, "system", NULL)->GetString();
3079 std::string pauthor = mjsonrpc_get_param(params, "author", NULL)->GetString();
3080 std::string psubject = mjsonrpc_get_param(params, "subject", NULL)->GetString();
3081 std::string psubtext = mjsonrpc_get_param(params, "subtext", NULL)->GetString();
3082
3083 MJsonNode* msg_array = MJsonNode::MakeArray();
3084
3085 int i, size, run, status;
3086 char date[80], author[80], type[80], system[80], subject[256], text[10000],
3087 orig_tag[80], reply_tag[80], attachment[3][256], encoding[80];
3088 char str[256], str2[10000], tag[256];
3089 struct tm tms;
3090
3091 // month name from midas.c
3092 extern const char *mname[];
3093
3094 /*---- convert end date to ltime ----*/
3095
3096 int y1 = -1;
3097 int m1 = -1;
3098 int d1 = -1;
3099
3100 int y2 = -1;
3101 int m2 = -1;
3102 int d2 = -1;
3103
3104 int r1 = -1;
3105 int r2 = -1;
3106
3107 if (pr1.length()>0)
3108 r1 = atoi(pr1.c_str());
3109
3110 if (pr2.length()>0)
3111 r2 = atoi(pr2.c_str());
3112
3113 time_t ltime_start = 0;
3114 time_t ltime_end = 0;
3115
3116 if (!last_n) {
3117 // decode starting date year, day and month
3118
3119 if (py1.length() > 0)
3120 y1 = atoi(py1.c_str());
3121
3122 if (pd1.length() > 0)
3123 d1 = atoi(pd1.c_str());
3124
3125 mstrlcpy(str, pm1.c_str(), sizeof(str));
3126 for (m1 = 0; m1 < 12; m1++)
3127 if (equal_ustring(str, mname[m1]))
3128 break;
3129 if (m1 == 12)
3130 m1 = 0;
3131
3132 if (pd2.length() > 0) {
3133 d2 = atoi(pd2.c_str());
3134 }
3135
3136 if (py2.length() > 0) {
3137 // decode ending date year, day and month
3138
3139 mstrlcpy(str, pm2.c_str(), sizeof(str));
3140 for (m2 = 0; m2 < 12; m2++)
3141 if (equal_ustring(str, mname[m2]))
3142 break;
3143 if (m2 == 12) {
3144 m2 = 0;
3145 }
3146 }
3147
3148 if (py2.length() > 0) {
3149 y2 = atoi(py2.c_str());
3150 }
3151
3152 if (y2>=0 && m2>=0 && d2>=0) {
3153 memset(&tms, 0, sizeof(struct tm));
3154 tms.tm_year = y2 % 100;
3155 tms.tm_mon = m2;
3156 tms.tm_mday = d2;
3157 tms.tm_hour = 24;
3158
3159 if (tms.tm_year < 90)
3160 tms.tm_year += 100;
3161 ltime_end = ss_mktime(&tms);
3162 }
3163 }
3164
3165 /*---- do query ----*/
3166
3167 tag[0] = 0;
3168
3169 if (last_n) {
3170 ss_tzset(); // required for localtime_r()
3171 time_t now = time(NULL);
3172 ltime_start = now - 3600 * last_n;
3173 struct tm tms;
3174 localtime_r(&ltime_start, &tms);
3175 sprintf(tag, "%02d%02d%02d.0", tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday);
3176 } else if (r1 > 0) {
3177 /* do run query */
3178 el_search_run(r1, tag);
3179 } else if (y1>=0 && m1>=0 && d1>=0) {
3180 /* do date-date query */
3181 sprintf(tag, "%02d%02d%02d.0", y1 % 100, m1 + 1, d1);
3182 }
3183
3184#if 0
3185 printf("js_el_query: y1 %d, m1 %d, d1 %d, y2 %d, m2 %d, d2 %d, r1 %d, r2 %d, last_n_hours %d, start time %lu, end time %lu, tag [%s]\n",
3186 y1, m1, d1,
3187 y2, m2, d2,
3188 r1, r2,
3189 last_n,
3190 ltime_start,
3191 ltime_end,
3192 tag);
3193#endif
3194
3195 do {
3196 size = sizeof(text);
3197 status = el_retrieve(tag, date, &run, author, type, system, subject,
3198 text, &size, orig_tag, reply_tag,
3199 attachment[0], attachment[1], attachment[2], encoding);
3200
3201 std::string this_tag = tag;
3202
3203 //printf("js_el_query: el_retrieve: size %d, status %d, tag [%s], run %d, tags [%s] [%s]\n", size, status, tag, run, orig_tag, reply_tag);
3204
3205 mstrlcat(tag, "+1", sizeof(tag));
3206
3207 /* check for end run */
3208 if ((r2 > 0) && (r2 < run)) {
3209 break;
3210 }
3211
3212 /* convert date to unix format */
3213 memset(&tms, 0, sizeof(struct tm));
3214 tms.tm_year = (tag[0] - '0') * 10 + (tag[1] - '0');
3215 tms.tm_mon = (tag[2] - '0') * 10 + (tag[3] - '0') - 1;
3216 tms.tm_mday = (tag[4] - '0') * 10 + (tag[5] - '0');
3217 tms.tm_hour = (date[11] - '0') * 10 + (date[12] - '0');
3218 tms.tm_min = (date[14] - '0') * 10 + (date[15] - '0');
3219 tms.tm_sec = (date[17] - '0') * 10 + (date[18] - '0');
3220
3221 if (tms.tm_year < 90)
3222 tms.tm_year += 100;
3223
3224 time_t ltime_current = ss_mktime(&tms);
3225
3226 //printf("js_el_query: ltime: start %ld, end %ld, current %ld\n", ltime_start, ltime_end, ltime_current);
3227
3228 /* check for start date */
3229 if (ltime_start > 0)
3230 if (ltime_current < ltime_start)
3231 continue;
3232
3233 /* check for end date */
3234 if (ltime_end > 0) {
3235 if (ltime_current > ltime_end)
3236 break;
3237 }
3238
3239 if (status == EL_SUCCESS) {
3240 /* do filtering */
3241 if ((ptype.length()>0) && !equal_ustring(ptype.c_str(), type))
3242 continue;
3243 if ((psystem.length()>0) && !equal_ustring(psystem.c_str(), system))
3244 continue;
3245
3246 if (pauthor.length()>0) {
3247 mstrlcpy(str, pauthor.c_str(), sizeof(str));
3248 for (i = 0; i < (int) strlen(str); i++)
3249 str[i] = toupper(str[i]);
3250 str[i] = 0;
3251 for (i = 0; i < (int) strlen(author) && author[i] != '@'; i++)
3252 str2[i] = toupper(author[i]);
3253 str2[i] = 0;
3254
3255 if (strstr(str2, str) == NULL)
3256 continue;
3257 }
3258
3259 if (psubject.length()>0) {
3260 mstrlcpy(str, psubject.c_str(), sizeof(str));
3261 for (i = 0; i < (int) strlen(str); i++)
3262 str[i] = toupper(str[i]);
3263 str[i] = 0;
3264 for (i = 0; i < (int) strlen(subject); i++)
3265 str2[i] = toupper(subject[i]);
3266 str2[i] = 0;
3267
3268 if (strstr(str2, str) == NULL)
3269 continue;
3270 }
3271
3272 if (psubtext.length()>0) {
3273 mstrlcpy(str, psubtext.c_str(), sizeof(str));
3274 for (i = 0; i < (int) strlen(str); i++)
3275 str[i] = toupper(str[i]);
3276 str[i] = 0;
3277 for (i = 0; i < (int) strlen(text); i++)
3278 str2[i] = toupper(text[i]);
3279 str2[i] = 0;
3280
3281 if (strstr(str2, str) == NULL)
3282 continue;
3283 }
3284
3285 /* filter passed: display line */
3286
3287 MJsonNode* msg = MJsonNode::MakeObject();
3288
3289 ss_repair_utf8(this_tag);
3290 msg->AddToObject("tag", MJsonNode::MakeString(this_tag.c_str()));
3291 ss_repair_utf8(date);
3292 msg->AddToObject("date", MJsonNode::MakeString(date));
3293 msg->AddToObject("run", MJsonNode::MakeInt(run));
3294 ss_repair_utf8(author);
3295 msg->AddToObject("author", MJsonNode::MakeString(author));
3297 msg->AddToObject("type", MJsonNode::MakeString(type));
3298 ss_repair_utf8(system);
3299 msg->AddToObject("system", MJsonNode::MakeString(system));
3300 ss_repair_utf8(subject);
3301 msg->AddToObject("subject", MJsonNode::MakeString(subject));
3302 ss_repair_utf8(text);
3303 msg->AddToObject("text", MJsonNode::MakeString(text));
3304 ss_repair_utf8(orig_tag);
3305 msg->AddToObject("orig_tag", MJsonNode::MakeString(orig_tag));
3306 ss_repair_utf8(reply_tag);
3307 msg->AddToObject("reply_tag", MJsonNode::MakeString(reply_tag));
3308 ss_repair_utf8(attachment[0]);
3309 msg->AddToObject("attachment0", MJsonNode::MakeString(attachment[0]));
3310 ss_repair_utf8(attachment[1]);
3311 msg->AddToObject("attachment1", MJsonNode::MakeString(attachment[1]));
3312 ss_repair_utf8(attachment[2]);
3313 msg->AddToObject("attachment2", MJsonNode::MakeString(attachment[2]));
3314 ss_repair_utf8(encoding);
3315 msg->AddToObject("encoding", MJsonNode::MakeString(encoding));
3316
3317 msg_array->AddToArray(msg);
3318 }
3319
3320 } while (status == EL_SUCCESS);
3321
3322 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "msg", msg_array);
3323}
INT el_search_run(int run, char *return_tag)
Definition elog.cxx:950
INT el_retrieve(char *tag, char *date, int *run, char *author, char *type, char *syst, char *subject, char *text, int *textsize, char *orig_tag, char *reply_tag, char *attachment1, char *attachment2, char *attachment3, char *encoding)
Definition elog.cxx:770
#define EL_SUCCESS
Definition midas.h:746
time_t ss_mktime(struct tm *tms)
Definition system.cxx:3437
void ss_tzset()
Definition system.cxx:3427
BOOL equal_ustring(const char *str1, const char *str2)
Definition odb.cxx:3285
const char * mname[]
Definition midas.cxx:144
MUTEX_T * tm
Definition odbedit.cxx:39
DWORD run
Definition odbhist.cxx:39
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_el_retrieve()

static MJsonNode * js_el_retrieve ( const MJsonNode *  params)
static

Definition at line 2984 of file mjsonrpc.cxx.

2985{
2986 if (!params) {
2987 MJSO* doc = MJSO::I();
2988 doc->D("Get an elog message");
2989 doc->P("tag", MJSON_STRING, "elog message tag");
2990 doc->R("status", MJSON_INT, "return status of el_retrieve");
2991 doc->R("msg.tag", MJSON_STRING, "message tag");
2992 return doc;
2993 }
2994
2995 MJsonNode* error = NULL;
2996
2997 std::string tag = mjsonrpc_get_param(params, "tag", &error)->GetString(); if (error) return error;
2998
2999 int run = 0;
3000 char date[80], author[80], type[80], system[80], subject[256], text[10000];
3001 char orig_tag[80], reply_tag[80], attachment[3][256], encoding[80];
3002
3003 char xtag[80];
3004 mstrlcpy(xtag, tag.c_str(), sizeof(xtag));
3005
3006 int size = sizeof(text);
3007
3008 int status = el_retrieve(xtag,
3009 date, &run, author, type, system, subject,
3010 text, &size, orig_tag, reply_tag,
3011 attachment[0], attachment[1], attachment[2], encoding);
3012
3013 //printf("js_el_retrieve: size %d, status %d, tag [%s]\n", size, status, xtag);
3014
3015 MJsonNode* msg = MJsonNode::MakeObject();
3016
3017 if (status == EL_SUCCESS) {
3018 ss_repair_utf8(xtag);
3019 msg->AddToObject("tag", MJsonNode::MakeString(xtag));
3020 ss_repair_utf8(date);
3021 msg->AddToObject("date", MJsonNode::MakeString(date));
3022 msg->AddToObject("run", MJsonNode::MakeInt(run));
3023 ss_repair_utf8(author);
3024 msg->AddToObject("author", MJsonNode::MakeString(author));
3026 msg->AddToObject("type", MJsonNode::MakeString(type));
3027 ss_repair_utf8(system);
3028 msg->AddToObject("system", MJsonNode::MakeString(system));
3029 ss_repair_utf8(subject);
3030 msg->AddToObject("subject", MJsonNode::MakeString(subject));
3031 ss_repair_utf8(text);
3032 msg->AddToObject("text", MJsonNode::MakeString(text));
3033 ss_repair_utf8(orig_tag);
3034 msg->AddToObject("orig_tag", MJsonNode::MakeString(orig_tag));
3035 ss_repair_utf8(reply_tag);
3036 msg->AddToObject("reply_tag", MJsonNode::MakeString(reply_tag));
3037 ss_repair_utf8(attachment[0]);
3038 msg->AddToObject("attachment0", MJsonNode::MakeString(attachment[0]));
3039 ss_repair_utf8(attachment[1]);
3040 msg->AddToObject("attachment1", MJsonNode::MakeString(attachment[1]));
3041 ss_repair_utf8(attachment[2]);
3042 msg->AddToObject("attachment2", MJsonNode::MakeString(attachment[2]));
3043 ss_repair_utf8(encoding);
3044 msg->AddToObject("encoding", MJsonNode::MakeString(encoding));
3045 }
3046
3047 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "msg", msg);
3048}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_ext_list_files()

static MJsonNode * js_ext_list_files ( const MJsonNode *  params)
static

Definition at line 4143 of file mjsonrpc.cxx.

4144{
4145 if (!params) {
4146 MJSO* doc = MJSO::I();
4147 doc->D("js_ext_list_files");
4148 doc->P("subdir", MJSON_STRING, "List files in experiment_directory/userfiles/subdir");
4149 doc->P("fileext", MJSON_STRING, "Filename extension");
4150 doc->R("status", MJSON_INT, "return status of midas library calls");
4151 doc->R("path", MJSON_STRING, "Search path");
4152 doc->R("subdirs[]", MJSON_STRING, "list of subdirectories");
4153 doc->R("files[].filename", MJSON_STRING, "script filename");
4154 doc->R("files[].description", MJSON_STRING, "script description");
4155 return doc;
4156 }
4157
4158 MJsonNode* error = NULL;
4159 std::string subdir = mjsonrpc_get_param(params, "subdir", &error)->GetString(); if (error) return error;
4160 std::string fileext = mjsonrpc_get_param(params, "fileext", &error)->GetString(); if (error) return error;
4161
4162 /*---- Not allowed to contain ../ - safety feature ----*/
4163 if (subdir.find("..") != std::string::npos) {
4164 return mjsonrpc_make_result("status", MJsonNode::MakeInt(DB_INVALID_PARAM), "error", MJsonNode::MakeString("The subdir is not permitted"));
4165 }
4166
4167 /*---- ext must start with *. and some not allowed ext - safety feature */
4168 if (fileext.find("..") != std::string::npos) {
4169 /*
4170 fileext.find("/") != std::string::npos ||
4171 fileext.find("*.") != 0 ||
4172 fileext.find("*.html") != std::string::npos || fileext.find("*.HTML") != std::string::npos ||
4173 fileext.find("*.htm") != std::string::npos || fileext.find("*.HTM") != std::string::npos ||
4174 fileext.find("*.js") != std::string::npos || fileext.find("*.JS") != std::string::npos ||
4175 fileext.find("*.pl") != std::string::npos || fileext.find("*.PL") != std::string::npos ||
4176 fileext.find("*.cgi") != std::string::npos || fileext.find("*.CGI") != std::string::npos ||
4177 fileext.find("*.*") != std::string::npos
4178 ) {
4179 */
4180 return mjsonrpc_make_result("status", MJsonNode::MakeInt(DB_INVALID_PARAM), "error", MJsonNode::MakeString("The filename extension is not permitted"));
4181 }
4182
4183 int status;
4184 HNDLE hDB;
4185
4187
4188 if (status != DB_SUCCESS) {
4189 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
4190 }
4191
4192 std::string path = cm_expand_env(cm_get_path().c_str());
4193 if (path[path.length()-1] != DIR_SEPARATOR) {
4194 path += DIR_SEPARATOR_STR;
4195 }
4196 path += "userfiles";
4197
4198 // Check if the userfiles folder exists
4199 if (access(path.c_str(), F_OK) != 0) {
4200 // Create the path if it doesn't exist
4201 if (mkdir(path.c_str(), 0777) != 0) {
4202 return mjsonrpc_make_result("status", MJsonNode::MakeInt(DB_INVALID_PARAM), "error", MJsonNode::MakeString("Failed to create the userfiles folder"));
4203 }
4204 }
4205
4206 if (subdir.length() > 0) {
4207 if (subdir[0] != DIR_SEPARATOR) {
4208 path += DIR_SEPARATOR_STR;
4209 }
4210 path += subdir;
4211 }
4212
4213 char* flist = NULL;
4214 MJsonNode* s = MJsonNode::MakeArray();
4215
4216 /*---- go over subdirectories ----*/
4217 int n = ss_dirlink_find(path.c_str(), "*", &flist);
4218
4219 for (int i=0 ; i<n ; i++) {
4220 if (flist[i*MAX_STRING_LENGTH] != '.') {
4221 //printf("subdir %d: [%s]\n", i, flist+i*MAX_STRING_LENGTH);
4223 s->AddToArray(MJsonNode::MakeString(flist+i*MAX_STRING_LENGTH));
4224 }
4225 }
4226
4227 MJsonNode* f = MJsonNode::MakeArray();
4228 time_t modtime = time(NULL);
4229 double fsize;
4230 /*---- go over files with extension fileext in path ----*/
4231 n = ss_file_find(path.c_str(), fileext.c_str(), &flist);
4232
4233 if (n == -1) {
4234 // path does not exist, return an error
4235 return mjsonrpc_make_result("status", MJsonNode::MakeInt(DB_INVALID_PARAM), "error", MJsonNode::MakeString("Subdirectory does not exist, create it first."));
4236 }
4237
4238 for (int i=0 ; i<n ; i++) {
4239 //printf("file %d: [%s]\n", i, flist+i*MAX_STRING_LENGTH);
4240 MJsonNode* o = MJsonNode::MakeObject();
4242 o->AddToObject("filename", MJsonNode::MakeString(flist+i*MAX_STRING_LENGTH));
4243 /* description is msl specific, do we need it? */
4244 std::string full_name = path;
4245 if (full_name.back() != DIR_SEPARATOR)
4246 full_name += DIR_SEPARATOR;
4247 full_name.append(flist+i*MAX_STRING_LENGTH);
4248 // o->AddToObject("description", MJsonNode::MakeString(full_name.c_str()));
4249 o->AddToObject("description", MJsonNode::MakeString("description"));
4250 modtime = ss_file_time(full_name.c_str());
4251 o->AddToObject("modtime", MJsonNode::MakeInt(modtime));
4252 fsize = ss_file_size(full_name.c_str());
4253 o->AddToObject("size", MJsonNode::MakeInt(fsize));
4254 f->AddToArray(o);
4255 }
4256
4257 free(flist);
4258 flist = NULL;
4259
4260 MJsonNode* r = MJsonNode::MakeObject();
4261 r->AddToObject("status", MJsonNode::MakeInt(SUCCESS));
4262 ss_repair_utf8(path);
4263 r->AddToObject("path", MJsonNode::MakeString(path.c_str()));
4264 r->AddToObject("subdirs", s);
4265 r->AddToObject("files", f);
4266
4267 return mjsonrpc_make_result(r);
4268
4269}
std::string cm_expand_env(const char *str)
Definition midas.cxx:7720
std::string cm_get_path()
Definition midas.cxx:1552
#define MAX_STRING_LENGTH
Definition msystem.h:113
INT ss_dirlink_find(const char *path, const char *pattern, char **plist)
Definition system.cxx:6950
time_t ss_file_time(const char *path)
Definition system.cxx:7088
double ss_file_size(const char *path)
Definition system.cxx:7050
INT ss_file_find(const char *path, const char *pattern, char **plist)
Definition system.cxx:6791
DWORD n[4]
Definition mana.cxx:247
#define DIR_SEPARATOR
Definition midas.h:193
#define DIR_SEPARATOR_STR
Definition midas.h:194
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_ext_read_file()

static MJsonNode * js_ext_read_file ( const MJsonNode *  params)
static

Definition at line 4347 of file mjsonrpc.cxx.

4348{
4349 if (!params) {
4350 MJSO* doc = MJSO::I();
4351 doc->D("js_ext_read_script");
4352 doc->P("filename", MJSON_STRING, "File name, read from experiment_directory/userfiles/filename");
4353 doc->R("content", MJSON_STRING, "ASCII file content");
4354 doc->R("status", MJSON_INT, "return status of midas library calls");
4355 doc->R("error", MJSON_STRING, "error text");
4356 return doc;
4357 }
4358
4359 MJsonNode* error = NULL;
4360 std::string filename = mjsonrpc_get_param(params, "filename", &error)->GetString(); if (error) return error;
4361
4362 /*---- filename should not contain the following - safety feature */
4363 if (filename.find("..") != std::string::npos ||
4364 filename.find("*") != std::string::npos) {
4365 return mjsonrpc_make_result("status", MJsonNode::MakeInt(DB_INVALID_PARAM), "error", MJsonNode::MakeString("The filename is not permitted"));
4366 }
4367
4368 int status;
4369 HNDLE hDB;
4370
4372
4373 if (status != DB_SUCCESS) {
4374 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "error", MJsonNode::MakeString("cm_get_experiment_database() error"));
4375 }
4376
4377 std::string path = cm_expand_env(cm_get_path().c_str());
4378 if (path[path.length()-1] != DIR_SEPARATOR) {
4379 path += DIR_SEPARATOR_STR;
4380 }
4381 path += "userfiles";
4382
4383 // Check if the userfiles folder exists
4384 if (access(path.c_str(), F_OK) != 0) {
4385 // Create the path if it doesn't exist
4386 if (mkdir(path.c_str(), 0777) != 0) {
4387 return mjsonrpc_make_result("status", MJsonNode::MakeInt(DB_INVALID_PARAM), "error", MJsonNode::MakeString("Failed to create the userfiles folder"));
4388 }
4389 }
4390
4391 path += DIR_SEPARATOR_STR;
4392 path += filename;
4393
4394 FILE* fp = fopen(path.c_str(), "r");
4395 if (!fp) {
4397 char errstr[256];
4398 sprintf(errstr, "fopen() errno %d (%s)", errno, strerror(errno));
4399 ss_repair_utf8(errstr);
4400 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "error", MJsonNode::MakeString(errstr));
4401 }
4402
4403 fseek(fp, 0, SEEK_END);
4404 size_t file_size = ftell(fp);
4405 rewind(fp);
4406
4407 char* buffer = new char[file_size+1];
4408 fread(buffer, file_size, 1, fp);
4409 // Maybe not needed here
4410 buffer[file_size] = '\0';
4411 fclose(fp);
4412
4413 std::string content = buffer;
4414 delete[] buffer;
4415 buffer = NULL;
4416
4418 std::string errstr = "no error";
4419
4420 return mjsonrpc_make_result("content", MJsonNode::MakeString(content.c_str()), "status", MJsonNode::MakeInt(status), "error", MJsonNode::MakeString(errstr.c_str()));
4421}
#define CM_SUCCESS
Definition midas.h:582
#define SS_FILE_ERROR
Definition midas.h:670
char content[600000]
Definition melog.cxx:90
static FILE * fp
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_ext_save_file()

static MJsonNode * js_ext_save_file ( const MJsonNode *  params)
static

Definition at line 4271 of file mjsonrpc.cxx.

4272{
4273 if (!params) {
4274 MJSO* doc = MJSO::I();
4275 doc->D("js_ext_save_file");
4276 doc->P("filename", MJSON_STRING, "File name, save in experiment_directory/userfiles/filename");
4277 doc->P("script", MJSON_STRING, "ASCII content");
4278 doc->R("status", MJSON_INT, "return status of midas library calls");
4279 doc->R("error", MJSON_STRING, "error text");
4280 return doc;
4281 }
4282
4283 /* Need to make sure that content cannot be abused (e.g. not Javascript code), how?? */
4284
4285 MJsonNode* error = NULL;
4286 std::string filename = mjsonrpc_get_param(params, "filename", &error)->GetString(); if (error) return error;
4287 std::string script = mjsonrpc_get_param(params, "script", &error)->GetString(); if (error) return error;
4288
4289 /*---- filename should not contain the following - safety feature */
4290 if (filename.find("..") != std::string::npos ) {
4291 /*
4292 filename.find("*") != std::string::npos ||
4293 filename.find(".html") != std::string::npos || filename.find(".HTML") != std::string::npos ||
4294 filename.find(".htm") != std::string::npos || filename.find(".HTM") != std::string::npos ||
4295 filename.find(".js") != std::string::npos || filename.find(".JS") != std::string::npos ||
4296 filename.find(".pl") != std::string::npos || filename.find(".PL") != std::string::npos ||
4297 filename.find(".cgi") != std::string::npos || filename.find(".CGI") != std::string::npos
4298 ) {
4299 */
4300 return mjsonrpc_make_result("status", MJsonNode::MakeInt(DB_INVALID_PARAM), "error", MJsonNode::MakeString("The filename is not permitted"));
4301 }
4302
4303 int status;
4304 HNDLE hDB;
4305
4307
4308 if (status != DB_SUCCESS) {
4309 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "error", MJsonNode::MakeString("cm_get_experiment_database() error"));
4310 }
4311
4312 std::string path = cm_expand_env(cm_get_path().c_str());
4313 path += "userfiles";
4314
4315 // Check if the userfiles folder exists
4316 if (access(path.c_str(), F_OK) != 0) {
4317 // Create the path if it doesn't exist
4318 if (mkdir(path.c_str(), 0777) != 0) {
4319 return mjsonrpc_make_result("status", MJsonNode::MakeInt(DB_INVALID_PARAM), "error", MJsonNode::MakeString("Failed to create the userfiles folder"));
4320 }
4321 }
4322
4323 path += DIR_SEPARATOR_STR;
4324 path += filename;
4325
4326 FILE* fp = fopen(path.c_str(), "w");
4327 if (!fp) {
4329 char errstr[256];
4330 sprintf(errstr, "fopen() errno %d (%s)", errno, strerror(errno));
4331 ss_repair_utf8(errstr);
4332 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "error", MJsonNode::MakeString(errstr));
4333 }
4334
4335 fwrite(script.c_str(), script.length(), 1, fp);
4336 //fprintf(fp, "\n");
4337 fclose(fp);
4338 fp = NULL;
4339
4341 std::string errstr = "no error";
4342
4343 //ss_repair_utf8(errstr); redundant!
4344 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "error", MJsonNode::MakeString(errstr.c_str()));
4345}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_get_timezone()

static MJsonNode * js_get_timezone ( const MJsonNode *  params)
static

Definition at line 4603 of file mjsonrpc.cxx.

4604{
4605 if (!params) {
4606 MJSO *doc = MJSO::I();
4607 doc->D("get current server timezone offset in seconds");
4608 doc->P(NULL, 0, "there are no input parameters");
4609 doc->R(NULL, MJSON_INT, "offset in seconds");
4610 return doc;
4611 }
4612
4613 ss_tzset(); // required for localtime_r()
4614 time_t rawtime = time(NULL);
4615 struct tm gmt_tms;
4616 gmtime_r(&rawtime, &gmt_tms);
4617 time_t gmt = ss_mktime(&gmt_tms);
4618 struct tm tms;
4619 localtime_r(&rawtime, &tms);
4620 time_t offset = rawtime - gmt + (tms.tm_isdst ? 3600 : 0);
4621
4622 return mjsonrpc_make_result(MJsonNode::MakeNumber(offset));
4623}
static int offset
Definition mgd.cxx:1500
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_hs_exit()

static void js_hs_exit ( )
static

Definition at line 1739 of file mjsonrpc.cxx.

1740{
1741 for (auto& e : gHistoryChannels) {
1742 //printf("history channel \"%s\" mh %p\n", e.first.c_str(), e.second);
1743 delete e.second;
1744 }
1745 gHistoryChannels.clear();
1746}
static double e(void)
Definition tinyexpr.c:136
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_hs_get_active_events()

static MJsonNode * js_hs_get_active_events ( const MJsonNode *  params)
static

Definition at line 1661 of file mjsonrpc.cxx.

1662{
1663 if (!params) {
1664 MJSO* doc = MJSO::I();
1665 doc->D("get list of active history events using hs_read_event_list()");
1666 doc->R("status", MJSON_INT, "return status of hs_read_event_list()");
1667 doc->R("events[]", MJSON_STRING, "array of history event names");
1668 return doc;
1669 }
1670
1672
1674
1675 MJsonNode* events = MJsonNode::MakeArray();
1676
1677 for (unsigned i=0; i<list.size(); i++) {
1679 events->AddToArray(MJsonNode::MakeString(list[i].c_str()));
1680 }
1681
1682 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "events", events);
1683}
int hs_read_event_list(std::vector< std::string > *pevents)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_hs_get_channels()

static MJsonNode * js_hs_get_channels ( const MJsonNode *  params)
static

Definition at line 1748 of file mjsonrpc.cxx.

1749{
1750 if (!params) {
1751 MJSO* doc = MJSO::I();
1752 doc->D("get list of history channels in /Logger/History");
1753 doc->R("status", MJSON_INT, "return success or failure status");
1754 doc->R("default_channel", MJSON_STRING, "name of the default logger history channel");
1755 doc->R("channels[]", MJSON_STRING, "all logger history channel names");
1756 doc->R("active_channels[]", MJSON_STRING, "active logger history channel names");
1757 return doc;
1758 }
1759
1760 MJsonNode* channels = MJsonNode::MakeArray();
1761 MJsonNode* active_channels = MJsonNode::MakeArray();
1762
1763 HNDLE hDB;
1765
1766 // get history channel name selected by user in ODB
1767
1768 //std::string selected_channel;
1769 //db_get_value_string(hDB, 0, "/History/LoggerHistoryChannel", 0, &selected_channel, TRUE);
1770
1771 int status;
1772 HNDLE hKeyChan;
1773
1774 status = db_find_key(hDB, 0, "/Logger/History", &hKeyChan);
1775 if (status == DB_SUCCESS) {
1776 for (int ichan=0; ; ichan++) {
1777 HNDLE hKey;
1778 status = db_enum_key(hDB, hKeyChan, ichan, &hKey);
1779 if (status == DB_NO_MORE_SUBKEYS) {
1781 break;
1782 }
1783 if (status != DB_SUCCESS)
1784 break;
1785
1786 KEY key;
1787
1789
1790 if (status == DB_SUCCESS) {
1792 channels->AddToArray(MJsonNode::MakeString(key.name));
1793
1794 INT active = 0;
1795 INT size = sizeof(active);
1796 status = db_get_value(hDB, hKey, "Active", &active, &size, TID_BOOL, FALSE);
1797 if (status == DB_SUCCESS) {
1798 if (active) {
1799 active_channels->AddToArray(MJsonNode::MakeString(key.name));
1800 }
1801 }
1802 }
1803 }
1804 }
1805
1806 std::string default_channel;
1807
1808 HNDLE hKey;
1810 if (status == DB_SUCCESS) {
1811 KEY key;
1813 if (status == DB_SUCCESS) {
1814 default_channel = key.name;
1815 }
1816 }
1817
1818 return mjsonrpc_make_result("status", MJsonNode::MakeInt(1),
1819 //"selected_channel", MJsonNode::MakeString(selected_channel.c_str()),
1820 "default_channel", MJsonNode::MakeString(default_channel.c_str()),
1821 "active_channels", active_channels,
1822 "channels", channels);
1823}
#define FALSE
Definition cfortran.h:309
#define DB_NO_MORE_SUBKEYS
Definition midas.h:647
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition odb.cxx:5357
int INT
Definition midas.h:129
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_hs_get_events()

static MJsonNode * js_hs_get_events ( const MJsonNode *  params)
static

Definition at line 1825 of file mjsonrpc.cxx.

1826{
1827 if (!params) {
1828 MJSO* doc = MJSO::I();
1829 doc->D("get list of history events that existed at give time using hs_get_events()");
1830 doc->P("channel?", MJSON_STRING, "midas history channel, default is the default reader channel");
1831 doc->P("time?", MJSON_NUMBER, "timestamp, value 0 means current time, default is 0");
1832 doc->R("status", MJSON_INT, "return status of hs_get_events()");
1833 doc->R("channel", MJSON_STRING, "logger history channel name");
1834 doc->R("events[]", MJSON_STRING, "array of history event names");
1835 return doc;
1836 }
1837
1838 std::string channel = mjsonrpc_get_param(params, "channel", NULL)->GetString();
1839 double time = mjsonrpc_get_param(params, "time", NULL)->GetDouble();
1840
1842
1843 MJsonNode* events = MJsonNode::MakeArray();
1844
1845 if (!mh) {
1846 int status = HS_FILE_ERROR;
1847 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "events", events);
1848 }
1849
1850 if (time == 0) {
1851 time = ::time(NULL);
1852 }
1853
1855
1856 int status = mh->hs_get_events(time, &list);
1857
1858 for (unsigned i=0; i<list.size(); i++) {
1860 events->AddToArray(MJsonNode::MakeString(list[i].c_str()));
1861 }
1862
1863 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "channel", MJsonNode::MakeString(mh->name), "events", events);
1864}
virtual int hs_get_events(time_t time_from, std::vector< std::string > *pevents)=0
get list of events that exist(ed) at given time and later (value 0 means "return all events from begi...
char name[NAME_LENGTH]
Definition history.h:111
#define HS_FILE_ERROR
Definition midas.h:729
INT channel
static MidasHistoryInterface * GetHistory(const char *name)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_hs_get_last_written()

static MJsonNode * js_hs_get_last_written ( const MJsonNode *  params)
static

Definition at line 1969 of file mjsonrpc.cxx.

1970{
1971 if (!params) {
1972 MJSO* doc = MJSO::I();
1973 doc->D("get list of history tags for given history events that existed at give time using hs_get_last_written()");
1974 doc->P("channel?", MJSON_STRING, "midas history channel, default is the default reader channel");
1975 doc->P("time?", MJSON_NUMBER, "timestamp, value 0 means current time, default is 0");
1976 doc->P("events[]", MJSON_STRING, "array of history event names");
1977 doc->P("tags[]", MJSON_STRING, "array of history event tag names");
1978 doc->P("index[]", MJSON_STRING, "array of history event tag array indices");
1979 doc->R("status", MJSON_INT, "return status");
1980 doc->R("channel", MJSON_STRING, "logger history channel name");
1981 doc->R("last_written[]", MJSON_NUMBER, "array of last-written times for each history event");
1982 return doc;
1983 }
1984
1985 std::string channel = mjsonrpc_get_param(params, "channel", NULL)->GetString();
1986 double time = mjsonrpc_get_param(params, "time", NULL)->GetDouble();
1987
1988 const MJsonNodeVector* events_array = mjsonrpc_get_param_array(params, "events", NULL);
1989 const MJsonNodeVector* tags_array = mjsonrpc_get_param_array(params, "tags", NULL);
1990 const MJsonNodeVector* index_array = mjsonrpc_get_param_array(params, "index", NULL);
1991
1993
1994 MJsonNode* lw = MJsonNode::MakeArray();
1995
1996 if (!mh) {
1997 int status = HS_FILE_ERROR;
1998 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "last_written", lw);
1999 }
2000
2001 unsigned num_var = events_array->size();
2002
2003 if (tags_array->size() != num_var) {
2004 return mjsonrpc_make_error(-32602, "Invalid params", "Arrays events and tags should have the same length");
2005 }
2006
2007 if (index_array->size() != num_var) {
2008 return mjsonrpc_make_error(-32602, "Invalid params", "Arrays events and index should have the same length");
2009 }
2010
2011 std::vector<std::string> event_names(num_var);
2012 std::vector<std::string> tag_names(num_var);
2013 // const char** event_name = new const char*[num_var];
2014 // const char** tag_name = new const char*[num_var];
2015 int* var_index = new int[num_var];
2016 time_t* last_written = new time_t[num_var];
2017
2018 for (unsigned i=0; i<num_var; i++) {
2019 //event_name[i] = (*events_array)[i]->GetString().c_str();
2020 //tag_name[i] = (*tags_array)[i]->GetString().c_str();
2021 event_names[i] = (*events_array)[i]->GetString();
2022 tag_names[i] = (*tags_array)[i]->GetString();
2023 var_index[i] = (*index_array)[i]->GetInt();
2024 }
2025
2026 if (/* DISABLES CODE */ (0)) {
2027 printf("time %f, num_vars %d:\n", time, num_var);
2028 for (unsigned i=0; i<num_var; i++) {
2029 printf("%d: [%s] [%s] [%d]\n", i, event_names[i].c_str(), tag_names[i].c_str(), var_index[i]);
2030 }
2031 }
2032
2033 if (time == 0) {
2034 time = ::time(NULL);
2035 }
2036
2037
2038 const char** event_name = new const char*[num_var];
2039 const char** tag_name = new const char*[num_var];
2040 for (unsigned i=0; i<num_var; i++) {
2041 event_name[i] = event_names[i].c_str();
2042 tag_name[i] = tag_names[i].c_str();
2043 }
2044 int status = mh->hs_get_last_written(time, num_var, event_name, tag_name, var_index, last_written);
2045
2046 for (unsigned i=0; i<num_var; i++) {
2047 if (/* DISABLES CODE */ (0)) {
2048 printf("%d: last_written %d\n", i, (int)last_written[i]);
2049 }
2050 lw->AddToArray(MJsonNode::MakeNumber(last_written[i]));
2051 }
2052
2053 delete[] event_name;
2054 delete[] tag_name;
2055 delete[] var_index;
2056 delete[] last_written;
2057
2058 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "channel", MJsonNode::MakeString(mh->name), "last_written", lw);
2059}
virtual int hs_get_last_written(time_t start_time, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], time_t last_written[])=0
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_hs_get_tags()

static MJsonNode * js_hs_get_tags ( const MJsonNode *  params)
static

Definition at line 1891 of file mjsonrpc.cxx.

1892{
1893 if (!params) {
1894 MJSO* doc = MJSO::I();
1895 doc->D("get list of history tags for given history events that existed at give time using hs_get_tags()");
1896 doc->P("channel?", MJSON_STRING, "midas history channel, default is the default reader channel");
1897 doc->P("time?", MJSON_NUMBER, "timestamp, value 0 means current time, default is 0");
1898 doc->P("events[]?", MJSON_STRING, "array of history event names, default is get all events using hs_get_events()");
1899 doc->R("status", MJSON_INT, "return status");
1900 doc->R("channel", MJSON_STRING, "logger history channel name");
1901 doc->R("events[].name", MJSON_STRING, "array of history event names for each history event");
1902 doc->R("events[].status", MJSON_INT, "array of status ohistory tags for each history event");
1903 doc->R("events[].tags[]", MJSON_STRING, "array of history tags for each history event");
1904 doc->R("events[].tags[].name", MJSON_STRING, "history tag name");
1905 doc->R("events[].tags[].type", MJSON_INT, "history tag midas data type");
1906 doc->R("events[].tags[].n_data?", MJSON_INT, "history tag number of array elements, omitted if 1");
1907 return doc;
1908 }
1909
1910 std::string channel = mjsonrpc_get_param(params, "channel", NULL)->GetString();
1911 double time = mjsonrpc_get_param(params, "time", NULL)->GetDouble();
1912 const MJsonNodeVector* events_array = mjsonrpc_get_param_array(params, "events", NULL);
1913
1914 if (time == 0) {
1915 time = ::time(NULL);
1916 }
1917
1919
1920 MJsonNode* events = MJsonNode::MakeArray();
1921
1922 if (!mh) {
1923 int status = HS_FILE_ERROR;
1924 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "events", events);
1925 }
1926
1927 std::vector<std::string> event_names;
1928
1929 if (events_array && events_array->size() > 0) {
1930 for (unsigned i=0; i<events_array->size(); i++) {
1931 event_names.push_back((*events_array)[i]->GetString());
1932 }
1933 }
1934
1935 if (event_names.size() < 1) {
1936 int status = mh->hs_get_events(time, &event_names);
1937 if (status != HS_SUCCESS) {
1938 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "events", events);
1939 }
1940 }
1941
1942 for (unsigned i=0; i<event_names.size(); i++) {
1943 MJsonNode* o = MJsonNode::MakeObject();
1944 const char* event_name = event_names[i].c_str();
1945 std::vector<TAG> tags;
1946 int status = mh->hs_get_tags(event_name, time, &tags);
1947 //ss_repair_utf8(event_name); redundant!
1948 o->AddToObject("name", MJsonNode::MakeString(event_name));
1949 o->AddToObject("status", MJsonNode::MakeInt(status));
1950 MJsonNode *ta = MJsonNode::MakeArray();
1951 for (unsigned j=0; j<tags.size(); j++) {
1952 MJsonNode* to = MJsonNode::MakeObject();
1953 ss_repair_utf8(tags[j].name);
1954 to->AddToObject("name", MJsonNode::MakeString(tags[j].name));
1955 to->AddToObject("type", MJsonNode::MakeInt(tags[j].type));
1956 if (tags[j].n_data != 1) {
1957 to->AddToObject("n_data", MJsonNode::MakeInt(tags[j].n_data));
1958 }
1959 ta->AddToArray(to);
1960 }
1961 o->AddToObject("tags", ta);
1962 events->AddToArray(o);
1963 }
1964
1965 int status = HS_SUCCESS;
1966 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "channel", MJsonNode::MakeString(mh->name), "events", events);
1967}
virtual int hs_get_tags(const char *event_name, time_t time_from, std::vector< TAG > *ptags)=0
get list of history variables for given event (use event names returned by hs_get_events()) that exis...
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_hs_image_retrieve()

static MJsonNode * js_hs_image_retrieve ( const MJsonNode *  params)
static

Definition at line 2939 of file mjsonrpc.cxx.

2939 {
2940 if (!params) {
2941 MJSO *doc = MJSO::I();
2942 doc->D("Get a list of history image files");
2943 doc->P("image?", MJSON_STRING, "image name as defined under /History/Images/<image>");
2944 doc->P("start_time", MJSON_NUMBER, "start time of the data");
2945 doc->P("end_time", MJSON_NUMBER, "end time of the data");
2946 doc->R("time[]", MJSON_ARRAYBUFFER, "array of time stamps in seconds");
2947 doc->R("filename[]", MJSON_ARRAYBUFFER, "array of file names");
2948 return doc;
2949 }
2950
2951 MJsonNode* error = NULL;
2952
2953 std::string image = mjsonrpc_get_param(params, "image", NULL)->GetString();
2954 double start_time = mjsonrpc_get_param(params, "start_time", &error)->GetDouble(); if (error) return error;
2955 double end_time = mjsonrpc_get_param(params, "end_time", &error)->GetDouble(); if (error) return error;
2956
2957 std::vector<time_t>vtime{};
2958 std::vector<std::string>vfilename{};
2959
2960 int status = hs_image_retrieve(image, start_time, end_time, vtime, vfilename);
2961 int count = 10;
2962 MJsonNode *tj = MJsonNode::MakeArray();
2963 MJsonNode *fj = MJsonNode::MakeArray();
2964
2965 for (int i=0 ; i<(int)vtime.size() ; i++) {
2966 tj->AddToArray(MJsonNode::MakeInt(vtime[i]));
2967 ss_repair_utf8(vfilename[i]);
2968 fj->AddToArray(MJsonNode::MakeString(vfilename[i].c_str()));
2969 }
2970 MJsonNode* data = MJsonNode::MakeObject();
2971 data->AddToObject("count", MJsonNode::MakeInt(count));
2972 data->AddToObject("time", tj);
2973 data->AddToObject("filename", fj);
2974
2975 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "data", data);
2976}
int hs_image_retrieve(std::string image_name, time_t start_time, time_t stop_time, std::vector< time_t > &vtime, std::vector< std::string > &vfilename)
void * data
Definition mana.cxx:268
double count
Definition mdump.cxx:33
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_hs_read()

static MJsonNode * js_hs_read ( const MJsonNode *  params)
static

Definition at line 2098 of file mjsonrpc.cxx.

2099{
2100 if (!params) {
2101 MJSO* doc = MJSO::I();
2102 doc->D("get history data for given history events that existed at give time using hs_read_buffer()");
2103 doc->P("channel?", MJSON_STRING, "midas history channel, default is the default reader channel");
2104 doc->P("start_time", MJSON_NUMBER, "start time of the data");
2105 doc->P("end_time", MJSON_NUMBER, "end time of the data");
2106 doc->P("events[]", MJSON_STRING, "array of history event names");
2107 doc->P("tags[]", MJSON_STRING, "array of history event tag names");
2108 doc->P("index[]", MJSON_STRING, "array of history event tag array indices");
2109 doc->R("status", MJSON_INT, "return status");
2110 doc->R("channel", MJSON_STRING, "logger history channel name");
2111 doc->R("data[]", MJSON_ARRAY, "array of history data");
2112 doc->R("data[].status", MJSON_INT, "status for each event");
2113 doc->R("data[].count", MJSON_INT, "number of data for each event");
2114 doc->R("data[].time[]", MJSON_NUMBER, "time data");
2115 doc->R("data[].value[]", MJSON_NUMBER, "value data");
2116 return doc;
2117 }
2118
2119 MJsonNode* error = NULL;
2120
2121 std::string channel = mjsonrpc_get_param(params, "channel", NULL)->GetString();
2122 double start_time = mjsonrpc_get_param(params, "start_time", &error)->GetDouble(); if (error) return error;
2123 double end_time = mjsonrpc_get_param(params, "end_time", &error)->GetDouble(); if (error) return error;
2124
2125 const MJsonNodeVector* events_array = mjsonrpc_get_param_array(params, "events", NULL);
2126 const MJsonNodeVector* tags_array = mjsonrpc_get_param_array(params, "tags", NULL);
2127 const MJsonNodeVector* index_array = mjsonrpc_get_param_array(params, "index", NULL);
2128
2130
2131 MJsonNode* data = MJsonNode::MakeArray();
2132
2133 if (!mh) {
2134 int status = HS_FILE_ERROR;
2135 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "data", data);
2136 }
2137
2138 unsigned num_var = events_array->size();
2139
2140 if (tags_array->size() != num_var) {
2141 return mjsonrpc_make_error(-32602, "Invalid params", "Arrays events and tags should have the same length");
2142 }
2143
2144 if (index_array->size() != num_var) {
2145 return mjsonrpc_make_error(-32602, "Invalid params", "Arrays events and index should have the same length");
2146 }
2147
2148 std::vector<std::string> event_names(num_var);
2149 std::vector<std::string> tag_names(num_var);
2150 int* var_index = new int[num_var];
2151 JsonHistoryBuffer** jbuf = new JsonHistoryBuffer*[num_var];
2153 int* hs_status = new int[num_var];
2154
2155 for (unsigned i=0; i<num_var; i++) {
2156 //event_name[i] = (*events_array)[i]->GetString().c_str();
2157 //tag_name[i] = (*tags_array)[i]->GetString().c_str();
2158 event_names[i] = (*events_array)[i]->GetString();
2159 tag_names[i] = (*tags_array)[i]->GetString();
2160 var_index[i] = (*index_array)[i]->GetInt();
2161 jbuf[i] = new JsonHistoryBuffer();
2162 buf[i] = jbuf[i];
2163 hs_status[i] = 0;
2164 }
2165
2166 if (/* DISABLES CODE */ (0)) {
2167 printf("time %f %f, num_vars %d:\n", start_time, end_time, num_var);
2168 for (unsigned i=0; i<num_var; i++) {
2169 printf("%d: [%s] [%s] [%d]\n", i, event_names[i].c_str(), tag_names[i].c_str(), var_index[i]);
2170 }
2171 }
2172
2173 const char** event_name = new const char*[num_var];
2174 const char** tag_name = new const char*[num_var];
2175 for (unsigned i=0; i<num_var; i++) {
2176 event_name[i] = event_names[i].c_str();
2177 tag_name[i] = tag_names[i].c_str();
2178 }
2179
2180 int status = mh->hs_read_buffer(start_time, end_time, num_var, event_name, tag_name, var_index, buf, hs_status);
2181
2182 for (unsigned i=0; i<num_var; i++) {
2183 jbuf[i]->Finish();
2184
2185 MJsonNode* obj = MJsonNode::MakeObject();
2186 obj->AddToObject("status", MJsonNode::MakeInt(hs_status[i]));
2187 obj->AddToObject("count", MJsonNode::MakeInt(jbuf[i]->fCount));
2188 obj->AddToObject("time", MJsonNode::MakeJSON(jbuf[i]->fTimeJson.c_str()));
2189 obj->AddToObject("value", MJsonNode::MakeJSON(jbuf[i]->fValueJson.c_str()));
2190 data->AddToArray(obj);
2191
2192 delete jbuf[i];
2193 jbuf[i] = NULL;
2194 buf[i] = NULL;
2195 }
2196
2197 delete[] event_name;
2198 delete[] tag_name;
2199 delete[] var_index;
2200 delete[] buf;
2201 delete[] jbuf;
2202 delete[] hs_status;
2203
2204 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "channel", MJsonNode::MakeString(mh->name), "data", data);
2205}
virtual int hs_read_buffer(time_t start_time, time_t end_time, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], MidasHistoryBufferInterface *buffer[], int status[])=0
returns HS_SUCCESS
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_hs_read_arraybuffer()

static MJsonNode * js_hs_read_arraybuffer ( const MJsonNode *  params)
static

Definition at line 2441 of file mjsonrpc.cxx.

2442{
2443 if (!params) {
2444 MJSO* doc = MJSO::I();
2445 doc->D("get history data for given history events that existed at give time using hs_read_buffer()");
2446 doc->P("channel?", MJSON_STRING, "midas history channel, default is the default reader channel");
2447 doc->P("start_time", MJSON_NUMBER, "start time of the data");
2448 doc->P("end_time", MJSON_NUMBER, "end time of the data");
2449 doc->P("events[]", MJSON_STRING, "array of history event names");
2450 doc->P("tags[]", MJSON_STRING, "array of history event tag names");
2451 doc->P("index[]", MJSON_STRING, "array of history event tag array indices");
2452 doc->R("binary data", MJSON_ARRAYBUFFER, "binary data, see documentation");
2453 return doc;
2454 }
2455
2456 MJsonNode* error = NULL;
2457
2458 std::string channel = mjsonrpc_get_param(params, "channel", NULL)->GetString();
2459 double start_time = mjsonrpc_get_param(params, "start_time", &error)->GetDouble(); if (error) return error;
2460 double end_time = mjsonrpc_get_param(params, "end_time", &error)->GetDouble(); if (error) return error;
2461
2462 const MJsonNodeVector* events_array = mjsonrpc_get_param_array(params, "events", NULL);
2463 const MJsonNodeVector* tags_array = mjsonrpc_get_param_array(params, "tags", NULL);
2464 const MJsonNodeVector* index_array = mjsonrpc_get_param_array(params, "index", NULL);
2465
2467
2468 if (!mh) {
2469 int status = HS_FILE_ERROR;
2470 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
2471 }
2472
2473 size_t num_var = events_array->size();
2474
2475 if (tags_array->size() != num_var) {
2476 return mjsonrpc_make_error(-32602, "Invalid params", "Arrays events and tags should have the same length");
2477 }
2478
2479 if (index_array->size() != num_var) {
2480 return mjsonrpc_make_error(-32602, "Invalid params", "Arrays events and index should have the same length");
2481 }
2482
2483 std::vector<std::string> event_names(num_var);
2484 std::vector<std::string> tag_names(num_var);
2485 int* var_index = new int[num_var];
2486 BinaryHistoryBuffer** jbuf = new BinaryHistoryBuffer*[num_var];
2488 int* hs_status = new int[num_var];
2489
2490 for (size_t i=0; i<num_var; i++) {
2491 //event_name[i] = (*events_array)[i]->GetString().c_str();
2492 //tag_name[i] = (*tags_array)[i]->GetString().c_str();
2493 event_names[i] = (*events_array)[i]->GetString();
2494 tag_names[i] = (*tags_array)[i]->GetString();
2495 var_index[i] = (*index_array)[i]->GetInt();
2496 jbuf[i] = new BinaryHistoryBuffer();
2497 buf[i] = jbuf[i];
2498 hs_status[i] = 0;
2499 }
2500
2501 if (/* DISABLES CODE */ (0)) {
2502 printf("time %f %f, num_vars %d:\n", start_time, end_time, int(num_var));
2503 for (size_t i=0; i<num_var; i++) {
2504 printf("%d: [%s] [%s] [%d]\n", int(i), event_names[i].c_str(), tag_names[i].c_str(), var_index[i]);
2505 }
2506 }
2507
2508 const char** event_name = new const char*[num_var];
2509 const char** tag_name = new const char*[num_var];
2510 for (unsigned i=0; i<num_var; i++) {
2511 event_name[i] = event_names[i].c_str();
2512 tag_name[i] = tag_names[i].c_str();
2513 }
2514
2515 int status = mh->hs_read_buffer(start_time, end_time, num_var, event_name, tag_name, var_index, buf, hs_status);
2516
2517 size_t num_values = 0;
2518
2519 for (unsigned i=0; i<num_var; i++) {
2520 jbuf[i]->Finish();
2521 num_values += jbuf[i]->fValues.size();
2522 }
2523
2524 // NB: beware of 32-bit integer overflow. all values are now 64-bit size_t, overflow should not happen.
2525 size_t p0_size = sizeof(double)*(2+2*num_var+2*num_values);
2526
2527 size_t size_limit = 1000*1024*1024;
2528
2529 if (p0_size > size_limit) {
2530 cm_msg(MERROR, "js_hs_read_binned_arraybuffer", "Refusing to return %zu bytes of history data, limit is %zu bytes\n", p0_size, size_limit);
2531
2532 for (size_t i=0; i<num_var; i++) {
2533 delete jbuf[i];
2534 jbuf[i] = NULL;
2535 buf[i] = NULL;
2536 }
2537
2538 delete[] event_name;
2539 delete[] tag_name;
2540 delete[] var_index;
2541 delete[] buf;
2542 delete[] jbuf;
2543 delete[] hs_status;
2544
2545 return mjsonrpc_make_error(-32603, "Internal error", "Too much history data");
2546 }
2547
2548 double* p0 = (double*)malloc(p0_size);
2549
2550 if (p0 == NULL) {
2551 cm_msg(MERROR, "js_hs_read_binned_arraybuffer", "Cannot allocate return buffer %d bytes\n", int(p0_size));
2552
2553 for (size_t i=0; i<num_var; i++) {
2554 delete jbuf[i];
2555 jbuf[i] = NULL;
2556 buf[i] = NULL;
2557 }
2558
2559 delete[] event_name;
2560 delete[] tag_name;
2561 delete[] var_index;
2562 delete[] buf;
2563 delete[] jbuf;
2564 delete[] hs_status;
2565
2566 return mjsonrpc_make_error(-32603, "Internal error", "Cannot allocate buffer, too much data");
2567 }
2568
2569 double *pptr = p0;
2570
2571 //
2572 // Binary data format:
2573 //
2574 // - hs_read() status
2575 // - num_var
2576 // - hs_status[0..num_var-1]
2577 // - num_values[0..num_var-1]
2578 // - data for var0:
2579 // - t[0][0], v[0][0] ... t[0][num_values[0]-1], v[0][num_values[0]-1]
2580 // - data for var1:
2581 // - t[1][0], v[1][0] ... t[1][num_values[1]-1], v[1][num_values[1]-1]
2582 // ...
2583 // - data for last variable:
2584 // - t[num_var-1][0], v[num_var-1][0] ... t[num_var-1][num_values[num_var-1]-1], v[num_var-1][num_values[num_var-1]-1]
2585 //
2586
2587 *pptr++ = status;
2588 *pptr++ = num_var;
2589
2590 for (size_t i=0; i<num_var; i++) {
2591 *pptr++ = hs_status[i];
2592 }
2593
2594 for (size_t i=0; i<num_var; i++) {
2595 *pptr++ = jbuf[i]->fValues.size();
2596 }
2597
2598 for (size_t i=0; i<num_var; i++) {
2599 size_t nv = jbuf[i]->fValues.size();
2600 for (size_t j=0; j<nv; j++) {
2601 *pptr++ = jbuf[i]->fTimes[j];
2602 *pptr++ = jbuf[i]->fValues[j];
2603 }
2604
2605 delete jbuf[i];
2606 jbuf[i] = NULL;
2607 buf[i] = NULL;
2608 }
2609
2610 //printf("p0_size %d, %d/%d\n", (int)p0_size, (int)(pptr-p0), (int)((pptr-p0)*sizeof(double)));
2611
2612 assert(p0_size == ((pptr-p0)*sizeof(double)));
2613
2614 delete[] event_name;
2615 delete[] tag_name;
2616 delete[] var_index;
2617 delete[] buf;
2618 delete[] jbuf;
2619 delete[] hs_status;
2620
2621 MJsonNode* result = MJsonNode::MakeArrayBuffer((char*)p0, p0_size);
2622
2623 return result;
2624}
std::vector< double > fValues
std::vector< double > fTimes
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_hs_read_binned()

static MJsonNode * js_hs_read_binned ( const MJsonNode *  params)
static

Definition at line 2207 of file mjsonrpc.cxx.

2208{
2209 if (!params) {
2210 MJSO* doc = MJSO::I();
2211 doc->D("get history data for given history events that existed at give time using hs_read_buffer()");
2212 doc->P("channel?", MJSON_STRING, "midas history channel, default is the default reader channel");
2213 doc->P("start_time", MJSON_NUMBER, "start time of the data");
2214 doc->P("end_time", MJSON_NUMBER, "end time of the data");
2215 doc->P("num_bins", MJSON_INT, "number of time bins");
2216 doc->P("events[]", MJSON_STRING, "array of history event names");
2217 doc->P("tags[]", MJSON_STRING, "array of history event tag names");
2218 doc->P("index[]", MJSON_STRING, "array of history event tag array indices");
2219 doc->R("status", MJSON_INT, "return status");
2220 doc->R("channel", MJSON_STRING, "logger history channel name");
2221 doc->R("data[]", MJSON_ARRAY, "array of history data");
2222 doc->R("data[].status", MJSON_INT, "status for each event");
2223 doc->R("data[].num_entries", MJSON_INT, "number of data points for each event");
2224 doc->R("data[].count[]", MJSON_INT, "number of data points for each bin");
2225 doc->R("data[].mean[]", MJSON_NUMBER, "mean for each bin");
2226 doc->R("data[].rms[]", MJSON_NUMBER, "rms for each bin");
2227 doc->R("data[].min[]", MJSON_NUMBER, "minimum value for each bin");
2228 doc->R("data[].max[]", MJSON_NUMBER, "maximum value for each bin");
2229 doc->R("data[].bins_first_time[]", MJSON_NUMBER, "first data point in each bin");
2230 doc->R("data[].bins_first_value[]", MJSON_NUMBER, "first data point in each bin");
2231 doc->R("data[].bins_last_time[]", MJSON_NUMBER, "last data point in each bin");
2232 doc->R("data[].bins_last_value[]", MJSON_NUMBER, "last data point in each bin");
2233 doc->R("data[].last_time", MJSON_NUMBER, "time of last data entry");
2234 doc->R("data[].last_value", MJSON_NUMBER, "value of last data entry");
2235 return doc;
2236 }
2237
2238 MJsonNode* error = NULL;
2239
2240 std::string channel = mjsonrpc_get_param(params, "channel", NULL)->GetString();
2241 double start_time = mjsonrpc_get_param(params, "start_time", &error)->GetDouble(); if (error) return error;
2242 double end_time = mjsonrpc_get_param(params, "end_time", &error)->GetDouble(); if (error) return error;
2243 int num_bins = mjsonrpc_get_param(params, "num_bins", &error)->GetInt(); if (error) return error;
2244
2245 if (num_bins < 1) {
2246 return mjsonrpc_make_error(-32602, "Invalid params", "Value of num_bins should be 1 or more");
2247 }
2248
2249 const MJsonNodeVector* events_array = mjsonrpc_get_param_array(params, "events", NULL);
2250 const MJsonNodeVector* tags_array = mjsonrpc_get_param_array(params, "tags", NULL);
2251 const MJsonNodeVector* index_array = mjsonrpc_get_param_array(params, "index", NULL);
2252
2254
2255 MJsonNode* data = MJsonNode::MakeArray();
2256
2257 if (!mh) {
2258 int status = HS_FILE_ERROR;
2259 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "data", data);
2260 }
2261
2262 unsigned num_var = events_array->size();
2263
2264 if (num_var < 1) {
2265 return mjsonrpc_make_error(-32602, "Invalid params", "Array of events should have 1 or more elements");
2266 }
2267
2268 if (tags_array->size() != num_var) {
2269 return mjsonrpc_make_error(-32602, "Invalid params", "Arrays events and tags should have the same length");
2270 }
2271
2272 if (index_array->size() != num_var) {
2273 return mjsonrpc_make_error(-32602, "Invalid params", "Arrays events and index should have the same length");
2274 }
2275
2276 std::vector<std::string> event_names(num_var);
2277 std::vector<std::string> tag_names(num_var);
2278 //const char** event_name = new const char*[num_var];
2279 //const char** tag_name = new const char*[num_var];
2280 int* var_index = new int[num_var];
2281
2282 int* num_entries = new int[num_var];
2283 time_t* last_time = new time_t[num_var];
2284 double* last_value = new double[num_var];
2285 int* hs_status = new int[num_var];
2286
2287 int** count_bins = new int*[num_var];
2288 double** mean_bins = new double*[num_var];
2289 double** rms_bins = new double*[num_var];
2290 double** min_bins = new double*[num_var];
2291 double** max_bins = new double*[num_var];
2292
2293 time_t** bins_first_time = new time_t*[num_var];
2294 time_t** bins_last_time = new time_t*[num_var];
2295
2296 double** bins_first_value = new double*[num_var];
2297 double** bins_last_value = new double*[num_var];
2298
2299 for (unsigned i=0; i<num_var; i++) {
2300 //event_name[i] = (*events_array)[i]->GetString().c_str();
2301 //tag_name[i] = (*tags_array)[i]->GetString().c_str();
2302 event_names[i] = (*events_array)[i]->GetString();
2303 tag_names[i] = (*tags_array)[i]->GetString();
2304 var_index[i] = (*index_array)[i]->GetInt();
2305 num_entries[i] = 0;
2306 last_time[i] = 0;
2307 last_value[i] = 0;
2308 hs_status[i] = 0;
2309 count_bins[i] = new int[num_bins];
2310 mean_bins[i] = new double[num_bins];
2311 rms_bins[i] = new double[num_bins];
2312 min_bins[i] = new double[num_bins];
2313 max_bins[i] = new double[num_bins];
2314
2315 bins_first_time[i] = new time_t[num_bins];
2316 bins_last_time[i] = new time_t[num_bins];
2317
2318 bins_first_value[i] = new double[num_bins];
2319 bins_last_value[i] = new double[num_bins];
2320 }
2321
2322 if (/* DISABLES CODE */ (0)) {
2323 printf("time %f %f, num_vars %d:\n", start_time, end_time, num_var);
2324 for (unsigned i=0; i<num_var; i++) {
2325 printf("%d: [%s] [%s] [%d]\n", i, event_names[i].c_str(), tag_names[i].c_str(), var_index[i]);
2326 }
2327 }
2328
2329 const char** event_name = new const char*[num_var];
2330 const char** tag_name = new const char*[num_var];
2331 for (unsigned i=0; i<num_var; i++) {
2332 event_name[i] = event_names[i].c_str();
2333 tag_name[i] = tag_names[i].c_str();
2334 }
2335
2336 int status = mh->hs_read_binned(start_time, end_time, num_bins, num_var, event_name, tag_name, var_index, num_entries, count_bins, mean_bins, rms_bins, min_bins, max_bins, bins_first_time, bins_first_value, bins_last_time, bins_last_value, last_time, last_value, hs_status);
2337
2338 for (unsigned i=0; i<num_var; i++) {
2339 MJsonNode* obj = MJsonNode::MakeObject();
2340 obj->AddToObject("status", MJsonNode::MakeInt(hs_status[i]));
2341 obj->AddToObject("num_entries", MJsonNode::MakeInt(num_entries[i]));
2342
2343 MJsonNode* a1 = MJsonNode::MakeArray();
2344 MJsonNode* a2 = MJsonNode::MakeArray();
2345 MJsonNode* a3 = MJsonNode::MakeArray();
2346 MJsonNode* a4 = MJsonNode::MakeArray();
2347 MJsonNode* a5 = MJsonNode::MakeArray();
2348
2349 MJsonNode* b1 = MJsonNode::MakeArray();
2350 MJsonNode* b2 = MJsonNode::MakeArray();
2351 MJsonNode* b3 = MJsonNode::MakeArray();
2352 MJsonNode* b4 = MJsonNode::MakeArray();
2353
2354 for (int j=0; j<num_bins; j++) {
2355 a1->AddToArray(MJsonNode::MakeInt(count_bins[i][j]));
2356 a2->AddToArray(MJsonNode::MakeNumber(mean_bins[i][j]));
2357 a3->AddToArray(MJsonNode::MakeNumber(rms_bins[i][j]));
2358 a4->AddToArray(MJsonNode::MakeNumber(min_bins[i][j]));
2359 a5->AddToArray(MJsonNode::MakeNumber(max_bins[i][j]));
2360
2361 b1->AddToArray(MJsonNode::MakeNumber(bins_first_time[i][j]));
2362 b2->AddToArray(MJsonNode::MakeNumber(bins_first_value[i][j]));
2363 b3->AddToArray(MJsonNode::MakeNumber(bins_last_time[i][j]));
2364 b4->AddToArray(MJsonNode::MakeNumber(bins_last_value[i][j]));
2365 }
2366
2367 obj->AddToObject("count", a1);
2368 obj->AddToObject("mean", a2);
2369 obj->AddToObject("rms", a3);
2370 obj->AddToObject("min", a4);
2371 obj->AddToObject("max", a5);
2372 obj->AddToObject("bins_first_time", b1);
2373 obj->AddToObject("bins_first_value", b2);
2374 obj->AddToObject("bins_last_time", b3);
2375 obj->AddToObject("bins_last_value", b4);
2376 obj->AddToObject("last_time", MJsonNode::MakeNumber(last_time[i]));
2377 obj->AddToObject("last_value", MJsonNode::MakeNumber(last_value[i]));
2378 data->AddToArray(obj);
2379
2380 delete count_bins[i];
2381 delete mean_bins[i];
2382 delete rms_bins[i];
2383 delete min_bins[i];
2384 delete max_bins[i];
2385
2386 delete bins_first_time[i];
2387 delete bins_first_value[i];
2388 delete bins_last_time[i];
2389 delete bins_last_value[i];
2390 }
2391
2392 delete[] count_bins;
2393 delete[] mean_bins;
2394 delete[] rms_bins;
2395 delete[] min_bins;
2396 delete[] max_bins;
2397
2398 delete[] bins_first_time;
2399 delete[] bins_first_value;
2400 delete[] bins_last_time;
2401 delete[] bins_last_value;
2402
2403 delete[] event_name;
2404 delete[] tag_name;
2405 delete[] var_index;
2406
2407 delete[] num_entries;
2408 delete[] last_time;
2409 delete[] last_value;
2410 delete[] hs_status;
2411
2412 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "channel", MJsonNode::MakeString(mh->name), "data", data);
2413}
virtual int hs_read_binned(time_t start_time, time_t end_time, int num_bins, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], int num_entries[], int *count_bins[], double *mean_bins[], double *rms_bins[], double *min_bins[], double *max_bins[], time_t *bins_first_time[], double *bins_first_value[], time_t *bins_last_time[], double *bins_last_value[], time_t last_time[], double last_value[], int status[])=0
returns HS_SUCCESS
DWORD last_time
Definition mana.cxx:3070
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_hs_read_binned_arraybuffer()

static MJsonNode * js_hs_read_binned_arraybuffer ( const MJsonNode *  params)
static

Definition at line 2626 of file mjsonrpc.cxx.

2627{
2628 if (!params) {
2629 MJSO* doc = MJSO::I();
2630 doc->D("get history data for given history events that existed at give time using hs_read_buffer()");
2631 doc->P("channel?", MJSON_STRING, "midas history channel, default is the default reader channel");
2632 doc->P("start_time", MJSON_NUMBER, "start time of the data");
2633 doc->P("end_time", MJSON_NUMBER, "end time of the data");
2634 doc->P("num_bins", MJSON_INT, "number of time bins");
2635 doc->P("events[]", MJSON_STRING, "array of history event names");
2636 doc->P("tags[]", MJSON_STRING, "array of history event tag names");
2637 doc->P("index[]", MJSON_STRING, "array of history event tag array indices");
2638 doc->R("binary data", MJSON_ARRAYBUFFER, "binary data, see documentation");
2639 return doc;
2640 }
2641
2642 MJsonNode* error = NULL;
2643
2644 std::string channel = mjsonrpc_get_param(params, "channel", NULL)->GetString();
2645 double start_time = mjsonrpc_get_param(params, "start_time", &error)->GetDouble(); if (error) return error;
2646 double end_time = mjsonrpc_get_param(params, "end_time", &error)->GetDouble(); if (error) return error;
2647 int inum_bins = mjsonrpc_get_param(params, "num_bins", &error)->GetInt(); if (error) return error;
2648
2649 if (inum_bins < 1) {
2650 return mjsonrpc_make_error(-32602, "Invalid params", "Value of num_bins should be 1 or more");
2651 }
2652
2653 size_t num_bins = inum_bins;
2654
2655 const MJsonNodeVector* events_array = mjsonrpc_get_param_array(params, "events", NULL);
2656 const MJsonNodeVector* tags_array = mjsonrpc_get_param_array(params, "tags", NULL);
2657 const MJsonNodeVector* index_array = mjsonrpc_get_param_array(params, "index", NULL);
2658
2660
2661 if (!mh) {
2662 int status = HS_FILE_ERROR;
2663 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
2664 }
2665
2666 size_t num_var = events_array->size();
2667
2668 if (num_var < 1) {
2669 return mjsonrpc_make_error(-32602, "Invalid params", "Array of events should have 1 or more elements");
2670 }
2671
2672 if (tags_array->size() != num_var) {
2673 return mjsonrpc_make_error(-32602, "Invalid params", "Arrays events and tags should have the same length");
2674 }
2675
2676 if (index_array->size() != num_var) {
2677 return mjsonrpc_make_error(-32602, "Invalid params", "Arrays events and index should have the same length");
2678 }
2679
2680 std::vector<std::string> event_names(num_var);
2681 std::vector<std::string> tag_names(num_var);
2682 //const char** event_name = new const char*[num_var];
2683 //const char** tag_name = new const char*[num_var];
2684 int* var_index = new int[num_var];
2685
2686 int* num_entries = new int[num_var];
2687 time_t* last_time = new time_t[num_var];
2688 double* last_value = new double[num_var];
2689 int* hs_status = new int[num_var];
2690
2691 int** count_bins = new int*[num_var];
2692 double** mean_bins = new double*[num_var];
2693 double** rms_bins = new double*[num_var];
2694 double** min_bins = new double*[num_var];
2695 double** max_bins = new double*[num_var];
2696
2697 time_t** bins_first_time = new time_t*[num_var];
2698 time_t** bins_last_time = new time_t*[num_var];
2699
2700 double** bins_first_value = new double*[num_var];
2701 double** bins_last_value = new double*[num_var];
2702
2703 for (unsigned i=0; i<num_var; i++) {
2704 //event_name[i] = (*events_array)[i]->GetString().c_str();
2705 //tag_name[i] = (*tags_array)[i]->GetString().c_str();
2706 event_names[i] = (*events_array)[i]->GetString();
2707 tag_names[i] = (*tags_array)[i]->GetString();
2708 var_index[i] = (*index_array)[i]->GetInt();
2709 num_entries[i] = 0;
2710 last_time[i] = 0;
2711 last_value[i] = 0;
2712 hs_status[i] = 0;
2713 count_bins[i] = new int[num_bins];
2714 mean_bins[i] = new double[num_bins];
2715 rms_bins[i] = new double[num_bins];
2716 min_bins[i] = new double[num_bins];
2717 max_bins[i] = new double[num_bins];
2718 bins_first_time[i] = new time_t[num_bins];
2719 bins_last_time[i] = new time_t[num_bins];
2720 bins_first_value[i] = new double[num_bins];
2721 bins_last_value[i] = new double[num_bins];
2722 }
2723
2724 if (/* DISABLES CODE */ (0)) {
2725 printf("time %f %f, num_vars %d:\n", start_time, end_time, int(num_var));
2726 for (size_t i=0; i<num_var; i++) {
2727 printf("%d: [%s] [%s] [%d]\n", int(i), event_names[i].c_str(), tag_names[i].c_str(), var_index[i]);
2728 }
2729 }
2730
2731 const char** event_name = new const char*[num_var];
2732 const char** tag_name = new const char*[num_var];
2733 for (size_t i=0; i<num_var; i++) {
2734 event_name[i] = event_names[i].c_str();
2735 tag_name[i] = tag_names[i].c_str();
2736 }
2737
2738 int status = mh->hs_read_binned(start_time, end_time, num_bins, num_var, event_name, tag_name, var_index, num_entries, count_bins, mean_bins, rms_bins, min_bins, max_bins, bins_first_time, bins_first_value, bins_last_time, bins_last_value, last_time, last_value, hs_status);
2739
2740 // NB: beware of 32-bit integer overflow: all variables are now 64-bit size_t, overflow should not happen
2741 size_t p0_size = sizeof(double)*(5+4*num_var+9*num_var*num_bins);
2742
2743 size_t size_limit = 100*1024*1024;
2744
2745 if (p0_size > size_limit) {
2746 cm_msg(MERROR, "js_hs_read_binned_arraybuffer", "Refusing to return %d bytes. limit is %d bytes\n", int(p0_size), int(size_limit));
2747
2748 for (size_t i=0; i<num_var; i++) {
2749 delete count_bins[i];
2750 delete mean_bins[i];
2751 delete rms_bins[i];
2752 delete min_bins[i];
2753 delete max_bins[i];
2754 delete bins_first_time[i];
2755 delete bins_first_value[i];
2756 delete bins_last_time[i];
2757 delete bins_last_value[i];
2758 }
2759
2760 delete[] count_bins;
2761 delete[] mean_bins;
2762 delete[] rms_bins;
2763 delete[] min_bins;
2764 delete[] max_bins;
2765
2766 delete[] bins_first_time;
2767 delete[] bins_first_value;
2768 delete[] bins_last_time;
2769 delete[] bins_last_value;
2770
2771 delete[] event_name;
2772 delete[] tag_name;
2773 delete[] var_index;
2774
2775 delete[] num_entries;
2776 delete[] last_time;
2777 delete[] last_value;
2778 delete[] hs_status;
2779
2780 return mjsonrpc_make_error(-32603, "Internal error", "Refuse to return too much data");
2781 }
2782
2783 double* p0 = (double*)malloc(p0_size);
2784
2785 if (p0 == NULL) {
2786 cm_msg(MERROR, "js_hs_read_binned_arraybuffer", "Cannot allocate return buffer %d bytes\n", int(p0_size));
2787
2788 for (size_t i=0; i<num_var; i++) {
2789 delete count_bins[i];
2790 delete mean_bins[i];
2791 delete rms_bins[i];
2792 delete min_bins[i];
2793 delete max_bins[i];
2794 delete bins_first_time[i];
2795 delete bins_first_value[i];
2796 delete bins_last_time[i];
2797 delete bins_last_value[i];
2798 }
2799
2800 delete[] count_bins;
2801 delete[] mean_bins;
2802 delete[] rms_bins;
2803 delete[] min_bins;
2804 delete[] max_bins;
2805
2806 delete[] bins_first_time;
2807 delete[] bins_first_value;
2808 delete[] bins_last_time;
2809 delete[] bins_last_value;
2810
2811 delete[] event_name;
2812 delete[] tag_name;
2813 delete[] var_index;
2814
2815 delete[] num_entries;
2816 delete[] last_time;
2817 delete[] last_value;
2818 delete[] hs_status;
2819
2820 return mjsonrpc_make_error(-32603, "Internal error", "Cannot allocate buffer, too much data");
2821 }
2822
2823 double *pptr = p0;
2824
2825 //
2826 // Binary data format:
2827 //
2828 // * header
2829 // -- hs_read() status
2830 // -- start_time
2831 // -- end_time
2832 // -- num_bins
2833 // -- num_var
2834 // * per variable info
2835 // -- hs_status[0..num_var-1]
2836 // -- num_entries[0..num_var-1]
2837 // -- last_time[0..num_var-1]
2838 // -- last_value[0..num_var-1]
2839 // * data for var0 bin0
2840 // -- count - number of entries in this bin
2841 // -- mean - mean value
2842 // -- rms - rms value
2843 // -- min - minimum value
2844 // -- max - maximum value
2845 // -- bins_first_time - first data point in each bin
2846 // -- bins_first_value
2847 // -- bins_last_time - last data point in each bin
2848 // -- bins_last_value
2849 // - data for var0 bin1
2850 // - ... bin[num_bins-1]
2851 // - data for var1 bin0
2852 // - ...
2853 // - data for var[num_vars-1] bin[0]
2854 // - ...
2855 // - data for var[num_vars-1] bin[num_bins-1]
2856 //
2857
2858 *pptr++ = status;
2859 *pptr++ = start_time;
2860 *pptr++ = end_time;
2861 *pptr++ = num_bins;
2862 *pptr++ = num_var;
2863
2864 for (unsigned i=0; i<num_var; i++) {
2865 *pptr++ = hs_status[i];
2866 }
2867
2868 for (unsigned i=0; i<num_var; i++) {
2869 *pptr++ = num_entries[i];
2870 }
2871
2872 for (unsigned i=0; i<num_var; i++) {
2873 *pptr++ = last_time[i];
2874 }
2875
2876 for (unsigned i=0; i<num_var; i++) {
2877 *pptr++ = last_value[i];
2878 }
2879
2880 for (size_t i=0; i<num_var; i++) {
2881 for (size_t j=0; j<num_bins; j++) {
2882 *pptr++ = count_bins[i][j];
2883 *pptr++ = mean_bins[i][j];
2884 *pptr++ = rms_bins[i][j];
2885 *pptr++ = min_bins[i][j];
2886 *pptr++ = max_bins[i][j];
2887 *pptr++ = bins_first_time[i][j];
2888 *pptr++ = bins_first_value[i][j];
2889 *pptr++ = bins_last_time[i][j];
2890 *pptr++ = bins_last_value[i][j];
2891 }
2892
2893 delete count_bins[i];
2894 delete mean_bins[i];
2895 delete rms_bins[i];
2896 delete min_bins[i];
2897 delete max_bins[i];
2898 delete bins_first_time[i];
2899 delete bins_first_value[i];
2900 delete bins_last_time[i];
2901 delete bins_last_value[i];
2902 }
2903
2904 //printf("p0_size %d, %d/%d\n", (int)p0_size, (int)(pptr-p0), (int)((pptr-p0)*sizeof(double)));
2905
2906 assert(p0_size == ((pptr-p0)*sizeof(double)));
2907
2908 delete[] count_bins;
2909 delete[] mean_bins;
2910 delete[] rms_bins;
2911 delete[] min_bins;
2912 delete[] max_bins;
2913
2914 delete[] bins_first_time;
2915 delete[] bins_first_value;
2916 delete[] bins_last_time;
2917 delete[] bins_last_value;
2918
2919 delete[] event_name;
2920 delete[] tag_name;
2921 delete[] var_index;
2922
2923 delete[] num_entries;
2924 delete[] last_time;
2925 delete[] last_value;
2926 delete[] hs_status;
2927
2928 MJsonNode* result = MJsonNode::MakeArrayBuffer((char*)p0, p0_size);
2929
2930 return result;
2931}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_hs_reopen()

static MJsonNode * js_hs_reopen ( const MJsonNode *  params)
static

Definition at line 1866 of file mjsonrpc.cxx.

1867{
1868 if (!params) {
1869 MJSO* doc = MJSO::I();
1870 doc->D("reopen the history channel to make sure we see the latest list of events using hs_clear_cache()");
1871 doc->P("channel?", MJSON_STRING, "midas history channel, default is the default reader channel");
1872 doc->R("status", MJSON_INT, "return status of hs_get_events()");
1873 doc->R("channel", MJSON_STRING, "logger history channel name");
1874 return doc;
1875 }
1876
1877 std::string channel = mjsonrpc_get_param(params, "channel", NULL)->GetString();
1878
1880
1881 if (!mh) {
1882 int status = HS_FILE_ERROR;
1883 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
1884 }
1885
1886 int status = mh->hs_clear_cache();
1887
1888 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "channel", MJsonNode::MakeString(mh->name));
1889}
virtual int hs_clear_cache()=0
clear internal cache, returns HS_SUCCESS
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_make_subdir()

static MJsonNode * js_make_subdir ( const MJsonNode *  params)
static

Definition at line 4077 of file mjsonrpc.cxx.

4078{
4079 if (!params) {
4080 MJSO* doc = MJSO::I();
4081 doc->D("js_make_subdir");
4082 doc->P("subdir", MJSON_STRING, "Create folder experiment_directory/userfiles/subdir");
4083 doc->R("status", MJSON_INT, "return status of midas library calls");
4084 doc->R("path", MJSON_STRING, "Search path");
4085 return doc;
4086 }
4087
4088 MJsonNode* error = NULL;
4089
4090 std::string subdir = mjsonrpc_get_param(params, "subdir", &error)->GetString(); if (error) return error;
4091
4092 /*---- Not allowed to contain ../ - safety feature ----*/
4093 if (subdir.find("..") != std::string::npos) {
4094 return mjsonrpc_make_result("status", MJsonNode::MakeInt(DB_INVALID_PARAM), "error", MJsonNode::MakeString("The subdir is not permitted"));
4095 }
4096
4097 int status;
4098 HNDLE hDB;
4099
4101
4102 if (status != DB_SUCCESS) {
4103 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
4104 }
4105
4106 std::string path = cm_expand_env(cm_get_path().c_str());
4107 if (path[path.length()-1] != DIR_SEPARATOR) {
4108 path += DIR_SEPARATOR_STR;
4109 }
4110 path += "userfiles";
4111
4112 // Check if the userfiles folder exists
4113 if (access(path.c_str(), F_OK) != 0) {
4114 // Create the path if it doesn't exist
4115 if (mkdir(path.c_str(), 0777) != 0) {
4116 return mjsonrpc_make_result("status", MJsonNode::MakeInt(DB_INVALID_PARAM), "error", MJsonNode::MakeString("Failed to create the userfiles folder"));
4117 }
4118 }
4119
4120 // Add subdir to userfiles
4121 if (subdir.length() > 0) {
4122 if (subdir[0] != DIR_SEPARATOR) {
4123 path += DIR_SEPARATOR_STR;
4124 }
4125 path += subdir;
4126 }
4127 // Check if the subdir exisits in userfiles, otherwise create it
4128 if (access(path.c_str(), F_OK) != 0) {
4129 // Create the path if it doesn't exist
4130 if (mkdir(path.c_str(), 0777) != 0) {
4131 return mjsonrpc_make_result("status", MJsonNode::MakeInt(DB_INVALID_PARAM), "error", MJsonNode::MakeString("Failed to create subdirectory"));
4132 }
4133 }
4134
4135
4136 MJsonNode* r = MJsonNode::MakeObject();
4137 r->AddToObject("status", MJsonNode::MakeInt(SUCCESS));
4138 ss_repair_utf8(path);
4139 r->AddToObject("path", MJsonNode::MakeString(path.c_str()));
4140 return mjsonrpc_make_result(r);
4141}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_read_binary_file()

static MJsonNode * js_read_binary_file ( const MJsonNode *  params)
static

Definition at line 4429 of file mjsonrpc.cxx.

4429 {
4430 if (!params) {
4431 MJSO* doc = MJSO::I();
4432 doc->D("js_read_binary_file");
4433 doc->P("filename", MJSON_STRING, "File name, read from experiment_directory/userfiles/filename");
4434 doc->R("binary data", MJSON_ARRAYBUFFER, "Binary file content");
4435 doc->R("status", MJSON_INT, "Return status of midas library calls");
4436 doc->R("error", MJSON_STRING, "Error text");
4437 return doc;
4438 }
4439
4440 MJsonNode* error = NULL;
4441 std::string filename = mjsonrpc_get_param(params, "filename", &error)->GetString();
4442 if (error) return error;
4443
4444 /*---- filename should not contain the following - safety feature */
4445 if (filename.find("..") != std::string::npos ||
4446 filename.find("*") != std::string::npos) {
4447 return mjsonrpc_make_result("status", MJsonNode::MakeInt(DB_INVALID_PARAM), "error", MJsonNode::MakeString("The filename is not permitted"));
4448 }
4449
4450 int status;
4451 HNDLE hDB;
4452
4454
4455 if (status != DB_SUCCESS) {
4456 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "error", MJsonNode::MakeString("cm_get_experiment_database() error"));
4457 }
4458
4459 std::string path = cm_expand_env(cm_get_path().c_str());
4460 if (path[path.length()-1] != DIR_SEPARATOR) {
4461 path += DIR_SEPARATOR_STR;
4462 }
4463 path += "userfiles";
4464
4465 // Check if the userfiles folder exists
4466 if (access(path.c_str(), F_OK) != 0) {
4467 // Create the path if it doesn't exist
4468 if (mkdir(path.c_str(), 0777) != 0) {
4469 return mjsonrpc_make_result("status", MJsonNode::MakeInt(DB_INVALID_PARAM), "error", MJsonNode::MakeString("Failed to create the userfiles folder"));
4470 }
4471 }
4472
4473 path += DIR_SEPARATOR_STR;
4474 path += filename;
4475
4476 FILE* fp = fopen(path.c_str(), "rb");
4477 if (!fp) {
4479 char errstr[256];
4480 sprintf(errstr, "fopen() errno %d (%s)", errno, strerror(errno));
4481 ss_repair_utf8(errstr);
4482 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status), "error", MJsonNode::MakeString(errstr));
4483 }
4484
4485 fseek(fp, 0, SEEK_END);
4486 size_t file_size = ftell(fp);
4487 rewind(fp);
4488
4489 char* buffer = new char[file_size];
4490 fread(buffer, file_size, 1, fp);
4491 // maybe not needed here
4492 //buffer[file_size] = '\0';
4493 fclose(fp);
4494
4496 std::string errstr = "no error";
4497
4498 MJsonNode* result = MJsonNode::MakeArrayBuffer(buffer, file_size);
4499 return result;
4500}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ js_ss_millitime()

static MJsonNode * js_ss_millitime ( const MJsonNode *  params)
static

Definition at line 3834 of file mjsonrpc.cxx.

3835{
3836 if (!params) {
3837 MJSO *doc = MJSO::I();
3838 doc->D("get current MIDAS time using ss_millitime()");
3839 doc->P(NULL, 0, "there are no input parameters");
3840 doc->R(NULL, MJSON_INT, "current value of ss_millitime()");
3841 return doc;
3842 }
3843
3844 return mjsonrpc_make_result(MJsonNode::MakeNumber(ss_millitime()));
3845}
DWORD ss_millitime()
Definition system.cxx:3465
Here is the call graph for this function:
Here is the caller graph for this function:

◆ MatchEvent()

static void MatchEvent ( const std::string  buffer_name,
const EVENT_HEADER pevent 
)
static

Definition at line 3621 of file mjsonrpc.cxx.

3622{
3623 std::lock_guard<std::mutex> guard(gEventStashMutex);
3624 for (EventStashEntry* s : gEventStash) {
3625 if (s->buffer_name != buffer_name)
3626 continue;
3627 if (bm_match_event(s->event_id, s->trigger_mask, pevent)) {
3628 s->ReplaceEvent(pevent);
3629 //s->Print(); printf(", matched\n");
3630 }
3631 }
3632}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mjsonrpc_get_param_array()

const MJsonNodeVector * mjsonrpc_get_param_array ( const MJsonNode *  params,
const char *  name,
MJsonNode **  error 
)

Definition at line 201 of file mjsonrpc.cxx.

202{
203 // NULL params is a request for documentation, return NULL
204 if (!params) {
205 if (error)
206 *error = MJsonNode::MakeObject();
207 return NULL;
208 }
209
210 const MJsonNode* node = mjsonrpc_get_param(params, name, error);
211
212 // handle error return from mjsonrpc_get_param()
213 if (error && *error) {
214 return NULL;
215 }
216
217 const MJsonNodeVector* v = node->GetArray();
218
219 if (!v) {
220 if (error)
221 *error = mjsonrpc_make_error(-32602, "Invalid params", (std::string("parameter must be an array: ") + name).c_str());
222 return NULL;
223 }
224
225 if (error)
226 *error = NULL;
227 return v;
228}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mjsonrpc_handle_request()

static MJsonNode * mjsonrpc_handle_request ( const MJsonNode *  request)
static

Definition at line 5110 of file mjsonrpc.cxx.

5111{
5112 // find required request elements
5113 const MJsonNode* version = request->FindObjectNode("jsonrpc");
5114 const MJsonNode* method = request->FindObjectNode("method");
5115 const MJsonNode* params = request->FindObjectNode("params");
5116 const MJsonNode* id = request->FindObjectNode("id");
5117
5118 std::string bad = "";
5119
5120 if (!version)
5121 add(&bad, "jsonrpc version is missing");
5122 if (!method)
5123 add(&bad, "method is missing");
5124 if (!params)
5125 add(&bad, "params is missing");
5126 if (!id)
5127 add(&bad, "id is missing");
5128
5129 if (version && (version->GetType() != MJSON_STRING))
5130 add(&bad, "jsonrpc version is not a string");
5131 if (version && (version->GetString() != "2.0"))
5132 add(&bad, "jsonrpc version is not 2.0");
5133
5134 if (method && (method->GetType() != MJSON_STRING))
5135 add(&bad, "method is not a string");
5136
5137 if (!method || bad.length() > 0) {
5138 MJsonNode* response = mjsonrpc_make_error(-32600, "Invalid request", bad.c_str());
5139 response->AddToObject("jsonrpc", MJsonNode::MakeString("2.0"));
5140 if (id) {
5141 response->AddToObject("id", id->Copy());
5142 } else {
5143 response->AddToObject("id", MJsonNode::MakeNull());
5144 }
5145
5146 if (mjsonrpc_debug) {
5147 printf("mjsonrpc: invalid request: reply:\n");
5148 printf("%s\n", response->Stringify().c_str());
5149 printf("\n");
5150 }
5151
5152 return response;
5153 }
5154
5155 double start_time = 0;
5156
5157 if (mjsonrpc_time) {
5158 start_time = GetTimeSec();
5159 }
5160
5161 const std::string ms = method->GetString();
5162 const char* m = ms.c_str();
5163
5164 MJsonNode* result = NULL;
5165
5166 // special built-in methods
5167
5168 if (strcmp(m, "echo") == 0) {
5169 result = mjsonrpc_make_result(request->Copy());
5170 } else if (strcmp(m, "error") == 0) {
5171 result = mjsonrpc_make_error(1, "test error", "test error");
5172 } else if (strcmp(m, "invalid_json") == 0) {
5173 if (mjsonrpc_debug) {
5174 printf("mjsonrpc: reply with invalid json\n");
5175 }
5176 return MJsonNode::MakeJSON("this is invalid json data");
5177 } else if (strcmp(m, "test_nan_inf") == 0) {
5178 double one = 1;
5179 double zero = 0;
5180 double nan = zero/zero;
5181 double plusinf = one/zero;
5182 double minusinf = -one/zero;
5183 MJsonNode* n = MJsonNode::MakeArray();
5184 n->AddToArray(MJsonNode::MakeNumber(nan));
5185 n->AddToArray(MJsonNode::MakeNumber(plusinf));
5186 n->AddToArray(MJsonNode::MakeNumber(minusinf));
5187 result = mjsonrpc_make_result("test_nan_plusinf_minusinf", n);
5188 } else if (strcmp(m, "test_arraybuffer") == 0) {
5189 if (mjsonrpc_debug) {
5190 printf("mjsonrpc: reply with test arraybuffer data\n");
5191 }
5192 size_t size = 32;
5193 char* ptr = (char*)malloc(size);
5194 assert(ptr != NULL);
5195 for (size_t i=0; i<size; i++) {
5196 ptr[i] = 'A' + i;
5197 }
5198 *((short*)(ptr+4*2*1)) = 111; // int16[4]
5199 *((int*)(ptr+4*2*2)) = 1234; // int32[4]
5200 *((double*)(ptr+4*2*3)) = 3.14; // float64[3]
5201 return MJsonNode::MakeArrayBuffer(ptr, size);
5202 } else {
5204 if (s != gMethodsTable.end()) {
5205 bool lock = s->second.fNeedsLocking;
5206 if (lock && gMutex)
5207 gMutex->lock();
5208 result = s->second.fHandler(params);
5209 if (lock && gMutex)
5210 gMutex->unlock();
5211 } else {
5212 result = mjsonrpc_make_error(-32601, "Method not found", (std::string("unknown method: ") + ms).c_str());
5213 }
5214 }
5215
5216 if (mjsonrpc_debug) {
5217 printf("mjsonrpc: handler reply:\n");
5218 result->Dump();
5219 printf("\n");
5220 }
5221
5222 double end_time = 0;
5223 double elapsed_time = 0;
5224 if (mjsonrpc_time) {
5225 end_time = GetTimeSec();
5226 elapsed_time = end_time - start_time;
5227 if (mjsonrpc_time > 1) {
5228 printf("request took %.3f seconds, method [%s]\n", elapsed_time, m);
5229 }
5230 }
5231
5232 if (result->GetType() == MJSON_ARRAYBUFFER) {
5233 return result;
5234 }
5235
5236 const MJsonNode *nerror = result->FindObjectNode("error");
5237 const MJsonNode *nresult = result->FindObjectNode("result");
5238
5239 if (nerror) {
5240 result->DeleteObjectNode("result");
5241 } else if (nresult) {
5242 result->DeleteObjectNode("error");
5243 } else {
5244 delete result;
5245 result = mjsonrpc_make_error(-32603, "Internal error", "bad dispatcher reply: no result and no error");
5246 }
5247
5248 result->AddToObject("jsonrpc", MJsonNode::MakeString("2.0"));
5249
5250 if (id) {
5251 result->AddToObject("id", id->Copy());
5252 } else {
5253 result->AddToObject("id", MJsonNode::MakeNull());
5254 }
5255
5256 if (mjsonrpc_time) {
5257 result->AddToObject("elapsed_time", MJsonNode::MakeNumber(elapsed_time));
5258 }
5259
5260 assert(result != NULL);
5261
5262 return result;
5263}
char response[10000]
Definition melog.cxx:90
char request[600000]
Definition melog.cxx:90
MethodsTable::iterator MethodsTableIterator
static double GetTimeSec()
Definition mjsonrpc.cxx:116
static MethodsTable gMethodsTable
INT add
Definition odbhist.cxx:40
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mjsonrpc_make_result()

MJsonNode * mjsonrpc_make_result ( const char *  name,
MJsonNode *  value,
const char *  name2,
MJsonNode *  value2,
const char *  name3,
MJsonNode *  value3,
const char *  name4,
MJsonNode *  value4 
)

Definition at line 158 of file mjsonrpc.cxx.

159{
160 MJsonNode* node = MJsonNode::MakeObject();
161
162 if (name)
163 node->AddToObject(name, value);
164 if (name2)
165 node->AddToObject(name2, value2);
166 if (name3)
167 node->AddToObject(name3, value3);
168 if (name4)
169 node->AddToObject(name4, value4);
170
171 MJsonNode* result = MJsonNode::MakeObject();
172 result->AddToObject("result", node);
173 return result;
174}

◆ mjsonrpc_make_schema()

static MJsonNode * mjsonrpc_make_schema ( MethodsTable h)
static

Definition at line 4751 of file mjsonrpc.cxx.

4752{
4753 MJsonNode* s = MJsonNode::MakeObject();
4754
4755 s->AddToObject("$schema", MJsonNode::MakeString("http://json-schema.org/schema#"));
4756 s->AddToObject("id", MJsonNode::MakeString("MIDAS JSON-RPC autogenerated schema"));
4757 s->AddToObject("title", MJsonNode::MakeString("MIDAS JSON-RPC schema"));
4758 s->AddToObject("description", MJsonNode::MakeString("Autogenerated schema for all MIDAS JSON-RPC methods"));
4759 s->AddToObject("type", MJsonNode::MakeString("object"));
4760
4761 MJsonNode* m = MJsonNode::MakeObject();
4762
4763 for (MethodsTableIterator iterator = h->begin(); iterator != h->end(); iterator++) {
4764 // iterator->first = key
4765 // iterator->second = value
4766 //printf("build schema for method \"%s\"!\n", iterator->first.c_str());
4767 MJsonNode* doc = iterator->second.fHandler(NULL);
4768 if (doc == NULL)
4769 doc = MJsonNode::MakeObject();
4770 m->AddToObject(iterator->first.c_str(), doc);
4771 }
4772
4773 s->AddToObject("properties", m);
4774 s->AddToObject("required", MJsonNode::MakeArray());
4775
4776 return s;
4777}
Here is the caller graph for this function:

◆ mjsonrpc_schema_to_html_anything()

std::string mjsonrpc_schema_to_html_anything ( const MJsonNode *  schema,
int  nest_level,
NestedOutput o 
)
static

Definition at line 5050 of file mjsonrpc.cxx.

5051{
5052 std::string type;
5053 std::string description;
5054 //bool optional = false;
5055
5056 const MJsonNode* t = schema->FindObjectNode("type");
5057 if (t)
5058 type = t->GetString();
5059 else
5060 type = "any";
5061
5062 const MJsonNode* d = schema->FindObjectNode("description");
5063 if (d)
5064 description = d->GetString();
5065
5066 //const MJsonNode* o = schema->FindObjectNode("optional");
5067 //if (o)
5068 // optional = o->GetBool();
5069
5070 if (type == "object") {
5071 return mjsonrpc_schema_to_html_object(schema, nest_level, o);
5072 } else if (type == "array") {
5073 return mjsonrpc_schema_to_html_array(schema, nest_level, o);
5074 } else {
5075 //if (optional)
5076 // output(nest_level, false, "?");
5077 //else
5078 // output(nest_level, false, "!");
5079 o->Output(nest_level, false, type);
5080 o->Output(nest_level+1, true, description);
5081 if (description.length() > 1) {
5082 return (type + "</td><td>" + description);
5083 } else {
5084 return (type);
5085 }
5086 }
5087}
void Output(int nest, bool span, std::string text)
char description[1000]
Definition mana.cxx:267
static std::string mjsonrpc_schema_to_html_array(const MJsonNode *schema, int nest_level, NestedOutput *o)
static std::string mjsonrpc_schema_to_html_object(const MJsonNode *schema, int nest_level, NestedOutput *o)
double d
Definition system.cxx:1313
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mjsonrpc_schema_to_html_array()

static std::string mjsonrpc_schema_to_html_array ( const MJsonNode *  schema,
int  nest_level,
NestedOutput o 
)
static

Definition at line 4994 of file mjsonrpc.cxx.

4995{
4996 const MJsonNode* d = schema->FindObjectNode("description");
4997 std::string description;
4998 if (d)
4999 description = d->GetString();
5000
5001 std::string xshort = "array";
5002 if (description.length() > 1)
5003 xshort += "</td><td>" + description;
5004
5005 const MJsonNode* items = schema->FindObjectNode("items");
5006
5007 if (!items) {
5008 o->Output(nest_level, false, "array");
5009 o->Output(nest_level+1, true, description);
5010 return xshort;
5011 }
5012
5013 const MJsonNodeVector *nodes = items->GetArray();
5014
5015 if (!nodes) {
5016 o->Output(nest_level, false, "array");
5017 o->Output(nest_level+1, true, description);
5018 return xshort;
5019 }
5020
5021 std::string nest = indent(nest_level * 4);
5022
5023 std::string s;
5024
5025 //s += "array</td><td>";
5026
5027 s += nest + "<table border=1>\n";
5028
5029 if (description.length() > 1) {
5030 s += nest + "<tr>\n";
5031 s += nest + " <td>" + description + "</td>\n";
5032 s += nest + "</tr>\n";
5033 }
5034
5035 o->Output(nest_level, true, description);
5036
5037 for (unsigned i=0; i<nodes->size(); i++) {
5038 o->Output(nest_level, false, "array of");
5039
5040 s += nest + "<tr>\n";
5041 s += nest + " <td> array of " + mjsonrpc_schema_to_html_anything((*nodes)[i], nest_level + 1, o) + "</td>\n";
5042 s += nest + "</tr>\n";
5043 }
5044
5045 s += nest + "</table>\n";
5046
5047 return s;
5048}
static std::string mjsonrpc_schema_to_html_anything(const MJsonNode *schema, int nest_level, NestedOutput *o)
static std::string indent(int x, const char *p=" ")
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mjsonrpc_schema_to_html_object()

static std::string mjsonrpc_schema_to_html_object ( const MJsonNode *  schema,
int  nest_level,
NestedOutput o 
)
static

Definition at line 4908 of file mjsonrpc.cxx.

4909{
4910 const MJsonNode* d = schema->FindObjectNode("description");
4911 std::string description;
4912 if (d)
4913 description = d->GetString();
4914
4915 std::string xshort = "object";
4916 if (description.length() > 1)
4917 xshort += "</td><td>" + description;
4918
4919 const MJsonNode* properties = schema->FindObjectNode("properties");
4920
4921 const MJsonNodeVector* required_list = NULL;
4922 const MJsonNode* r = schema->FindObjectNode("required");
4923 if (r)
4924 required_list = r->GetArray();
4925
4926 if (!properties) {
4927 o->Output(nest_level, false, "object");
4928 o->Output(nest_level+1, true, description);
4929 return xshort;
4930 }
4931
4932 const MJsonStringVector *names = properties->GetObjectNames();
4933 const MJsonNodeVector *nodes = properties->GetObjectNodes();
4934
4935 if (!names || !nodes) {
4936 o->Output(nest_level, false, "object");
4937 o->Output(nest_level+1, true, description);
4938 return xshort;
4939 }
4940
4941 std::string nest = indent(nest_level * 4);
4942
4943 std::string s;
4944
4945 s += nest + "<table border=1>\n";
4946
4947 if (description.length() > 1) {
4948 s += nest + "<tr>\n";
4949 s += nest + " <td colspan=3>" + description + "</td>\n";
4950 s += nest + "</tr>\n";
4951 }
4952
4953 o->Output(nest_level, true, description);
4954
4955 for (unsigned i=0; i<names->size(); i++) {
4956 std::string name = (*names)[i];
4957 const MJsonNode* node = (*nodes)[i];
4958
4959 bool required = false;
4960 if (required_list)
4961 for (unsigned j=0; j<required_list->size(); j++)
4962 if ((*required_list)[j])
4963 if ((*required_list)[j]->GetString() == name) {
4964 required = true;
4965 break;
4966 }
4967
4968 bool is_array = false;
4969 const MJsonNode* type = node->FindObjectNode("type");
4970 if (type && type->GetString() == "array")
4971 is_array = true;
4972
4973 if (is_array)
4974 name += "[]";
4975
4976 if (!required)
4977 name += "?";
4978
4979 o->Output(nest_level, false, name);
4980
4981 s += nest + "<tr>\n";
4982 s += nest + " <td>" + name + "</td>\n";
4983 s += nest + " <td>";
4984 s += mjsonrpc_schema_to_html_anything(node, nest_level + 1, o);
4985 s += "</td>\n";
4986 s += nest + "</tr>\n";
4987 }
4988
4989 s += nest + "</table>\n";
4990
4991 return s;
4992}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_array_index_list()

static int parse_array_index_list ( const char *  method,
const char *  path,
std::vector< unsigned > *  list 
)
static

Definition at line 560 of file mjsonrpc.cxx.

561{
562 // parse array index in form of:
563 // odbpath[number]
564 // odbpath[number,number]
565 // odbpath[number-number]
566 // or any combination of them, i.e. odbpath[1,10-15,20,30-40]
567
568 const char*s = strchr(path, '[');
569
570 if (!s) {
571 cm_msg(MERROR, method, "expected an array index character \'[\' in \"%s\"", path);
572 return DB_OUT_OF_RANGE;
573 }
574
575 s++; // skip '[' itself
576
577 while (s && (*s != 0)) {
578
579 // check that we have a number
580 if (!isdigit(*s)) {
581 cm_msg(MERROR, method, "expected a number in array index in \"%s\" at \"%s\"", path, s);
582 return DB_OUT_OF_RANGE;
583 }
584
585 unsigned value1 = strtoul(s, (char**)&s, 10);
586
587 // array range,
588 if (*s == '-') {
589 s++; // skip the minus char
590
591 if (!isdigit(*s)) {
592 cm_msg(MERROR, method, "expected a number in array index in \"%s\" at \"%s\"", path, s);
593 return DB_OUT_OF_RANGE;
594 }
595
596 unsigned value2 = strtoul(s, (char**)&s, 10);
597
598 if (value2 >= value1)
599 for (unsigned i=value1; i<=value2; i++)
600 list->push_back(i);
601 else {
602 // this is stupid. simple loop like this
603 // for (unsigned i=value1; i>=value2; i--)
604 // does not work for range 4-0, because value2 is 0,
605 // and x>=0 is always true for unsigned numbers,
606 // so we would loop forever... K.O.
607 for (unsigned i=value1; i!=value2; i--)
608 list->push_back(i);
609 list->push_back(value2);
610 }
611 } else {
612 list->push_back(value1);
613 }
614
615 if (*s == ',') {
616 s++; // skip the comma char
617 continue; // back to the begin of loop
618 }
619
620 if (*s == ']') {
621 s++; // skip the closing bracket
622 s = NULL;
623 continue; // done
624 }
625
626 cm_msg(MERROR, method, "invalid char in array index in \"%s\" at \"%s\"", path, s);
627 return DB_OUT_OF_RANGE;
628 }
629
630#if 0
631 printf("parsed array indices for \"%s\" size is %d: ", path, (int)list->size());
632 for (unsigned i=0; i<list->size(); i++)
633 printf(" %d", (*list)[i]);
634 printf("\n");
635#endif
636
637 return SUCCESS;
638}
#define DB_OUT_OF_RANGE
Definition midas.h:652
Here is the call graph for this function:
Here is the caller graph for this function:

◆ remove()

static std::string remove ( const std::string  s,
char  c 
)
static

Definition at line 253 of file mjsonrpc.cxx.

254{
255 std::string::size_type pos = s.find(c);
256 if (pos == std::string::npos)
257 return s;
258 else
259 return s.substr(0, pos);
260}
char c
Definition system.cxx:1312
Here is the caller graph for this function:

◆ set_debug()

static MJsonNode * set_debug ( const MJsonNode *  params)
static

Definition at line 4522 of file mjsonrpc.cxx.

4523{
4524 if (!params) {
4525 MJSO* doc = MJSO::I();
4526 doc->D("set new value of mjsonrpc_debug");
4527 doc->P(NULL, MJSON_INT, "new value of mjsonrpc_debug");
4528 doc->R(NULL, MJSON_INT, "new value of mjsonrpc_debug");
4529 return doc;
4530 }
4531
4532 mjsonrpc_debug = params->GetInt();
4533 return mjsonrpc_make_result("debug", MJsonNode::MakeInt(mjsonrpc_debug));
4534}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_sleep()

static MJsonNode * set_sleep ( const MJsonNode *  params)
static

Definition at line 4549 of file mjsonrpc.cxx.

4550{
4551 if (!params) {
4552 MJSO* doc = MJSO::I();
4553 doc->D("set new value of mjsonrpc_sleep");
4554 doc->P(NULL, MJSON_INT, "new value of mjsonrpc_sleep");
4555 doc->R(NULL, MJSON_INT, "new value of mjsonrpc_sleep");
4556 return doc;
4557 }
4558
4559 mjsonrpc_sleep = params->GetInt();
4560 return mjsonrpc_make_result("sleep", MJsonNode::MakeInt(mjsonrpc_sleep));
4561}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_time()

static MJsonNode * set_time ( const MJsonNode *  params)
static

Definition at line 4576 of file mjsonrpc.cxx.

4577{
4578 if (!params) {
4579 MJSO* doc = MJSO::I();
4580 doc->D("set new value of mjsonrpc_time");
4581 doc->P(NULL, MJSON_INT, "new value of mjsonrpc_time");
4582 doc->R(NULL, MJSON_INT, "new value of mjsonrpc_time");
4583 return doc;
4584 }
4585
4586 mjsonrpc_time = params->GetInt();
4587 return mjsonrpc_make_result("time", MJsonNode::MakeInt(mjsonrpc_time));
4588}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ start_program()

static MJsonNode * start_program ( const MJsonNode *  params)
static

Definition at line 486 of file mjsonrpc.cxx.

487{
488 if (!params) {
489 MJSO* doc = MJSO::I();
490 doc->D("start MIDAS program defined in ODB /Programs/name");
491 doc->P("name", MJSON_STRING, "name of the program, corresponding to ODB /Programs/name");
492 doc->R("status", MJSON_INT, "return status of ss_system()");
493 return doc;
494 }
495
496 MJsonNode* error = NULL;
497
498 std::string name = mjsonrpc_get_param(params, "name", &error)->GetString(); if (error) return error;
499
500 std::string path = "";
501 path += "/Programs/";
502 path += name;
503 path += "/Start command";
504
505 HNDLE hDB;
507
508 char command[256];
509 int size = sizeof(command);
510 int status = db_get_value(hDB, 0, path.c_str(), command, &size, TID_STRING, FALSE);
511
512 if (status == DB_SUCCESS && command[0]) {
513 status = ss_system(command);
514 }
515
516 return mjsonrpc_make_result("status", MJsonNode::MakeInt(status));
517}
INT ss_system(const char *command)
Definition system.cxx:2188
Here is the call graph for this function:
Here is the caller graph for this function:

◆ StashEvent()

static void StashEvent ( const std::string  buffer_name,
int  event_id,
int  trigger_mask,
const EVENT_HEADER pevent 
)
static

Definition at line 3594 of file mjsonrpc.cxx.

3595{
3596 std::lock_guard<std::mutex> guard(gEventStashMutex);
3597 bool found = false;
3598 for (EventStashEntry* s : gEventStash) {
3599 if (s->buffer_name != buffer_name)
3600 continue;
3601 if (s->event_id == event_id && s->trigger_mask == trigger_mask) {
3602 found = true;
3603 s->ReplaceEvent(pevent);
3604 //s->Print(); printf(", replaced\n");
3605 } else if (bm_match_event(s->event_id, s->trigger_mask, pevent)) {
3606 s->ReplaceEvent(pevent);
3607 //s->Print(); printf(", matched\n");
3608 }
3609 }
3610 if (!found) {
3613 s->event_id = event_id;
3615 s->pevent = CopyEvent(pevent);
3616 //s->Print(); printf(", added\n");
3617 gEventStash.push_back(s);
3618 }
3619}
std::string buffer_name
int event_id
const EVENT_HEADER * pevent
int trigger_mask
Here is the call graph for this function:
Here is the caller graph for this function:

◆ xnull()

static MJsonNode * xnull ( const MJsonNode *  params)
static

Definition at line 413 of file mjsonrpc.cxx.

414{
415 if (!params) {
416 MJSO* doc = MJSO::I();
417 doc->D("RPC method always returns null");
418 doc->P(NULL, 0, "method parameters are ignored");
419 doc->R(NULL, MJSON_NULL, "always returns null");
420 return doc;
421 }
422
423 return mjsonrpc_make_result(MJsonNode::MakeNull());
424}
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ gEventStash

std::vector<EventStashEntry*> gEventStash
static

Definition at line 3592 of file mjsonrpc.cxx.

◆ gEventStashMutex

std::mutex gEventStashMutex
static

Definition at line 3591 of file mjsonrpc.cxx.

◆ gHistoryChannels

MhiMap gHistoryChannels
static

Definition at line 1687 of file mjsonrpc.cxx.

◆ gMethodsTable

MethodsTable gMethodsTable
static

Definition at line 4641 of file mjsonrpc.cxx.

◆ gMutex

std::mutex* gMutex = NULL
static

Definition at line 4642 of file mjsonrpc.cxx.

◆ gNullNode

MJsonNode* gNullNode = NULL
static

Definition at line 176 of file mjsonrpc.cxx.

◆ mjsonrpc_sleep

int mjsonrpc_sleep = 0
static

Definition at line 113 of file mjsonrpc.cxx.

◆ mjsonrpc_time

int mjsonrpc_time = 0
static

Definition at line 114 of file mjsonrpc.cxx.