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

            Line data    Source code
       1              : /*******************************************************************\
       2              : 
       3              :   Name:         fetest.cxx
       4              :   Created by:   K.Olchanski
       5              : 
       6              :   Contents:     Front end for testing MIDAS
       7              : 
       8              : \********************************************************************/
       9              : 
      10              : #undef NDEBUG // midas required assert() to be always enabled
      11              : 
      12              : #include <stdio.h>
      13              : #include <signal.h> // SIGPIPE
      14              : #include <assert.h> // assert()
      15              : #include <stdlib.h> // malloc()
      16              : #include <math.h> // M_PI
      17              : 
      18              : #include "midas.h"
      19              : #include "tmfe.h"
      20              : 
      21              : #include <string> // std::string
      22              : #include <thread> // std::thread
      23              : #include <atomic> // atd::atomic
      24              : 
      25              : class EqRandom :
      26              :    public TMFeEquipment
      27              : {
      28              : public:
      29            0 :    EqRandom(const char* eqname, const char* eqfilename) // ctor
      30            0 :       : TMFeEquipment(eqname, eqfilename)
      31              :    {
      32            0 :       fEqConfEventID = 2;
      33            0 :       fEqConfPeriodMilliSec = 1000;
      34            0 :       fEqConfLogHistory = 0;
      35            0 :       fEqConfWriteEventsToOdb = false;
      36            0 :       fEqConfReadOnlyWhenRunning = true;
      37            0 :    }
      38              :    
      39            0 :    TMFeResult HandleInit(const std::vector<std::string>& args)
      40              :    {
      41            0 :       fEqConfReadOnlyWhenRunning = true;
      42            0 :       fEqConfWriteEventsToOdb = false;
      43            0 :       fEqConfLogHistory = 0;
      44            0 :       return TMFeOk();
      45              :    }
      46              :    
      47            0 :    void HandlePeriodic()
      48              :    {
      49            0 :       char event[fEqConfMaxEventSize];
      50              : 
      51            0 :       ComposeEvent(event, fEqConfMaxEventSize);
      52              :       
      53            0 :       char* pbh = event + sizeof(EVENT_HEADER);
      54              :       
      55            0 :       double r = drand48();
      56            0 :       if (r < 0.3)
      57            0 :          bk_init(pbh);
      58            0 :       else if (r < 0.6)
      59            0 :          bk_init32(pbh);
      60              :       else
      61            0 :          bk_init32a(pbh);
      62              :       
      63            0 :       int nbank = 0+9*drand48(); // nbank range: 0..9, see how bank names are generated: RND0..RND9
      64              :       
      65            0 :       for (int i=0; i<nbank; i++) {
      66            0 :          int tid = 1+(TID_LAST-1)*drand48();
      67            0 :          int size = 0+100*drand48();
      68              : 
      69              :          //int total = bk_size(pbh);
      70              :          //printf("total %d, add %d, max %d\n", total, size, (int)fMaxEventSize);
      71              : 
      72              :          char name[5];
      73            0 :          name[0] = 'R';
      74            0 :          name[1] = 'N';
      75            0 :          name[2] = 'D';
      76            0 :          name[3] = '0' + (nbank-i-1);
      77            0 :          name[4] = 0;
      78              :          
      79              :          char* ptr;
      80            0 :          bk_create(pbh, name, tid, (void**)&ptr);
      81              :          
      82            0 :          for (int j=0; j<size; j++)
      83            0 :             ptr[j] = (nbank-i-1);
      84              :          
      85            0 :          bk_close(pbh, ptr + size);
      86              :       }
      87              : 
      88              :       //printf("sending %d, max %d\n", (int)bk_size(pbh), (int)fMaxEventSize);
      89              : 
      90            0 :       EqSendEvent(event);
      91            0 :    }
      92              : 
      93              : #if 0
      94              :   { "random"   ,         /* equipment name */
      95              :     {
      96              :       EVID_RANDOM, (1<<EVID_RANDOM),           /* event ID, trigger mask */
      97              :       "SYSTEM",             /* event buffer */
      98              :       EQ_PERIODIC,          /* equipment type */
      99              :       0,                    /* event source */
     100              :       "MIDAS",              /* format */
     101              :       TRUE,                 /* enabled */
     102              :       RO_RUNNING,           /* Read when running */
     103              :       100,                  /* poll every so milliseconds */
     104              :       0,                    /* stop run after this event limit */
     105              :       0,                    /* number of sub events */
     106              :       0,                    /* history period */
     107              :       "", "", ""
     108              :     },
     109              :     read_random_event,/* readout routine */
     110              :   },
     111              : #endif
     112              : 
     113              : };
     114              : 
     115              : class EqSlow :
     116              :    public TMFeEquipment
     117              : {
     118              : public:
     119            0 :    EqSlow(const char* eqname, const char* eqfilename) // ctor
     120            0 :       : TMFeEquipment(eqname, eqfilename)
     121              :    {
     122            0 :       fEqConfEventID = 3;
     123            0 :       fEqConfPeriodMilliSec = 1000;
     124            0 :       fEqConfLogHistory = 1;
     125            0 :       fEqConfWriteEventsToOdb = true;
     126            0 :    }
     127              : 
     128            0 :    TMFeResult HandleInit(const std::vector<std::string>& args)
     129              :    {
     130            0 :       fEqConfReadOnlyWhenRunning = false;
     131            0 :       fEqConfWriteEventsToOdb = true;
     132              :       //fEqConfLogHistory = 1;
     133            0 :       return TMFeOk();
     134              :    }
     135              :    
     136            0 :    void SendData(double dvalue)
     137              :    {
     138              :       char buf[1024];
     139            0 :       ComposeEvent(buf, sizeof(buf));
     140            0 :       BkInit(buf, sizeof(buf));
     141              :          
     142            0 :       double* ptr = (double*)BkOpen(buf, "data", TID_DOUBLE);
     143            0 :       *ptr++ = dvalue;
     144            0 :       BkClose(buf, ptr);
     145              : 
     146            0 :       EqSendEvent(buf);
     147            0 :    }
     148              : 
     149              : //#define TEST_PERIOD 1
     150              : 
     151              : #ifdef TEST_PERIOD
     152              :    double first = 0;
     153              :    double prev = 0;
     154              :    int count = 0;
     155              : #endif
     156              :    
     157            0 :    void HandlePeriodic()
     158              :    {
     159              : #ifdef TEST_PERIOD
     160              :       double now = TMFE::GetTime();
     161              :       if (first == 0)
     162              :          first = now;
     163              :       double elapsed = now - prev;
     164              :       double expected = first + count*fEqConfPeriodMilliSec/1000.0;
     165              :       printf("count %d, periodic %f, expected %f, diff %f, elapsed %f\n", count, now, expected, now-expected, elapsed);
     166              :       prev = now;
     167              :       count++;
     168              : 
     169              :       //TMFE::Sleep(2);
     170              : #endif
     171              :       
     172              :       //printf("EqSlow::HandlePeriodic!\n");
     173            0 :       double t = TMFE::GetTime();
     174            0 :       double data = 100.0*sin(-M_PI/2.0+M_PI*t/60);
     175            0 :       SendData(data);
     176              :       char status_buf[256];
     177            0 :       sprintf(status_buf, "value %.1f", data);
     178            0 :       EqSetStatus(status_buf, "#00FF00");
     179            0 :    }
     180              : 
     181              : #if 0
     182              :   { "slow"   ,         /* equipment name */
     183              :     {
     184              :       EVID_SLOW, (1<<EVID_SLOW),           /* event ID, trigger mask */
     185              :       "SYSTEM",             /* event buffer */
     186              :       EQ_PERIODIC,          /* equipment type */
     187              :       0,                    /* event source */
     188              :       "MIDAS",              /* format */
     189              :       TRUE,                 /* enabled */
     190              :       RO_ALWAYS,            /* Read when running */
     191              :       1000,                 /* poll every so milliseconds */
     192              :       0,                    /* stop run after this event limit */
     193              :       0,                    /* number of sub events */
     194              :       1,                    /* history period */
     195              :       "", "", ""
     196              :     },
     197              :     read_slow_event,/* readout routine */
     198              :   },
     199              : #endif
     200              : };
     201              : 
     202              : class EqRare :
     203              :    public TMFeEquipment
     204              : {
     205              : public:
     206            0 :    EqRare(const char* eqname, const char* eqfilename) // ctor
     207            0 :       : TMFeEquipment(eqname, eqfilename)
     208              :    {
     209            0 :       fEqConfEventID = 4;
     210            0 :       fEqConfPeriodMilliSec = 10000;
     211            0 :       fEqConfLogHistory = 0;
     212            0 :       fEqConfWriteEventsToOdb = false;
     213            0 :       fEqConfReadOnlyWhenRunning = false;
     214            0 :    }
     215              : 
     216            0 :    TMFeResult HandleInit(const std::vector<std::string>& args)
     217              :    {
     218            0 :       return TMFeOk();
     219              :    }
     220              :    
     221            0 :    void SendData(double dvalue)
     222              :    {
     223              :       char buf[1024];
     224            0 :       ComposeEvent(buf, sizeof(buf));
     225            0 :       BkInit(buf, sizeof(buf));
     226              :          
     227            0 :       double* ptr = (double*)BkOpen(buf, "rare", TID_DOUBLE);
     228            0 :       *ptr++ = dvalue;
     229            0 :       BkClose(buf, ptr);
     230              : 
     231            0 :       EqSendEvent(buf);
     232            0 :    }
     233              : 
     234            0 :    void HandlePeriodic()
     235              :    {
     236              :       //printf("EqSlow::HandlePeriodic!\n");
     237            0 :       double t = TMFE::GetTime();
     238            0 :       double data = 100.0*sin(-M_PI/2.0+M_PI*t/60);
     239            0 :       SendData(data);
     240              :       char status_buf[256];
     241            0 :       sprintf(status_buf, "value %.1f", data);
     242            0 :       EqSetStatus(status_buf, "#00FF00");
     243            0 :    }
     244              : };
     245              : 
     246              : class EqBulk :
     247              :    public TMFeEquipment
     248              : {
     249              : public: // configuration
     250              :    int fEventSize = 0;
     251              :    double fEventSleep = 1.0;
     252              :    std::vector<char> fEventBuffer;
     253              : 
     254              : public: // internal state
     255              :    std::atomic_bool fThreadRunning{false};
     256              :    std::thread *fThread = NULL;
     257              :    
     258              : public:
     259            0 :    EqBulk(const char* eqname, const char* eqfilename) // ctor
     260            0 :       : TMFeEquipment(eqname, eqfilename)
     261              :    {
     262            0 :       fEqConfPeriodMilliSec = 1000;
     263            0 :       fEqConfEventID = 3;
     264            0 :       fEqConfReadOnlyWhenRunning = true;
     265            0 :    }
     266              : 
     267            0 :    ~EqBulk() // dtor
     268            0 :    {
     269              :       // wait for thread to finish
     270            0 :       while (fThreadRunning) {
     271            0 :          fMfe->Sleep(0.1);
     272              :       }
     273              : 
     274            0 :       if (fThread) {
     275            0 :          fThread->join();
     276            0 :          delete fThread;
     277            0 :          fThread = NULL;
     278              :       }
     279            0 :    }
     280              : 
     281            0 :    TMFeResult HandleInit(const std::vector<std::string>& args)
     282              :    {
     283            0 :       EqSetStatus("Starting...", "white");
     284              : 
     285            0 :       fEqConfReadOnlyWhenRunning = true;
     286            0 :       fEqConfWriteEventsToOdb = false;
     287              : 
     288            0 :       fOdbEqSettings->RI("event_size", &fEventSize, true);
     289            0 :       fOdbEqSettings->RD("event_sleep_sec", &fEventSleep, true);
     290              : 
     291            0 :       printf("Event size set to %d bytes\n", fEventSize);
     292              : 
     293            0 :       fEventBuffer.resize(16+8+16+fEventSize+100);
     294              : 
     295              :       //size = sizeof(test_rb_wait_sleep);
     296              :       //status = db_get_value(hDB, hSet, "rb_wait_sleep", &test_rb_wait_sleep, &size, TID_DWORD, TRUE);
     297              :       //assert(status == DB_SUCCESS);
     298              :       //printf("Ring buffer wait sleep %d ms\n", test_rb_wait_sleep);
     299              : 
     300            0 :       fThread = new std::thread(&EqBulk::Thread, this);
     301              :       
     302            0 :       return TMFeOk();
     303              :    }
     304              : 
     305            0 :    void SendEvent()
     306              :    {
     307            0 :       char* buf = fEventBuffer.data();
     308            0 :       size_t bufsize = fEventBuffer.size();
     309            0 :       ComposeEvent(buf, bufsize);
     310            0 :       BkInit(buf, bufsize);
     311              :          
     312            0 :       char* ptr = (char*)BkOpen(buf, "bulk", TID_BYTE);
     313            0 :       ptr += fEventSize;
     314            0 :       BkClose(buf, ptr);
     315              : 
     316            0 :       EqSendEvent(buf);
     317            0 :    }
     318              : 
     319            0 :    void Thread()
     320              :    {
     321            0 :       printf("FeBulk::Thread: thread started\n");
     322              : 
     323            0 :       EqSetStatus("Thread running", "#00FF00");
     324              : 
     325            0 :       fThreadRunning = true;
     326            0 :       while (!fMfe->fShutdownRequested) {
     327            0 :          if (fMfe->fStateRunning || !fEqConfReadOnlyWhenRunning) {
     328            0 :             fMfe->Sleep(fEventSleep);
     329            0 :             SendEvent();
     330              :          } else {
     331            0 :             fMfe->Sleep(1.0);
     332              :          }
     333              :       }
     334              :       
     335            0 :       printf("FeBulk::Thread: thread finished\n");
     336            0 :       fThreadRunning = false;
     337            0 :    }
     338              : 
     339              : #if 0
     340              :    EQUIPMENT equipment[] = {
     341              : 
     342              :   { "test"   ,         /* equipment name */
     343              :     {
     344              :       EVID_TEST, (1<<EVID_TEST),           /* event ID, trigger mask */
     345              :       "SYSTEM",             /* event buffer */
     346              :       EQ_USER,              /* equipment type */
     347              :       0,                    /* event source */
     348              :       "MIDAS",              /* format */
     349              :       TRUE,                 /* enabled */
     350              :       RO_RUNNING,           /* Read when running */
     351              :       100,                  /* poll every so milliseconds */
     352              :       0,                    /* stop run after this event limit */
     353              :       0,                    /* number of sub events */
     354              :       0,                    /* no history */
     355              :       "", "", ""
     356              :     },
     357              :     read_test_event,/* readout routine */
     358              :   },
     359              :   { "" }
     360              : };
     361              : #endif
     362              : };
     363              : 
     364              : class EqRpc :
     365              :    public TMFeEquipment
     366              : {
     367              : public:
     368            0 :    EqRpc(const char* eqname, const char* eqfilename) // ctor
     369            0 :       : TMFeEquipment(eqname, eqfilename)
     370              :    {
     371            0 :       fEqConfEventID = 1;
     372            0 :    }
     373              : 
     374            0 :    ~EqRpc() // dtor
     375            0 :    {
     376            0 :    }
     377              : 
     378            0 :    TMFeResult HandleInit(const std::vector<std::string>& args)
     379              :    {
     380            0 :       fEqConfBuffer = "SYSTEM";
     381            0 :       EqSetStatus("Started...", "white");
     382            0 :       fMfe->Msg(MINFO, "HandleInit", std::string("Init") + " Ok!");
     383            0 :       return TMFeOk();
     384              :    }
     385              : 
     386            0 :    TMFeResult HandleRpc(const char* cmd, const char* args, std::string& response)
     387              :    {
     388            0 :       fMfe->Msg(MINFO, "HandleRpc", "RPC cmd [%s], args [%s]", cmd, args);
     389              : 
     390              :       // RPC handler
     391              :       
     392              :       char tmp[256];
     393            0 :       time_t now = time(NULL);
     394            0 :       sprintf(tmp, "{ \"current_time\" : [ %d, \"%s\"] }", (int)now, ctime(&now));
     395              :       
     396            0 :       response = tmp;
     397              : 
     398            0 :       return TMFeOk();
     399              :    }
     400              : 
     401            0 :    TMFeResult HandleBinaryRpc(const char* cmd, const char* args, std::vector<char>& response)
     402              :    {
     403            0 :       fMfe->Msg(MINFO, "HandleBinaryRpc", "RPC cmd [%s], args [%s]", cmd, args);
     404              : 
     405              :       // RPC handler
     406              :       
     407            0 :       response.resize(8*64);
     408              : 
     409            0 :       uint64_t* p64 = (uint64_t*)response.data();
     410              : 
     411            0 :       for (size_t i=0; i<response.size()/sizeof(p64[0]); i++) {
     412            0 :          *p64++ = (1<<i);
     413              :       }
     414              :       
     415            0 :       return TMFeOk();
     416              :    }
     417              : 
     418            0 :    TMFeResult HandleBeginRun(int run_number)
     419              :    {
     420            0 :       fMfe->Msg(MINFO, "HandleBeginRun", "Begin run %d!", run_number);
     421            0 :       EqSetStatus("Running", "#00FF00");
     422              :       
     423            0 :       printf("begin_of_run %d\n", run_number);
     424              :       
     425            0 :       int fail = 0;
     426            0 :       fOdbEqSettings->RI("begin_of_run_fail", &fail, true);
     427              :       
     428            0 :       if (fail) {
     429            0 :          printf("fail_begin_of_run: returning error status %d\n", fail);
     430            0 :          return TMFeErrorMessage("begin of run failed by ODB setting!");
     431              :       }
     432              :       
     433            0 :       double s = 0;
     434            0 :       fOdbEqSettings->RD("begin_of_run_sleep_sec", &s, true);
     435              :       
     436            0 :       if (s) {
     437            0 :          fMfe->SetWatchdogSec(s + 1);
     438            0 :          int ms = int(s*1000.0);
     439            0 :          printf("sleep_begin_of_run: calling ss_sleep(%d)\n", ms);
     440            0 :          ss_sleep(ms);
     441              :       }
     442              :       
     443            0 :       return TMFeOk();
     444              :    }
     445              : 
     446            0 :    TMFeResult HandleEndRun(int run_number)
     447              :    {
     448            0 :       fMfe->Msg(MINFO, "HandleEndRun", "End run %d!", run_number);
     449            0 :       EqSetStatus("Stopped", "#00FF00");
     450              : 
     451            0 :       printf("end_of_run %d\n", run_number);
     452              :       
     453            0 :       int fail = 0;
     454            0 :       fOdbEqSettings->RI("end_of_run_fail", &fail, true);
     455              :       
     456            0 :       if (fail) {
     457            0 :          printf("fail_end_of_run: returning error status %d\n", fail);
     458            0 :          return TMFeResult(fail, "end of run failed by ODB setting!");
     459              :       }
     460              :       
     461            0 :       double s = 0;
     462            0 :       fOdbEqSettings->RD("end_of_run_sleep_sec", &s, true);
     463              :       
     464            0 :       if (s) {
     465            0 :          fMfe->SetWatchdogSec(s + 1);
     466            0 :          int ms = int(s*1000.0);
     467            0 :          printf("sleep_end_of_run: calling ss_sleep(%d)\n", ms);
     468            0 :          ss_sleep(ms);
     469              :       }
     470              :       
     471            0 :       return TMFeOk();
     472              :    }
     473              : 
     474            0 :    TMFeResult HandlePauseRun(int run_number)
     475              :    {
     476            0 :       fMfe->Msg(MINFO, "HandlePauseRun", "Pause run %d!", run_number);
     477            0 :       EqSetStatus("Stopped", "#00FF00");
     478              : 
     479            0 :       printf("pause_run %d\n", run_number);
     480              : 
     481            0 :       int fail = 0;
     482            0 :       fOdbEqSettings->RI("pause_run_fail", &fail, true);
     483              :       
     484            0 :       if (fail) {
     485            0 :          printf("fail_pause_run: returning error status %d\n", fail);
     486            0 :          return TMFeResult(fail, "pause run failed by ODB setting!");
     487              :       }
     488              :       
     489            0 :       return TMFeOk();
     490              :    }
     491              : 
     492            0 :    TMFeResult HandleResumeRun(int run_number)
     493              :    {
     494            0 :       fMfe->Msg(MINFO, "HandleResumeRun", "Resume run %d!", run_number);
     495            0 :       EqSetStatus("Stopped", "#00FF00");
     496              : 
     497            0 :       printf("resume_run %d\n", run_number);
     498              : 
     499            0 :       int fail = 0;
     500            0 :       fOdbEqSettings->RI("resume_run_fail", &fail, true);
     501              :       
     502            0 :       if (fail) {
     503            0 :          printf("fail_resume_run: returning error status %d\n", fail);
     504            0 :          return TMFeResult(fail, "resume run failed by ODB setting!");
     505              :       }
     506              :       
     507            0 :       return TMFeOk();
     508              :    }
     509              : 
     510            0 :    TMFeResult HandleStartAbortRun(int run_number)
     511              :    {
     512            0 :       fMfe->Msg(MINFO, "HandleStartAbortRun", "Begin run %d aborted!", run_number);
     513            0 :       EqSetStatus("Stopped", "#00FF00");
     514              : 
     515            0 :       printf("start abort run %d\n", run_number);
     516              : 
     517            0 :       int fail = 0;
     518            0 :       fOdbEqSettings->RI("start_abort_fail", &fail, true);
     519              :       
     520            0 :       if (fail) {
     521            0 :          printf("fail_start_abort: returning error status %d\n", fail);
     522            0 :          return TMFeResult(fail, "start abort failed by ODB setting!");
     523              :       }
     524              :       
     525            0 :       return TMFeOk();
     526              :    }
     527              : };
     528              : 
     529              : class FeTest: public TMFrontend
     530              : {
     531              : public:
     532            0 :    FeTest() // ctor
     533            0 :    {
     534            0 :       FeSetName("fetest");
     535            0 :       FeAddEquipment(new EqRpc("test_rpc", __FILE__));
     536            0 :       FeAddEquipment(new EqRandom("test_random", __FILE__));
     537            0 :       FeAddEquipment(new EqSlow("test_slow", __FILE__));
     538            0 :       FeAddEquipment(new EqRare("test_rare", __FILE__));
     539            0 :       FeAddEquipment(new EqBulk("test_bulk", __FILE__));
     540            0 :    }
     541              : 
     542            0 :    void HandleUsage()
     543              :    {
     544              :       //printf("FeEverything::HandleUsage!\n");
     545            0 :    };
     546              :    
     547            0 :    TMFeResult HandleArguments(const std::vector<std::string>& args)
     548              :    {
     549              :       //printf("FeEverything::HandleArguments!\n");
     550            0 :       return TMFeOk();
     551              :    };
     552              :    
     553            0 :    TMFeResult HandleFrontendInit(const std::vector<std::string>& args)
     554              :    {
     555              :       //printf("FeEverything::HandleFrontendInit!\n");
     556            0 :       return TMFeOk();
     557              :    };
     558              :    
     559            0 :    TMFeResult HandleFrontendReady(const std::vector<std::string>& args)
     560              :    {
     561              :       //printf("FeEverything::HandleFrontendReady!\n");
     562              :       //FeStartPeriodicThread();
     563              :       //fMfe->StartRpcThread();
     564            0 :       return TMFeOk();
     565              :    };
     566              :    
     567            0 :    void HandleFrontendExit()
     568              :    {
     569              :       //printf("FeEverything::HandleFrontendExit!\n");
     570            0 :    };
     571              : };
     572              : 
     573              : // boilerplate main function
     574              : 
     575            0 : int main(int argc, char* argv[])
     576              : {
     577            0 :    FeTest fe_test;
     578            0 :    return fe_test.FeMain(argc, argv);
     579            0 : }
     580              : 
     581              : /* emacs
     582              :  * Local Variables:
     583              :  * tab-width: 8
     584              :  * c-basic-offset: 3
     585              :  * indent-tabs-mode: nil
     586              :  * End:
     587              :  */
        

Generated by: LCOV version 2.0-1