119 return tv.tv_sec*1.0 +
tv.tv_usec/1000000.0;
124 MJsonNode* errnode = MJsonNode::MakeObject();
125 errnode->AddToObject(
"code", MJsonNode::MakeInt(code));
126 errnode->AddToObject(
"message", MJsonNode::MakeString(
message));
127 errnode->AddToObject(
"data", MJsonNode::MakeString(
data));
129 MJsonNode* result = MJsonNode::MakeObject();
130 result->AddToObject(
"error", errnode);
136 MJsonNode* result = MJsonNode::MakeObject();
137 result->AddToObject(
"result", node);
143 MJsonNode* node = MJsonNode::MakeObject();
148 node->AddToObject(name2, value2);
150 node->AddToObject(name3, value3);
152 MJsonNode* result = MJsonNode::MakeObject();
153 result->AddToObject(
"result", node);
157 MJsonNode*
mjsonrpc_make_result(
const char*
name, MJsonNode*
value,
const char* name2, MJsonNode* value2,
const char* name3, MJsonNode* value3,
const char* name4, MJsonNode* value4)
159 MJsonNode* node = MJsonNode::MakeObject();
164 node->AddToObject(name2, value2);
166 node->AddToObject(name3, value3);
168 node->AddToObject(name4, value4);
170 MJsonNode* result = MJsonNode::MakeObject();
171 result->AddToObject(
"result", node);
184 *error = MJsonNode::MakeObject();
188 const MJsonNode* obj = params->FindObjectNode(
name);
205 *error = MJsonNode::MakeObject();
212 if (error && *error) {
216 const MJsonNodeVector* v = node->GetArray();
220 *error =
mjsonrpc_make_error(-32602,
"Invalid params", (std::string(
"parameter must be an array: ") +
name).c_str());
233 p->AddToObject(
"description", MJsonNode::MakeString(
description));
234 p->AddToObject(
"type", MJsonNode::MakeString(
"object"));
236 p->
required = MJsonNode::MakeArray();
238 p->AddToObject(
"required", p->
required);
245 p->AddToObject(
"description", MJsonNode::MakeString(
description));
246 p->AddToObject(
"type", MJsonNode::MakeString(
"array"));
247 p->
items = MJsonNode::MakeArray();
248 p->AddToObject(
"items", p->
items);
252 static std::string
remove(
const std::string s,
char c)
254 std::string::size_type pos = s.find(
c);
255 if (pos == std::string::npos)
258 return s.substr(0, pos);
266 bool optional = strchr(xname,
'?');
267 bool array = strchr(xname,
'[');
270 std::string
name = xname;
276 s->AddToObject(
"optional", MJsonNode::MakeBool(
true));
280 s->DeleteObjectNode(
"description");
286 items->AddToArray(s);
292 required->AddToArray(MJsonNode::MakeString(
name.c_str()));
304 this->AddToObject(
"description", MJsonNode::MakeString(
description));
357 MJsonNode* p = MJsonNode::MakeObject();
358 p->AddToObject(
"description", MJsonNode::MakeString(
description));
359 if (mjson_type == MJSON_ARRAY)
360 p->AddToObject(
"type", MJsonNode::MakeString(
"array"));
361 else if (mjson_type == MJSON_OBJECT)
362 p->AddToObject(
"type", MJsonNode::MakeString(
"object"));
363 else if (mjson_type == MJSON_STRING)
364 p->AddToObject(
"type", MJsonNode::MakeString(
"string"));
365 else if (mjson_type == MJSON_INT)
366 p->AddToObject(
"type", MJsonNode::MakeString(
"integer"));
367 else if (mjson_type == MJSON_NUMBER)
368 p->AddToObject(
"type", MJsonNode::MakeString(
"number"));
369 else if (mjson_type == MJSON_BOOL)
370 p->AddToObject(
"type", MJsonNode::MakeString(
"bool"));
371 else if (mjson_type == MJSON_NULL)
372 p->AddToObject(
"type", MJsonNode::MakeString(
"null"));
373 else if (mjson_type == MJSON_ARRAYBUFFER)
374 p->AddToObject(
"type", MJsonNode::MakeString(
"arraybuffer"));
375 else if (mjson_type == MJSON_JSON)
376 p->AddToObject(
"type", MJsonNode::MakeString(
"json"));
377 else if (mjson_type == 0)
380 assert(!
"invalid value of mjson_type");
387 s->AddToObject(
"description", MJsonNode::MakeString(
description));
388 s->AddToObject(
"type", MJsonNode::MakeString(
"object"));
396 s->AddToObject(
"description", MJsonNode::MakeString(
description));
397 s->AddToObject(
"type", MJsonNode::MakeString(
"array"));
403 : MJsonNode(MJSON_OBJECT)
412 static MJsonNode*
xnull(
const MJsonNode* params)
416 doc->
D(
"RPC method always returns null");
417 doc->
P(NULL, 0,
"method parameters are ignored");
418 doc->
R(NULL, MJSON_NULL,
"always returns null");
435 doc->
D(
"calls MIDAS cm_exist() to check if given MIDAS program is running");
436 doc->
P(
"name", MJSON_STRING,
"name of the program, corresponding to ODB /Programs/name");
437 doc->
P(
"unique?", MJSON_BOOL,
"bUnique argument to cm_exist()");
438 doc->
R(
"status", MJSON_INT,
"return status of cm_exist()");
442 MJsonNode* error = NULL;
453 printf(
"cm_exist(%s,%d) -> %d\n",
name.c_str(), unique,
status);
462 doc->
D(
"calls MIDAS cm_shutdown() to stop given MIDAS program");
463 doc->
P(
"name", MJSON_STRING,
"name of the program, corresponding to ODB /Programs/name");
464 doc->
P(
"unique?", MJSON_BOOL,
"bUnique argument to cm_shutdown()");
465 doc->
R(
"status", MJSON_INT,
"return status of cm_shutdown()");
469 MJsonNode* error = NULL;
480 printf(
"cm_shutdown(%s,%d) -> %d\n",
name.c_str(), unique,
status);
489 doc->
D(
"start MIDAS program defined in ODB /Programs/name");
490 doc->
P(
"name", MJSON_STRING,
"name of the program, corresponding to ODB /Programs/name");
491 doc->
R(
"status", MJSON_INT,
"return status of ss_system()");
495 MJsonNode* error = NULL;
499 std::string path =
"";
500 path +=
"/Programs/";
502 path +=
"/Start command";
508 int size =
sizeof(command);
522 doc->
D(
"execute custom script defined in ODB /Script (scripts show in the menu) or /CustomScript (scripts from custom pages)");
523 doc->
P(
"script?", MJSON_STRING,
"Execute ODB /Script/xxx");
524 doc->
P(
"customscript?", MJSON_STRING,
"Execute ODB /CustomScript/xxx");
525 doc->
R(
"status", MJSON_INT,
"return status of cm_exec_script()");
530 std::string customscript =
mjsonrpc_get_param(params,
"customscript", NULL)->GetString();
534 if (script.length() > 0) {
538 }
else if (customscript.length() > 0) {
539 path +=
"/CustomScript";
541 path += customscript;
546 if (path.length() > 0) {
567 const char*s = strchr(path,
'[');
570 cm_msg(
MERROR, method,
"expected an array index character \'[\' in \"%s\"", path);
576 while (s && (*s != 0)) {
580 cm_msg(
MERROR, method,
"expected a number in array index in \"%s\" at \"%s\"", path, s);
584 unsigned value1 = strtoul(s, (
char**)&s, 10);
591 cm_msg(
MERROR, method,
"expected a number in array index in \"%s\" at \"%s\"", path, s);
595 unsigned value2 = strtoul(s, (
char**)&s, 10);
597 if (value2 >= value1)
598 for (
unsigned i=value1;
i<=value2;
i++)
606 for (
unsigned i=value1;
i!=value2;
i--)
608 list->push_back(value2);
611 list->push_back(value1);
625 cm_msg(
MERROR, method,
"invalid char in array index in \"%s\" at \"%s\"", path, s);
630 printf(
"parsed array indices for \"%s\" size is %d: ", path, (
int)
list->size());
631 for (
unsigned i=0;
i<
list->size();
i++)
632 printf(
" %d", (*
list)[
i]);
643 doc->
D(
"get values of ODB data from given subtrees");
644 doc->
P(
"paths[]", MJSON_STRING,
"array of ODB subtree paths, see note on array indices");
645 doc->
P(
"omit_names?", MJSON_BOOL,
"omit the /name entries");
646 doc->
P(
"omit_last_written?", MJSON_BOOL,
"omit the /last_written entries and the last_written[] result");
647 doc->
P(
"omit_tid?", MJSON_BOOL,
"omit the tid[] result");
648 doc->
P(
"omit_old_timestamp?", MJSON_NUMBER,
"omit data older than given ODB timestamp");
649 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");
650 doc->
R(
"data[]", 0,
"values of ODB data for each path, all key names are in lower case, all symlinks are followed");
651 doc->
R(
"status[]", MJSON_INT,
"return status of db_copy_json_values() or db_copy_json_index() for each path");
652 doc->
R(
"tid?[]", MJSON_INT,
"odb type id for each path, absent if omit_tid is true");
653 doc->
R(
"last_written?[]", MJSON_NUMBER,
"last_written value of the ODB subtree for each path, absent if omit_last_written is true");
657 MJsonNode* error = NULL;
662 bool omit_last_written =
mjsonrpc_get_param(params,
"omit_last_written", NULL)->GetBool();
664 double xomit_old_timestamp =
mjsonrpc_get_param(params,
"omit_old_timestamp", NULL)->GetDouble();
665 time_t omit_old_timestamp = (time_t)xomit_old_timestamp;
668 MJsonNode* dresult = MJsonNode::MakeArray();
669 MJsonNode* sresult = MJsonNode::MakeArray();
670 MJsonNode* tresult = MJsonNode::MakeArray();
671 MJsonNode* lwresult = MJsonNode::MakeArray();
676 for (
unsigned i=0;
i<paths->size();
i++) {
680 std::string path = (*paths)[
i]->GetString();
684 dresult->AddToArray(MJsonNode::MakeNull());
685 sresult->AddToArray(MJsonNode::MakeInt(
status));
686 tresult->AddToArray(MJsonNode::MakeNull());
687 lwresult->AddToArray(MJsonNode::MakeNull());
693 dresult->AddToArray(MJsonNode::MakeNull());
694 sresult->AddToArray(MJsonNode::MakeInt(
status));
695 tresult->AddToArray(MJsonNode::MakeNull());
696 lwresult->AddToArray(MJsonNode::MakeNull());
700 if (path.find(
"[") != std::string::npos) {
701 std::vector<unsigned>
list;
705 dresult->AddToArray(MJsonNode::MakeNull());
706 sresult->AddToArray(MJsonNode::MakeInt(
status));
707 tresult->AddToArray(MJsonNode::MakeInt(
key.
type));
712 if (
list.size() > 1) {
713 MJsonNode *ddresult = MJsonNode::MakeArray();
714 MJsonNode *ssresult = MJsonNode::MakeArray();
716 for (
unsigned i=0;
i<
list.size();
i++) {
724 ddresult->AddToArray(MJsonNode::MakeJSON(buf));
725 ssresult->AddToArray(MJsonNode::MakeInt(
status));
727 ddresult->AddToArray(MJsonNode::MakeNull());
728 ssresult->AddToArray(MJsonNode::MakeInt(
status));
735 dresult->AddToArray(ddresult);
736 sresult->AddToArray(ssresult);
737 tresult->AddToArray(MJsonNode::MakeInt(
key.
type));
748 dresult->AddToArray(MJsonNode::MakeJSON(buf));
749 sresult->AddToArray(MJsonNode::MakeInt(
status));
750 tresult->AddToArray(MJsonNode::MakeInt(
key.
type));
753 dresult->AddToArray(MJsonNode::MakeNull());
754 sresult->AddToArray(MJsonNode::MakeInt(
status));
755 tresult->AddToArray(MJsonNode::MakeInt(
key.
type));
768 omit_last_written, omit_old_timestamp, preserve_case);
772 dresult->AddToArray(MJsonNode::MakeJSON(buf));
773 sresult->AddToArray(MJsonNode::MakeInt(
status));
774 tresult->AddToArray(MJsonNode::MakeInt(
key.
type));
777 dresult->AddToArray(MJsonNode::MakeNull());
778 sresult->AddToArray(MJsonNode::MakeInt(
status));
779 tresult->AddToArray(MJsonNode::MakeInt(
key.
type));
788 MJsonNode* result = MJsonNode::MakeObject();
790 result->AddToObject(
"data", dresult);
791 result->AddToObject(
"status", sresult);
793 result->AddToObject(
"tid", tresult);
796 if (!omit_last_written)
797 result->AddToObject(
"last_written", lwresult);
804 static MJsonNode*
js_db_ls(
const MJsonNode* params)
808 doc->
D(
"get contents of given ODB subdirectory in the \"ls\" json encoding - similar to odbedit command \"ls -l\"");
809 doc->
P(
"paths[]", MJSON_STRING,
"array of ODB subtree paths");
810 doc->
R(
"data[]", MJSON_OBJECT,
"keys and values of ODB data for each path");
811 doc->
R(
"status[]", MJSON_INT,
"return status of db_copy_json_ls() for each path");
815 MJsonNode* error = NULL;
819 MJsonNode* dresult = MJsonNode::MakeArray();
820 MJsonNode* sresult = MJsonNode::MakeArray();
825 for (
unsigned i=0;
i<paths->size();
i++) {
828 std::string path = (*paths)[
i]->GetString();
832 dresult->AddToArray(MJsonNode::MakeNull());
833 sresult->AddToArray(MJsonNode::MakeInt(
status));
845 dresult->AddToArray(MJsonNode::MakeJSON(buf));
846 sresult->AddToArray(MJsonNode::MakeInt(
status));
848 dresult->AddToArray(MJsonNode::MakeNull());
849 sresult->AddToArray(MJsonNode::MakeInt(
status));
863 doc->
D(
"get complete ODB data in the \"save\" json encoding, suitable for reloading with odbedit command \"load\"");
864 doc->
P(
"paths[]", MJSON_STRING,
"array of ODB subtree paths");
865 doc->
R(
"data[]", MJSON_OBJECT,
"keys and values of ODB data for each path");
866 doc->
R(
"status[]", MJSON_INT,
"return status of db_copy_json_save() for each path");
870 MJsonNode* error = NULL;
874 MJsonNode* dresult = MJsonNode::MakeArray();
875 MJsonNode* sresult = MJsonNode::MakeArray();
880 for (
unsigned i=0;
i<paths->size();
i++) {
883 std::string path = (*paths)[
i]->GetString();
887 dresult->AddToArray(MJsonNode::MakeNull());
888 sresult->AddToArray(MJsonNode::MakeInt(
status));
900 dresult->AddToArray(MJsonNode::MakeJSON(buf));
901 sresult->AddToArray(MJsonNode::MakeInt(
status));
903 dresult->AddToArray(MJsonNode::MakeNull());
904 sresult->AddToArray(MJsonNode::MakeInt(
status));
918 doc->
D(
"write data into ODB");
919 doc->
P(
"paths[]", MJSON_STRING,
"array of ODB subtree paths, see note on array indices");
920 doc->
P(
"values[]", 0,
"array of data values written to ODB via db_paste_json() for each path");
921 doc->
R(
"status[]", MJSON_INT,
"array of return status of db_paste_json() for each path");
925 MJsonNode* error = NULL;
930 if (paths->size() != values->size()) {
931 return mjsonrpc_make_error(-32602,
"Invalid params",
"paths and values should have the same length");
934 MJsonNode* sresult = MJsonNode::MakeArray();
939 for (
unsigned i=0;
i<paths->size();
i++) {
942 std::string path = (*paths)[
i]->GetString();
946 sresult->AddToArray(MJsonNode::MakeInt(
status));
950 const MJsonNode* v = (*values)[
i];
953 if (path.find(
"[*]") != std::string::npos) {
960 }
else if (path.find(
"[") != std::string::npos) {
961 std::vector<unsigned>
list;
965 sresult->AddToArray(MJsonNode::MakeInt(
status));
974 if (
list.size() < 1) {
975 cm_msg(
MERROR,
"js_db_paste",
"invalid array indices for array path \"%s\"", path.c_str());
978 }
else if (
list.size() == 1) {
979 if (v->GetType() == MJSON_ARRAY) {
980 cm_msg(
MERROR,
"js_db_paste",
"unexpected array of values for array path \"%s\"", path.c_str());
986 sresult->AddToArray(MJsonNode::MakeInt(
status));
987 }
else if ((
list.size() > 1) && (v->GetType() == MJSON_ARRAY)) {
988 const MJsonNodeVector* vvalues = v->GetArray();
990 if (
list.size() != vvalues->size()) {
991 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());
996 MJsonNode *ssresult = MJsonNode::MakeArray();
998 for (
unsigned j =0;
j <
list.size();
j++) {
999 const MJsonNode* vv = (*vvalues)[
j];
1002 cm_msg(
MERROR,
"js_db_paste",
"internal error: NULL array value at index %d for array path \"%s\"",
j, path.c_str());
1008 ssresult->AddToArray(MJsonNode::MakeInt(
status));
1011 sresult->AddToArray(ssresult);
1013 MJsonNode *ssresult = MJsonNode::MakeArray();
1014 for (
unsigned j =0;
j <
list.size();
j++) {
1016 ssresult->AddToArray(MJsonNode::MakeInt(
status));
1018 sresult->AddToArray(ssresult);
1022 sresult->AddToArray(MJsonNode::MakeInt(
status));
1033 doc->
D(
"Create new ODB entries");
1034 MJSO* o = doc->
PA(
"array of ODB paths to be created")->
AddObject(
"",
"arguments to db_create_key() and db_set_num_values()");
1035 o->
Add(
"path", MJSON_STRING,
"ODB path to be created");
1036 o->
Add(
"type", MJSON_INT,
"MIDAS TID_xxx type");
1037 o->
Add(
"array_length?", MJSON_INT,
"optional array length, default is 1");
1038 o->
Add(
"string_length?", MJSON_INT,
"for TID_STRING, optional string length, default is NAME_LENGTH");
1039 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");
1043 MJsonNode* sresult = MJsonNode::MakeArray();
1045 const MJsonNodeVector* pp = params->GetArray();
1048 return mjsonrpc_make_error(-32602,
"Invalid params",
"parameters must be an array of objects");
1054 for (
unsigned i=0;
i<pp->size();
i++) {
1055 const MJsonNode* p = (*pp)[
i];
1063 if (string_length == 0)
1072 char* buf = (
char*)calloc(1, string_length);
1073 assert(buf != NULL);
1074 int size = string_length;
1087 sresult->AddToArray(MJsonNode::MakeInt(
status));
1097 doc->
D(
"delete ODB keys");
1098 doc->
P(
"paths[]", MJSON_STRING,
"array of ODB paths to delete");
1099 doc->
R(
"status[]", MJSON_INT,
"return status of db_delete_key() for each path");
1103 MJsonNode* error = NULL;
1107 MJsonNode* sresult = MJsonNode::MakeArray();
1112 for (
unsigned i=0;
i<paths->size();
i++) {
1115 std::string path = (*paths)[
i]->GetString();
1119 sresult->AddToArray(MJsonNode::MakeInt(
status));
1124 sresult->AddToArray(MJsonNode::MakeInt(
status));
1134 doc->
D(
"Change size of ODB arrays");
1135 doc->
P(
"paths[]", MJSON_STRING,
"array of ODB paths to resize");
1136 doc->
P(
"new_lengths[]", MJSON_INT,
"array of new lengths for each ODB path");
1137 doc->
R(
"status[]", MJSON_INT,
"return status of db_set_num_values() for each path");
1141 MJsonNode* error = NULL;
1146 if (paths->size() != lengths->size()) {
1147 return mjsonrpc_make_error(-32602,
"Invalid params",
"arrays \"paths\" and \"new_lengths\" should have the same length");
1150 MJsonNode* sresult = MJsonNode::MakeArray();
1155 for (
unsigned i=0;
i<paths->size();
i++) {
1158 std::string path = (*paths)[
i]->GetString();
1162 sresult->AddToArray(MJsonNode::MakeInt(
status));
1166 int length = (*lengths)[
i]->GetInt();
1173 sresult->AddToArray(MJsonNode::MakeInt(
status));
1183 doc->
D(
"Change size of ODB string arrays");
1184 doc->
P(
"paths[]", MJSON_STRING,
"array of ODB paths to resize");
1185 doc->
P(
"new_lengths[]", MJSON_INT,
"array of new lengths for each ODB path");
1186 doc->
P(
"new_string_lengths[]", MJSON_INT,
"array of new string lengths for each ODB path");
1187 doc->
R(
"status[]", MJSON_INT,
"return status of db_resize_string() for each path");
1191 MJsonNode* error = NULL;
1195 const MJsonNodeVector* string_lengths =
mjsonrpc_get_param_array(params,
"new_string_lengths", &error);
if (error)
return error;
1197 if (paths->size() != lengths->size()) {
1198 return mjsonrpc_make_error(-32602,
"Invalid params",
"arrays \"paths\" and \"new_lengths\" should have the same length");
1201 if (paths->size() != string_lengths->size()) {
1202 return mjsonrpc_make_error(-32602,
"Invalid params",
"arrays \"paths\" and \"new_string_lengths\" should have the same length");
1205 MJsonNode* sresult = MJsonNode::MakeArray();
1210 for (
unsigned i=0;
i<paths->size();
i++) {
1211 std::string path = (*paths)[
i]->GetString();
1213 int length = (*lengths)[
i]->GetInt();
1219 int string_length = (*string_lengths)[
i]->GetInt();
1226 sresult->AddToArray(MJsonNode::MakeInt(
status));
1236 doc->
D(
"get ODB keys");
1237 doc->
P(
"paths[]", MJSON_STRING,
"array of ODB paths");
1238 doc->
R(
"status[]", MJSON_INT,
"return status of db_key() for each path");
1239 doc->
R(
"keys[]", MJSON_OBJECT,
"key data for each path");
1240 doc->
R(
"keys[].type", MJSON_INT,
"key type TID_xxx");
1241 doc->
R(
"keys[].num_values", MJSON_INT,
"array length, 1 for normal entries");
1242 doc->
R(
"keys[].name", MJSON_STRING,
"key name");
1243 doc->
R(
"keys[].total_size", MJSON_INT,
"data total size in bytes");
1244 doc->
R(
"keys[].item_size", MJSON_INT,
"array element size, string length for TID_STRING");
1245 doc->
R(
"keys[].access_mode", MJSON_INT,
"access mode bitmap of MODE_xxx");
1246 doc->
R(
"keys[].notify_count", MJSON_INT,
"number of hotlinks attached to this key");
1247 doc->
R(
"keys[].last_written", MJSON_INT,
"timestamp when data was last updated");
1251 MJsonNode* error = NULL;
1255 MJsonNode* kresult = MJsonNode::MakeArray();
1256 MJsonNode* sresult = MJsonNode::MakeArray();
1261 for (
unsigned i=0;
i<paths->size();
i++) {
1265 std::string path = (*paths)[
i]->GetString();
1269 kresult->AddToArray(MJsonNode::MakeNull());
1270 sresult->AddToArray(MJsonNode::MakeInt(
status));
1276 kresult->AddToArray(MJsonNode::MakeNull());
1277 sresult->AddToArray(MJsonNode::MakeInt(
status));
1281 MJsonNode* jkey = MJsonNode::MakeObject();
1283 jkey->AddToObject(
"type", MJsonNode::MakeInt(
key.
type));
1284 jkey->AddToObject(
"num_values", MJsonNode::MakeInt(
key.
num_values));
1286 jkey->AddToObject(
"name", MJsonNode::MakeString(
key.
name));
1287 jkey->AddToObject(
"total_size", MJsonNode::MakeInt(
key.
total_size));
1288 jkey->AddToObject(
"item_size", MJsonNode::MakeInt(
key.
item_size));
1289 jkey->AddToObject(
"access_mode", MJsonNode::MakeInt(
key.
access_mode));
1290 jkey->AddToObject(
"notify_count", MJsonNode::MakeInt(
key.
notify_count));
1291 jkey->AddToObject(
"last_written", MJsonNode::MakeInt(
key.
last_written));
1293 kresult->AddToArray(jkey);
1294 sresult->AddToArray(MJsonNode::MakeInt(
status));
1304 doc->
D(
"Change size of ODB arrays");
1305 doc->
P(
"paths[]", MJSON_STRING,
"array of ODB paths to rename");
1306 doc->
P(
"new_names[]", MJSON_STRING,
"array of new names for each ODB path");
1307 doc->
R(
"status[]", MJSON_INT,
"return status of db_rename_key() for each path");
1311 MJsonNode* error = NULL;
1316 if (paths->size() != names->size()) {
1317 return mjsonrpc_make_error(-32602,
"Invalid params",
"arrays \"paths\" and \"new_names\" should have the same length");
1320 MJsonNode* sresult = MJsonNode::MakeArray();
1325 for (
unsigned i=0;
i<paths->size();
i++) {
1328 std::string path = (*paths)[
i]->GetString();
1332 sresult->AddToArray(MJsonNode::MakeInt(
status));
1336 std::string new_name = (*names)[
i]->GetString();
1337 if (new_name.length() < 1) {
1344 sresult->AddToArray(MJsonNode::MakeInt(
status));
1354 doc->
D(
"Create ODB symlinks");
1355 doc->
P(
"new_links[]", MJSON_STRING,
"array of new symlinks to be created");
1356 doc->
P(
"target_paths[]", MJSON_STRING,
"array of existing ODB paths for each link");
1357 doc->
R(
"status[]", MJSON_INT,
"return status of db_create_link() for each path");
1361 MJsonNode* error = NULL;
1363 const MJsonNodeVector* target_paths =
mjsonrpc_get_param_array(params,
"target_paths", &error);
if (error)
return error;
1366 if (target_paths->size() != new_links->size()) {
1367 return mjsonrpc_make_error(-32602,
"Invalid params",
"arrays \"target_paths\" and \"new_links\" should have the same length");
1370 MJsonNode* sresult = MJsonNode::MakeArray();
1375 for (
unsigned i=0;
i<new_links->size();
i++) {
1377 std::string target_path = (*target_paths)[
i]->GetString();
1378 std::string new_link = (*new_links)[
i]->GetString();
1379 if (new_link.length() < 1) {
1386 sresult->AddToArray(MJsonNode::MakeInt(
status));
1396 doc->
D(
"Change order of ODB keys in a subdirectory");
1397 doc->
P(
"paths[]", MJSON_STRING,
"array of new symlinks to be created");
1398 doc->
P(
"indices[]", MJSON_INT,
"array of existing ODB paths for each link");
1399 doc->
R(
"status[]", MJSON_INT,
"return status of db_reorder_key() for each path");
1403 MJsonNode* error = NULL;
1408 if (paths->size() != indices->size()) {
1409 return mjsonrpc_make_error(-32602,
"Invalid params",
"arrays \"paths\" and \"indices\" should have the same length");
1412 MJsonNode* sresult = MJsonNode::MakeArray();
1417 for (
unsigned i=0;
i<paths->size();
i++) {
1420 std::string path = (*paths)[
i]->GetString();
1421 int index = (*indices)[
i]->GetInt();
1425 sresult->AddToArray(MJsonNode::MakeInt(
status));
1431 sresult->AddToArray(MJsonNode::MakeInt(
status));
1441 doc->
D(
"Show ODB open records starting from given ODB path");
1442 doc->
P(
"path?", MJSON_STRING,
"ODB path");
1443 doc->
R(
"sor", MJSON_JSON,
"return value of db_sor()");
1447 MJsonNode* error = NULL;
1449 std::string path =
mjsonrpc_get_param(params,
"path", NULL)->GetString();
if (error)
return error;
1454 MJsonNode* sor =
db_sor(
hDB, path.c_str());
1463 doc->
D(
"Show ODB clients");
1464 doc->
R(
"scl", MJSON_JSON,
"return value of db_scl()");
1486 doc->
D(
"get message facilities using cm_msg_facilities()");
1487 doc->
R(
"status", MJSON_INT,
"return status of cm_msg_facilities()");
1488 doc->
R(
"facilities[]", MJSON_STRING,
"array of facility names");
1496 MJsonNode* facilities = MJsonNode::MakeArray();
1498 for (
unsigned i=0;
i<
list.size();
i++) {
1500 facilities->AddToArray(MJsonNode::MakeString(
list[
i].c_str()));
1504 "facilities", facilities);
1511 doc->
D(
"Generate a midas message using cm_msg1()");
1512 doc->
P(
"facility?", MJSON_STRING,
"message facility, default is \"midas\"");
1513 doc->
P(
"user?", MJSON_STRING,
"message user, default is \"javascript_commands\"");
1514 doc->
P(
"type?", MJSON_INT,
"message type, MT_xxx from midas.h, default is MT_INFO");
1515 doc->
P(
"message", MJSON_STRING,
"message text");
1516 doc->
R(
"status", MJSON_INT,
"return status of cm_msg1()");
1520 MJsonNode* error = NULL;
1527 if (facility.size() <1)
1530 user =
"javascript_commands";
1543 doc->
D(
"Retrieve midas messages using cm_msg_retrieve2()");
1544 doc->
P(
"facility?", MJSON_STRING,
"message facility, default is \"midas\"");
1545 doc->
P(
"min_messages?", MJSON_INT,
"get at least this many messages, default is 1");
1546 doc->
P(
"time?", MJSON_NUMBER,
"start from given timestamp, value 0 means give me newest messages, default is 0");
1547 doc->
R(
"num_messages", MJSON_INT,
"number of messages returned");
1548 doc->
R(
"messages", MJSON_STRING,
"messages separated by \\n");
1549 doc->
R(
"status", MJSON_INT,
"return status of cm_msg_retrieve2()");
1557 if (facility.size() < 1)
1560 int num_messages = 0;
1561 char* messages = NULL;
1565 MJsonNode* result = MJsonNode::MakeObject();
1567 result->AddToObject(
"status", MJsonNode::MakeInt(
status));
1568 result->AddToObject(
"num_messages", MJsonNode::MakeInt(num_messages));
1572 result->AddToObject(
"messages", MJsonNode::MakeString(messages));
1590 doc->
D(
"reset alarms");
1591 doc->
P(
"alarms[]", MJSON_STRING,
"array of alarm names");
1592 doc->
R(
"status[]", MJSON_INT,
"return status of al_reset_alarm() for each alarm");
1596 MJsonNode* error = NULL;
1600 MJsonNode* sresult = MJsonNode::MakeArray();
1602 for (
unsigned i=0;
i<alarms->size();
i++) {
1604 sresult->AddToArray(MJsonNode::MakeInt(
status));
1614 doc->
D(
"trigger an alarm");
1615 doc->
P(
"name", MJSON_STRING,
"alarm name");
1616 doc->
P(
"message", MJSON_STRING,
"alarm message");
1617 doc->
P(
"class", MJSON_STRING,
"alarm class");
1618 doc->
P(
"condition", MJSON_STRING,
"alarm condition");
1619 doc->
P(
"type", MJSON_INT,
"alarm type (AT_xxx)");
1620 doc->
R(
"status", MJSON_INT,
"return status of al_trigger_alarm()");
1624 MJsonNode* error = NULL;
1628 std::string xclass =
mjsonrpc_get_param(params,
"class", &error)->GetString();
if (error)
return error;
1629 std::string condition =
mjsonrpc_get_param(params,
"condition", &error)->GetString();
if (error)
return error;
1641 doc->
D(
"trigger an alarm");
1642 doc->
P(
"class", MJSON_STRING,
"alarm class");
1643 doc->
P(
"message", MJSON_STRING,
"alarm message");
1644 doc->
P(
"first?", MJSON_BOOL,
"see al_trigger_class() in midas.c");
1645 doc->
R(
"status", MJSON_INT,
"return status of al_trigger_class()");
1649 MJsonNode* error = NULL;
1651 std::string xclass =
mjsonrpc_get_param(params,
"class", &error)->GetString();
if (error)
return error;
1672 doc->
D(
"get list of active history events using hs_read_event_list()");
1673 doc->
R(
"status", MJSON_INT,
"return status of hs_read_event_list()");
1674 doc->
R(
"events[]", MJSON_STRING,
"array of history event names");
1682 MJsonNode* events = MJsonNode::MakeArray();
1684 for (
unsigned i=0;
i<
list.size();
i++) {
1686 events->AddToArray(MJsonNode::MakeString(
list[
i].c_str()));
1692 typedef std::map<std::string,MidasHistoryInterface*>
MhiMap;
1712 if (strlen(
name) < 1) {
1733 cm_msg(
MERROR,
"GetHistory",
"Cannot configure history, hs_get_history() status %d",
status);
1759 doc->
D(
"get list of history channels in /Logger/History");
1760 doc->
R(
"status", MJSON_INT,
"return success or failure status");
1761 doc->
R(
"default_channel", MJSON_STRING,
"name of the default logger history channel");
1762 doc->
R(
"channels[]", MJSON_STRING,
"all logger history channel names");
1763 doc->
R(
"active_channels[]", MJSON_STRING,
"active logger history channel names");
1767 MJsonNode* channels = MJsonNode::MakeArray();
1768 MJsonNode* active_channels = MJsonNode::MakeArray();
1783 for (
int ichan=0; ; ichan++) {
1799 channels->AddToArray(MJsonNode::MakeString(
key.
name));
1802 INT size =
sizeof(active);
1806 active_channels->AddToArray(MJsonNode::MakeString(
key.
name));
1813 std::string default_channel;
1827 "default_channel", MJsonNode::MakeString(default_channel.c_str()),
1828 "active_channels", active_channels,
1829 "channels", channels);
1836 doc->
D(
"get list of history events that existed at give time using hs_get_events()");
1837 doc->
P(
"channel?", MJSON_STRING,
"midas history channel, default is the default reader channel");
1838 doc->
P(
"time?", MJSON_NUMBER,
"timestamp, value 0 means current time, default is 0");
1839 doc->
R(
"status", MJSON_INT,
"return status of hs_get_events()");
1840 doc->
R(
"channel", MJSON_STRING,
"logger history channel name");
1841 doc->
R(
"events[]", MJSON_STRING,
"array of history event names");
1850 MJsonNode* events = MJsonNode::MakeArray();
1858 time = ::time(NULL);
1865 for (
unsigned i=0;
i<
list.size();
i++) {
1867 events->AddToArray(MJsonNode::MakeString(
list[
i].c_str()));
1877 doc->
D(
"reopen the history channel to make sure we see the latest list of events using hs_clear_cache()");
1878 doc->
P(
"channel?", MJSON_STRING,
"midas history channel, default is the default reader channel");
1879 doc->
R(
"status", MJSON_INT,
"return status of hs_get_events()");
1880 doc->
R(
"channel", MJSON_STRING,
"logger history channel name");
1902 doc->
D(
"get list of history tags for given history events that existed at give time using hs_get_tags()");
1903 doc->
P(
"channel?", MJSON_STRING,
"midas history channel, default is the default reader channel");
1904 doc->
P(
"time?", MJSON_NUMBER,
"timestamp, value 0 means current time, default is 0");
1905 doc->
P(
"events[]?", MJSON_STRING,
"array of history event names, default is get all events using hs_get_events()");
1906 doc->
R(
"status", MJSON_INT,
"return status");
1907 doc->
R(
"channel", MJSON_STRING,
"logger history channel name");
1908 doc->
R(
"events[].name", MJSON_STRING,
"array of history event names for each history event");
1909 doc->
R(
"events[].status", MJSON_INT,
"array of status ohistory tags for each history event");
1910 doc->
R(
"events[].tags[]", MJSON_STRING,
"array of history tags for each history event");
1911 doc->
R(
"events[].tags[].name", MJSON_STRING,
"history tag name");
1912 doc->
R(
"events[].tags[].type", MJSON_INT,
"history tag midas data type");
1913 doc->
R(
"events[].tags[].n_data?", MJSON_INT,
"history tag number of array elements, omitted if 1");
1922 time = ::time(NULL);
1927 MJsonNode* events = MJsonNode::MakeArray();
1934 std::vector<std::string> event_names;
1936 if (events_array && events_array->size() > 0) {
1937 for (
unsigned i=0;
i<events_array->size();
i++) {
1938 event_names.push_back((*events_array)[
i]->GetString());
1942 if (event_names.size() < 1) {
1949 for (
unsigned i=0;
i<event_names.size();
i++) {
1950 MJsonNode* o = MJsonNode::MakeObject();
1951 const char* event_name = event_names[
i].c_str();
1952 std::vector<TAG> tags;
1955 o->AddToObject(
"name", MJsonNode::MakeString(event_name));
1956 o->AddToObject(
"status", MJsonNode::MakeInt(
status));
1957 MJsonNode *ta = MJsonNode::MakeArray();
1958 for (
unsigned j=0;
j<tags.size();
j++) {
1959 MJsonNode* to = MJsonNode::MakeObject();
1961 to->AddToObject(
"name", MJsonNode::MakeString(tags[
j].
name));
1962 to->AddToObject(
"type", MJsonNode::MakeInt(tags[
j].
type));
1963 if (tags[
j].n_data != 1) {
1964 to->AddToObject(
"n_data", MJsonNode::MakeInt(tags[
j].n_data));
1968 o->AddToObject(
"tags", ta);
1969 events->AddToArray(o);
1980 doc->
D(
"get list of history tags for given history events that existed at give time using hs_get_last_written()");
1981 doc->
P(
"channel?", MJSON_STRING,
"midas history channel, default is the default reader channel");
1982 doc->
P(
"time?", MJSON_NUMBER,
"timestamp, value 0 means current time, default is 0");
1983 doc->
P(
"events[]", MJSON_STRING,
"array of history event names");
1984 doc->
P(
"tags[]", MJSON_STRING,
"array of history event tag names");
1985 doc->
P(
"index[]", MJSON_STRING,
"array of history event tag array indices");
1986 doc->
R(
"status", MJSON_INT,
"return status");
1987 doc->
R(
"channel", MJSON_STRING,
"logger history channel name");
1988 doc->
R(
"last_written[]", MJSON_NUMBER,
"array of last-written times for each history event");
2001 MJsonNode* lw = MJsonNode::MakeArray();
2008 unsigned num_var = events_array->size();
2010 if (tags_array->size() != num_var) {
2011 return mjsonrpc_make_error(-32602,
"Invalid params",
"Arrays events and tags should have the same length");
2014 if (index_array->size() != num_var) {
2015 return mjsonrpc_make_error(-32602,
"Invalid params",
"Arrays events and index should have the same length");
2018 std::vector<std::string> event_names(num_var);
2019 std::vector<std::string> tag_names(num_var);
2022 int* var_index =
new int[num_var];
2023 time_t* last_written =
new time_t[num_var];
2025 for (
unsigned i=0;
i<num_var;
i++) {
2028 event_names[
i] = (*events_array)[
i]->GetString();
2029 tag_names[
i] = (*tags_array)[
i]->GetString();
2030 var_index[
i] = (*index_array)[
i]->GetInt();
2034 printf(
"time %f, num_vars %d:\n", time, num_var);
2035 for (
unsigned i=0;
i<num_var;
i++) {
2036 printf(
"%d: [%s] [%s] [%d]\n",
i, event_names[
i].c_str(), tag_names[
i].c_str(), var_index[
i]);
2041 time = ::time(NULL);
2045 const char** event_name =
new const char*[num_var];
2046 const char** tag_name =
new const char*[num_var];
2047 for (
unsigned i=0;
i<num_var;
i++) {
2048 event_name[
i] = event_names[
i].c_str();
2049 tag_name[
i] = tag_names[
i].c_str();
2053 for (
unsigned i=0;
i<num_var;
i++) {
2055 printf(
"%d: last_written %d\n",
i, (
int)last_written[
i]);
2057 lw->AddToArray(MJsonNode::MakeNumber(last_written[
i]));
2060 delete[] event_name;
2063 delete[] last_written;
2094 fTimeJson += MJsonNode::EncodeDouble(t);
2109 doc->
D(
"get history data for given history events that existed at give time using hs_read_buffer()");
2110 doc->
P(
"channel?", MJSON_STRING,
"midas history channel, default is the default reader channel");
2111 doc->
P(
"start_time", MJSON_NUMBER,
"start time of the data");
2112 doc->
P(
"end_time", MJSON_NUMBER,
"end time of the data");
2113 doc->
P(
"events[]", MJSON_STRING,
"array of history event names");
2114 doc->
P(
"tags[]", MJSON_STRING,
"array of history event tag names");
2115 doc->
P(
"index[]", MJSON_STRING,
"array of history event tag array indices");
2116 doc->
R(
"status", MJSON_INT,
"return status");
2117 doc->
R(
"channel", MJSON_STRING,
"logger history channel name");
2118 doc->
R(
"data[]", MJSON_ARRAY,
"array of history data");
2119 doc->
R(
"data[].status", MJSON_INT,
"status for each event");
2120 doc->
R(
"data[].count", MJSON_INT,
"number of data for each event");
2121 doc->
R(
"data[].time[]", MJSON_NUMBER,
"time data");
2122 doc->
R(
"data[].value[]", MJSON_NUMBER,
"value data");
2126 MJsonNode* error = NULL;
2129 double start_time =
mjsonrpc_get_param(params,
"start_time", &error)->GetDouble();
if (error)
return error;
2130 double end_time =
mjsonrpc_get_param(params,
"end_time", &error)->GetDouble();
if (error)
return error;
2138 MJsonNode*
data = MJsonNode::MakeArray();
2145 unsigned num_var = events_array->size();
2147 if (tags_array->size() != num_var) {
2148 return mjsonrpc_make_error(-32602,
"Invalid params",
"Arrays events and tags should have the same length");
2151 if (index_array->size() != num_var) {
2152 return mjsonrpc_make_error(-32602,
"Invalid params",
"Arrays events and index should have the same length");
2155 std::vector<std::string> event_names(num_var);
2156 std::vector<std::string> tag_names(num_var);
2157 int* var_index =
new int[num_var];
2160 int* hs_status =
new int[num_var];
2162 for (
unsigned i=0;
i<num_var;
i++) {
2165 event_names[
i] = (*events_array)[
i]->GetString();
2166 tag_names[
i] = (*tags_array)[
i]->GetString();
2167 var_index[
i] = (*index_array)[
i]->GetInt();
2174 printf(
"time %f %f, num_vars %d:\n", start_time, end_time, num_var);
2175 for (
unsigned i=0;
i<num_var;
i++) {
2176 printf(
"%d: [%s] [%s] [%d]\n",
i, event_names[
i].c_str(), tag_names[
i].c_str(), var_index[
i]);
2180 const char** event_name =
new const char*[num_var];
2181 const char** tag_name =
new const char*[num_var];
2182 for (
unsigned i=0;
i<num_var;
i++) {
2183 event_name[
i] = event_names[
i].c_str();
2184 tag_name[
i] = tag_names[
i].c_str();
2187 int status =
mh->
hs_read_buffer(start_time, end_time, num_var, event_name, tag_name, var_index, buf, hs_status);
2189 for (
unsigned i=0;
i<num_var;
i++) {
2192 MJsonNode* obj = MJsonNode::MakeObject();
2193 obj->AddToObject(
"status", MJsonNode::MakeInt(hs_status[
i]));
2194 obj->AddToObject(
"count", MJsonNode::MakeInt(jbuf[
i]->fCount));
2195 obj->AddToObject(
"time", MJsonNode::MakeJSON(jbuf[
i]->fTimeJson.c_str()));
2196 obj->AddToObject(
"value", MJsonNode::MakeJSON(jbuf[
i]->fValueJson.c_str()));
2197 data->AddToArray(obj);
2204 delete[] event_name;
2218 doc->
D(
"get history data for given history events that existed at give time using hs_read_buffer()");
2219 doc->
P(
"channel?", MJSON_STRING,
"midas history channel, default is the default reader channel");
2220 doc->
P(
"start_time", MJSON_NUMBER,
"start time of the data");
2221 doc->
P(
"end_time", MJSON_NUMBER,
"end time of the data");
2222 doc->
P(
"num_bins", MJSON_INT,
"number of time bins");
2223 doc->
P(
"events[]", MJSON_STRING,
"array of history event names");
2224 doc->
P(
"tags[]", MJSON_STRING,
"array of history event tag names");
2225 doc->
P(
"index[]", MJSON_STRING,
"array of history event tag array indices");
2226 doc->
R(
"status", MJSON_INT,
"return status");
2227 doc->
R(
"channel", MJSON_STRING,
"logger history channel name");
2228 doc->
R(
"data[]", MJSON_ARRAY,
"array of history data");
2229 doc->
R(
"data[].status", MJSON_INT,
"status for each event");
2230 doc->
R(
"data[].num_entries", MJSON_INT,
"number of data points for each event");
2231 doc->
R(
"data[].count[]", MJSON_INT,
"number of data points for each bin");
2232 doc->
R(
"data[].mean[]", MJSON_NUMBER,
"mean for each bin");
2233 doc->
R(
"data[].rms[]", MJSON_NUMBER,
"rms for each bin");
2234 doc->
R(
"data[].min[]", MJSON_NUMBER,
"minimum value for each bin");
2235 doc->
R(
"data[].max[]", MJSON_NUMBER,
"maximum value for each bin");
2236 doc->
R(
"data[].bins_first_time[]", MJSON_NUMBER,
"first data point in each bin");
2237 doc->
R(
"data[].bins_first_value[]", MJSON_NUMBER,
"first data point in each bin");
2238 doc->
R(
"data[].bins_last_time[]", MJSON_NUMBER,
"last data point in each bin");
2239 doc->
R(
"data[].bins_last_value[]", MJSON_NUMBER,
"last data point in each bin");
2240 doc->
R(
"data[].last_time", MJSON_NUMBER,
"time of last data entry");
2241 doc->
R(
"data[].last_value", MJSON_NUMBER,
"value of last data entry");
2245 MJsonNode* error = NULL;
2248 double start_time =
mjsonrpc_get_param(params,
"start_time", &error)->GetDouble();
if (error)
return error;
2249 double end_time =
mjsonrpc_get_param(params,
"end_time", &error)->GetDouble();
if (error)
return error;
2250 int num_bins =
mjsonrpc_get_param(params,
"num_bins", &error)->GetInt();
if (error)
return error;
2253 return mjsonrpc_make_error(-32602,
"Invalid params",
"Value of num_bins should be 1 or more");
2262 MJsonNode*
data = MJsonNode::MakeArray();
2269 unsigned num_var = events_array->size();
2272 return mjsonrpc_make_error(-32602,
"Invalid params",
"Array of events should have 1 or more elements");
2275 if (tags_array->size() != num_var) {
2276 return mjsonrpc_make_error(-32602,
"Invalid params",
"Arrays events and tags should have the same length");
2279 if (index_array->size() != num_var) {
2280 return mjsonrpc_make_error(-32602,
"Invalid params",
"Arrays events and index should have the same length");
2283 std::vector<std::string> event_names(num_var);
2284 std::vector<std::string> tag_names(num_var);
2287 int* var_index =
new int[num_var];
2289 int* num_entries =
new int[num_var];
2290 time_t*
last_time =
new time_t[num_var];
2291 double* last_value =
new double[num_var];
2292 int* hs_status =
new int[num_var];
2294 int** count_bins =
new int*[num_var];
2295 double** mean_bins =
new double*[num_var];
2296 double** rms_bins =
new double*[num_var];
2297 double** min_bins =
new double*[num_var];
2298 double** max_bins =
new double*[num_var];
2300 time_t** bins_first_time =
new time_t*[num_var];
2301 time_t** bins_last_time =
new time_t*[num_var];
2303 double** bins_first_value =
new double*[num_var];
2304 double** bins_last_value =
new double*[num_var];
2306 for (
unsigned i=0;
i<num_var;
i++) {
2309 event_names[
i] = (*events_array)[
i]->GetString();
2310 tag_names[
i] = (*tags_array)[
i]->GetString();
2311 var_index[
i] = (*index_array)[
i]->GetInt();
2316 count_bins[
i] =
new int[num_bins];
2317 mean_bins[
i] =
new double[num_bins];
2318 rms_bins[
i] =
new double[num_bins];
2319 min_bins[
i] =
new double[num_bins];
2320 max_bins[
i] =
new double[num_bins];
2322 bins_first_time[
i] =
new time_t[num_bins];
2323 bins_last_time[
i] =
new time_t[num_bins];
2325 bins_first_value[
i] =
new double[num_bins];
2326 bins_last_value[
i] =
new double[num_bins];
2330 printf(
"time %f %f, num_vars %d:\n", start_time, end_time, num_var);
2331 for (
unsigned i=0;
i<num_var;
i++) {
2332 printf(
"%d: [%s] [%s] [%d]\n",
i, event_names[
i].c_str(), tag_names[
i].c_str(), var_index[
i]);
2336 const char** event_name =
new const char*[num_var];
2337 const char** tag_name =
new const char*[num_var];
2338 for (
unsigned i=0;
i<num_var;
i++) {
2339 event_name[
i] = event_names[
i].c_str();
2340 tag_name[
i] = tag_names[
i].c_str();
2343 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);
2345 for (
unsigned i=0;
i<num_var;
i++) {
2346 MJsonNode* obj = MJsonNode::MakeObject();
2347 obj->AddToObject(
"status", MJsonNode::MakeInt(hs_status[
i]));
2348 obj->AddToObject(
"num_entries", MJsonNode::MakeInt(num_entries[
i]));
2350 MJsonNode* a1 = MJsonNode::MakeArray();
2351 MJsonNode* a2 = MJsonNode::MakeArray();
2352 MJsonNode* a3 = MJsonNode::MakeArray();
2353 MJsonNode* a4 = MJsonNode::MakeArray();
2354 MJsonNode* a5 = MJsonNode::MakeArray();
2356 MJsonNode* b1 = MJsonNode::MakeArray();
2357 MJsonNode* b2 = MJsonNode::MakeArray();
2358 MJsonNode* b3 = MJsonNode::MakeArray();
2359 MJsonNode* b4 = MJsonNode::MakeArray();
2361 for (
int j=0;
j<num_bins;
j++) {
2362 a1->AddToArray(MJsonNode::MakeInt(count_bins[
i][
j]));
2363 a2->AddToArray(MJsonNode::MakeNumber(mean_bins[
i][
j]));
2364 a3->AddToArray(MJsonNode::MakeNumber(rms_bins[
i][
j]));
2365 a4->AddToArray(MJsonNode::MakeNumber(min_bins[
i][
j]));
2366 a5->AddToArray(MJsonNode::MakeNumber(max_bins[
i][
j]));
2368 b1->AddToArray(MJsonNode::MakeNumber(bins_first_time[
i][
j]));
2369 b2->AddToArray(MJsonNode::MakeNumber(bins_first_value[
i][
j]));
2370 b3->AddToArray(MJsonNode::MakeNumber(bins_last_time[
i][
j]));
2371 b4->AddToArray(MJsonNode::MakeNumber(bins_last_value[
i][
j]));
2374 obj->AddToObject(
"count", a1);
2375 obj->AddToObject(
"mean", a2);
2376 obj->AddToObject(
"rms", a3);
2377 obj->AddToObject(
"min", a4);
2378 obj->AddToObject(
"max", a5);
2379 obj->AddToObject(
"bins_first_time", b1);
2380 obj->AddToObject(
"bins_first_value", b2);
2381 obj->AddToObject(
"bins_last_time", b3);
2382 obj->AddToObject(
"bins_last_value", b4);
2383 obj->AddToObject(
"last_time", MJsonNode::MakeNumber(
last_time[
i]));
2384 obj->AddToObject(
"last_value", MJsonNode::MakeNumber(last_value[
i]));
2385 data->AddToArray(obj);
2387 delete count_bins[
i];
2388 delete mean_bins[
i];
2393 delete bins_first_time[
i];
2394 delete bins_first_value[
i];
2395 delete bins_last_time[
i];
2396 delete bins_last_value[
i];
2399 delete[] count_bins;
2405 delete[] bins_first_time;
2406 delete[] bins_first_value;
2407 delete[] bins_last_time;
2408 delete[] bins_last_value;
2410 delete[] event_name;
2414 delete[] num_entries;
2416 delete[] last_value;
2452 doc->
D(
"get history data for given history events that existed at give time using hs_read_buffer()");
2453 doc->
P(
"channel?", MJSON_STRING,
"midas history channel, default is the default reader channel");
2454 doc->
P(
"start_time", MJSON_NUMBER,
"start time of the data");
2455 doc->
P(
"end_time", MJSON_NUMBER,
"end time of the data");
2456 doc->
P(
"events[]", MJSON_STRING,
"array of history event names");
2457 doc->
P(
"tags[]", MJSON_STRING,
"array of history event tag names");
2458 doc->
P(
"index[]", MJSON_STRING,
"array of history event tag array indices");
2459 doc->
R(
"binary data", MJSON_ARRAYBUFFER,
"binary data, see documentation");
2463 MJsonNode* error = NULL;
2466 double start_time =
mjsonrpc_get_param(params,
"start_time", &error)->GetDouble();
if (error)
return error;
2467 double end_time =
mjsonrpc_get_param(params,
"end_time", &error)->GetDouble();
if (error)
return error;
2480 size_t num_var = events_array->size();
2482 if (tags_array->size() != num_var) {
2483 return mjsonrpc_make_error(-32602,
"Invalid params",
"Arrays events and tags should have the same length");
2486 if (index_array->size() != num_var) {
2487 return mjsonrpc_make_error(-32602,
"Invalid params",
"Arrays events and index should have the same length");
2490 std::vector<std::string> event_names(num_var);
2491 std::vector<std::string> tag_names(num_var);
2492 int* var_index =
new int[num_var];
2495 int* hs_status =
new int[num_var];
2497 for (
size_t i=0;
i<num_var;
i++) {
2500 event_names[
i] = (*events_array)[
i]->GetString();
2501 tag_names[
i] = (*tags_array)[
i]->GetString();
2502 var_index[
i] = (*index_array)[
i]->GetInt();
2509 printf(
"time %f %f, num_vars %d:\n", start_time, end_time,
int(num_var));
2510 for (
size_t i=0;
i<num_var;
i++) {
2511 printf(
"%d: [%s] [%s] [%d]\n",
int(
i), event_names[
i].c_str(), tag_names[
i].c_str(), var_index[
i]);
2515 const char** event_name =
new const char*[num_var];
2516 const char** tag_name =
new const char*[num_var];
2517 for (
unsigned i=0;
i<num_var;
i++) {
2518 event_name[
i] = event_names[
i].c_str();
2519 tag_name[
i] = tag_names[
i].c_str();
2522 int status =
mh->
hs_read_buffer(start_time, end_time, num_var, event_name, tag_name, var_index, buf, hs_status);
2524 size_t num_values = 0;
2526 for (
unsigned i=0;
i<num_var;
i++) {
2528 num_values += jbuf[
i]->
fValues.size();
2532 size_t p0_size =
sizeof(double)*(2+2*num_var+2*num_values);
2534 size_t size_limit = 1000*1024*1024;
2536 if (p0_size > size_limit) {
2537 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);
2539 for (
size_t i=0;
i<num_var;
i++) {
2545 delete[] event_name;
2555 double* p0 = (
double*)malloc(p0_size);
2558 cm_msg(
MERROR,
"js_hs_read_binned_arraybuffer",
"Cannot allocate return buffer %d bytes\n",
int(p0_size));
2560 for (
size_t i=0;
i<num_var;
i++) {
2566 delete[] event_name;
2573 return mjsonrpc_make_error(-32603,
"Internal error",
"Cannot allocate buffer, too much data");
2597 for (
size_t i=0;
i<num_var;
i++) {
2598 *pptr++ = hs_status[
i];
2601 for (
size_t i=0;
i<num_var;
i++) {
2605 for (
size_t i=0;
i<num_var;
i++) {
2606 size_t nv = jbuf[
i]->
fValues.size();
2607 for (
size_t j=0;
j<nv;
j++) {
2619 assert(p0_size == ((pptr-p0)*
sizeof(
double)));
2621 delete[] event_name;
2628 MJsonNode* result = MJsonNode::MakeArrayBuffer((
char*)p0, p0_size);
2637 doc->
D(
"get history data for given history events that existed at give time using hs_read_buffer()");
2638 doc->
P(
"channel?", MJSON_STRING,
"midas history channel, default is the default reader channel");
2639 doc->
P(
"start_time", MJSON_NUMBER,
"start time of the data");
2640 doc->
P(
"end_time", MJSON_NUMBER,
"end time of the data");
2641 doc->
P(
"num_bins", MJSON_INT,
"number of time bins");
2642 doc->
P(
"events[]", MJSON_STRING,
"array of history event names");
2643 doc->
P(
"tags[]", MJSON_STRING,
"array of history event tag names");
2644 doc->
P(
"index[]", MJSON_STRING,
"array of history event tag array indices");
2645 doc->
R(
"binary data", MJSON_ARRAYBUFFER,
"binary data, see documentation");
2649 MJsonNode* error = NULL;
2652 double start_time =
mjsonrpc_get_param(params,
"start_time", &error)->GetDouble();
if (error)
return error;
2653 double end_time =
mjsonrpc_get_param(params,
"end_time", &error)->GetDouble();
if (error)
return error;
2654 int inum_bins =
mjsonrpc_get_param(params,
"num_bins", &error)->GetInt();
if (error)
return error;
2656 if (inum_bins < 1) {
2657 return mjsonrpc_make_error(-32602,
"Invalid params",
"Value of num_bins should be 1 or more");
2660 size_t num_bins = inum_bins;
2673 size_t num_var = events_array->size();
2676 return mjsonrpc_make_error(-32602,
"Invalid params",
"Array of events should have 1 or more elements");
2679 if (tags_array->size() != num_var) {
2680 return mjsonrpc_make_error(-32602,
"Invalid params",
"Arrays events and tags should have the same length");
2683 if (index_array->size() != num_var) {
2684 return mjsonrpc_make_error(-32602,
"Invalid params",
"Arrays events and index should have the same length");
2687 std::vector<std::string> event_names(num_var);
2688 std::vector<std::string> tag_names(num_var);
2691 int* var_index =
new int[num_var];
2693 int* num_entries =
new int[num_var];
2694 time_t*
last_time =
new time_t[num_var];
2695 double* last_value =
new double[num_var];
2696 int* hs_status =
new int[num_var];
2698 int** count_bins =
new int*[num_var];
2699 double** mean_bins =
new double*[num_var];
2700 double** rms_bins =
new double*[num_var];
2701 double** min_bins =
new double*[num_var];
2702 double** max_bins =
new double*[num_var];
2704 time_t** bins_first_time =
new time_t*[num_var];
2705 time_t** bins_last_time =
new time_t*[num_var];
2707 double** bins_first_value =
new double*[num_var];
2708 double** bins_last_value =
new double*[num_var];
2710 for (
unsigned i=0;
i<num_var;
i++) {
2713 event_names[
i] = (*events_array)[
i]->GetString();
2714 tag_names[
i] = (*tags_array)[
i]->GetString();
2715 var_index[
i] = (*index_array)[
i]->GetInt();
2720 count_bins[
i] =
new int[num_bins];
2721 mean_bins[
i] =
new double[num_bins];
2722 rms_bins[
i] =
new double[num_bins];
2723 min_bins[
i] =
new double[num_bins];
2724 max_bins[
i] =
new double[num_bins];
2725 bins_first_time[
i] =
new time_t[num_bins];
2726 bins_last_time[
i] =
new time_t[num_bins];
2727 bins_first_value[
i] =
new double[num_bins];
2728 bins_last_value[
i] =
new double[num_bins];
2732 printf(
"time %f %f, num_vars %d:\n", start_time, end_time,
int(num_var));
2733 for (
size_t i=0;
i<num_var;
i++) {
2734 printf(
"%d: [%s] [%s] [%d]\n",
int(
i), event_names[
i].c_str(), tag_names[
i].c_str(), var_index[
i]);
2738 const char** event_name =
new const char*[num_var];
2739 const char** tag_name =
new const char*[num_var];
2740 for (
size_t i=0;
i<num_var;
i++) {
2741 event_name[
i] = event_names[
i].c_str();
2742 tag_name[
i] = tag_names[
i].c_str();
2745 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);
2748 size_t p0_size =
sizeof(double)*(5+4*num_var+9*num_var*num_bins);
2750 size_t size_limit = 100*1024*1024;
2752 if (p0_size > size_limit) {
2753 cm_msg(
MERROR,
"js_hs_read_binned_arraybuffer",
"Refusing to return %d bytes. limit is %d bytes\n",
int(p0_size),
int(size_limit));
2755 for (
size_t i=0;
i<num_var;
i++) {
2756 delete count_bins[
i];
2757 delete mean_bins[
i];
2761 delete bins_first_time[
i];
2762 delete bins_first_value[
i];
2763 delete bins_last_time[
i];
2764 delete bins_last_value[
i];
2767 delete[] count_bins;
2773 delete[] bins_first_time;
2774 delete[] bins_first_value;
2775 delete[] bins_last_time;
2776 delete[] bins_last_value;
2778 delete[] event_name;
2782 delete[] num_entries;
2784 delete[] last_value;
2790 double* p0 = (
double*)malloc(p0_size);
2793 cm_msg(
MERROR,
"js_hs_read_binned_arraybuffer",
"Cannot allocate return buffer %d bytes\n",
int(p0_size));
2795 for (
size_t i=0;
i<num_var;
i++) {
2796 delete count_bins[
i];
2797 delete mean_bins[
i];
2801 delete bins_first_time[
i];
2802 delete bins_first_value[
i];
2803 delete bins_last_time[
i];
2804 delete bins_last_value[
i];
2807 delete[] count_bins;
2813 delete[] bins_first_time;
2814 delete[] bins_first_value;
2815 delete[] bins_last_time;
2816 delete[] bins_last_value;
2818 delete[] event_name;
2822 delete[] num_entries;
2824 delete[] last_value;
2827 return mjsonrpc_make_error(-32603,
"Internal error",
"Cannot allocate buffer, too much data");
2866 *pptr++ = start_time;
2871 for (
unsigned i=0;
i<num_var;
i++) {
2872 *pptr++ = hs_status[
i];
2875 for (
unsigned i=0;
i<num_var;
i++) {
2876 *pptr++ = num_entries[
i];
2879 for (
unsigned i=0;
i<num_var;
i++) {
2883 for (
unsigned i=0;
i<num_var;
i++) {
2884 *pptr++ = last_value[
i];
2887 for (
size_t i=0;
i<num_var;
i++) {
2888 for (
size_t j=0;
j<num_bins;
j++) {
2889 *pptr++ = count_bins[
i][
j];
2890 *pptr++ = mean_bins[
i][
j];
2891 *pptr++ = rms_bins[
i][
j];
2892 *pptr++ = min_bins[
i][
j];
2893 *pptr++ = max_bins[
i][
j];
2894 *pptr++ = bins_first_time[
i][
j];
2895 *pptr++ = bins_first_value[
i][
j];
2896 *pptr++ = bins_last_time[
i][
j];
2897 *pptr++ = bins_last_value[
i][
j];
2900 delete count_bins[
i];
2901 delete mean_bins[
i];
2905 delete bins_first_time[
i];
2906 delete bins_first_value[
i];
2907 delete bins_last_time[
i];
2908 delete bins_last_value[
i];
2913 assert(p0_size == ((pptr-p0)*
sizeof(
double)));
2915 delete[] count_bins;
2921 delete[] bins_first_time;
2922 delete[] bins_first_value;
2923 delete[] bins_last_time;
2924 delete[] bins_last_value;
2926 delete[] event_name;
2930 delete[] num_entries;
2932 delete[] last_value;
2935 MJsonNode* result = MJsonNode::MakeArrayBuffer((
char*)p0, p0_size);
2949 doc->
D(
"Get a list of history image files");
2950 doc->
P(
"image?", MJSON_STRING,
"image name as defined under /History/Images/<image>");
2951 doc->
P(
"start_time", MJSON_NUMBER,
"start time of the data");
2952 doc->
P(
"end_time", MJSON_NUMBER,
"end time of the data");
2953 doc->
R(
"time[]", MJSON_ARRAYBUFFER,
"array of time stamps in seconds");
2954 doc->
R(
"filename[]", MJSON_ARRAYBUFFER,
"array of file names");
2958 MJsonNode* error = NULL;
2961 double start_time =
mjsonrpc_get_param(params,
"start_time", &error)->GetDouble();
if (error)
return error;
2962 double end_time =
mjsonrpc_get_param(params,
"end_time", &error)->GetDouble();
if (error)
return error;
2964 std::vector<time_t>vtime{};
2965 std::vector<std::string>vfilename{};
2969 MJsonNode *tj = MJsonNode::MakeArray();
2970 MJsonNode *fj = MJsonNode::MakeArray();
2972 for (
int i=0 ;
i<(int)vtime.size() ;
i++) {
2973 tj->AddToArray(MJsonNode::MakeInt(vtime[
i]));
2975 fj->AddToArray(MJsonNode::MakeString(vfilename[
i].c_str()));
2977 MJsonNode*
data = MJsonNode::MakeObject();
2978 data->AddToObject(
"count", MJsonNode::MakeInt(
count));
2979 data->AddToObject(
"time", tj);
2980 data->AddToObject(
"filename", fj);
2995 doc->
D(
"Get an elog message");
2996 doc->
P(
"tag", MJSON_STRING,
"elog message tag");
2997 doc->
R(
"status", MJSON_INT,
"return status of el_retrieve");
2998 doc->
R(
"msg.tag", MJSON_STRING,
"message tag");
3002 MJsonNode* error = NULL;
3004 std::string tag =
mjsonrpc_get_param(params,
"tag", &error)->GetString();
if (error)
return error;
3007 char date[80], author[80],
type[80], system[80], subject[256], text[10000];
3008 char orig_tag[80], reply_tag[80], attachment[3][256], encoding[80];
3011 strlcpy(xtag, tag.c_str(),
sizeof(xtag));
3013 int size =
sizeof(text);
3016 date, &
run, author,
type, system, subject,
3017 text, &size, orig_tag, reply_tag,
3018 attachment[0], attachment[1], attachment[2], encoding);
3022 MJsonNode* msg = MJsonNode::MakeObject();
3026 msg->AddToObject(
"tag", MJsonNode::MakeString(xtag));
3028 msg->AddToObject(
"date", MJsonNode::MakeString(date));
3029 msg->AddToObject(
"run", MJsonNode::MakeInt(
run));
3031 msg->AddToObject(
"author", MJsonNode::MakeString(author));
3033 msg->AddToObject(
"type", MJsonNode::MakeString(
type));
3035 msg->AddToObject(
"system", MJsonNode::MakeString(system));
3037 msg->AddToObject(
"subject", MJsonNode::MakeString(subject));
3039 msg->AddToObject(
"text", MJsonNode::MakeString(text));
3041 msg->AddToObject(
"orig_tag", MJsonNode::MakeString(orig_tag));
3043 msg->AddToObject(
"reply_tag", MJsonNode::MakeString(reply_tag));
3045 msg->AddToObject(
"attachment0", MJsonNode::MakeString(attachment[0]));
3047 msg->AddToObject(
"attachment1", MJsonNode::MakeString(attachment[1]));
3049 msg->AddToObject(
"attachment2", MJsonNode::MakeString(attachment[2]));
3051 msg->AddToObject(
"encoding", MJsonNode::MakeString(encoding));
3061 doc->
D(
"Query elog messages");
3062 doc->
P(
"last_n_hours?", MJSON_INT,
"return messages from the last N hours");
3063 doc->
R(
"status", MJSON_INT,
"return status of el_retrieve");
3064 doc->
R(
"msg[].tag", MJSON_STRING,
"message tag");
3090 MJsonNode* msg_array = MJsonNode::MakeArray();
3093 char date[80], author[80],
type[80], system[80], subject[256], text[10000],
3094 orig_tag[80], reply_tag[80], attachment[3][256], encoding[80];
3095 char str[256], str2[10000], tag[256];
3099 extern const char *
mname[];
3115 r1 = atoi(pr1.c_str());
3118 r2 = atoi(pr2.c_str());
3120 time_t ltime_start = 0;
3121 time_t ltime_end = 0;
3126 if (py1.length() > 0)
3127 y1 = atoi(py1.c_str());
3129 if (pd1.length() > 0)
3130 d1 = atoi(pd1.c_str());
3133 for (m1 = 0; m1 < 12; m1++)
3139 if (pd2.length() > 0) {
3140 d2 = atoi(pd2.c_str());
3143 if (py2.length() > 0) {
3147 for (m2 = 0; m2 < 12; m2++)
3155 if (py2.length() > 0) {
3156 y2 = atoi(py2.c_str());
3159 if (y2>=0 && m2>=0 && d2>=0) {
3160 memset(&tms, 0,
sizeof(
struct tm));
3161 tms.tm_year = y2 % 100;
3166 if (tms.tm_year < 90)
3178 time_t now = time(NULL);
3179 ltime_start = now - 3600 * last_n;
3181 localtime_r(<ime_start, &tms);
3182 sprintf(tag,
"%02d%02d%02d.0", tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday);
3183 }
else if (r1 > 0) {
3186 }
else if (y1>=0 && m1>=0 && d1>=0) {
3188 sprintf(tag,
"%02d%02d%02d.0", y1 % 100, m1 + 1, d1);
3192 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",
3203 size =
sizeof(text);
3205 text, &size, orig_tag, reply_tag,
3206 attachment[0], attachment[1], attachment[2], encoding);
3208 std::string this_tag = tag;
3212 strlcat(tag,
"+1",
sizeof(tag));
3215 if ((r2 > 0) && (r2 <
run)) {
3220 memset(&tms, 0,
sizeof(
struct tm));
3221 tms.tm_year = (tag[0] -
'0') * 10 + (tag[1] -
'0');
3222 tms.tm_mon = (tag[2] -
'0') * 10 + (tag[3] -
'0') - 1;
3223 tms.tm_mday = (tag[4] -
'0') * 10 + (tag[5] -
'0');
3224 tms.tm_hour = (date[11] -
'0') * 10 + (date[12] -
'0');
3225 tms.tm_min = (date[14] -
'0') * 10 + (date[15] -
'0');
3226 tms.tm_sec = (date[17] -
'0') * 10 + (date[18] -
'0');
3228 if (tms.tm_year < 90)
3236 if (ltime_start > 0)
3237 if (ltime_current < ltime_start)
3241 if (ltime_end > 0) {
3242 if (ltime_current > ltime_end)
3250 if ((psystem.length()>0) && !
equal_ustring(psystem.c_str(), system))
3253 if (pauthor.length()>0) {
3255 for (
i = 0;
i < (int) strlen(
str);
i++)
3258 for (
i = 0;
i < (int) strlen(author) && author[
i] !=
'@';
i++)
3259 str2[
i] = toupper(author[
i]);
3262 if (strstr(str2,
str) == NULL)
3266 if (psubject.length()>0) {
3268 for (
i = 0;
i < (int) strlen(
str);
i++)
3271 for (
i = 0;
i < (int) strlen(subject);
i++)
3272 str2[
i] = toupper(subject[
i]);
3275 if (strstr(str2,
str) == NULL)
3279 if (psubtext.length()>0) {
3281 for (
i = 0;
i < (int) strlen(
str);
i++)
3284 for (
i = 0;
i < (int) strlen(text);
i++)
3285 str2[
i] = toupper(text[
i]);
3288 if (strstr(str2,
str) == NULL)
3294 MJsonNode* msg = MJsonNode::MakeObject();
3297 msg->AddToObject(
"tag", MJsonNode::MakeString(this_tag.c_str()));
3299 msg->AddToObject(
"date", MJsonNode::MakeString(date));
3300 msg->AddToObject(
"run", MJsonNode::MakeInt(
run));
3302 msg->AddToObject(
"author", MJsonNode::MakeString(author));
3304 msg->AddToObject(
"type", MJsonNode::MakeString(
type));
3306 msg->AddToObject(
"system", MJsonNode::MakeString(system));
3308 msg->AddToObject(
"subject", MJsonNode::MakeString(subject));
3310 msg->AddToObject(
"text", MJsonNode::MakeString(text));
3312 msg->AddToObject(
"orig_tag", MJsonNode::MakeString(orig_tag));
3314 msg->AddToObject(
"reply_tag", MJsonNode::MakeString(reply_tag));
3316 msg->AddToObject(
"attachment0", MJsonNode::MakeString(attachment[0]));
3318 msg->AddToObject(
"attachment1", MJsonNode::MakeString(attachment[1]));
3320 msg->AddToObject(
"attachment2", MJsonNode::MakeString(attachment[2]));
3322 msg->AddToObject(
"encoding", MJsonNode::MakeString(encoding));
3324 msg_array->AddToArray(msg);
3336 doc->
D(
"Delete elog message");
3337 doc->
P(
"tag", MJSON_STRING,
"tag of message to delete");
3338 doc->
R(
"status", MJSON_INT,
"return status of el_delete");
3342 MJsonNode* error = NULL;
3343 std::string tag =
mjsonrpc_get_param(params,
"tag", &error)->GetString();
if (error)
return error;
3355 static MJsonNode*
jrpc(
const MJsonNode* params)
3359 doc->
D(
"make RPC call into frontend program via RPC_JRPC");
3360 doc->
P(
"client_name", MJSON_STRING,
"Connect to this MIDAS client, see cm_connect_client()");
3361 doc->
P(
"cmd", MJSON_STRING,
"Command passed to client");
3362 doc->
P(
"args", MJSON_STRING,
"Parameters passed to client as a string, could be JSON encoded");
3363 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.");
3364 doc->
R(
"reply", MJSON_STRING,
"Reply from client as a string, could be JSON encoded");
3365 doc->
R(
"status", MJSON_INT,
"return status of cm_connect_client() and rpc_client_call()");
3369 MJsonNode* error = NULL;
3371 std::string
name =
mjsonrpc_get_param(params,
"client_name", &error)->GetString();
if (error)
return error;
3372 std::string cmd =
mjsonrpc_get_param(params,
"cmd", &error)->GetString();
if (error)
return error;
3373 std::string args =
mjsonrpc_get_param(params,
"args", &error)->GetString();
if (error)
return error;
3374 int max_reply_length =
mjsonrpc_get_param(params,
"max_reply_length", NULL)->GetInt();
3378 int buf_length = 1024;
3380 if (max_reply_length > buf_length)
3381 buf_length = max_reply_length;
3383 char* buf = (
char*)malloc(buf_length);
3408 MJsonNode* reply = MJsonNode::MakeString(buf);
3420 static MJsonNode*
brpc(
const MJsonNode* params)
3424 doc->
D(
"make RPC call into frontend program via RPC_BRPC");
3425 doc->
P(
"client_name", MJSON_STRING,
"Connect to this MIDAS client, see cm_connect_client()");
3426 doc->
P(
"cmd", MJSON_STRING,
"Command passed to client");
3427 doc->
P(
"args", MJSON_STRING,
"Parameters passed to client as a string, could be JSON encoded");
3428 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.");
3429 doc->
R(
"reply", MJSON_STRING,
"Reply from client as a string, could be JSON encoded");
3430 doc->
R(
"status", MJSON_INT,
"return status of cm_connect_client() and rpc_client_call()");
3434 MJsonNode* error = NULL;
3436 std::string
name =
mjsonrpc_get_param(params,
"client_name", &error)->GetString();
if (error)
return error;
3437 std::string cmd =
mjsonrpc_get_param(params,
"cmd", &error)->GetString();
if (error)
return error;
3438 std::string args =
mjsonrpc_get_param(params,
"args", &error)->GetString();
if (error)
return error;
3439 int max_reply_length =
mjsonrpc_get_param(params,
"max_reply_length", NULL)->GetInt();
3443 int buf_length = 1024;
3445 if (max_reply_length > buf_length)
3446 buf_length = max_reply_length;
3448 char* buf = (
char*)malloc(buf_length);
3472 return MJsonNode::MakeArrayBuffer(buf, buf_length);
3485 doc->
D(
"start and stop runs");
3486 doc->
P(
"transition", MJSON_STRING,
"requested transition: TR_START, TR_STOP, TR_PAUSE, TR_RESUME");
3487 doc->
P(
"run_number?", MJSON_INT,
"New run number, value 0 means /runinfo/run_number + 1, default is 0");
3488 doc->
P(
"async_flag?", MJSON_INT,
"Transition type. Default is multithreaded transition TR_MTHREAD");
3489 doc->
P(
"debug_flag?", MJSON_INT,
"See cm_transition(), value 1: trace to stdout, value 2: trace to midas.log");
3490 doc->
R(
"status", MJSON_INT,
"return status of cm_transition()");
3491 doc->
R(
"error_string?", MJSON_STRING,
"return error string from cm_transition()");
3495 MJsonNode* error = NULL;
3497 std::string xtransition =
mjsonrpc_get_param(params,
"transition", &error)->GetString();
if (error)
return error;
3506 if (xtransition ==
"TR_START")
3508 else if (xtransition ==
"TR_STOP")
3510 else if (xtransition ==
"TR_PAUSE")
3512 else if (xtransition ==
"TR_RESUME")
3518 if (async_flag == 0)
3521 char error_str[1024];
3525 MJsonNode* result = MJsonNode::MakeObject();
3527 result->AddToObject(
"status", MJsonNode::MakeInt(
status));
3528 if (strlen(error_str) > 0) {
3530 result->AddToObject(
"error_string", MJsonNode::MakeString(error_str));
3582 printf(
", size %d, serial %d, time %d, event_id %d, trigger_mask %x",
pevent->
data_size,
pevent->
serial_number,
pevent->
time_stamp,
pevent->
event_id,
pevent->
trigger_mask);
3598 s->ReplaceEvent(pevent);
3600 }
else if (
bm_match_event(s->event_id, s->trigger_mask, pevent)) {
3601 s->ReplaceEvent(pevent);
3623 s->ReplaceEvent(pevent);
3647 if (s->pevent->event_id == last_event_id
3648 && s->pevent->trigger_mask == last_trigger_mask
3649 && s->pevent->serial_number == last_serial_number
3650 && s->pevent->time_stamp == last_time_stamp) {
3666 doc->
D(
"read event buffers");
3667 doc->
P(
"buffer_name", MJSON_STRING,
"name of event buffer");
3668 doc->
P(
"event_id?", MJSON_INT,
"requested event id, -1 means any event id");
3669 doc->
P(
"trigger_mask?", MJSON_INT,
"requested trigger mask, -1 means any trigger mask");
3670 doc->
P(
"get_recent?", MJSON_BOOL,
"get last available event that matches this event request");
3671 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]");
3672 doc->
P(
"timeout_millisec?", MJSON_NUMBER,
"how long to wait for an event");
3673 doc->
R(
"binary data", MJSON_ARRAYBUFFER,
"binary event data");
3674 doc->
R(
"status", MJSON_INT,
"return status of bm_open_buffer(), bm_request_event(), bm_set_cache_size(), bm_receive_alloc()");
3678 MJsonNode* error = NULL;
3684 const MJsonNodeVector* last_event_header =
mjsonrpc_get_param(params,
"last_event_header", NULL)->GetArray();
3685 int timeout_millisec =
mjsonrpc_get_param(params,
"timeout_millisec", NULL)->GetInt();
3687 int last_event_id = 0;
3688 int last_trigger_mask = 0;
3689 int last_serial_number = 0;
3690 int last_time_stamp = 0;
3692 if (last_event_header && last_event_header->size() > 0) {
3693 if (last_event_header->size() != 4) {
3694 return mjsonrpc_make_error(-32602,
"Invalid params",
"last_event_header should be an array with 4 elements");
3697 last_event_id = (*last_event_header)[0]->GetInt();
3698 last_trigger_mask = (*last_event_header)[1]->GetInt();
3699 last_serial_number = (*last_event_header)[2]->GetInt();
3700 last_time_stamp = (*last_event_header)[3]->GetInt();
3715 HNDLE buffer_handle = 0;
3723 static std::mutex
gMutex;
3724 std::lock_guard<std::mutex> lock_guard(
gMutex);
3733 MJsonNode* result = MJsonNode::MakeObject();
3734 result->AddToObject(
"status", MJsonNode::MakeInt(
status));
3739 MJsonNode* result = MJsonNode::MakeObject();
3740 result->AddToObject(
"status", MJsonNode::MakeInt(
status));
3746 MJsonNode* result = MJsonNode::MakeObject();
3747 result->AddToObject(
"status", MJsonNode::MakeInt(
status));
3753 if (timeout_millisec <= 0)
3754 timeout_millisec = 100.0;
3757 double end_time = start_time + timeout_millisec/1000.0;
3785 return MJsonNode::MakeArrayBuffer((
char*)pevent,
event_size);
3800 MJsonNode* result = MJsonNode::MakeObject();
3801 result->AddToObject(
"status", MJsonNode::MakeInt(
status));
3815 return MJsonNode::MakeArrayBuffer((
char*)pevent,
event_size);
3818 MJsonNode* result = MJsonNode::MakeObject();
3833 doc->
D(
"get current MIDAS time using ss_millitime()");
3834 doc->
P(NULL, 0,
"there are no input parameters");
3835 doc->
R(NULL, MJSON_INT,
"current value of ss_millitime()");
3852 doc->
D(
"get alarm data");
3853 doc->
P(
"get_all?", MJSON_BOOL,
"get all alarms, even in alarm system not active and alarms not triggered");
3854 doc->
R(
"status", MJSON_INT,
"return status of midas library calls");
3855 doc->
R(
"alarm_system_active", MJSON_BOOL,
"value of ODB \"/Alarms/alarm system active\"");
3856 doc->
R(
"alarms", MJSON_OBJECT,
"alarm data, keyed by alarm name");
3857 doc->
R(
"alarms[].triggered", MJSON_BOOL,
"alarm is triggered");
3858 doc->
R(
"alarms[].active", MJSON_BOOL,
"alarm is enabled");
3859 doc->
R(
"alarms[].class", MJSON_STRING,
"alarm class");
3860 doc->
R(
"alarms[].type", MJSON_INT,
"alarm type AT_xxx");
3861 doc->
R(
"alarms[].bgcolor", MJSON_STRING,
"display background color");
3862 doc->
R(
"alarms[].fgcolor", MJSON_STRING,
"display foreground color");
3863 doc->
R(
"alarms[].message", MJSON_STRING,
"alarm ODB message field");
3864 doc->
R(
"alarms[].condition", MJSON_STRING,
"alarm ODB condition field");
3865 doc->
R(
"alarms[].evaluated_value?", MJSON_STRING,
"evaluated alarm condition (AT_EVALUATED alarms only)");
3866 doc->
R(
"alarms[].periodic_next_time?", MJSON_STRING,
"next time the periodic alarm will fire (AT_PERIODIC alarms only)");
3867 doc->
R(
"alarms[].time_triggered_first", MJSON_STRING,
"time when alarm was triggered");
3868 doc->
R(
"alarms[].show_to_user", MJSON_STRING,
"final alarm text shown to user by mhttpd");
3887 int alarm_system_active = 0;
3891 size =
sizeof(flag);
3898 alarm_system_active = flag;
3900 if (!alarm_system_active)
3903 "alarm_system_active", MJsonNode::MakeBool(alarm_system_active!=0),
3904 "alarms", MJsonNode::MakeObject());
3915 MJsonNode* alarms = MJsonNode::MakeObject();
3917 for (
int i = 0;;
i++) {
3931 size =
sizeof(flag);
3939 MJsonNode* a = MJsonNode::MakeObject();
3941 a->AddToObject(
"triggered", MJsonNode::MakeBool(flag!=0));
3944 size =
sizeof(
BOOL);
3947 a->AddToObject(
"active", MJsonNode::MakeBool(flag!=0));
3950 strcpy(alarm_class,
"Alarm");
3951 size =
sizeof(alarm_class);
3955 a->AddToObject(
"class", MJsonNode::MakeString(alarm_class));
3958 size =
sizeof(atype);
3961 a->AddToObject(
"type", MJsonNode::MakeInt(atype));
3966 strcpy(bgcol,
"red");
3968 if (strlen(alarm_class) > 0) {
3969 sprintf(
str,
"/Alarms/Classes/%s/Display BGColor", alarm_class);
3970 size =
sizeof(bgcol);
3975 a->AddToObject(
"bgcolor", MJsonNode::MakeString(bgcol));
3978 strcpy(fgcol,
"black");
3980 if (strlen(alarm_class) > 0) {
3981 sprintf(
str,
"/Alarms/Classes/%s/Display FGColor", alarm_class);
3982 size =
sizeof(fgcol);
3987 a->AddToObject(
"fgcolor", MJsonNode::MakeString(fgcol));
3995 a->AddToObject(
"message", MJsonNode::MakeString(msg));
3999 size =
sizeof(cond);
4003 a->AddToObject(
"condition", MJsonNode::MakeString(cond));
4005 char show_to_user[256];
4008 char value_str[256];
4012 assert(strlen(value_str) + 1 <
sizeof(value_str));
4014 sprintf(show_to_user, msg, value_str);
4016 assert(strlen(show_to_user) + 1 <
sizeof(show_to_user));
4019 a->AddToObject(
"evaluated_value", MJsonNode::MakeString(value_str));
4021 strlcpy(show_to_user, msg,
sizeof(show_to_user));
4024 a->AddToObject(
"show_to_user", MJsonNode::MakeString(show_to_user));
4031 a->AddToObject(
"time_triggered_first", MJsonNode::MakeString(
str));
4035 size =
sizeof(last);
4044 size =
sizeof(interval);
4047 time_t tnext = last + interval;
4050 ctime_r(&tnext, ctimebuf);
4053 a->AddToObject(
"periodic_next_time", MJsonNode::MakeString(ctimebuf));
4056 alarms->AddToObject(
name, a);
4060 "alarm_system_active", MJsonNode::MakeBool(alarm_system_active!=0),
4074 doc->
D(
"js_make_subdir");
4075 doc->
P(
"subdir", MJSON_STRING,
"Create folder experiment_directory/userfiles/subdir");
4076 doc->
R(
"status", MJSON_INT,
"return status of midas library calls");
4077 doc->
R(
"path", MJSON_STRING,
"Search path");
4081 MJsonNode* error = NULL;
4083 std::string subdir =
mjsonrpc_get_param(params,
"subdir", &error)->GetString();
if (error)
return error;
4086 if (subdir.find(
"..") != std::string::npos) {
4103 path +=
"userfiles";
4106 if (access(path.c_str(), F_OK) != 0) {
4108 if (mkdir(path.c_str(), 0777) != 0) {
4114 if (subdir.length() > 0) {
4121 if (access(path.c_str(), F_OK) != 0) {
4123 if (mkdir(path.c_str(), 0777) != 0) {
4129 MJsonNode* r = MJsonNode::MakeObject();
4130 r->AddToObject(
"status", MJsonNode::MakeInt(
SUCCESS));
4132 r->AddToObject(
"path", MJsonNode::MakeString(path.c_str()));
4140 doc->
D(
"js_ext_list_files");
4141 doc->
P(
"subdir", MJSON_STRING,
"List files in experiment_directory/userfiles/subdir");
4142 doc->
P(
"fileext", MJSON_STRING,
"Filename extension");
4143 doc->
R(
"status", MJSON_INT,
"return status of midas library calls");
4144 doc->
R(
"path", MJSON_STRING,
"Search path");
4145 doc->
R(
"subdirs[]", MJSON_STRING,
"list of subdirectories");
4146 doc->
R(
"files[].filename", MJSON_STRING,
"script filename");
4147 doc->
R(
"files[].description", MJSON_STRING,
"script description");
4151 MJsonNode* error = NULL;
4152 std::string subdir =
mjsonrpc_get_param(params,
"subdir", &error)->GetString();
if (error)
return error;
4153 std::string fileext =
mjsonrpc_get_param(params,
"fileext", &error)->GetString();
if (error)
return error;
4156 if (subdir.find(
"..") != std::string::npos) {
4161 if (fileext.find(
"..") != std::string::npos) {
4189 path +=
"userfiles";
4192 if (access(path.c_str(), F_OK) != 0) {
4194 if (mkdir(path.c_str(), 0777) != 0) {
4199 if (subdir.length() > 0) {
4207 MJsonNode* s = MJsonNode::MakeArray();
4212 for (
int i=0 ;
i<
n ;
i++) {
4220 MJsonNode* f = MJsonNode::MakeArray();
4221 time_t modtime = time(NULL);
4231 for (
int i=0 ;
i<
n ;
i++) {
4233 MJsonNode* o = MJsonNode::MakeObject();
4237 std::string full_name = path;
4242 o->AddToObject(
"description", MJsonNode::MakeString(
"description"));
4244 o->AddToObject(
"modtime", MJsonNode::MakeInt(modtime));
4246 o->AddToObject(
"size", MJsonNode::MakeInt(fsize));
4253 MJsonNode* r = MJsonNode::MakeObject();
4254 r->AddToObject(
"status", MJsonNode::MakeInt(
SUCCESS));
4256 r->AddToObject(
"path", MJsonNode::MakeString(path.c_str()));
4257 r->AddToObject(
"subdirs", s);
4258 r->AddToObject(
"files", f);
4268 doc->
D(
"js_ext_save_file");
4269 doc->
P(
"filename", MJSON_STRING,
"File name, save in experiment_directory/userfiles/filename");
4270 doc->
P(
"script", MJSON_STRING,
"ASCII content");
4271 doc->
R(
"status", MJSON_INT,
"return status of midas library calls");
4272 doc->
R(
"error", MJSON_STRING,
"error text");
4278 MJsonNode* error = NULL;
4279 std::string filename =
mjsonrpc_get_param(params,
"filename", &error)->GetString();
if (error)
return error;
4280 std::string script =
mjsonrpc_get_param(params,
"script", &error)->GetString();
if (error)
return error;
4283 if (filename.find(
"..") != std::string::npos ) {
4302 return mjsonrpc_make_result(
"status", MJsonNode::MakeInt(
status),
"error", MJsonNode::MakeString(
"cm_get_experiment_database() error"));
4306 path +=
"userfiles";
4309 if (access(path.c_str(), F_OK) != 0) {
4311 if (mkdir(path.c_str(), 0777) != 0) {
4319 FILE*
fp = fopen(path.c_str(),
"w");
4323 sprintf(errstr,
"fopen() errno %d (%s)", errno, strerror(errno));
4328 fwrite(script.c_str(), script.length(), 1,
fp);
4334 std::string errstr =
"no error";
4344 doc->
D(
"js_ext_read_script");
4345 doc->
P(
"filename", MJSON_STRING,
"File name, read from experiment_directory/userfiles/filename");
4346 doc->
R(
"content", MJSON_STRING,
"ASCII file content");
4347 doc->
R(
"status", MJSON_INT,
"return status of midas library calls");
4348 doc->
R(
"error", MJSON_STRING,
"error text");
4352 MJsonNode* error = NULL;
4353 std::string filename =
mjsonrpc_get_param(params,
"filename", &error)->GetString();
if (error)
return error;
4356 if (filename.find(
"..") != std::string::npos ||
4357 filename.find(
"*") != std::string::npos) {
4367 return mjsonrpc_make_result(
"status", MJsonNode::MakeInt(
status),
"error", MJsonNode::MakeString(
"cm_get_experiment_database() error"));
4374 path +=
"userfiles";
4377 if (access(path.c_str(), F_OK) != 0) {
4379 if (mkdir(path.c_str(), 0777) != 0) {
4387 FILE*
fp = fopen(path.c_str(),
"r");
4391 sprintf(errstr,
"fopen() errno %d (%s)", errno, strerror(errno));
4396 fseek(
fp, 0, SEEK_END);
4397 size_t file_size = ftell(
fp);
4400 char* buffer =
new char[file_size+1];
4401 fread(buffer, file_size, 1,
fp);
4403 buffer[file_size] =
'\0';
4411 std::string errstr =
"no error";
4413 return mjsonrpc_make_result(
"content", MJsonNode::MakeString(
content.c_str()),
"status", MJsonNode::MakeInt(
status),
"error", MJsonNode::MakeString(errstr.c_str()));
4425 doc->
D(
"js_read_binary_file");
4426 doc->
P(
"filename", MJSON_STRING,
"File name, read from experiment_directory/userfiles/filename");
4427 doc->
R(
"binary data", MJSON_ARRAYBUFFER,
"Binary file content");
4428 doc->
R(
"status", MJSON_INT,
"Return status of midas library calls");
4429 doc->
R(
"error", MJSON_STRING,
"Error text");
4433 MJsonNode* error = NULL;
4435 if (error)
return error;
4438 if (filename.find(
"..") != std::string::npos ||
4439 filename.find(
"*") != std::string::npos) {
4449 return mjsonrpc_make_result(
"status", MJsonNode::MakeInt(
status),
"error", MJsonNode::MakeString(
"cm_get_experiment_database() error"));
4456 path +=
"userfiles";
4459 if (access(path.c_str(), F_OK) != 0) {
4461 if (mkdir(path.c_str(), 0777) != 0) {
4469 FILE*
fp = fopen(path.c_str(),
"rb");
4473 sprintf(errstr,
"fopen() errno %d (%s)", errno, strerror(errno));
4478 fseek(
fp, 0, SEEK_END);
4479 size_t file_size = ftell(
fp);
4482 char* buffer =
new char[file_size];
4483 fread(buffer, file_size, 1,
fp);
4489 std::string errstr =
"no error";
4491 MJsonNode* result = MJsonNode::MakeArrayBuffer(buffer, file_size);
4506 doc->
D(
"get current value of mjsonrpc_debug");
4507 doc->
P(NULL, 0,
"there are no input parameters");
4508 doc->
R(NULL, MJSON_INT,
"current value of mjsonrpc_debug");
4519 doc->
D(
"set new value of mjsonrpc_debug");
4520 doc->
P(NULL, MJSON_INT,
"new value of mjsonrpc_debug");
4521 doc->
R(NULL, MJSON_INT,
"new value of mjsonrpc_debug");
4533 doc->
D(
"get current value of mjsonrpc_sleep");
4534 doc->
P(NULL, 0,
"there are no input parameters");
4535 doc->
R(NULL, MJSON_INT,
"current value of mjsonrpc_sleep");
4546 doc->
D(
"set new value of mjsonrpc_sleep");
4547 doc->
P(NULL, MJSON_INT,
"new value of mjsonrpc_sleep");
4548 doc->
R(NULL, MJSON_INT,
"new value of mjsonrpc_sleep");
4560 doc->
D(
"get current value of mjsonrpc_time");
4561 doc->
P(NULL, 0,
"there are no input parameters");
4562 doc->
R(NULL, MJSON_INT,
"current value of mjsonrpc_time");
4573 doc->
D(
"set new value of mjsonrpc_time");
4574 doc->
P(NULL, MJSON_INT,
"new value of mjsonrpc_time");
4575 doc->
R(NULL, MJSON_INT,
"new value of mjsonrpc_time");
4587 doc->
D(
"Get the MIDAS JSON-RPC schema JSON object");
4588 doc->
P(NULL, 0,
"there are no input parameters");
4589 doc->
R(NULL, MJSON_OBJECT,
"returns the MIDAS JSON-RPC schema JSON object");
4600 doc->
D(
"get current server timezone offset in seconds");
4601 doc->
P(NULL, 0,
"there are no input parameters");
4602 doc->
R(NULL, MJSON_INT,
"offset in seconds");
4607 time_t rawtime = time(NULL);
4609 gmtime_r(&rawtime, &gmt_tms);
4612 localtime_r(&rawtime, &tms);
4613 time_t
offset = rawtime - gmt + (tms.tm_isdst ? 3600 : 0);
4640 e.fHandler = handler;
4641 e.fNeedsLocking = needs_locking;
4647 gMutex = (std::mutex*)mutex;
4653 printf(
"mjsonrpc_init!\n");
4737 printf(
"mjsonrpc_exit!\n");
4746 MJsonNode* s = MJsonNode::MakeObject();
4748 s->AddToObject(
"$schema", MJsonNode::MakeString(
"http://json-schema.org/schema#"));
4749 s->AddToObject(
"id", MJsonNode::MakeString(
"MIDAS JSON-RPC autogenerated schema"));
4750 s->AddToObject(
"title", MJsonNode::MakeString(
"MIDAS JSON-RPC schema"));
4751 s->AddToObject(
"description", MJsonNode::MakeString(
"Autogenerated schema for all MIDAS JSON-RPC methods"));
4752 s->AddToObject(
"type", MJsonNode::MakeString(
"object"));
4754 MJsonNode* m = MJsonNode::MakeObject();
4760 MJsonNode* doc = iterator->second.fHandler(NULL);
4762 doc = MJsonNode::MakeObject();
4763 m->AddToObject(iterator->first.c_str(), doc);
4766 s->AddToObject(
"properties", m);
4767 s->AddToObject(
"required", MJsonNode::MakeArray());
4778 static void mjsonrpc_print_schema()
4782 std::string
str = s->Stringify(1);
4783 printf(
"MJSON-RPC schema:\n");
4784 printf(
"%s\n",
str.c_str());
4789 static std::string
indent(
int x,
const char* p =
" ")
4794 for (
int i=0;
i<x;
i++)
4815 void Output(
int nest,
bool span, std::string text)
4817 if (text.length() < 1)
4829 std::vector<int> tablen;
4830 std::vector<std::string> tab;
4831 std::vector<std::string> tabx;
4833 tablen.push_back(0);
4837 std::string xtab =
"";
4839 for (
int n=0; ;
n++) {
4841 for (
unsigned i=0;
i<
fLines.size();
i++) {
4848 int l =
fLines[
i].text.length();
4855 tablen.push_back(len);
4856 tab.push_back(
indent(len,
" ") +
" | ");
4857 xtab +=
indent(len,
" ") +
" | ";
4858 tabx.push_back(xtab);
4865 for (
unsigned i=0;
i<
fLines.size();
i++) {
4872 int ipad = tablen[
n+1] -
fLines[
i].text.length();
4876 std::string hr =
indent(maxlen-tabx[
n].length(),
"-");
4879 s += std::string(
" | ") +
fLines[
i].text + pad;
4880 else if (
n == nest) {
4882 if (
n == 0 ||
n == 1)
4883 s += tabx[
n] + hr +
"\n";
4884 s += tabx[
n] +
fLines[
i].text + pad;
4887 if (
n == 0 ||
n == 1)
4888 s += tabx[
n] + hr +
"\n";
4889 s += tabx[
n] +
fLines[
i].text + pad;
4903 const MJsonNode*
d = schema->FindObjectNode(
"description");
4908 std::string xshort =
"object";
4912 const MJsonNode* properties = schema->FindObjectNode(
"properties");
4914 const MJsonNodeVector* required_list = NULL;
4915 const MJsonNode* r = schema->FindObjectNode(
"required");
4917 required_list = r->GetArray();
4920 o->
Output(nest_level,
false,
"object");
4925 const MJsonStringVector *names = properties->GetObjectNames();
4926 const MJsonNodeVector *nodes = properties->GetObjectNodes();
4928 if (!names || !nodes) {
4929 o->
Output(nest_level,
false,
"object");
4934 std::string nest =
indent(nest_level * 4);
4938 s += nest +
"<table border=1>\n";
4941 s += nest +
"<tr>\n";
4942 s += nest +
" <td colspan=3>" +
description +
"</td>\n";
4943 s += nest +
"</tr>\n";
4948 for (
unsigned i=0;
i<names->size();
i++) {
4949 std::string
name = (*names)[
i];
4950 const MJsonNode* node = (*nodes)[
i];
4952 bool required =
false;
4954 for (
unsigned j=0;
j<required_list->size();
j++)
4955 if ((*required_list)[
j])
4956 if ((*required_list)[
j]->GetString() ==
name) {
4961 bool is_array =
false;
4962 const MJsonNode*
type = node->FindObjectNode(
"type");
4963 if (
type &&
type->GetString() ==
"array")
4974 s += nest +
"<tr>\n";
4975 s += nest +
" <td>" +
name +
"</td>\n";
4976 s += nest +
" <td>";
4979 s += nest +
"</tr>\n";
4982 s += nest +
"</table>\n";
4989 const MJsonNode*
d = schema->FindObjectNode(
"description");
4994 std::string xshort =
"array";
4998 const MJsonNode* items = schema->FindObjectNode(
"items");
5001 o->
Output(nest_level,
false,
"array");
5006 const MJsonNodeVector *nodes = items->GetArray();
5009 o->
Output(nest_level,
false,
"array");
5014 std::string nest =
indent(nest_level * 4);
5020 s += nest +
"<table border=1>\n";
5023 s += nest +
"<tr>\n";
5025 s += nest +
"</tr>\n";
5030 for (
unsigned i=0;
i<nodes->size();
i++) {
5031 o->
Output(nest_level,
false,
"array of");
5033 s += nest +
"<tr>\n";
5035 s += nest +
"</tr>\n";
5038 s += nest +
"</table>\n";
5049 const MJsonNode* t = schema->FindObjectNode(
"type");
5051 type = t->GetString();
5055 const MJsonNode*
d = schema->FindObjectNode(
"description");
5063 if (
type ==
"object") {
5065 }
else if (
type ==
"array") {
5095 static void add(std::string* s,
const char* text)
5098 if (s->length() > 0)
5106 const MJsonNode* version =
request->FindObjectNode(
"jsonrpc");
5107 const MJsonNode* method =
request->FindObjectNode(
"method");
5108 const MJsonNode* params =
request->FindObjectNode(
"params");
5109 const MJsonNode*
id =
request->FindObjectNode(
"id");
5111 std::string bad =
"";
5114 add(&bad,
"jsonrpc version is missing");
5116 add(&bad,
"method is missing");
5118 add(&bad,
"params is missing");
5120 add(&bad,
"id is missing");
5122 if (version&&version->GetType() != MJSON_STRING)
5123 add(&bad,
"jsonrpc version is not a string");
5124 if (version&&version->GetString() !=
"2.0")
5125 add(&bad,
"jsonrpc version is not 2.0");
5127 if (method&&method->GetType() != MJSON_STRING)
5128 add(&bad,
"method is not a string");
5130 if (bad.length() > 0) {
5132 response->AddToObject(
"jsonrpc", MJsonNode::MakeString(
"2.0"));
5134 response->AddToObject(
"id", id->Copy());
5136 response->AddToObject(
"id", MJsonNode::MakeNull());
5140 printf(
"mjsonrpc: invalid request: reply:\n");
5141 printf(
"%s\n",
response->Stringify().c_str());
5148 double start_time = 0;
5154 const std::string ms = method->GetString();
5155 const char* m = ms.c_str();
5157 MJsonNode* result = NULL;
5161 if (strcmp(m,
"echo") == 0) {
5163 }
else if (strcmp(m,
"error") == 0) {
5165 }
else if (strcmp(m,
"invalid_json") == 0) {
5167 printf(
"mjsonrpc: reply with invalid json\n");
5169 return MJsonNode::MakeJSON(
"this is invalid json data");
5170 }
else if (strcmp(m,
"test_nan_inf") == 0) {
5173 double nan = zero/zero;
5174 double plusinf = one/zero;
5175 double minusinf = -one/zero;
5176 MJsonNode*
n = MJsonNode::MakeArray();
5177 n->AddToArray(MJsonNode::MakeNumber(nan));
5178 n->AddToArray(MJsonNode::MakeNumber(plusinf));
5179 n->AddToArray(MJsonNode::MakeNumber(minusinf));
5181 }
else if (strcmp(m,
"test_arraybuffer") == 0) {
5183 printf(
"mjsonrpc: reply with test arraybuffer data\n");
5186 char* ptr = (
char*)malloc(size);
5187 for (
size_t i=0;
i<size;
i++) {
5190 *((
short*)(ptr+4*2*1)) = 111;
5191 *((
int*)(ptr+4*2*2)) = 1234;
5192 *((
double*)(ptr+4*2*3)) = 3.14;
5193 return MJsonNode::MakeArrayBuffer(ptr, size);
5197 bool lock = s->second.fNeedsLocking;
5200 result = s->second.fHandler(params);
5204 result =
mjsonrpc_make_error(-32601,
"Method not found", (std::string(
"unknown method: ") + ms).c_str());
5209 printf(
"mjsonrpc: handler reply:\n");
5214 double end_time = 0;
5215 double elapsed_time = 0;
5218 elapsed_time = end_time - start_time;
5220 printf(
"request took %.3f seconds, method [%s]\n", elapsed_time, m);
5224 if (result->GetType() == MJSON_ARRAYBUFFER) {
5228 const MJsonNode *nerror = result->FindObjectNode(
"error");
5229 const MJsonNode *nresult = result->FindObjectNode(
"result");
5232 result->DeleteObjectNode(
"result");
5233 }
else if (nresult) {
5234 result->DeleteObjectNode(
"error");
5237 result =
mjsonrpc_make_error(-32603,
"Internal error",
"bad dispatcher reply: no result and no error");
5240 result->AddToObject(
"jsonrpc", MJsonNode::MakeString(
"2.0"));
5243 result->AddToObject(
"id", id->Copy());
5245 result->AddToObject(
"id", MJsonNode::MakeNull());
5249 result->AddToObject(
"elapsed_time", MJsonNode::MakeNumber(elapsed_time));
5252 assert(result != NULL);
5260 MJsonNode *
request = MJsonNode::Parse(post_data);
5265 printf(
"mjsonrpc: request:\n");
5279 if (
request->GetType() == MJSON_ERROR) {
5281 reply->AddToObject(
"jsonrpc", MJsonNode::MakeString(
"2.0"));
5282 reply->AddToObject(
"id", MJsonNode::MakeNull());
5285 printf(
"mjsonrpc: invalid json: reply:\n");
5286 printf(
"%s\n", reply->Stringify().c_str());
5292 }
else if (
request->GetType() == MJSON_OBJECT) {
5296 }
else if (
request->GetType() == MJSON_ARRAY) {
5297 const MJsonNodeVector* a =
request->GetArray();
5299 if (a->size() < 1) {
5300 MJsonNode* reply =
mjsonrpc_make_error(-32600,
"Invalid request",
"batch request array has less than 1 element");
5301 reply->AddToObject(
"jsonrpc", MJsonNode::MakeString(
"2.0"));
5302 reply->AddToObject(
"id", MJsonNode::MakeNull());
5305 printf(
"mjsonrpc: invalid json: reply:\n");
5306 printf(
"%s\n", reply->Stringify().c_str());
5314 MJsonNode* reply = MJsonNode::MakeArray();
5316 for (
unsigned i=0;
i<a->size();
i++) {
5318 reply->AddToArray(r);
5319 if (r->GetType() == MJSON_ARRAYBUFFER) {
5322 reply =
mjsonrpc_make_error(-32600,
"Invalid request",
"MJSON_ARRAYBUFFER return is not permitted for batch requests");
5323 reply->AddToObject(
"jsonrpc", MJsonNode::MakeString(
"2.0"));
5324 reply->AddToObject(
"id", MJsonNode::MakeNull());
5332 MJsonNode* reply =
mjsonrpc_make_error(-32600,
"Invalid request",
"request is not a JSON object or JSON array");
5333 reply->AddToObject(
"jsonrpc", MJsonNode::MakeString(
"2.0"));
5334 reply->AddToObject(
"id", MJsonNode::MakeNull());
5337 printf(
"mjsonrpc: invalid json: reply:\n");
5338 printf(
"%s\n", reply->Stringify().c_str());
void Add(time_t t, double v)
std::vector< double > fValues
std::vector< double > fTimes
void Add(time_t t, double v)
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...
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...
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
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
virtual int hs_clear_cache()=0
clear internal cache, returns HS_SUCCESS
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
void Output(int nest, bool span, std::string text)
std::vector< NestedLine > fLines
INT transition(INT run_number, char *error)
INT al_trigger_class(const char *alarm_class, const char *alarm_message, BOOL first)
BOOL al_evaluate_condition(const char *condition, char *value)
INT al_reset_alarm(const char *alarm_name)
INT al_trigger_alarm(const char *alarm_name, const char *alarm_message, const char *default_class, const char *cond_str, INT type)
INT bm_open_buffer(const char *buffer_name, INT buffer_size, INT *buffer_handle)
INT bm_request_event(HNDLE buffer_handle, short int event_id, short int trigger_mask, INT sampling_type, HNDLE *request_id, EVENT_HANDLER *func)
INT bm_set_cache_size(INT buffer_handle, size_t read_size, size_t write_size)
INT bm_match_event(short int event_id, short int trigger_mask, const EVENT_HEADER *pevent)
INT bm_get_buffer_handle(const char *buffer_name, INT *buffer_handle)
INT bm_receive_event_alloc(INT buffer_handle, EVENT_HEADER **ppevent, int timeout_msec)
INT cm_shutdown(const char *name, BOOL bUnique)
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
INT cm_connect_client(const char *client_name, HNDLE *hConn)
INT cm_transition(INT transition, INT run_number, char *errstr, INT errstr_size, INT async_flag, INT debug_flag)
std::string cm_expand_env(const char *str)
int cm_exec_script(const char *odb_path_to_script)
INT cm_get_path(char *path, int path_size)
INT cm_exist(const char *name, BOOL bUnique)
INT el_search_run(int run, char *return_tag)
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)
INT el_delete_message(const char *tag)
#define DB_NO_MORE_SUBKEYS
MJSO * AddArray(const char *name, const char *description)
void D(const char *description)
void P(const char *name, int mjson_type, const char *description)
MJSO * AddObject(const char *name, const char *description)
static MJSO * MakeArraySchema(const char *description)
MJSO * RA(const char *description)
MJsonNode * mjsonrpc_make_result(MJsonNode *node)
void Add(const char *name, int mjson_type, const char *description)
MJsonNode *() mjsonrpc_handler_t(const MJsonNode *params)
void mjsonrpc_user_init()
void AddToSchema(MJsonNode *s, const char *name)
MJsonNode * mjsonrpc_make_error(int code, const char *message, const char *data)
static MJSO * MakeObjectSchema(const char *description)
MJsonNode * mjsonrpc_get_schema()
void mjsonrpc_set_std_mutex(void *mutex)
const MJsonNode * mjsonrpc_get_param(const MJsonNode *params, const char *name, MJsonNode **error)
std::string mjsonrpc_schema_to_text(const MJsonNode *schema)
void mjsonrpc_add_handler(const char *method, mjsonrpc_handler_t *handler, bool needs_locking)
void R(const char *name, int mjson_type, const char *description)
MJsonNode * mjsonrpc_decode_post_data(const char *post_data)
MJSO * PA(const char *description)
#define MAX_STRING_LENGTH
time_t ss_mktime(struct tm *tms)
INT ss_dirlink_find(const char *path, const char *pattern, char **plist)
time_t ss_file_time(const char *path)
double ss_file_size(const char *path)
INT ss_sleep(INT millisec)
bool ss_repair_utf8(char *string)
INT ss_system(const char *command)
INT ss_file_find(const char *path, const char *pattern, char **plist)
INT cm_msg1(INT message_type, const char *filename, INT line, const char *facility, const char *routine, const char *format,...)
INT EXPRT cm_msg_facilities(STRING_LIST *list)
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
INT cm_msg_retrieve2(const char *facility, time_t t, INT n_message, char **messages, int *num_messages)
BOOL equal_ustring(const char *str1, const char *str2)
INT db_delete_key(HNDLE hDB, HNDLE hKey, BOOL follow_links)
INT db_find_link(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
INT db_get_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, void *data, INT *buf_size, DWORD type, BOOL create)
INT db_reorder_key(HNDLE hDB, HNDLE hKey, INT idx)
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
INT db_copy_json_save(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end)
MJsonNode * db_scl(HNDLE hDB)
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
INT db_copy_json_index(HNDLE hDB, HNDLE hKey, int index, char **buffer, int *buffer_size, int *buffer_end)
INT db_set_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
INT db_enum_link(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
INT db_copy_json_ls(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end)
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)
INT db_set_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type)
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
MJsonNode * db_sor(HNDLE hDB, const char *root_path)
INT db_rename_key(HNDLE hDB, HNDLE hKey, const char *name)
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
INT EXPRT db_resize_string(HNDLE hdb, HNDLE hKeyRoot, const char *key_name, int num_values, int max_string_length)
INT db_set_num_values(HNDLE hDB, HNDLE hKey, INT num_values)
INT db_create_link(HNDLE hDB, HNDLE hKey, const char *link_name, const char *destination)
INT EXPRT db_paste_json_node(HNDLE hDB, HNDLE hKeyRoot, int index, const MJsonNode *node)
INT rpc_client_call(HNDLE hConn, DWORD routine_id,...)
int hs_read_event_list(std::vector< std::string > *pevents)
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)
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)
char buffer_name[NAME_LENGTH]
#define DIR_SEPARATOR_STR
size_t EXPRT strlcat(char *dst, const char *src, size_t size)
std::vector< std::string > STRING_LIST
size_t EXPRT strlcpy(char *dst, const char *src, size_t size)
MidasHistoryInterface * mh
#define message(type, str)
static MJsonNode * js_db_delete(const MJsonNode *params)
static MJsonNode * js_ext_save_file(const MJsonNode *params)
static MJsonNode * xnull(const MJsonNode *params)
static MJsonNode * mjsonrpc_make_schema(MethodsTable *h)
static MJsonNode * js_hs_get_last_written(const MJsonNode *params)
static const EVENT_HEADER * CopyEvent(const EVENT_HEADER *pevent)
static MJsonNode * js_read_binary_file(const MJsonNode *params)
static MJsonNode * js_make_subdir(const MJsonNode *params)
static MJsonNode * js_hs_read_arraybuffer(const MJsonNode *params)
std::map< std::string, MethodsTableEntry > MethodsTable
static MJsonNode * js_el_delete(const MJsonNode *params)
static MJsonNode * js_db_resize_string(const MJsonNode *params)
static MJsonNode * js_db_sor(const MJsonNode *params)
static MJsonNode * js_cm_transition(const MJsonNode *params)
static MJsonNode * jrpc(const MJsonNode *params)
static MJsonNode * js_db_copy(const MJsonNode *params)
static MhiMap gHistoryChannels
static MJsonNode * js_hs_read_binned_arraybuffer(const MJsonNode *params)
static MJsonNode * mjsonrpc_handle_request(const MJsonNode *request)
static std::string mjsonrpc_schema_to_html_array(const MJsonNode *schema, int nest_level, NestedOutput *o)
static MJsonNode * js_cm_msg_facilities(const MJsonNode *params)
static MJsonNode * js_cm_msg_retrieve(const MJsonNode *params)
static MJsonNode * get_debug(const MJsonNode *params)
static void StashEvent(const std::string buffer_name, int event_id, int trigger_mask, const EVENT_HEADER *pevent)
static MJsonNode * js_get_timezone(const MJsonNode *params)
static MJsonNode * js_db_create(const MJsonNode *params)
static MJsonNode * js_db_get_values(const MJsonNode *params)
static MJsonNode * js_db_reorder(const MJsonNode *params)
static MJsonNode * js_db_ls(const MJsonNode *params)
static int parse_array_index_list(const char *method, const char *path, std::vector< unsigned > *list)
static MidasHistoryInterface * GetHistory(const char *name)
const MJsonNodeVector * mjsonrpc_get_param_array(const MJsonNode *params, const char *name, MJsonNode **error)
static MJsonNode * js_bm_receive_event(const MJsonNode *params)
static MJsonNode * set_sleep(const MJsonNode *params)
static MJsonNode * exec_script(const MJsonNode *params)
static MJsonNode * js_hs_image_retrieve(const MJsonNode *params)
static MJsonNode * js_el_retrieve(const MJsonNode *params)
static MJsonNode * js_al_trigger_class(const MJsonNode *params)
static MJsonNode * js_al_trigger_alarm(const MJsonNode *params)
static MJsonNode * get_alarms(const MJsonNode *params)
static std::string mjsonrpc_schema_to_html_anything(const MJsonNode *schema, int nest_level, NestedOutput *o)
static std::string remove(const std::string s, char c)
static MJsonNode * get_time(const MJsonNode *params)
static void DeleteEventStash()
static MJsonNode * js_db_resize(const MJsonNode *params)
static MJsonNode * js_db_rename(const MJsonNode *params)
static MJsonNode * js_ss_millitime(const MJsonNode *params)
static MJsonNode * set_debug(const MJsonNode *params)
MethodsTable::iterator MethodsTableIterator
static MJsonNode * js_ext_list_files(const MJsonNode *params)
static MJsonNode * js_hs_get_active_events(const MJsonNode *params)
static int mjsonrpc_sleep
static void add(std::string *s, const char *text)
std::map< std::string, MidasHistoryInterface * > MhiMap
static MJsonNode * js_cm_exist(const MJsonNode *params)
static MJsonNode * brpc(const MJsonNode *params)
static MJsonNode * js_hs_reopen(const MJsonNode *params)
static std::string mjsonrpc_schema_to_html_object(const MJsonNode *schema, int nest_level, NestedOutput *o)
static std::mutex * gMutex
static MJsonNode * js_cm_shutdown(const MJsonNode *params)
static MJsonNode * get_schema(const MJsonNode *params)
static MJsonNode * js_al_reset_alarm(const MJsonNode *params)
static std::vector< EventStashEntry * > gEventStash
static std::string indent(int x, const char *p=" ")
static MJsonNode * js_hs_get_tags(const MJsonNode *params)
static double GetTimeSec()
static MJsonNode * gNullNode
static MJsonNode * js_hs_read_binned(const MJsonNode *params)
static MJsonNode * js_db_scl(const MJsonNode *params)
static MJsonNode * js_hs_read(const MJsonNode *params)
static MJsonNode * js_db_paste(const MJsonNode *params)
static MJsonNode * js_hs_get_events(const MJsonNode *params)
static std::mutex gEventStashMutex
static MJsonNode * get_sleep(const MJsonNode *params)
static MJsonNode * js_ext_read_file(const MJsonNode *params)
static MJsonNode * set_time(const MJsonNode *params)
static MJsonNode * js_cm_msg1(const MJsonNode *params)
static MethodsTable gMethodsTable
static MJsonNode * js_db_key(const MJsonNode *params)
static MJsonNode * js_el_query(const MJsonNode *params)
static MJsonNode * js_hs_get_channels(const MJsonNode *params)
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 MJsonNode * start_program(const MJsonNode *params)
static void MatchEvent(const std::string buffer_name, const EVENT_HEADER *pevent)
static MJsonNode * js_db_link(const MJsonNode *params)
int gettimeofday(struct timeval *tp, void *tzp)
const EVENT_HEADER * pevent
void ReplaceEvent(const EVENT_HEADER *xpevent)
mjsonrpc_handler_t * fHandler
static te_expr * list(state *s)