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_ROOT   4
 
#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 3954 of file mlogger.cxx.

◆ CHECKSUM_NONE

#define CHECKSUM_NONE   0

Definition at line 3952 of file mlogger.cxx.

◆ CHECKSUM_SHA256

#define CHECKSUM_SHA256   3

Definition at line 3955 of file mlogger.cxx.

◆ CHECKSUM_SHA512

#define CHECKSUM_SHA512   4

Definition at line 3956 of file mlogger.cxx.

◆ CHECKSUM_ZLIB

#define CHECKSUM_ZLIB   1

Definition at line 3953 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]",\
"",\
TH1X EXPRT * h1_book(const char *name, const char *title, int bins, double min, double max)
Definition rmidas.h:24

Definition at line 202 of file mlogger.cxx.

202 { \
203"Active = BOOL : 1",\
204"Type = STRING : [8] Disk",\
205"Filename = STRING : [256] run%05d.mid",\
206"Format = STRING : [8] MIDAS",\
207"Compression = INT32 : 0",\
208"ODB dump = BOOL : 1",\
209"ODB dump format = STRING : [32] json",\
210"Log messages = UINT32 : 0",\
211"Buffer = STRING : [32] SYSTEM",\
212"Event ID = INT32 : -1",\
213"Trigger mask = INT32 : -1",\
214"Event limit = DOUBLE : 0",\
215"Byte limit = DOUBLE : 0",\
216"Subrun Byte limit = DOUBLE : 0",\
217"Tape capacity = DOUBLE : 0",\
218"Subdir format = STRING : [32]",\
219"Current filename = STRING : [256]",\
220"Data checksum = STRING : [256]",\
221"File checksum = STRING : [256]",\
222"Compress = STRING : [256]",\
223"Output = STRING : [256]",\
224"Gzip compression = UINT32 : 0",\
225"Bzip2 compression = UINT32 : 0",\
226"Pbzip2 num cpu = UINT32 : 0",\
227"Pbzip2 compression = UINT32 : 0",\
228"Pbzip2 options = STRING : [256]",\
229"",\
230NULL}

◆ 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",\
"",\

Definition at line 242 of file mlogger.cxx.

242 {\
243"Events written = DOUBLE : 0",\
244"Bytes written = DOUBLE : 0",\
245"Bytes written uncompressed = DOUBLE : 0",\
246"Bytes written total = DOUBLE : 0",\
247"Bytes written subrun = DOUBLE : 0",\
248"Files written = DOUBLE : 0",\
249"Disk level = DOUBLE : 0",\
250"",\
251NULL}

◆ CHN_TREE_STR

#define CHN_TREE_STR (   _name)

Definition at line 98 of file mlogger.cxx.

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

◆ COMPRESS_BZIP2

#define COMPRESS_BZIP2   3

Definition at line 3979 of file mlogger.cxx.

◆ COMPRESS_LZ4

#define COMPRESS_LZ4   2

Definition at line 3978 of file mlogger.cxx.

◆ COMPRESS_NONE

#define COMPRESS_NONE   0

Definition at line 3976 of file mlogger.cxx.

◆ COMPRESS_PBZIP2

#define COMPRESS_PBZIP2   4

Definition at line 3980 of file mlogger.cxx.

◆ COMPRESS_ZLIB

#define COMPRESS_ZLIB   1

Definition at line 3977 of file mlogger.cxx.

◆ DELETE

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

Definition at line 368 of file mlogger.cxx.

◆ DISK_CHECK_INTERVAL_MILLISEC

#define DISK_CHECK_INTERVAL_MILLISEC   10000

Definition at line 310 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 367 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 365 of file mlogger.cxx.

◆ OUTPUT_FILE

#define OUTPUT_FILE   2

Definition at line 3996 of file mlogger.cxx.

◆ OUTPUT_FTP

#define OUTPUT_FTP   3

Definition at line 3997 of file mlogger.cxx.

◆ OUTPUT_NONE

#define OUTPUT_NONE   0

Definition at line 3994 of file mlogger.cxx.

◆ OUTPUT_NULL

#define OUTPUT_NULL   1

Definition at line 3995 of file mlogger.cxx.

◆ OUTPUT_PIPE

#define OUTPUT_PIPE   5

Definition at line 3999 of file mlogger.cxx.

◆ OUTPUT_ROOT

#define OUTPUT_ROOT   4

Definition at line 3998 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 4749 of file mlogger.cxx.

4750{
4751 int status;
4752 int size, i;
4753 int index = *indexp;
4754
4755#if 0
4756 {
4757 /* print the tags */
4758 printf("add_event: event %d, name \"%s\", ntags %d\n", event_id, event_name, ntags);
4759 for (i=0; i<ntags; i++) {
4760 printf("tag %d: name \"%s\", type %d, n_data %d\n", i, tags[i].name, tags[i].type, tags[i].n_data);
4761 }
4762 }
4763#endif
4764
4765 /* check for duplicate event id's */
4766 for (i=0; i<index; i++) {
4767 if (strcmp(hist_log[i].event_name, event_name) == 0) {
4768 cm_msg(MERROR, "add_event", "Duplicate event name \'%s\' with event id %d", event_name, event_id);
4769 return 0;
4770 }
4771 }
4772
4773 while (index >= hist_log_size) {
4774 int new_size = 2*hist_log_size;
4775
4776 if (hist_log_size == 0)
4777 new_size = 10;
4778
4780 assert(hist_log!=NULL);
4781
4783 }
4784
4785 if (index >= hist_log_max)
4786 hist_log_max = index + 1;
4787
4788 /* check for invalid history tags */
4789 for (i=0; i<ntags; i++) {
4790 if (tags[i].type == TID_STRING) {
4791 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);
4792 return 0;
4793 }
4794 if (tags[i].type == TID_INT64) {
4795 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);
4796 return 0;
4797 }
4798 if (tags[i].type == TID_UINT64) {
4799 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);
4800 return 0;
4801 }
4802 if (rpc_tid_size(tags[i].type) == 0) {
4803 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);
4804 return 0;
4805 }
4806 }
4807
4808 /* check for trailing spaces in tag names */
4809 for (i=0; i<ntags; i++) {
4810 if (isspace(tags[i].name[strlen(tags[i].name)-1])) {
4811 cm_msg(MERROR, "add_event", "Invalid tag %d \'%s\' in event %d \'%s\': has trailing spaces", i, tags[i].name, event_id, event_name);
4812 return 0;
4813 }
4814 }
4815
4816 for (unsigned i=0; i<mh.size(); i++) {
4817 status = mh[i]->hs_define_event(event_name, timestamp, ntags, tags);
4818 if (status != HS_SUCCESS) {
4819 cm_msg(MERROR, "add_event", "Cannot define event \"%s\", hs_define_event() status %d", event_name, status);
4820 return 0;
4821 }
4822 }
4823
4824 status = db_get_record_size(hDB, hKey, 0, &size);
4825
4826 if (status != DB_SUCCESS) {
4827 cm_msg(MERROR, "add_event", "Cannot define event \"%s\", db_get_record_size() status %d", event_name, status);
4828 return 0;
4829 }
4830
4831 /* setup hist_log structure for this event */
4832 mstrlcpy(hist_log[index].event_name, event_name, sizeof(hist_log[index].event_name));
4835 hist_log[index].buffer_size = size;
4836 hist_log[index].buffer = (char*)malloc(size);
4837 hist_log[index].min_period = min_period;
4838 hist_log[index].last_log = 0;
4839
4840 if (hist_log[index].buffer == NULL) {
4841 cm_msg(MERROR, "add_event", "Cannot allocate data buffer for event \"%s\" size %d", event_name, size);
4842 return 0;
4843 }
4844
4845 /* open hot link to variables */
4846 if (hotlink) {
4848 if (status != DB_SUCCESS) {
4849 cm_msg(MERROR, "add_event",
4850 "Cannot hotlink event %d \"%s\" for history logging, db_open_record() status %d",
4851 event_id, event_name, status);
4852 return status;
4853 }
4854 }
4855
4856 history_events.push_back(event_name);
4857
4858 if (verbose)
4859 printf("Created event %d for equipment \"%s\", %d tags, size %d\n", event_id, event_name, ntags, size);
4860
4861 *indexp = index+1;
4862
4863 return SUCCESS;
4864}
#define DB_SUCCESS
Definition midas.h:631
#define HS_SUCCESS
Definition midas.h:727
#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:929
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:13300
INT db_get_record_size(HNDLE hDB, HNDLE hKey, INT align, INT *buf_size)
Definition odb.cxx:11621
INT rpc_tid_size(INT id)
Definition midas.cxx:11779
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:5571
static std::vector< MidasHistoryInterface * > mh
Definition mlogger.cxx:4746
static int hist_log_size
Definition mlogger.cxx:334
static std::vector< std::string > history_events
Definition mlogger.cxx:4747
static HNDLE hDB
Definition mlogger.cxx:338
static struct hist_log_s * hist_log
Definition mlogger.cxx:336
BOOL verbose
Definition mlogger.cxx:315
static int hist_log_max
Definition mlogger.cxx:335
DWORD status
Definition odbhist.cxx:39
char * buffer
Definition mlogger.cxx:326
HNDLE hKeyVar
Definition mlogger.cxx:328
INT buffer_size
Definition mlogger.cxx:327
time_t min_period
Definition mlogger.cxx:330
DWORD n_var
Definition mlogger.cxx:329
time_t last_log
Definition mlogger.cxx:331
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 4021 of file mlogger.cxx.

4022{
4023 (*def) += std::string(" ") + str;
4024 if (v)
4025 return v; // keep returning the first selection
4026 if (val.find(str) == 0) {
4027 *sel = str;
4028 return n; // if no selection yet, return the new selection
4029 }
4030 return v;
4031}
DWORD n[4]
Definition mana.cxx:247
char str[256]
Definition odbhist.cxx:33
Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_file_exists()

static bool check_file_exists ( const char filename)
static

Definition at line 394 of file mlogger.cxx.

395{
396 struct stat st;
397 int status = stat(filename, &st);
398 if (status == -1) {
399 return false;
400 }
401 return true;
402}
Here is the call graph for this function:
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 5877 of file mlogger.cxx.

5878{
5879 /* close buffers */
5880 for (unsigned i = 0; i < log_channels.size(); i++) {
5882#ifndef FAL_MAIN
5883 if (chn->buffer_handle) {
5884 bm_close_buffer(chn->buffer_handle);
5885 for (unsigned j = i + 1; j < log_channels.size(); j++)
5886 if (log_channels[j]->buffer_handle == chn->buffer_handle)
5887 log_channels[j]->buffer_handle = 0;
5888 }
5889
5890 if (chn->msg_request_id)
5891 bm_delete_request(chn->msg_request_id);
5892#endif
5893
5894 delete chn;
5895 log_channels[i] = NULL;
5896 }
5897
5898 log_channels.clear();
5899
5900 return SUCCESS;
5901}
INT bm_delete_request(INT request_id)
Definition midas.cxx:8606
INT bm_close_buffer(INT buffer_handle)
Definition midas.cxx:7118
std::vector< LOG_CHN * > log_channels
Definition mlogger.cxx:322
INT j
Definition odbhist.cxx:40
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 5832 of file mlogger.cxx.

5833{
5835
5836 for (unsigned i = 0; i < log_channels.size(); i++) {
5838 if (chn->handle || chn->ftp_con|| chn->pfile) {
5839 /* generate MTALK message */
5840#ifndef FAL_MAIN
5841 /* wait until buffer is empty */
5842 if (chn->buffer_handle) {
5843#ifdef DELAYED_STOP
5844 DWORD start_time = ss_millitime();
5845 do {
5846 cm_yield(100);
5847 } while (ss_millitime() - start_time < DELAYED_STOP);
5848#else
5849 INT n_bytes;
5850 do {
5851 bm_get_buffer_level(chn->buffer_handle, &n_bytes);
5852 if (n_bytes > 0)
5853 cm_yield(100);
5854 } while (n_bytes > 0);
5855#endif
5856 }
5857#endif /* FAL_MAIN */
5858
5859 /* close logging channel */
5861
5862 /* close statistics record */
5863 db_set_record(hDB, chn->stats_hkey, &chn->statistics, sizeof(CHN_STATISTICS), 0);
5864 db_close_record(hDB, chn->stats_hkey);
5865 db_unwatch(hDB, chn->settings_hkey);
5866 chn->stats_hkey = 0;
5867 chn->settings_hkey = 0;
5868 }
5869 }
5870
5871 if (p_tape_flag)
5873
5874 return SUCCESS;
5875}
#define FALSE
Definition cfortran.h:309
INT cm_yield(INT millisec)
Definition midas.cxx:5664
unsigned int DWORD
Definition mcstd.h:51
DWORD ss_millitime()
Definition system.cxx:3465
INT db_unwatch(HNDLE hDB, HNDLE hKey)
Definition odb.cxx:13898
INT db_set_record(HNDLE hDB, HNDLE hKey, void *data, INT buf_size, INT align)
Definition odb.cxx:12299
INT db_close_record(HNDLE hDB, HNDLE hKey)
Definition odb.cxx:13483
INT run_number[2]
Definition mana.cxx:246
INT bm_get_buffer_level(INT buffer_handle, INT *n_bytes)
Definition midas.cxx:7860
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:4290
Here is the call graph for this function:
Here is the caller graph for this function:

◆ close_history()

void close_history ( )

Definition at line 5533 of file mlogger.cxx.

5534{
5535 INT status;
5537
5538 /* close system history */
5539 status = db_find_key(hDB, 0, "/History/Links", &hKeyRoot);
5540 if (status == DB_SUCCESS) {
5541 for (int i = 0;; i++) {
5542 HNDLE hKey;
5545 break;
5547 }
5548 }
5549
5550 /* close event history */
5551 for (int i = 0; i < hist_log_max; i++)
5552 if (hist_log[i].hKeyVar) {
5553 db_close_record(hDB, hist_log[i].hKeyVar);
5554 hist_log[i].hKeyVar = 0;
5555 if (hist_log[i].buffer)
5556 free(hist_log[i].buffer);
5557 hist_log[i].buffer = NULL;
5558 }
5559
5560 for (unsigned h=0; h<mh.size(); h++) {
5561 mh[h]->hs_disconnect();
5562 delete mh[h];
5563 mh[h] = NULL;
5564 }
5565
5566 mh.clear();
5567}
#define DB_NO_MORE_SUBKEYS
Definition midas.h:646
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition odb.cxx:4084
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition odb.cxx:5591
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 2492 of file mlogger.cxx.

2493{
2494 std::string filename;
2495 int size, write_flag;
2497
2498 size = sizeof(write_flag);
2499 write_flag = 0;
2500 db_get_value(hDB, 0, "/Logger/Runlog/ASCII/Write data", &write_flag, &size, TID_BOOL, TRUE);
2501
2502 filename = "runlog.log";
2503 db_get_value_string(hDB, 0, "/Logger/Runlog/ASCII/Filename", 0, &filename, TRUE);
2504
2505 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links BOR", &hKeyRoot);
2506 if (!hKeyRoot) {
2507 /* create some default links */
2508 db_create_key(hDB, 0, "/Logger/Runlog/ASCII/Links BOR", TID_KEY);
2509
2510 if (db_find_key(hDB, 0, "/Runinfo/Run number", &hKey) == DB_SUCCESS)
2511 db_create_link(hDB, 0, "/Logger/Runlog/ASCII/Links BOR/Run number", "/Runinfo/Run number");
2512
2513 if (db_find_key(hDB, 0, "/Experiment/Run parameters/Comment", &hKey) == DB_SUCCESS)
2514 db_create_link(hDB, 0, "/Logger/Runlog/ASCII/Links BOR/Comment", "/Experiment/Run parameters/Comment");
2515
2516 if (db_find_key(hDB, 0, "/Runinfo/Start time", &hKey) == DB_SUCCESS)
2517 db_create_link(hDB, 0, "/Logger/Runlog/ASCII/Links BOR/Start time", "/Runinfo/Start time");
2518 }
2519
2520 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links EOR", &hKeyRoot);
2521 if (!hKeyRoot) {
2522 /* create some default links */
2523 db_create_key(hDB, 0, "/Logger/Runlog/ASCII/Links EOR", TID_KEY);
2524
2525 if (db_find_key(hDB, 0, "/Runinfo/Stop time", &hKey) == DB_SUCCESS)
2526 db_create_link(hDB, 0, "/Logger/Runlog/ASCII/Links EOR/Stop time", "/Runinfo/Stop time");
2527
2528 if (db_find_key(hDB, 0, "/Equipment/Trigger/Statistics/Events sent", &hKey) == DB_SUCCESS)
2529 db_create_link(hDB, 0, "/Logger/Runlog/ASCII/Links EOR/Number of events",
2530 "/Equipment/Trigger/Statistics/Events sent");
2531
2532 }
2533}
#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:5420
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
Definition odb.cxx:3313
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:13945
INT db_create_link(HNDLE hDB, HNDLE hKey, const char *link_name, const char *destination)
Definition odb.cxx:3606
#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 2651 of file mlogger.cxx.

2652{
2653 char dirname[256];
2654 int size, write_flag;
2656
2657 size = sizeof(write_flag);
2658 write_flag = 0;
2659 db_get_value(hDB, 0, "/Logger/Runlog/JSON/Write data", &write_flag, &size, TID_BOOL, TRUE);
2660
2661 size = sizeof(dirname);
2662 strcpy(dirname, "runlogs");
2663 db_get_value(hDB, 0, "/Logger/Runlog/JSON/Subdir", dirname, &size, TID_STRING, TRUE);
2664
2665 db_find_key(hDB, 0, "/Logger/Runlog/JSON/Links BOR", &hKeyRoot);
2666 if (!hKeyRoot) {
2667 /* create some default links */
2668 db_create_key(hDB, 0, "/Logger/Runlog/JSON/Links BOR", TID_KEY);
2669
2670 if (db_find_key(hDB, 0, "/Runinfo/Run number", &hKey) == DB_SUCCESS)
2671 db_create_link(hDB, 0, "/Logger/Runlog/JSON/Links BOR/Run number", "/Runinfo/Run number");
2672
2673 if (db_find_key(hDB, 0, "/Experiment/Run parameters/Comment", &hKey) == DB_SUCCESS)
2674 db_create_link(hDB, 0, "/Logger/Runlog/JSON/Links BOR/Comment", "/Experiment/Run parameters/Comment");
2675
2676 if (db_find_key(hDB, 0, "/Runinfo/Start time", &hKey) == DB_SUCCESS)
2677 db_create_link(hDB, 0, "/Logger/Runlog/JSON/Links BOR/Start time", "/Runinfo/Start time");
2678 }
2679
2680 db_find_key(hDB, 0, "/Logger/Runlog/JSON/Links EOR", &hKeyRoot);
2681 if (!hKeyRoot) {
2682 /* create some default links */
2683 db_create_key(hDB, 0, "/Logger/Runlog/JSON/Links EOR", TID_KEY);
2684
2685 if (db_find_key(hDB, 0, "/Runinfo/Stop time", &hKey) == DB_SUCCESS)
2686 db_create_link(hDB, 0, "/Logger/Runlog/JSON/Links EOR/Stop time", "/Runinfo/Stop time");
2687
2688 if (db_find_key(hDB, 0, "/Equipment/Trigger/Statistics/Events sent", &hKey) == DB_SUCCESS)
2689 db_create_link(hDB, 0, "/Logger/Runlog/JSON/Links EOR/Number of events",
2690 "/Equipment/Trigger/Statistics/Events sent");
2691
2692 }
2693}
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 3316 of file mlogger.cxx.

3317{
3318 INT i, index, status, size;
3319 char str[80];
3321 WORD id;
3322
3323#define EVENT_DEF_CACHE_SIZE 30
3324 static EVENT_DEF *event_def = NULL;
3325
3326 /* allocate memory for cache */
3327 if (event_def == NULL)
3329
3330 assert(event_def != NULL);
3331
3332 /* lookup if event definition in cache */
3333 for (i = 0; event_def[i].event_id; i++)
3334 if (event_def[i].event_id == event_id)
3335 return &event_def[i];
3336
3337 /* search free cache entry */
3338 for (index = 0; index < EVENT_DEF_CACHE_SIZE; index++)
3339 if (event_def[index].event_id == 0)
3340 break;
3341
3342 if (index == EVENT_DEF_CACHE_SIZE) {
3343 cm_msg(MERROR, "db_get_event_definition", "too many event definitions");
3344 return NULL;
3345 }
3346
3347 /* check for system events */
3348 if (event_id < 0) {
3349 event_def[index].event_id = event_id;
3350 event_def[index].format = FORMAT_MIDAS;
3351 event_def[index].hDefKey = 0;
3352 return &event_def[index];
3353 }
3354
3355 status = db_find_key(hDB, 0, "/equipment", &hKeyRoot);
3356 if (status != DB_SUCCESS) {
3357 cm_msg(MERROR, "db_get_event_definition", "cannot find /equipment entry in ODB");
3358 return NULL;
3359 }
3360
3361 for (i = 0;; i++) {
3362 /* search for client with specific name */
3364 if (status == DB_NO_MORE_SUBKEYS) {
3365 cm_msg(MERROR, "db_get_event_definition", "Cannot find event id %d under /equipment", event_id);
3366 return NULL;
3367 }
3368
3369 size = sizeof(id);
3370 status = db_get_value(hDB, hKey, "Common/Event ID", &id, &size, TID_UINT16, TRUE);
3371 if (status != DB_SUCCESS)
3372 continue;
3373
3374 if (id == event_id) {
3375 /* set cache entry */
3376 event_def[index].event_id = id;
3377
3378 size = sizeof(str);
3379 str[0] = 0;
3380 db_get_value(hDB, hKey, "Common/Format", str, &size, TID_STRING, TRUE);
3381
3382 if (equal_ustring(str, "Fixed"))
3383 event_def[index].format = FORMAT_FIXED;
3384 else if (equal_ustring(str, "MIDAS"))
3385 event_def[index].format = FORMAT_MIDAS;
3386 else {
3387 cm_msg(MERROR, "db_get_event_definition", "unknown data format name \"%s\"", str);
3388 event_def[index].event_id = 0;
3389 return NULL;
3390 }
3391
3392 db_find_key(hDB, hKey, "Variables", &event_def[index].hDefKey);
3393 return &event_def[index];
3394 }
3395 }
3396}
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:3206
#define EVENT_DEF_CACHE_SIZE
Here is the call graph for this function:

◆ fopen_wx()

static FILE * fopen_wx ( const char filename)
static

Definition at line 386 of file mlogger.cxx.

387{
388 int fd = open(filename, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IRGRP|S_IROTH);
389 if (fd == -1)
390 return NULL;
391 return fdopen(fd, "w");
392}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ftp_error()

INT ftp_error ( const char message)

Definition at line 2826 of file mlogger.cxx.

2827{
2828 cm_msg(MERROR, "ftp_error", "%s", message);
2829 return 1;
2830}
#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 2832 of file mlogger.cxx.

2833{
2834 INT status;
2835 short port = 0;
2836 char *token;
2838 char user[32], pass[32];
2839 char directory[256], file_name[256], file_mode[256];
2840 char bdestination[256]; // have to make a copy of destination because strtok() modifies it's string
2842 char* destination = bdestination;
2843
2844 // skip leading slash
2845 if (destination[0] == '/')
2846 destination += 1;
2847
2848 /*
2849 destination should have the form:
2850 host, port, user, password, directory, run%05d.mid
2851 */
2852
2853 /* break destination in components */
2854 token = strtok(destination, ",");
2855 if (token)
2856 mstrlcpy(host_name, token, sizeof(host_name));
2857
2858 token = strtok(NULL, ", ");
2859 if (token)
2860 port = atoi(token);
2861
2862 token = strtok(NULL, ", ");
2863 if (token)
2864 mstrlcpy(user, token, sizeof(user));
2865
2866 token = strtok(NULL, ", ");
2867 if (token)
2868 mstrlcpy(pass, token, sizeof(pass));
2869
2870 token = strtok(NULL, ", ");
2871 if (token)
2872 mstrlcpy(directory, token, sizeof(directory));
2873
2874 token = strtok(NULL, ", ");
2875 if (token)
2876 mstrlcpy(file_name, token, sizeof(file_name));
2877
2878 token = strtok(NULL, ", ");
2879 file_mode[0] = 0;
2880 if (token)
2881 mstrlcpy(file_mode, token, sizeof(file_mode));
2882
2883#ifdef FAL_MAIN
2885#else
2886 ftp_debug((int (*)(const char *)) puts, ftp_error);
2887#endif
2888
2889 status = ftp_login(con, host_name, port, user, pass, "");
2890 if (status >= 0)
2891 return status;
2892
2893 status = ftp_chdir(*con, directory);
2894 if (status >= 0)
2895 return status;
2896
2897 status = ftp_binary(*con);
2898 if (status >= 0)
2899 return status;
2900
2901 if (file_mode[0]) {
2902 status = ftp_command(*con, "umask %s", file_mode, 200, 250, EOF);
2903 if (status >= 0)
2904 return status;
2905 }
2906
2907 if (ftp_open_write(*con, file_name) >= 0)
2908 return (*con)->err_no;
2909
2910 return SS_SUCCESS;
2911}
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:663
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:2826
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 4403 of file mlogger.cxx.

4404{
4405 int status, size, flag;
4406
4407 size = sizeof(BOOL);
4408 flag = FALSE;
4409 status = db_get_value(hDB, 0, "/Logger/Async transitions", &flag, &size, TID_BOOL, FALSE);
4410
4411 if (status == DB_SUCCESS) {
4412 cm_msg(MINFO, "get_trans_flag", "ODB \"/Logger/Async transitions\" is obsolete, please delete it");
4413 }
4414
4415 size = sizeof(BOOL);
4416 flag = TRUE;
4417 status = db_get_value(hDB, 0, "/Logger/Multithread transitions", &flag, &size, TID_BOOL, FALSE);
4418
4419 if (status == DB_SUCCESS) {
4420 cm_msg(MINFO, "get_trans_flag", "ODB \"/Logger/Multithread transitions\" is obsolete, please delete it");
4421 }
4422
4423 size = sizeof(BOOL);
4424 flag = FALSE;
4425 db_get_value(hDB, 0, "/Logger/Detached transitions", &flag, &size, TID_BOOL, TRUE);
4426
4427 // NB: we must use multithread or detached (via mtransition) transition
4428 // otherwise we deadlock against frontends: they are writing to the SYSTEM
4429 // buffer but we (mlogger) are not reading from it. if SYSTEM buffer is full,
4430 // clients get stuck waiting for free space and cannot not handle TR_STOP RPC.
4431 // if they could handle, it, they would still be stuck in bm_flush_cache()
4432 // because we (mlogger) are not reading the SYSTEM buffer and these last
4433 // events have nowhere to go. K.O.
4434
4435 if (flag)
4436 return TR_DETACH;
4437 else
4438 return TR_MTHREAD;
4439}
#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 4001 of file mlogger.cxx.

4002{
4004 value[0] = 0;
4005 int size = sizeof(value);
4006 int status = db_get_value(hDB, hDir, name, &value, &size, TID_STRING, FALSE);
4007 if (status != DB_SUCCESS)
4008 return "";
4009 return value;
4010}
#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 57 of file mlogger.cxx.

58{
59 char buf[256];
60 sprintf(buf, "%d", value);
61 return buf;
62}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ log_close()

INT log_close ( LOG_CHN log_chn,
INT  run_number 
)

Definition at line 4290 of file mlogger.cxx.

4291{
4292 if (log_chn->writer) {
4293 /* write ODB dump */
4294 if (log_chn->settings.odb_dump)
4296
4297 WriterInterface* wr = log_chn->writer;
4298
4300
4301 /* update statistics */
4302
4303 double incr = wr->fBytesOut - log_chn->statistics.bytes_written_subrun;
4304 if (incr < 0)
4305 incr = 0;
4306
4307 //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);
4308
4309 log_chn->statistics.bytes_written += incr;
4310 log_chn->statistics.bytes_written_subrun = wr->fBytesOut;
4311 log_chn->statistics.bytes_written_total += incr;
4312 }
4313#ifdef OBSOLETE
4314#ifdef HAVE_ROOT
4315 } else if (log_chn->format == FORMAT_ROOT) {
4317#endif
4318 } else if (log_chn->format == FORMAT_MIDAS) {
4320 }
4321#endif
4322
4323 /* if file name starts with '.', rename it */
4324 char str[256]; // FIXME: this will truncate the filename of the output file. K.O.
4325 mstrlcpy(str, log_chn->path.c_str(), sizeof(str));
4326 char* p = str;
4327 if (strrchr(str, DIR_SEPARATOR)) {
4328 p = strrchr(str, DIR_SEPARATOR)+1;
4329 }
4330 if (*p == '.') {
4331 mstrlcpy(p, p+1, sizeof(str));
4332 rename(log_chn->path.c_str(), str); // FIXME: must check return status. K.O.
4333 }
4334
4335 log_chn->statistics.files_written += 1;
4336 log_chn->handle = 0;
4337 log_chn->ftp_con = NULL;
4338
4339 if (log_chn->writer) {
4340 delete log_chn->writer;
4341 log_chn->writer = NULL;
4342 }
4343
4344 return SS_SUCCESS;
4345}
virtual int wr_close(LOG_CHN *log_chn, int run_number)=0
#define FORMAT_ROOT
Definition midas.h:317
#define DIR_SEPARATOR
Definition midas.h:193
#define EVENTID_EOR
Definition midas.h:901
void log_odb_dump(LOG_CHN *log_chn, short int event_id, INT run_number)
Definition mlogger.cxx:1785
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 4084 of file mlogger.cxx.

4085{
4086 assert(log_chn->writer == NULL);
4087 log_chn->writer = NULL;
4088
4089 if (log_chn->output_module > 0) {
4090
4091 if (log_chn->compression_module == COMPRESS_ZLIB) {
4092
4093 if (log_chn->output_module != OUTPUT_FILE) {
4094 cm_msg(MERROR, "log_create_writer", "channel %s requested GZIP/ZLIB compression, output module must be FILE", log_chn->path.c_str());
4095 return SS_FILE_ERROR;
4096 }
4097
4098 log_chn->writer = new WriterGzip(log_chn, 0);
4099 log_chn->do_disk_level = TRUE;
4100 }
4101 else if (log_chn->compression_module == COMPRESS_BZIP2) {
4102
4103 if (log_chn->output_module != OUTPUT_FILE) {
4104 cm_msg(MERROR, "log_create_writer", "channel %s requested BZIP2 compression, output module must be FILE", log_chn->path.c_str());
4105 return SS_FILE_ERROR;
4106 }
4107
4108 log_chn->writer = NewWriterBzip2(log_chn);
4109 log_chn->do_disk_level = TRUE;
4110
4111 }
4112 else if (log_chn->compression_module == COMPRESS_PBZIP2) {
4113
4114 if (log_chn->output_module != OUTPUT_FILE) {
4115 cm_msg(MERROR, "log_create_writer", "channel %s requested PBZIP2 compression, output module must be FILE", log_chn->path.c_str());
4116 return SS_FILE_ERROR;
4117 }
4118
4119 log_chn->writer = NewWriterPbzip2(log_chn);
4120 log_chn->do_disk_level = TRUE;
4121 }
4122 else if (log_chn->output_module == OUTPUT_NULL) {
4123
4124 log_chn->writer = new WriterNull(log_chn);
4125 log_chn->do_disk_level = TRUE;
4126 }
4127 else if (log_chn->output_module == OUTPUT_FILE) {
4128
4129 log_chn->writer = NewCompression(log_chn, log_chn->compression_module, NewChecksum(log_chn, log_chn->post_checksum_module, 0, new WriterFile(log_chn)));
4130 log_chn->do_disk_level = TRUE;
4131 }
4132 else if (log_chn->output_module == OUTPUT_FTP) {
4133
4134 log_chn->writer = NewCompression(log_chn, log_chn->compression_module, NewChecksum(log_chn, log_chn->post_checksum_module, 0, new WriterFtp(log_chn)));
4135 log_chn->do_disk_level = FALSE;
4136 log_chn->statistics.disk_level = -1;
4137 }
4138 else if (log_chn->output_module == OUTPUT_ROOT) {
4139
4140#ifdef HAVE_ROOT
4141 log_chn->writer = new WriterROOT(log_chn);
4142 log_chn->do_disk_level = TRUE;
4143#else
4144 cm_msg(MERROR, "log_create_writer", "channel \"%s\" requested ROOT output, but mlogger is built without HAVE_ROOT", log_chn->name.c_str());
4145 log_chn->writer = new WriterNull(log_chn);
4146 log_chn->do_disk_level = TRUE;
4147#endif
4148 }
4149 else if (log_chn->output_module == OUTPUT_PIPE) {
4150
4151 log_chn->writer = NewCompression(log_chn, log_chn->compression_module, NewChecksum(log_chn, log_chn->post_checksum_module, 0, new WriterPopen(log_chn, "xxx", "")));
4152 log_chn->do_disk_level = FALSE;
4153 log_chn->statistics.disk_level = -1;
4154 }
4155
4156 //log_chn->writer = new WriterROOT(log_chn);
4157 //log_chn->do_disk_level = TRUE;
4158
4159 if (log_chn->pre_checksum_module) {
4160 log_chn->writer = NewChecksum(log_chn, log_chn->pre_checksum_module, 1, log_chn->writer);
4161 }
4162
4163 //cm_msg(MINFO, "log_create_writer", "channel \"%s\" writer chain: %s", log_chn->path.c_str(), log_chn->writer->wr_get_chain().c_str());
4164
4165 return SUCCESS;
4166 }
4167
4168 cm_msg(MERROR, "log_create_writer", "channel %s invalid output module value %d", log_chn->path.c_str(), log_chn->output_module);
4169 return SS_FILE_ERROR;
4170
4171#ifdef OBSOLETE
4172 int xcompress = log_chn->compression;
4173 // compression format: ABNNN
4174 // A - pre-compression checksum,
4175 // B - post-compression (file) checksum,
4176 // NNN - compression code
4177 int compression = xcompress%1000;
4178 int prechecksum = (xcompress/10000)%10;
4179 int postchecksum = (xcompress/1000)%10;
4180
4181 // 0=old file output, 1-9=old gzip output
4182 if (compression < 10)
4183 return SUCCESS;
4184
4185 if (compression==80) {
4186#ifdef HAVE_ROOT
4187 log_chn->writer = new WriterROOT(log_chn);
4188 log_chn->do_disk_level = TRUE;
4189#else
4190 log_chn->writer = new WriterNull(log_chn);
4191 log_chn->do_disk_level = TRUE;
4192#endif
4193 } else if (compression==81) {
4194 log_chn->writer = new WriterFtp(log_chn);
4195 log_chn->do_disk_level = FALSE;
4196 log_chn->statistics.disk_level = -1;
4197 } else if (compression==82) {
4199 log_chn->do_disk_level = FALSE;
4200 log_chn->statistics.disk_level = -1;
4201 } else if (compression==98) {
4202 log_chn->writer = new WriterNull(log_chn);
4203 log_chn->do_disk_level = TRUE;
4204 } else if (compression==99) {
4205 log_chn->writer = new WriterFile(log_chn);
4206 log_chn->do_disk_level = TRUE;
4207 } else if (compression==100) {
4209 log_chn->do_disk_level = TRUE;
4210 } else if (compression==200) {
4211 log_chn->writer = NewWriterBzip2(log_chn);
4212 log_chn->do_disk_level = TRUE;
4213 } else if (compression==201) {
4214 log_chn->writer = NewWriterPbzip2(log_chn);
4215 log_chn->do_disk_level = TRUE;
4216 } else if (compression==300) {
4217 log_chn->writer = new WriterGzip(log_chn, 0);
4218 log_chn->do_disk_level = TRUE;
4219 } else if (compression==301) {
4220 log_chn->writer = new WriterGzip(log_chn, 1);
4221 log_chn->do_disk_level = TRUE;
4222 } else if (compression==309) {
4223 log_chn->writer = new WriterGzip(log_chn, 9);
4224 log_chn->do_disk_level = TRUE;
4225 } else {
4226 cm_msg(MERROR, "log_create_writer", "channel %s unknown compression mode %d", log_chn->path.c_str(), log_chn->compression);
4227 return SS_FILE_ERROR;
4228 }
4229
4230 if (prechecksum) {
4231 log_chn->writer = NewChecksum(log_chn, prechecksum, 1, log_chn->writer);
4232 }
4233#endif
4234
4235 return SS_SUCCESS;
4236}
#define SS_FILE_ERROR
Definition midas.h:669
WriterInterface * NewCompression(LOG_CHN *log_chn, int code, WriterInterface *chained)
Definition mlogger.cxx:3982
#define OUTPUT_FILE
Definition mlogger.cxx:3996
#define OUTPUT_NULL
Definition mlogger.cxx:3995
WriterInterface * NewChecksum(LOG_CHN *log_chn, int code, int level, WriterInterface *chained)
Definition mlogger.cxx:3958
WriterInterface * NewWriterBzip2(LOG_CHN *log_chn)
Definition mlogger.cxx:3918
#define OUTPUT_FTP
Definition mlogger.cxx:3997
#define OUTPUT_PIPE
Definition mlogger.cxx:3999
#define COMPRESS_BZIP2
Definition mlogger.cxx:3979
#define COMPRESS_PBZIP2
Definition mlogger.cxx:3980
#define OUTPUT_ROOT
Definition mlogger.cxx:3998
WriterInterface * NewWriterPbzip2(LOG_CHN *log_chn)
Definition mlogger.cxx:3930
#define COMPRESS_ZLIB
Definition mlogger.cxx:3977
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 4349 of file mlogger.cxx.

4350{
4351 std::string str = log_chn->path.c_str();
4352 size_t pos = str.rfind('/');
4353 if (pos != std::string::npos) {
4354 str.erase(pos); // strip filename for bzip2
4355 }
4356
4357 //printf("log_disk_level [%s] [%s]\n", log_chn->path.c_str(), str.c_str());
4358
4359 double MiB = 1024*1024;
4360 double disk_size = ss_disk_size(str.c_str());
4361 double disk_free = ss_disk_free(str.c_str());
4362 double limit = 10E6;
4363 double level = 1.0-disk_free/disk_size;
4364
4365 if (pdisk_size)
4366 *pdisk_size = disk_size; // should be in statistics
4367 if (pdisk_free)
4368 *pdisk_free = disk_free; // should be in statistics
4369
4370 log_chn->statistics.disk_level = level;
4371
4372 if (verbose)
4373 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);
4374
4375 return SUCCESS;
4376}
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 5677 of file mlogger.cxx.

5678{
5679 INT size, status, run_number = 0;
5680 std::string path;
5681 std::string data_dir;
5683
5684 chn_settings = &log_chn->settings;
5685 size = sizeof(run_number);
5686 status = db_get_value(hDB, 0, "Runinfo/Run number", &run_number, &size, TID_INT32, TRUE);
5687 assert(status == SUCCESS);
5688
5689 std::string filename = chn_settings->filename;
5690 /* Check if data stream are throw pipe command */
5691 log_chn->pipe_command = "";
5692 bool ispipe = false;
5693 if (log_chn->type == LOG_TYPE_DISK) {
5694 char* p = strchr(chn_settings->filename, '>');
5695 if (chn_settings->filename[0] == '|' && p) {
5696 /* skip second arrow in ">>" */
5697 while (*p == '>')
5698 p++;
5699 /* skip spaces after '>' */
5700 while (*p == ' ')
5701 p++;
5702 filename = p;
5703 ispipe = true;
5704 // pipe_command is contents of chn_settings->filename without the leading "|" and trailing ">"
5705 log_chn->pipe_command = "";
5706 const char*s = chn_settings->filename;
5707 /* skip leading pipe */
5708 if (*s == '|')
5709 s++;
5710 /* skip spaces */
5711 while (*s == ' ')
5712 s++;
5713 /* copy up to ">" */
5714 while (*s != '>') {
5715 log_chn->pipe_command += *s++;
5716 }
5717 /* copy as many ">" as they put there */
5718 while (*s == '>') {
5719 log_chn->pipe_command += *s++;
5720 }
5721 }
5722 }
5723
5724 std::string str;
5725
5726 /* if disk, precede filename with directory if not already there */
5727 if (log_chn->type == LOG_TYPE_DISK && filename[0] != DIR_SEPARATOR) {
5728 db_get_value_string(hDB, 0, "/Logger/Data Dir", 0, &data_dir, TRUE);
5729 if (data_dir.empty()) {
5731 } else {
5732 if (data_dir.back() != DIR_SEPARATOR)
5734 }
5735 str = data_dir;
5736
5737 /* append subdirectory if requested */
5738 if (chn_settings->subdir_format[0]) {
5739 ss_tzset(); // required for localtime_r()
5740 time_t now;
5741 time(&now);
5742 struct tm tms;
5743 localtime_r(&now, &tms);
5744
5745 char dir[256];
5746 strftime(dir, sizeof(dir), chn_settings->subdir_format, &tms);
5747 str += dir;
5749 }
5750
5751 /* create directory if needed */
5752#ifdef OS_WINNT
5753 status = mkdir(str.c_str());
5754#else
5755 status = mkdir(str.c_str(), 0755);
5756#endif
5757#if defined(EEXIST)
5758 if (status == -1 && errno != EEXIST)
5759 cm_msg(MERROR, "log_generate_file_name", "Cannot create subdirectory \"%s\", mkdir() errno %d (%s)", str.c_str(), errno, strerror(errno));
5760#endif
5761
5762 str += filename;
5763 } else {
5764 str = filename;
5765 }
5766
5767 /* check if two "%" are present in filename */
5768 if (strchr(str.c_str(), '%')) {
5769 if (strchr(strchr(str.c_str(), '%')+1, '%')) {
5770 /* substitude first "%d" by current run number, second "%d" by subrun number */
5771 path = msprintf(str.c_str(), run_number, log_chn->subrun_number);
5772 } else {
5773 /* substitue "%d" by current run number */
5774 path = msprintf(str.c_str(), run_number);
5775 }
5776 } else {
5777 path = str;
5778 }
5779
5780 /* add required file extension */
5781 if (log_chn->writer) {
5782 path += log_chn->writer->wr_get_file_ext();
5783 }
5784
5785 log_chn->path = path;
5786
5787 /* write back current file name to ODB */
5788 std::string tmpstr;
5789 if (strncmp(path.c_str(), data_dir.c_str(), data_dir.length()) == 0)
5790 tmpstr = path.c_str() + data_dir.length();
5791 else
5792 tmpstr = path;
5793 char cstr[256];
5794 mstrlcpy(cstr, tmpstr.c_str(), sizeof(cstr));
5795 db_set_value(hDB, log_chn->settings_hkey, "Current filename", cstr, 256, 1, TID_STRING);
5796
5797 /* construct full pipe command */
5798 if (ispipe) {
5799 /* check if %d must be substitude by current run number in pipe command options */
5800 if (strchr(log_chn->pipe_command.c_str(), '%')) {
5801 std::string str = log_chn->pipe_command;
5802 if (strchr(strchr(str.c_str(), '%')+1, '%')) {
5803 /* substitude first "%d" by current run number, second "%d" by subrun number */
5804 log_chn->pipe_command = msprintf(str.c_str(), run_number, log_chn->subrun_number);
5805 } else {
5806 /* substitue "%d" by current run number */
5807 log_chn->pipe_command = msprintf(str.c_str(), run_number);
5808 }
5809 } else {
5810 }
5811 /* add a space */
5812 if (log_chn->pipe_command.back() != ' ')
5813 log_chn->pipe_command += " ";
5814 /* add generated filename to pipe command */
5815 log_chn->pipe_command += path;
5816 //printf("pipe command [%s]\n", log_chn->pipe_command.c_str());
5817 }
5818
5819 return CM_SUCCESS;
5820}
std::string cm_get_path()
Definition midas.cxx:1551
#define CM_SUCCESS
Definition midas.h:582
#define TID_INT32
Definition midas.h:339
#define LOG_TYPE_DISK
Definition msystem.h:500
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:5266
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
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 5571 of file mlogger.cxx.

5572{
5573 INT i, size, status;
5575
5576 time_t now = time(NULL);
5577
5578 for (i = 0; i < hist_log_max; i++)
5579 if (hist_log[i].hKeyVar == hKey)
5580 break;
5581
5582 if (i == hist_log_max)
5583 return;
5584
5585 /* check if over minimum period */
5586 if (now - hist_log[i].last_log < hist_log[i].min_period)
5587 return;
5588
5589 /* check if event size has changed */
5590 db_get_record_size(hDB, hKey, 0, &size);
5591 if (size != hist_log[i].buffer_size) {
5592 close_history();
5593 status = open_history();
5594 if (status != CM_SUCCESS) {
5595 printf("Error in history system, aborting.\n");
5597 exit(1);
5598 }
5599 return;
5600 }
5601
5603
5604 if (verbose)
5605 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);
5606
5607 for (unsigned h=0; h<mh.size(); h++) {
5608 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);
5609 if (verbose)
5610 if (status != HS_SUCCESS)
5611 printf("write_history_event: \'%s\', channel \'%s\' hs_write_event() status %d\n", hist_log[i].event_name, mh[h]->name, status);
5612 }
5613
5615
5617 if (end_millitime - start_millitime > 3000)
5618 cm_msg(MINFO, "log_history", "History write operation took %d ms", end_millitime - start_millitime);
5619}
INT cm_disconnect_experiment(void)
Definition midas.cxx:2860
void maybe_flush_history(time_t now)
Definition mlogger.cxx:5515
void close_history()
Definition mlogger.cxx:5533
INT open_history()
Definition mlogger.cxx:4866
static std::string TimeToString(time_t t)
Definition mlogger.cxx:64
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 1785 of file mlogger.cxx.

1786{
1787 if (equal_ustring(log_chn->settings.odb_dump_format, "odb")) {
1789 } else if (equal_ustring(log_chn->settings.odb_dump_format, "xml")) {
1791 } else if (equal_ustring(log_chn->settings.odb_dump_format, "json")) {
1793 } else {
1794 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());
1795 }
1796}
void log_odb_dump_json(LOG_CHN *log_chn, short int event_id, INT run_number)
Definition mlogger.cxx:1758
void log_odb_dump_xml(LOG_CHN *log_chn, short int event_id, INT run_number)
Definition mlogger.cxx:1727
void log_odb_dump_odb(LOG_CHN *log_chn, short int event_id, INT run_number)
Definition mlogger.cxx:1698
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 1758 of file mlogger.cxx.

1759{
1760 /* write ODB dump */
1761
1762 char* buffer = NULL;
1763 int buffer_size = 0;
1764 int buffer_end = 0;
1765
1766 int status = db_copy_json_save(hDB, 0, &buffer, &buffer_size, &buffer_end);
1767
1768 //printf("db_copy_json_save: status %d, buffer_size %d, buffer_end %d\n", status, buffer_size, buffer_end);
1769
1770 if (status == DB_SUCCESS) {
1771 int event_size = sizeof(EVENT_HEADER) + buffer_end;
1773 if (pevent == NULL) {
1774 cm_msg(MERROR, "log_odb_dump", "Cannot allocate ODB dump buffer size %d", event_size);
1775 } else {
1777 memcpy(pevent+1, buffer, buffer_end);
1778 log_write(log_chn, pevent);
1779 free(pevent);
1780 }
1781 }
1782 free(buffer);
1783}
INT bm_compose_event(EVENT_HEADER *event_header, short int event_id, short int trigger_mask, DWORD data_size, DWORD serial)
Definition midas.cxx:8303
INT db_copy_json_save(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end)
Definition odb.cxx:10480
#define MIDAS_MAGIC
Definition midas.h:911
INT log_write(LOG_CHN *log_chn, EVENT_HEADER *pheader)
Definition mlogger.cxx:4538
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 1698 of file mlogger.cxx.

1699{
1700 /* write ODB dump */
1701
1702 static int buffer_size = 100000;
1703
1704 do {
1705 EVENT_HEADER* pevent = (EVENT_HEADER *) malloc(buffer_size);
1706 if (pevent == NULL) {
1707 cm_msg(MERROR, "log_odb_dump", "Cannot allocate ODB dump buffer");
1708 break;
1709 }
1710
1711 int size = buffer_size - sizeof(EVENT_HEADER);
1712 //int status = db_copy_xml(hDB, 0, (char *) (pevent + 1), &size);
1713 int status = db_copy(hDB, 0, (char *) (pevent + 1), &size, "");
1714 if (status != DB_TRUNCATED) {
1715 bm_compose_event(pevent, event_id, MIDAS_MAGIC, buffer_size - sizeof(EVENT_HEADER) - size + 1, run_number);
1716 log_write(log_chn, pevent);
1717 free(pevent);
1718 break;
1719 }
1720
1721 /* increase buffer size if truncated */
1722 free(pevent);
1723 buffer_size *= 10;
1724 } while (1);
1725}
#define DB_TRUNCATED
Definition midas.h:644
INT db_copy(HNDLE hDB, HNDLE hKey, char *buffer, INT *buffer_size, const char *path)
Definition odb.cxx:8222
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 1727 of file mlogger.cxx.

1728{
1729 /* write ODB dump */
1730
1731 static int buffer_size = 100000;
1732
1733 do {
1734 EVENT_HEADER* pevent = (EVENT_HEADER *) malloc(buffer_size);
1735 if (pevent == NULL) {
1736 cm_msg(MERROR, "log_odb_dump", "Cannot allocate ODB dump buffer");
1737 break;
1738 }
1739
1740 int size = buffer_size - sizeof(EVENT_HEADER);
1741 int status = db_copy_xml(hDB, 0, (char *) (pevent + 1), &size, true);
1742
1743 /* following line would dump ODB in old ASCII format instead of XML */
1744 //status = db_copy(hDB, 0, (char *) (pevent + 1), &size, "");
1745 if (status != DB_TRUNCATED) {
1747 log_write(log_chn, pevent);
1748 free(pevent);
1749 break;
1750 }
1751
1752 /* increase buffer size if truncated */
1753 free(pevent);
1754 buffer_size *= 10;
1755 } while (1);
1756}
INT db_copy_xml(HNDLE hDB, HNDLE hKey, char *buffer, int *buffer_size, bool header)
Definition odb.cxx:9042
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 4240 of file mlogger.cxx.

4241{
4242 INT status = SUCCESS;
4243
4244 log_chn->last_checked = ss_millitime();
4245
4246 if (log_chn->writer) {
4247 WriterInterface* wr = log_chn->writer;
4248
4250
4251 if (status != SUCCESS)
4252 return status;
4253
4254 /* write ODB dump */
4255 if (log_chn->settings.odb_dump)
4257
4258 /* update statistics */
4259 double incr = wr->fBytesOut - log_chn->statistics.bytes_written_subrun;
4260 if (incr < 0)
4261 incr = 0;
4262
4263 //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);
4264
4265 log_chn->statistics.bytes_written += incr;
4266 log_chn->statistics.bytes_written_subrun = wr->fBytesOut;
4267 log_chn->statistics.bytes_written_total += incr;
4268 } else {
4269 return SS_INVALID_FORMAT;
4270 }
4271#ifdef OBSOLETE
4272 } else if (equal_ustring(log_chn->settings.format, "ROOT")) {
4273#ifdef HAVE_ROOT
4274 log_chn->format = FORMAT_ROOT;
4276#else
4277 return SS_NO_ROOT;
4278#endif
4279 } else if (equal_ustring(log_chn->settings.format, "MIDAS")) {
4280 log_chn->format = FORMAT_MIDAS;
4282 } else
4283 return SS_INVALID_FORMAT;
4284#endif
4285 return status;
4286}
virtual int wr_open(LOG_CHN *log_chn, int run_number)=0
#define SS_INVALID_FORMAT
Definition midas.h:688
#define SS_NO_ROOT
Definition midas.h:689
#define EVENTID_BOR
Definition midas.h:900
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 5623 of file mlogger.cxx.

5624{
5625 INT size, total_size, status, index;
5626 DWORD i;
5627 KEY key;
5629
5630 index = (INT) (POINTER_T) info;
5631
5632 time_t now = time(NULL);
5633
5634 /* check if over period */
5635 if (now - hist_log[index].last_log < hist_log[index].min_period)
5636 return;
5637
5638 for (i = 0, total_size = 0;; i++) {
5639 status = db_enum_key(hDB, hist_log[index].hKeyVar, i, &hKey);
5641 break;
5642
5643 db_get_key(hDB, hKey, &key);
5644 size = key.total_size;
5645 db_get_data(hDB, hKey, (char *) hist_log[index].buffer + total_size, &size, key.type);
5646 total_size += size;
5647 }
5648
5649 if (i != hist_log[index].n_var) {
5650 close_history();
5651 status = open_history();
5652 if (status != CM_SUCCESS) {
5653 printf("Error in history system, aborting.\n");
5655 exit(1);
5656 }
5657 return;
5658 }
5659
5661
5662 if (verbose)
5663 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);
5664
5665 for (unsigned h=0; h<mh.size(); h++)
5666 mh[h]->hs_write_event(hist_log[index].event_name, hist_log[index].last_log, total_size, hist_log[index].buffer);
5667
5669
5671 if (end_millitime - start_millitime > 3000)
5672 cm_msg(MINFO, "log_system_history", "History write operation took %d ms", end_millitime - start_millitime);
5673}
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:6544
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
Definition odb.cxx:6024
void ** info
Definition fesimdaq.cxx:41
KEY key
Definition mdump.cxx:34
#define POINTER_T
Definition midas.h:166
Definition midas.h:1026
DWORD type
Definition midas.h:1027
INT total_size
Definition midas.h:1031
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 4538 of file mlogger.cxx.

4539{
4540 INT status = 0, size;
4543
4544 //printf("log_write %d\n", pevent->data_size + sizeof(EVENT_HEADER));
4545
4546 DWORD start_time = ss_millitime();
4547 int evt_size = pevent->data_size + sizeof(EVENT_HEADER);
4548
4549 if (log_chn->writer) {
4550 WriterInterface* wr = log_chn->writer;
4551 status = wr->wr_write(log_chn, pevent, evt_size);
4552
4553 if (status == SUCCESS) {
4554 /* update statistics */
4555 log_chn->statistics.events_written++;
4556 log_chn->statistics.bytes_written_uncompressed += evt_size;
4557 }
4558
4559 double incr = wr->fBytesOut - log_chn->statistics.bytes_written_subrun;
4560 if (incr < 0)
4561 incr = 0;
4562
4563 //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);
4564
4565 log_chn->statistics.bytes_written += incr;
4566 log_chn->statistics.bytes_written_subrun = wr->fBytesOut;
4567 log_chn->statistics.bytes_written_total += incr;
4568 }
4569#ifdef OBSOLETE
4570 } else {
4571 int written = 0;
4572
4573 if (log_chn->format == FORMAT_MIDAS) {
4574 written = midas_write(log_chn, pevent, pevent->data_size + sizeof(EVENT_HEADER));
4575#ifdef HAVE_ROOT
4576 } else if (log_chn->format == FORMAT_ROOT) {
4577 written = root_write(log_chn, pevent, pevent->data_size + sizeof(EVENT_HEADER));
4578#endif
4579 }
4580
4581 /* update statistics */
4582 if (written > 0) {
4583 log_chn->statistics.events_written++;
4584 log_chn->statistics.bytes_written_uncompressed += evt_size;
4585 log_chn->statistics.bytes_written += written;
4586 log_chn->statistics.bytes_written_total += written;
4587 log_chn->statistics.bytes_written_subrun += written;
4588 }
4589
4590 if (written < 0)
4592 else
4594 }
4595#endif
4596
4598 if (actual_time - start_time > 3000)
4599 cm_msg(MINFO, "log_write", "Write operation on \'%s\' took %d ms", log_chn->path.c_str(), actual_time - start_time);
4600
4601 if (status != SS_SUCCESS && !stop_requested) {
4602 cm_msg(MTALK, "log_write", "Error writing output file, stopping run");
4603 cm_msg(MERROR, "log_write", "Cannot write \'%s\', error %d, stopping run", log_chn->path.c_str(), status);
4604 stop_the_run(0);
4605
4606 return status;
4607 }
4608
4609 /* check if event limit is reached to stop run */
4611 log_chn->settings.event_limit > 0 &&
4612 log_chn->statistics.events_written >= log_chn->settings.event_limit) {
4614
4615 cm_msg(MTALK, "log_write", "stopping run after having received %1.0lf events",
4616 log_chn->settings.event_limit);
4617
4618 status = stop_the_run(1);
4619 return status;
4620 }
4621
4622 /* check if duration is reached for subrun */
4623 duration = 0;
4624 size = sizeof(duration);
4625 db_get_value(hDB, 0, "/Logger/Subrun duration", &duration, &size, TID_UINT32, TRUE);
4627 int run_number;
4628
4629 // cm_msg(MTALK, "main", "stopping subrun after %d seconds", duration);
4630
4631 size = sizeof(run_number);
4632 status = db_get_value(hDB, 0, "Runinfo/Run number", &run_number, &size, TID_INT32, TRUE);
4633 assert(status == SUCCESS);
4634
4635 stop_requested = TRUE; // avoid recursive call thourgh log_odb_dump
4637 log_chn->subrun_number++;
4638 log_chn->statistics.bytes_written_subrun = 0;
4644 }
4645
4646 /* check if byte limit is reached for subrun */
4647 if (!stop_requested && log_chn->settings.subrun_byte_limit > 0 &&
4648 log_chn->statistics.bytes_written_subrun >= log_chn->settings.subrun_byte_limit) {
4649 int run_number;
4650
4651 // cm_msg(MTALK, "main", "stopping subrun after %1.0lf bytes", log_chn->settings.subrun_byte_limit);
4652
4653 size = sizeof(run_number);
4654 status = db_get_value(hDB, 0, "Runinfo/Run number", &run_number, &size, TID_INT32, TRUE);
4655 assert(status == SUCCESS);
4656
4657 stop_requested = TRUE; // avoid recursive call thourgh log_odb_dump
4659 log_chn->subrun_number++;
4660 log_chn->statistics.bytes_written_subrun = 0;
4666 }
4667
4668 /* check if new subrun is requested manually */
4670 size = sizeof(next_subrun);
4671 db_get_value(hDB, 0, "/Logger/Next subrun", &next_subrun, &size, TID_BOOL, true);
4672 if (!stop_requested && next_subrun) {
4673 int run_number;
4674
4675 // cm_msg(MTALK, "main", "stopping subrun by user request");
4676
4677 size = sizeof(run_number);
4678 status = db_get_value(hDB, 0, "Runinfo/Run number", &run_number, &size, TID_INT32, TRUE);
4679 assert(status == SUCCESS);
4680
4681 stop_requested = TRUE; // avoid recursive call thourgh log_odb_dump
4683 log_chn->subrun_number++;
4684 log_chn->statistics.bytes_written_subrun = 0;
4690
4692 db_set_value(hDB, 0, "/Logger/Next subrun", &next_subrun, sizeof(next_subrun), 1, TID_BOOL);
4693 }
4694
4695 /* check if byte limit is reached to stop run */
4697 log_chn->settings.byte_limit > 0 &&
4698 log_chn->statistics.bytes_written >= log_chn->settings.byte_limit) {
4700
4701 cm_msg(MTALK, "log_write", "stopping run after having received %1.0lf mega bytes",
4702 log_chn->statistics.bytes_written / 1E6);
4703
4704 status = stop_the_run(1);
4705
4706 return status;
4707 }
4708
4709 /* stop run if less than 10MB free disk space */
4711 if (log_chn->type == LOG_TYPE_DISK && log_chn->do_disk_level && actual_time - log_chn->last_checked > DISK_CHECK_INTERVAL_MILLISEC) {
4712 log_chn->last_checked = actual_time;
4713
4714 const double MiB = 1024*1024;
4715 double disk_size = 0;
4716 double disk_free = 0;
4717
4719
4720 double limit = 10E6;
4721
4722 if (disk_size > 100E9) {
4723 limit = 1000E6;
4724 } else if (disk_size > 10E9) {
4725 limit = 100E6;
4726 }
4727
4728 if (disk_free < limit) {
4730 cm_msg(MTALK, "log_write", "disk nearly full, stopping the run");
4731 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);
4732
4733 status = stop_the_run(0);
4734 }
4735 }
4736
4737 return status;
4738}
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:310
int log_create_writer(LOG_CHN *log_chn)
Definition mlogger.cxx:4084
int log_generate_file_name(LOG_CHN *log_chn)
Definition mlogger.cxx:5677
INT log_open(LOG_CHN *log_chn, INT run_number)
Definition mlogger.cxx:4240
BOOL in_stop_transition
Definition mlogger.cxx:313
DWORD subrun_start_time
Definition mlogger.cxx:319
BOOL stop_requested
Definition mlogger.cxx:316
int log_disk_level(LOG_CHN *log_chn, double *pdisk_size, double *pdisk_free)
Definition mlogger.cxx:4349
int stop_the_run(int restart)
Definition mlogger.cxx:4443
Here is the call graph for this function:
Here is the caller graph for this function:

◆ logger_init()

void logger_init ( )

Definition at line 1618 of file mlogger.cxx.

1619{
1620 INT size, status, delay;
1621 BOOL flag;
1623 KEY key;
1624 std::string str;
1625
1626 /*---- create /logger entries -----*/
1627
1628 str = cm_get_path();
1629 db_get_value_string(hDB, 0, "/Logger/Data dir", 0, &str, TRUE);
1630
1631 str = "";
1632 db_get_value_string(hDB, 0, "/Logger/Message dir", 0, &str, TRUE);
1633
1634 str = "";
1635 db_get_value_string(hDB, 0, "/Logger/History dir", 0, &str, TRUE);
1636
1637 str = "";
1638 db_get_value_string(hDB, 0, "/Logger/Message file date format", 0, &str, TRUE);
1639
1640 size = sizeof(BOOL);
1641 flag = TRUE;
1642 db_get_value(hDB, 0, "/Logger/Write data", &flag, &size, TID_BOOL, TRUE);
1643
1644 flag = FALSE;
1645 db_get_value(hDB, 0, "/Logger/ODB Dump", &flag, &size, TID_BOOL, TRUE);
1646
1647 str = "run%05d.json";
1648 db_get_value_string(hDB, 0, "/Logger/ODB Dump File", 0, &str, TRUE);
1649
1650 str = "last.json";
1651 db_get_value_string(hDB, 0, "/Logger/ODB Last Dump File", 0, &str, TRUE);
1652
1653 flag = FALSE;
1654 size = sizeof(BOOL);
1655 db_get_value(hDB, 0, "/Logger/Auto restart", &flag, &size, TID_BOOL, TRUE);
1656
1657 delay = 0;
1658 size = sizeof(INT);
1659 db_get_value(hDB, 0, "/Logger/Auto restart delay", &delay, &size, TID_INT32, TRUE);
1660
1661 flag = TRUE;
1662 db_get_value(hDB, 0, "/Logger/Tape message", &flag, &size, TID_BOOL, TRUE);
1663
1664 /* create at least one logging channel */
1665 status = db_find_key(hDB, 0, "/Logger/Channels/0", &hKey);
1666 if (status != DB_SUCCESS) {
1667 /* if no channels are defined, define at least one */
1668 status = db_create_record(hDB, 0, "/Logger/Channels/0", strcomb1(chn_tree_str).c_str());
1669 if (status != DB_SUCCESS)
1670 cm_msg(MERROR, "logger_init", "Cannot create channel entry in database");
1671 } else {
1672 /* check format of other channels */
1673 status = db_find_key(hDB, 0, "/Logger/Channels", &hKey);
1674 if (status == DB_SUCCESS) {
1675 for (int index = 0; ; index++) {
1678 break;
1679
1682 if (status != DB_SUCCESS && status != DB_OPEN_RECORD) {
1683 cm_msg(MERROR, "logger_init", "Cannot create/check channel record %s, db_check_record() status %d", key.name, status);
1684 break;
1685 }
1686 }
1687 }
1688 }
1689#ifdef HAVE_MYSQL
1691#endif
1694}
#define DB_OPEN_RECORD
Definition midas.h:650
std::string strcomb1(const char **list)
Definition odb.cxx:600
INT db_check_record(HNDLE hDB, HNDLE hKey, const char *keyname, const char *rec_str, BOOL correct)
Definition odb.cxx:12981
INT db_create_record(HNDLE hDB, HNDLE hKey, const char *orig_key_name, const char *init_str)
Definition odb.cxx:12808
void create_runlog_json_tree()
Definition mlogger.cxx:2651
void create_runlog_ascii_tree()
Definition mlogger.cxx:2492
char name[NAME_LENGTH]
Definition midas.h:1029
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 6439 of file mlogger.cxx.

6440{
6441 INT status, msg, i, size, ch = 0;
6444 DWORD last_time_kb = 0;
6447
6448#ifdef HAVE_ROOT
6449 char **rargv;
6450 int rargc;
6451
6452 /* copy first argument */
6453 rargc = 0;
6454 rargv = (char **) malloc(sizeof(char *) * 2);
6455 assert(rargv != NULL);
6456 rargv[rargc] = (char *) malloc(strlen(argv[rargc]) + 1);
6457 assert(rargv[rargc] != NULL);
6458 strcpy(rargv[rargc], argv[rargc]);
6459 rargc++;
6460
6461 /* append argument "-b" for batch mode without graphics */
6462 rargv[rargc++] = (char *)"-b";
6463
6464 TApplication theApp("mlogger", &rargc, rargv);
6465
6466 /* free argument memory */
6467 free(rargv[0]);
6468 rargv[0] = NULL;
6469 free(rargv);
6470 rargv = NULL;
6471
6472#endif
6473
6474#ifdef SIGPIPE
6475 // undo ROOT overwrites SIGPIPE
6477#endif
6478
6479 setbuf(stdout, NULL);
6480 setbuf(stderr, NULL);
6481
6482 /* get default from environment */
6484
6486
6487 /* parse command line parameters */
6488 for (i = 1; i < argc; i++) {
6489 if (argv[i][0] == '-' && argv[i][1] == 'd')
6490 debug = TRUE;
6491 else if (argv[i][0] == '-' && argv[i][1] == 'D')
6492 daemon = TRUE;
6493 else if (argv[i][0] == '-' && argv[i][1] == 's')
6494 save_mode = TRUE;
6495 else if (argv[i][0] == '-' && argv[i][1] == 'v')
6496 verbose = TRUE;
6497 else if (argv[i][0] == '-') {
6498 if (i + 1 >= argc || argv[i + 1][0] == '-')
6499 goto usage;
6500 if (argv[i][1] == 'e')
6501 strcpy(exp_name, argv[++i]);
6502 else {
6503 usage:
6504 printf("usage: mlogger [-e Experiment] [-d] [-D] [-s] [-v]\n\n");
6505 return 1;
6506 }
6507 }
6508 }
6509
6510 if (daemon) {
6511 printf("Becoming a daemon...\n");
6513 }
6514
6516 if (status != CM_SUCCESS)
6517 return 1;
6518
6519 /* check if logger already running */
6520 status = cm_exist("Logger", FALSE);
6521 if (status == CM_SUCCESS) {
6522 printf("Logger runs already.\n");
6524 return 1;
6525 }
6526
6528
6529 /* turn off watchdog if in debug mode */
6530 if (debug)
6532
6533 /* turn on save mode */
6534 if (save_mode) {
6537 }
6538
6539 /* register transition callbacks */
6541 cm_msg(MERROR, "main", "cannot register callbacks");
6542 return 1;
6543 }
6544
6549
6550 /* initialize ODB */
6551 logger_init();
6552
6553 /* obtain current state */
6555 size = sizeof(local_state);
6556 status = db_get_value(hDB, 0, "/Runinfo/State", &local_state, &size, TID_INT32, true);
6557
6558 /* open history logging */
6559 if (open_history() != CM_SUCCESS) {
6560 printf("Error in history system, aborting startup.\n");
6562 return 1;
6563 }
6564
6565 /* print startup message */
6566 std::string data_dir;
6567 db_get_value_string(hDB, 0, "/Logger/Data dir", 0, &data_dir, TRUE);
6568 if (data_dir.length() <= 0)
6570 printf("Data directory is \"%s\" unless specified under /Logger/channels/\n", data_dir.c_str());
6571
6572 /* Alternate message path */
6573 std::string message_dir;
6574 db_get_value_string(hDB, 0, "/Logger/Message dir", 0, &message_dir, TRUE);
6575 if (message_dir.empty()) {
6577 printf("Message directory is \"%s\" unless specified in /Logger/Message dir\n", message_dir.c_str());
6578 } else
6579 printf("Message directory is \"%s\"\n", message_dir.c_str());
6580
6581 /* Alternate History and Elog path */
6582 std::string history_dir;
6583 db_get_value_string(hDB, 0, "/Logger/History dir", 0, &history_dir, TRUE);
6584 if (history_dir.empty()) {
6586 printf("History directory is \"%s\" unless specified under /Logger/history/\n", history_dir.c_str());
6587 } else
6588 printf("History directory is \"%s\"\n", history_dir.c_str());
6589
6590#ifdef HAVE_MYSQL
6591 {
6592 std::string sql_host;
6593 std::string sql_db;
6594 std::string sql_table;
6595
6596 HNDLE hktemp;
6597 status = db_find_key(hDB, 0, "/Logger/Runlog/SQL/Hostname", &hktemp);
6598 if (status == DB_SUCCESS) {
6599 db_get_value_string(hDB, 0, "/Logger/Runlog/SQL/Hostname", 0, &sql_host, FALSE);
6600 db_get_value_string(hDB, 0, "/Logger/Runlog/SQL/Database", 0, &sql_db, FALSE);
6601 db_get_value_string(hDB, 0, "/Logger/Runlog/SQL/Table", 0, &sql_table, FALSE);
6602 printf("SQL database is %s/%s/%s", sql_host.c_str(), sql_db.c_str(), sql_table.c_str());
6603 }
6604 }
6605#endif
6606
6607 printf("\nMIDAS logger started. Stop with \"!\"\n");
6608
6609 /* initialize ss_getchar() */
6610 ss_getchar(0);
6611
6612 /* start image history threads */
6614
6615 do {
6616 msg = cm_yield(100);
6617
6618 /* maybe update channel disk levels */
6620
6621 /* update channel statistics once every second */
6622 if (ss_millitime() - last_time_stat > 1000) {
6624 /*
6625 printf("update statistics!\n");
6626 //LOG_CHN* log_chn = log_chn[0];
6627 printf("events %.0f, subrun %.0f, written %.0f, total %.0f\n", log_chn->statistics.events_written,
6628 log_chn->statistics.bytes_written_subrun,
6629 log_chn->statistics.bytes_written,
6630 log_chn->statistics.bytes_written_total);
6631 */
6633 }
6634
6635 /* check for auto restart */
6636 if (auto_restart && ss_time() > auto_restart) {
6638 }
6639
6640 /* check if time is reached to stop run */
6641 duration = 0;
6642 size = sizeof(duration);
6643 db_get_value(hDB, 0, "/Logger/Run duration", &duration, &size, TID_UINT32, true);
6645 duration > 0 && ss_time() >= run_start_time + duration) {
6646 cm_msg(MTALK, "main", "stopping run after %d seconds", duration);
6647 status = stop_the_run(1);
6648 }
6649
6650 /* stop the run if previous attempt failed */
6651 if (stop_try_later) {
6652 if (ss_time_sec() > stop_try_later) {
6653 cm_msg(MTALK, "main", "another attempt to stop the run");
6654 status = stop_the_run(0);
6655 }
6656 }
6657
6658 /* check keyboard once every 100 ms */
6659 if (ss_millitime() - last_time_kb > 100) {
6661
6662 ch = 0;
6663 while (ss_kbhit()) {
6664 ch = ss_getchar(0);
6665 if (ch == -1)
6666 ch = getchar();
6667
6668 if ((char) ch == '!')
6669 break;
6670 }
6671 }
6672
6673 } while (msg != RPC_SHUTDOWN && msg != SS_ABORT && ch != '!');
6674
6675 /* reset terminal */
6677
6678 /* close history logging */
6679 close_history();
6680
6681 /* stop image history threads */
6683 printf("Stopping image history threads...");
6684 fflush(stdout);
6686 printf("ok\n");
6687 }
6688
6690
6691 return 0;
6692}
static void usage()
INT cm_register_transition(INT transition, INT(*func)(INT, char *), INT sequence_number)
Definition midas.cxx:3615
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition midas.cxx:3025
INT cm_connect_experiment(const char *host_name, const char *exp_name, const char *client_name, void(*func)(char *))
Definition midas.cxx:2292
INT cm_get_environment(char *host_name, int host_name_size, char *exp_name, int exp_name_size)
Definition midas.cxx:2148
INT cm_set_watchdog_params(BOOL call_watchdog, DWORD timeout)
Definition midas.cxx:3297
INT cm_exist(const char *name, BOOL bUnique)
Definition midas.cxx:7542
#define SS_ABORT
Definition midas.h:677
#define RPC_SHUTDOWN
Definition midas.h:707
#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:13787
INT db_protect_database(HNDLE hDB)
Definition odb.cxx:3172
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:6278
INT tr_start_abort(INT run_number, char *error)
Definition mlogger.cxx:6249
void stop_image_history()
INT local_state
Definition mlogger.cxx:312
INT tr_pause(INT run_number, char *error)
Definition mlogger.cxx:6386
INT tr_start(INT run_number, char *error)
Definition mlogger.cxx:5939
INT tr_resume(INT run_number, char *error)
Definition mlogger.cxx:6398
int maybe_check_disk_level()
Definition mlogger.cxx:4378
DWORD auto_restart
Definition mlogger.cxx:318
int start_the_run()
Definition mlogger.cxx:4477
double stop_try_later
Definition mlogger.cxx:320
int get_number_image_history_threads()
DWORD run_start_time
Definition mlogger.cxx:319
void logger_init()
Definition mlogger.cxx:1618
void start_image_history()
Here is the call graph for this function:

◆ maybe_check_disk_level()

int maybe_check_disk_level ( )

Definition at line 4378 of file mlogger.cxx.

4379{
4381 static DWORD last_check_time = 0;
4382
4383 if (last_check_time == 0)
4385
4387 return SUCCESS;
4388
4390
4391 for (unsigned i = 0; i < log_channels.size(); i++) {
4393
4394 if (!chn->do_disk_level)
4395 continue;
4396
4398 }
4399
4400 return SUCCESS;
4401}
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 5515 of file mlogger.cxx.

5516{
5517 time_t flush_period_sec = 1; // flush once every 1 seconds
5518
5520
5521 if (verbose)
5522 printf("flush history buffers!\n");
5523
5524 for (unsigned h = 0; h < mh.size(); h++)
5525 mh[h]->hs_flush_buffers();
5526
5528 }
5529}
time_t last_history_flush
Definition mlogger.cxx:5513
Here is the call graph for this function:
Here is the caller graph for this function:

◆ new_LOG_CHN()

LOG_CHN * new_LOG_CHN ( const char name)

Definition at line 300 of file mlogger.cxx.

301{
302 LOG_CHN* chn = new LOG_CHN;
303 chn->name = name;
304 // chn->settings clear settings
305 return chn;
306};
std::string name
Definition mlogger.cxx:262
Here is the call graph for this function:
Here is the caller graph for this function:

◆ NewChecksum()

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

Definition at line 3958 of file mlogger.cxx.

3959{
3960 if (code == CHECKSUM_NONE) {
3961 return chained;
3962 } else if (code == CHECKSUM_ZLIB) {
3963 return new WriterCRC32Zlib(log_chn, level, chained);
3964 } else if (code == CHECKSUM_CRC32C) {
3965 return new WriterCRC32C(log_chn, level, chained);
3966 } else if (code == CHECKSUM_SHA256) {
3967 return new WriterSHA256(log_chn, level, chained);
3968 } else if (code == CHECKSUM_SHA512) {
3969 return new WriterSHA512(log_chn, level, chained);
3970 } else {
3971 cm_msg(MERROR, "log_create_writer", "channel %s unknown checksum code %d", log_chn->path.c_str(), code);
3972 return chained;
3973 }
3974}
#define CHECKSUM_ZLIB
Definition mlogger.cxx:3953
#define CHECKSUM_CRC32C
Definition mlogger.cxx:3954
#define CHECKSUM_SHA256
Definition mlogger.cxx:3955
#define CHECKSUM_NONE
Definition mlogger.cxx:3952
#define CHECKSUM_SHA512
Definition mlogger.cxx:3956
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 3982 of file mlogger.cxx.

3983{
3984 if (code == COMPRESS_NONE) {
3985 return chained;
3986 } else if (code == COMPRESS_LZ4) {
3987 return new WriterLZ4(log_chn, chained);
3988 } else {
3989 cm_msg(MERROR, "log_create_writer", "channel %s unknown compression code %d", log_chn->path.c_str(), code);
3990 return chained;
3991 }
3992}
#define COMPRESS_NONE
Definition mlogger.cxx:3976
#define COMPRESS_LZ4
Definition mlogger.cxx:3978
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 3918 of file mlogger.cxx.

3919{
3920 std::string bzip2_command = "bzip2 -z";
3921
3922 if (log_chn->settings.bzip2_compression) {
3923 bzip2_command += " -";
3924 bzip2_command += IntToString(log_chn->settings.bzip2_compression);
3925 }
3926
3927 return new WriterPopen(log_chn, (bzip2_command + " > ").c_str(), ".bz2");
3928}
static std::string IntToString(int value)
Definition mlogger.cxx:57
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 3930 of file mlogger.cxx.

3931{
3932 std::string pbzip2_command = "pbzip2 -c -z";
3933
3934 if (log_chn->settings.pbzip2_num_cpu) {
3935 pbzip2_command += " -p";
3936 pbzip2_command += IntToString(log_chn->settings.pbzip2_num_cpu);
3937 }
3938
3939 if (log_chn->settings.pbzip2_compression) {
3940 pbzip2_command += " -";
3941 pbzip2_command += IntToString(log_chn->settings.pbzip2_compression);
3942 }
3943
3944 if (strlen(log_chn->settings.pbzip2_options) > 0) {
3945 pbzip2_command += " ";
3946 pbzip2_command += log_chn->settings.pbzip2_options;
3947 }
3948
3949 return new WriterPopen(log_chn, (pbzip2_command + " > ").c_str(), ".bz2");
3950}
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 1800 of file mlogger.cxx.

1801{
1802 std::string path;
1803
1804 if (strchr(filename, DIR_SEPARATOR) == NULL) {
1805 db_get_value_string(hDB, 0, "/Logger/Data Dir", 0, &path, TRUE, 256);
1806 if (path.length() > 0) {
1807 if (!ends_with_char(path, DIR_SEPARATOR)) {
1808 path += DIR_SEPARATOR_STR;
1809 }
1810 }
1811 path += filename;
1812 } else {
1813 path = filename;
1814 }
1815
1816 //printf("filename [%s] path [%s]\n", filename, path.c_str());
1817
1818 DWORD t0 = ss_millitime();
1819
1820 if (ends_with_ustring(filename, ".xml"))
1821 db_save_xml(hDB, 0, path.c_str());
1822 else if (ends_with_ustring(filename, ".json"))
1823 db_save_json(hDB, 0, path.c_str());
1824 else
1825 db_save(hDB, 0, path.c_str(), FALSE);
1826
1828 chmod(path.c_str(), 0444);
1829
1830 DWORD te = ss_millitime();
1831
1832 if (verbose)
1833 printf("saved odb to \"%s\" in %d ms\n", path.c_str(), te-t0);
1834}
INT db_save_json(HNDLE hDB, HNDLE hKey, const char *filename, int flags)
Definition odb.cxx:10532
INT db_save_xml(HNDLE hDB, HNDLE hKey, const char *filename)
Definition odb.cxx:9485
INT db_save(HNDLE hDB, HNDLE hKey, const char *filename, BOOL bRemote)
Definition odb.cxx:9250
BOOL ends_with_ustring(const char *str, const char *suffix)
Definition odb.cxx:3227
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 4866 of file mlogger.cxx.

4867{
4868 INT size, index, i_tag, status, i, j, li, max_event_id;
4869 int ieq;
4870 INT n_var, n_tags, n_names = 0;
4873 TAG *tag = NULL;
4875 WORD eq_id;
4878
4879 time_t now = time(NULL);
4880
4881 double tstart = ss_time_sec();
4882
4883 // delete old history channels
4884
4885 for (unsigned i=0; i<mh.size(); i++)
4886 delete mh[i];
4887 mh.clear();
4888
4889 history_events.clear();
4890
4891 // create and initialize the history channels tree
4892
4893 status = db_find_key(hDB, 0, "/Logger/History", &hKeyHist);
4894
4895 if (status == DB_NO_KEY) {
4896 int active;
4897 std::string type;
4898 int debug;
4899
4900 // create entry for FILE history
4901
4902 type = "FILE";
4903 status = db_get_value_string(hDB, 0, "/Logger/History/FILE/Type", 0, &type, TRUE);
4904 assert(status==DB_SUCCESS);
4905
4906 active = 1;
4907 size = sizeof(active);
4908 status = db_get_value(hDB, 0, "/Logger/History/FILE/Active", &active, &size, TID_BOOL, TRUE);
4909 assert(status==DB_SUCCESS);
4910
4911 debug = 0;
4912 size = sizeof(debug);
4913 status = db_get_value(hDB, 0, "/Logger/History/FILE/Debug", &debug, &size, TID_INT32, TRUE);
4914 assert(status==DB_SUCCESS);
4915
4916 int per_variable = 1;
4917 size = sizeof(per_variable);
4918 status = db_get_value(hDB, 0, "/Logger/History/FILE/PerVariableHistory", &per_variable, &size, TID_INT32, TRUE);
4919 assert(status==DB_SUCCESS);
4920
4921 // create entry for the MIDAS history
4922
4923 type = "MIDAS";
4924 status = db_get_value_string(hDB, 0, "/Logger/History/MIDAS/Type", 0, &type, TRUE);
4925 assert(status==DB_SUCCESS);
4926
4927 active = 0;
4928 size = sizeof(active);
4929 status = db_get_value(hDB, 0, "/Logger/History/MIDAS/Active", &active, &size, TID_BOOL, TRUE);
4930 assert(status==DB_SUCCESS);
4931
4932 debug = 0;
4933 size = sizeof(debug);
4934 status = db_get_value(hDB, 0, "/Logger/History/MIDAS/Debug", &debug, &size, TID_INT32, TRUE);
4935 assert(status==DB_SUCCESS);
4936
4937 // create entry for ODBC (MySQL) history
4938
4939 type = "ODBC";
4940 status = db_get_value_string(hDB, 0, "/Logger/History/ODBC/Type", 0, &type, TRUE);
4941 assert(status==DB_SUCCESS);
4942
4943 active = 0;
4944 size = sizeof(active);
4945 status = db_get_value(hDB, 0, "/Logger/History/ODBC/Active", &active, &size, TID_BOOL, TRUE);
4946 assert(status==DB_SUCCESS);
4947
4948 debug = 0;
4949 size = sizeof(debug);
4950 status = db_get_value(hDB, 0, "/Logger/History/ODBC/Debug", &debug, &size, TID_INT32, TRUE);
4951 assert(status==DB_SUCCESS);
4952
4953 // create entry for SQLITE history
4954
4955 type = "SQLITE";
4956 status = db_get_value_string(hDB, 0, "/Logger/History/SQLITE/Type", 0, &type, TRUE);
4957 assert(status==DB_SUCCESS);
4958
4959 active = 0;
4960 size = sizeof(active);
4961 status = db_get_value(hDB, 0, "/Logger/History/SQLITE/Active", &active, &size, TID_BOOL, TRUE);
4962 assert(status==DB_SUCCESS);
4963
4964 debug = 0;
4965 size = sizeof(debug);
4966 status = db_get_value(hDB, 0, "/Logger/History/SQLITE/Debug", &debug, &size, TID_INT32, TRUE);
4967 assert(status==DB_SUCCESS);
4968
4969 // create entry for MYSQL history writer
4970
4971 type = "MYSQL";
4972 status = db_get_value_string(hDB, 0, "/Logger/History/MYSQL/Type", 0, &type, TRUE);
4973 assert(status==DB_SUCCESS);
4974
4975 active = 0;
4976 size = sizeof(active);
4977 status = db_get_value(hDB, 0, "/Logger/History/MYSQL/Active", &active, &size, TID_BOOL, TRUE);
4978 assert(status==DB_SUCCESS);
4979
4980 debug = 0;
4981 size = sizeof(debug);
4982 status = db_get_value(hDB, 0, "/Logger/History/MYSQL/Debug", &debug, &size, TID_INT32, TRUE);
4983 assert(status==DB_SUCCESS);
4984
4985 // create entry for PGSQL history writer
4986
4987 type = "PGSQL";
4988 status = db_get_value_string(hDB, 0, "/Logger/History/PGSQL/Type", 0, &type, TRUE);
4989 assert(status==DB_SUCCESS);
4990
4991 active = 0;
4992 size = sizeof(active);
4993 status = db_get_value(hDB, 0, "/Logger/History/PGSQL/Active", &active, &size, TID_BOOL, TRUE);
4994 assert(status==DB_SUCCESS);
4995
4996 debug = 0;
4997 size = sizeof(debug);
4998 status = db_get_value(hDB, 0, "/Logger/History/PGSQL/Debug", &debug, &size, TID_INT32, TRUE);
4999 assert(status==DB_SUCCESS);
5000
5001 // get newly created /Logger/History
5002
5003 status = db_find_key(hDB, 0, "/Logger/History", &hKeyHist);
5004 }
5005
5006 if (status != DB_SUCCESS) {
5007 cm_msg(MERROR, "open_history", "Something is wrong with /Logger/History, db_find_key() status %d", status);
5008 return status;
5009 }
5010
5011 // loop over history channels
5012
5013 for (int ichan = 0; ; ichan++) {
5015 if (status != DB_SUCCESS)
5016 break;
5017
5019
5021
5022 if (status==HS_SUCCESS && hi) {
5023 if (strcasecmp(hi->type, "MIDAS")==0) {
5024 i = 0;
5025 size = sizeof(i);
5026 status = db_get_value(hDB, hKey, "PerVariableHistory", &i, &size, TID_INT32, TRUE);
5027 assert(status==DB_SUCCESS);
5028
5029 if (i)
5031 } else if (strcasecmp(hi->type, "FILE")==0) {
5032 i = 0;
5033 size = sizeof(i);
5034 status = db_get_value(hDB, hKey, "PerVariableHistory", &i, &size, TID_INT32, TRUE);
5035 assert(status==DB_SUCCESS);
5036
5037 if (i)
5039 } else if (strcasecmp(hi->type, "ODBC")==0) {
5041 } else if (strcasecmp(hi->type, "SQLITE")==0) {
5043 } else if (strcasecmp(hi->type, "MYSQL")==0) {
5045 } else if (strcasecmp(hi->type, "PGSQL")==0) {
5047 }
5048
5049 if (verbose)
5050 cm_msg(MINFO, "open_history", "Writing history to channel \'%s\' type \'%s\'", hi->name, hi->type);
5051
5052 mh.push_back(hi);
5053 }
5054 }
5055
5056 // prepare history channels
5057
5058 for (unsigned i=0; i<mh.size(); i++) {
5059 status = mh[i]->hs_clear_cache();
5060 assert(status == HS_SUCCESS);
5061 }
5062
5063 // check global per-variable history settings
5064
5065 i = 0;
5066 size = sizeof(i);
5067 status = db_get_value(hDB, 0, "/History/PerVariableHistory", &i, &size, TID_INT32, FALSE);
5068 if (status==DB_SUCCESS) {
5069 cm_msg(MERROR, "open_history", "mlogger ODB setting /History/PerVariableHistory is obsolete, please delete it. Use /Logger/History/MIDAS/PerVariableHistory instead");
5070 if (i)
5072 }
5073
5075 static int previous = -1;
5078 cm_msg(MINFO, "open_history", "Per-variable history is enabled");
5079 else
5080 ;//cm_msg(MINFO, "open_history", "Per-variable history is disabled");
5081 }
5083 }
5084
5085 // setup history links
5086
5087 if (db_find_key(hDB, 0, "/History/Links", &hKeyRoot) != DB_SUCCESS ||
5088 db_find_key(hDB, 0, "/History/Links/System", &hKeyRoot) != DB_SUCCESS) {
5089 /* create default history keys */
5090 db_create_key(hDB, 0, "/History/Links", TID_KEY);
5091
5092 if (db_find_key(hDB, 0, "/Equipment/Trigger/Statistics/Events per sec.", &hKeyEq) == DB_SUCCESS)
5093 db_create_link(hDB, 0, "/History/Links/System/Trigger per sec.",
5094 "/Equipment/Trigger/Statistics/Events per sec.");
5095
5096 if (db_find_key(hDB, 0, "/Equipment/Trigger/Statistics/kBytes per sec.", &hKeyEq) == DB_SUCCESS)
5097 db_create_link(hDB, 0, "/History/Links/System/Trigger kB per sec.",
5098 "/Equipment/Trigger/Statistics/kBytes per sec.");
5099 }
5100
5101 /*---- define equipment events as history ------------------------*/
5102
5103 max_event_id = 0;
5104
5105 status = db_find_key(hDB, 0, "/Equipment", &hKeyRoot);
5106 if (status == DB_NO_KEY) {
5107 cm_msg(MINFO, "open_history", "Cannot find /Equipment entry in database, history system is inactive");
5108 return CM_SUCCESS;
5109 }
5110
5111 if (status != DB_SUCCESS) {
5112 cm_msg(MERROR, "open_history", "Cannot find /Equipment entry in database, db_find_key() status %d", status);
5113 return status;
5114 }
5115
5116 /* loop over equipment */
5117 index = 0;
5118 for (ieq = 0; ; ieq++) {
5120 if (status != DB_SUCCESS)
5121 break;
5122
5123 int32_t min_period = 0; // in seconds
5124
5125 /* retrieve min period for history logging */
5126 size = sizeof(min_period);
5127 db_get_value(hDB, hKeyEq, "Common/Log history", &min_period, &size, TID_INT32, TRUE);
5128
5129 /* define history tags only if log history flag is on */
5130 if (min_period > 0) {
5132
5133 /* get equipment name */
5135 strcpy(eq_name, key.name);
5136
5137 if (strchr(eq_name, ':'))
5138 cm_msg(MERROR, "open_history", "Equipment name \'%s\' contains characters \':\', this may break the history system", eq_name);
5139
5140 status = db_find_key(hDB, hKeyEq, "Variables", &hKeyVar);
5141 if (status != DB_SUCCESS) {
5142 cm_msg(MERROR, "open_history", "Cannot find /Equipment/%s/Variables entry in database", eq_name);
5143 return 0;
5144 }
5145
5146 size = sizeof(eq_id);
5147 status = db_get_value(hDB, hKeyEq, "Common/Event ID", &eq_id, &size, TID_UINT16, TRUE);
5148 assert(status == DB_SUCCESS);
5149
5150 size = sizeof(int);
5151 status = db_get_value(hDB, hKeyEq, "Settings/PerVariableHistory", &per_variable_history, &size, TID_INT32, FALSE);
5152 assert(status == DB_SUCCESS || status == DB_NO_KEY);
5153
5154 if (verbose)
5155 printf
5156 ("\n==================== Equipment \"%s\", ID %d =======================\n",
5157 eq_name, eq_id);
5158
5159 /* count keys in variables tree */
5160 for (n_var = 0, n_tags = 0;; n_var++) {
5161 status = db_enum_key(hDB, hKeyVar, n_var, &hKey);
5163 break;
5164 db_get_key(hDB, hKey, &key);
5165 if (key.type != TID_KEY) {
5167 }
5168 else {
5169 int ii;
5170 for (ii=0;; ii++) {
5171 KEY vvarkey;
5172 HNDLE hhKey;
5173
5176 break;
5177
5178 /* get variable key */
5180
5181 n_tags += vvarkey.num_values;
5182 }
5183 }
5184 }
5185
5186 if (n_var == 0)
5187 cm_msg(MINFO, "open_history", "Equipment \"%s\" history is enabled, but there are no Variables in ODB", eq_name);
5188
5189 /* create tag array */
5190 tag = (TAG *) calloc(sizeof(TAG), n_tags);
5191
5192 i_tag = 0;
5193 for (i=0; ; i++) {
5194 status = db_enum_key(hDB, hKeyVar, i, &hKey);
5196 break;
5197
5198 /* get variable key */
5200
5201
5202 HNDLE hKeyNames = 0;
5203 BOOL single_names = false;
5204
5205 /* look for names */
5206
5207 if (!hKeyNames) {
5208 sprintf(str, "Settings/Names %s", varkey.name);
5210 if (hKeyNames) {
5211 if (verbose)
5212 printf("Using \"/Equipment/%s/Settings/Names %s\" for variable \"%s\"\n", eq_name, varkey.name, varkey.name);
5213
5214 /* define tags from names list */
5217 }
5218 }
5219
5220 if (!hKeyNames) {
5221 db_find_key(hDB, hKeyEq, "Settings/Names", &hKeyNames);
5222 single_names = (hKeyNames > 0);
5223
5224 if (hKeyNames) {
5225 if (verbose)
5226 printf("Using \"/Equipment/%s/Settings/Names\" for variable \"%s\"\n", eq_name, varkey.name);
5227
5228 /* define tags from names list */
5231 }
5232 }
5233
5234 if (hKeyNames && n_names < varkey.num_values) {
5235 cm_msg(MERROR, "open_history",
5236 "Array size mismatch: \"/Equipment/%s/Settings/%s\" has %d entries while \"/Equipment/%s/Variables/%s\" has %d entries",
5238 eq_name, varkey.name, varkey.num_values);
5239 free(tag);
5240 return 0;
5241 }
5242
5243 if (hKeyNames) {
5244 /* loop over array elements */
5245 for (j = 0; j < varkey.num_values; j++) {
5246 char xname[256];
5247
5248 tag[i_tag].name[0] = 0;
5249
5250 /* get name #j */
5251 size = sizeof(xname);
5253 if (status == DB_SUCCESS)
5254 mstrlcpy(tag[i_tag].name, xname, sizeof(tag[i_tag].name));
5255
5256 if (strlen(tag[i_tag].name) < 1) {
5257 char buf[256];
5258 sprintf(buf, "%d", j);
5259 mstrlcpy(tag[i_tag].name, varkey.name, NAME_LENGTH);
5260 mstrlcat(tag[i_tag].name, "_", NAME_LENGTH);
5261 mstrlcat(tag[i_tag].name, buf, NAME_LENGTH);
5262 }
5263
5264 /* append variable key name for single name array */
5265 if (single_names) {
5266 if (strlen(tag[i_tag].name) + 1 + strlen(varkey.name) >= NAME_LENGTH) {
5267 cm_msg(MERROR, "open_history",
5268 "Name for history entry \"%s %s\" too long", tag[i_tag].name, varkey.name);
5269 free(tag);
5270 return 0;
5271 }
5272 mstrlcat(tag[i_tag].name, " ", NAME_LENGTH);
5273 mstrlcat(tag[i_tag].name, varkey.name, NAME_LENGTH);
5274 }
5275
5276 tag[i_tag].type = varkey.type;
5277 tag[i_tag].n_data = 1;
5278
5279 if (verbose)
5280 printf("Defined tag %d, name \"%s\", type %d, num_values %d\n",
5281 i_tag, tag[i_tag].name, tag[i_tag].type, tag[i_tag].n_data);
5282
5283 i_tag++;
5284 }
5285 } else if (varkey.type == TID_KEY) {
5286 int ii;
5287 for (ii=0;; ii++) {
5288 KEY vvarkey;
5289 HNDLE hhKey;
5290
5293 break;
5294
5295 /* get variable key */
5297
5298 mstrlcpy(tag[i_tag].name, varkey.name, NAME_LENGTH);
5299 mstrlcat(tag[i_tag].name, "_", NAME_LENGTH);
5300 mstrlcat(tag[i_tag].name, vvarkey.name, NAME_LENGTH);
5301 tag[i_tag].type = vvarkey.type;
5302 tag[i_tag].n_data = vvarkey.num_values;
5303
5304 if (verbose)
5305 printf("Defined tag %d, name \"%s\", type %d, num_values %d\n", i_tag, tag[i_tag].name,
5306 tag[i_tag].type, tag[i_tag].n_data);
5307
5308 i_tag++;
5309 }
5310 } else {
5311 mstrlcpy(tag[i_tag].name, varkey.name, NAME_LENGTH);
5312 tag[i_tag].type = varkey.type;
5313 tag[i_tag].n_data = varkey.num_values;
5314
5315 if (verbose)
5316 printf("Defined tag %d, name \"%s\", type %d, num_values %d\n", i_tag, tag[i_tag].name,
5317 tag[i_tag].type, tag[i_tag].n_data);
5318
5319 i_tag++;
5320 }
5321
5322 if (per_variable_history && i_tag>0) {
5323 WORD event_id = 0;
5324 char event_name[NAME_LENGTH];
5325
5326 mstrlcpy(event_name, eq_name, NAME_LENGTH);
5327 mstrlcat(event_name, "/", NAME_LENGTH);
5328 mstrlcat(event_name, varkey.name, NAME_LENGTH);
5329
5330 assert(i_tag <= n_tags);
5331
5332 status = add_event(&index, now, event_id, event_name, hKey, i_tag, tag, min_period, 1);
5333 if (status != DB_SUCCESS)
5334 return status;
5335
5336 i_tag = 0;
5337 } /* if per-variable history */
5338
5339 } /* loop over variables */
5340
5341 if (!per_variable_history && i_tag>0) {
5342 assert(i_tag <= n_tags);
5343
5344 status = add_event(&index, now, eq_id, eq_name, hKeyVar, i_tag, tag, min_period, 1);
5345 if (status != DB_SUCCESS)
5346 return status;
5347
5348 }
5349
5350 if (tag) {
5351 free(tag);
5352 tag = NULL;
5353 }
5354
5355 /* remember maximum event id for later use with system events */
5356 if (eq_id > max_event_id)
5358 }
5359 } /* loop over equipments */
5360
5361 /*---- define linked trees --------------------------------------*/
5362
5363 /* round up event id */
5364 max_event_id = ((int) ((max_event_id + 1) / 10) + 1) * 10;
5365
5366 status = db_find_key(hDB, 0, "/History/Links", &hKeyRoot);
5367 if (status == DB_SUCCESS) {
5368 for (li = 0;; li++) {
5371 break;
5372
5374 strcpy(hist_name, histkey.name);
5376
5378 if (key.type != TID_KEY) {
5379 cm_msg(MERROR, "open_history", "Only subkeys allows in /History/Links, key \"%s\"", key.name);
5380 continue;
5381 }
5382
5383 if (verbose)
5384 printf("\n==================== History link \"%s\", ID %d =======================\n",
5386
5387 /* count subkeys in link */
5388 for (i = n_var = 0;; i++) {
5391 break;
5392
5393 if (status == DB_SUCCESS && db_get_key(hDB, hKey, &key) == DB_SUCCESS) {
5394 if (key.type != TID_KEY)
5395 n_var++;
5396 } else {
5398 db_get_key(hDB, hKey, &key);
5399 cm_msg(MERROR, "open_history",
5400 "History link /History/Links/%s/%s is invalid", hist_name, key.name);
5401 return 0;
5402 }
5403 }
5404
5405 if (n_var == 0)
5406 cm_msg(MERROR, "open_history", "History event %s has no variables in ODB", hist_name);
5407 else {
5408 /* create tag array */
5409 tag = (TAG *) calloc(sizeof(TAG), n_var);
5410
5411 assert(tag != NULL);
5412
5413 for (i = 0, size = 0, n_var = 0;; i++) {
5416 break;
5417
5418 /* get link key */
5420
5421 if (linkkey.type == TID_KEY)
5422 continue;
5423
5424 /* get link target */
5426 if (db_get_key(hDB, hVarKey, &varkey) == DB_SUCCESS) {
5427 /* hot-link individual values */
5428 if (histkey.type == TID_KEY) {
5429 db_close_record(hDB, hVarKey); // close previously opened record
5431 (void *) (POINTER_T) index);
5432 }
5433
5434 strcpy(tag[n_var].name, linkkey.name);
5435 tag[n_var].type = varkey.type;
5436 tag[n_var].n_data = varkey.num_values;
5437
5438 if (verbose)
5439 printf("Defined tag \"%s\", type %d, num_values %d\n",
5440 tag[n_var].name, tag[n_var].type, tag[n_var].n_data);
5441
5442 size += varkey.total_size;
5443 n_var++;
5444 }
5445 }
5446
5447 /* hot-link whole subtree */
5448 if (histkey.type == TID_LINK) {
5449 db_close_record(hDB, hHistKey); // close previously opened record
5451 }
5452
5453 status = add_event(&index, now, max_event_id, hist_name, hHistKey, n_var, tag, 0, 0);
5454 if (status != DB_SUCCESS)
5455 return status;
5456
5457 free(tag);
5458 tag = NULL;
5459
5460 max_event_id++;
5461 }
5462 }
5463 }
5464
5465 /*---- define run start/stop event ------------------------------*/
5466
5467 tag = (TAG *) calloc(sizeof(TAG), 2);
5468
5469 assert(tag != NULL);
5470
5471 strcpy(tag[0].name, "State");
5472 tag[0].type = TID_UINT32;
5473 tag[0].n_data = 1;
5474
5475 strcpy(tag[1].name, "Run number");
5476 tag[1].type = TID_UINT32;
5477 tag[1].n_data = 1;
5478
5479 const char* event_name = "Run transitions";
5480
5481 for (unsigned i=0; i<mh.size(); i++) {
5482 status = mh[i]->hs_define_event(event_name, now, 2, tag);
5483 if (status != HS_SUCCESS) {
5484 cm_msg(MERROR, "add_event", "Cannot define event \"%s\", hs_define_event() status %d", event_name, status);
5485 return 0;
5486 }
5487 }
5488
5489 history_events.push_back(event_name);
5490
5491 free(tag);
5492 tag = NULL;
5493
5494 /* outcommented not to produce a log entry on every run
5495 cm_msg(MINFO, "open_history", "Configured history with %d events", count_events);
5496 */
5497
5499 if (status != HS_SUCCESS)
5500 return status;
5501
5502 double tend = ss_time_sec();
5503 double telapsed = tend - tstart;
5504 if (telapsed > 10.0) {
5505 cm_msg(MERROR, "open_history", "open_history() took %.3f seconds", telapsed);
5506 }
5507
5508 return CM_SUCCESS;
5509}
#define DB_NO_KEY
Definition midas.h:642
#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:6898
INT db_enum_link(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition odb.cxx:5730
#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:5623
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:4749
INT num_values
Definition midas.h:1028
Definition midas.h:1232
DWORD type
Definition midas.h:1234
DWORD n_data
Definition midas.h:1235
char name[NAME_LENGTH]
Definition midas.h:1233
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 6412 of file mlogger.cxx.

6413{
6414 if (verbose)
6415 printf("write data event: req %d, evid %d, timestamp %d, size %d\n", request_id, pheader->event_id, pheader->time_stamp, pheader->data_size);
6416
6417 /* find logging channel for this request id */
6418 for (unsigned i = 0; i < log_channels.size(); i++) {
6420 if (chn->handle == 0 && chn->ftp_con == NULL)
6421 continue;
6422
6423 /* write normal events */
6424 if (chn->request_id == request_id) {
6425 log_write(chn, pheader);
6426 break;
6427 }
6428
6429 /* write messages */
6430 if (chn->msg_request_id == request_id) {
6431 log_write(chn, pheader);
6432 break;
6433 }
6434 }
6435}
short int event_id
Definition midas.h:852
DWORD data_size
Definition midas.h:856
DWORD time_stamp
Definition midas.h:855
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 4033 of file mlogger.cxx.

4034{
4035 std::string val = get_value(hDB, hSet, name);
4036 std::string sel;
4037 std::string def;
4038 int s = 0;
4039 s = check_add(s, CHECKSUM_NONE, val, "NONE", false, &def, &sel);
4040 s = check_add(s, CHECKSUM_CRC32C, val, "CRC32C", true, &def, &sel);
4041 s = check_add(s, CHECKSUM_SHA256, val, "SHA256", false, &def, &sel);
4042 s = check_add(s, CHECKSUM_SHA512, val, "SHA512", false, &def, &sel);
4043 s = check_add(s, CHECKSUM_ZLIB, val, "ZLIB", false, &def, &sel);
4044 if (sel == "")
4045 sel = "NONE";
4046 //set_value(hDB, hSet, name, sel, def);
4047 return s;
4048}
std::string get_value(HNDLE hDB, HNDLE hDir, const char *name)
Definition mlogger.cxx:4001
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:4021
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 4050 of file mlogger.cxx.

4051{
4052 std::string val = get_value(hDB, hSet, name);
4053 std::string sel;
4054 std::string def;
4055 int s = 0;
4056 s = check_add(s, COMPRESS_NONE, val, "none", false, &def, &sel);
4057 s = check_add(s, COMPRESS_ZLIB, val, "gzip", true, &def, &sel);
4058 s = check_add(s, COMPRESS_LZ4, val, "lz4", false, &def, &sel);
4059 s = check_add(s, COMPRESS_BZIP2, val, "bzip2", false, &def, &sel);
4060 s = check_add(s, COMPRESS_PBZIP2, val, "pbzip2", false, &def, &sel);
4061 if (sel == "")
4062 sel = "none";
4063 //set_value(hDB, hSet, name, sel, def);
4064 return s;
4065}
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 4067 of file mlogger.cxx.

4068{
4069 std::string val = get_value(hDB, hSet, name);
4070 std::string sel;
4071 std::string def;
4072 int s = 0;
4073 s = check_add(s, OUTPUT_NULL, val, "NULL", false, &def, &sel);
4074 s = check_add(s, OUTPUT_FILE, val, "FILE", true, &def, &sel);
4075 s = check_add(s, OUTPUT_FTP, val, "FTP", false, &def, &sel);
4076 s = check_add(s, OUTPUT_ROOT, val, "ROOT", false, &def, &sel);
4077 s = check_add(s, OUTPUT_PIPE, val, "PIPE", false, &def, &sel);
4078 if (sel == "")
4079 sel = "FILE";
4080 //set_value(hDB, hSet, name, sel, def);
4081 return s;
4082}
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 4012 of file mlogger.cxx.

4013{
4014 std::string s = set + " (one of:" + def + ")";
4015 int size = 256; // MUST match record definition // strlen(value);
4016 s.reserve(size);
4017 const char* value = s.c_str();
4018 db_set_value(hDB, hDir, name, value, size, 1, TID_STRING);
4019}
#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 4477 of file mlogger.cxx.

4478{
4479 int status, size, state, run_number, flag;
4480 char errstr[256];
4481
4483 auto_restart = 0;
4484
4485 /* check if autorestart is still on */
4486 size = sizeof(BOOL);
4487 flag = FALSE;
4488 db_get_value(hDB, 0, "/Logger/Auto restart", &flag, &size, TID_BOOL, TRUE);
4489
4490 if (!flag) {
4491 cm_msg(MINFO, "start_the_run", "Run auto restart canceled");
4492 return SUCCESS;
4493 }
4494
4495 /* check if really stopped */
4496 size = sizeof(state);
4497 status = db_get_value(hDB, 0, "Runinfo/State", &state, &size, TID_INT32, TRUE);
4498 if (status != DB_SUCCESS) {
4499 cm_msg(MERROR, "start_the_run", "cannot get Runinfo/State in database, db_get_value() status %d", status);
4500 return status;
4501 }
4502
4503 static int backoff = 1;
4504
4505 if (state != STATE_STOPPED) {
4506 cm_msg(MINFO, "start_the_run", "Runinfo/State %d is not STATE_STOPPED, will try again in %d seconds", state, backoff);
4507 auto_restart = ss_time() + backoff; /* try again later */
4508 if (backoff < 1)
4509 backoff = 1;
4510 else if (backoff > 1*60)
4511 backoff = 1*60;
4512 else
4513 backoff *= 2;
4514 return SUCCESS;
4515 }
4516
4517 backoff = 1;
4518
4519 size = sizeof(run_number);
4520 status = db_get_value(hDB, 0, "/Runinfo/Run number", &run_number, &size, TID_INT32, TRUE);
4521 assert(status == SUCCESS);
4522
4523 if (run_number <= 0) {
4524 cm_msg(MERROR, "start_the_run", "aborting on attempt to use invalid run number %d", run_number);
4525 abort();
4526 }
4527
4528 int trans_flag = get_trans_flag();
4529
4530 cm_msg(MTALK, "start_the_run", "starting new run");
4531 status = cm_transition(TR_START, run_number + 1, errstr, sizeof(errstr), trans_flag, verbose);
4532 if (status != CM_SUCCESS)
4533 cm_msg(MERROR, "start_the_run", "cannot restart run: cm_transition() status %d, error: %s", status, errstr);
4534
4535 return status;
4536}
INT cm_transition(INT transition, INT run_number, char *errstr, INT errstr_size, INT async_flag, INT debug_flag)
Definition midas.cxx:5308
static int get_trans_flag()
Definition mlogger.cxx:4403
BOOL start_requested
Definition mlogger.cxx:317
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 4443 of file mlogger.cxx.

4444{
4445 int status, flag, size;
4446 char errstr[256];
4447
4448 if (restart) {
4449 size = sizeof(BOOL);
4450 flag = FALSE;
4451 db_get_value(hDB, 0, "/Logger/Auto restart", &flag, &size, TID_BOOL, TRUE);
4452
4453 if (flag) {
4455 auto_restart = 0;
4456 }
4457 }
4458
4460 stop_try_later = 0;
4461
4462 int trans_flag = get_trans_flag();
4463
4464 status = cm_transition(TR_STOP, 0, errstr, sizeof(errstr), trans_flag, verbose);
4466 cm_msg(MERROR, "stop_the_run", "another transition is in progress, will try again later");
4468 stop_try_later = ss_time_sec() + 10.0;
4469 } else if (status != CM_SUCCESS) {
4470 cm_msg(MERROR, "stop_the_run", "cannot stop the run, cm_transition() status %d, error: %s", status, errstr);
4471 return status;
4472 }
4473
4474 return status;
4475}
#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 64 of file mlogger.cxx.

65{
66 const char* sign = "";
67
68 if (t == 0)
69 return "0";
70
71 time_t tt = t;
72
73 if (t < 0) {
74 sign = "-";
75 tt = -t;
76 }
77
78 assert(tt > 0);
79
80 std::string v;
81 while (tt) {
82 char c = '0' + tt%10;
83 tt /= 10;
84 v = c + v;
85 }
86
87 v = sign + v;
88
89 //printf("time %.0f -> %s\n", (double)t, v.c_str());
90
91 return v;
92}
char c
Definition system.cxx:1312
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tr_pause()

INT tr_pause ( INT  run_number,
char error 
)

Definition at line 6386 of file mlogger.cxx.

6387{
6388 /* write transition event into history */
6390
6392
6394
6395 return CM_SUCCESS;
6396}
#define STATE_PAUSED
Definition midas.h:306
INT cm_msg_flush_buffer()
Definition midas.cxx:879
static int write_history(DWORD transition, DWORD run_number)
Definition mlogger.cxx:5905
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 6398 of file mlogger.cxx.

6399{
6400 /* write transition event into history */
6402
6404
6406
6407 return CM_SUCCESS;
6408}
#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 5939 of file mlogger.cxx.

5952{
5953 INT size, status;
5956 KEY key;
5958 HNDLE hDB;
5959
5960 if (verbose)
5961 printf("tr_start: run %d\n", run_number);
5962
5963 DWORD t0 = ss_millitime();
5964
5966
5967 /* save current ODB */
5968 std::string str = "last.json";
5969 db_get_value_string(hDB, 0, "/Logger/ODB Last Dump File", 0, &str, TRUE);
5970 odb_save(str.c_str(), false);
5971
5972 DWORD t1 = ss_millitime();
5973
5975
5977 close_buffers();
5978
5979 DWORD t2 = ss_millitime();
5980
5982
5984
5985 /* read global logging flag */
5986 size = sizeof(BOOL);
5987 write_data = TRUE;
5988 db_get_value(hDB, 0, "/Logger/Write data", &write_data, &size, TID_BOOL, TRUE);
5989
5990 /* read tape message flag */
5991 size = sizeof(tape_message);
5992 db_get_value(hDB, 0, "/Logger/Tape message", &tape_message, &size, TID_BOOL, TRUE);
5993
5994 /* reset next subrun flag */
5995 status = FALSE;
5996 db_set_value(hDB, 0, "/Logger/Next subrun", &status, sizeof(status), 1, TID_BOOL);
5997
5998 /* loop over all channels */
5999 status = db_find_key(hDB, 0, "/Logger/Channels", &hKeyRoot);
6000 if (status != DB_SUCCESS) {
6001 /* if no channels are defined, define at least one */
6002 status = db_create_record(hDB, 0, "/Logger/Channels/0/", strcomb1(chn_tree_str).c_str());
6003 if (status != DB_SUCCESS) {
6004 strcpy(error, "Cannot create channel entry in database");
6005 cm_msg(MERROR, "tr_start", "%s", error);
6006 return 0;
6007 }
6008
6009 status = db_find_key(hDB, 0, "/Logger/Channels", &hKeyRoot);
6010 if (status != DB_SUCCESS) {
6011 strcpy(error, "Cannot create channel entry in database");
6012 cm_msg(MERROR, "tr_start", "%s", error);
6013 return 0;
6014 }
6015 }
6016
6017 // after close_buffers() all log channels are closed and deleted
6018 assert(log_channels.size() == 0);
6019
6020 for (unsigned index = 0; ; index++) {
6023 break;
6024
6025 /* correct channel record */
6028 if (status != DB_SUCCESS && status != DB_OPEN_RECORD) {
6029 cm_msg(MERROR, "tr_start", "Cannot create/check channel record, status %d", status);
6030 break;
6031 }
6032
6033 if (status == DB_SUCCESS || status == DB_OPEN_RECORD) {
6035
6036 log_channels.push_back(chn);
6037
6038 /* save settings key */
6039 status = db_find_key(hDB, hKeyChannel, "Settings", &chn->settings_hkey);
6040 if (status != DB_SUCCESS) {
6041 strcpy(error, "Cannot find channel settings info");
6042 cm_msg(MERROR, "tr_start", "%s", error);
6043 return 0;
6044 }
6045
6046 /* save statistics key */
6047 status = db_find_key(hDB, hKeyChannel, "Statistics", &chn->stats_hkey);
6048 if (status != DB_SUCCESS) {
6049 strcpy(error, "Cannot find channel statistics info");
6050 cm_msg(MERROR, "tr_start", "%s", error);
6051 return 0;
6052 }
6053
6054 /* clear statistics */
6055 size = sizeof(CHN_STATISTICS);
6056 db_get_record1(hDB, chn->stats_hkey, &chn->statistics, &size, 0, strcomb1(chn_statistics_str).c_str());
6057
6058 chn->statistics.events_written = 0;
6059 chn->statistics.bytes_written = 0;
6060 chn->statistics.bytes_written_uncompressed = 0;
6061 chn->statistics.bytes_written_subrun = 0;
6062
6063 db_set_record(hDB, chn->stats_hkey, &chn->statistics, size, 0);
6064
6065 /* get channel info structure */
6066 chn_settings = &chn->settings;
6067 size = sizeof(CHN_SETTINGS);
6068 status = db_get_record1(hDB, chn->settings_hkey, chn_settings, &size, 0, strcomb1(chn_settings_str).c_str());
6069 if (status != DB_SUCCESS) {
6070 strcpy(error, "Cannot read channel info");
6071 cm_msg(MERROR, "tr_start", "%s", error);
6072 return 0;
6073 }
6074
6075 chn->pre_checksum_module = select_checksum_module(hDB, chn->settings_hkey, "data checksum");
6076 chn->post_checksum_module = select_checksum_module(hDB, chn->settings_hkey, "file checksum");
6077 chn->compression_module = select_compression_module(hDB, chn->settings_hkey, "compress");
6078 chn->output_module = select_output_module(hDB, chn->settings_hkey, "output");
6079
6080 //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);
6081
6082 /* check if active */
6083 if (!chn_settings->active || !write_data)
6084 continue;
6085
6086#ifdef OBSOLETE
6087 /* check for type */
6088 if (equal_ustring(chn_settings->type, "FTP"))
6089 chn->type = LOG_TYPE_FTP;
6090 else if (equal_ustring(chn_settings->type, "Disk"))
6091 chn->type = LOG_TYPE_DISK;
6092 else {
6093 sprintf(error, "Invalid channel type \"%s\", pease use \"Tape\", \"FTP\" or \"Disk\"", chn_settings->type);
6094 cm_msg(MERROR, "tr_start", "%s", error);
6095 return 0;
6096 }
6097#endif
6098
6099#ifdef OBSOLETE
6100 /* set compression level */
6101 chn->compression = 0;
6102 size = sizeof(chn->compression);
6103 status = db_get_value(hDB, chn->settings_hkey, "Compression", &chn->compression, &size, TID_INT32, FALSE);
6104#endif
6105
6106 /* initialize subrun number */
6107 chn->subrun_number = 0;
6108
6111
6112 /* open logging channel */
6114
6115 /* return if logging channel couldn't be opened */
6116 if (status != SS_SUCCESS) {
6117 if (status == SS_FILE_ERROR)
6118 sprintf(error, "Cannot open file \'%s\' (See messages)", chn->path.c_str());
6119 if (status == SS_FILE_EXISTS)
6120 sprintf(error, "File \'%s\' exists already, run start aborted", chn->path.c_str());
6121 if (status == SS_NO_TAPE)
6122 sprintf(error, "No tape in device \'%s\'", chn->path.c_str());
6123 if (status == SS_TAPE_ERROR)
6124 sprintf(error, "Tape error, cannot start run");
6125 if (status == SS_DEV_BUSY)
6126 sprintf(error, "Device \'%s\' used by someone else", chn->path.c_str());
6128 sprintf(error, "Cannot open FTP channel to \'%s\'", chn->path.c_str());
6129 if (status == SS_NO_ROOT)
6130 sprintf(error, "No ROOT support compiled into mlogger, please compile with -DHAVE_ROOT flag");
6131
6133 sprintf(error, "Invalid data format, please use \"MIDAS\", \"ASCII\", \"DUMP\" or \"ROOT\"");
6134
6135 cm_msg(MERROR, "tr_start", "%s", error);
6136 return 0;
6137 }
6138
6139 /* close records if open from previous run start with abort */
6140 if (chn->stats_hkey)
6141 db_close_record(hDB, chn->stats_hkey);
6142 if (chn->settings_hkey)
6143 db_close_record(hDB, chn->settings_hkey);
6144
6145 /* open hot link to statistics tree */
6146 status = db_open_record1(hDB, chn->stats_hkey, &chn->statistics, sizeof(CHN_STATISTICS), MODE_WRITE, NULL, NULL, strcomb1(chn_statistics_str).c_str());
6147 if (status == DB_NO_ACCESS) {
6148 /* record is probably still in exclusive access by dead logger, so reset it */
6150 if (status != DB_SUCCESS)
6151 cm_msg(MERROR, "tr_start", "Cannot change access mode for statistics record, error %d", status);
6152 else
6153 cm_msg(MINFO, "tr_start", "Recovered access mode for statistics record of channel \"%s\"", chn->name.c_str());
6154 status = db_open_record1(hDB, chn->stats_hkey, &chn->statistics, sizeof(CHN_STATISTICS), MODE_WRITE, NULL, NULL, strcomb1(chn_statistics_str).c_str());
6155 }
6156
6157 if (status != DB_SUCCESS)
6158 cm_msg(MERROR, "tr_start", "Cannot open statistics record for channel \"%s\", error %d", chn->name.c_str(), status);
6159
6160 /* open hot link to settings tree */
6161 status = db_watch(hDB, chn->settings_hkey, watch_settings, chn);
6162 if (status != DB_SUCCESS)
6163 cm_msg(MERROR, "tr_start", "db_watch() status %d, cannot open channel settings record, probably other logger is using it", status);
6164
6165#ifndef FAL_MAIN
6166 /* open buffer */
6167 status = bm_open_buffer(chn_settings->buffer, DEFAULT_BUFFER_SIZE, &chn->buffer_handle);
6168 if (status != BM_SUCCESS && status != BM_CREATED) {
6169 sprintf(error, "Cannot open buffer %s", chn_settings->buffer);
6170 cm_msg(MERROR, "tr_start", "%s", error);
6171 return 0;
6172 }
6173 bm_set_cache_size(chn->buffer_handle, 1000000, 0);
6174
6175 /* place event request */
6176 status = bm_request_event(chn->buffer_handle, (short) chn_settings->event_id, (short) chn_settings->trigger_mask, GET_ALL, &chn->request_id, receive_event);
6177
6178 if (status != BM_SUCCESS) {
6179 sprintf(error, "Cannot place event request");
6180 cm_msg(MERROR, "tr_start", "%s", error);
6181 return 0;
6182 }
6183
6184 /* open message buffer if requested */
6185 if (chn_settings->log_messages) {
6186 status = bm_open_buffer((char*)MESSAGE_BUFFER_NAME, MESSAGE_BUFFER_SIZE, &chn->msg_buffer_handle);
6187 if (status != BM_SUCCESS && status != BM_CREATED) {
6188 sprintf(error, "Cannot open buffer %s", MESSAGE_BUFFER_NAME);
6189 cm_msg(MERROR, "tr_start", "%s", error);
6190 return 0;
6191 }
6192
6193 /* place event request */
6194 status = bm_request_event(chn->msg_buffer_handle, (short) EVENTID_MESSAGE, (short) chn_settings->log_messages, GET_ALL, &chn->msg_request_id, receive_event);
6195
6196 if (status != BM_SUCCESS) {
6197 sprintf(error, "Cannot place event request");
6198 cm_msg(MERROR, "tr_start", "%s", error);
6199 return 0;
6200 }
6201 }
6202#endif
6203 }
6204 }
6205
6206 DWORD t3 = ss_millitime();
6207
6208 if (tape_flag && tape_message)
6209 cm_msg(MTALK, "tr_start", "tape mounting finished");
6210
6211 /* write transition event into history */
6213
6214 DWORD t4 = ss_millitime();
6215
6216#ifdef HAVE_MYSQL
6217 /* write to SQL database if requested */
6219#endif
6220
6221 /* write to runlog file(s) if requested */
6224
6225 DWORD t5 = ss_millitime();
6226 DWORD te = t5;
6227
6228 if (verbose)
6229 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",
6230 run_number,
6231 te-t0,
6232 t1-t0,
6233 t2-t1,
6234 t3-t2,
6235 t4-t3,
6236 t5-t4
6237 );
6238
6241
6243
6244 return CM_SUCCESS;
6245}
#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:6739
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:8487
INT bm_set_cache_size(INT buffer_handle, size_t read_size, size_t write_size)
Definition midas.cxx:8162
#define BM_SUCCESS
Definition midas.h:605
#define BM_CREATED
Definition midas.h:606
#define DB_NO_ACCESS
Definition midas.h:648
#define SS_TAPE_ERROR
Definition midas.h:682
#define SS_FILE_EXISTS
Definition midas.h:686
#define SS_NO_TAPE
Definition midas.h:679
#define SS_DEV_BUSY
Definition midas.h:680
#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
#define LOG_TYPE_FTP
Definition msystem.h:502
INT db_get_record1(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT align, const char *rec_str)
Definition odb.cxx:11812
INT db_set_mode(HNDLE hDB, HNDLE hKey, WORD mode, BOOL recurse)
Definition odb.cxx:8032
INT db_watch(HNDLE hDB, HNDLE hKey, void(*dispatcher)(INT, INT, INT, void *), void *info)
Definition odb.cxx:13823
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:13451
#define DEFAULT_BUFFER_SIZE
Definition midas.h:255
#define EVENTID_MESSAGE
Definition midas.h:902
int select_compression_module(HNDLE hDB, HNDLE hSet, const char *name)
Definition mlogger.cxx:4050
void receive_event(HNDLE hBuf, HNDLE request_id, EVENT_HEADER *pheader, void *pevent)
Definition mlogger.cxx:6412
int select_checksum_module(HNDLE hDB, HNDLE hSet, const char *name)
Definition mlogger.cxx:4033
void odb_save(const char *filename, bool make_file_readonly)
Definition mlogger.cxx:1800
BOOL tape_message
Definition mlogger.cxx:314
int select_output_module(HNDLE hDB, HNDLE hSet, const char *name)
Definition mlogger.cxx:4067
static void watch_settings(HNDLE hDB, HNDLE hKey, HNDLE index, void *info)
Definition mlogger.cxx:5921
LOG_CHN * new_LOG_CHN(const char *name)
Definition mlogger.cxx:300
int close_buffers()
Definition mlogger.cxx:5877
void write_runlog_json(BOOL bor)
Definition mlogger.cxx:2698
void write_runlog_ascii(BOOL bor)
Definition mlogger.cxx:2537
int close_channels(int run_number, BOOL *p_tape_flag)
Definition mlogger.cxx:5832
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 6249 of file mlogger.cxx.

6250{
6251 if (verbose)
6252 printf("tr_start_abort: run %d\n", run_number);
6253
6255
6256 for (unsigned i = 0; i < log_channels.size(); i++) {
6258 if (chn->handle && chn->type == LOG_TYPE_DISK) {
6259 cm_msg(MINFO, "tr_start_abort", "Deleting previous file \"%s\"", chn->path.c_str());
6260 unlink(chn->path.c_str());
6261 }
6262 }
6263
6265 close_buffers();
6266
6268
6270
6272
6273 return CM_SUCCESS;
6274}
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 6278 of file mlogger.cxx.

6286{
6287 INT size;
6289 char filename[256];
6290 char str[256];
6291
6292 if (verbose)
6293 printf("tr_stop: run %d\n", run_number);
6294
6296 return CM_SUCCESS;
6297
6298 DWORD t0 = ss_millitime();
6299
6301
6303 close_buffers();
6304
6305 DWORD t1 = ss_millitime();
6306
6307 /* ODB dump if requested */
6308 size = sizeof(flag);
6309 flag = 0;
6310 db_get_value(hDB, 0, "/Logger/ODB Dump", &flag, &size, TID_BOOL, TRUE);
6311 if (flag) {
6312 strcpy(str, "run%d.json");
6313 size = sizeof(str);
6314 str[0] = 0;
6315 db_get_value(hDB, 0, "/Logger/ODB Dump File", str, &size, TID_STRING, TRUE);
6316 if (str[0] == 0)
6317 strcpy(str, "run%d.json");
6318
6319 /* substitue "%d" by current run number */
6320 if (strchr(str, '%'))
6321 sprintf(filename, str, run_number);
6322 else
6323 strcpy(filename, str);
6324
6325 odb_save(filename, true);
6326 }
6327
6328 DWORD t2 = ss_millitime();
6329
6330#ifdef HAVE_MYSQL
6331 /* write to SQL database if requested */
6333#endif
6334
6335 /* write to ASCII file(s) if requested */
6338
6339 DWORD t3 = ss_millitime();
6340
6342
6343 if (tape_flag & tape_message)
6344 cm_msg(MTALK, "tr_stop", "all tape channels closed");
6345
6346 /* write transition event into history */
6348
6349 DWORD t4 = ss_millitime();
6350
6351 /* clear flag */
6353 stop_try_later = 0;
6354
6355 if (start_requested) {
6356 int delay = 0;
6357 size = sizeof(delay);
6358 db_get_value(hDB, 0, "/Logger/Auto restart delay", &delay, &size, TID_INT32, TRUE);
6359 auto_restart = ss_time() + delay; /* start after specified delay */
6361 }
6362
6363 DWORD te = t4;
6364
6365 if (verbose)
6366 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",
6367 run_number,
6368 te-t0,
6369 t1-t0,
6370 t2-t1,
6371 t3-t2,
6372 t4-t3);
6373
6374
6376
6378
6379 return CM_SUCCESS;
6380}
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 5921 of file mlogger.cxx.

5922{
5923 int status;
5924 assert(info != NULL);
5926 int size = sizeof(CHN_SETTINGS);
5927 status = db_get_record1(hDB, log_chn->settings_hkey, &log_chn->settings, &size, 0, strcomb1(chn_settings_str).c_str());
5928 if (status != DB_SUCCESS) {
5929 cm_msg(MINFO, "watch_settings", "db_get_record(%s) status %d", log_chn->name.c_str(), status);
5930 return;
5931 }
5932
5933 if (verbose)
5934 printf("Channel %s settings updated\n", log_chn->name.c_str());
5935}
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 5905 of file mlogger.cxx.

5906{
5907 DWORD eb[2];
5908 eb[0] = transition;
5909 eb[1] = run_number;
5910
5911 time_t now = time(NULL);
5912
5913 for (unsigned h=0; h<mh.size(); h++)
5914 mh[h]->hs_write_event("Run transitions", now, sizeof(eb), (const char*)eb);
5915
5916 return SUCCESS;
5917}
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 2537 of file mlogger.cxx.

2538{
2539 char filename[256], dir[256], path[256];
2540 int status, size, write_flag;
2542
2543 /* do not update runlog if logger does not write data */
2544 size = sizeof(BOOL);
2545 write_flag = FALSE;
2546 db_get_value(hDB, 0, "/Logger/Write data", &write_flag, &size, TID_BOOL, TRUE);
2547 if (!write_flag)
2548 return;
2549
2550 /* get BOR or EOR list */
2551 if (bor) {
2552 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links BOR", &hKeyRoot);
2553 if (!hKeyRoot) {
2554 cm_msg(MERROR, "write_runlog_ascii", "Cannot find \"/Logger/Runlog/ASCII/Links BOR");
2555 return;
2556 }
2557 } else {
2558 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links EOR", &hKeyRoot);
2559 if (!hKeyRoot) {
2560 cm_msg(MERROR, "write_runlog_ascii", "Cannot find \"/Logger/Runlog/ASCII/Links EOR");
2561 return;
2562 }
2563 }
2564
2565 size = sizeof(write_flag);
2566 write_flag = 0;
2567 db_get_value(hDB, 0, "/Logger/Runlog/ASCII/Write data", &write_flag, &size, TID_BOOL, TRUE);
2568
2569 size = sizeof(filename);
2570 strcpy(filename, "runlog.log");
2571 db_get_value(hDB, 0, "/Logger/Runlog/ASCII/Filename", filename, &size, TID_STRING, TRUE);
2572
2573 if (strchr(filename, DIR_SEPARATOR) == NULL) {
2574 size = sizeof(dir);
2575 dir[0] = 0;
2576 db_get_value(hDB, 0, "/Logger/Message Dir", dir, &size, TID_STRING, TRUE);
2577 if (dir[0] != 0)
2578 if (dir[strlen(dir) - 1] != DIR_SEPARATOR)
2580 strcpy(path, dir);
2581 strcat(path, filename);
2582 } else
2583 strcpy(path, filename);
2584
2585 /* continue only if data should be written */
2586 if (!write_flag)
2587 return;
2588
2589 FILE *f = fopen(path, "r");
2590 if (f == NULL) {
2591 // create new file
2592 f = fopen(path, "wt");
2593
2594 assert(f != NULL);
2595
2596 // write column header line with variable names
2597 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links BOR", &hKeyRoot);
2598 for (int i = 0;; i++) {
2601 break;
2602 KEY key;
2603 db_get_key(hDB, hKey, &key);
2604 fprintf(f, "%s\t", key.name);
2605 }
2606 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links EOR", &hKeyRoot);
2607 for (int i = 0;; i++) {
2610 break;
2611 KEY key;
2612 db_get_key(hDB, hKey, &key);
2613 fprintf(f, "%s\t", key.name);
2614 }
2615 fprintf(f, "\n");
2616 fclose(f);
2617 }
2618
2619 // append data to logfile
2620 f = fopen(path, "at");
2621
2622 assert(f != NULL);
2623
2624 if (bor)
2625 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links BOR", &hKeyRoot);
2626 else
2627 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links EOR", &hKeyRoot);
2628
2629 for (int i = 0;; i++) {
2632 break;
2633 KEY key;
2634 db_get_key(hDB, hKey, &key);
2635 int size = key.total_size;
2636 char* data = (char*)malloc(size);
2637 assert(data);
2638 db_get_data(hDB, hKey, data, &size, key.type);
2639 std::string str = db_sprintf(data, size, 0, key.type);
2640 //printf("BBB key %s size %d %d [%s]\n", key.name, size, (int)strlen(str), str);
2641 free(data);
2642 fprintf(f, "%s\t", str.c_str());
2643 }
2644 if (!bor)
2645 fprintf(f, "\n");
2646 fclose(f);
2647}
INT db_sprintf(char *string, const void *data, INT data_size, INT idx, DWORD type)
Definition odb.cxx:10849
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 2698 of file mlogger.cxx.

2698 {
2699 char filename[256], messagedir[256], datadir[256], dirname[256], path[256];
2700 int status, size, write_flag;
2701 int runnumber;
2702 HNDLE hKey;
2703
2704 /* do not update runlog if logger does not write data */
2705 size = sizeof(BOOL);
2706 write_flag = FALSE;
2707 db_get_value(hDB, 0, "/Logger/Write data", &write_flag, &size, TID_BOOL, TRUE);
2708 if (!write_flag)
2709 return;
2710
2711 /* get BOR or EOR list */
2712 if (bor) {
2713 db_find_key(hDB, 0, "/Logger/Runlog/JSON/Links BOR", &hKey);
2714 if (!hKey) {
2715 cm_msg(MERROR, "write_runlog_json", "Cannot find \"/Logger/Runlog/JSON/Links BOR");
2716 return;
2717 }
2718 } else {
2719 db_find_key(hDB, 0, "/Logger/Runlog/JSON/Links EOR", &hKey);
2720 if (!hKey) {
2721 cm_msg(MERROR, "write_runlog_json", "Cannot find \"/Logger/Runlog/JSON/Links EOR");
2722 return;
2723 }
2724 }
2725
2726 size = sizeof(write_flag);
2727 write_flag = 0;
2728 db_get_value(hDB, 0, "/Logger/Runlog/JSON/Write data", &write_flag, &size, TID_BOOL, TRUE);
2729
2730 size = sizeof(datadir);
2731 strcpy(datadir, "");
2732 db_get_value(hDB, 0, "/Logger/Data Dir", datadir, &size, TID_STRING, TRUE);
2733
2734 size = sizeof(messagedir);
2735 strcpy(messagedir, "");
2736 db_get_value(hDB, 0, "/Logger/Message Dir", messagedir, &size, TID_STRING, TRUE);
2737
2738 size = sizeof(dirname);
2739 strcpy(dirname, "runlogs");
2740 db_get_value(hDB, 0, "/Logger/Runlog/JSON/Subdir", dirname, &size, TID_STRING, TRUE);
2741
2742 size = sizeof(runnumber);
2743 db_get_value(hDB, 0, "/Runinfo/Run number", &runnumber, &size, TID_INT32, FALSE);
2744
2745 snprintf(filename, 256, "runlog_%06i.json", runnumber);
2746
2747 // use /Logger/Message dir, and if empty use /Logger/Data dir
2748 mstrlcpy(path, messagedir, sizeof(path));
2749 if (path[0] == 0)
2750 mstrlcpy(path, datadir, sizeof(path));
2751 if (path[strlen(path) - 1] != DIR_SEPARATOR)
2752 mstrlcat(path, DIR_SEPARATOR_STR, sizeof(path));
2753 mstrlcat(path, dirname, sizeof(path));
2754 if (path[strlen(path) - 1] != DIR_SEPARATOR)
2755 mstrlcat(path, DIR_SEPARATOR_STR, sizeof(path));
2756
2757 /* create directory if needed */
2758#ifdef OS_WINNT
2759 status = mkdir(path);
2760#else
2761 status = mkdir(path, 0755);
2762#endif
2763
2764 mstrlcat(path, filename, sizeof(path));
2765
2766 /* continue only if data should be written */
2767 if (!write_flag)
2768 return;
2769
2770 char fileflag[2] = "a";
2771 if (bor)
2772 strcpy(fileflag, "a");
2773
2774 FILE *file = fopen(path, fileflag);
2775 if (file == NULL) {
2776 cm_msg(MERROR, "write_runlog_json", "Cannot open file \"%s\"", path);
2777 return;
2778 }
2779
2780 if (bor)
2781 db_find_key(hDB, 0, "/Logger/Runlog/JSON/Links BOR", &hKey);
2782 else
2783 db_find_key(hDB, 0, "/Logger/Runlog/JSON/Links EOR", &hKey);
2784
2785 int buffer_size = 100000;
2786 char *buffer = (char *)malloc(buffer_size);
2787 int buffer_end = 0;
2788
2789 if (bor)
2790 json_write(&buffer, &buffer_size, &buffer_end, 0, "{\n \"BOR\": ", 0);
2791 else
2792 json_write(&buffer, &buffer_size, &buffer_end, 0, " \"EOR\": ", 0);
2793
2794 if (!rpc_is_remote())
2797 status = json_write_anything(hDB, hKey, &buffer, &buffer_size, &buffer_end, JS_LEVEL_1, 0, flags, 0);
2798 if (!rpc_is_remote())
2800
2801 if (bor)
2802 json_write(&buffer, &buffer_size, &buffer_end, 0, ",\n", 0);
2803 else
2804 json_write(&buffer, &buffer_size, &buffer_end, 0, " \n}\n", 0);
2805
2806 if (status == DB_SUCCESS) {
2807 if (buffer) {
2808 size_t wr = fwrite(buffer, 1, buffer_end, file);
2809 if (wr != (size_t) buffer_end) {
2810 cm_msg(MERROR, "write_runlog_json", "Cannot write to file \"%s\", fwrite() errno %d (%s)", filename, errno, strerror(errno));
2811 free(buffer);
2812 fclose(file);
2813 return;
2814 }
2815 }
2816 }
2817
2818 if (buffer)
2819 free(buffer);
2820
2821 fclose(file);
2822}
INT db_lock_database(HNDLE hDB)
Definition odb.cxx:2460
INT db_unlock_database(HNDLE hDB)
Definition odb.cxx:2582
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:10389
void json_write(char **buffer, int *buffer_size, int *buffer_end, int level, const char *s, int quoted)
Definition odb.cxx:9532
bool rpc_is_remote(void)
Definition midas.cxx:12783
#define JSFLAG_RECURSE
Definition midas.h:1722
#define JSFLAG_FOLLOW_LINKS
Definition midas.h:1721
#define JSFLAG_OMIT_LAST_WRITTEN
Definition midas.h:1725
#define JSFLAG_OMIT_NAMES
Definition midas.h:1724
#define JS_LEVEL_1
Definition midas.h:1718
#define JSFLAG_OMIT_OLD
Definition midas.h:1726
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 372 of file mlogger.cxx.

373{
374 std::string path = xpath;
375 while (level > 0) {
376 size_t p = path.rfind(".");
377 //printf("level %d, path [%s], pos %d\n", level, path.c_str(), (int)p);
378 if (p == std::string::npos)
379 break;
380 path = path.substr(0, p);
381 level--;
382 }
383 return path;
384}
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ auto_restart

DWORD auto_restart = 0

Definition at line 318 of file mlogger.cxx.

◆ hDB

HNDLE hDB
static

Definition at line 338 of file mlogger.cxx.

◆ hist_log

struct hist_log_s* hist_log = NULL
static

Definition at line 336 of file mlogger.cxx.

◆ hist_log_max

int hist_log_max = 0
static

Definition at line 335 of file mlogger.cxx.

◆ hist_log_size

int hist_log_size = 0
static

Definition at line 334 of file mlogger.cxx.

◆ history_events

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

Definition at line 4747 of file mlogger.cxx.

◆ in_stop_transition

BOOL in_stop_transition = FALSE

Definition at line 313 of file mlogger.cxx.

◆ last_history_flush

time_t last_history_flush = 0

Definition at line 5513 of file mlogger.cxx.

◆ local_state

INT local_state

Definition at line 312 of file mlogger.cxx.

◆ log_channels

std::vector<LOG_CHN*> log_channels

Definition at line 322 of file mlogger.cxx.

◆ mh

std::vector<MidasHistoryInterface*> mh
static

Definition at line 4746 of file mlogger.cxx.

◆ run_start_time

DWORD run_start_time

Definition at line 319 of file mlogger.cxx.

◆ start_requested

BOOL start_requested = FALSE

Definition at line 317 of file mlogger.cxx.

◆ stop_requested

BOOL stop_requested = FALSE

Definition at line 316 of file mlogger.cxx.

◆ stop_try_later

double stop_try_later = 0

Definition at line 320 of file mlogger.cxx.

◆ subrun_start_time

DWORD subrun_start_time

Definition at line 319 of file mlogger.cxx.

◆ tape_message

BOOL tape_message = TRUE

Definition at line 314 of file mlogger.cxx.

◆ verbose

BOOL verbose = FALSE

Definition at line 315 of file mlogger.cxx.