MIDAS
Loading...
Searching...
No Matches
mlogger.cxx File Reference
#include "midas.h"
#include "msystem.h"
#include "hardware.h"
#include "mstrlcpy.h"
#include <errno.h>
#include <assert.h>
#include <string>
#include "mdsupport.h"
#include <zlib.h>
#include "crc32c.h"
#include "sha256.h"
#include "sha512.h"
#include "mlz4frame.h"
#include "history.h"
Include dependency graph for mlogger.cxx:

Go to the source code of this file.

Classes

struct  CHN_SETTINGS
 
struct  CHN_STATISTICS
 
struct  LOG_CHN
 
struct  hist_log_s
 
struct  MIDAS_INFO
 
class  WriterInterface
 
class  WriterNull
 
class  WriterFile
 
class  WriterGzip
 
class  WriterPopen
 
class  WriterCRC32Zlib
 
class  WriterCRC32C
 
class  WriterSHA256
 
class  WriterSHA512
 
class  WriterLZ4
 
class  WriterFtp
 
struct  EVENT_DEF
 

Macros

#define HAVE_LOGGING
 
#define CHN_TREE_STR(_name)
 
#define CHN_SETTINGS_STR(_name)
 
#define CHN_STATISTICS_STR(_name)
 
#define DISK_CHECK_INTERVAL_MILLISEC   10000
 
#define MEMZERO(obj)   memset(&(obj), 0, sizeof(obj))
 
#define FREE(ptr)   if (ptr) free(ptr); (ptr)=NULL;
 
#define DELETE(ptr)   if (ptr) delete (ptr); (ptr)=NULL;
 
#define EVENT_DEF_CACHE_SIZE   30
 
#define CHECKSUM_NONE   0
 
#define CHECKSUM_ZLIB   1
 
#define CHECKSUM_CRC32C   2
 
#define CHECKSUM_SHA256   3
 
#define CHECKSUM_SHA512   4
 
#define COMPRESS_NONE   0
 
#define COMPRESS_ZLIB   1
 
#define COMPRESS_LZ4   2
 
#define COMPRESS_BZIP2   3
 
#define COMPRESS_PBZIP2   4
 
#define OUTPUT_NONE   0
 
#define OUTPUT_NULL   1
 
#define OUTPUT_FILE   2
 
#define OUTPUT_FTP   3
 
#define OUTPUT_PIPE   5
 

Functions

void create_runlog_ascii_tree ()
 
void create_runlog_json_tree ()
 
static std::string IntToString (int value)
 
static std::string TimeToString (time_t t)
 
LOG_CHNnew_LOG_CHN (const char *name)
 
static CHN_SETTINGS_STR (chn_settings_str)
 
static CHN_STATISTICS_STR (chn_statistics_str)
 
static CHN_TREE_STR (chn_tree_str)
 
void receive_event (HNDLE hBuf, HNDLE request_id, EVENT_HEADER *pheader, void *pevent)
 
INT log_write (LOG_CHN *log_chn, EVENT_HEADER *pheader)
 
void log_system_history (HNDLE hDB, HNDLE hKey, void *info)
 
int log_generate_file_name (LOG_CHN *log_chn)
 
void start_image_history ()
 
void stop_image_history ()
 
int get_number_image_history_threads ()
 
static std::string xpathname (const char *xpath, int level)
 
static FILE * fopen_wx (const char *filename)
 
static bool check_file_exists (const char *filename)
 
void logger_init ()
 
void log_odb_dump_odb (LOG_CHN *log_chn, short int event_id, INT run_number)
 
void log_odb_dump_xml (LOG_CHN *log_chn, short int event_id, INT run_number)
 
void log_odb_dump_json (LOG_CHN *log_chn, short int event_id, INT run_number)
 
void log_odb_dump (LOG_CHN *log_chn, short int event_id, INT run_number)
 
void odb_save (const char *filename, bool make_file_readonly)
 
void write_runlog_ascii (BOOL bor)
 
void write_runlog_json (BOOL bor)
 
INT ftp_error (const char *message)
 
INT ftp_open (const char *xdestination, FTP_CON **con)
 
EVENT_DEFdb_get_event_definition (short int event_id)
 
WriterInterfaceNewWriterBzip2 (LOG_CHN *log_chn)
 
WriterInterfaceNewWriterPbzip2 (LOG_CHN *log_chn)
 
WriterInterfaceNewChecksum (LOG_CHN *log_chn, int code, int level, WriterInterface *chained)
 
WriterInterfaceNewCompression (LOG_CHN *log_chn, int code, WriterInterface *chained)
 
std::string get_value (HNDLE hDB, HNDLE hDir, const char *name)
 
void set_value (HNDLE hDB, HNDLE hDir, const char *name, const std::string &set, const std::string &def)
 
int check_add (int v, int n, const std::string &val, const char *str, bool bdef, std::string *def, std::string *sel)
 
int select_checksum_module (HNDLE hDB, HNDLE hSet, const char *name)
 
int select_compression_module (HNDLE hDB, HNDLE hSet, const char *name)
 
int select_output_module (HNDLE hDB, HNDLE hSet, const char *name)
 
int log_create_writer (LOG_CHN *log_chn)
 
INT log_open (LOG_CHN *log_chn, INT run_number)
 
INT log_close (LOG_CHN *log_chn, INT run_number)
 
int log_disk_level (LOG_CHN *log_chn, double *pdisk_size, double *pdisk_free)
 
int maybe_check_disk_level ()
 
static int get_trans_flag ()
 
int stop_the_run (int restart)
 
int start_the_run ()
 
void log_history (HNDLE hDB, HNDLE hKey, void *info)
 
static int add_event (int *indexp, time_t timestamp, int event_id, const char *event_name, HNDLE hKey, int ntags, const TAG *tags, time_t min_period, int hotlink)
 
INT open_history ()
 
void maybe_flush_history (time_t now)
 
void close_history ()
 
int close_channels (int run_number, BOOL *p_tape_flag)
 
int close_buffers ()
 
static int write_history (DWORD transition, DWORD run_number)
 
static void watch_settings (HNDLE hDB, HNDLE hKey, HNDLE index, void *info)
 
INT tr_start (INT run_number, char *error)
 
INT tr_start_abort (INT run_number, char *error)
 
INT tr_stop (INT run_number, char *error)
 
INT tr_pause (INT run_number, char *error)
 
INT tr_resume (INT run_number, char *error)
 
int main (int argc, char *argv[])
 

Variables

INT local_state
 
BOOL in_stop_transition = FALSE
 
BOOL tape_message = TRUE
 
BOOL verbose = FALSE
 
BOOL stop_requested = FALSE
 
BOOL start_requested = FALSE
 
DWORD auto_restart = 0
 
DWORD run_start_time
 
DWORD subrun_start_time
 
double stop_try_later = 0
 
std::vector< LOG_CHN * > log_channels
 
static int hist_log_size = 0
 
static int hist_log_max = 0
 
static struct hist_log_shist_log = NULL
 
static HNDLE hDB
 
static std::vector< MidasHistoryInterface * > mh
 
static std::vector< std::string > history_events
 
time_t last_history_flush = 0
 

Macro Definition Documentation

◆ CHECKSUM_CRC32C

#define CHECKSUM_CRC32C   2

Definition at line 3117 of file mlogger.cxx.

◆ CHECKSUM_NONE

#define CHECKSUM_NONE   0

Definition at line 3115 of file mlogger.cxx.

◆ CHECKSUM_SHA256

#define CHECKSUM_SHA256   3

Definition at line 3118 of file mlogger.cxx.

◆ CHECKSUM_SHA512

#define CHECKSUM_SHA512   4

Definition at line 3119 of file mlogger.cxx.

◆ CHECKSUM_ZLIB

#define CHECKSUM_ZLIB   1

Definition at line 3116 of file mlogger.cxx.

◆ CHN_SETTINGS_STR

#define CHN_SETTINGS_STR (   _name)
Value:
const char *_name[] = { \
"Active = BOOL : 1",\
"Type = STRING : [8] Disk",\
"Filename = STRING : [256] run%05d.mid",\
"Format = STRING : [8] MIDAS",\
"Compression = INT32 : 0",\
"ODB dump = BOOL : 1",\
"ODB dump format = STRING : [32] json",\
"Log messages = UINT32 : 0",\
"Buffer = STRING : [32] SYSTEM",\
"Event ID = INT32 : -1",\
"Trigger mask = INT32 : -1",\
"Event limit = DOUBLE : 0",\
"Byte limit = DOUBLE : 0",\
"Subrun Byte limit = DOUBLE : 0",\
"Tape capacity = DOUBLE : 0",\
"Subdir format = STRING : [32]",\
"Current filename = STRING : [256]",\
"Data checksum = STRING : [256]",\
"File checksum = STRING : [256]",\
"Compress = STRING : [256]",\
"Output = STRING : [256]",\
"Gzip compression = UINT32 : 0",\
"Bzip2 compression = UINT32 : 0",\
"Pbzip2 num cpu = UINT32 : 0",\
"Pbzip2 compression = UINT32 : 0",\
"Pbzip2 options = STRING : [256]",\
"",\
NULL}

Definition at line 191 of file mlogger.cxx.

191 { \
192"Active = BOOL : 1",\
193"Type = STRING : [8] Disk",\
194"Filename = STRING : [256] run%05d.mid",\
195"Format = STRING : [8] MIDAS",\
196"Compression = INT32 : 0",\
197"ODB dump = BOOL : 1",\
198"ODB dump format = STRING : [32] json",\
199"Log messages = UINT32 : 0",\
200"Buffer = STRING : [32] SYSTEM",\
201"Event ID = INT32 : -1",\
202"Trigger mask = INT32 : -1",\
203"Event limit = DOUBLE : 0",\
204"Byte limit = DOUBLE : 0",\
205"Subrun Byte limit = DOUBLE : 0",\
206"Tape capacity = DOUBLE : 0",\
207"Subdir format = STRING : [32]",\
208"Current filename = STRING : [256]",\
209"Data checksum = STRING : [256]",\
210"File checksum = STRING : [256]",\
211"Compress = STRING : [256]",\
212"Output = STRING : [256]",\
213"Gzip compression = UINT32 : 0",\
214"Bzip2 compression = UINT32 : 0",\
215"Pbzip2 num cpu = UINT32 : 0",\
216"Pbzip2 compression = UINT32 : 0",\
217"Pbzip2 options = STRING : [256]",\
218"",\
219NULL}

◆ CHN_STATISTICS_STR

#define CHN_STATISTICS_STR (   _name)
Value:
const char *_name[] = {\
"Events written = DOUBLE : 0",\
"Bytes written = DOUBLE : 0",\
"Bytes written uncompressed = DOUBLE : 0",\
"Bytes written total = DOUBLE : 0",\
"Bytes written subrun = DOUBLE : 0",\
"Files written = DOUBLE : 0",\
"Disk level = DOUBLE : 0",\
"",\
NULL}

Definition at line 231 of file mlogger.cxx.

231 {\
232"Events written = DOUBLE : 0",\
233"Bytes written = DOUBLE : 0",\
234"Bytes written uncompressed = DOUBLE : 0",\
235"Bytes written total = DOUBLE : 0",\
236"Bytes written subrun = DOUBLE : 0",\
237"Files written = DOUBLE : 0",\
238"Disk level = DOUBLE : 0",\
239"",\
240NULL}

◆ CHN_TREE_STR

#define CHN_TREE_STR (   _name)

Definition at line 87 of file mlogger.cxx.

87 {\
88"[Settings]",\
89"Active = BOOL : 1",\
90"Type = STRING : [8] Disk",\
91"Filename = STRING : [256] run%05d.mid",\
92"Format = STRING : [8] MIDAS",\
93"Compression = INT32 : 0",\
94"ODB dump = BOOL : 1",\
95"ODB dump format = STRING : [32] json",\
96"Options ODB dump format = STRING[3] :",\
97"[32] odb",\
98"[32] xml",\
99"[32] json",\
100"Log messages = UINT32 : 0",\
101"Buffer = STRING : [32] SYSTEM",\
102"Event ID = INT32 : -1",\
103"Trigger mask = INT32 : -1",\
104"Event limit = DOUBLE : 0",\
105"Byte limit = DOUBLE : 0",\
106"Subrun Byte limit = DOUBLE : 0",\
107"Tape capacity = DOUBLE : 0",\
108"Subdir format = STRING : [32]",\
109"Current filename = STRING : [256]",\
110"Data checksum = STRING : [256] CRC32C",\
111"Options Data checksum = STRING[5] :",\
112"[32] NONE",\
113"[32] CRC32C",\
114"[32] SHA256",\
115"[32] SHA512",\
116"[32] ZLIB",\
117"File checksum = STRING : [256] CRC32C",\
118"Options File checksum = STRING[5] :",\
119"[32] NONE",\
120"[32] CRC32C",\
121"[32] SHA256",\
122"[32] SHA512",\
123"[32] ZLIB",\
124"Compress = STRING : [256] lz4",\
125"Options Compress = STRING[5] :",\
126"[32] none",\
127"[32] gzip",\
128"[32] lz4",\
129"[32] bzip2",\
130"[32] pbzip2",\
131"Output = STRING : [256] FILE",\
132"Options Output = STRING[5] :",\
133"[32] NULL",\
134"[32] FILE",\
135"[32] FTP",\
136"[32] ROOT",\
137"[32] PIPE",\
138"Gzip compression = UINT32 : 0",\
139"Bzip2 compression = UINT32 : 0",\
140"Pbzip2 num cpu = UINT32 : 0",\
141"Pbzip2 compression = UINT32 : 0",\
142"Pbzip2 options = STRING : [256]",\
143"",\
144"[Statistics]",\
145"Events written = DOUBLE : 0",\
146"Bytes written = DOUBLE : 0",\
147"Bytes written uncompressed = DOUBLE : 0",\
148"Bytes written total = DOUBLE : 0",\
149"Bytes written subrun = DOUBLE : 0",\
150"Files written = DOUBLE : 0",\
151"Disk level = DOUBLE : 0",\
152"",\
153NULL}

◆ COMPRESS_BZIP2

#define COMPRESS_BZIP2   3

Definition at line 3142 of file mlogger.cxx.

◆ COMPRESS_LZ4

#define COMPRESS_LZ4   2

Definition at line 3141 of file mlogger.cxx.

◆ COMPRESS_NONE

#define COMPRESS_NONE   0

Definition at line 3139 of file mlogger.cxx.

◆ COMPRESS_PBZIP2

#define COMPRESS_PBZIP2   4

Definition at line 3143 of file mlogger.cxx.

◆ COMPRESS_ZLIB

#define COMPRESS_ZLIB   1

Definition at line 3140 of file mlogger.cxx.

◆ DELETE

#define DELETE (   ptr)    if (ptr) delete (ptr); (ptr)=NULL;

Definition at line 342 of file mlogger.cxx.

◆ DISK_CHECK_INTERVAL_MILLISEC

#define DISK_CHECK_INTERVAL_MILLISEC   10000

Definition at line 284 of file mlogger.cxx.

◆ EVENT_DEF_CACHE_SIZE

#define EVENT_DEF_CACHE_SIZE   30

◆ FREE

#define FREE (   ptr)    if (ptr) free(ptr); (ptr)=NULL;

Definition at line 341 of file mlogger.cxx.

◆ HAVE_LOGGING

#define HAVE_LOGGING

Definition at line 22 of file mlogger.cxx.

◆ MEMZERO

#define MEMZERO (   obj)    memset(&(obj), 0, sizeof(obj))

Definition at line 339 of file mlogger.cxx.

◆ OUTPUT_FILE

#define OUTPUT_FILE   2

Definition at line 3159 of file mlogger.cxx.

◆ OUTPUT_FTP

#define OUTPUT_FTP   3

Definition at line 3160 of file mlogger.cxx.

◆ OUTPUT_NONE

#define OUTPUT_NONE   0

Definition at line 3157 of file mlogger.cxx.

◆ OUTPUT_NULL

#define OUTPUT_NULL   1

Definition at line 3158 of file mlogger.cxx.

◆ OUTPUT_PIPE

#define OUTPUT_PIPE   5

Definition at line 3162 of file mlogger.cxx.

Function Documentation

◆ add_event()

static int add_event ( int *  indexp,
time_t  timestamp,
int  event_id,
const char *  event_name,
HNDLE  hKey,
int  ntags,
const TAG tags,
time_t  min_period,
int  hotlink 
)
static

Definition at line 3784 of file mlogger.cxx.

3785{
3786 int status;
3787 int size, i;
3788 int index = *indexp;
3789
3790#if 0
3791 {
3792 /* print the tags */
3793 printf("add_event: event %d, name \"%s\", ntags %d\n", event_id, event_name, ntags);
3794 for (i=0; i<ntags; i++) {
3795 printf("tag %d: name \"%s\", type %d, n_data %d\n", i, tags[i].name, tags[i].type, tags[i].n_data);
3796 }
3797 }
3798#endif
3799
3800 /* check for duplicate event id's */
3801 for (i=0; i<index; i++) {
3802 if (strcmp(hist_log[i].event_name, event_name) == 0) {
3803 cm_msg(MERROR, "add_event", "Duplicate event name \'%s\' with event id %d", event_name, event_id);
3804 return 0;
3805 }
3806 }
3807
3808 while (index >= hist_log_size) {
3809 int new_size = 2*hist_log_size;
3810
3811 if (hist_log_size == 0)
3812 new_size = 10;
3813
3814 hist_log = (hist_log_s*)realloc(hist_log, sizeof(hist_log[0])*new_size);
3815 assert(hist_log!=NULL);
3816
3817 hist_log_size = new_size;
3818 }
3819
3820 if (index >= hist_log_max)
3821 hist_log_max = index + 1;
3822
3823 /* check for invalid history tags */
3824 for (i=0; i<ntags; i++) {
3825 if (tags[i].type == TID_STRING) {
3826 cm_msg(MERROR, "add_event", "Invalid tag %d \'%s\' in event %d \'%s\': cannot do history for TID_STRING data, sorry!", i, tags[i].name, event_id, event_name);
3827 return 0;
3828 }
3829 if (tags[i].type == TID_INT64) {
3830 cm_msg(MERROR, "add_event", "Invalid tag %d \'%s\' in event %d \'%s\': cannot do history for TID_INT64 data, sorry!", i, tags[i].name, event_id, event_name);
3831 return 0;
3832 }
3833 if (tags[i].type == TID_UINT64) {
3834 cm_msg(MERROR, "add_event", "Invalid tag %d \'%s\' in event %d \'%s\': cannot do history for TID_UINT64 data, sorry!", i, tags[i].name, event_id, event_name);
3835 return 0;
3836 }
3837 if (rpc_tid_size(tags[i].type) == 0) {
3838 cm_msg(MERROR, "add_event", "Invalid tag %d \'%s\' in event %d \'%s\': type %d size is zero", i, tags[i].name, event_id, event_name, tags[i].type);
3839 return 0;
3840 }
3841 }
3842
3843 /* check for trailing spaces in tag names */
3844 for (i=0; i<ntags; i++) {
3845 if (isspace(tags[i].name[strlen(tags[i].name)-1])) {
3846 cm_msg(MERROR, "add_event", "Invalid tag %d \'%s\' in event %d \'%s\': has trailing spaces", i, tags[i].name, event_id, event_name);
3847 return 0;
3848 }
3849 }
3850
3851 for (unsigned i=0; i<mh.size(); i++) {
3852 status = mh[i]->hs_define_event(event_name, timestamp, ntags, tags);
3853 if (status != HS_SUCCESS) {
3854 cm_msg(MERROR, "add_event", "Cannot define event \"%s\", hs_define_event() status %d", event_name, status);
3855 return 0;
3856 }
3857 }
3858
3859 status = db_get_record_size(hDB, hKey, 0, &size);
3860
3861 if (status != DB_SUCCESS) {
3862 cm_msg(MERROR, "add_event", "Cannot define event \"%s\", db_get_record_size() status %d", event_name, status);
3863 return 0;
3864 }
3865
3866 /* setup hist_log structure for this event */
3867 mstrlcpy(hist_log[index].event_name, event_name, sizeof(hist_log[index].event_name));
3868 hist_log[index].n_var = ntags;
3870 hist_log[index].buffer_size = size;
3871 hist_log[index].buffer = (char*)malloc(size);
3872 hist_log[index].min_period = min_period;
3873 hist_log[index].last_log = 0;
3874
3875 if (hist_log[index].buffer == NULL) {
3876 cm_msg(MERROR, "add_event", "Cannot allocate data buffer for event \"%s\" size %d", event_name, size);
3877 return 0;
3878 }
3879
3880 /* open hot link to variables */
3881 if (hotlink) {
3882 status = db_open_record(hDB, hKey, hist_log[index].buffer, size, MODE_READ, log_history, NULL);
3883 if (status != DB_SUCCESS) {
3884 cm_msg(MERROR, "add_event",
3885 "Cannot hotlink event %d \"%s\" for history logging, db_open_record() status %d",
3886 event_id, event_name, status);
3887 return status;
3888 }
3889 }
3890
3891 history_events.push_back(event_name);
3892
3893 if (verbose)
3894 printf("Created event %d for equipment \"%s\", %d tags, size %d\n", event_id, event_name, ntags, size);
3895
3896 *indexp = index+1;
3897
3898 return SUCCESS;
3899}
#define DB_SUCCESS
Definition midas.h:632
#define HS_SUCCESS
Definition midas.h:728
#define SUCCESS
Definition mcstd.h:54
#define TID_UINT64
Definition midas.h:352
#define TID_INT64
Definition midas.h:351
#define TID_STRING
Definition midas.h:346
#define MERROR
Definition midas.h:559
#define MODE_READ
Definition midas.h:370
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
Definition midas.cxx:931
INT db_open_record(HNDLE hDB, HNDLE hKey, void *ptr, INT rec_size, WORD access_mode, void(*dispatcher)(INT, INT, void *), void *info)
Definition odb.cxx:13322
INT db_get_record_size(HNDLE hDB, HNDLE hKey, INT align, INT *buf_size)
Definition odb.cxx:11640
INT rpc_tid_size(INT id)
Definition midas.cxx:11888
HNDLE hKey
INT index
Definition mana.cxx:271
INT type
Definition mana.cxx:269
INT i
Definition mdump.cxx:32
#define event_id
#define name(x)
Definition midas_macro.h:24
void log_history(HNDLE hDB, HNDLE hKey, void *info)
Definition mlogger.cxx:4606
static std::vector< MidasHistoryInterface * > mh
Definition mlogger.cxx:3781
static int hist_log_size
Definition mlogger.cxx:308
static std::vector< std::string > history_events
Definition mlogger.cxx:3782
static HNDLE hDB
Definition mlogger.cxx:312
static struct hist_log_s * hist_log
Definition mlogger.cxx:310
BOOL verbose
Definition mlogger.cxx:289
static int hist_log_max
Definition mlogger.cxx:309
DWORD status
Definition odbhist.cxx:39
char * buffer
Definition mlogger.cxx:300
HNDLE hKeyVar
Definition mlogger.cxx:302
INT buffer_size
Definition mlogger.cxx:301
time_t min_period
Definition mlogger.cxx:304
DWORD n_var
Definition mlogger.cxx:303
time_t last_log
Definition mlogger.cxx:305
Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_add()

int check_add ( int  v,
int  n,
const std::string &  val,
const char *  str,
bool  bdef,
std::string *  def,
std::string *  sel 
)

Definition at line 3184 of file mlogger.cxx.

3185{
3186 (*def) += std::string(" ") + str;
3187 if (v)
3188 return v; // keep returning the first selection
3189 if (val.find(str) == 0) {
3190 *sel = str;
3191 return n; // if no selection yet, return the new selection
3192 }
3193 return v;
3194}
DWORD n[4]
Definition mana.cxx:247
char str[256]
Definition odbhist.cxx:33
Here is the caller graph for this function:

◆ check_file_exists()

static bool check_file_exists ( const char *  filename)
static

Definition at line 368 of file mlogger.cxx.

369{
370 struct stat st;
371 int status = stat(filename, &st);
372 if (status == -1) {
373 return false;
374 }
375 return true;
376}
Here is the caller graph for this function:

◆ CHN_SETTINGS_STR()

static CHN_SETTINGS_STR ( chn_settings_str  )
static

◆ CHN_STATISTICS_STR()

static CHN_STATISTICS_STR ( chn_statistics_str  )
static

◆ CHN_TREE_STR()

static CHN_TREE_STR ( chn_tree_str  )
static

◆ close_buffers()

INT close_buffers ( void  )

Definition at line 4912 of file mlogger.cxx.

4913{
4914 /* close buffers */
4915 for (unsigned i = 0; i < log_channels.size(); i++) {
4916 LOG_CHN* chn = log_channels[i];
4917#ifndef FAL_MAIN
4918 if (chn->buffer_handle) {
4920 for (unsigned j = i + 1; j < log_channels.size(); j++)
4921 if (log_channels[j]->buffer_handle == chn->buffer_handle)
4922 log_channels[j]->buffer_handle = 0;
4923 }
4924
4925 if (chn->msg_request_id)
4927#endif
4928
4929 delete chn;
4930 log_channels[i] = NULL;
4931 }
4932
4933 log_channels.clear();
4934
4935 return SUCCESS;
4936}
INT bm_delete_request(INT request_id)
Definition midas.cxx:8595
INT bm_close_buffer(INT buffer_handle)
Definition midas.cxx:7107
std::vector< LOG_CHN * > log_channels
Definition mlogger.cxx:296
INT j
Definition odbhist.cxx:40
INT msg_request_id
Definition mlogger.cxx:257
INT buffer_handle
Definition mlogger.cxx:254
Here is the call graph for this function:
Here is the caller graph for this function:

◆ close_channels()

int close_channels ( int  run_number,
BOOL p_tape_flag 
)

Definition at line 4867 of file mlogger.cxx.

4868{
4869 BOOL tape_flag = FALSE;
4870
4871 for (unsigned i = 0; i < log_channels.size(); i++) {
4872 LOG_CHN* chn = log_channels[i];
4873 if (chn->handle || chn->ftp_con|| chn->pfile) {
4874 /* generate MTALK message */
4875#ifndef FAL_MAIN
4876 /* wait until buffer is empty */
4877 if (chn->buffer_handle) {
4878#ifdef DELAYED_STOP
4879 DWORD start_time = ss_millitime();
4880 do {
4881 cm_yield(100);
4882 } while (ss_millitime() - start_time < DELAYED_STOP);
4883#else
4884 INT n_bytes;
4885 do {
4886 bm_get_buffer_level(chn->buffer_handle, &n_bytes);
4887 if (n_bytes > 0)
4888 cm_yield(100);
4889 } while (n_bytes > 0);
4890#endif
4891 }
4892#endif /* FAL_MAIN */
4893
4894 /* close logging channel */
4895 log_close(chn, run_number);
4896
4897 /* close statistics record */
4898 db_set_record(hDB, chn->stats_hkey, &chn->statistics, sizeof(CHN_STATISTICS), 0);
4901 chn->stats_hkey = 0;
4902 chn->settings_hkey = 0;
4903 }
4904 }
4905
4906 if (p_tape_flag)
4907 *p_tape_flag = tape_flag;
4908
4909 return SUCCESS;
4910}
#define FALSE
Definition cfortran.h:309
INT cm_yield(INT millisec)
Definition midas.cxx:5660
unsigned int DWORD
Definition mcstd.h:51
DWORD ss_millitime()
Definition system.cxx:3465
INT db_unwatch(HNDLE hDB, HNDLE hKey)
Definition odb.cxx:13920
INT db_set_record(HNDLE hDB, HNDLE hKey, void *data, INT buf_size, INT align)
Definition odb.cxx:12320
INT db_close_record(HNDLE hDB, HNDLE hKey)
Definition odb.cxx:13505
INT run_number[2]
Definition mana.cxx:246
INT bm_get_buffer_level(INT buffer_handle, INT *n_bytes)
Definition midas.cxx:7849
DWORD BOOL
Definition midas.h:105
int INT
Definition midas.h:129
INT log_close(LOG_CHN *log_chn, INT run_number)
Definition mlogger.cxx:3361
void * pfile
Definition mlogger.cxx:264
INT handle
Definition mlogger.cxx:249
void * ftp_con
Definition mlogger.cxx:263
CHN_STATISTICS statistics
Definition mlogger.cxx:261
HNDLE settings_hkey
Definition mlogger.cxx:259
HNDLE stats_hkey
Definition mlogger.cxx:258
Here is the call graph for this function:
Here is the caller graph for this function:

◆ close_history()

void close_history ( )

Definition at line 4568 of file mlogger.cxx.

4569{
4570 INT status;
4571 HNDLE hKeyRoot;
4572
4573 /* close system history */
4574 status = db_find_key(hDB, 0, "/History/Links", &hKeyRoot);
4575 if (status == DB_SUCCESS) {
4576 for (int i = 0;; i++) {
4577 HNDLE hKey;
4578 status = db_enum_key(hDB, hKeyRoot, i, &hKey);
4580 break;
4582 }
4583 }
4584
4585 /* close event history */
4586 for (int i = 0; i < hist_log_max; i++)
4587 if (hist_log[i].hKeyVar) {
4588 db_close_record(hDB, hist_log[i].hKeyVar);
4589 hist_log[i].hKeyVar = 0;
4590 if (hist_log[i].buffer)
4591 free(hist_log[i].buffer);
4592 hist_log[i].buffer = NULL;
4593 }
4594
4595 for (unsigned h=0; h<mh.size(); h++) {
4596 mh[h]->hs_disconnect();
4597 delete mh[h];
4598 mh[h] = NULL;
4599 }
4600
4601 mh.clear();
4602}
#define DB_NO_MORE_SUBKEYS
Definition midas.h:647
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition odb.cxx:4256
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition odb.cxx:5357
INT HNDLE
Definition midas.h:132
Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_runlog_ascii_tree()

void create_runlog_ascii_tree ( )

Definition at line 2466 of file mlogger.cxx.

2467{
2468 std::string filename;
2469 int size, write_flag;
2470 HNDLE hKeyRoot, hKey;
2471
2472 size = sizeof(write_flag);
2473 write_flag = 0;
2474 db_get_value(hDB, 0, "/Logger/Runlog/ASCII/Write data", &write_flag, &size, TID_BOOL, TRUE);
2475
2476 filename = "runlog.log";
2477 db_get_value_string(hDB, 0, "/Logger/Runlog/ASCII/Filename", 0, &filename, TRUE);
2478
2479 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links BOR", &hKeyRoot);
2480 if (!hKeyRoot) {
2481 /* create some default links */
2482 db_create_key(hDB, 0, "/Logger/Runlog/ASCII/Links BOR", TID_KEY);
2483
2484 if (db_find_key(hDB, 0, "/Runinfo/Run number", &hKey) == DB_SUCCESS)
2485 db_create_link(hDB, 0, "/Logger/Runlog/ASCII/Links BOR/Run number", "/Runinfo/Run number");
2486
2487 if (db_find_key(hDB, 0, "/Experiment/Run parameters/Comment", &hKey) == DB_SUCCESS)
2488 db_create_link(hDB, 0, "/Logger/Runlog/ASCII/Links BOR/Comment", "/Experiment/Run parameters/Comment");
2489
2490 if (db_find_key(hDB, 0, "/Runinfo/Start time", &hKey) == DB_SUCCESS)
2491 db_create_link(hDB, 0, "/Logger/Runlog/ASCII/Links BOR/Start time", "/Runinfo/Start time");
2492 }
2493
2494 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links EOR", &hKeyRoot);
2495 if (!hKeyRoot) {
2496 /* create some default links */
2497 db_create_key(hDB, 0, "/Logger/Runlog/ASCII/Links EOR", TID_KEY);
2498
2499 if (db_find_key(hDB, 0, "/Runinfo/Stop time", &hKey) == DB_SUCCESS)
2500 db_create_link(hDB, 0, "/Logger/Runlog/ASCII/Links EOR/Stop time", "/Runinfo/Stop time");
2501
2502 if (db_find_key(hDB, 0, "/Equipment/Trigger/Statistics/Events sent", &hKey) == DB_SUCCESS)
2503 db_create_link(hDB, 0, "/Logger/Runlog/ASCII/Links EOR/Number of events",
2504 "/Equipment/Trigger/Statistics/Events sent");
2505
2506 }
2507}
#define TID_KEY
Definition midas.h:349
#define TID_BOOL
Definition midas.h:340
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
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
Definition odb.cxx:3392
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_create_link(HNDLE hDB, HNDLE hKey, const char *link_name, const char *destination)
Definition odb.cxx:3688
#define TRUE
Definition midas.h:182
Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_runlog_json_tree()

void create_runlog_json_tree ( )

Definition at line 2625 of file mlogger.cxx.

2626{
2627 char dirname[256];
2628 int size, write_flag;
2629 HNDLE hKeyRoot, hKey;
2630
2631 size = sizeof(write_flag);
2632 write_flag = 0;
2633 db_get_value(hDB, 0, "/Logger/Runlog/JSON/Write data", &write_flag, &size, TID_BOOL, TRUE);
2634
2635 size = sizeof(dirname);
2636 strcpy(dirname, "runlogs");
2637 db_get_value(hDB, 0, "/Logger/Runlog/JSON/Subdir", dirname, &size, TID_STRING, TRUE);
2638
2639 db_find_key(hDB, 0, "/Logger/Runlog/JSON/Links BOR", &hKeyRoot);
2640 if (!hKeyRoot) {
2641 /* create some default links */
2642 db_create_key(hDB, 0, "/Logger/Runlog/JSON/Links BOR", TID_KEY);
2643
2644 if (db_find_key(hDB, 0, "/Runinfo/Run number", &hKey) == DB_SUCCESS)
2645 db_create_link(hDB, 0, "/Logger/Runlog/JSON/Links BOR/Run number", "/Runinfo/Run number");
2646
2647 if (db_find_key(hDB, 0, "/Experiment/Run parameters/Comment", &hKey) == DB_SUCCESS)
2648 db_create_link(hDB, 0, "/Logger/Runlog/JSON/Links BOR/Comment", "/Experiment/Run parameters/Comment");
2649
2650 if (db_find_key(hDB, 0, "/Runinfo/Start time", &hKey) == DB_SUCCESS)
2651 db_create_link(hDB, 0, "/Logger/Runlog/JSON/Links BOR/Start time", "/Runinfo/Start time");
2652 }
2653
2654 db_find_key(hDB, 0, "/Logger/Runlog/JSON/Links EOR", &hKeyRoot);
2655 if (!hKeyRoot) {
2656 /* create some default links */
2657 db_create_key(hDB, 0, "/Logger/Runlog/JSON/Links EOR", TID_KEY);
2658
2659 if (db_find_key(hDB, 0, "/Runinfo/Stop time", &hKey) == DB_SUCCESS)
2660 db_create_link(hDB, 0, "/Logger/Runlog/JSON/Links EOR/Stop time", "/Runinfo/Stop time");
2661
2662 if (db_find_key(hDB, 0, "/Equipment/Trigger/Statistics/Events sent", &hKey) == DB_SUCCESS)
2663 db_create_link(hDB, 0, "/Logger/Runlog/JSON/Links EOR/Number of events",
2664 "/Equipment/Trigger/Statistics/Events sent");
2665
2666 }
2667}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_event_definition()

EVENT_DEF * db_get_event_definition ( short int  event_id)

Definition at line 2997 of file mlogger.cxx.

2998{
2999 INT i, index, status, size;
3000 char str[80];
3001 HNDLE hKey, hKeyRoot;
3002 WORD id;
3003
3004#define EVENT_DEF_CACHE_SIZE 30
3005 static EVENT_DEF *event_def = NULL;
3006
3007 /* allocate memory for cache */
3008 if (event_def == NULL)
3009 event_def = (EVENT_DEF *) calloc(EVENT_DEF_CACHE_SIZE, sizeof(EVENT_DEF));
3010
3011 assert(event_def != NULL);
3012
3013 /* lookup if event definition in cache */
3014 for (i = 0; event_def[i].event_id; i++)
3015 if (event_def[i].event_id == event_id)
3016 return &event_def[i];
3017
3018 /* search free cache entry */
3019 for (index = 0; index < EVENT_DEF_CACHE_SIZE; index++)
3020 if (event_def[index].event_id == 0)
3021 break;
3022
3023 if (index == EVENT_DEF_CACHE_SIZE) {
3024 cm_msg(MERROR, "db_get_event_definition", "too many event definitions");
3025 return NULL;
3026 }
3027
3028 /* check for system events */
3029 if (event_id < 0) {
3030 event_def[index].event_id = event_id;
3031 event_def[index].format = FORMAT_MIDAS;
3032 event_def[index].hDefKey = 0;
3033 return &event_def[index];
3034 }
3035
3036 status = db_find_key(hDB, 0, "/equipment", &hKeyRoot);
3037 if (status != DB_SUCCESS) {
3038 cm_msg(MERROR, "db_get_event_definition", "cannot find /equipment entry in ODB");
3039 return NULL;
3040 }
3041
3042 for (i = 0;; i++) {
3043 /* search for client with specific name */
3044 status = db_enum_key(hDB, hKeyRoot, i, &hKey);
3045 if (status == DB_NO_MORE_SUBKEYS) {
3046 cm_msg(MERROR, "db_get_event_definition", "Cannot find event id %d under /equipment", event_id);
3047 return NULL;
3048 }
3049
3050 size = sizeof(id);
3051 status = db_get_value(hDB, hKey, "Common/Event ID", &id, &size, TID_UINT16, TRUE);
3052 if (status != DB_SUCCESS)
3053 continue;
3054
3055 if (id == event_id) {
3056 /* set cache entry */
3057 event_def[index].event_id = id;
3058
3059 size = sizeof(str);
3060 str[0] = 0;
3061 db_get_value(hDB, hKey, "Common/Format", str, &size, TID_STRING, TRUE);
3062
3063 if (equal_ustring(str, "Fixed"))
3064 event_def[index].format = FORMAT_FIXED;
3065 else if (equal_ustring(str, "MIDAS"))
3066 event_def[index].format = FORMAT_MIDAS;
3067 else {
3068 cm_msg(MERROR, "db_get_event_definition", "unknown data format name \"%s\"", str);
3069 event_def[index].event_id = 0;
3070 return NULL;
3071 }
3072
3073 db_find_key(hDB, hKey, "Variables", &event_def[index].hDefKey);
3074 return &event_def[index];
3075 }
3076 }
3077}
unsigned short int WORD
Definition mcstd.h:49
#define FORMAT_FIXED
Definition midas.h:314
#define FORMAT_MIDAS
Definition midas.h:311
#define TID_UINT16
Definition midas.h:333
BOOL equal_ustring(const char *str1, const char *str2)
Definition odb.cxx:3285
#define EVENT_DEF_CACHE_SIZE
HNDLE hDefKey
Definition mana.cxx:450
WORD format
Definition mana.cxx:449
short int event_id
Definition mana.cxx:447
Here is the call graph for this function:

◆ fopen_wx()

static FILE * fopen_wx ( const char *  filename)
static

Definition at line 360 of file mlogger.cxx.

361{
362 int fd = open(filename, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IRGRP|S_IROTH);
363 if (fd == -1)
364 return NULL;
365 return fdopen(fd, "w");
366}
Here is the caller graph for this function:

◆ ftp_error()

INT ftp_error ( const char *  message)

Definition at line 2800 of file mlogger.cxx.

2801{
2802 cm_msg(MERROR, "ftp_error", "%s", message);
2803 return 1;
2804}
#define message(type, str)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ftp_open()

INT ftp_open ( const char *  xdestination,
FTP_CON **  con 
)

Definition at line 2806 of file mlogger.cxx.

2807{
2808 INT status;
2809 short port = 0;
2810 char *token;
2812 char user[32], pass[32];
2813 char directory[256], file_name[256], file_mode[256];
2814 char bdestination[256]; // have to make a copy of destination because strtok() modifies it's string
2815 mstrlcpy(bdestination, xdestination, sizeof(bdestination));
2816 char* destination = bdestination;
2817
2818 // skip leading slash
2819 if (destination[0] == '/')
2820 destination += 1;
2821
2822 /*
2823 destination should have the form:
2824 host, port, user, password, directory, run%05d.mid
2825 */
2826
2827 /* break destination in components */
2828 token = strtok(destination, ",");
2829 if (token)
2830 mstrlcpy(host_name, token, sizeof(host_name));
2831
2832 token = strtok(NULL, ", ");
2833 if (token)
2834 port = atoi(token);
2835
2836 token = strtok(NULL, ", ");
2837 if (token)
2838 mstrlcpy(user, token, sizeof(user));
2839
2840 token = strtok(NULL, ", ");
2841 if (token)
2842 mstrlcpy(pass, token, sizeof(pass));
2843
2844 token = strtok(NULL, ", ");
2845 if (token)
2846 mstrlcpy(directory, token, sizeof(directory));
2847
2848 token = strtok(NULL, ", ");
2849 if (token)
2850 mstrlcpy(file_name, token, sizeof(file_name));
2851
2852 token = strtok(NULL, ", ");
2853 file_mode[0] = 0;
2854 if (token)
2855 mstrlcpy(file_mode, token, sizeof(file_mode));
2856
2857#ifdef FAL_MAIN
2858 ftp_debug(NULL, ftp_error);
2859#else
2860 ftp_debug((int (*)(const char *)) puts, ftp_error);
2861#endif
2862
2863 status = ftp_login(con, host_name, port, user, pass, "");
2864 if (status >= 0)
2865 return status;
2866
2867 status = ftp_chdir(*con, directory);
2868 if (status >= 0)
2869 return status;
2870
2871 status = ftp_binary(*con);
2872 if (status >= 0)
2873 return status;
2874
2875 if (file_mode[0]) {
2876 status = ftp_command(*con, "umask %s", file_mode, 200, 250, EOF);
2877 if (status >= 0)
2878 return status;
2879 }
2880
2881 if (ftp_open_write(*con, file_name) >= 0)
2882 return (*con)->err_no;
2883
2884 return SS_SUCCESS;
2885}
int ftp_login(FTP_CON **con, const char *host, unsigned short port, const char *user, const char *password, const char *account)
Definition ftplib.cxx:388
int ftp_command(FTP_CON *con, const char *command, const char *param,...)
Definition ftplib.cxx:146
void ftp_debug(int(*debug_func)(const char *message), int(*error_func)(const char *message))
Definition ftplib.cxx:32
#define ftp_chdir(ftp, dir)
Definition ftplib.h:35
#define ftp_binary(ftp)
Definition ftplib.h:39
#define ftp_open_write(ftp, file)
Definition ftplib.h:41
#define SS_SUCCESS
Definition midas.h:664
char host_name[HOST_NAME_LENGTH]
Definition mana.cxx:242
#define HOST_NAME_LENGTH
Definition midas.h:273
INT ftp_error(const char *message)
Definition mlogger.cxx:2800
char file_name[256]
Definition odbhist.cxx:41
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_number_image_history_threads()

int get_number_image_history_threads ( )
extern

Definition at line 317 of file history_image.cxx.

317{ return 0; }
Here is the caller graph for this function:

◆ get_trans_flag()

static int get_trans_flag ( )
static

Definition at line 3465 of file mlogger.cxx.

3466{
3467 int status, size, flag;
3468
3469 size = sizeof(BOOL);
3470 flag = FALSE;
3471 status = db_get_value(hDB, 0, "/Logger/Async transitions", &flag, &size, TID_BOOL, FALSE);
3472
3473 if (status == DB_SUCCESS) {
3474 cm_msg(MINFO, "get_trans_flag", "ODB \"/Logger/Async transitions\" is obsolete, please delete it");
3475 }
3476
3477 size = sizeof(BOOL);
3478 flag = TRUE;
3479 status = db_get_value(hDB, 0, "/Logger/Multithread transitions", &flag, &size, TID_BOOL, FALSE);
3480
3481 if (status == DB_SUCCESS) {
3482 cm_msg(MINFO, "get_trans_flag", "ODB \"/Logger/Multithread transitions\" is obsolete, please delete it");
3483 }
3484
3485 size = sizeof(BOOL);
3486 flag = FALSE;
3487 db_get_value(hDB, 0, "/Logger/Detached transitions", &flag, &size, TID_BOOL, TRUE);
3488
3489 // NB: we must use multithread or detached (via mtransition) transition
3490 // otherwise we deadlock against frontends: they are writing to the SYSTEM
3491 // buffer but we (mlogger) are not reading from it. if SYSTEM buffer is full,
3492 // clients get stuck waiting for free space and cannot not handle TR_STOP RPC.
3493 // if they could handle, it, they would still be stuck in bm_flush_cache()
3494 // because we (mlogger) are not reading the SYSTEM buffer and these last
3495 // events have nowhere to go. K.O.
3496
3497 if (flag)
3498 return TR_DETACH;
3499 else
3500 return TR_MTHREAD;
3501}
#define TR_MTHREAD
Definition midas.h:361
#define MINFO
Definition midas.h:560
#define TR_DETACH
Definition midas.h:360
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_value()

std::string get_value ( HNDLE  hDB,
HNDLE  hDir,
const char *  name 
)

Definition at line 3164 of file mlogger.cxx.

3165{
3167 value[0] = 0;
3168 int size = sizeof(value);
3169 int status = db_get_value(hDB, hDir, name, &value, &size, TID_STRING, FALSE);
3170 if (status != DB_SUCCESS)
3171 return "";
3172 return value;
3173}
#define MAX_STRING_LENGTH
Definition msystem.h:113
double value[100]
Definition odbhist.cxx:42
Here is the call graph for this function:
Here is the caller graph for this function:

◆ IntToString()

static std::string IntToString ( int  value)
static

Definition at line 46 of file mlogger.cxx.

47{
48 char buf[256];
49 sprintf(buf, "%d", value);
50 return buf;
51}
Here is the caller graph for this function:

◆ log_close()

INT log_close ( LOG_CHN log_chn,
INT  run_number 
)

Definition at line 3361 of file mlogger.cxx.

3362{
3363 if (log_chn->writer) {
3364 /* write ODB dump */
3365 if (log_chn->settings.odb_dump)
3367
3368 WriterInterface* wr = log_chn->writer;
3369
3370 wr->wr_close(log_chn, run_number);
3371
3372 /* update statistics */
3373
3374 double incr = wr->fBytesOut - log_chn->statistics.bytes_written_subrun;
3375 if (incr < 0)
3376 incr = 0;
3377
3378 //printf("bytes out %f, incr %f, subrun %f, written %f, total %f (log_close)\n", wr->fBytesOut, incr, log_chn->statistics.bytes_written_subrun, log_chn->statistics.bytes_written, log_chn->statistics.bytes_written_total);
3379
3380 log_chn->statistics.bytes_written += incr;
3382 log_chn->statistics.bytes_written_total += incr;
3383 }
3384
3385 /* if file name starts with '.', rename it */
3386 char str[256]; // FIXME: this will truncate the filename of the output file. K.O.
3387 mstrlcpy(str, log_chn->path.c_str(), sizeof(str));
3388 char* p = str;
3389 if (strrchr(str, DIR_SEPARATOR)) {
3390 p = strrchr(str, DIR_SEPARATOR)+1;
3391 }
3392 if (*p == '.') {
3393 mstrlcpy(p, p+1, sizeof(str));
3394 rename(log_chn->path.c_str(), str); // FIXME: must check return status. K.O.
3395 }
3396
3397 log_chn->statistics.files_written += 1;
3398 log_chn->handle = 0;
3399 log_chn->ftp_con = NULL;
3400
3401 if (log_chn->writer) {
3402 delete log_chn->writer;
3403 log_chn->writer = NULL;
3404 }
3405
3406 return SS_SUCCESS;
3407}
virtual int wr_close(LOG_CHN *log_chn, int run_number)=0
#define DIR_SEPARATOR
Definition midas.h:193
#define EVENTID_EOR
Definition midas.h:902
void log_odb_dump(LOG_CHN *log_chn, short int event_id, INT run_number)
Definition mlogger.cxx:1759
double bytes_written_subrun
Definition mlogger.cxx:226
double bytes_written_total
Definition mlogger.cxx:225
double bytes_written
Definition mlogger.cxx:223
double files_written
Definition mlogger.cxx:227
std::string path
Definition mlogger.cxx:250
WriterInterface * writer
Definition mlogger.cxx:265
CHN_SETTINGS settings
Definition mlogger.cxx:260
Here is the call graph for this function:
Here is the caller graph for this function:

◆ log_create_writer()

int log_create_writer ( LOG_CHN log_chn)

Definition at line 3246 of file mlogger.cxx.

3247{
3248 assert(log_chn->writer == NULL);
3249 log_chn->writer = NULL;
3250
3251 if (log_chn->output_module > 0) {
3252
3253 if (log_chn->compression_module == COMPRESS_ZLIB) {
3254
3255 if (log_chn->output_module != OUTPUT_FILE) {
3256 cm_msg(MERROR, "log_create_writer", "channel %s requested GZIP/ZLIB compression, output module must be FILE", log_chn->path.c_str());
3257 return SS_FILE_ERROR;
3258 }
3259
3260 log_chn->writer = new WriterGzip(log_chn, 0);
3261 log_chn->do_disk_level = TRUE;
3262 }
3263 else if (log_chn->compression_module == COMPRESS_BZIP2) {
3264
3265 if (log_chn->output_module != OUTPUT_FILE) {
3266 cm_msg(MERROR, "log_create_writer", "channel %s requested BZIP2 compression, output module must be FILE", log_chn->path.c_str());
3267 return SS_FILE_ERROR;
3268 }
3269
3270 log_chn->writer = NewWriterBzip2(log_chn);
3271 log_chn->do_disk_level = TRUE;
3272
3273 }
3274 else if (log_chn->compression_module == COMPRESS_PBZIP2) {
3275
3276 if (log_chn->output_module != OUTPUT_FILE) {
3277 cm_msg(MERROR, "log_create_writer", "channel %s requested PBZIP2 compression, output module must be FILE", log_chn->path.c_str());
3278 return SS_FILE_ERROR;
3279 }
3280
3281 log_chn->writer = NewWriterPbzip2(log_chn);
3282 log_chn->do_disk_level = TRUE;
3283 }
3284 else if (log_chn->output_module == OUTPUT_NULL) {
3285
3286 log_chn->writer = new WriterNull(log_chn);
3287 log_chn->do_disk_level = TRUE;
3288 }
3289 else if (log_chn->output_module == OUTPUT_FILE) {
3290
3291 log_chn->writer = NewCompression(log_chn, log_chn->compression_module, NewChecksum(log_chn, log_chn->post_checksum_module, 0, new WriterFile(log_chn)));
3292 log_chn->do_disk_level = TRUE;
3293 }
3294 else if (log_chn->output_module == OUTPUT_FTP) {
3295
3296 log_chn->writer = NewCompression(log_chn, log_chn->compression_module, NewChecksum(log_chn, log_chn->post_checksum_module, 0, new WriterFtp(log_chn)));
3297 log_chn->do_disk_level = FALSE;
3298 log_chn->statistics.disk_level = -1;
3299 }
3300 else if (log_chn->output_module == OUTPUT_PIPE) {
3301
3302 log_chn->writer = NewCompression(log_chn, log_chn->compression_module, NewChecksum(log_chn, log_chn->post_checksum_module, 0, new WriterPopen(log_chn, "xxx", "")));
3303 log_chn->do_disk_level = FALSE;
3304 log_chn->statistics.disk_level = -1;
3305 }
3306
3307 //log_chn->writer = new WriterROOT(log_chn);
3308 //log_chn->do_disk_level = TRUE;
3309
3310 if (log_chn->pre_checksum_module) {
3311 log_chn->writer = NewChecksum(log_chn, log_chn->pre_checksum_module, 1, log_chn->writer);
3312 }
3313
3314 //cm_msg(MINFO, "log_create_writer", "channel \"%s\" writer chain: %s", log_chn->path.c_str(), log_chn->writer->wr_get_chain().c_str());
3315
3316 return SUCCESS;
3317 }
3318
3319 cm_msg(MERROR, "log_create_writer", "channel %s invalid output module value %d", log_chn->path.c_str(), log_chn->output_module);
3320 return SS_FILE_ERROR;
3321}
#define SS_FILE_ERROR
Definition midas.h:670
WriterInterface * NewCompression(LOG_CHN *log_chn, int code, WriterInterface *chained)
Definition mlogger.cxx:3145
#define OUTPUT_FILE
Definition mlogger.cxx:3159
#define OUTPUT_NULL
Definition mlogger.cxx:3158
WriterInterface * NewChecksum(LOG_CHN *log_chn, int code, int level, WriterInterface *chained)
Definition mlogger.cxx:3121
WriterInterface * NewWriterBzip2(LOG_CHN *log_chn)
Definition mlogger.cxx:3081
#define OUTPUT_FTP
Definition mlogger.cxx:3160
#define OUTPUT_PIPE
Definition mlogger.cxx:3162
#define COMPRESS_BZIP2
Definition mlogger.cxx:3142
#define COMPRESS_PBZIP2
Definition mlogger.cxx:3143
WriterInterface * NewWriterPbzip2(LOG_CHN *log_chn)
Definition mlogger.cxx:3093
#define COMPRESS_ZLIB
Definition mlogger.cxx:3140
double disk_level
Definition mlogger.cxx:228
int post_checksum_module
Definition mlogger.cxx:270
int output_module
Definition mlogger.cxx:271
int compression_module
Definition mlogger.cxx:269
BOOL do_disk_level
Definition mlogger.cxx:267
int pre_checksum_module
Definition mlogger.cxx:268
Here is the call graph for this function:
Here is the caller graph for this function:

◆ log_disk_level()

int log_disk_level ( LOG_CHN log_chn,
double *  pdisk_size,
double *  pdisk_free 
)

Definition at line 3411 of file mlogger.cxx.

3412{
3413 std::string str = log_chn->path.c_str();
3414 size_t pos = str.rfind('/');
3415 if (pos != std::string::npos) {
3416 str.erase(pos); // strip filename for bzip2
3417 }
3418
3419 //printf("log_disk_level [%s] [%s]\n", log_chn->path.c_str(), str.c_str());
3420
3421 double MiB = 1024*1024;
3422 double disk_size = ss_disk_size(str.c_str());
3423 double disk_free = ss_disk_free(str.c_str());
3424 double limit = 10E6;
3425 double level = 1.0-disk_free/disk_size;
3426
3427 if (pdisk_size)
3428 *pdisk_size = disk_size; // should be in statistics
3429 if (pdisk_free)
3430 *pdisk_free = disk_free; // should be in statistics
3431
3432 log_chn->statistics.disk_level = level;
3433
3434 if (verbose)
3435 printf("log_disk_level: channel path [%s], disk_size %1.0lf MiB, disk_free %1.0lf MiB, limit %1.0f MiB, disk level %.1f%%\n", log_chn->path.c_str(), disk_size/MiB, disk_free/MiB, limit/MiB, level*100.0);
3436
3437 return SUCCESS;
3438}
double ss_disk_size(const char *path)
Definition system.cxx:7126
double ss_disk_free(const char *path)
Definition system.cxx:6698
const double MiB
Here is the call graph for this function:
Here is the caller graph for this function:

◆ log_generate_file_name()

int log_generate_file_name ( LOG_CHN log_chn)

Definition at line 4712 of file mlogger.cxx.

4713{
4714 INT size, status, run_number = 0;
4715 std::string path;
4716 std::string data_dir;
4717 CHN_SETTINGS *chn_settings;
4718
4719 chn_settings = &log_chn->settings;
4720 size = sizeof(run_number);
4721 status = db_get_value(hDB, 0, "Runinfo/Run number", &run_number, &size, TID_INT32, TRUE);
4722 assert(status == SUCCESS);
4723
4724 std::string filename = chn_settings->filename;
4725 /* Check if data stream are throw pipe command */
4726 log_chn->pipe_command = "";
4727 bool ispipe = false;
4728 if (log_chn->type == LOG_TYPE_DISK) {
4729 char* p = strchr(chn_settings->filename, '>');
4730 if (chn_settings->filename[0] == '|' && p) {
4731 /* skip second arrow in ">>" */
4732 while (*p == '>')
4733 p++;
4734 /* skip spaces after '>' */
4735 while (*p == ' ')
4736 p++;
4737 filename = p;
4738 ispipe = true;
4739 // pipe_command is contents of chn_settings->filename without the leading "|" and trailing ">"
4740 log_chn->pipe_command = "";
4741 const char*s = chn_settings->filename;
4742 /* skip leading pipe */
4743 if (*s == '|')
4744 s++;
4745 /* skip spaces */
4746 while (*s == ' ')
4747 s++;
4748 /* copy up to ">" */
4749 while (*s != '>') {
4750 log_chn->pipe_command += *s++;
4751 }
4752 /* copy as many ">" as they put there */
4753 while (*s == '>') {
4754 log_chn->pipe_command += *s++;
4755 }
4756 }
4757 }
4758
4759 std::string str;
4760
4761 /* if disk, precede filename with directory if not already there */
4762 if (log_chn->type == LOG_TYPE_DISK && filename[0] != DIR_SEPARATOR) {
4763 db_get_value_string(hDB, 0, "/Logger/Data Dir", 0, &data_dir, TRUE);
4764 if (data_dir.empty()) {
4765 data_dir = cm_get_path();
4766 } else {
4767 if (data_dir.back() != DIR_SEPARATOR)
4768 data_dir += DIR_SEPARATOR_STR;
4769 }
4770 str = data_dir;
4771
4772 /* append subdirectory if requested */
4773 if (chn_settings->subdir_format[0]) {
4774 ss_tzset(); // required for localtime_r()
4775 time_t now;
4776 time(&now);
4777 struct tm tms;
4778 localtime_r(&now, &tms);
4779
4780 char dir[256];
4781 strftime(dir, sizeof(dir), chn_settings->subdir_format, &tms);
4782 str += dir;
4784 }
4785
4786 /* create directory if needed */
4787#ifdef OS_WINNT
4788 status = mkdir(str.c_str());
4789#else
4790 status = mkdir(str.c_str(), 0755);
4791#endif
4792#if defined(EEXIST)
4793 if (status == -1 && errno != EEXIST)
4794 cm_msg(MERROR, "log_generate_file_name", "Cannot create subdirectory \"%s\", mkdir() errno %d (%s)", str.c_str(), errno, strerror(errno));
4795#endif
4796
4797 str += filename;
4798 } else {
4799 str = filename;
4800 }
4801
4802 /* check if two "%" are present in filename */
4803 if (strchr(str.c_str(), '%')) {
4804 if (strchr(strchr(str.c_str(), '%')+1, '%')) {
4805 /* substitude first "%d" by current run number, second "%d" by subrun number */
4806 path = msprintf(str.c_str(), run_number, log_chn->subrun_number);
4807 } else {
4808 /* substitue "%d" by current run number */
4809 path = msprintf(str.c_str(), run_number);
4810 }
4811 } else {
4812 path = str;
4813 }
4814
4815 /* add required file extension */
4816 if (log_chn->writer) {
4817 path += log_chn->writer->wr_get_file_ext();
4818 }
4819
4820 log_chn->path = path;
4821
4822 /* write back current file name to ODB */
4823 std::string tmpstr;
4824 if (strncmp(path.c_str(), data_dir.c_str(), data_dir.length()) == 0)
4825 tmpstr = path.c_str() + data_dir.length();
4826 else
4827 tmpstr = path;
4828 char cstr[256];
4829 mstrlcpy(cstr, tmpstr.c_str(), sizeof(cstr));
4830 db_set_value(hDB, log_chn->settings_hkey, "Current filename", cstr, 256, 1, TID_STRING);
4831
4832 /* construct full pipe command */
4833 if (ispipe) {
4834 /* check if %d must be substitude by current run number in pipe command options */
4835 if (strchr(log_chn->pipe_command.c_str(), '%')) {
4836 std::string str = log_chn->pipe_command;
4837 if (strchr(strchr(str.c_str(), '%')+1, '%')) {
4838 /* substitude first "%d" by current run number, second "%d" by subrun number */
4839 log_chn->pipe_command = msprintf(str.c_str(), run_number, log_chn->subrun_number);
4840 } else {
4841 /* substitue "%d" by current run number */
4842 log_chn->pipe_command = msprintf(str.c_str(), run_number);
4843 }
4844 } else {
4845 }
4846 /* add a space */
4847 if (log_chn->pipe_command.back() != ' ')
4848 log_chn->pipe_command += " ";
4849 /* add generated filename to pipe command */
4850 log_chn->pipe_command += path;
4851 //printf("pipe command [%s]\n", log_chn->pipe_command.c_str());
4852 }
4853
4854 return CM_SUCCESS;
4855}
virtual std::string wr_get_file_ext()
Definition mlogger.cxx:388
std::string cm_get_path()
Definition midas.cxx:1553
#define CM_SUCCESS
Definition midas.h:582
#define TID_INT32
Definition midas.h:339
#define LOG_TYPE_DISK
Definition msystem.h:501
void ss_tzset()
Definition system.cxx:3427
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
std::string msprintf(const char *format,...)
Definition midas.cxx:419
#define DIR_SEPARATOR_STR
Definition midas.h:194
MUTEX_T * tm
Definition odbedit.cxx:39
char filename[256]
Definition mlogger.cxx:158
char subdir_format[32]
Definition mlogger.cxx:172
INT subrun_number
Definition mlogger.cxx:253
INT type
Definition mlogger.cxx:252
std::string pipe_command
Definition mlogger.cxx:251
Here is the call graph for this function:
Here is the caller graph for this function:

◆ log_history()

void log_history ( HNDLE  hDB,
HNDLE  hKey,
void *  info 
)

Definition at line 4606 of file mlogger.cxx.

4607{
4608 INT i, size, status;
4609 DWORD start_millitime = ss_millitime();
4610
4611 time_t now = time(NULL);
4612
4613 for (i = 0; i < hist_log_max; i++)
4614 if (hist_log[i].hKeyVar == hKey)
4615 break;
4616
4617 if (i == hist_log_max)
4618 return;
4619
4620 /* check if over minimum period */
4621 if (now - hist_log[i].last_log < hist_log[i].min_period)
4622 return;
4623
4624 /* check if event size has changed */
4625 db_get_record_size(hDB, hKey, 0, &size);
4626 if (size != hist_log[i].buffer_size) {
4627 close_history();
4628 status = open_history();
4629 if (status != CM_SUCCESS) {
4630 printf("Error in history system, aborting.\n");
4632 exit(1);
4633 }
4634 return;
4635 }
4636
4637 hist_log[i].last_log = now;
4638
4639 if (verbose)
4640 printf("Log history event: \'%s\', timestamp %s, buffer %p, size %d\n", hist_log[i].event_name, TimeToString(hist_log[i].last_log).c_str(), hist_log[i].buffer, hist_log[i].buffer_size);
4641
4642 for (unsigned h=0; h<mh.size(); h++) {
4643 status = mh[h]->hs_write_event(hist_log[i].event_name, hist_log[i].last_log, hist_log[i].buffer_size, hist_log[i].buffer);
4644 if (verbose)
4645 if (status != HS_SUCCESS)
4646 printf("write_history_event: \'%s\', channel \'%s\' hs_write_event() status %d\n", hist_log[i].event_name, mh[h]->name, status);
4647 }
4648
4650
4651 DWORD end_millitime = ss_millitime();
4652 if (end_millitime - start_millitime > 3000)
4653 cm_msg(MINFO, "log_history", "History write operation took %d ms", end_millitime - start_millitime);
4654}
INT cm_disconnect_experiment(void)
Definition midas.cxx:2862
void maybe_flush_history(time_t now)
Definition mlogger.cxx:4550
void close_history()
Definition mlogger.cxx:4568
INT open_history()
Definition mlogger.cxx:3901
static std::string TimeToString(time_t t)
Definition mlogger.cxx:53
Here is the call graph for this function:
Here is the caller graph for this function:

◆ log_odb_dump()

void log_odb_dump ( LOG_CHN log_chn,
short int  event_id,
INT  run_number 
)

Definition at line 1759 of file mlogger.cxx.

1760{
1761 if (equal_ustring(log_chn->settings.odb_dump_format, "odb")) {
1763 } else if (equal_ustring(log_chn->settings.odb_dump_format, "xml")) {
1765 } else if (equal_ustring(log_chn->settings.odb_dump_format, "json")) {
1767 } else {
1768 cm_msg(MERROR, "log_odb_dump", "Invalid ODB dump format \"%s\" in ODB settings for channel \"%s\". Valid formats are: \"odb\", \"xml\", \"json\"", log_chn->settings.odb_dump_format, log_chn->name.c_str());
1769 }
1770}
void log_odb_dump_json(LOG_CHN *log_chn, short int event_id, INT run_number)
Definition mlogger.cxx:1732
void log_odb_dump_xml(LOG_CHN *log_chn, short int event_id, INT run_number)
Definition mlogger.cxx:1701
void log_odb_dump_odb(LOG_CHN *log_chn, short int event_id, INT run_number)
Definition mlogger.cxx:1672
char odb_dump_format[32]
Definition mlogger.cxx:162
std::string name
Definition mlogger.cxx:248
Here is the call graph for this function:
Here is the caller graph for this function:

◆ log_odb_dump_json()

void log_odb_dump_json ( LOG_CHN log_chn,
short int  event_id,
INT  run_number 
)

Definition at line 1732 of file mlogger.cxx.

1733{
1734 /* write ODB dump */
1735
1736 char* buffer = NULL;
1737 int buffer_size = 0;
1738 int buffer_end = 0;
1739
1740 int status = db_copy_json_save(hDB, 0, &buffer, &buffer_size, &buffer_end);
1741
1742 //printf("db_copy_json_save: status %d, buffer_size %d, buffer_end %d\n", status, buffer_size, buffer_end);
1743
1744 if (status == DB_SUCCESS) {
1745 int event_size = sizeof(EVENT_HEADER) + buffer_end;
1746 EVENT_HEADER* pevent = (EVENT_HEADER *) malloc(event_size);
1747 if (pevent == NULL) {
1748 cm_msg(MERROR, "log_odb_dump", "Cannot allocate ODB dump buffer size %d", event_size);
1749 } else {
1750 bm_compose_event(pevent, event_id, MIDAS_MAGIC, buffer_end, run_number);
1751 memcpy(pevent+1, buffer, buffer_end);
1752 log_write(log_chn, pevent);
1753 free(pevent);
1754 }
1755 }
1756 free(buffer);
1757}
INT bm_compose_event(EVENT_HEADER *event_header, short int event_id, short int trigger_mask, DWORD data_size, DWORD serial)
Definition midas.cxx:8292
INT db_copy_json_save(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end)
Definition odb.cxx:10496
#define MIDAS_MAGIC
Definition midas.h:912
INT log_write(LOG_CHN *log_chn, EVENT_HEADER *pheader)
Definition mlogger.cxx:3600
int event_size
Definition msysmon.cxx:527
Here is the call graph for this function:
Here is the caller graph for this function:

◆ log_odb_dump_odb()

void log_odb_dump_odb ( LOG_CHN log_chn,
short int  event_id,
INT  run_number 
)

Definition at line 1672 of file mlogger.cxx.

1673{
1674 /* write ODB dump */
1675
1676 static int buffer_size = 100000;
1677
1678 do {
1679 EVENT_HEADER* pevent = (EVENT_HEADER *) malloc(buffer_size);
1680 if (pevent == NULL) {
1681 cm_msg(MERROR, "log_odb_dump", "Cannot allocate ODB dump buffer");
1682 break;
1683 }
1684
1685 int size = buffer_size - sizeof(EVENT_HEADER);
1686 //int status = db_copy_xml(hDB, 0, (char *) (pevent + 1), &size);
1687 int status = db_copy(hDB, 0, (char *) (pevent + 1), &size, "");
1688 if (status != DB_TRUNCATED) {
1689 bm_compose_event(pevent, event_id, MIDAS_MAGIC, buffer_size - sizeof(EVENT_HEADER) - size + 1, run_number);
1690 log_write(log_chn, pevent);
1691 free(pevent);
1692 break;
1693 }
1694
1695 /* increase buffer size if truncated */
1696 free(pevent);
1697 buffer_size *= 10;
1698 } while (1);
1699}
#define DB_TRUNCATED
Definition midas.h:645
INT db_copy(HNDLE hDB, HNDLE hKey, char *buffer, INT *buffer_size, const char *path)
Definition odb.cxx:8230
Here is the call graph for this function:
Here is the caller graph for this function:

◆ log_odb_dump_xml()

void log_odb_dump_xml ( LOG_CHN log_chn,
short int  event_id,
INT  run_number 
)

Definition at line 1701 of file mlogger.cxx.

1702{
1703 /* write ODB dump */
1704
1705 static int buffer_size = 100000;
1706
1707 do {
1708 EVENT_HEADER* pevent = (EVENT_HEADER *) malloc(buffer_size);
1709 if (pevent == NULL) {
1710 cm_msg(MERROR, "log_odb_dump", "Cannot allocate ODB dump buffer");
1711 break;
1712 }
1713
1714 int size = buffer_size - sizeof(EVENT_HEADER);
1715 int status = db_copy_xml(hDB, 0, (char *) (pevent + 1), &size, true);
1716
1717 /* following line would dump ODB in old ASCII format instead of XML */
1718 //status = db_copy(hDB, 0, (char *) (pevent + 1), &size, "");
1719 if (status != DB_TRUNCATED) {
1721 log_write(log_chn, pevent);
1722 free(pevent);
1723 break;
1724 }
1725
1726 /* increase buffer size if truncated */
1727 free(pevent);
1728 buffer_size *= 10;
1729 } while (1);
1730}
INT db_copy_xml(HNDLE hDB, HNDLE hKey, char *buffer, int *buffer_size, bool header)
Definition odb.cxx:9055
Here is the call graph for this function:
Here is the caller graph for this function:

◆ log_open()

INT log_open ( LOG_CHN log_chn,
INT  run_number 
)

Definition at line 3325 of file mlogger.cxx.

3326{
3327 INT status = SUCCESS;
3328
3329 log_chn->last_checked = ss_millitime();
3330
3331 if (log_chn->writer) {
3332 WriterInterface* wr = log_chn->writer;
3333
3334 int status = wr->wr_open(log_chn, run_number);
3335
3336 if (status != SUCCESS)
3337 return status;
3338
3339 /* write ODB dump */
3340 if (log_chn->settings.odb_dump)
3342
3343 /* update statistics */
3344 double incr = wr->fBytesOut - log_chn->statistics.bytes_written_subrun;
3345 if (incr < 0)
3346 incr = 0;
3347
3348 //printf("bytes out %f, incr %f, subrun %f, written %f, total %f (log_open)\n", wr->fBytesOut, incr, log_chn->statistics.bytes_written_subrun, log_chn->statistics.bytes_written, log_chn->statistics.bytes_written_total);
3349
3350 log_chn->statistics.bytes_written += incr;
3352 log_chn->statistics.bytes_written_total += incr;
3353 } else {
3354 return SS_INVALID_FORMAT;
3355 }
3356 return status;
3357}
virtual int wr_open(LOG_CHN *log_chn, int run_number)=0
#define SS_INVALID_FORMAT
Definition midas.h:689
#define EVENTID_BOR
Definition midas.h:901
DWORD last_checked
Definition mlogger.cxx:266
Here is the call graph for this function:
Here is the caller graph for this function:

◆ log_system_history()

void log_system_history ( HNDLE  hDB,
HNDLE  hKey,
void *  info 
)

Definition at line 4658 of file mlogger.cxx.

4659{
4660 INT size, total_size, status, index;
4661 DWORD i;
4662 KEY key;
4663 DWORD start_millitime = ss_millitime();
4664
4665 index = (INT) (POINTER_T) info;
4666
4667 time_t now = time(NULL);
4668
4669 /* check if over period */
4670 if (now - hist_log[index].last_log < hist_log[index].min_period)
4671 return;
4672
4673 for (i = 0, total_size = 0;; i++) {
4674 status = db_enum_key(hDB, hist_log[index].hKeyVar, i, &hKey);
4676 break;
4677
4678 db_get_key(hDB, hKey, &key);
4679 size = key.total_size;
4680 db_get_data(hDB, hKey, (char *) hist_log[index].buffer + total_size, &size, key.type);
4681 total_size += size;
4682 }
4683
4684 if (i != hist_log[index].n_var) {
4685 close_history();
4686 status = open_history();
4687 if (status != CM_SUCCESS) {
4688 printf("Error in history system, aborting.\n");
4690 exit(1);
4691 }
4692 return;
4693 }
4694
4695 hist_log[index].last_log = now;
4696
4697 if (verbose)
4698 printf("write history event: \'%s\', timestamp %s, buffer %p, size %d\n", hist_log[index].event_name, TimeToString(hist_log[index].last_log).c_str(), hist_log[index].buffer, hist_log[index].buffer_size);
4699
4700 for (unsigned h=0; h<mh.size(); h++)
4701 mh[h]->hs_write_event(hist_log[index].event_name, hist_log[index].last_log, total_size, hist_log[index].buffer);
4702
4704
4705 DWORD end_millitime = ss_millitime();
4706 if (end_millitime - start_millitime > 3000)
4707 cm_msg(MINFO, "log_system_history", "History write operation took %d ms", end_millitime - start_millitime);
4708}
static INT hs_write_event(DWORD event_id, const void *data, DWORD size)
Definition history.cxx:656
INT db_get_data(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
Definition odb.cxx:6563
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
Definition odb.cxx:6043
void ** info
Definition fesimdaq.cxx:41
KEY key
Definition mdump.cxx:34
#define POINTER_T
Definition midas.h:166
Definition midas.h:1027
DWORD type
Definition midas.h:1028
INT total_size
Definition midas.h:1032
Here is the call graph for this function:
Here is the caller graph for this function:

◆ log_write()

INT log_write ( LOG_CHN log_chn,
EVENT_HEADER pheader 
)

Definition at line 3600 of file mlogger.cxx.

3601{
3602 INT status = 0, size;
3603 DWORD duration;
3604 BOOL next_subrun;
3605
3606 //printf("log_write %d\n", pevent->data_size + sizeof(EVENT_HEADER));
3607
3608 DWORD start_time = ss_millitime();
3609 int evt_size = pevent->data_size + sizeof(EVENT_HEADER);
3610
3611 if (log_chn->writer) {
3612 WriterInterface* wr = log_chn->writer;
3613 status = wr->wr_write(log_chn, pevent, evt_size);
3614
3615 if (status == SUCCESS) {
3616 /* update statistics */
3617 log_chn->statistics.events_written++;
3618 log_chn->statistics.bytes_written_uncompressed += evt_size;
3619 }
3620
3621 double incr = wr->fBytesOut - log_chn->statistics.bytes_written_subrun;
3622 if (incr < 0)
3623 incr = 0;
3624
3625 //printf("events %.0f, bytes out %.0f, incr %.0f, subrun %.0f, written %.0f, total %.0f\n", log_chn->statistics.events_written, wr->fBytesOut, incr, log_chn->statistics.bytes_written_subrun, log_chn->statistics.bytes_written, log_chn->statistics.bytes_written_total);
3626
3627 log_chn->statistics.bytes_written += incr;
3629 log_chn->statistics.bytes_written_total += incr;
3630 }
3631
3633 if (actual_time - start_time > 3000)
3634 cm_msg(MINFO, "log_write", "Write operation on \'%s\' took %d ms", log_chn->path.c_str(), actual_time - start_time);
3635
3636 if (status != SS_SUCCESS && !stop_requested) {
3637 cm_msg(MTALK, "log_write", "Error writing output file, stopping run");
3638 cm_msg(MERROR, "log_write", "Cannot write \'%s\', error %d, stopping run", log_chn->path.c_str(), status);
3639 stop_the_run(0);
3640
3641 return status;
3642 }
3643
3644 /* check if event limit is reached to stop run */
3646 log_chn->settings.event_limit > 0 &&
3647 log_chn->statistics.events_written >= log_chn->settings.event_limit) {
3649
3650 cm_msg(MTALK, "log_write", "stopping run after having received %1.0lf events",
3651 log_chn->settings.event_limit);
3652
3653 status = stop_the_run(1);
3654 return status;
3655 }
3656
3657 /* check if duration is reached for subrun */
3658 duration = 0;
3659 size = sizeof(duration);
3660 db_get_value(hDB, 0, "/Logger/Subrun duration", &duration, &size, TID_UINT32, TRUE);
3661 if (!stop_requested && duration > 0 && ss_time() >= subrun_start_time + duration) {
3662 int run_number;
3663
3664 // cm_msg(MTALK, "main", "stopping subrun after %d seconds", duration);
3665
3666 size = sizeof(run_number);
3667 status = db_get_value(hDB, 0, "Runinfo/Run number", &run_number, &size, TID_INT32, TRUE);
3668 assert(status == SUCCESS);
3669
3670 stop_requested = TRUE; // avoid recursive call thourgh log_odb_dump
3671 log_close(log_chn, run_number);
3672 log_chn->subrun_number++;
3673 log_chn->statistics.bytes_written_subrun = 0;
3674 log_create_writer(log_chn);
3675 log_generate_file_name(log_chn);
3676 log_open(log_chn, run_number);
3679 }
3680
3681 /* check if byte limit is reached for subrun */
3682 if (!stop_requested && log_chn->settings.subrun_byte_limit > 0 &&
3684 int run_number;
3685
3686 // cm_msg(MTALK, "main", "stopping subrun after %1.0lf bytes", log_chn->settings.subrun_byte_limit);
3687
3688 size = sizeof(run_number);
3689 status = db_get_value(hDB, 0, "Runinfo/Run number", &run_number, &size, TID_INT32, TRUE);
3690 assert(status == SUCCESS);
3691
3692 stop_requested = TRUE; // avoid recursive call thourgh log_odb_dump
3693 log_close(log_chn, run_number);
3694 log_chn->subrun_number++;
3695 log_chn->statistics.bytes_written_subrun = 0;
3696 log_create_writer(log_chn);
3697 log_generate_file_name(log_chn);
3698 log_open(log_chn, run_number);
3701 }
3702
3703 /* check if new subrun is requested manually */
3704 next_subrun = FALSE;
3705 size = sizeof(next_subrun);
3706 db_get_value(hDB, 0, "/Logger/Next subrun", &next_subrun, &size, TID_BOOL, true);
3707 if (!stop_requested && next_subrun) {
3708 int run_number;
3709
3710 // cm_msg(MTALK, "main", "stopping subrun by user request");
3711
3712 size = sizeof(run_number);
3713 status = db_get_value(hDB, 0, "Runinfo/Run number", &run_number, &size, TID_INT32, TRUE);
3714 assert(status == SUCCESS);
3715
3716 stop_requested = TRUE; // avoid recursive call thourgh log_odb_dump
3717 log_close(log_chn, run_number);
3718 log_chn->subrun_number++;
3719 log_chn->statistics.bytes_written_subrun = 0;
3720 log_create_writer(log_chn);
3721 log_generate_file_name(log_chn);
3722 log_open(log_chn, run_number);
3725
3726 next_subrun = FALSE;
3727 db_set_value(hDB, 0, "/Logger/Next subrun", &next_subrun, sizeof(next_subrun), 1, TID_BOOL);
3728 }
3729
3730 /* check if byte limit is reached to stop run */
3732 log_chn->settings.byte_limit > 0 &&
3733 log_chn->statistics.bytes_written >= log_chn->settings.byte_limit) {
3735
3736 cm_msg(MTALK, "log_write", "stopping run after having received %1.0lf mega bytes",
3737 log_chn->statistics.bytes_written / 1E6);
3738
3739 status = stop_the_run(1);
3740
3741 return status;
3742 }
3743
3744 /* stop run if less than 10MB free disk space */
3746 if (log_chn->type == LOG_TYPE_DISK && log_chn->do_disk_level && actual_time - log_chn->last_checked > DISK_CHECK_INTERVAL_MILLISEC) {
3747 log_chn->last_checked = actual_time;
3748
3749 const double MiB = 1024*1024;
3750 double disk_size = 0;
3751 double disk_free = 0;
3752
3753 log_disk_level(log_chn, &disk_size, &disk_free);
3754
3755 double limit = 10E6;
3756
3757 if (disk_size > 100E9) {
3758 limit = 1000E6;
3759 } else if (disk_size > 10E9) {
3760 limit = 100E6;
3761 }
3762
3763 if (disk_free < limit) {
3765 cm_msg(MTALK, "log_write", "disk nearly full, stopping the run");
3766 cm_msg(MERROR, "log_write", "Disk \'%s\' is almost full: %1.0lf MiBytes free out of %1.0f MiBytes, stopping the run", log_chn->path.c_str(), disk_free/MiB, disk_size/MiB);
3767
3768 status = stop_the_run(0);
3769 }
3770 }
3771
3772 return status;
3773}
virtual int wr_write(LOG_CHN *log_chn, const void *data, const int size)=0
#define MTALK
Definition midas.h:564
#define TID_UINT32
Definition midas.h:337
DWORD ss_time()
Definition system.cxx:3534
DWORD actual_time
Definition mfe.cxx:37
#define DISK_CHECK_INTERVAL_MILLISEC
Definition mlogger.cxx:284
int log_create_writer(LOG_CHN *log_chn)
Definition mlogger.cxx:3246
int log_generate_file_name(LOG_CHN *log_chn)
Definition mlogger.cxx:4712
INT log_open(LOG_CHN *log_chn, INT run_number)
Definition mlogger.cxx:3325
BOOL in_stop_transition
Definition mlogger.cxx:287
DWORD subrun_start_time
Definition mlogger.cxx:293
BOOL stop_requested
Definition mlogger.cxx:290
int log_disk_level(LOG_CHN *log_chn, double *pdisk_size, double *pdisk_free)
Definition mlogger.cxx:3411
int stop_the_run(int restart)
Definition mlogger.cxx:3505
double event_limit
Definition mlogger.cxx:168
double subrun_byte_limit
Definition mlogger.cxx:170
double byte_limit
Definition mlogger.cxx:169
double bytes_written_uncompressed
Definition mlogger.cxx:224
double events_written
Definition mlogger.cxx:222
Here is the call graph for this function:
Here is the caller graph for this function:

◆ logger_init()

void logger_init ( )

Definition at line 1592 of file mlogger.cxx.

1593{
1594 INT size, status, delay;
1595 BOOL flag;
1596 HNDLE hKey, hKeyChannel;
1597 KEY key;
1598 std::string str;
1599
1600 /*---- create /logger entries -----*/
1601
1602 str = cm_get_path();
1603 db_get_value_string(hDB, 0, "/Logger/Data dir", 0, &str, TRUE);
1604
1605 str = "";
1606 db_get_value_string(hDB, 0, "/Logger/Message dir", 0, &str, TRUE);
1607
1608 str = "";
1609 db_get_value_string(hDB, 0, "/Logger/History dir", 0, &str, TRUE);
1610
1611 str = "";
1612 db_get_value_string(hDB, 0, "/Logger/Message file date format", 0, &str, TRUE);
1613
1614 size = sizeof(BOOL);
1615 flag = TRUE;
1616 db_get_value(hDB, 0, "/Logger/Write data", &flag, &size, TID_BOOL, TRUE);
1617
1618 flag = FALSE;
1619 db_get_value(hDB, 0, "/Logger/ODB Dump", &flag, &size, TID_BOOL, TRUE);
1620
1621 str = "run%05d.json";
1622 db_get_value_string(hDB, 0, "/Logger/ODB Dump File", 0, &str, TRUE);
1623
1624 str = "last.json";
1625 db_get_value_string(hDB, 0, "/Logger/ODB Last Dump File", 0, &str, TRUE);
1626
1627 flag = FALSE;
1628 size = sizeof(BOOL);
1629 db_get_value(hDB, 0, "/Logger/Auto restart", &flag, &size, TID_BOOL, TRUE);
1630
1631 delay = 0;
1632 size = sizeof(INT);
1633 db_get_value(hDB, 0, "/Logger/Auto restart delay", &delay, &size, TID_INT32, TRUE);
1634
1635 flag = TRUE;
1636 db_get_value(hDB, 0, "/Logger/Tape message", &flag, &size, TID_BOOL, TRUE);
1637
1638 /* create at least one logging channel */
1639 status = db_find_key(hDB, 0, "/Logger/Channels/0", &hKey);
1640 if (status != DB_SUCCESS) {
1641 /* if no channels are defined, define at least one */
1642 status = db_create_record(hDB, 0, "/Logger/Channels/0", strcomb1(chn_tree_str).c_str());
1643 if (status != DB_SUCCESS)
1644 cm_msg(MERROR, "logger_init", "Cannot create channel entry in database");
1645 } else {
1646 /* check format of other channels */
1647 status = db_find_key(hDB, 0, "/Logger/Channels", &hKey);
1648 if (status == DB_SUCCESS) {
1649 for (int index = 0; ; index++) {
1650 status = db_enum_key(hDB, hKey, index, &hKeyChannel);
1652 break;
1653
1654 db_get_key(hDB, hKeyChannel, &key);
1655 status = db_check_record(hDB, hKey, key.name, strcomb1(chn_tree_str).c_str(), TRUE);
1656 if (status != DB_SUCCESS && status != DB_OPEN_RECORD) {
1657 cm_msg(MERROR, "logger_init", "Cannot create/check channel record %s, db_check_record() status %d", key.name, status);
1658 break;
1659 }
1660 }
1661 }
1662 }
1663#ifdef HAVE_MYSQL
1664 create_runlog_sql_tree();
1665#endif
1668}
#define DB_OPEN_RECORD
Definition midas.h:651
std::string strcomb1(const char **list)
Definition odb.cxx:668
INT db_check_record(HNDLE hDB, HNDLE hKey, const char *keyname, const char *rec_str, BOOL correct)
Definition odb.cxx:13003
INT db_create_record(HNDLE hDB, HNDLE hKey, const char *orig_key_name, const char *init_str)
Definition odb.cxx:12831
void create_runlog_json_tree()
Definition mlogger.cxx:2625
void create_runlog_ascii_tree()
Definition mlogger.cxx:2466
char name[NAME_LENGTH]
Definition midas.h:1030
Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 5456 of file mlogger.cxx.

5457{
5458 INT status, msg, i, size, ch = 0;
5460 BOOL debug, daemon, save_mode;
5461 DWORD last_time_kb = 0;
5462 DWORD last_time_stat = 0;
5463 DWORD duration;
5464
5465#ifdef SIGPIPE
5466 // undo ROOT overwrites SIGPIPE
5467 signal(SIGPIPE, SIG_IGN);
5468#endif
5469
5470 setbuf(stdout, NULL);
5471 setbuf(stderr, NULL);
5472
5473 /* get default from environment */
5475
5476 debug = daemon = save_mode = FALSE;
5477
5478 /* parse command line parameters */
5479 for (i = 1; i < argc; i++) {
5480 if (argv[i][0] == '-' && argv[i][1] == 'd')
5481 debug = TRUE;
5482 else if (argv[i][0] == '-' && argv[i][1] == 'D')
5483 daemon = TRUE;
5484 else if (argv[i][0] == '-' && argv[i][1] == 's')
5485 save_mode = TRUE;
5486 else if (argv[i][0] == '-' && argv[i][1] == 'v')
5487 verbose = TRUE;
5488 else if (argv[i][0] == '-') {
5489 if (i + 1 >= argc || argv[i + 1][0] == '-')
5490 goto usage;
5491 if (argv[i][1] == 'e')
5492 strcpy(exp_name, argv[++i]);
5493 else {
5494 usage:
5495 printf("usage: mlogger [-e Experiment] [-d] [-D] [-s] [-v]\n\n");
5496 return 1;
5497 }
5498 }
5499 }
5500
5501 if (daemon) {
5502 printf("Becoming a daemon...\n");
5504 }
5505
5506 status = cm_connect_experiment(host_name, exp_name, "Logger", NULL);
5507 if (status != CM_SUCCESS)
5508 return 1;
5509
5510 /* check if logger already running */
5511 status = cm_exist("Logger", FALSE);
5512 if (status == CM_SUCCESS) {
5513 printf("Logger runs already.\n");
5515 return 1;
5516 }
5517
5519
5520 /* turn off watchdog if in debug mode */
5521 if (debug)
5523
5524 /* turn on save mode */
5525 if (save_mode) {
5528 }
5529
5530 /* register transition callbacks */
5532 cm_msg(MERROR, "main", "cannot register callbacks");
5533 return 1;
5534 }
5535
5540
5541 /* initialize ODB */
5542 logger_init();
5543
5544 /* obtain current state */
5546 size = sizeof(local_state);
5547 status = db_get_value(hDB, 0, "/Runinfo/State", &local_state, &size, TID_INT32, true);
5548
5549 /* open history logging */
5550 if (open_history() != CM_SUCCESS) {
5551 printf("Error in history system, aborting startup.\n");
5553 return 1;
5554 }
5555
5556 /* print startup message */
5557 std::string data_dir;
5558 db_get_value_string(hDB, 0, "/Logger/Data dir", 0, &data_dir, TRUE);
5559 if (data_dir.length() <= 0)
5560 data_dir = cm_get_path();
5561 printf("Data directory is \"%s\" unless specified under /Logger/channels/\n", data_dir.c_str());
5562
5563 /* Alternate message path */
5564 std::string message_dir;
5565 db_get_value_string(hDB, 0, "/Logger/Message dir", 0, &message_dir, TRUE);
5566 if (message_dir.empty()) {
5567 message_dir = data_dir;
5568 printf("Message directory is \"%s\" unless specified in /Logger/Message dir\n", message_dir.c_str());
5569 } else
5570 printf("Message directory is \"%s\"\n", message_dir.c_str());
5571
5572 /* Alternate History and Elog path */
5573 std::string history_dir;
5574 db_get_value_string(hDB, 0, "/Logger/History dir", 0, &history_dir, TRUE);
5575 if (history_dir.empty()) {
5576 history_dir = data_dir;
5577 printf("History directory is \"%s\" unless specified under /Logger/history/\n", history_dir.c_str());
5578 } else
5579 printf("History directory is \"%s\"\n", history_dir.c_str());
5580
5581#ifdef HAVE_MYSQL
5582 {
5583 std::string sql_host;
5584 std::string sql_db;
5585 std::string sql_table;
5586
5587 HNDLE hktemp;
5588 status = db_find_key(hDB, 0, "/Logger/Runlog/SQL/Hostname", &hktemp);
5589 if (status == DB_SUCCESS) {
5590 db_get_value_string(hDB, 0, "/Logger/Runlog/SQL/Hostname", 0, &sql_host, FALSE);
5591 db_get_value_string(hDB, 0, "/Logger/Runlog/SQL/Database", 0, &sql_db, FALSE);
5592 db_get_value_string(hDB, 0, "/Logger/Runlog/SQL/Table", 0, &sql_table, FALSE);
5593 printf("SQL database is %s/%s/%s", sql_host.c_str(), sql_db.c_str(), sql_table.c_str());
5594 }
5595 }
5596#endif
5597
5598 printf("\nMIDAS logger started. Stop with \"!\"\n");
5599
5600 /* initialize ss_getchar() */
5601 ss_getchar(0);
5602
5603 /* start image history threads */
5605
5606 do {
5607 msg = cm_yield(100);
5608
5609 /* maybe update channel disk levels */
5611
5612 /* update channel statistics once every second */
5613 if (ss_millitime() - last_time_stat > 1000) {
5614 last_time_stat = ss_millitime();
5615 /*
5616 printf("update statistics!\n");
5617 //LOG_CHN* log_chn = log_chn[0];
5618 printf("events %.0f, subrun %.0f, written %.0f, total %.0f\n", log_chn->statistics.events_written,
5619 log_chn->statistics.bytes_written_subrun,
5620 log_chn->statistics.bytes_written,
5621 log_chn->statistics.bytes_written_total);
5622 */
5624 }
5625
5626 /* check for auto restart */
5627 if (auto_restart && ss_time() > auto_restart) {
5629 }
5630
5631 /* check if time is reached to stop run */
5632 duration = 0;
5633 size = sizeof(duration);
5634 db_get_value(hDB, 0, "/Logger/Run duration", &duration, &size, TID_UINT32, true);
5636 duration > 0 && ss_time() >= run_start_time + duration) {
5637 cm_msg(MTALK, "main", "stopping run after %d seconds", duration);
5638 status = stop_the_run(1);
5639 }
5640
5641 /* stop the run if previous attempt failed */
5642 if (stop_try_later) {
5643 if (ss_time_sec() > stop_try_later) {
5644 cm_msg(MTALK, "main", "another attempt to stop the run");
5645 status = stop_the_run(0);
5646 }
5647 }
5648
5649 /* check keyboard once every 100 ms */
5650 if (ss_millitime() - last_time_kb > 100) {
5651 last_time_kb = ss_millitime();
5652
5653 ch = 0;
5654 while (ss_kbhit()) {
5655 ch = ss_getchar(0);
5656 if (ch == -1)
5657 ch = getchar();
5658
5659 if ((char) ch == '!')
5660 break;
5661 }
5662 }
5663
5664 } while (msg != RPC_SHUTDOWN && msg != SS_ABORT && ch != '!');
5665
5666 /* reset terminal */
5668
5669 /* close history logging */
5670 close_history();
5671
5672 /* stop image history threads */
5674 printf("Stopping image history threads...");
5675 fflush(stdout);
5677 printf("ok\n");
5678 }
5679
5681
5682 return 0;
5683}
static void usage()
INT cm_register_transition(INT transition, INT(*func)(INT, char *), INT sequence_number)
Definition midas.cxx:3617
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition midas.cxx:3027
INT cm_connect_experiment(const char *host_name, const char *exp_name, const char *client_name, void(*func)(char *))
Definition midas.cxx:2294
INT cm_get_environment(char *host_name, int host_name_size, char *exp_name, int exp_name_size)
Definition midas.cxx:2150
INT cm_set_watchdog_params(BOOL call_watchdog, DWORD timeout)
Definition midas.cxx:3299
INT cm_exist(const char *name, BOOL bUnique)
Definition midas.cxx:7531
#define SS_ABORT
Definition midas.h:678
#define RPC_SHUTDOWN
Definition midas.h:708
#define TR_RESUME
Definition midas.h:408
#define TR_PAUSE
Definition midas.h:407
#define TR_START
Definition midas.h:405
#define TR_STARTABORT
Definition midas.h:409
#define STATE_STOPPED
Definition midas.h:305
#define TR_STOP
Definition midas.h:406
BOOL ss_kbhit()
Definition system.cxx:3736
INT ss_getchar(BOOL reset)
Definition system.cxx:7581
INT ss_daemon_init(BOOL keep_stdout)
Definition system.cxx:2073
double ss_time_sec()
Definition system.cxx:3539
INT db_send_changed_records()
Definition odb.cxx:13809
INT db_protect_database(HNDLE hDB)
Definition odb.cxx:3251
std::string history_dir()
char exp_name[NAME_LENGTH]
Definition mana.cxx:243
BOOL debug
debug printouts
Definition mana.cxx:254
BOOL daemon
Definition mana.cxx:258
#define NAME_LENGTH
Definition midas.h:272
INT tr_stop(INT run_number, char *error)
Definition mlogger.cxx:5295
INT tr_start_abort(INT run_number, char *error)
Definition mlogger.cxx:5266
void stop_image_history()
INT local_state
Definition mlogger.cxx:286
INT tr_pause(INT run_number, char *error)
Definition mlogger.cxx:5403
INT tr_start(INT run_number, char *error)
Definition mlogger.cxx:4974
INT tr_resume(INT run_number, char *error)
Definition mlogger.cxx:5415
int maybe_check_disk_level()
Definition mlogger.cxx:3440
DWORD auto_restart
Definition mlogger.cxx:292
int start_the_run()
Definition mlogger.cxx:3539
double stop_try_later
Definition mlogger.cxx:294
int get_number_image_history_threads()
DWORD run_start_time
Definition mlogger.cxx:293
void logger_init()
Definition mlogger.cxx:1592
void start_image_history()
Here is the call graph for this function:

◆ maybe_check_disk_level()

int maybe_check_disk_level ( )

Definition at line 3440 of file mlogger.cxx.

3441{
3443 static DWORD last_check_time = 0;
3444
3445 if (last_check_time == 0)
3446 last_check_time = actual_time;
3447
3448 if (actual_time - last_check_time < DISK_CHECK_INTERVAL_MILLISEC)
3449 return SUCCESS;
3450
3451 last_check_time = actual_time;
3452
3453 for (unsigned i = 0; i < log_channels.size(); i++) {
3454 LOG_CHN* chn = log_channels[i];
3455
3456 if (!chn->do_disk_level)
3457 continue;
3458
3459 log_disk_level(chn, NULL, NULL);
3460 }
3461
3462 return SUCCESS;
3463}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ maybe_flush_history()

void maybe_flush_history ( time_t  now)

Definition at line 4550 of file mlogger.cxx.

4551{
4552 time_t flush_period_sec = 1; // flush once every 1 seconds
4553
4554 if ((last_history_flush == 0) || (now >= last_history_flush + flush_period_sec)) {
4555
4556 if (verbose)
4557 printf("flush history buffers!\n");
4558
4559 for (unsigned h = 0; h < mh.size(); h++)
4560 mh[h]->hs_flush_buffers();
4561
4562 last_history_flush = now;
4563 }
4564}
time_t last_history_flush
Definition mlogger.cxx:4548
Here is the caller graph for this function:

◆ new_LOG_CHN()

LOG_CHN * new_LOG_CHN ( const char *  name)

Definition at line 274 of file mlogger.cxx.

275{
276 LOG_CHN* chn = new LOG_CHN;
277 chn->name = name;
278 // chn->settings clear settings
279 return chn;
280};
Here is the caller graph for this function:

◆ NewChecksum()

WriterInterface * NewChecksum ( LOG_CHN log_chn,
int  code,
int  level,
WriterInterface chained 
)

Definition at line 3121 of file mlogger.cxx.

3122{
3123 if (code == CHECKSUM_NONE) {
3124 return chained;
3125 } else if (code == CHECKSUM_ZLIB) {
3126 return new WriterCRC32Zlib(log_chn, level, chained);
3127 } else if (code == CHECKSUM_CRC32C) {
3128 return new WriterCRC32C(log_chn, level, chained);
3129 } else if (code == CHECKSUM_SHA256) {
3130 return new WriterSHA256(log_chn, level, chained);
3131 } else if (code == CHECKSUM_SHA512) {
3132 return new WriterSHA512(log_chn, level, chained);
3133 } else {
3134 cm_msg(MERROR, "log_create_writer", "channel %s unknown checksum code %d", log_chn->path.c_str(), code);
3135 return chained;
3136 }
3137}
#define CHECKSUM_ZLIB
Definition mlogger.cxx:3116
#define CHECKSUM_CRC32C
Definition mlogger.cxx:3117
#define CHECKSUM_SHA256
Definition mlogger.cxx:3118
#define CHECKSUM_NONE
Definition mlogger.cxx:3115
#define CHECKSUM_SHA512
Definition mlogger.cxx:3119
Here is the call graph for this function:
Here is the caller graph for this function:

◆ NewCompression()

WriterInterface * NewCompression ( LOG_CHN log_chn,
int  code,
WriterInterface chained 
)

Definition at line 3145 of file mlogger.cxx.

3146{
3147 if (code == COMPRESS_NONE) {
3148 return chained;
3149 } else if (code == COMPRESS_LZ4) {
3150 return new WriterLZ4(log_chn, chained);
3151 } else {
3152 cm_msg(MERROR, "log_create_writer", "channel %s unknown compression code %d", log_chn->path.c_str(), code);
3153 return chained;
3154 }
3155}
#define COMPRESS_NONE
Definition mlogger.cxx:3139
#define COMPRESS_LZ4
Definition mlogger.cxx:3141
Here is the call graph for this function:
Here is the caller graph for this function:

◆ NewWriterBzip2()

WriterInterface * NewWriterBzip2 ( LOG_CHN log_chn)

Definition at line 3081 of file mlogger.cxx.

3082{
3083 std::string bzip2_command = "bzip2 -z";
3084
3085 if (log_chn->settings.bzip2_compression) {
3086 bzip2_command += " -";
3087 bzip2_command += IntToString(log_chn->settings.bzip2_compression);
3088 }
3089
3090 return new WriterPopen(log_chn, (bzip2_command + " > ").c_str(), ".bz2");
3091}
static std::string IntToString(int value)
Definition mlogger.cxx:46
uint32_t bzip2_compression
Definition mlogger.cxx:183
Here is the call graph for this function:
Here is the caller graph for this function:

◆ NewWriterPbzip2()

WriterInterface * NewWriterPbzip2 ( LOG_CHN log_chn)

Definition at line 3093 of file mlogger.cxx.

3094{
3095 std::string pbzip2_command = "pbzip2 -c -z";
3096
3097 if (log_chn->settings.pbzip2_num_cpu) {
3098 pbzip2_command += " -p";
3099 pbzip2_command += IntToString(log_chn->settings.pbzip2_num_cpu);
3100 }
3101
3102 if (log_chn->settings.pbzip2_compression) {
3103 pbzip2_command += " -";
3104 pbzip2_command += IntToString(log_chn->settings.pbzip2_compression);
3105 }
3106
3107 if (strlen(log_chn->settings.pbzip2_options) > 0) {
3108 pbzip2_command += " ";
3109 pbzip2_command += log_chn->settings.pbzip2_options;
3110 }
3111
3112 return new WriterPopen(log_chn, (pbzip2_command + " > ").c_str(), ".bz2");
3113}
uint32_t pbzip2_num_cpu
Definition mlogger.cxx:184
uint32_t pbzip2_compression
Definition mlogger.cxx:185
char pbzip2_options[256]
Definition mlogger.cxx:186
Here is the call graph for this function:
Here is the caller graph for this function:

◆ odb_save()

void odb_save ( const char *  filename,
bool  make_file_readonly 
)

Definition at line 1774 of file mlogger.cxx.

1775{
1776 std::string path;
1777
1778 if (strchr(filename, DIR_SEPARATOR) == NULL) {
1779 db_get_value_string(hDB, 0, "/Logger/Data Dir", 0, &path, TRUE, 256);
1780 if (path.length() > 0) {
1781 if (!ends_with_char(path, DIR_SEPARATOR)) {
1782 path += DIR_SEPARATOR_STR;
1783 }
1784 }
1785 path += filename;
1786 } else {
1787 path = filename;
1788 }
1789
1790 //printf("filename [%s] path [%s]\n", filename, path.c_str());
1791
1792 DWORD t0 = ss_millitime();
1793
1794 if (ends_with_ustring(filename, ".xml"))
1795 db_save_xml(hDB, 0, path.c_str());
1796 else if (ends_with_ustring(filename, ".json"))
1797 db_save_json(hDB, 0, path.c_str());
1798 else
1799 db_save(hDB, 0, path.c_str(), FALSE);
1800
1801 if (make_file_readonly)
1802 chmod(path.c_str(), 0444);
1803
1804 DWORD te = ss_millitime();
1805
1806 if (verbose)
1807 printf("saved odb to \"%s\" in %d ms\n", path.c_str(), te-t0);
1808}
INT db_save_json(HNDLE hDB, HNDLE hKey, const char *filename, int flags)
Definition odb.cxx:10548
INT db_save_xml(HNDLE hDB, HNDLE hKey, const char *filename)
Definition odb.cxx:9503
INT db_save(HNDLE hDB, HNDLE hKey, const char *filename, BOOL bRemote)
Definition odb.cxx:9263
BOOL ends_with_ustring(const char *str, const char *suffix)
Definition odb.cxx:3306
bool ends_with_char(const std::string &s, char c)
Definition midas.cxx:412
Here is the call graph for this function:
Here is the caller graph for this function:

◆ open_history()

INT open_history ( )

Definition at line 3901 of file mlogger.cxx.

3902{
3903 INT size, index, i_tag, status, i, j, li, max_event_id;
3904 int ieq;
3905 INT n_var, n_tags, n_names = 0;
3906 HNDLE hKeyRoot, hKeyVar, hLinkKey, hVarKey, hKeyEq, hHistKey, hKey;
3907 HNDLE hKeyHist;
3908 TAG *tag = NULL;
3909 KEY key, varkey, linkkey, histkey;
3910 WORD eq_id;
3911 char str[256], eq_name[NAME_LENGTH], hist_name[NAME_LENGTH];
3912 int global_per_variable_history = 0;
3913
3914 time_t now = time(NULL);
3915
3916 double tstart = ss_time_sec();
3917
3918 // delete old history channels
3919
3920 for (unsigned i=0; i<mh.size(); i++)
3921 delete mh[i];
3922 mh.clear();
3923
3924 history_events.clear();
3925
3926 // create and initialize the history channels tree
3927
3928 status = db_find_key(hDB, 0, "/Logger/History", &hKeyHist);
3929
3930 if (status == DB_NO_KEY) {
3931 int active;
3932 std::string type;
3933 int debug;
3934
3935 // create entry for FILE history
3936
3937 type = "FILE";
3938 status = db_get_value_string(hDB, 0, "/Logger/History/FILE/Type", 0, &type, TRUE);
3939 assert(status==DB_SUCCESS);
3940
3941 active = 1;
3942 size = sizeof(active);
3943 status = db_get_value(hDB, 0, "/Logger/History/FILE/Active", &active, &size, TID_BOOL, TRUE);
3944 assert(status==DB_SUCCESS);
3945
3946 debug = 0;
3947 size = sizeof(debug);
3948 status = db_get_value(hDB, 0, "/Logger/History/FILE/Debug", &debug, &size, TID_INT32, TRUE);
3949 assert(status==DB_SUCCESS);
3950
3951 int per_variable = 1;
3952 size = sizeof(per_variable);
3953 status = db_get_value(hDB, 0, "/Logger/History/FILE/PerVariableHistory", &per_variable, &size, TID_INT32, TRUE);
3954 assert(status==DB_SUCCESS);
3955
3956 // create entry for the MIDAS history
3957
3958 type = "MIDAS";
3959 status = db_get_value_string(hDB, 0, "/Logger/History/MIDAS/Type", 0, &type, TRUE);
3960 assert(status==DB_SUCCESS);
3961
3962 active = 0;
3963 size = sizeof(active);
3964 status = db_get_value(hDB, 0, "/Logger/History/MIDAS/Active", &active, &size, TID_BOOL, TRUE);
3965 assert(status==DB_SUCCESS);
3966
3967 debug = 0;
3968 size = sizeof(debug);
3969 status = db_get_value(hDB, 0, "/Logger/History/MIDAS/Debug", &debug, &size, TID_INT32, TRUE);
3970 assert(status==DB_SUCCESS);
3971
3972 // create entry for ODBC (MySQL) history
3973
3974 type = "ODBC";
3975 status = db_get_value_string(hDB, 0, "/Logger/History/ODBC/Type", 0, &type, TRUE);
3976 assert(status==DB_SUCCESS);
3977
3978 active = 0;
3979 size = sizeof(active);
3980 status = db_get_value(hDB, 0, "/Logger/History/ODBC/Active", &active, &size, TID_BOOL, TRUE);
3981 assert(status==DB_SUCCESS);
3982
3983 debug = 0;
3984 size = sizeof(debug);
3985 status = db_get_value(hDB, 0, "/Logger/History/ODBC/Debug", &debug, &size, TID_INT32, TRUE);
3986 assert(status==DB_SUCCESS);
3987
3988 // create entry for SQLITE history
3989
3990 type = "SQLITE";
3991 status = db_get_value_string(hDB, 0, "/Logger/History/SQLITE/Type", 0, &type, TRUE);
3992 assert(status==DB_SUCCESS);
3993
3994 active = 0;
3995 size = sizeof(active);
3996 status = db_get_value(hDB, 0, "/Logger/History/SQLITE/Active", &active, &size, TID_BOOL, TRUE);
3997 assert(status==DB_SUCCESS);
3998
3999 debug = 0;
4000 size = sizeof(debug);
4001 status = db_get_value(hDB, 0, "/Logger/History/SQLITE/Debug", &debug, &size, TID_INT32, TRUE);
4002 assert(status==DB_SUCCESS);
4003
4004 // create entry for MYSQL history writer
4005
4006 type = "MYSQL";
4007 status = db_get_value_string(hDB, 0, "/Logger/History/MYSQL/Type", 0, &type, TRUE);
4008 assert(status==DB_SUCCESS);
4009
4010 active = 0;
4011 size = sizeof(active);
4012 status = db_get_value(hDB, 0, "/Logger/History/MYSQL/Active", &active, &size, TID_BOOL, TRUE);
4013 assert(status==DB_SUCCESS);
4014
4015 debug = 0;
4016 size = sizeof(debug);
4017 status = db_get_value(hDB, 0, "/Logger/History/MYSQL/Debug", &debug, &size, TID_INT32, TRUE);
4018 assert(status==DB_SUCCESS);
4019
4020 // create entry for PGSQL history writer
4021
4022 type = "PGSQL";
4023 status = db_get_value_string(hDB, 0, "/Logger/History/PGSQL/Type", 0, &type, TRUE);
4024 assert(status==DB_SUCCESS);
4025
4026 active = 0;
4027 size = sizeof(active);
4028 status = db_get_value(hDB, 0, "/Logger/History/PGSQL/Active", &active, &size, TID_BOOL, TRUE);
4029 assert(status==DB_SUCCESS);
4030
4031 debug = 0;
4032 size = sizeof(debug);
4033 status = db_get_value(hDB, 0, "/Logger/History/PGSQL/Debug", &debug, &size, TID_INT32, TRUE);
4034 assert(status==DB_SUCCESS);
4035
4036 // get newly created /Logger/History
4037
4038 status = db_find_key(hDB, 0, "/Logger/History", &hKeyHist);
4039 }
4040
4041 if (status != DB_SUCCESS) {
4042 cm_msg(MERROR, "open_history", "Something is wrong with /Logger/History, db_find_key() status %d", status);
4043 return status;
4044 }
4045
4046 // loop over history channels
4047
4048 for (int ichan = 0; ; ichan++) {
4049 status = db_enum_key(hDB, hKeyHist, ichan, &hKey);
4050 if (status != DB_SUCCESS)
4051 break;
4052
4053 MidasHistoryInterface* hi = NULL;
4054
4056
4057 if (status==HS_SUCCESS && hi) {
4058 if (strcasecmp(hi->type, "MIDAS")==0) {
4059 i = 0;
4060 size = sizeof(i);
4061 status = db_get_value(hDB, hKey, "PerVariableHistory", &i, &size, TID_INT32, TRUE);
4062 assert(status==DB_SUCCESS);
4063
4064 if (i)
4065 global_per_variable_history = 1;
4066 } else if (strcasecmp(hi->type, "FILE")==0) {
4067 i = 0;
4068 size = sizeof(i);
4069 status = db_get_value(hDB, hKey, "PerVariableHistory", &i, &size, TID_INT32, TRUE);
4070 assert(status==DB_SUCCESS);
4071
4072 if (i)
4073 global_per_variable_history = 1;
4074 } else if (strcasecmp(hi->type, "ODBC")==0) {
4075 global_per_variable_history = 1;
4076 } else if (strcasecmp(hi->type, "SQLITE")==0) {
4077 global_per_variable_history = 1;
4078 } else if (strcasecmp(hi->type, "MYSQL")==0) {
4079 global_per_variable_history = 1;
4080 } else if (strcasecmp(hi->type, "PGSQL")==0) {
4081 global_per_variable_history = 1;
4082 }
4083
4084 if (verbose)
4085 cm_msg(MINFO, "open_history", "Writing history to channel \'%s\' type \'%s\'", hi->name, hi->type);
4086
4087 mh.push_back(hi);
4088 }
4089 }
4090
4091 // prepare history channels
4092
4093 for (unsigned i=0; i<mh.size(); i++) {
4094 status = mh[i]->hs_clear_cache();
4095 assert(status == HS_SUCCESS);
4096 }
4097
4098 // check global per-variable history settings
4099
4100 i = 0;
4101 size = sizeof(i);
4102 status = db_get_value(hDB, 0, "/History/PerVariableHistory", &i, &size, TID_INT32, FALSE);
4103 if (status==DB_SUCCESS) {
4104 cm_msg(MERROR, "open_history", "mlogger ODB setting /History/PerVariableHistory is obsolete, please delete it. Use /Logger/History/MIDAS/PerVariableHistory instead");
4105 if (i)
4106 global_per_variable_history = i;
4107 }
4108
4109 if (global_per_variable_history) {
4110 static int previous = -1;
4111 if (global_per_variable_history != previous) {
4112 if (global_per_variable_history)
4113 cm_msg(MINFO, "open_history", "Per-variable history is enabled");
4114 else
4115 ;//cm_msg(MINFO, "open_history", "Per-variable history is disabled");
4116 }
4117 previous = global_per_variable_history;
4118 }
4119
4120 // setup history links
4121
4122 if (db_find_key(hDB, 0, "/History/Links", &hKeyRoot) != DB_SUCCESS ||
4123 db_find_key(hDB, 0, "/History/Links/System", &hKeyRoot) != DB_SUCCESS) {
4124 /* create default history keys */
4125 db_create_key(hDB, 0, "/History/Links", TID_KEY);
4126
4127 if (db_find_key(hDB, 0, "/Equipment/Trigger/Statistics/Events per sec.", &hKeyEq) == DB_SUCCESS)
4128 db_create_link(hDB, 0, "/History/Links/System/Trigger per sec.",
4129 "/Equipment/Trigger/Statistics/Events per sec.");
4130
4131 if (db_find_key(hDB, 0, "/Equipment/Trigger/Statistics/kBytes per sec.", &hKeyEq) == DB_SUCCESS)
4132 db_create_link(hDB, 0, "/History/Links/System/Trigger kB per sec.",
4133 "/Equipment/Trigger/Statistics/kBytes per sec.");
4134 }
4135
4136 /*---- define equipment events as history ------------------------*/
4137
4138 max_event_id = 0;
4139
4140 status = db_find_key(hDB, 0, "/Equipment", &hKeyRoot);
4141 if (status == DB_NO_KEY) {
4142 cm_msg(MINFO, "open_history", "Cannot find /Equipment entry in database, history system is inactive");
4143 return CM_SUCCESS;
4144 }
4145
4146 if (status != DB_SUCCESS) {
4147 cm_msg(MERROR, "open_history", "Cannot find /Equipment entry in database, db_find_key() status %d", status);
4148 return status;
4149 }
4150
4151 /* loop over equipment */
4152 index = 0;
4153 for (ieq = 0; ; ieq++) {
4154 status = db_enum_key(hDB, hKeyRoot, ieq, &hKeyEq);
4155 if (status != DB_SUCCESS)
4156 break;
4157
4158 int32_t min_period = 0; // in seconds
4159
4160 /* retrieve min period for history logging */
4161 size = sizeof(min_period);
4162 db_get_value(hDB, hKeyEq, "Common/Log history", &min_period, &size, TID_INT32, TRUE);
4163
4164 /* define history tags only if log history flag is on */
4165 if (min_period > 0) {
4166 BOOL per_variable_history = global_per_variable_history;
4167
4168 /* get equipment name */
4169 db_get_key(hDB, hKeyEq, &key);
4170 strcpy(eq_name, key.name);
4171
4172 if (strchr(eq_name, ':'))
4173 cm_msg(MERROR, "open_history", "Equipment name \'%s\' contains characters \':\', this may break the history system", eq_name);
4174
4175 status = db_find_key(hDB, hKeyEq, "Variables", &hKeyVar);
4176 if (status != DB_SUCCESS) {
4177 cm_msg(MERROR, "open_history", "Cannot find /Equipment/%s/Variables entry in database", eq_name);
4178 return 0;
4179 }
4180
4181 size = sizeof(eq_id);
4182 status = db_get_value(hDB, hKeyEq, "Common/Event ID", &eq_id, &size, TID_UINT16, TRUE);
4183 assert(status == DB_SUCCESS);
4184
4185 size = sizeof(int);
4186 status = db_get_value(hDB, hKeyEq, "Settings/PerVariableHistory", &per_variable_history, &size, TID_INT32, FALSE);
4187 assert(status == DB_SUCCESS || status == DB_NO_KEY);
4188
4189 if (verbose)
4190 printf
4191 ("\n==================== Equipment \"%s\", ID %d =======================\n",
4192 eq_name, eq_id);
4193
4194 /* count keys in variables tree */
4195 for (n_var = 0, n_tags = 0;; n_var++) {
4196 status = db_enum_key(hDB, hKeyVar, n_var, &hKey);
4198 break;
4199 db_get_key(hDB, hKey, &key);
4200 if (key.type != TID_KEY) {
4201 n_tags += key.num_values;
4202 }
4203 else {
4204 int ii;
4205 for (ii=0;; ii++) {
4206 KEY vvarkey;
4207 HNDLE hhKey;
4208
4209 status = db_enum_key(hDB, hKey, ii, &hhKey);
4211 break;
4212
4213 /* get variable key */
4214 db_get_key(hDB, hhKey, &vvarkey);
4215
4216 n_tags += vvarkey.num_values;
4217 }
4218 }
4219 }
4220
4221 if (n_var == 0)
4222 cm_msg(MINFO, "open_history", "Equipment \"%s\" history is enabled, but there are no Variables in ODB", eq_name);
4223
4224 /* create tag array */
4225 tag = (TAG *) calloc(sizeof(TAG), n_tags);
4226
4227 i_tag = 0;
4228 for (i=0; ; i++) {
4229 status = db_enum_key(hDB, hKeyVar, i, &hKey);
4231 break;
4232
4233 /* get variable key */
4234 db_get_key(hDB, hKey, &varkey);
4235
4236
4237 HNDLE hKeyNames = 0;
4238 BOOL single_names = false;
4239
4240 /* look for names */
4241
4242 if (!hKeyNames) {
4243 sprintf(str, "Settings/Names %s", varkey.name);
4244 db_find_key(hDB, hKeyEq, str, &hKeyNames);
4245 if (hKeyNames) {
4246 if (verbose)
4247 printf("Using \"/Equipment/%s/Settings/Names %s\" for variable \"%s\"\n", eq_name, varkey.name, varkey.name);
4248
4249 /* define tags from names list */
4250 db_get_key(hDB, hKeyNames, &key);
4251 n_names = key.num_values;
4252 }
4253 }
4254
4255 if (!hKeyNames) {
4256 db_find_key(hDB, hKeyEq, "Settings/Names", &hKeyNames);
4257 single_names = (hKeyNames > 0);
4258
4259 if (hKeyNames) {
4260 if (verbose)
4261 printf("Using \"/Equipment/%s/Settings/Names\" for variable \"%s\"\n", eq_name, varkey.name);
4262
4263 /* define tags from names list */
4264 db_get_key(hDB, hKeyNames, &key);
4265 n_names = key.num_values;
4266 }
4267 }
4268
4269 if (hKeyNames && n_names < varkey.num_values) {
4270 cm_msg(MERROR, "open_history",
4271 "Array size mismatch: \"/Equipment/%s/Settings/%s\" has %d entries while \"/Equipment/%s/Variables/%s\" has %d entries",
4272 eq_name, key.name, n_names,
4273 eq_name, varkey.name, varkey.num_values);
4274 free(tag);
4275 return 0;
4276 }
4277
4278 if (hKeyNames) {
4279 /* loop over array elements */
4280 for (j = 0; j < varkey.num_values; j++) {
4281 char xname[256];
4282
4283 tag[i_tag].name[0] = 0;
4284
4285 /* get name #j */
4286 size = sizeof(xname);
4287 status = db_get_data_index(hDB, hKeyNames, xname, &size, j, TID_STRING);
4288 if (status == DB_SUCCESS)
4289 mstrlcpy(tag[i_tag].name, xname, sizeof(tag[i_tag].name));
4290
4291 if (strlen(tag[i_tag].name) < 1) {
4292 char buf[256];
4293 sprintf(buf, "%d", j);
4294 mstrlcpy(tag[i_tag].name, varkey.name, NAME_LENGTH);
4295 mstrlcat(tag[i_tag].name, "_", NAME_LENGTH);
4296 mstrlcat(tag[i_tag].name, buf, NAME_LENGTH);
4297 }
4298
4299 /* append variable key name for single name array */
4300 if (single_names) {
4301 if (strlen(tag[i_tag].name) + 1 + strlen(varkey.name) >= NAME_LENGTH) {
4302 cm_msg(MERROR, "open_history",
4303 "Name for history entry \"%s %s\" too long", tag[i_tag].name, varkey.name);
4304 free(tag);
4305 return 0;
4306 }
4307 mstrlcat(tag[i_tag].name, " ", NAME_LENGTH);
4308 mstrlcat(tag[i_tag].name, varkey.name, NAME_LENGTH);
4309 }
4310
4311 tag[i_tag].type = varkey.type;
4312 tag[i_tag].n_data = 1;
4313
4314 if (verbose)
4315 printf("Defined tag %d, name \"%s\", type %d, num_values %d\n",
4316 i_tag, tag[i_tag].name, tag[i_tag].type, tag[i_tag].n_data);
4317
4318 i_tag++;
4319 }
4320 } else if (varkey.type == TID_KEY) {
4321 int ii;
4322 for (ii=0;; ii++) {
4323 KEY vvarkey;
4324 HNDLE hhKey;
4325
4326 status = db_enum_key(hDB, hKey, ii, &hhKey);
4328 break;
4329
4330 /* get variable key */
4331 db_get_key(hDB, hhKey, &vvarkey);
4332
4333 mstrlcpy(tag[i_tag].name, varkey.name, NAME_LENGTH);
4334 mstrlcat(tag[i_tag].name, "_", NAME_LENGTH);
4335 mstrlcat(tag[i_tag].name, vvarkey.name, NAME_LENGTH);
4336 tag[i_tag].type = vvarkey.type;
4337 tag[i_tag].n_data = vvarkey.num_values;
4338
4339 if (verbose)
4340 printf("Defined tag %d, name \"%s\", type %d, num_values %d\n", i_tag, tag[i_tag].name,
4341 tag[i_tag].type, tag[i_tag].n_data);
4342
4343 i_tag++;
4344 }
4345 } else {
4346 mstrlcpy(tag[i_tag].name, varkey.name, NAME_LENGTH);
4347 tag[i_tag].type = varkey.type;
4348 tag[i_tag].n_data = varkey.num_values;
4349
4350 if (verbose)
4351 printf("Defined tag %d, name \"%s\", type %d, num_values %d\n", i_tag, tag[i_tag].name,
4352 tag[i_tag].type, tag[i_tag].n_data);
4353
4354 i_tag++;
4355 }
4356
4357 if (per_variable_history && i_tag>0) {
4358 WORD event_id = 0;
4359 char event_name[NAME_LENGTH];
4360
4361 mstrlcpy(event_name, eq_name, NAME_LENGTH);
4362 mstrlcat(event_name, "/", NAME_LENGTH);
4363 mstrlcat(event_name, varkey.name, NAME_LENGTH);
4364
4365 assert(i_tag <= n_tags);
4366
4367 status = add_event(&index, now, event_id, event_name, hKey, i_tag, tag, min_period, 1);
4368 if (status != DB_SUCCESS)
4369 return status;
4370
4371 i_tag = 0;
4372 } /* if per-variable history */
4373
4374 } /* loop over variables */
4375
4376 if (!per_variable_history && i_tag>0) {
4377 assert(i_tag <= n_tags);
4378
4379 status = add_event(&index, now, eq_id, eq_name, hKeyVar, i_tag, tag, min_period, 1);
4380 if (status != DB_SUCCESS)
4381 return status;
4382
4383 }
4384
4385 if (tag) {
4386 free(tag);
4387 tag = NULL;
4388 }
4389
4390 /* remember maximum event id for later use with system events */
4391 if (eq_id > max_event_id)
4392 max_event_id = eq_id;
4393 }
4394 } /* loop over equipments */
4395
4396 /*---- define linked trees --------------------------------------*/
4397
4398 /* round up event id */
4399 max_event_id = ((int) ((max_event_id + 1) / 10) + 1) * 10;
4400
4401 status = db_find_key(hDB, 0, "/History/Links", &hKeyRoot);
4402 if (status == DB_SUCCESS) {
4403 for (li = 0;; li++) {
4404 status = db_enum_link(hDB, hKeyRoot, li, &hHistKey);
4406 break;
4407
4408 db_get_key(hDB, hHistKey, &histkey);
4409 strcpy(hist_name, histkey.name);
4410 db_enum_key(hDB, hKeyRoot, li, &hHistKey);
4411
4412 db_get_key(hDB, hHistKey, &key);
4413 if (key.type != TID_KEY) {
4414 cm_msg(MERROR, "open_history", "Only subkeys allows in /History/Links, key \"%s\"", key.name);
4415 continue;
4416 }
4417
4418 if (verbose)
4419 printf("\n==================== History link \"%s\", ID %d =======================\n",
4420 hist_name, max_event_id);
4421
4422 /* count subkeys in link */
4423 for (i = n_var = 0;; i++) {
4424 status = db_enum_key(hDB, hHistKey, i, &hKey);
4426 break;
4427
4428 if (status == DB_SUCCESS && db_get_key(hDB, hKey, &key) == DB_SUCCESS) {
4429 if (key.type != TID_KEY)
4430 n_var++;
4431 } else {
4432 db_enum_link(hDB, hHistKey, i, &hKey);
4433 db_get_key(hDB, hKey, &key);
4434 cm_msg(MERROR, "open_history",
4435 "History link /History/Links/%s/%s is invalid", hist_name, key.name);
4436 return 0;
4437 }
4438 }
4439
4440 if (n_var == 0)
4441 cm_msg(MERROR, "open_history", "History event %s has no variables in ODB", hist_name);
4442 else {
4443 /* create tag array */
4444 tag = (TAG *) calloc(sizeof(TAG), n_var);
4445
4446 assert(tag != NULL);
4447
4448 for (i = 0, size = 0, n_var = 0;; i++) {
4449 status = db_enum_link(hDB, hHistKey, i, &hLinkKey);
4451 break;
4452
4453 /* get link key */
4454 db_get_key(hDB, hLinkKey, &linkkey);
4455
4456 if (linkkey.type == TID_KEY)
4457 continue;
4458
4459 /* get link target */
4460 db_enum_key(hDB, hHistKey, i, &hVarKey);
4461 if (db_get_key(hDB, hVarKey, &varkey) == DB_SUCCESS) {
4462 /* hot-link individual values */
4463 if (histkey.type == TID_KEY) {
4464 db_close_record(hDB, hVarKey); // close previously opened record
4465 db_open_record(hDB, hVarKey, NULL, varkey.total_size, MODE_READ, log_system_history,
4466 (void *) (POINTER_T) index);
4467 }
4468
4469 strcpy(tag[n_var].name, linkkey.name);
4470 tag[n_var].type = varkey.type;
4471 tag[n_var].n_data = varkey.num_values;
4472
4473 if (verbose)
4474 printf("Defined tag \"%s\", type %d, num_values %d\n",
4475 tag[n_var].name, tag[n_var].type, tag[n_var].n_data);
4476
4477 size += varkey.total_size;
4478 n_var++;
4479 }
4480 }
4481
4482 /* hot-link whole subtree */
4483 if (histkey.type == TID_LINK) {
4484 db_close_record(hDB, hHistKey); // close previously opened record
4485 db_open_record(hDB, hHistKey, NULL, size, MODE_READ, log_system_history, (void *) (POINTER_T) index);
4486 }
4487
4488 status = add_event(&index, now, max_event_id, hist_name, hHistKey, n_var, tag, 0, 0);
4489 if (status != DB_SUCCESS)
4490 return status;
4491
4492 free(tag);
4493 tag = NULL;
4494
4495 max_event_id++;
4496 }
4497 }
4498 }
4499
4500 /*---- define run start/stop event ------------------------------*/
4501
4502 tag = (TAG *) calloc(sizeof(TAG), 2);
4503
4504 assert(tag != NULL);
4505
4506 strcpy(tag[0].name, "State");
4507 tag[0].type = TID_UINT32;
4508 tag[0].n_data = 1;
4509
4510 strcpy(tag[1].name, "Run number");
4511 tag[1].type = TID_UINT32;
4512 tag[1].n_data = 1;
4513
4514 const char* event_name = "Run transitions";
4515
4516 for (unsigned i=0; i<mh.size(); i++) {
4517 status = mh[i]->hs_define_event(event_name, now, 2, tag);
4518 if (status != HS_SUCCESS) {
4519 cm_msg(MERROR, "add_event", "Cannot define event \"%s\", hs_define_event() status %d", event_name, status);
4520 return 0;
4521 }
4522 }
4523
4524 history_events.push_back(event_name);
4525
4526 free(tag);
4527 tag = NULL;
4528
4529 /* outcommented not to produce a log entry on every run
4530 cm_msg(MINFO, "open_history", "Configured history with %d events", count_events);
4531 */
4532
4534 if (status != HS_SUCCESS)
4535 return status;
4536
4537 double tend = ss_time_sec();
4538 double telapsed = tend - tstart;
4539 if (telapsed > 10.0) {
4540 cm_msg(MERROR, "open_history", "open_history() took %.3f seconds", telapsed);
4541 }
4542
4543 return CM_SUCCESS;
4544}
char type[NAME_LENGTH]
history channel name
Definition history.h:112
char name[NAME_LENGTH]
Definition history.h:111
#define DB_NO_KEY
Definition midas.h:643
#define TID_LINK
Definition midas.h:350
INT db_get_data_index(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT idx, DWORD type)
Definition odb.cxx:6917
INT db_enum_link(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition odb.cxx:5495
#define HS_GET_WRITER
Definition history.h:36
int hs_save_event_list(const std::vector< std::string > *pevents)
int hs_get_history(HNDLE hDB, HNDLE hKey, int flags, int debug_flag, MidasHistoryInterface **mh)
void log_system_history(HNDLE hDB, HNDLE hKey, void *info)
Definition mlogger.cxx:4658
static int add_event(int *indexp, time_t timestamp, int event_id, const char *event_name, HNDLE hKey, int ntags, const TAG *tags, time_t min_period, int hotlink)
Definition mlogger.cxx:3784
INT num_values
Definition midas.h:1029
Definition midas.h:1233
DWORD type
Definition midas.h:1235
DWORD n_data
Definition midas.h:1236
char name[NAME_LENGTH]
Definition midas.h:1234
Here is the call graph for this function:
Here is the caller graph for this function:

◆ receive_event()

void receive_event ( HNDLE  hBuf,
HNDLE  request_id,
EVENT_HEADER pheader,
void *  pevent 
)

Definition at line 5429 of file mlogger.cxx.

5430{
5431 if (verbose)
5432 printf("write data event: req %d, evid %d, timestamp %d, size %d\n", request_id, pheader->event_id, pheader->time_stamp, pheader->data_size);
5433
5434 /* find logging channel for this request id */
5435 for (unsigned i = 0; i < log_channels.size(); i++) {
5436 LOG_CHN* chn = log_channels[i];
5437 if (chn->handle == 0 && chn->ftp_con == NULL)
5438 continue;
5439
5440 /* write normal events */
5441 if (chn->request_id == request_id) {
5442 log_write(chn, pheader);
5443 break;
5444 }
5445
5446 /* write messages */
5447 if (chn->msg_request_id == request_id) {
5448 log_write(chn, pheader);
5449 break;
5450 }
5451 }
5452}
short int event_id
Definition midas.h:853
DWORD data_size
Definition midas.h:857
DWORD time_stamp
Definition midas.h:856
INT request_id
Definition mlogger.cxx:256
Here is the call graph for this function:
Here is the caller graph for this function:

◆ select_checksum_module()

int select_checksum_module ( HNDLE  hDB,
HNDLE  hSet,
const char *  name 
)

Definition at line 3196 of file mlogger.cxx.

3197{
3198 std::string val = get_value(hDB, hSet, name);
3199 std::string sel;
3200 std::string def;
3201 int s = 0;
3202 s = check_add(s, CHECKSUM_NONE, val, "NONE", false, &def, &sel);
3203 s = check_add(s, CHECKSUM_CRC32C, val, "CRC32C", true, &def, &sel);
3204 s = check_add(s, CHECKSUM_SHA256, val, "SHA256", false, &def, &sel);
3205 s = check_add(s, CHECKSUM_SHA512, val, "SHA512", false, &def, &sel);
3206 s = check_add(s, CHECKSUM_ZLIB, val, "ZLIB", false, &def, &sel);
3207 if (sel == "")
3208 sel = "NONE";
3209 //set_value(hDB, hSet, name, sel, def);
3210 return s;
3211}
std::string get_value(HNDLE hDB, HNDLE hDir, const char *name)
Definition mlogger.cxx:3164
int check_add(int v, int n, const std::string &val, const char *str, bool bdef, std::string *def, std::string *sel)
Definition mlogger.cxx:3184
HNDLE hSet
Definition msysmon.cxx:531
Here is the call graph for this function:
Here is the caller graph for this function:

◆ select_compression_module()

int select_compression_module ( HNDLE  hDB,
HNDLE  hSet,
const char *  name 
)

Definition at line 3213 of file mlogger.cxx.

3214{
3215 std::string val = get_value(hDB, hSet, name);
3216 std::string sel;
3217 std::string def;
3218 int s = 0;
3219 s = check_add(s, COMPRESS_NONE, val, "none", false, &def, &sel);
3220 s = check_add(s, COMPRESS_ZLIB, val, "gzip", true, &def, &sel);
3221 s = check_add(s, COMPRESS_LZ4, val, "lz4", false, &def, &sel);
3222 s = check_add(s, COMPRESS_BZIP2, val, "bzip2", false, &def, &sel);
3223 s = check_add(s, COMPRESS_PBZIP2, val, "pbzip2", false, &def, &sel);
3224 if (sel == "")
3225 sel = "none";
3226 //set_value(hDB, hSet, name, sel, def);
3227 return s;
3228}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ select_output_module()

int select_output_module ( HNDLE  hDB,
HNDLE  hSet,
const char *  name 
)

Definition at line 3230 of file mlogger.cxx.

3231{
3232 std::string val = get_value(hDB, hSet, name);
3233 std::string sel;
3234 std::string def;
3235 int s = 0;
3236 s = check_add(s, OUTPUT_NULL, val, "NULL", false, &def, &sel);
3237 s = check_add(s, OUTPUT_FILE, val, "FILE", true, &def, &sel);
3238 s = check_add(s, OUTPUT_FTP, val, "FTP", false, &def, &sel);
3239 s = check_add(s, OUTPUT_PIPE, val, "PIPE", false, &def, &sel);
3240 if (sel == "")
3241 sel = "FILE";
3242 //set_value(hDB, hSet, name, sel, def);
3243 return s;
3244}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_value()

void set_value ( HNDLE  hDB,
HNDLE  hDir,
const char *  name,
const std::string &  set,
const std::string &  def 
)

Definition at line 3175 of file mlogger.cxx.

3176{
3177 std::string s = set + " (one of:" + def + ")";
3178 int size = 256; // MUST match record definition // strlen(value);
3179 s.reserve(size);
3180 const char* value = s.c_str();
3181 db_set_value(hDB, hDir, name, value, size, 1, TID_STRING);
3182}
#define set(var, value)
Here is the call graph for this function:

◆ start_image_history()

void start_image_history ( )
extern

Definition at line 315 of file history_image.cxx.

315{}
Here is the caller graph for this function:

◆ start_the_run()

int start_the_run ( )

Definition at line 3539 of file mlogger.cxx.

3540{
3541 int status, size, state, run_number, flag;
3542 char errstr[256];
3543
3545 auto_restart = 0;
3546
3547 /* check if autorestart is still on */
3548 size = sizeof(BOOL);
3549 flag = FALSE;
3550 db_get_value(hDB, 0, "/Logger/Auto restart", &flag, &size, TID_BOOL, TRUE);
3551
3552 if (!flag) {
3553 cm_msg(MINFO, "start_the_run", "Run auto restart canceled");
3554 return SUCCESS;
3555 }
3556
3557 /* check if really stopped */
3558 size = sizeof(state);
3559 status = db_get_value(hDB, 0, "Runinfo/State", &state, &size, TID_INT32, TRUE);
3560 if (status != DB_SUCCESS) {
3561 cm_msg(MERROR, "start_the_run", "cannot get Runinfo/State in database, db_get_value() status %d", status);
3562 return status;
3563 }
3564
3565 static int backoff = 1;
3566
3567 if (state != STATE_STOPPED) {
3568 cm_msg(MINFO, "start_the_run", "Runinfo/State %d is not STATE_STOPPED, will try again in %d seconds", state, backoff);
3569 auto_restart = ss_time() + backoff; /* try again later */
3570 if (backoff < 1)
3571 backoff = 1;
3572 else if (backoff > 1*60)
3573 backoff = 1*60;
3574 else
3575 backoff *= 2;
3576 return SUCCESS;
3577 }
3578
3579 backoff = 1;
3580
3581 size = sizeof(run_number);
3582 status = db_get_value(hDB, 0, "/Runinfo/Run number", &run_number, &size, TID_INT32, TRUE);
3583 assert(status == SUCCESS);
3584
3585 if (run_number <= 0) {
3586 cm_msg(MERROR, "start_the_run", "aborting on attempt to use invalid run number %d", run_number);
3587 abort();
3588 }
3589
3590 int trans_flag = get_trans_flag();
3591
3592 cm_msg(MTALK, "start_the_run", "starting new run");
3593 status = cm_transition(TR_START, run_number + 1, errstr, sizeof(errstr), trans_flag, verbose);
3594 if (status != CM_SUCCESS)
3595 cm_msg(MERROR, "start_the_run", "cannot restart run: cm_transition() status %d, error: %s", status, errstr);
3596
3597 return status;
3598}
INT cm_transition(INT transition, INT run_number, char *errstr, INT errstr_size, INT async_flag, INT debug_flag)
Definition midas.cxx:5304
static int get_trans_flag()
Definition mlogger.cxx:3465
BOOL start_requested
Definition mlogger.cxx:291
Here is the call graph for this function:
Here is the caller graph for this function:

◆ stop_image_history()

void stop_image_history ( )
extern

Definition at line 316 of file history_image.cxx.

316{}
Here is the caller graph for this function:

◆ stop_the_run()

int stop_the_run ( int  restart)

Definition at line 3505 of file mlogger.cxx.

3506{
3507 int status, flag, size;
3508 char errstr[256];
3509
3510 if (restart) {
3511 size = sizeof(BOOL);
3512 flag = FALSE;
3513 db_get_value(hDB, 0, "/Logger/Auto restart", &flag, &size, TID_BOOL, TRUE);
3514
3515 if (flag) {
3517 auto_restart = 0;
3518 }
3519 }
3520
3522 stop_try_later = 0;
3523
3524 int trans_flag = get_trans_flag();
3525
3526 status = cm_transition(TR_STOP, 0, errstr, sizeof(errstr), trans_flag, verbose);
3528 cm_msg(MERROR, "stop_the_run", "another transition is in progress, will try again later");
3530 stop_try_later = ss_time_sec() + 10.0;
3531 } else if (status != CM_SUCCESS) {
3532 cm_msg(MERROR, "stop_the_run", "cannot stop the run, cm_transition() status %d, error: %s", status, errstr);
3533 return status;
3534 }
3535
3536 return status;
3537}
#define CM_TRANSITION_IN_PROGRESS
Definition midas.h:592
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TimeToString()

static std::string TimeToString ( time_t  t)
static

Definition at line 53 of file mlogger.cxx.

54{
55 const char* sign = "";
56
57 if (t == 0)
58 return "0";
59
60 time_t tt = t;
61
62 if (t < 0) {
63 sign = "-";
64 tt = -t;
65 }
66
67 assert(tt > 0);
68
69 std::string v;
70 while (tt) {
71 char c = '0' + tt%10;
72 tt /= 10;
73 v = c + v;
74 }
75
76 v = sign + v;
77
78 //printf("time %.0f -> %s\n", (double)t, v.c_str());
79
80 return v;
81}
char c
Definition system.cxx:1312
Here is the caller graph for this function:

◆ tr_pause()

INT tr_pause ( INT  run_number,
char *  error 
)

Definition at line 5403 of file mlogger.cxx.

5404{
5405 /* write transition event into history */
5407
5409
5411
5412 return CM_SUCCESS;
5413}
#define STATE_PAUSED
Definition midas.h:306
INT cm_msg_flush_buffer()
Definition midas.cxx:881
static int write_history(DWORD transition, DWORD run_number)
Definition mlogger.cxx:4940
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tr_resume()

INT tr_resume ( INT  run_number,
char *  error 
)

Definition at line 5415 of file mlogger.cxx.

5416{
5417 /* write transition event into history */
5419
5421
5423
5424 return CM_SUCCESS;
5425}
#define STATE_RUNNING
Definition midas.h:307
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tr_start()

INT tr_start ( INT  run_number,
char *  error 
)

Definition at line 4974 of file mlogger.cxx.

4987{
4988 INT size, status;
4989 HNDLE hKeyRoot, hKeyChannel;
4990 CHN_SETTINGS *chn_settings;
4991 KEY key;
4992 BOOL write_data, tape_flag = FALSE;
4993 HNDLE hDB;
4994
4995 if (verbose)
4996 printf("tr_start: run %d\n", run_number);
4997
4998 assert(error != NULL);
4999
5000 DWORD t0 = ss_millitime();
5001
5003
5004 /* save current ODB */
5005 std::string str = "last.json";
5006 db_get_value_string(hDB, 0, "/Logger/ODB Last Dump File", 0, &str, TRUE);
5007 odb_save(str.c_str(), false);
5008
5009 DWORD t1 = ss_millitime();
5010
5012
5014 close_buffers();
5015
5016 DWORD t2 = ss_millitime();
5017
5019
5021
5022 /* read global logging flag */
5023 size = sizeof(BOOL);
5024 write_data = TRUE;
5025 db_get_value(hDB, 0, "/Logger/Write data", &write_data, &size, TID_BOOL, TRUE);
5026
5027 /* read tape message flag */
5028 size = sizeof(tape_message);
5029 db_get_value(hDB, 0, "/Logger/Tape message", &tape_message, &size, TID_BOOL, TRUE);
5030
5031 /* reset next subrun flag */
5032 status = FALSE;
5033 db_set_value(hDB, 0, "/Logger/Next subrun", &status, sizeof(status), 1, TID_BOOL);
5034
5035 /* loop over all channels */
5036 status = db_find_key(hDB, 0, "/Logger/Channels", &hKeyRoot);
5037 if (status != DB_SUCCESS) {
5038 /* if no channels are defined, define at least one */
5039 status = db_create_record(hDB, 0, "/Logger/Channels/0/", strcomb1(chn_tree_str).c_str());
5040 if (status != DB_SUCCESS) {
5041 strcpy(error, "Cannot create channel entry in database");
5042 cm_msg(MERROR, "tr_start", "%s", error);
5043 return 0;
5044 }
5045
5046 status = db_find_key(hDB, 0, "/Logger/Channels", &hKeyRoot);
5047 if (status != DB_SUCCESS) {
5048 strcpy(error, "Cannot create channel entry in database");
5049 cm_msg(MERROR, "tr_start", "%s", error);
5050 return 0;
5051 }
5052 }
5053
5054 // after close_buffers() all log channels are closed and deleted
5055 assert(log_channels.size() == 0);
5056
5057 for (unsigned index = 0; ; index++) {
5058 status = db_enum_key(hDB, hKeyRoot, index, &hKeyChannel);
5060 break;
5061
5062 /* correct channel record */
5063 db_get_key(hDB, hKeyChannel, &key);
5064 status = db_check_record(hDB, hKeyRoot, key.name, strcomb1(chn_tree_str).c_str(), TRUE);
5065 if (status != DB_SUCCESS && status != DB_OPEN_RECORD) {
5066 cm_msg(MERROR, "tr_start", "Cannot create/check channel record, status %d", status);
5067 break;
5068 }
5069
5070 if (status == DB_SUCCESS || status == DB_OPEN_RECORD) {
5071 LOG_CHN* chn = new_LOG_CHN(key.name);
5072
5073 log_channels.push_back(chn);
5074
5075 /* save settings key */
5076 status = db_find_key(hDB, hKeyChannel, "Settings", &chn->settings_hkey);
5077 if (status != DB_SUCCESS) {
5078 strcpy(error, "Cannot find channel settings info");
5079 cm_msg(MERROR, "tr_start", "%s", error);
5080 return 0;
5081 }
5082
5083 /* save statistics key */
5084 status = db_find_key(hDB, hKeyChannel, "Statistics", &chn->stats_hkey);
5085 if (status != DB_SUCCESS) {
5086 strcpy(error, "Cannot find channel statistics info");
5087 cm_msg(MERROR, "tr_start", "%s", error);
5088 return 0;
5089 }
5090
5091 /* clear statistics */
5092 size = sizeof(CHN_STATISTICS);
5093 db_get_record1(hDB, chn->stats_hkey, &chn->statistics, &size, 0, strcomb1(chn_statistics_str).c_str());
5094
5095 chn->statistics.events_written = 0;
5096 chn->statistics.bytes_written = 0;
5099
5100 db_set_record(hDB, chn->stats_hkey, &chn->statistics, size, 0);
5101
5102 /* get channel info structure */
5103 chn_settings = &chn->settings;
5104 size = sizeof(CHN_SETTINGS);
5105 status = db_get_record1(hDB, chn->settings_hkey, chn_settings, &size, 0, strcomb1(chn_settings_str).c_str());
5106 if (status != DB_SUCCESS) {
5107 strcpy(error, "Cannot read channel info");
5108 cm_msg(MERROR, "tr_start", "%s", error);
5109 return 0;
5110 }
5111
5112 chn->pre_checksum_module = select_checksum_module(hDB, chn->settings_hkey, "data checksum");
5113 chn->post_checksum_module = select_checksum_module(hDB, chn->settings_hkey, "file checksum");
5115 chn->output_module = select_output_module(hDB, chn->settings_hkey, "output");
5116
5117 //printf("channel settings pre [%d] compress [%d] post [%d] output [%d]\n", chn->pre_checksum_module, chn->compression_module, chn->post_checksum_module, chn->output_module);
5118
5119 /* check if active */
5120 if (!chn_settings->active || !write_data)
5121 continue;
5122
5123 /* initialize subrun number */
5124 chn->subrun_number = 0;
5125
5126 log_create_writer(chn);
5128
5129 /* open logging channel */
5130 status = log_open(chn, run_number);
5131
5132 /* return if logging channel couldn't be opened */
5133 if (status != SS_SUCCESS) {
5134 if (status == SS_FILE_ERROR)
5135 sprintf(error, "Cannot open file \'%s\' (See messages)", chn->path.c_str());
5136 if (status == SS_FILE_EXISTS)
5137 sprintf(error, "File \'%s\' exists already, run start aborted", chn->path.c_str());
5138 if (status == SS_NO_TAPE)
5139 sprintf(error, "No tape in device \'%s\'", chn->path.c_str());
5140 if (status == SS_TAPE_ERROR)
5141 sprintf(error, "Tape error, cannot start run");
5142 if (status == SS_DEV_BUSY)
5143 sprintf(error, "Device \'%s\' used by someone else", chn->path.c_str());
5145 sprintf(error, "Cannot open FTP channel to \'%s\'", chn->path.c_str());
5146 if (status == SS_NO_ROOT)
5147 sprintf(error, "No ROOT support compiled into mlogger, please compile with -DHAVE_ROOT flag");
5148
5150 sprintf(error, "Invalid data format, please use \"MIDAS\", \"ASCII\", \"DUMP\" or \"ROOT\"");
5151
5152 cm_msg(MERROR, "tr_start", "%s", error);
5153 return 0;
5154 }
5155
5156 /* close records if open from previous run start with abort */
5157 if (chn->stats_hkey)
5159 if (chn->settings_hkey)
5161
5162 /* open hot link to statistics tree */
5163 status = db_open_record1(hDB, chn->stats_hkey, &chn->statistics, sizeof(CHN_STATISTICS), MODE_WRITE, NULL, NULL, strcomb1(chn_statistics_str).c_str());
5164 if (status == DB_NO_ACCESS) {
5165 /* record is probably still in exclusive access by dead logger, so reset it */
5167 if (status != DB_SUCCESS)
5168 cm_msg(MERROR, "tr_start", "Cannot change access mode for statistics record, error %d", status);
5169 else
5170 cm_msg(MINFO, "tr_start", "Recovered access mode for statistics record of channel \"%s\"", chn->name.c_str());
5171 status = db_open_record1(hDB, chn->stats_hkey, &chn->statistics, sizeof(CHN_STATISTICS), MODE_WRITE, NULL, NULL, strcomb1(chn_statistics_str).c_str());
5172 }
5173
5174 if (status != DB_SUCCESS)
5175 cm_msg(MERROR, "tr_start", "Cannot open statistics record for channel \"%s\", error %d", chn->name.c_str(), status);
5176
5177 /* open hot link to settings tree */
5179 if (status != DB_SUCCESS)
5180 cm_msg(MERROR, "tr_start", "db_watch() status %d, cannot open channel settings record, probably other logger is using it", status);
5181
5182#ifndef FAL_MAIN
5183 /* open buffer */
5185 if (status != BM_SUCCESS && status != BM_CREATED) {
5186 sprintf(error, "Cannot open buffer %s", chn_settings->buffer);
5187 cm_msg(MERROR, "tr_start", "%s", error);
5188 return 0;
5189 }
5190 bm_set_cache_size(chn->buffer_handle, 1000000, 0);
5191
5192 /* place event request */
5193 status = bm_request_event(chn->buffer_handle, (short) chn_settings->event_id, (short) chn_settings->trigger_mask, GET_ALL, &chn->request_id, receive_event);
5194
5195 if (status != BM_SUCCESS) {
5196 sprintf(error, "Cannot place event request");
5197 cm_msg(MERROR, "tr_start", "%s", error);
5198 return 0;
5199 }
5200
5201 /* open message buffer if requested */
5202 if (chn_settings->log_messages) {
5204 if (status != BM_SUCCESS && status != BM_CREATED) {
5205 sprintf(error, "Cannot open buffer %s", MESSAGE_BUFFER_NAME);
5206 cm_msg(MERROR, "tr_start", "%s", error);
5207 return 0;
5208 }
5209
5210 /* place event request */
5212
5213 if (status != BM_SUCCESS) {
5214 sprintf(error, "Cannot place event request");
5215 cm_msg(MERROR, "tr_start", "%s", error);
5216 return 0;
5217 }
5218 }
5219#endif
5220 }
5221 }
5222
5223 DWORD t3 = ss_millitime();
5224
5225 if (tape_flag && tape_message)
5226 cm_msg(MTALK, "tr_start", "tape mounting finished");
5227
5228 /* write transition event into history */
5230
5231 DWORD t4 = ss_millitime();
5232
5233#ifdef HAVE_MYSQL
5234 /* write to SQL database if requested */
5235 write_runlog_sql(TRUE);
5236#endif
5237
5238 /* write to runlog file(s) if requested */
5241
5242 DWORD t5 = ss_millitime();
5243 DWORD te = t5;
5244
5245 if (verbose)
5246 printf("tr_start: run %d started in %d ms: odb dump %d ms, close channels %d ms, configure channels %d ms, configure history %d ms, write runlog %d ms\n",
5247 run_number,
5248 te-t0,
5249 t1-t0,
5250 t2-t1,
5251 t3-t2,
5252 t4-t3,
5253 t5-t4
5254 );
5255
5258
5260
5261 return CM_SUCCESS;
5262}
#define FTP_RESPONSE_ERROR
Definition ftplib.cxx:22
#define FTP_NET_ERROR
Definition ftplib.cxx:20
INT bm_open_buffer(const char *buffer_name, INT buffer_size, INT *buffer_handle)
Definition midas.cxx:6728
INT bm_request_event(HNDLE buffer_handle, short int event_id, short int trigger_mask, INT sampling_type, HNDLE *request_id, EVENT_HANDLER *func)
Definition midas.cxx:8476
INT bm_set_cache_size(INT buffer_handle, size_t read_size, size_t write_size)
Definition midas.cxx:8151
#define BM_SUCCESS
Definition midas.h:605
#define BM_CREATED
Definition midas.h:606
#define DB_NO_ACCESS
Definition midas.h:649
#define SS_TAPE_ERROR
Definition midas.h:683
#define SS_FILE_EXISTS
Definition midas.h:687
#define SS_NO_TAPE
Definition midas.h:680
#define SS_DEV_BUSY
Definition midas.h:681
#define SS_NO_ROOT
Definition midas.h:690
#define GET_ALL
Definition midas.h:321
#define MODE_DELETE
Definition midas.h:372
#define MODE_WRITE
Definition midas.h:371
#define MESSAGE_BUFFER_NAME
Definition msystem.h:111
#define MESSAGE_BUFFER_SIZE
Definition msystem.h:110
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_set_mode(HNDLE hDB, HNDLE hKey, WORD mode, BOOL recurse)
Definition odb.cxx:8040
INT db_watch(HNDLE hDB, HNDLE hKey, void(*dispatcher)(INT, INT, INT, void *), void *info)
Definition odb.cxx:13845
INT db_open_record1(HNDLE hDB, HNDLE hKey, void *ptr, INT rec_size, WORD access_mode, void(*dispatcher)(INT, INT, void *), void *info, const char *rec_str)
Definition odb.cxx:13473
#define DEFAULT_BUFFER_SIZE
Definition midas.h:255
#define EVENTID_MESSAGE
Definition midas.h:903
int select_compression_module(HNDLE hDB, HNDLE hSet, const char *name)
Definition mlogger.cxx:3213
void receive_event(HNDLE hBuf, HNDLE request_id, EVENT_HEADER *pheader, void *pevent)
Definition mlogger.cxx:5429
int select_checksum_module(HNDLE hDB, HNDLE hSet, const char *name)
Definition mlogger.cxx:3196
void odb_save(const char *filename, bool make_file_readonly)
Definition mlogger.cxx:1774
BOOL tape_message
Definition mlogger.cxx:288
int select_output_module(HNDLE hDB, HNDLE hSet, const char *name)
Definition mlogger.cxx:3230
static void watch_settings(HNDLE hDB, HNDLE hKey, HNDLE index, void *info)
Definition mlogger.cxx:4956
LOG_CHN * new_LOG_CHN(const char *name)
Definition mlogger.cxx:274
int close_buffers()
Definition mlogger.cxx:4912
void write_runlog_json(BOOL bor)
Definition mlogger.cxx:2672
void write_runlog_ascii(BOOL bor)
Definition mlogger.cxx:2511
int close_channels(int run_number, BOOL *p_tape_flag)
Definition mlogger.cxx:4867
DWORD log_messages
Definition mlogger.cxx:164
char buffer[32]
Definition mlogger.cxx:165
INT msg_buffer_handle
Definition mlogger.cxx:255
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tr_start_abort()

INT tr_start_abort ( INT  run_number,
char *  error 
)

Definition at line 5266 of file mlogger.cxx.

5267{
5268 if (verbose)
5269 printf("tr_start_abort: run %d\n", run_number);
5270
5272
5273 for (unsigned i = 0; i < log_channels.size(); i++) {
5274 LOG_CHN* chn = log_channels[i];
5275 if (chn->handle && chn->type == LOG_TYPE_DISK) {
5276 cm_msg(MINFO, "tr_start_abort", "Deleting previous file \"%s\"", chn->path.c_str());
5277 unlink(chn->path.c_str());
5278 }
5279 }
5280
5282 close_buffers();
5283
5285
5287
5289
5290 return CM_SUCCESS;
5291}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tr_stop()

INT tr_stop ( INT  run_number,
char *  error 
)

Definition at line 5295 of file mlogger.cxx.

5303{
5304 INT size;
5305 BOOL flag, tape_flag = FALSE;
5306 char filename[256];
5307 char str[256];
5308
5309 if (verbose)
5310 printf("tr_stop: run %d\n", run_number);
5311
5313 return CM_SUCCESS;
5314
5315 DWORD t0 = ss_millitime();
5316
5318
5319 close_channels(run_number, &tape_flag);
5320 close_buffers();
5321
5322 DWORD t1 = ss_millitime();
5323
5324 /* ODB dump if requested */
5325 size = sizeof(flag);
5326 flag = 0;
5327 db_get_value(hDB, 0, "/Logger/ODB Dump", &flag, &size, TID_BOOL, TRUE);
5328 if (flag) {
5329 strcpy(str, "run%d.json");
5330 size = sizeof(str);
5331 str[0] = 0;
5332 db_get_value(hDB, 0, "/Logger/ODB Dump File", str, &size, TID_STRING, TRUE);
5333 if (str[0] == 0)
5334 strcpy(str, "run%d.json");
5335
5336 /* substitue "%d" by current run number */
5337 if (strchr(str, '%'))
5338 sprintf(filename, str, run_number);
5339 else
5340 strcpy(filename, str);
5341
5342 odb_save(filename, true);
5343 }
5344
5345 DWORD t2 = ss_millitime();
5346
5347#ifdef HAVE_MYSQL
5348 /* write to SQL database if requested */
5349 write_runlog_sql(FALSE);
5350#endif
5351
5352 /* write to ASCII file(s) if requested */
5355
5356 DWORD t3 = ss_millitime();
5357
5359
5360 if (tape_flag & tape_message)
5361 cm_msg(MTALK, "tr_stop", "all tape channels closed");
5362
5363 /* write transition event into history */
5365
5366 DWORD t4 = ss_millitime();
5367
5368 /* clear flag */
5370 stop_try_later = 0;
5371
5372 if (start_requested) {
5373 int delay = 0;
5374 size = sizeof(delay);
5375 db_get_value(hDB, 0, "/Logger/Auto restart delay", &delay, &size, TID_INT32, TRUE);
5376 auto_restart = ss_time() + delay; /* start after specified delay */
5378 }
5379
5380 DWORD te = t4;
5381
5382 if (verbose)
5383 printf("tr_stop: run %d stopped in %d ms: close channels %d ms, odb dump %d ms, write run log %d ms, write history %d ms\n",
5384 run_number,
5385 te-t0,
5386 t1-t0,
5387 t2-t1,
5388 t3-t2,
5389 t4-t3);
5390
5391
5393
5395
5396 return CM_SUCCESS;
5397}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ watch_settings()

static void watch_settings ( HNDLE  hDB,
HNDLE  hKey,
HNDLE  index,
void *  info 
)
static

Definition at line 4956 of file mlogger.cxx.

4957{
4958 int status;
4959 assert(info != NULL);
4960 LOG_CHN *log_chn = (LOG_CHN*)info;
4961 int size = sizeof(CHN_SETTINGS);
4962 status = db_get_record1(hDB, log_chn->settings_hkey, &log_chn->settings, &size, 0, strcomb1(chn_settings_str).c_str());
4963 if (status != DB_SUCCESS) {
4964 cm_msg(MINFO, "watch_settings", "db_get_record(%s) status %d", log_chn->name.c_str(), status);
4965 return;
4966 }
4967
4968 if (verbose)
4969 printf("Channel %s settings updated\n", log_chn->name.c_str());
4970}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_history()

static int write_history ( DWORD  transition,
DWORD  run_number 
)
static

Definition at line 4940 of file mlogger.cxx.

4941{
4942 DWORD eb[2];
4943 eb[0] = transition;
4944 eb[1] = run_number;
4945
4946 time_t now = time(NULL);
4947
4948 for (unsigned h=0; h<mh.size(); h++)
4949 mh[h]->hs_write_event("Run transitions", now, sizeof(eb), (const char*)eb);
4950
4951 return SUCCESS;
4952}
INT transition(INT run_number, char *error)
Definition consume.cxx:35
Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_runlog_ascii()

void write_runlog_ascii ( BOOL  bor)

Definition at line 2511 of file mlogger.cxx.

2512{
2513 char filename[256], dir[256], path[256];
2514 int status, size, write_flag;
2515 HNDLE hKey, hKeyRoot;
2516
2517 /* do not update runlog if logger does not write data */
2518 size = sizeof(BOOL);
2519 write_flag = FALSE;
2520 db_get_value(hDB, 0, "/Logger/Write data", &write_flag, &size, TID_BOOL, TRUE);
2521 if (!write_flag)
2522 return;
2523
2524 /* get BOR or EOR list */
2525 if (bor) {
2526 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links BOR", &hKeyRoot);
2527 if (!hKeyRoot) {
2528 cm_msg(MERROR, "write_runlog_ascii", "Cannot find \"/Logger/Runlog/ASCII/Links BOR");
2529 return;
2530 }
2531 } else {
2532 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links EOR", &hKeyRoot);
2533 if (!hKeyRoot) {
2534 cm_msg(MERROR, "write_runlog_ascii", "Cannot find \"/Logger/Runlog/ASCII/Links EOR");
2535 return;
2536 }
2537 }
2538
2539 size = sizeof(write_flag);
2540 write_flag = 0;
2541 db_get_value(hDB, 0, "/Logger/Runlog/ASCII/Write data", &write_flag, &size, TID_BOOL, TRUE);
2542
2543 size = sizeof(filename);
2544 strcpy(filename, "runlog.log");
2545 db_get_value(hDB, 0, "/Logger/Runlog/ASCII/Filename", filename, &size, TID_STRING, TRUE);
2546
2547 if (strchr(filename, DIR_SEPARATOR) == NULL) {
2548 size = sizeof(dir);
2549 dir[0] = 0;
2550 db_get_value(hDB, 0, "/Logger/Message Dir", dir, &size, TID_STRING, TRUE);
2551 if (dir[0] != 0)
2552 if (dir[strlen(dir) - 1] != DIR_SEPARATOR)
2553 strcat(dir, DIR_SEPARATOR_STR);
2554 strcpy(path, dir);
2555 strcat(path, filename);
2556 } else
2557 strcpy(path, filename);
2558
2559 /* continue only if data should be written */
2560 if (!write_flag)
2561 return;
2562
2563 FILE *f = fopen(path, "r");
2564 if (f == NULL) {
2565 // create new file
2566 f = fopen(path, "wt");
2567
2568 assert(f != NULL);
2569
2570 // write column header line with variable names
2571 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links BOR", &hKeyRoot);
2572 for (int i = 0;; i++) {
2573 status = db_enum_key(hDB, hKeyRoot, i, &hKey);
2575 break;
2576 KEY key;
2577 db_get_key(hDB, hKey, &key);
2578 fprintf(f, "%s\t", key.name);
2579 }
2580 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links EOR", &hKeyRoot);
2581 for (int i = 0;; i++) {
2582 status = db_enum_key(hDB, hKeyRoot, i, &hKey);
2584 break;
2585 KEY key;
2586 db_get_key(hDB, hKey, &key);
2587 fprintf(f, "%s\t", key.name);
2588 }
2589 fprintf(f, "\n");
2590 fclose(f);
2591 }
2592
2593 // append data to logfile
2594 f = fopen(path, "at");
2595
2596 assert(f != NULL);
2597
2598 if (bor)
2599 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links BOR", &hKeyRoot);
2600 else
2601 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links EOR", &hKeyRoot);
2602
2603 for (int i = 0;; i++) {
2604 status = db_enum_key(hDB, hKeyRoot, i, &hKey);
2606 break;
2607 KEY key;
2608 db_get_key(hDB, hKey, &key);
2609 int size = key.total_size;
2610 char* data = (char*)malloc(size);
2611 assert(data);
2612 db_get_data(hDB, hKey, data, &size, key.type);
2613 std::string str = db_sprintf(data, size, 0, key.type);
2614 //printf("BBB key %s size %d %d [%s]\n", key.name, size, (int)strlen(str), str);
2615 free(data);
2616 fprintf(f, "%s\t", str.c_str());
2617 }
2618 if (!bor)
2619 fprintf(f, "\n");
2620 fclose(f);
2621}
INT db_sprintf(char *string, const void *data, INT data_size, INT idx, DWORD type)
Definition odb.cxx:10865
void * data
Definition mana.cxx:268
INT bor(INT run_number, char *error)
Definition mana.cxx:1675
Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_runlog_json()

void write_runlog_json ( BOOL  bor)

Definition at line 2672 of file mlogger.cxx.

2672 {
2673 char filename[256], messagedir[256], datadir[256], dirname[256], path[256];
2674 int status, size, write_flag;
2675 int runnumber;
2676 HNDLE hKey;
2677
2678 /* do not update runlog if logger does not write data */
2679 size = sizeof(BOOL);
2680 write_flag = FALSE;
2681 db_get_value(hDB, 0, "/Logger/Write data", &write_flag, &size, TID_BOOL, TRUE);
2682 if (!write_flag)
2683 return;
2684
2685 /* get BOR or EOR list */
2686 if (bor) {
2687 db_find_key(hDB, 0, "/Logger/Runlog/JSON/Links BOR", &hKey);
2688 if (!hKey) {
2689 cm_msg(MERROR, "write_runlog_json", "Cannot find \"/Logger/Runlog/JSON/Links BOR");
2690 return;
2691 }
2692 } else {
2693 db_find_key(hDB, 0, "/Logger/Runlog/JSON/Links EOR", &hKey);
2694 if (!hKey) {
2695 cm_msg(MERROR, "write_runlog_json", "Cannot find \"/Logger/Runlog/JSON/Links EOR");
2696 return;
2697 }
2698 }
2699
2700 size = sizeof(write_flag);
2701 write_flag = 0;
2702 db_get_value(hDB, 0, "/Logger/Runlog/JSON/Write data", &write_flag, &size, TID_BOOL, TRUE);
2703
2704 size = sizeof(datadir);
2705 strcpy(datadir, "");
2706 db_get_value(hDB, 0, "/Logger/Data Dir", datadir, &size, TID_STRING, TRUE);
2707
2708 size = sizeof(messagedir);
2709 strcpy(messagedir, "");
2710 db_get_value(hDB, 0, "/Logger/Message Dir", messagedir, &size, TID_STRING, TRUE);
2711
2712 size = sizeof(dirname);
2713 strcpy(dirname, "runlogs");
2714 db_get_value(hDB, 0, "/Logger/Runlog/JSON/Subdir", dirname, &size, TID_STRING, TRUE);
2715
2716 size = sizeof(runnumber);
2717 db_get_value(hDB, 0, "/Runinfo/Run number", &runnumber, &size, TID_INT32, FALSE);
2718
2719 snprintf(filename, 256, "runlog_%06i.json", runnumber);
2720
2721 // use /Logger/Message dir, and if empty use /Logger/Data dir
2722 mstrlcpy(path, messagedir, sizeof(path));
2723 if (path[0] == 0)
2724 mstrlcpy(path, datadir, sizeof(path));
2725 if (path[strlen(path) - 1] != DIR_SEPARATOR)
2726 mstrlcat(path, DIR_SEPARATOR_STR, sizeof(path));
2727 mstrlcat(path, dirname, sizeof(path));
2728 if (path[strlen(path) - 1] != DIR_SEPARATOR)
2729 mstrlcat(path, DIR_SEPARATOR_STR, sizeof(path));
2730
2731 /* create directory if needed */
2732#ifdef OS_WINNT
2733 status = mkdir(path);
2734#else
2735 status = mkdir(path, 0755);
2736#endif
2737
2738 mstrlcat(path, filename, sizeof(path));
2739
2740 /* continue only if data should be written */
2741 if (!write_flag)
2742 return;
2743
2744 char fileflag[2] = "a";
2745 if (bor)
2746 strcpy(fileflag, "a");
2747
2748 FILE *file = fopen(path, fileflag);
2749 if (file == NULL) {
2750 cm_msg(MERROR, "write_runlog_json", "Cannot open file \"%s\"", path);
2751 return;
2752 }
2753
2754 if (bor)
2755 db_find_key(hDB, 0, "/Logger/Runlog/JSON/Links BOR", &hKey);
2756 else
2757 db_find_key(hDB, 0, "/Logger/Runlog/JSON/Links EOR", &hKey);
2758
2759 int buffer_size = 100000;
2760 char *buffer = (char *)malloc(buffer_size);
2761 int buffer_end = 0;
2762
2763 if (bor)
2764 json_write(&buffer, &buffer_size, &buffer_end, 0, "{\n \"BOR\": ", 0);
2765 else
2766 json_write(&buffer, &buffer_size, &buffer_end, 0, " \"EOR\": ", 0);
2767
2768 if (!rpc_is_remote())
2771 status = json_write_anything(hDB, hKey, &buffer, &buffer_size, &buffer_end, JS_LEVEL_1, 0, flags, 0);
2772 if (!rpc_is_remote())
2774
2775 if (bor)
2776 json_write(&buffer, &buffer_size, &buffer_end, 0, ",\n", 0);
2777 else
2778 json_write(&buffer, &buffer_size, &buffer_end, 0, " \n}\n", 0);
2779
2780 if (status == DB_SUCCESS) {
2781 if (buffer) {
2782 size_t wr = fwrite(buffer, 1, buffer_end, file);
2783 if (wr != (size_t) buffer_end) {
2784 cm_msg(MERROR, "write_runlog_json", "Cannot write to file \"%s\", fwrite() errno %d (%s)", filename, errno, strerror(errno));
2785 free(buffer);
2786 fclose(file);
2787 return;
2788 }
2789 }
2790 }
2791
2792 if (buffer)
2793 free(buffer);
2794
2795 fclose(file);
2796}
int EXPRT json_write_anything(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end, int level, int must_be_subdir, int flags, time_t timestamp)
Definition odb.cxx:10405
void json_write(char **buffer, int *buffer_size, int *buffer_end, int level, const char *s, int quoted)
Definition odb.cxx:9550
static DATABASE * db_lock_database(HNDLE hDB, int *pstatus, const char *caller, bool check_attached=true)
Definition odb.cxx:2508
static void db_unlock_database(DATABASE *pdb, const char *caller)
Definition odb.cxx:2670
bool rpc_is_remote(void)
Definition midas.cxx:12892
#define JSFLAG_RECURSE
Definition midas.h:1728
#define JSFLAG_FOLLOW_LINKS
Definition midas.h:1727
#define JSFLAG_OMIT_LAST_WRITTEN
Definition midas.h:1731
#define JSFLAG_OMIT_NAMES
Definition midas.h:1730
#define JS_LEVEL_1
Definition midas.h:1724
#define JSFLAG_OMIT_OLD
Definition midas.h:1732
Here is the call graph for this function:
Here is the caller graph for this function:

◆ xpathname()

static std::string xpathname ( const char *  xpath,
int  level 
)
static

Definition at line 346 of file mlogger.cxx.

347{
348 std::string path = xpath;
349 while (level > 0) {
350 size_t p = path.rfind(".");
351 //printf("level %d, path [%s], pos %d\n", level, path.c_str(), (int)p);
352 if (p == std::string::npos)
353 break;
354 path = path.substr(0, p);
355 level--;
356 }
357 return path;
358}
Here is the caller graph for this function:

Variable Documentation

◆ auto_restart

DWORD auto_restart = 0

Definition at line 292 of file mlogger.cxx.

◆ hDB

HNDLE hDB
static

Definition at line 312 of file mlogger.cxx.

◆ hist_log

struct hist_log_s* hist_log = NULL
static

Definition at line 310 of file mlogger.cxx.

◆ hist_log_max

int hist_log_max = 0
static

Definition at line 309 of file mlogger.cxx.

◆ hist_log_size

int hist_log_size = 0
static

Definition at line 308 of file mlogger.cxx.

◆ history_events

std::vector<std::string> history_events
static

Definition at line 3782 of file mlogger.cxx.

◆ in_stop_transition

BOOL in_stop_transition = FALSE

Definition at line 287 of file mlogger.cxx.

◆ last_history_flush

time_t last_history_flush = 0

Definition at line 4548 of file mlogger.cxx.

◆ local_state

INT local_state

Definition at line 286 of file mlogger.cxx.

◆ log_channels

std::vector<LOG_CHN*> log_channels

Definition at line 296 of file mlogger.cxx.

◆ mh

std::vector<MidasHistoryInterface*> mh
static

Definition at line 3781 of file mlogger.cxx.

◆ run_start_time

DWORD run_start_time

Definition at line 293 of file mlogger.cxx.

◆ start_requested

BOOL start_requested = FALSE

Definition at line 291 of file mlogger.cxx.

◆ stop_requested

BOOL stop_requested = FALSE

Definition at line 290 of file mlogger.cxx.

◆ stop_try_later

double stop_try_later = 0

Definition at line 294 of file mlogger.cxx.

◆ subrun_start_time

DWORD subrun_start_time

Definition at line 293 of file mlogger.cxx.

◆ tape_message

BOOL tape_message = TRUE

Definition at line 288 of file mlogger.cxx.

◆ verbose

BOOL verbose = FALSE

Definition at line 289 of file mlogger.cxx.