MIDAS
Loading...
Searching...
No Matches
Midas Alarm Functions (al_xxx)

Functions

BOOL al_evaluate_condition (const char *alarm_name, const char *condition, std::string *pvalue)
 
INT al_trigger_alarm (const char *alarm_name, const char *alarm_message, const char *default_class, const char *cond_str, INT type)
 
INT al_trigger_class (const char *alarm_class, const char *alarm_message, BOOL first)
 
INT al_reset_alarm (const char *alarm_name)
 
INT al_check ()
 
INT al_get_alarms (std::string *presult)
 
INT EXPRT al_define_odb_alarm (const char *name, const char *condition, const char *aclass, const char *message)
 

Detailed Description

dox


Function Documentation

◆ al_check()

INT al_check ( void  )

Scan ODB for alarms.

Returns
AL_SUCCESS

Definition at line 612 of file alarm.cxx.

612 {
613 if (rpc_is_remote()) {
614 return rpc_call(RPC_AL_CHECK);
615 }
616
617#ifdef LOCAL_ROUTINES
618 {
619 INT status, size, semaphore;
620 HNDLE hDB, hkeyroot, hkey;
621 KEY key;
622 //char str[256];
623 PROGRAM_INFO_STR(program_info_str);
624 PROGRAM_INFO program_info;
625 BOOL flag;
626
627 ALARM_ODB_STR(alarm_odb_str);
628 ALARM_PERIODIC_STR(alarm_periodic_str);
629
631
632 if (hDB == 0)
633 return AL_SUCCESS; /* called from server not yet connected */
634
635 /* check online mode */
636 flag = TRUE;
637 size = sizeof(flag);
638 db_get_value(hDB, 0, "/Runinfo/Online Mode", &flag, &size, TID_INT, TRUE);
639 if (!flag)
640 return AL_SUCCESS;
641
642 /* check global alarm flag */
643 flag = TRUE;
644 size = sizeof(flag);
645 db_get_value(hDB, 0, "/Alarms/Alarm system active", &flag, &size, TID_BOOL, TRUE);
646 if (!flag)
647 return AL_SUCCESS;
648
649 /* request semaphore */
650 cm_get_experiment_semaphore(&semaphore, NULL, NULL, NULL);
651 status = ss_semaphore_wait_for(semaphore, 100);
652 if (status == SS_TIMEOUT)
653 return AL_SUCCESS; /* someone else is doing alarm business */
654 if (status != SS_SUCCESS) {
655 fprintf(stderr, "al_check: Something is wrong with our semaphore, ss_semaphore_wait_for() returned %d, aborting.\n", status);
656 // abort(); // DOES NOT RETURN
657 // NOT REACHED
658 fprintf(stderr, "al_check: Cannot abort - this will lock you out of odb. From this point, MIDAS will not work correctly. Please read the discussion at https://midas.triumf.ca/elog/Midas/945\n");
659 return AL_SUCCESS;
660 }
661
662 /* check ODB alarms */
663 db_find_key(hDB, 0, "/Alarms/Alarms", &hkeyroot);
664 if (!hkeyroot) {
665 /* create default ODB alarm */
666 status = db_create_record(hDB, 0, "/Alarms/Alarms/Demo ODB", strcomb1(alarm_odb_str).c_str());
667
668 db_find_key(hDB, 0, "/Alarms/Alarms", &hkeyroot);
669 if (!hkeyroot) {
670 ss_semaphore_release(semaphore);
671 return AL_SUCCESS;
672 }
673
674 status = db_create_record(hDB, 0, "/Alarms/Alarms/Demo periodic", strcomb1(alarm_periodic_str).c_str());
675
676 db_find_key(hDB, 0, "/Alarms/Alarms", &hkeyroot);
677 if (!hkeyroot) {
678 ss_semaphore_release(semaphore);
679 return AL_SUCCESS;
680 }
681
682 /* create default alarm classes */
683 midas::odb alarm = {
684 {"Write system message", true},
685 {"Write Elog message", false},
686 {"System message interval", 60},
687 {"System message last", (uint32_t)0},
688 {"Execute command", ""},
689 {"Execute interval", 0},
690 {"Execute last", (uint32_t)0},
691 {"Stop run", false},
692 {"Display BGColor", "red"},
693 {"Display FGColor", "black"},
694 {"Alarm sound", true}
695 };
696 auto warning = alarm;
697 alarm.connect("/Alarms/Classes/Alarm");
698 warning["Display BGColor"] = "yellow";
699 warning.connect("/Alarms/Classes/Warning");
700 std::cout << warning << std::endl;
701 }
702
703 for (int i = 0;; i++) {
704 ALARM a;
705
706 status = db_enum_key(hDB, hkeyroot, i, &hkey);
708 break;
709
710 db_get_key(hDB, hkey, &key);
711
712 size = sizeof(a);
713 status = db_get_record1(hDB, hkey, &a, &size, 0, strcomb1(alarm_odb_str).c_str());
714 if (status != DB_SUCCESS || a.type < 1 || a.type > AT_LAST) {
715 /* make sure alarm record has right structure */
716 db_check_record(hDB, hkey, "", strcomb1(alarm_odb_str).c_str(), TRUE);
717 size = sizeof(a);
718 status = db_get_record1(hDB, hkey, &a, &size, 0, strcomb1(alarm_odb_str).c_str());
719 if (status != DB_SUCCESS || a.type < 1 || a.type > AT_LAST) {
720 cm_msg(MERROR, "al_check", "Cannot get alarm record");
721 continue;
722 }
723 }
724
725 /* check periodic alarm only when active */
726 if (a.active && a.type == AT_PERIODIC && a.check_interval > 0 && (INT) ss_time() - (INT) a.checked_last > a.check_interval) {
727 /* if checked_last has not been set, set it to current time */
728 if (a.checked_last == 0) {
729 a.checked_last = ss_time();
730 db_set_record(hDB, hkey, &a, size, 0);
731 } else
733 }
734
735 /* check alarm only when active and not internal */
736 if (a.active && a.type == AT_EVALUATED && a.check_interval > 0 && (INT) ss_time() - (INT) a.checked_last > a.check_interval) {
737 /* if condition is true, trigger alarm */
738 std::string value;
740 a.checked_last = ss_time();
741 status = db_set_value(hDB, hkey, "Checked last", &a.checked_last, sizeof(DWORD), 1, TID_DWORD);
742 if (status != DB_SUCCESS) {
743 cm_msg(MERROR, "al_check", "Cannot change alarm record");
744 continue;
745 }
746 a.trigger_count++;
747 status = db_set_value(hDB, hkey, "Trigger count", &a.trigger_count, sizeof(DWORD), 1, TID_DWORD);
748 if (status != DB_SUCCESS) {
749 cm_msg(MERROR, "al_check", "Cannot change alarm record");
750 continue;
751 }
753 a.trigger_count = 0;
754 status = db_set_value(hDB, hkey, "Trigger count", &a.trigger_count, sizeof(DWORD), 1, TID_DWORD);
755 if (status != DB_SUCCESS) {
756 cm_msg(MERROR, "al_check", "Cannot change alarm record");
757 continue;
758 }
759
760 std::string str = msprintf(a.alarm_message, value.c_str());
761 if (a.trigger_count_required > 0)
762 str += " (for more than " + std::to_string(a.trigger_count_required) + "*" +
763 std::to_string(a.check_interval) + " seconds)";
765 }
766 } else {
767 a.checked_last = ss_time();
768 status = db_set_value(hDB, hkey, "Checked last", &a.checked_last, sizeof(DWORD), 1, TID_DWORD);
769 if (status != DB_SUCCESS) {
770 cm_msg(MERROR, "al_check", "Cannot change alarm record");
771 continue;
772 }
773 a.trigger_count = 0;
774 status = db_set_value(hDB, hkey, "Trigger count", &a.trigger_count, sizeof(DWORD), 1, TID_DWORD);
775 if (status != DB_SUCCESS) {
776 cm_msg(MERROR, "al_check", "Cannot change alarm record");
777 continue;
778 }
779 }
780 }
781 }
782
783 /* check /programs alarms */
784 db_find_key(hDB, 0, "/Programs", &hkeyroot);
785 if (hkeyroot) {
786 for (int i = 0;; i++) {
787 status = db_enum_key(hDB, hkeyroot, i, &hkey);
789 break;
790
791 db_get_key(hDB, hkey, &key);
792
793 /* don't check "execute on xxx" */
794 if (key.type != TID_KEY)
795 continue;
796
797 size = sizeof(program_info);
798 status = db_get_record1(hDB, hkey, &program_info, &size, 0, strcomb1(program_info_str).c_str());
799 if (status != DB_SUCCESS) {
800 cm_msg(MERROR, "al_check",
801 "Cannot get program info record for program \"%s\", db_get_record1() status %d", key.name,
802 status);
803 continue;
804 }
805
806 time_t now = ss_time();
807
808 // get name of this client
809 std::string name = rpc_get_name();
810 std::string str = name;
811
812 // truncate name of this client to the length of program name in /Programs/xxx
813 // to get rid if "odbedit1", "odbedit2", etc.
814 str.resize(strlen(key.name));
815
816 //printf("str [%s], key.name [%s]\n", str.c_str(), key.name);
817
818 if (!equal_ustring(str.c_str(), key.name) && cm_exist(key.name, FALSE) == CM_NO_CLIENT) {
819 if (program_info.first_failed == 0) {
820 program_info.first_failed = (DWORD) now;
821 db_set_record(hDB, hkey, &program_info, sizeof(program_info), 0);
822 }
823
824 // printf("check %d-%d = %d >= %d\n", now, program_info.first_failed, now - program_info.first_failed,
825 // program_info.check_interval / 1000);
826
827 /* fire alarm when not running for more than what specified in check interval */
828 if (now - program_info.first_failed >= program_info.check_interval / 1000) {
829 /* if not running and alarm class defined, trigger alarm */
830 if (program_info.alarm_class[0]) {
831 std::string str = msprintf("Program %s is not running", key.name);
832 al_trigger_alarm(key.name, str.c_str(), program_info.alarm_class, "Program not running", AT_PROGRAM);
833 }
834
835 /* auto restart program */
836 if (program_info.auto_restart && program_info.start_command[0]) {
837 ss_system(program_info.start_command);
838 program_info.first_failed = 0;
839 cm_msg(MTALK, "al_check", "Program %s restarted", key.name);
840 }
841 }
842 } else {
843 if (program_info.first_failed != 0) {
844 program_info.first_failed = 0;
845 db_set_record(hDB, hkey, &program_info, sizeof(program_info), 0);
846 }
847 }
848 }
849 }
850
851 ss_semaphore_release(semaphore);
852 }
853#endif /* LOCAL_COUTINES */
854
855 return SUCCESS;
856}
#define FALSE
Definition cfortran.h:309
void connect(const std::string &path, const std::string &name, bool write_defaults, bool delete_keys_not_in_defaults=false)
Definition odbxx.cxx:1377
BOOL al_evaluate_condition(const char *alarm_name, const char *condition, std::string *pvalue)
Definition alarm.cxx:41
INT al_trigger_alarm(const char *alarm_name, const char *alarm_message, const char *default_class, const char *cond_str, INT type)
Definition alarm.cxx:283
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition midas.cxx:3027
INT cm_get_experiment_semaphore(INT *semaphore_alarm, INT *semaphore_elog, INT *semaphore_history, INT *semaphore_msg)
Definition midas.cxx:3049
INT cm_exist(const char *name, BOOL bUnique)
Definition midas.cxx:7531
#define CM_NO_CLIENT
Definition midas.h:584
#define DB_SUCCESS
Definition midas.h:632
#define DB_NO_MORE_SUBKEYS
Definition midas.h:647
#define SS_SUCCESS
Definition midas.h:664
#define SS_TIMEOUT
Definition midas.h:675
#define AL_SUCCESS
Definition midas.h:755
unsigned int DWORD
Definition mcstd.h:51
#define SUCCESS
Definition mcstd.h:54
#define TID_KEY
Definition midas.h:349
#define TID_BOOL
Definition midas.h:340
#define MERROR
Definition midas.h:559
#define MTALK
Definition midas.h:564
#define TID_INT
Definition midas.h:338
#define TID_DWORD
Definition midas.h:336
INT ss_semaphore_release(HNDLE semaphore_handle)
Definition system.cxx:2853
DWORD ss_time()
Definition system.cxx:3534
INT ss_semaphore_wait_for(HNDLE semaphore_handle, DWORD timeout_millisec)
Definition system.cxx:2711
INT ss_system(const char *command)
Definition system.cxx:2188
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
Definition midas.cxx:931
BOOL equal_ustring(const char *str1, const char *str2)
Definition odb.cxx:3285
INT db_get_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, void *data, INT *buf_size, DWORD type, BOOL create)
Definition odb.cxx:5185
std::string strcomb1(const char **list)
Definition odb.cxx:668
INT db_get_record1(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT align, const char *rec_str)
Definition odb.cxx:11834
INT db_check_record(HNDLE hDB, HNDLE hKey, const char *keyname, const char *rec_str, BOOL correct)
Definition odb.cxx:13003
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
Definition odb.cxx:6043
INT db_set_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type)
Definition odb.cxx:5028
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition odb.cxx:4256
INT db_set_record(HNDLE hDB, HNDLE hKey, void *data, INT buf_size, INT align)
Definition odb.cxx:12320
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition odb.cxx:5357
INT db_create_record(HNDLE hDB, HNDLE hKey, const char *orig_key_name, const char *init_str)
Definition odb.cxx:12831
std::string rpc_get_name()
Definition midas.cxx:13215
bool rpc_is_remote(void)
Definition midas.cxx:12892
INT rpc_call(DWORD routine_id,...)
Definition midas.cxx:14115
#define RPC_AL_CHECK
Definition mrpc.h:114
HNDLE hDB
main ODB handle
Definition mana.cxx:207
KEY key
Definition mdump.cxx:34
INT i
Definition mdump.cxx:32
#define DWORD
Definition mhdump.cxx:31
std::string msprintf(const char *format,...)
Definition midas.cxx:419
INT HNDLE
Definition midas.h:132
DWORD BOOL
Definition midas.h:105
#define AT_PROGRAM
Definition midas.h:1442
#define ALARM_PERIODIC_STR(_name)
Definition midas.h:1511
int INT
Definition midas.h:129
#define AT_PERIODIC
Definition midas.h:1444
#define PROGRAM_INFO_STR(_name)
Definition midas.h:1447
#define AT_LAST
Definition midas.h:1445
#define ALARM_ODB_STR(_name)
Definition midas.h:1494
#define TRUE
Definition midas.h:182
#define AT_EVALUATED
Definition midas.h:1443
#define name(x)
Definition midas_macro.h:24
double value[100]
Definition odbhist.cxx:42
char str[256]
Definition odbhist.cxx:33
DWORD status
Definition odbhist.cxx:39
INT type
Definition midas.h:1482
char alarm_class[32]
Definition midas.h:1490
DWORD trigger_count
Definition midas.h:1485
INT check_interval
Definition midas.h:1483
DWORD trigger_count_required
Definition midas.h:1486
DWORD checked_last
Definition midas.h:1484
BOOL active
Definition midas.h:1480
char alarm_message[80]
Definition midas.h:1491
char condition[256]
Definition midas.h:1489
Definition midas.h:1027
DWORD type
Definition midas.h:1028
char name[NAME_LENGTH]
Definition midas.h:1030
BOOL auto_restart
Definition midas.h:1436
DWORD check_interval
Definition midas.h:1432
char alarm_class[32]
Definition midas.h:1437
char start_command[256]
Definition midas.h:1433
DWORD first_failed
Definition midas.h:1438
Here is the call graph for this function:
Here is the caller graph for this function:

◆ al_define_odb_alarm()

INT EXPRT al_define_odb_alarm ( const char *  name,
const char *  condition,
const char *  aclass,
const char *  message 
)

Create an alarm that will trigger when an ODB condition is met.

Parameters
nameAlarm name, defined in /alarms/alarms
classAlarm class to be triggered
conditionAlarm condition to be evaluated
messageAlarm message
Returns
AL_SUCCESS

Definition at line 940 of file alarm.cxx.

940 {
941 HNDLE hDB, hKey;
942 ALARM_ODB_STR(alarm_odb_str);
943
945
946 std::string str = msprintf("/Alarms/Alarms/%s", name);
947
948 db_create_record(hDB, 0, str.c_str(), strcomb1(alarm_odb_str).c_str());
949 db_find_key(hDB, 0, str.c_str(), &hKey);
950 if (!hKey)
951 return DB_NO_MEMORY;
952
953 db_set_value(hDB, hKey, "Condition", condition, 256, 1, TID_STRING);
954 db_set_value(hDB, hKey, "Alarm Class", aclass, 32, 1, TID_STRING);
955 db_set_value(hDB, hKey, "Alarm Message", message, 80, 1, TID_STRING);
956
957 return AL_SUCCESS;
958}
#define DB_NO_MEMORY
Definition midas.h:634
#define TID_STRING
Definition midas.h:346
HNDLE hKey
#define message(type, str)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ al_evaluate_condition()

BOOL al_evaluate_condition ( const char *  alarm_name,
const char *  condition,
std::string *  pvalue 
)

dox

Definition at line 41 of file alarm.cxx.

42{
43 int i, j, size, status;
44
45 //char str[256];
46 //strcpy(str, condition);
47
48 std::vector<char> buf;
49 buf.insert(buf.end(), condition, condition+strlen(condition)+1);
50 char* str = buf.data();
51
52 /* find value and operator */
53 char op[3];
54 op[0] = op[1] = op[2] = 0;
55 for (i = strlen(str) - 1; i > 0; i--)
56 if (strchr("<>=!&", str[i]) != NULL)
57 break;
58 op[0] = str[i];
59 for (j = 1; str[i + j] == ' '; j++)
60 ;
61
62 std::string value2_str = str + i + j;
63 double value2 = atof(value2_str.c_str());
64
65 str[i] = 0;
66
67 if (i > 0 && strchr("<>=!&", str[i - 1])) {
68 op[1] = op[0];
69 op[0] = str[--i];
70 str[i] = 0;
71 }
72
73 i--;
74 while (i > 0 && str[i] == ' ')
75 i--;
76 str[i + 1] = 0;
77
78 /* check if function */
79 std::string function;
80 if (str[i] == ')') {
81 str[i--] = 0;
82 if (strchr(str, '(')) {
83 *strchr(str, '(') = 0;
84 function = str;
85 for (i = strlen(str) + 1, j = 0; str[i]; i++, j++)
86 str[j] = str[i];
87 str[j] = 0;
88 i = j - 1;
89 }
90 }
91
92 std::vector<int> indices;
93 bool index_present = false;
94
95 // process indices
96 if (strchr(str, '[') && str[strlen(str)-1] == ']') {
97 index_present = true;
98
99 // Remove the square brackets from the string
100 std::string cleanInput = strchr(str, '[') + 1;
101 cleanInput.pop_back();
102
103 // Remove index from str
104 *strchr(str, '[') = 0;
105
106 // retrieve key
107 if (!midas::odb::exists(str)) {
108 cm_msg(MERROR, "al_evaluate_condition", "Alarm \"%s\": Cannot find ODB key \"%s\" to evaluate alarm condition", alarm_name, str);
109 if (pvalue)
110 *pvalue = "(cannot find in odb)";
111 return FALSE;
112 }
113 midas::odb k((const char *)str);
114
115 // Split the string by commas
116 std::stringstream ss(cleanInput);
117 std::string token;
118 while (std::getline(ss, token, ',')) {
119 // Remove whitespace
120 token.erase(std::remove_if(token.begin(), token.end(), ::isspace), token.end());
121
122 // Check if token is "*", if so set all indices
123 if (token == "*") {
124 for (int i = 0; i < k.get_num_values(); ++i)
125 indices.push_back(i);
126 } else {
127 // Check if the token represents a range (e.g., "4-7")
128 auto dashPos = token.find('-');
129 if (dashPos != std::string::npos) {
130 // Extract the start and end of the range
131 int start = std::stoi(token.substr(0, dashPos));
132 int end = std::stoi(token.substr(dashPos + 1));
133
134 // Add all numbers in the range [start, end]
135 for (int i = start; i <= end; ++i) {
136 indices.push_back(i);
137 }
138 } else {
139 // It's a single number, add it to the list
140 indices.push_back(std::stoi(token));
141 }
142 }
143 }
144 }
145
146 HNDLE hDB, hkey;
148 db_find_key(hDB, 0, str, &hkey);
149 if (!hkey) {
150 cm_msg(MERROR, "al_evaluate_condition", "Alarm \"%s\": Cannot find ODB key \"%s\" to evaluate alarm condition", alarm_name, str);
151 if (pvalue)
152 *pvalue = "(cannot find in odb)";
153 return FALSE;
154 }
155
156 KEY key;
157 db_get_key(hDB, hkey, &key);
158
159 //printf("Alarm \"%s\": [%s], idx1 %d, idx2 %d, op [%s], value2 [%s] %g, function [%s]\n", alarm_name, condition, idx1, idx2, op, value2_str.c_str(), value2, function.c_str());
160
161 // put at least one value into the indices
162 if (indices.empty())
163 indices.push_back(0);
164
165 // go through all indices
166 for (int idx : indices) {
167 std::string value1_str;
168 double value1 = 0;
169
170 if (equal_ustring(function.c_str(), "access")) {
171 /* check key access time */
172 DWORD dtime;
173 db_get_key_time(hDB, hkey, &dtime);
174 value1_str = msprintf("%d", dtime);
175 value1 = atof(value1_str.c_str());
176 } else if (equal_ustring(function.c_str(), "access_running")) {
177 /* check key access time if running */
178 DWORD dtime;
179 db_get_key_time(hDB, hkey, &dtime);
180 int state = 0;
181 size = sizeof(state);
182 db_get_value(hDB, 0, "/Runinfo/State", &state, &size, TID_INT, FALSE);
183 if (state == STATE_RUNNING) {
184 value1_str = msprintf("%d", dtime).c_str();
185 value1 = atof(value1_str.c_str());
186 } else {
187 value1_str = "0";
188 value1 = 0;
189 }
190 } else {
191 /* get key data and convert to double */
192 status = db_get_key(hDB, hkey, &key);
193 if (status != DB_SUCCESS) {
194 cm_msg(MERROR, "al_evaluate_condition", "Alarm \"%s\": Cannot get ODB key \"%s\" to evaluate alarm condition", alarm_name, str);
195 if (pvalue)
196 *pvalue = "(odb error)";
197 return FALSE;
198 } else {
199 char data[256];
200 size = sizeof(data);
201 status = db_get_data_index(hDB, hkey, data, &size, idx, key.type);
202 if (status != DB_SUCCESS) {
203 cm_msg(MERROR, "al_evaluate_condition", "Alarm \"%s\": Cannot get ODB value \"%s\" index %d to evaluate alarm condition", alarm_name, str, idx);
204 if (pvalue)
205 *pvalue = "(odb error)";
206 return FALSE;
207 }
208
209 value1_str = db_sprintf(data, size, 0, key.type);
210 value1 = atof(value1_str.c_str());
211 }
212 }
213
214 /* convert boolean values to integers */
215 if (key.type == TID_BOOL) {
216 value1 = (value1_str[0] == 'Y' || value1_str[0] == 'y' || value1_str[0] == '1');
217 value2 = (value2_str[0] == 'Y' || value2_str[0] == 'y' || value2_str[0] == '1');
218 }
219
220 /* return value */
221 if (pvalue) {
222 if (index_present)
223 *pvalue = msprintf("[%d] %s", idx, value1_str.c_str());
224 else
225 *pvalue = value1_str;
226 }
227
228 /* now do logical operation */
229 if (strcmp(op, "=") == 0)
230 if (value1 == value2)
231 return TRUE;
232 if (strcmp(op, "==") == 0)
233 if (value1 == value2)
234 return TRUE;
235 if (strcmp(op, "!=") == 0)
236 if (value1 != value2)
237 return TRUE;
238 if (strcmp(op, "<") == 0)
239 if (value1 < value2)
240 return TRUE;
241 if (strcmp(op, ">") == 0)
242 if (value1 > value2)
243 return TRUE;
244 if (strcmp(op, "<=") == 0)
245 if (value1 <= value2)
246 return TRUE;
247 if (strcmp(op, ">=") == 0)
248 if (value1 >= value2)
249 return TRUE;
250 if (strcmp(op, "&") == 0)
251 if (((unsigned int) value1 & (unsigned int) value2) > 0)
252 return TRUE;
253 }
254
255 return FALSE;
256}
static bool exists(const std::string &name)
Definition odbxx.cxx:76
#define STATE_RUNNING
Definition midas.h:307
INT db_get_data_index(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT idx, DWORD type)
Definition odb.cxx:6917
INT db_sprintf(char *string, const void *data, INT data_size, INT idx, DWORD type)
Definition odb.cxx:10865
INT db_get_key_time(HNDLE hDB, HNDLE hKey, DWORD *delta)
Definition odb.cxx:6156
void * data
Definition mana.cxx:268
#define end
INT j
Definition odbhist.cxx:40
INT k
Definition odbhist.cxx:40
Here is the call graph for this function:
Here is the caller graph for this function:

◆ al_get_alarms()

INT al_get_alarms ( std::string *  presult)

Scan ODB for alarms.

Returns
AL_SUCCESS

Definition at line 863 of file alarm.cxx.

864{
865 if (!presult)
866 return 0;
867
868 HNDLE hDB, hkey;
869
871 presult->clear();
872 int n = 0;
873 db_find_key(hDB, 0, "/Alarms/Alarms", &hkey);
874 if (hkey) {
875 /* check global alarm flag */
876 int flag = TRUE;
877 int size = sizeof(flag);
878 db_get_value(hDB, 0, "/Alarms/Alarm System active", &flag, &size, TID_BOOL, FALSE);
879 if (flag) {
880 for (int i = 0;; i++) {
881 HNDLE hsubkey;
882
883 db_enum_link(hDB, hkey, i, &hsubkey);
884
885 if (!hsubkey)
886 break;
887
888 KEY key;
889 db_get_key(hDB, hsubkey, &key);
890
891 flag = 0;
892 size = sizeof(flag);
893 db_get_value(hDB, hsubkey, "Triggered", &flag, &size, TID_INT, FALSE);
894 if (flag) {
895 n++;
896
897 std::string alarm_class, msg;
898 int alarm_type;
899
900 db_get_value_string(hDB, hsubkey, "Alarm Class", 0, &alarm_class);
901 db_get_value_string(hDB, hsubkey, "Alarm Message", 0, &msg);
902
903 size = sizeof(alarm_type);
904 db_get_value(hDB, hsubkey, "Type", &alarm_type, &size, TID_INT, FALSE);
905
906 std::string str;
907
908 if (alarm_type == AT_EVALUATED) {
909 db_get_value_string(hDB, hsubkey, "Condition", 0, &str);
910
911 /* retrieve value */
912 std::string value;
914 str = msprintf(msg.c_str(), value.c_str());
915 } else
916 str = msg;
917
918 *presult += alarm_class;
919 *presult += ": ";
920 *presult += str;
921 *presult += "\n";
922 }
923 }
924 }
925 }
926
927 return n;
928}
INT EXPRT db_get_value_string(HNDLE hdb, HNDLE hKeyRoot, const char *key_name, int index, std::string *s, BOOL create, int create_string_length)
Definition odb.cxx:13967
INT db_enum_link(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition odb.cxx:5495
DWORD n[4]
Definition mana.cxx:247
Here is the call graph for this function:
Here is the caller graph for this function:

◆ al_reset_alarm()

INT al_reset_alarm ( const char *  alarm_name)

dox Reset (acknoledge) alarm.

Parameters
alarm_nameAlarm name, defined in /alarms/alarms
Returns
AL_SUCCESS, AL_RESETE, AL_INVALID_NAME

Definition at line 519 of file alarm.cxx.

519 {
520 int status, size, i;
521 HNDLE hDB, hkeyalarm, hsubkey;
522 KEY key;
523 ALARM a;
524 ALARM_ODB_STR(alarm_str);
525
527
528 if (alarm_name == NULL) {
529 /* reset all alarms */
530 db_find_key(hDB, 0, "/Alarms/Alarms", &hkeyalarm);
531 if (hkeyalarm) {
532 for (i = 0;; i++) {
533 db_enum_link(hDB, hkeyalarm, i, &hsubkey);
534
535 if (!hsubkey)
536 break;
537
538 db_get_key(hDB, hsubkey, &key);
540 }
541 }
542 return AL_SUCCESS;
543 }
544
545 /* find alarm and alarm class */
546 std::string str = msprintf("/Alarms/Alarms/%s", alarm_name);
547 db_find_key(hDB, 0, str.c_str(), &hkeyalarm);
548 if (!hkeyalarm) {
549 /*cm_msg(MERROR, "al_reset_alarm", "Alarm %s not found in ODB", alarm_name);*/
550 return AL_INVALID_NAME;
551 }
552
553 size = sizeof(a);
554 status = db_get_record1(hDB, hkeyalarm, &a, &size, 0, strcomb1(alarm_str).c_str());
555 if (status != DB_SUCCESS) {
556 cm_msg(MERROR, "al_reset_alarm", "Cannot get alarm record");
557 return AL_ERROR_ODB;
558 }
559
560 str = msprintf("/Alarms/Classes/%s", a.alarm_class);
561 if (!midas::odb::exists(str)) {
562 cm_msg(MERROR, "al_reset_alarm", "Alarm class %s not found in ODB", a.alarm_class);
563 return AL_INVALID_NAME;
564 }
565
566 midas::odb ac(str);
567
568 if (a.triggered) {
569 if (a.type == AT_PERIODIC) {
570
571 // set checked_last to occurrence of alarm, to get exactly one period until next alarm
572
573 struct tm tm_time;
574 memset(&tm_time, 0, sizeof(tm_time));
575
576 strptime(a.time_triggered_first, "%a %b %d %H:%M:%S %Y", &tm_time);
577 time_t t = mktime(&tm_time);
578
579 while ((int)ss_time() > t + a.check_interval)
580 t += a.check_interval;
581
582 a.checked_last = t;
583 } else {
584 a.checked_last = 0;
585 }
586
587 a.triggered = 0;
588 a.time_triggered_first[0] = 0;
589 a.time_triggered_last[0] = 0;
590 a.trigger_count = 0;
591
592 ac["System message last"] = (uint32_t)0;
593 ac["Execute last"] = (uint32_t)0;
594
595 status = db_set_record(hDB, hkeyalarm, &a, sizeof(a), 0);
596 if (status != DB_SUCCESS) {
597 cm_msg(MERROR, "al_reset_alarm", "Cannot update alarm record");
598 return AL_ERROR_ODB;
599 }
600 cm_msg(MINFO, "al_reset_alarm", "Alarm \"%s\" reset", alarm_name);
601 return AL_RESET;
602 }
603
604 return AL_SUCCESS;
605}
INT al_reset_alarm(const char *alarm_name)
Definition alarm.cxx:519
#define AL_INVALID_NAME
Definition midas.h:756
#define AL_RESET
Definition midas.h:758
#define AL_ERROR_ODB
Definition midas.h:757
#define MINFO
Definition midas.h:560
MUTEX_T * tm
Definition odbedit.cxx:39
char time_triggered_first[32]
Definition midas.h:1487
char time_triggered_last[32]
Definition midas.h:1488
INT triggered
Definition midas.h:1481
Here is the call graph for this function:
Here is the caller graph for this function:

◆ al_trigger_alarm()

INT al_trigger_alarm ( const char *  alarm_name,
const char *  alarm_message,
const char *  default_class,
const char *  cond_str,
INT  type 
)

dox Trigger a certain alarm.

...
lazy.alarm[0] = 0;
size = sizeof(lazy.alarm);
db_get_value(hDB, pLch->hKey, "Settings/Alarm Class", lazy.alarm, &size, TID_STRING, TRUE);
// trigger alarm if defined
if (lazy.alarm[0])
al_trigger_alarm("Tape", "Tape full...load new one!", lazy.alarm, "Tape full", AT_INTERNAL);
...
LAZY_SETTING lazy
#define AT_INTERNAL
Definition midas.h:1441
char alarm[32]
Parameters
alarm_nameAlarm name, defined in /alarms/alarms
alarm_messageOptional message which goes with alarm
default_classIf alarm is not yet defined under /alarms/alarms/<alarm_name>, a new one is created and this default class is used.
cond_strString displayed in alarm condition
typeAlarm type, one of AT_xxx
Returns
AL_SUCCESS, AL_INVALID_NAME

Definition at line 283 of file alarm.cxx.

284 {
285 if (rpc_is_remote())
286 return rpc_call(RPC_AL_TRIGGER_ALARM, alarm_name, alarm_message, default_class, cond_str, type);
287
288#ifdef LOCAL_ROUTINES
289 {
290 int status, size;
291 HNDLE hDB, hkeyalarm, hkey;
292 ALARM a;
293 BOOL flag;
294 ALARM_ODB_STR(alarm_odb_str);
295
297
298 /* check online mode */
299 flag = TRUE;
300 size = sizeof(flag);
301 db_get_value(hDB, 0, "/Runinfo/Online Mode", &flag, &size, TID_INT, TRUE);
302 if (!flag)
303 return AL_SUCCESS;
304
305 /* find alarm */
306 std::string alarm_path = msprintf("/Alarms/Alarms/%s", alarm_name);
307
308 db_find_key(hDB, 0, alarm_path.c_str(), &hkeyalarm);
309 if (!hkeyalarm) {
310 /* alarm must be an internal analyzer alarm, so create a default alarm */
311 status = db_create_record(hDB, 0, alarm_path.c_str(), strcomb1(alarm_odb_str).c_str());
312 db_find_key(hDB, 0, alarm_path.c_str(), &hkeyalarm);
313 if (!hkeyalarm) {
314 cm_msg(MERROR, "al_trigger_alarm", "Cannot create alarm record for alarm \"%s\", db_create_record() status %d", alarm_path.c_str(), status);
315 return AL_ERROR_ODB;
316 }
317
318 if (default_class && default_class[0])
319 db_set_value(hDB, hkeyalarm, "Alarm Class", default_class, 32, 1, TID_STRING);
320 status = TRUE;
321 db_set_value(hDB, hkeyalarm, "Active", &status, sizeof(status), 1, TID_BOOL);
322 }
323
324 /* set parameters for internal alarms */
325 if (type != AT_EVALUATED && type != AT_PERIODIC) {
326 db_set_value(hDB, hkeyalarm, "Type", &type, sizeof(INT), 1, TID_INT);
327 char str[256];
328 mstrlcpy(str, cond_str, sizeof(str));
329 db_set_value(hDB, hkeyalarm, "Condition", str, 256, 1, TID_STRING);
330 }
331
332 size = sizeof(a);
333 status = db_get_record1(hDB, hkeyalarm, &a, &size, 0, strcomb1(alarm_odb_str).c_str());
334 if (status != DB_SUCCESS || a.type < 1 || a.type > AT_LAST) {
335 /* make sure alarm record has right structure */
336 size = sizeof(a);
337 status = db_get_record1(hDB, hkeyalarm, &a, &size, 0, strcomb1(alarm_odb_str).c_str());
338 if (status != DB_SUCCESS) {
339 cm_msg(MERROR, "al_trigger_alarm", "Cannot get alarm record for alarm \"%s\", db_get_record1() status %d", alarm_path.c_str(), status);
340 return AL_ERROR_ODB;
341 }
342 }
343
344 /* if internal alarm, check if active and check interval */
345 if (a.type != AT_EVALUATED && a.type != AT_PERIODIC) {
346 /* check global alarm flag */
347 flag = TRUE;
348 size = sizeof(flag);
349 db_get_value(hDB, 0, "/Alarms/Alarm system active", &flag, &size, TID_BOOL, TRUE);
350 if (!flag)
351 return AL_SUCCESS;
352
353 if (!a.active)
354 return AL_SUCCESS;
355
356 if ((INT) ss_time() - (INT) a.checked_last < a.check_interval)
357 return AL_SUCCESS;
358
359 /* now the alarm will be triggered, so save time */
360 a.checked_last = ss_time();
361 }
362
363 if (a.type == AT_PROGRAM) {
364 /* alarm class of "program not running" alarms is set in two places,
365 * complain if they do not match */
366 if (!equal_ustring(a.alarm_class, default_class)) {
367 cm_msg(MERROR, "al_trigger_alarm",
368 "Program alarm class mismatch: \"%s/Alarm class\" set to \"%s\" does not match \"/Programs/%s/Alarm "
369 "Class\" set to \"%s\"",
370 alarm_path.c_str(), a.alarm_class, alarm_name, default_class);
371 }
372 }
373
374 /* write back alarm message for internal alarms */
375 if (a.type != AT_EVALUATED && a.type != AT_PERIODIC) {
376 mstrlcpy(a.alarm_message, alarm_message, sizeof(a.alarm_message));
377 }
378
379 /* now trigger alarm class defined in this alarm */
380 if (a.alarm_class[0])
381 al_trigger_class(a.alarm_class, alarm_message, a.triggered > 0);
382
383 /* check for and trigger "All" class */
384 if (db_find_key(hDB, 0, "/Alarms/Classes/All", &hkey) == DB_SUCCESS)
385 al_trigger_class("All", alarm_message, a.triggered > 0);
386
387 /* signal alarm being triggered */
388 std::string now = cm_asctime();
389
390 if (!a.triggered)
391 mstrlcpy(a.time_triggered_first, now.c_str(), sizeof(a.time_triggered_first));
392
393 a.triggered++;
394 mstrlcpy(a.time_triggered_last, now.c_str(), sizeof(a.time_triggered_last));
395
396 a.checked_last = ss_time();
397
398 status = db_set_record(hDB, hkeyalarm, &a, sizeof(a), 0);
399 if (status != DB_SUCCESS) {
400 cm_msg(MERROR, "al_trigger_alarm", "Cannot update alarm record for alarm \"%s\", db_set_record() status %d", alarm_path.c_str(), status);
401 return AL_ERROR_ODB;
402 }
403 }
404#endif /* LOCAL_ROUTINES */
405
406 return AL_SUCCESS;
407}
INT al_trigger_class(const char *alarm_class, const char *alarm_message, BOOL first)
Definition alarm.cxx:413
std::string cm_asctime()
Definition midas.cxx:1428
#define RPC_AL_TRIGGER_ALARM
Definition mrpc.h:115
INT type
Definition mana.cxx:269
Here is the call graph for this function:
Here is the caller graph for this function:

◆ al_trigger_class()

INT al_trigger_class ( const char *  alarm_class,
const char *  alarm_message,
BOOL  first 
)

dox

Definition at line 413 of file alarm.cxx.

434{
435 int size, state;
436 HNDLE hDB;
437 DWORD now = ss_time();
438
440
441 /* get alarm class */
442 std::string alarm_path = msprintf("/Alarms/Classes/%s", alarm_class);
443 if (!midas::odb::exists(alarm_path)) {
444 cm_msg(MERROR, "al_trigger_class", "Alarm class \"%s\" for alarm \"%s\" not found in ODB", alarm_class, alarm_message);
445 return AL_INVALID_NAME;
446 }
447
448 midas::odb ac(alarm_path);
449
450 std::string msg;
451
452 /* write system message */
453 bool write_system_message = ac["Write system message"];
454 int system_message_interval = ac["System message interval"];
455 DWORD system_message_last = ac["System message last"];
456 if (write_system_message && (now - system_message_last >= (DWORD) system_message_interval)) {
457 if (equal_ustring(alarm_class, "All"))
458 msg = msprintf("General alarm: %s", alarm_message);
459 else
460 msg = msprintf("%s: %s", alarm_class, alarm_message);
461 cm_msg(MTALK, "al_trigger_class", "%s", msg.c_str());
462 system_message_last = now;
463 ac["System message last"] = (uint32_t)system_message_last;
464 }
465
466 /* write elog message on first trigger if using internal ELOG */
467 if ((bool)ac["Write Elog message"] && first) {
468 BOOL external_elog = FALSE;
469 size = sizeof(external_elog);
470 db_get_value(hDB, 0, "/Elog/External Elog", &external_elog, &size, TID_BOOL, FALSE);
471 if (!external_elog) {
472 char tag[32];
473 tag[0] = 0;
474 el_submit(0, "Alarm system", "Alarm", "General", alarm_class, msg.c_str(), "", "plain", "", "", 0, "", "", 0, "", "", 0, tag, sizeof(tag));
475 }
476 }
477
478 /* execute command */
479 std::string execute_command = ac["Execute command"];
480 int execute_interval = ac["Execute interval"];
481 DWORD execute_last = ac["Execute last"];
482 if (!execute_command.empty() && execute_interval > 0 && (INT) ss_time() - (INT) execute_last > execute_interval) {
483 if (equal_ustring(alarm_class, "All"))
484 msg = msprintf("General alarm: %s", alarm_message);
485 else
486 msg = msprintf("%s: %s", alarm_class, alarm_message);
487 std::string command = msprintf(execute_command.c_str(), msg.c_str());
488 cm_msg(MINFO, "al_trigger_class", "Execute: %s", command.c_str());
489 ss_system(command.c_str());
490 execute_last = ss_time();
491 ac["Execute last"] = (uint32_t)execute_last;
492 }
493
494 /* stop run */
495 if ((bool)ac["Stop run"]) {
497 size = sizeof(state);
498 db_get_value(hDB, 0, "/Runinfo/State", &state, &size, TID_INT, TRUE);
499 if (state != STATE_STOPPED) {
500 cm_msg(MINFO, "al_trigger_class", "Stopping the run from alarm class \'%s\', message \'%s\'", alarm_class,
501 alarm_message);
502 cm_transition(TR_STOP, 0, NULL, 0, TR_DETACH, FALSE);
503 }
504 }
505
506 return AL_SUCCESS;
507}
INT cm_transition(INT transition, INT run_number, char *errstr, INT errstr_size, INT async_flag, INT debug_flag)
Definition midas.cxx:5304
INT el_submit(int run, const char *author, const char *type, const char *syst, const char *subject, const char *text, const char *reply_to, const char *encoding, const char *afilename1, const char *buffer1, INT buffer_size1, const char *afilename2, const char *buffer2, INT buffer_size2, const char *afilename3, const char *buffer3, INT buffer_size3, char *tag, INT tag_size)
Definition elog.cxx:126
#define STATE_STOPPED
Definition midas.h:305
#define TR_DETACH
Definition midas.h:360
#define TR_STOP
Definition midas.h:406
Here is the call graph for this function:
Here is the caller graph for this function: