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