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

            Line data    Source code
       1              : /********************************************************************\
       2              : 
       3              :   Name:         history_common.cxx
       4              :   Created by:   Konstantin Olchanski
       5              : 
       6              :   Contents:     History functions common to all history implementations
       7              : 
       8              : \********************************************************************/
       9              : 
      10              : #include <stdio.h>
      11              : #include <stdlib.h>
      12              : #include <string.h>
      13              : #include <assert.h>
      14              : 
      15              : #include <map>
      16              : 
      17              : #include "midas.h"
      18              : #include "msystem.h"
      19              : #include "history.h"
      20              : #include "mstrlcpy.h"
      21              : 
      22            0 : int hs_get_history(HNDLE hDB, HNDLE hKey, int flags, int debug_flag, MidasHistoryInterface **mh)
      23              : {
      24              :    int status, size;
      25            0 :    std::string type;
      26              :    int active;
      27              :    int debug;
      28              :    KEY key;
      29              : 
      30            0 :    *mh = NULL;
      31              : 
      32            0 :    if (!hKey || (flags&HS_GET_DEFAULT)) {
      33            0 :       status = hs_find_reader_channel(hDB, &hKey, debug_flag);
      34            0 :       if (status != HS_SUCCESS)
      35            0 :          return status;
      36              :    }
      37              : 
      38            0 :    status = db_get_key(hDB, hKey, &key);
      39            0 :    assert(status == DB_SUCCESS);
      40              : 
      41            0 :    if (strcasecmp(key.name, "image") == 0) {
      42            0 :       if (debug_flag)
      43            0 :          cm_msg(MINFO, "hs_get_history", "History channel \'IMAGE\' handled by image facility");
      44            0 :       return DB_NO_KEY;
      45              :    }
      46              : 
      47            0 :    active = 0;
      48            0 :    size = sizeof(active);
      49            0 :    status = db_get_value(hDB, hKey, "Active", &active, &size, TID_BOOL, TRUE);
      50            0 :    assert(status == DB_SUCCESS);
      51              :    
      52            0 :    status = db_get_value_string(hDB, hKey, "Type", 0, &type, TRUE);
      53            0 :    assert(status == DB_SUCCESS);
      54              :    
      55            0 :    debug = 0;
      56            0 :    size = sizeof(debug);
      57            0 :    status = db_get_value(hDB, hKey, "Debug", &debug, &size, TID_INT, TRUE);
      58            0 :    assert(status == DB_SUCCESS);
      59              : 
      60            0 :    if (debug_flag)
      61            0 :       printf("hs_get_history: see channel hkey %d, name \'%s\', active %d, type [%s], debug %d\n", hKey, key.name, active, type.c_str(), debug);
      62              : 
      63            0 :    if (strcasecmp(type.c_str(), "MIDAS")==0) {
      64              : 
      65            0 :       std::string tmp;
      66              :       // create ODB "History dir"
      67            0 :       db_get_value_string(hDB, hKey, "History dir", 0, &tmp, TRUE);
      68              : 
      69            0 :       std::string path = cm_get_history_path(key.name);
      70              : 
      71              :       int i;
      72              :       
      73            0 :       i = 1;
      74            0 :       size = sizeof(i);
      75            0 :       status = db_get_value(hDB, 0, "/Logger/WriteFileHistory", &i, &size, TID_BOOL, FALSE);
      76            0 :       if (status==DB_SUCCESS) {
      77            0 :          cm_msg(MERROR, "hs_get_history", "mlogger ODB setting /Logger/WriteFileHistory is obsolete, please delete it. Use /Logger/History/MIDAS/Active instead");
      78            0 :          if (i==0)
      79            0 :             active = 0;
      80              :       }
      81              :       
      82            0 :       if (active || (flags & HS_GET_INACTIVE)) {
      83            0 :          *mh = MakeMidasHistory();
      84            0 :          assert(*mh);
      85              :          
      86            0 :          (*mh)->hs_set_debug(debug);
      87              :          
      88            0 :          status = (*mh)->hs_connect(path.c_str());
      89            0 :          if (status != HS_SUCCESS) {
      90            0 :             cm_msg(MERROR, "hs_get_history", "Cannot connect to MIDAS history, status %d", status);
      91            0 :             return status;
      92              :          }
      93              : 
      94            0 :          if (debug_flag)
      95            0 :             cm_msg(MINFO, "hs_get_history", "Connected history channel \'%s\' type MIDAS history in \"%s\"", key.name, path.c_str());
      96              :       }
      97              :       
      98            0 :    } else if (strcasecmp(type.c_str(), "ODBC")==0) {
      99              : 
     100              :       if (1) {
     101              :          int i;
     102              :       
     103            0 :          i = 0;
     104            0 :          size = sizeof(i);
     105            0 :          status = db_get_value(hDB, 0, "/Logger/ODBC_Debug", &i, &size, TID_INT, FALSE);
     106            0 :          if (status==DB_SUCCESS) {
     107            0 :             cm_msg(MERROR, "hs_get_history", "mlogger ODB setting /Logger/ODBC_Debug is obsolete, please delete it. Use /Logger/History/ODBC/Debug instead");
     108              :          }
     109              : 
     110            0 :          status = db_get_value(hDB, 0, "/History/ODBC_Debug", &i, &size, TID_INT, FALSE);
     111            0 :          if (status==DB_SUCCESS) {
     112            0 :             cm_msg(MERROR, "hs_get_history", "mhttpd ODB setting /History/ODBC_Debug is obsolete, please delete it. Use /Logger/History/ODBC/Debug instead");
     113              :          }
     114              :       
     115            0 :          std::string dsn;
     116              :       
     117            0 :          status = db_get_value_string(hDB, 0, "/Logger/ODBC_DSN", 0, &dsn, FALSE);
     118            0 :          if (status==DB_SUCCESS) {
     119            0 :             cm_msg(MERROR, "hs_get_history", "mlogger ODB setting /Logger/ODBC_DSN is obsolete, please delete it. Use /Logger/History/ODBC/Writer_ODBC_DSN instead");
     120              :          }
     121              : 
     122            0 :          status = db_get_value_string(hDB, 0, "/History/ODBC_DSN", 0, &dsn, FALSE);
     123            0 :          if (status==DB_SUCCESS) {
     124            0 :             cm_msg(MERROR, "hs_get_history", "mhttpd ODB setting /History/ODBC_DSN is obsolete, please delete it. Use /Logger/History/ODBC/Reader_ODBC_DSN instead");
     125              :          }
     126            0 :       }
     127              : 
     128            0 :       std::string writer_dsn = "history_writer";
     129            0 :       std::string reader_dsn = "history_reader";
     130              :       
     131            0 :       status = db_get_value_string(hDB, hKey, "Writer_ODBC_DSN", 0, &writer_dsn, TRUE);
     132            0 :       assert(status == DB_SUCCESS);
     133              : 
     134            0 :       status = db_get_value_string(hDB, hKey, "Reader_ODBC_DSN", 0, &reader_dsn, TRUE);
     135            0 :       assert(status == DB_SUCCESS);
     136              :       
     137            0 :       std::string dsn;
     138              : 
     139            0 :       if (flags & HS_GET_READER)
     140            0 :          dsn = reader_dsn;
     141            0 :       else if (flags & HS_GET_WRITER)
     142            0 :          dsn = writer_dsn;
     143              :       
     144            0 :       if (active || (flags & HS_GET_INACTIVE)) {
     145            0 :          if (debug == 2) {
     146            0 :             *mh = MakeMidasHistorySqlDebug();
     147            0 :          } else if (dsn.length() > 1) {
     148            0 :             *mh = MakeMidasHistoryODBC();
     149              :          }
     150              : 
     151            0 :          if (*mh == NULL)
     152            0 :             return HS_FILE_ERROR;
     153              :          
     154            0 :          (*mh)->hs_set_debug(debug);
     155              : 
     156            0 :          status = (*mh)->hs_connect(dsn.c_str());
     157            0 :          if (status != HS_SUCCESS) {
     158            0 :             cm_msg(MERROR, "hs_get_history", "Cannot connect to ODBC SQL driver \'%s\', status %d. Check .odbc.ini and MIDAS documentation", dsn.c_str(), status);
     159            0 :             return status;
     160              :          }
     161              : 
     162            0 :          if (debug_flag)
     163            0 :             cm_msg(MINFO, "hs_get_history", "Connected history channel \'%s\' type ODBC (MySQL), DSN \'%s\'", key.name, dsn.c_str());
     164              :       }
     165            0 :    } else if (strcasecmp(type.c_str(), "SQLITE")==0) {
     166              : 
     167            0 :       std::string tmp;
     168              :       // create ODB "History dir"
     169            0 :       db_get_value_string(hDB, hKey, "History dir", 0, &tmp, TRUE);
     170              : 
     171            0 :       std::string path = cm_get_history_path(key.name);
     172              : 
     173            0 :       if (active || (flags & HS_GET_INACTIVE)) {
     174            0 :          *mh = MakeMidasHistorySqlite();
     175            0 :          if (*mh == NULL)
     176            0 :             return HS_FILE_ERROR;
     177              :          
     178            0 :          (*mh)->hs_set_debug(debug);
     179              : 
     180            0 :          status = (*mh)->hs_connect(path.c_str());
     181            0 :          if (status != HS_SUCCESS) {
     182            0 :             cm_msg(MERROR, "hs_get_history", "Cannot connect to SQLITE history, status %d, see messages", status);
     183            0 :             return status;
     184              :          }
     185              : 
     186            0 :          if (debug_flag)
     187            0 :             cm_msg(MINFO, "hs_get_history", "Connected history channel \'%s\' type SQLITE in \'%s\'", key.name, path.c_str());
     188              :       }
     189            0 :    } else if (strcasecmp(type.c_str(), "FILE")==0) {
     190              : 
     191            0 :       std::string tmp;
     192              :       // create ODB "History dir"
     193            0 :       db_get_value_string(hDB, hKey, "History dir", 0, &tmp, TRUE);
     194              : 
     195            0 :       std::string path = cm_get_history_path(key.name);
     196              : 
     197              :       //printf("FILE path [%s], expt_path [%s], local History Dir [%s]\n", path.c_str(), expt_path, dir);
     198              : 
     199            0 :       if (active || (flags & HS_GET_INACTIVE)) {
     200            0 :          *mh = MakeMidasHistoryFile();
     201            0 :          if (*mh == NULL)
     202            0 :             return HS_FILE_ERROR;
     203              :          
     204            0 :          (*mh)->hs_set_debug(debug);
     205              :          
     206            0 :          status = (*mh)->hs_connect(path.c_str());
     207            0 :          if (status != HS_SUCCESS) {
     208            0 :             cm_msg(MERROR, "hs_get_history", "Cannot connect to FILE history, status %d, see messages", status);
     209            0 :             return status;
     210              :          }
     211              :          
     212            0 :          if (debug_flag)
     213            0 :             cm_msg(MINFO, "hs_get_history", "Connected history channel \'%s\' type FILE in \'%s\'", key.name, path.c_str());
     214              :       }
     215            0 :    } else if (strcasecmp(type.c_str(), "MYSQL")==0) {
     216              : 
     217            0 :       std::string writer_dsn = "mysql_writer.txt";
     218            0 :       std::string reader_dsn = "mysql_reader.txt";
     219              : 
     220            0 :       status = db_get_value_string(hDB, hKey, "MYSQL Writer", 0, &writer_dsn, TRUE);
     221            0 :       assert(status == DB_SUCCESS);
     222              : 
     223            0 :       status = db_get_value_string(hDB, hKey, "MYSQL Reader", 0, &reader_dsn, TRUE);
     224            0 :       assert(status == DB_SUCCESS);
     225              : 
     226            0 :       std::string dsn;
     227              : 
     228            0 :       if (flags & HS_GET_READER)
     229            0 :          dsn = reader_dsn;
     230            0 :       else if (flags & HS_GET_WRITER)
     231            0 :          dsn = writer_dsn;
     232              : 
     233            0 :       std::string path;
     234              : 
     235            0 :       if (dsn[0] == DIR_SEPARATOR)
     236            0 :          path = dsn;
     237              :       else {
     238            0 :          std::string expt_path = cm_get_path();
     239              : 
     240            0 :          path = expt_path;
     241              :          // normally expt_path has the trailing '/', see midas.c::cm_set_path()
     242            0 :          if (path[path.length() - 1] != DIR_SEPARATOR)
     243            0 :             path += DIR_SEPARATOR_STR;
     244            0 :          path += dsn;
     245            0 :       }
     246              : 
     247            0 :       if (active || (flags & HS_GET_INACTIVE)) {
     248            0 :          *mh = MakeMidasHistoryMysql();
     249            0 :          if (*mh == NULL)
     250            0 :             return HS_FILE_ERROR;
     251              : 
     252            0 :          (*mh)->hs_set_debug(debug);
     253              : 
     254            0 :          status = (*mh)->hs_connect(path.c_str());
     255            0 :          if (status != HS_SUCCESS) {
     256            0 :             cm_msg(MERROR, "hs_get_history", "Cannot connect to MYSQL history, status %d", status);
     257            0 :             return status;
     258              :          }
     259              : 
     260            0 :          if (debug_flag)
     261            0 :             cm_msg(MINFO, "hs_get_history", "Connected history channel \'%s\' type MYSQL at \'%s\'", key.name,
     262              :                    path.c_str());
     263              :       }
     264            0 :    } else if (strcasecmp(type.c_str(), "PGSQL")==0) {
     265              : 
     266            0 :       std::string writer_dsn = "pgsql_writer.txt";
     267            0 :       std::string reader_dsn = "pgsql_reader.txt";
     268              : 
     269            0 :       status = db_get_value_string(hDB, hKey, "PGSQL Writer", 0, &writer_dsn, TRUE);
     270            0 :       assert(status == DB_SUCCESS);
     271              : 
     272            0 :       status = db_get_value_string(hDB, hKey, "PGSQL Reader", 0, &reader_dsn, TRUE);
     273            0 :       assert(status == DB_SUCCESS);
     274              : 
     275            0 :       std::string dsn;
     276              : 
     277            0 :       if (flags & HS_GET_READER)
     278            0 :          dsn = reader_dsn;
     279            0 :       else if (flags & HS_GET_WRITER)
     280            0 :          dsn = writer_dsn;
     281              : 
     282            0 :       std::string path;
     283              : 
     284            0 :       if (dsn[0] == DIR_SEPARATOR)
     285            0 :          path = dsn;
     286              :       else {
     287            0 :          std::string expt_path = cm_get_path();
     288              : 
     289            0 :          path = expt_path;
     290              :          // normally expt_path has the trailing '/', see midas.c::cm_set_path()
     291            0 :          if (path[path.length() - 1] != DIR_SEPARATOR)
     292            0 :             path += DIR_SEPARATOR_STR;
     293            0 :          path += dsn;
     294            0 :       }
     295              : 
     296            0 :       int downsample = 0;
     297            0 :       size = sizeof(downsample);
     298            0 :       status = db_get_value(hDB, hKey, "Enable downsampling queries", &downsample, &size, TID_BOOL, TRUE);
     299            0 :       assert(status == DB_SUCCESS);
     300              : 
     301            0 :       if (active || (flags & HS_GET_INACTIVE)) {
     302            0 :          *mh = MakeMidasHistoryPgsql();
     303            0 :          if (*mh == NULL)
     304            0 :             return HS_FILE_ERROR;
     305              : 
     306            0 :          (*mh)->hs_set_debug(debug);
     307              :          //(*mh)->hs_set_downsample(downsample);
     308              : 
     309            0 :          status = (*mh)->hs_connect(path.c_str());
     310            0 :          if (status != HS_SUCCESS) {
     311            0 :             cm_msg(MERROR, "hs_get_history", "Cannot connect to PGSQL history, status %d", status);
     312            0 :             return status;
     313              :          }
     314              : 
     315            0 :          if (debug_flag)
     316            0 :             cm_msg(MINFO, "hs_get_history", "Connected history channel \'%s\' type PGSQL at \'%s\'", key.name,
     317              :                    path.c_str());
     318              :       }
     319            0 :    } else if (strcasecmp(type.c_str(), "IMAGE")==0) {
     320            0 :       if (debug_flag)
     321            0 :          cm_msg(MINFO, "hs_get_history", "History channel \'IMAGE\' handled by image facility");
     322              :    } else {
     323            0 :       cm_msg(MERROR, "hs_get_history", "Logger history channel /Logger/History/%s/Type has invalid value \'%s\', valid values are MIDAS, ODBC, SQLITE, MYSQL, FILE and IMAGE", key.name, type.c_str());
     324            0 :       return HS_FILE_ERROR;
     325              :    }
     326              : 
     327            0 :    if (*mh == NULL)
     328            0 :       return HS_FILE_ERROR;
     329              :    
     330            0 :    mstrlcpy((*mh)->name, key.name, sizeof((*mh)->name));
     331            0 :    mstrlcpy((*mh)->type, type.c_str(), sizeof((*mh)->type));
     332              : 
     333            0 :    return HS_SUCCESS;
     334            0 : }
     335              : 
     336              : // find history reader channel, returns ODB handle to the history channel definition in /Logger/History/...
     337            0 : int hs_find_reader_channel(HNDLE hDB, HNDLE* hKeyOut, int debug_flag)
     338              : {
     339              :    int status;
     340              :    int size;
     341              :    HNDLE hKeyChan;
     342              :    HNDLE hKey;
     343            0 :    std::string hschanname;
     344              : 
     345            0 :    *hKeyOut = 0;
     346              : 
     347            0 :    status = db_find_key(hDB, 0, "/Logger/History", &hKeyChan);
     348            0 :    if (status != DB_SUCCESS) {
     349            0 :       cm_msg(MERROR, "hs_find_reader_channel", "Cannot find /Logger/History, db_find_key() status %d", status);
     350            0 :       return status;
     351              :    }
     352              : 
     353              :    // get history channel name selected by user in ODB
     354              : 
     355            0 :    status = db_get_value_string(hDB, 0, "/History/LoggerHistoryChannel", 0, &hschanname, TRUE);
     356            0 :    assert(status == DB_SUCCESS);
     357              : 
     358            0 :    if (hschanname.length() > 0) {
     359            0 :       status = db_find_key(hDB, hKeyChan, hschanname.c_str(), &hKey);
     360            0 :       if (status == DB_NO_KEY) {
     361            0 :          cm_msg(MERROR, "hs_find_reader_channel", "Misconfigured history: history channel name in /History/LoggerHistoryChannel is \'%s\', not present in /Logger/History, db_find_key() status %d", hschanname.c_str(), status);
     362            0 :          return HS_FILE_ERROR;
     363              :       }
     364            0 :       assert(status == DB_SUCCESS);
     365            0 :       *hKeyOut = hKey;
     366            0 :       return HS_SUCCESS;
     367              :    }
     368              : 
     369              :    //  if selected channel name is blank, find first active channel
     370              :    
     371            0 :    for (int ichan=0; ; ichan++) {
     372            0 :       status = db_enum_key(hDB, hKeyChan, ichan, &hKey);
     373            0 :       if (status != DB_SUCCESS)
     374            0 :          break;
     375              :       
     376            0 :       int active = 0;
     377            0 :       size = sizeof(active);
     378            0 :       status = db_get_value(hDB, hKey, "Active", &active, &size, TID_BOOL, FALSE);
     379            0 :       if (status == DB_SUCCESS && active != 0) {
     380            0 :          *hKeyOut = hKey;
     381            0 :          return HS_SUCCESS;
     382              :       }
     383            0 :    }
     384              :    
     385            0 :    cm_msg(MERROR, "hs_find_reader_channel", "Cannot find default history: /History/LoggerHistoryChannel is empty and there are no active history channels in /Logger/History");
     386            0 :    return HS_FILE_ERROR;
     387            0 : }
     388              : 
     389            0 : static std::string hs_event_list_filename()
     390              : {
     391            0 :    std::string path = cm_get_path();
     392            0 :    return path + ".LOGGER_HISTORY_EVENTS.TXT";
     393            0 : }
     394              : 
     395              : // save list of active events
     396            0 : int hs_save_event_list(const std::vector<std::string> *pevents)
     397              : {
     398            0 :    std::string ss;
     399            0 :    for (unsigned i=0; i<pevents->size(); i++)
     400            0 :       ss += (*pevents)[i] + "\n";
     401              : 
     402            0 :    std::string fname = hs_event_list_filename();
     403              : 
     404            0 :    FILE *fp = fopen(fname.c_str(), "w");
     405            0 :    if (!fp) {
     406            0 :       cm_msg(MERROR, "hs_save_event_list", "Cannot open file \'%s\', errno %d (%s)", fname.c_str(), errno, strerror(errno));
     407            0 :       return HS_FILE_ERROR;
     408              :    }
     409              : 
     410            0 :    const char* s = ss.c_str();
     411            0 :    int len = strlen(s);
     412              : 
     413            0 :    int wr = write(fileno(fp), s, len);
     414              : 
     415            0 :    if (wr != len) {
     416            0 :       cm_msg(MERROR, "hs_save_event_list", "Cannot write to file \'%s\', errno %d (%s)", fname.c_str(), errno, strerror(errno));
     417            0 :       fclose(fp);
     418            0 :       return HS_FILE_ERROR;
     419              :    }
     420              : 
     421            0 :    fclose(fp);
     422            0 :    return HS_SUCCESS;
     423            0 : }
     424              : 
     425              : // get list of active events
     426            0 : int hs_read_event_list(std::vector<std::string> *pevents)
     427              : {
     428            0 :    std::string fname = hs_event_list_filename();
     429              : 
     430            0 :    FILE *fp = fopen(fname.c_str(), "r");
     431            0 :    if (!fp) {
     432            0 :       cm_msg(MERROR, "hs_read_event_list", "Cannot open file \'%s\', errno %d (%s)", fname.c_str(), errno, strerror(errno));
     433            0 :       return HS_FILE_ERROR;
     434              :    }
     435              : 
     436              :    while (1) {
     437              :       char buf[256];
     438            0 :       char *s = fgets(buf, sizeof(buf), fp);
     439            0 :       if (!s) // EOF
     440            0 :          break;
     441              :       // kill trailing \n and \r
     442            0 :       s = strchr(buf, '\n');
     443            0 :       if (s)
     444            0 :          *s = 0;
     445            0 :       s = strchr(buf, '\r');
     446            0 :       if (s)
     447            0 :          *s = 0;
     448            0 :       pevents->push_back(buf);
     449            0 :    }
     450              : 
     451            0 :    fclose(fp);
     452            0 :    return HS_SUCCESS;
     453            0 : }
     454              : 
     455              : /* emacs
     456              :  * Local Variables:
     457              :  * tab-width: 8
     458              :  * c-basic-offset: 3
     459              :  * indent-tabs-mode: nil
     460              :  * End:
     461              :  */
        

Generated by: LCOV version 2.0-1