00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "midas.h"
00013 #include "msystem.h"
00014 #include "strlcpy.h"
00015 #include <assert.h>
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00032
00033
00034
00035
00036
00037
00038
00039
00040 BOOL al_evaluate_condition(char *condition, char *value)
00041 {
00042 HNDLE hDB, hkey;
00043 int i, j, idx, size;
00044 KEY key;
00045 double value1, value2;
00046 char value1_str[256], value2_str[256], str[256], op[3], function[80];
00047 char data[10000];
00048 DWORD dtime;
00049
00050 strcpy(str, condition);
00051 op[1] = op[2] = 0;
00052 value1 = value2 = 0;
00053 idx = 0;
00054
00055
00056 for (i = strlen(str) - 1; i > 0; i--)
00057 if (strchr("<>=!", str[i]) != NULL)
00058 break;
00059 op[0] = str[i];
00060 for (j = 1; str[i + j] == ' '; j++);
00061 strlcpy(value2_str, str + i + j, sizeof(value2_str));
00062 value2 = atof(value2_str);
00063 str[i] = 0;
00064
00065 if (i > 0 && strchr("<>=!", str[i - 1])) {
00066 op[1] = op[0];
00067 op[0] = str[--i];
00068 str[i] = 0;
00069 }
00070
00071 i--;
00072 while (i > 0 && str[i] == ' ')
00073 i--;
00074 str[i + 1] = 0;
00075
00076
00077 function[0] = 0;
00078 if (str[i] == ')') {
00079 str[i--] = 0;
00080 if (strchr(str, '(')) {
00081 *strchr(str, '(') = 0;
00082 strcpy(function, str);
00083 for (i = strlen(str) + 1, j = 0; str[i]; i++, j++)
00084 str[j] = str[i];
00085 str[j] = 0;
00086 i = j - 1;
00087 }
00088 }
00089
00090
00091 if (str[i] == ']') {
00092 str[i--] = 0;
00093 while (i > 0 && isdigit(str[i]))
00094 i--;
00095 idx = atoi(str + i + 1);
00096 str[i] = 0;
00097 }
00098
00099 cm_get_experiment_database(&hDB, NULL);
00100 db_find_key(hDB, 0, str, &hkey);
00101 if (!hkey) {
00102 cm_msg(MERROR, "al_evaluate_condition", "Cannot find key %s to evaluate alarm condition", str);
00103 if (value)
00104 strcpy(value, "unknown");
00105 return FALSE;
00106 }
00107
00108 if (equal_ustring(function, "access")) {
00109
00110 db_get_key_time(hDB, hkey, &dtime);
00111 sprintf(value1_str, "%d", dtime);
00112 value1 = atof(value1_str);
00113 } else {
00114
00115 db_get_key(hDB, hkey, &key);
00116 size = sizeof(data);
00117 db_get_data(hDB, hkey, data, &size, key.type);
00118 db_sprintf(value1_str, data, size, idx, key.type);
00119 value1 = atof(value1_str);
00120 }
00121
00122
00123 if (key.type == TID_BOOL) {
00124 value1 = (value1_str[0] == 'Y' || value1_str[0] == 'y' || value1_str[0] == '1');
00125 value2 = (value2_str[0] == 'Y' || value2_str[0] == 'y' || value2_str[0] == '1');
00126 }
00127
00128
00129 if (value)
00130 strcpy(value, value1_str);
00131
00132
00133 if (strcmp(op, "=") == 0)
00134 return value1 == value2;
00135 if (strcmp(op, "==") == 0)
00136 return value1 == value2;
00137 if (strcmp(op, "!=") == 0)
00138 return value1 != value2;
00139 if (strcmp(op, "<") == 0)
00140 return value1 < value2;
00141 if (strcmp(op, ">") == 0)
00142 return value1 > value2;
00143 if (strcmp(op, "<=") == 0)
00144 return value1 <= value2;
00145 if (strcmp(op, ">=") == 0)
00146 return value1 >= value2;
00147
00148 return FALSE;
00149 }
00150
00151
00152 #endif
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 INT al_trigger_alarm(char *alarm_name, char *alarm_message, char *default_class, char *cond_str, INT type)
00177 {
00178 if (rpc_is_remote())
00179 return rpc_call(RPC_AL_TRIGGER_ALARM, alarm_name, alarm_message, default_class, cond_str, type);
00180
00181 #ifdef LOCAL_ROUTINES
00182 {
00183 int status, size;
00184 HNDLE hDB, hkeyalarm;
00185 char str[256];
00186 ALARM a;
00187 BOOL flag;
00188 ALARM_ODB_STR(alarm_odb_str);
00189
00190 cm_get_experiment_database(&hDB, NULL);
00191
00192
00193 flag = TRUE;
00194 size = sizeof(flag);
00195 db_get_value(hDB, 0, "/Runinfo/Online Mode", &flag, &size, TID_INT, TRUE);
00196 if (!flag)
00197 return AL_SUCCESS;
00198
00199
00200 sprintf(str, "/Alarms/Alarms/%s", alarm_name);
00201 db_find_key(hDB, 0, str, &hkeyalarm);
00202 if (!hkeyalarm) {
00203
00204 status = db_create_record(hDB, 0, str, strcomb(alarm_odb_str));
00205 db_find_key(hDB, 0, str, &hkeyalarm);
00206 if (!hkeyalarm) {
00207 cm_msg(MERROR, "al_trigger_alarm", "Cannot create alarm record");
00208 return AL_ERROR_ODB;
00209 }
00210
00211 if (default_class && default_class[0])
00212 db_set_value(hDB, hkeyalarm, "Alarm Class", default_class, 32, 1, TID_STRING);
00213 status = TRUE;
00214 db_set_value(hDB, hkeyalarm, "Active", &status, sizeof(status), 1, TID_BOOL);
00215 }
00216
00217
00218 if (type != AT_EVALUATED && type != AT_PERIODIC) {
00219 db_set_value(hDB, hkeyalarm, "Type", &type, sizeof(INT), 1, TID_INT);
00220 strcpy(str, cond_str);
00221 db_set_value(hDB, hkeyalarm, "Condition", str, 256, 1, TID_STRING);
00222 }
00223
00224 size = sizeof(a);
00225 status = db_get_record(hDB, hkeyalarm, &a, &size, 0);
00226 if (status != DB_SUCCESS || a.type < 1 || a.type > AT_LAST) {
00227
00228 db_check_record(hDB, hkeyalarm, "", strcomb(alarm_odb_str), TRUE);
00229
00230 size = sizeof(a);
00231 status = db_get_record(hDB, hkeyalarm, &a, &size, 0);
00232 if (status != DB_SUCCESS) {
00233 cm_msg(MERROR, "al_trigger_alarm", "Cannot get alarm record");
00234 return AL_ERROR_ODB;
00235 }
00236 }
00237
00238
00239 if (a.type != AT_EVALUATED && a.type != AT_PERIODIC) {
00240
00241 flag = TRUE;
00242 size = sizeof(flag);
00243 db_get_value(hDB, 0, "/Alarms/Alarm system active", &flag, &size, TID_BOOL, TRUE);
00244 if (!flag)
00245 return AL_SUCCESS;
00246
00247 if (!a.active)
00248 return AL_SUCCESS;
00249
00250 if ((INT) ss_time() - (INT) a.checked_last < a.check_interval)
00251 return AL_SUCCESS;
00252
00253
00254 a.checked_last = ss_time();
00255 }
00256
00257
00258 if (a.type != AT_EVALUATED && a.type != AT_PERIODIC) {
00259 strncpy(a.alarm_message, alarm_message, 79);
00260 a.alarm_message[79] = 0;
00261 }
00262
00263
00264 if (a.alarm_class[0])
00265 al_trigger_class(a.alarm_class, alarm_message, a.triggered > 0);
00266
00267
00268 cm_asctime(str, sizeof(str));
00269
00270 if (!a.triggered)
00271 strcpy(a.time_triggered_first, str);
00272
00273 a.triggered++;
00274 strcpy(a.time_triggered_last, str);
00275
00276 a.checked_last = ss_time();
00277
00278 status = db_set_record(hDB, hkeyalarm, &a, sizeof(a), 0);
00279 if (status != DB_SUCCESS) {
00280 cm_msg(MERROR, "al_trigger_alarm", "Cannot update alarm record");
00281 return AL_ERROR_ODB;
00282 }
00283
00284 }
00285 #endif
00286
00287 return AL_SUCCESS;
00288 }
00289
00290
00291 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00292
00293
00294 INT al_trigger_class(char *alarm_class, char *alarm_message, BOOL first)
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 {
00316 int status, size, state;
00317 HNDLE hDB, hkeyclass;
00318 char str[256], command[256], tag[32], url[256];
00319 ALARM_CLASS ac;
00320
00321 cm_get_experiment_database(&hDB, NULL);
00322
00323
00324 sprintf(str, "/Alarms/Classes/%s", alarm_class);
00325 db_find_key(hDB, 0, str, &hkeyclass);
00326 if (!hkeyclass) {
00327 cm_msg(MERROR, "al_trigger_class", "Alarm class %s not found in ODB", alarm_class);
00328 return AL_INVALID_NAME;
00329 }
00330
00331 size = sizeof(ac);
00332 status = db_get_record(hDB, hkeyclass, &ac, &size, 0);
00333 if (status != DB_SUCCESS) {
00334 cm_msg(MERROR, "al_trigger_class", "Cannot get alarm class record");
00335 return AL_ERROR_ODB;
00336 }
00337
00338
00339 if (ac.write_system_message && (INT) ss_time() - (INT) ac.system_message_last > ac.system_message_interval) {
00340 sprintf(str, "%s: %s", alarm_class, alarm_message);
00341 cm_msg(MTALK, "al_trigger_class", str);
00342 ac.system_message_last = ss_time();
00343 }
00344
00345
00346 size = sizeof(url);
00347 if (ac.write_elog_message && first &&
00348 db_get_value(hDB, 0, "/Elog/URL", url, &size, TID_STRING, FALSE) != DB_SUCCESS)
00349 el_submit(0, "Alarm system", "Alarm", "General", alarm_class, str,
00350 "", "plain", "", "", 0, "", "", 0, "", "", 0, tag, 32);
00351
00352
00353 if (ac.execute_command[0] &&
00354 ac.execute_interval > 0 && (INT) ss_time() - (INT) ac.execute_last > ac.execute_interval) {
00355 sprintf(str, "%s: %s", alarm_class, alarm_message);
00356 sprintf(command, ac.execute_command, str);
00357 cm_msg(MINFO, "al_trigger_class", "Execute: %s", command);
00358 ss_system(command);
00359 ac.execute_last = ss_time();
00360 }
00361
00362
00363 if (ac.stop_run) {
00364 state = STATE_STOPPED;
00365 size = sizeof(state);
00366 db_get_value(hDB, 0, "/Runinfo/State", &state, &size, TID_INT, TRUE);
00367 if (state != STATE_STOPPED)
00368 cm_transition(TR_STOP, 0, NULL, 0, ASYNC, FALSE);
00369 }
00370
00371 status = db_set_record(hDB, hkeyclass, &ac, sizeof(ac), 0);
00372 if (status != DB_SUCCESS) {
00373 cm_msg(MERROR, "al_trigger_class", "Cannot update alarm class record");
00374 return AL_ERROR_ODB;
00375 }
00376
00377 return AL_SUCCESS;
00378 }
00379
00380
00381 #endif
00382
00383
00384
00385
00386
00387
00388
00389
00390 INT al_reset_alarm(char *alarm_name)
00391 {
00392 int status, size, i;
00393 HNDLE hDB, hkeyalarm, hkeyclass, hsubkey;
00394 KEY key;
00395 char str[256];
00396 ALARM a;
00397 ALARM_CLASS ac;
00398
00399 cm_get_experiment_database(&hDB, NULL);
00400
00401 if (alarm_name == NULL) {
00402
00403 db_find_key(hDB, 0, "/Alarms/Alarms", &hkeyalarm);
00404 if (hkeyalarm) {
00405 for (i = 0;; i++) {
00406 db_enum_link(hDB, hkeyalarm, i, &hsubkey);
00407
00408 if (!hsubkey)
00409 break;
00410
00411 db_get_key(hDB, hsubkey, &key);
00412 al_reset_alarm(key.name);
00413 }
00414 }
00415 return AL_SUCCESS;
00416 }
00417
00418
00419 sprintf(str, "/Alarms/Alarms/%s", alarm_name);
00420 db_find_key(hDB, 0, str, &hkeyalarm);
00421 if (!hkeyalarm) {
00422 cm_msg(MERROR, "al_reset_alarm", "Alarm %s not found in ODB", alarm_name);
00423 return AL_INVALID_NAME;
00424 }
00425
00426 size = sizeof(a);
00427 status = db_get_record(hDB, hkeyalarm, &a, &size, 0);
00428 if (status != DB_SUCCESS) {
00429 cm_msg(MERROR, "al_reset_alarm", "Cannot get alarm record");
00430 return AL_ERROR_ODB;
00431 }
00432
00433 sprintf(str, "/Alarms/Classes/%s", a.alarm_class);
00434 db_find_key(hDB, 0, str, &hkeyclass);
00435 if (!hkeyclass) {
00436 cm_msg(MERROR, "al_reset_alarm", "Alarm class %s not found in ODB", a.alarm_class);
00437 return AL_INVALID_NAME;
00438 }
00439
00440 size = sizeof(ac);
00441 status = db_get_record(hDB, hkeyclass, &ac, &size, 0);
00442 if (status != DB_SUCCESS) {
00443 cm_msg(MERROR, "al_reset_alarm", "Cannot get alarm class record");
00444 return AL_ERROR_ODB;
00445 }
00446
00447 if (a.triggered) {
00448 a.triggered = 0;
00449 a.time_triggered_first[0] = 0;
00450 a.time_triggered_last[0] = 0;
00451 a.checked_last = 0;
00452
00453 ac.system_message_last = 0;
00454 ac.execute_last = 0;
00455
00456 status = db_set_record(hDB, hkeyalarm, &a, sizeof(a), 0);
00457 if (status != DB_SUCCESS) {
00458 cm_msg(MERROR, "al_reset_alarm", "Cannot update alarm record");
00459 return AL_ERROR_ODB;
00460 }
00461 status = db_set_record(hDB, hkeyclass, &ac, sizeof(ac), 0);
00462 if (status != DB_SUCCESS) {
00463 cm_msg(MERROR, "al_reset_alarm", "Cannot update alarm class record");
00464 return AL_ERROR_ODB;
00465 }
00466 return AL_RESET;
00467 }
00468
00469 return AL_SUCCESS;
00470 }
00471
00472
00473
00474
00475
00476
00477
00478 INT al_check()
00479 {
00480 if (rpc_is_remote())
00481 return rpc_call(RPC_AL_CHECK);
00482
00483 #ifdef LOCAL_ROUTINES
00484 {
00485 INT i, status, size, mutex;
00486 HNDLE hDB, hkeyroot, hkey;
00487 KEY key;
00488 ALARM a;
00489 char str[256], value[256];
00490 time_t now;
00491 PROGRAM_INFO program_info;
00492 BOOL flag;
00493
00494 ALARM_CLASS_STR(alarm_class_str);
00495 ALARM_ODB_STR(alarm_odb_str);
00496 ALARM_PERIODIC_STR(alarm_periodic_str);
00497
00498 cm_get_experiment_database(&hDB, NULL);
00499
00500 if (hDB == 0)
00501 return AL_SUCCESS;
00502
00503
00504 flag = TRUE;
00505 size = sizeof(flag);
00506 db_get_value(hDB, 0, "/Runinfo/Online Mode", &flag, &size, TID_INT, TRUE);
00507 if (!flag)
00508 return AL_SUCCESS;
00509
00510
00511 flag = TRUE;
00512 size = sizeof(flag);
00513 db_get_value(hDB, 0, "/Alarms/Alarm system active", &flag, &size, TID_BOOL, TRUE);
00514 if (!flag)
00515 return AL_SUCCESS;
00516
00517
00518 cm_get_experiment_mutex(&mutex, NULL, NULL, NULL);
00519 status = ss_mutex_wait_for(mutex, 100);
00520 if (status != SS_SUCCESS)
00521 return SUCCESS;
00522
00523
00524 db_find_key(hDB, 0, "/Alarms/Alarms", &hkeyroot);
00525 if (!hkeyroot) {
00526
00527 status = db_create_record(hDB, 0, "/Alarms/Alarms/Demo ODB", strcomb(alarm_odb_str));
00528 db_find_key(hDB, 0, "/Alarms/Alarms", &hkeyroot);
00529 if (!hkeyroot) {
00530 ss_mutex_release(mutex);
00531 return SUCCESS;
00532 }
00533
00534 status = db_create_record(hDB, 0, "/Alarms/Alarms/Demo periodic", strcomb(alarm_periodic_str));
00535 db_find_key(hDB, 0, "/Alarms/Alarms", &hkeyroot);
00536 if (!hkeyroot) {
00537 ss_mutex_release(mutex);
00538 return SUCCESS;
00539 }
00540
00541
00542 status = db_create_record(hDB, 0, "/Alarms/Classes/Alarm", strcomb(alarm_class_str));
00543 status = db_create_record(hDB, 0, "/Alarms/Classes/Warning", strcomb(alarm_class_str));
00544 if (status != DB_SUCCESS) {
00545 ss_mutex_release(mutex);
00546 return SUCCESS;
00547 }
00548 }
00549
00550 for (i = 0;; i++) {
00551 status = db_enum_key(hDB, hkeyroot, i, &hkey);
00552 if (status == DB_NO_MORE_SUBKEYS)
00553 break;
00554
00555 db_get_key(hDB, hkey, &key);
00556
00557 size = sizeof(a);
00558 status = db_get_record(hDB, hkey, &a, &size, 0);
00559 if (status != DB_SUCCESS || a.type < 1 || a.type > AT_LAST) {
00560
00561 db_check_record(hDB, hkey, "", strcomb(alarm_odb_str), TRUE);
00562 size = sizeof(a);
00563 status = db_get_record(hDB, hkey, &a, &size, 0);
00564 if (status != DB_SUCCESS || a.type < 1 || a.type > AT_LAST) {
00565 cm_msg(MERROR, "al_check", "Cannot get alarm record");
00566 continue;
00567 }
00568 }
00569
00570
00571 if (a.active &&
00572 a.type == AT_PERIODIC &&
00573 a.check_interval > 0 && (INT) ss_time() - (INT) a.checked_last > a.check_interval) {
00574
00575 if (a.checked_last == 0) {
00576 a.checked_last = ss_time();
00577 db_set_record(hDB, hkey, &a, size, 0);
00578 } else
00579 al_trigger_alarm(key.name, a.alarm_message, a.alarm_class, "", AT_PERIODIC);
00580 }
00581
00582
00583 if (a.active &&
00584 a.type == AT_EVALUATED &&
00585 a.check_interval > 0 && (INT) ss_time() - (INT) a.checked_last > a.check_interval) {
00586
00587 if (al_evaluate_condition(a.condition, value)) {
00588 sprintf(str, a.alarm_message, value);
00589 al_trigger_alarm(key.name, str, a.alarm_class, "", AT_EVALUATED);
00590 } else {
00591 a.checked_last = ss_time();
00592 status = db_set_record(hDB, hkey, &a, sizeof(a), 0);
00593 if (status != DB_SUCCESS) {
00594 cm_msg(MERROR, "al_check", "Cannot write back alarm record");
00595 continue;
00596 }
00597 }
00598 }
00599 }
00600
00601
00602 db_find_key(hDB, 0, "/Programs", &hkeyroot);
00603 if (hkeyroot) {
00604 for (i = 0;; i++) {
00605 status = db_enum_key(hDB, hkeyroot, i, &hkey);
00606 if (status == DB_NO_MORE_SUBKEYS)
00607 break;
00608
00609 db_get_key(hDB, hkey, &key);
00610
00611
00612 if (key.type != TID_KEY)
00613 continue;
00614
00615 size = sizeof(program_info);
00616 status = db_get_record(hDB, hkey, &program_info, &size, 0);
00617 if (status != DB_SUCCESS) {
00618 cm_msg(MERROR, "al_check", "Cannot get program info record");
00619 continue;
00620 }
00621
00622 now = ss_time();
00623
00624 rpc_get_name(str);
00625 str[strlen(key.name)] = 0;
00626 if (!equal_ustring(str, key.name) && cm_exist(key.name, FALSE) == CM_NO_CLIENT) {
00627 if (program_info.first_failed == 0)
00628 program_info.first_failed = (DWORD) now;
00629
00630
00631 if (now - program_info.first_failed >= program_info.check_interval / 1000) {
00632
00633 if (program_info.alarm_class[0]) {
00634 sprintf(str, "Program %s is not running", key.name);
00635 al_trigger_alarm(key.name, str, program_info.alarm_class,
00636 "Program not running", AT_PROGRAM);
00637 }
00638
00639
00640 if (program_info.auto_restart && program_info.start_command[0]) {
00641 ss_system(program_info.start_command);
00642 program_info.first_failed = 0;
00643 cm_msg(MTALK, "al_check", "Program %s restarted", key.name);
00644 }
00645 }
00646 } else
00647 program_info.first_failed = 0;
00648
00649 db_set_record(hDB, hkey, &program_info, sizeof(program_info), 0);
00650 }
00651 }
00652
00653 ss_mutex_release(mutex);
00654 }
00655 #endif
00656
00657 return SUCCESS;
00658 }
00659
00660
00661
00662
00663