LCOV - code coverage report
Current view: top level - progs - mtransition.cxx (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 208 0
Test Date: 2025-11-11 10:26:08 Functions: 0.0 % 3 0

            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
        

Generated by: LCOV version 2.0-1