Line data Source code
1 : /********************************************************************\
2 :
3 : Name: mtransition.cxx
4 : Created by: Stefan Ritt and Konstantin Olchanski
5 :
6 : Contents: Command-line interface to run state transitions
7 :
8 : $Id$
9 :
10 : \********************************************************************/
11 :
12 : #undef NDEBUG // midas required assert() to be always enabled
13 :
14 : #include <stdio.h>
15 : #include <stdlib.h>
16 : #include <string.h>
17 : #include <ctype.h>
18 : #include <assert.h>
19 : #include <signal.h>
20 : #include <unistd.h> // sleep()
21 :
22 : #include "midas.h"
23 :
24 : /*------------------------------------------------------------------*/
25 :
26 0 : int read_state(HNDLE hDB)
27 : {
28 : /* check if run is stopped */
29 0 : int state = STATE_STOPPED;
30 0 : int size = sizeof(state);
31 0 : int status = db_get_value(hDB, 0, "/Runinfo/State", &state, &size, TID_INT, FALSE);
32 0 : assert(status == DB_SUCCESS);
33 0 : return state;
34 : }
35 :
36 0 : void usage()
37 : {
38 0 : fprintf(stderr, "Usage: mtransition [-v] [-d debug_flag] [-f] [-h Hostname] [-e Experiment] commands...\n");
39 0 : fprintf(stderr, "Options:\n");
40 0 : fprintf(stderr, " -v - report activity\n");
41 0 : fprintf(stderr, " -d debug_flag - passed through cm_transition(debug_flag): 0=normal, 1=printf, 2=cm_msg(MINFO)\n");
42 0 : fprintf(stderr, " -f - force new state regardless of current state\n");
43 0 : fprintf(stderr, " -m - multithread transition\n");
44 0 : fprintf(stderr, " -a - async multithread transition\n");
45 0 : fprintf(stderr, " -h Hostname - connect to mserver on remote host\n");
46 0 : fprintf(stderr, " -e Experiment - connect to non-default experiment\n");
47 0 : fprintf(stderr, "Commands:\n");
48 0 : fprintf(stderr, " START [runno] - start a new run\n");
49 0 : fprintf(stderr, " STOP - stop the run\n");
50 0 : fprintf(stderr, " PAUSE - pause the run\n");
51 0 : fprintf(stderr, " RESUME - resume the run\n");
52 0 : fprintf(stderr, " STARTABORT - cleanup after failed START\n");
53 0 : fprintf(stderr, " DELAY 100 - sleep for 100 seconds\n");
54 0 : fprintf(stderr, " DELAY \"/logger/Auto restart delay\" - sleep for time specified in ODB variable\n");
55 0 : fprintf(stderr, " IF \"/logger/Auto restart\" - continue only if ODB variable is set to TRUE\n");
56 0 : cm_set_msg_print(MT_ERROR, 0, NULL);
57 0 : cm_disconnect_experiment();
58 0 : exit (1);
59 : }
60 :
61 0 : int main(int argc, char *argv[])
62 : {
63 : int status;
64 0 : bool verbose = false;
65 0 : int debug_flag = 0;
66 0 : bool force = false;
67 0 : bool multithread = false;
68 0 : bool asyncmultithread = false;
69 0 : std::string host_name;
70 0 : std::string exp_name;
71 :
72 0 : setbuf(stdout, NULL);
73 0 : setbuf(stderr, NULL);
74 :
75 : #ifndef OS_WINNT
76 0 : signal(SIGPIPE, SIG_IGN);
77 : #endif
78 :
79 : /* get default from environment */
80 0 : cm_get_environment(&host_name, &exp_name);
81 :
82 : /* parse command line parameters */
83 :
84 0 : if (argc < 2)
85 0 : usage(); // does not return
86 :
87 0 : for (int i = 1; i < argc; i++) {
88 0 : if (argv[i][0] == '-') {
89 0 : if (argv[i][1] == 'v')
90 0 : verbose = true;
91 0 : else if (argv[i][1] == 'f')
92 0 : force = true;
93 0 : else if (argv[i][1] == 'a')
94 0 : asyncmultithread = true;
95 0 : else if (argv[i][1] == 'm')
96 0 : multithread = true;
97 0 : else if (argv[i][1] == 'd' && i < argc-1)
98 0 : debug_flag = strtoul(argv[++i], NULL, 0);
99 0 : else if (argv[i][1] == 'e' && i < argc-1)
100 0 : exp_name = argv[++i];
101 0 : else if (argv[i][1] == 'h' && i < argc-1)
102 0 : host_name = argv[++i];
103 : else
104 0 : usage(); // does not return
105 : }
106 : }
107 :
108 0 : if (debug_flag)
109 0 : verbose = true;
110 0 : else if (verbose)
111 0 : debug_flag = 1;
112 :
113 : /* do not produce a startup message */
114 0 : cm_set_msg_print(MT_ERROR, 0, NULL);
115 :
116 0 : status = cm_connect_experiment1(host_name.c_str(), exp_name.c_str(), "mtransition", NULL,
117 : DEFAULT_ODB_SIZE,
118 : DEFAULT_WATCHDOG_TIMEOUT);
119 0 : if (status != CM_SUCCESS) {
120 0 : fprintf(stderr,"Error: Cannot connect to experiment \'%s\' on host \'%s\', status %d\n",
121 : exp_name.c_str(),
122 : host_name.c_str(),
123 : status);
124 0 : exit(1);
125 : }
126 :
127 0 : if (verbose)
128 0 : printf("Connected to experiment \'%s\' on host \'%s\'\n", exp_name.c_str(), host_name.c_str());
129 :
130 : HNDLE hDB;
131 :
132 0 : status = cm_get_experiment_database(&hDB, NULL);
133 0 : assert(status == CM_SUCCESS);
134 :
135 0 : int tr_flag = TR_SYNC;
136 0 : if (multithread)
137 0 : tr_flag = TR_MTHREAD|TR_SYNC;
138 0 : if (asyncmultithread)
139 0 : tr_flag = TR_MTHREAD|TR_ASYNC;
140 :
141 0 : for (int i=1; i<argc; i++) {
142 :
143 0 : if (argv[i][0] == '-') {
144 :
145 : // skip command line switches
146 :
147 0 : if (argv[i][1] == 'd')
148 0 : i++;
149 0 : else if (argv[i][1] == 'h')
150 0 : i++;
151 0 : if (argv[i][1] == 'e')
152 0 : i++;
153 :
154 0 : continue;
155 :
156 0 : } else if (strcmp(argv[i], "START") == 0) {
157 :
158 : /* start */
159 :
160 : /* check if run is already started */
161 0 : int state = read_state(hDB);
162 :
163 0 : if (!force && state == STATE_RUNNING) {
164 0 : printf("START: Run is already started\n");
165 0 : cm_set_msg_print(MT_ERROR, 0, NULL);
166 0 : cm_disconnect_experiment();
167 0 : exit(1);
168 0 : } else if (!force && state == STATE_PAUSED) {
169 0 : printf("START: Run is paused, please use \"RESUME\"\n");
170 0 : cm_set_msg_print(MT_ERROR, 0, NULL);
171 0 : cm_disconnect_experiment();
172 0 : exit(1);
173 : }
174 :
175 : /* get present run number */
176 0 : int old_run_number = 0;
177 0 : int size = sizeof(old_run_number);
178 0 : status = db_get_value(hDB, 0, "/Runinfo/Run number", &old_run_number, &size, TID_INT, FALSE);
179 0 : assert(status == DB_SUCCESS);
180 0 : assert(old_run_number >= 0);
181 :
182 0 : int new_run_number = old_run_number + 1;
183 :
184 0 : if (i+1 < argc) {
185 0 : if (isdigit(argv[i+1][0])) {
186 0 : new_run_number = atoi(argv[i+1]);
187 0 : i++;
188 : }
189 : }
190 :
191 0 : if (verbose)
192 0 : printf("Starting run %d\n", new_run_number);
193 :
194 : char str[256];
195 0 : status = cm_transition(TR_START, new_run_number, str, sizeof(str), tr_flag, debug_flag);
196 0 : if (status != CM_SUCCESS) {
197 : /* in case of error, reset run number */
198 0 : status = db_set_value(hDB, 0, "/Runinfo/Run number", &old_run_number, sizeof(old_run_number), 1, TID_INT);
199 0 : assert(status == DB_SUCCESS);
200 :
201 0 : printf("START: cm_transition status %d, message \'%s\'\n", status, str);
202 : }
203 :
204 0 : } else if (strcmp(argv[i], "STOP") == 0) {
205 :
206 : /* check if run is stopped */
207 :
208 0 : int state = read_state(hDB);
209 :
210 0 : if (state == STATE_STOPPED) {
211 0 : printf("Run is already stopped, stopping again.\n");
212 : }
213 :
214 : char str[256];
215 0 : status = cm_transition(TR_STOP, 0, str, sizeof(str), tr_flag, debug_flag);
216 :
217 0 : if (status != CM_SUCCESS)
218 0 : printf("STOP: cm_transition status %d, message \'%s\'\n", status, str);
219 :
220 0 : } else if (strcmp(argv[i], "PAUSE") == 0) {
221 :
222 : /* check if run is started */
223 :
224 0 : int state = read_state(hDB);
225 :
226 0 : if (!force && state == STATE_PAUSED) {
227 0 : printf("PAUSE: Run is already paused\n");
228 0 : continue;
229 : }
230 :
231 0 : if (state != STATE_RUNNING) {
232 0 : printf("PAUSE: Run is not started\n");
233 0 : cm_set_msg_print(MT_ERROR, 0, NULL);
234 0 : cm_disconnect_experiment();
235 0 : exit(1);
236 : }
237 :
238 : char str[256];
239 0 : status = cm_transition(TR_PAUSE, 0, str, sizeof(str), tr_flag, debug_flag);
240 :
241 0 : if (status != CM_SUCCESS)
242 0 : printf("PAUSE: cm_transition status %d, message \'%s\'\n", status, str);
243 :
244 0 : } else if (strcmp(argv[i], "RESUME") == 0) {
245 :
246 0 : int state = read_state(hDB);
247 :
248 0 : if (!force && state == STATE_RUNNING) {
249 0 : printf("RESUME: Run is already running\n");
250 0 : continue;
251 0 : } else if (!force && state != STATE_PAUSED) {
252 0 : printf("RESUME: Run is not paused\n");
253 0 : cm_set_msg_print(MT_ERROR, 0, NULL);
254 0 : cm_disconnect_experiment();
255 0 : exit(1);
256 : }
257 :
258 : char str[256];
259 0 : status = cm_transition(TR_RESUME, 0, str, sizeof(str), tr_flag, debug_flag);
260 0 : if (status != CM_SUCCESS)
261 0 : printf("RESUME: cm_transition status %d, message \'%s\'\n", status, str);
262 :
263 0 : } else if (strcmp(argv[i], "STARTABORT") == 0) {
264 :
265 : char str[256];
266 0 : status = cm_transition(TR_STARTABORT, 0, str, sizeof(str), tr_flag, debug_flag);
267 0 : if (status != CM_SUCCESS)
268 0 : printf("STARTABORT: cm_transition status %d, message \'%s\'\n", status, str);
269 :
270 0 : } else if (strcmp(argv[i], "DELAY") == 0) {
271 :
272 0 : if (argv[i+1] == NULL) {
273 0 : fprintf(stderr,"Command DELAY requires an argument\n");
274 0 : usage(); // does not return
275 : }
276 :
277 0 : const char* arg = argv[++i];
278 0 : int delay = 0;
279 :
280 0 : if (isdigit(arg[0])) {
281 0 : delay = atoi(arg);
282 0 : } else if (arg[0] == '/') {
283 0 : int size = sizeof(delay);
284 0 : status = db_get_value(hDB, 0, arg, &delay, &size, TID_INT, FALSE);
285 0 : if (status != DB_SUCCESS) {
286 0 : fprintf(stderr,"DELAY: Cannot read ODB variable \'%s\', status %d\n", arg, status);
287 0 : cm_set_msg_print(MT_ERROR, 0, NULL);
288 0 : cm_disconnect_experiment();
289 0 : exit(1);
290 : }
291 : }
292 :
293 0 : if (verbose)
294 0 : printf("DELAY \'%s\' %d sec\n", arg, delay);
295 :
296 0 : status = ss_sleep(delay*1000);
297 0 : assert(status == SS_SUCCESS);
298 :
299 0 : } else if (strcmp(argv[i], "IF") == 0) {
300 :
301 0 : if (argv[i+1] == NULL) {
302 0 : fprintf(stderr,"Command IF requires an argument\n");
303 0 : usage(); // does not return
304 : }
305 :
306 0 : const char* arg = argv[++i];
307 0 : int value = 0;
308 :
309 0 : if (isdigit(arg[0])) {
310 0 : value = atoi(arg);
311 0 : } else if (arg[0] == '/') {
312 0 : int size = sizeof(value);
313 0 : status = db_get_value(hDB, 0, arg, &value, &size, TID_BOOL, FALSE);
314 0 : if (status == DB_TYPE_MISMATCH) {
315 0 : status = db_get_value(hDB, 0, arg, &value, &size, TID_INT, FALSE);
316 : }
317 0 : if (status != DB_SUCCESS) {
318 0 : fprintf(stderr,"IF: Cannot read ODB variable \'%s\', status %d\n", arg, status);
319 0 : cm_set_msg_print(MT_ERROR, 0, NULL);
320 0 : cm_disconnect_experiment();
321 0 : exit(1);
322 : }
323 : }
324 :
325 0 : if (verbose)
326 0 : printf("IF \'%s\' value %d\n", arg, value);
327 :
328 0 : if (!value) {
329 0 : cm_set_msg_print(MT_ERROR, 0, NULL);
330 0 : cm_disconnect_experiment();
331 0 : exit(0);
332 : }
333 :
334 : } else {
335 :
336 0 : fprintf(stderr,"Unknown command \'%s\'\n", argv[i]);
337 0 : usage(); // does not return
338 :
339 : }
340 : }
341 :
342 : while (1) {
343 0 : int status = cm_transition_cleanup();
344 0 : if (status == CM_SUCCESS)
345 0 : break;
346 0 : printf("waiting for transition to finish!\n");
347 0 : ::sleep(1);
348 0 : }
349 :
350 : /* do not produce a shutdown message */
351 0 : cm_set_msg_print(MT_ERROR, 0, NULL);
352 :
353 0 : cm_disconnect_experiment();
354 :
355 0 : return 0;
356 0 : }
357 :
358 : // end
|