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 FILEfopen_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 3943 of file mlogger.cxx.

◆ CHECKSUM_NONE

#define CHECKSUM_NONE   0

Definition at line 3941 of file mlogger.cxx.

◆ CHECKSUM_SHA256

#define CHECKSUM_SHA256   3

Definition at line 3944 of file mlogger.cxx.

◆ CHECKSUM_SHA512

#define CHECKSUM_SHA512   4

Definition at line 3945 of file mlogger.cxx.

◆ CHECKSUM_ZLIB

#define CHECKSUM_ZLIB   1

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

◆ COMPRESS_LZ4

#define COMPRESS_LZ4   2

Definition at line 3967 of file mlogger.cxx.

◆ COMPRESS_NONE

#define COMPRESS_NONE   0

Definition at line 3965 of file mlogger.cxx.

◆ COMPRESS_PBZIP2

#define COMPRESS_PBZIP2   4

Definition at line 3969 of file mlogger.cxx.

◆ COMPRESS_ZLIB

#define COMPRESS_ZLIB   1

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

◆ OUTPUT_FTP

#define OUTPUT_FTP   3

Definition at line 3986 of file mlogger.cxx.

◆ OUTPUT_NONE

#define OUTPUT_NONE   0

Definition at line 3983 of file mlogger.cxx.

◆ OUTPUT_NULL

#define OUTPUT_NULL   1

Definition at line 3984 of file mlogger.cxx.

◆ OUTPUT_PIPE

#define OUTPUT_PIPE   5

Definition at line 3988 of file mlogger.cxx.

◆ OUTPUT_ROOT

#define OUTPUT_ROOT   4

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

4739{
4740 int status;
4741 int size, i;
4742 int index = *indexp;
4743
4744#if 0
4745 {
4746 /* print the tags */
4747 printf("add_event: event %d, name \"%s\", ntags %d\n", event_id, event_name, ntags);
4748 for (i=0; i<ntags; i++) {
4749 printf("tag %d: name \"%s\", type %d, n_data %d\n", i, tags[i].name, tags[i].type, tags[i].n_data);
4750 }
4751 }
4752#endif
4753
4754 /* check for duplicate event id's */
4755 for (i=0; i<index; i++) {
4756 if (strcmp(hist_log[i].event_name, event_name) == 0) {
4757 cm_msg(MERROR, "add_event", "Duplicate event name \'%s\' with event id %d", event_name, event_id);
4758 return 0;
4759 }
4760 }
4761
4762 while (index >= hist_log_size) {
4763 int new_size = 2*hist_log_size;
4764
4765 if (hist_log_size == 0)
4766 new_size = 10;
4767
4769 assert(hist_log!=NULL);
4770
4772 }
4773
4774 if (index >= hist_log_max)
4775 hist_log_max = index + 1;
4776
4777 /* check for invalid history tags */
4778 for (i=0; i<ntags; i++) {
4779 if (tags[i].type == TID_STRING) {
4780 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);
4781 return 0;
4782 }
4783 if (tags[i].type == TID_INT64) {
4784 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);
4785 return 0;
4786 }
4787 if (tags[i].type == TID_UINT64) {
4788 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);
4789 return 0;
4790 }
4791 if (rpc_tid_size(tags[i].type) == 0) {
4792 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);
4793 return 0;
4794 }
4795 }
4796
4797 /* check for trailing spaces in tag names */
4798 for (i=0; i<ntags; i++) {
4799 if (isspace(tags[i].name[strlen(tags[i].name)-1])) {
4800 cm_msg(MERROR, "add_event", "Invalid tag %d \'%s\' in event %d \'%s\': has trailing spaces", i, tags[i].name, event_id, event_name);
4801 return 0;
4802 }
4803 }
4804
4805 for (unsigned i=0; i<mh.size(); i++) {
4806 status = mh[i]->hs_define_event(event_name, timestamp, ntags, tags);
4807 if (status != HS_SUCCESS) {
4808 cm_msg(MERROR, "add_event", "Cannot define event \"%s\", hs_define_event() status %d", event_name, status);
4809 return 0;
4810 }
4811 }
4812
4813 status = db_get_record_size(hDB, hKey, 0, &size);
4814
4815 if (status != DB_SUCCESS) {
4816 cm_msg(MERROR, "add_event", "Cannot define event \"%s\", db_get_record_size() status %d", event_name, status);
4817 return 0;
4818 }
4819
4820 /* setup hist_log structure for this event */
4821 mstrlcpy(hist_log[index].event_name, event_name, sizeof(hist_log[index].event_name));
4824 hist_log[index].buffer_size = size;
4825 hist_log[index].buffer = (char*)malloc(size);
4826 hist_log[index].min_period = min_period;
4827 hist_log[index].last_log = 0;
4828
4829 if (hist_log[index].buffer == NULL) {
4830 cm_msg(MERROR, "add_event", "Cannot allocate data buffer for event \"%s\" size %d", event_name, size);
4831 return 0;
4832 }
4833
4834 /* open hot link to variables */
4835 if (hotlink) {
4837 if (status != DB_SUCCESS) {
4838 cm_msg(MERROR, "add_event",
4839 "Cannot hotlink event %d \"%s\" for history logging, db_open_record() status %d",
4840 event_id, event_name, status);
4841 return status;
4842 }
4843 }
4844
4845 history_events.push_back(event_name);
4846
4847 if (verbose)
4848 printf("Created event %d for equipment \"%s\", %d tags, size %d\n", event_id, event_name, ntags, size);
4849
4850 *indexp = index+1;
4851
4852 return SUCCESS;
4853}
#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:915
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:13291
INT db_get_record_size(HNDLE hDB, HNDLE hKey, INT align, INT *buf_size)
Definition odb.cxx:11615
INT rpc_tid_size(INT id)
Definition midas.cxx:11757
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:5556
static std::vector< MidasHistoryInterface * > mh
Definition mlogger.cxx:4735
static int hist_log_size
Definition mlogger.cxx:334
static std::vector< std::string > history_events
Definition mlogger.cxx:4736
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 4010 of file mlogger.cxx.

4011{
4012 (*def) += std::string(" ") + str;
4013 if (v)
4014 return v; // keep returning the first selection
4015 if (val.find(str) == 0) {
4016 *sel = str;
4017 return n; // if no selection yet, return the new selection
4018 }
4019 return v;
4020}
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 5862 of file mlogger.cxx.

5863{
5864 /* close buffers */
5865 for (unsigned i = 0; i < log_channels.size(); i++) {
5867#ifndef FAL_MAIN
5868 if (chn->buffer_handle) {
5869 bm_close_buffer(chn->buffer_handle);
5870 for (unsigned j = i + 1; j < log_channels.size(); j++)
5871 if (log_channels[j]->buffer_handle == chn->buffer_handle)
5872 log_channels[j]->buffer_handle = 0;
5873 }
5874
5875 if (chn->msg_request_id)
5876 bm_delete_request(chn->msg_request_id);
5877#endif
5878
5879 delete chn;
5880 log_channels[i] = NULL;
5881 }
5882
5883 log_channels.clear();
5884
5885 return SUCCESS;
5886}
INT bm_delete_request(INT request_id)
Definition midas.cxx:8584
INT bm_close_buffer(INT buffer_handle)
Definition midas.cxx:7096
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 5817 of file mlogger.cxx.

5818{
5820
5821 for (unsigned i = 0; i < log_channels.size(); i++) {
5823 if (chn->handle || chn->ftp_con|| chn->pfile) {
5824 /* generate MTALK message */
5825#ifndef FAL_MAIN
5826 /* wait until buffer is empty */
5827 if (chn->buffer_handle) {
5828#ifdef DELAYED_STOP
5829 DWORD start_time = ss_millitime();
5830 do {
5831 cm_yield(100);
5832 } while (ss_millitime() - start_time < DELAYED_STOP);
5833#else
5834 INT n_bytes;
5835 do {
5836 bm_get_buffer_level(chn->buffer_handle, &n_bytes);
5837 if (n_bytes > 0)
5838 cm_yield(100);
5839 } while (n_bytes > 0);
5840#endif
5841 }
5842#endif /* FAL_MAIN */
5843
5844 /* close logging channel */
5846
5847 /* close statistics record */
5848 db_set_record(hDB, chn->stats_hkey, &chn->statistics, sizeof(CHN_STATISTICS), 0);
5849 db_close_record(hDB, chn->stats_hkey);
5850 db_unwatch(hDB, chn->settings_hkey);
5851 chn->stats_hkey = 0;
5852 chn->settings_hkey = 0;
5853 }
5854 }
5855
5856 if (p_tape_flag)
5858
5859 return SUCCESS;
5860}
#define FALSE
Definition cfortran.h:309
INT cm_yield(INT millisec)
Definition midas.cxx:5642
unsigned int DWORD
Definition mcstd.h:51
DWORD ss_millitime()
Definition system.cxx:3393
INT db_unwatch(HNDLE hDB, HNDLE hKey)
Definition odb.cxx:13887
INT db_set_record(HNDLE hDB, HNDLE hKey, void *data, INT buf_size, INT align)
Definition odb.cxx:12291
INT db_close_record(HNDLE hDB, HNDLE hKey)
Definition odb.cxx:13473
INT run_number[2]
Definition mana.cxx:246
INT bm_get_buffer_level(INT buffer_handle, INT *n_bytes)
Definition midas.cxx:7838
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:4279
Here is the call graph for this function:
Here is the caller graph for this function:

◆ close_history()

void close_history ( )

Definition at line 5518 of file mlogger.cxx.

5519{
5520 INT status;
5522
5523 /* close system history */
5524 status = db_find_key(hDB, 0, "/History/Links", &hKeyRoot);
5525 if (status == DB_SUCCESS) {
5526 for (int i = 0;; i++) {
5527 HNDLE hKey;
5530 break;
5532 }
5533 }
5534
5535 /* close event history */
5536 for (int i = 0; i < hist_log_max; i++)
5537 if (hist_log[i].hKeyVar) {
5538 db_close_record(hDB, hist_log[i].hKeyVar);
5539 hist_log[i].hKeyVar = 0;
5540 if (hist_log[i].buffer)
5541 free(hist_log[i].buffer);
5542 hist_log[i].buffer = NULL;
5543 }
5544
5545 for (unsigned h=0; h<mh.size(); h++) {
5546 mh[h]->hs_disconnect();
5547 delete mh[h];
5548 mh[h] = NULL;
5549 }
5550
5551 mh.clear();
5552}
#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:4079
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition odb.cxx:5586
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:5415
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
Definition odb.cxx:3308
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:13934
INT db_create_link(HNDLE hDB, HNDLE hKey, const char *link_name, const char *destination)
Definition odb.cxx:3601
#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 2647 of file mlogger.cxx.

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

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

2823{
2824 cm_msg(MERROR, "ftp_error", "%s", message);
2825 return 1;
2826}
#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 2828 of file mlogger.cxx.

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

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

3991{
3993 value[0] = 0;
3994 int size = sizeof(value);
3995 int status = db_get_value(hDB, hDir, name, &value, &size, TID_STRING, FALSE);
3996 if (status != DB_SUCCESS)
3997 return "";
3998 return value;
3999}
#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 4279 of file mlogger.cxx.

4280{
4281 if (log_chn->writer) {
4282 /* write ODB dump */
4283 if (log_chn->settings.odb_dump)
4285
4286 WriterInterface* wr = log_chn->writer;
4287
4289
4290 /* update statistics */
4291
4292 double incr = wr->fBytesOut - log_chn->statistics.bytes_written_subrun;
4293 if (incr < 0)
4294 incr = 0;
4295
4296 //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);
4297
4298 log_chn->statistics.bytes_written += incr;
4299 log_chn->statistics.bytes_written_subrun = wr->fBytesOut;
4300 log_chn->statistics.bytes_written_total += incr;
4301 }
4302#ifdef OBSOLETE
4303#ifdef HAVE_ROOT
4304 } else if (log_chn->format == FORMAT_ROOT) {
4306#endif
4307 } else if (log_chn->format == FORMAT_MIDAS) {
4309 }
4310#endif
4311
4312 /* if file name starts with '.', rename it */
4313 char str[256]; // FIXME: this will truncate the filename of the output file. K.O.
4314 mstrlcpy(str, log_chn->path.c_str(), sizeof(str));
4315 char* p = str;
4316 if (strrchr(str, DIR_SEPARATOR)) {
4317 p = strrchr(str, DIR_SEPARATOR)+1;
4318 }
4319 if (*p == '.') {
4320 mstrlcpy(p, p+1, sizeof(str));
4321 rename(log_chn->path.c_str(), str); // FIXME: must check return status. K.O.
4322 }
4323
4324 log_chn->statistics.files_written += 1;
4325 log_chn->handle = 0;
4326 log_chn->ftp_con = NULL;
4327
4328 if (log_chn->writer) {
4329 delete log_chn->writer;
4330 log_chn->writer = NULL;
4331 }
4332
4333 return SS_SUCCESS;
4334}
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 4073 of file mlogger.cxx.

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

4339{
4340 std::string str = log_chn->path.c_str();
4341 size_t pos = str.rfind('/');
4342 if (pos != std::string::npos) {
4343 str.erase(pos); // strip filename for bzip2
4344 }
4345
4346 //printf("log_disk_level [%s] [%s]\n", log_chn->path.c_str(), str.c_str());
4347
4348 double MiB = 1024*1024;
4349 double disk_size = ss_disk_size(str.c_str());
4350 double disk_free = ss_disk_free(str.c_str());
4351 double limit = 10E6;
4352 double level = 1.0-disk_free/disk_size;
4353
4354 if (pdisk_size)
4355 *pdisk_size = disk_size; // should be in statistics
4356 if (pdisk_free)
4357 *pdisk_free = disk_free; // should be in statistics
4358
4359 log_chn->statistics.disk_level = level;
4360
4361 if (verbose)
4362 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);
4363
4364 return SUCCESS;
4365}
double ss_disk_size(const char *path)
Definition system.cxx:7048
double ss_disk_free(const char *path)
Definition system.cxx:6620
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 5662 of file mlogger.cxx.

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

5557{
5558 INT i, size, status;
5560
5561 time_t now = time(NULL);
5562
5563 for (i = 0; i < hist_log_max; i++)
5564 if (hist_log[i].hKeyVar == hKey)
5565 break;
5566
5567 if (i == hist_log_max)
5568 return;
5569
5570 /* check if over minimum period */
5571 if (now - hist_log[i].last_log < hist_log[i].min_period)
5572 return;
5573
5574 /* check if event size has changed */
5575 db_get_record_size(hDB, hKey, 0, &size);
5576 if (size != hist_log[i].buffer_size) {
5577 close_history();
5578 status = open_history();
5579 if (status != CM_SUCCESS) {
5580 printf("Error in history system, aborting.\n");
5582 exit(1);
5583 }
5584 return;
5585 }
5586
5588
5589 if (verbose)
5590 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);
5591
5592 for (unsigned h=0; h<mh.size(); h++) {
5593 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);
5594 if (verbose)
5595 if (status != HS_SUCCESS)
5596 printf("write_history_event: \'%s\', channel \'%s\' hs_write_event() status %d\n", hist_log[i].event_name, mh[h]->name, status);
5597 }
5598
5600
5602 if (end_millitime - start_millitime > 3000)
5603 cm_msg(MINFO, "log_history", "History write operation took %d ms", end_millitime - start_millitime);
5604}
INT cm_disconnect_experiment(void)
Definition midas.cxx:2846
void maybe_flush_history(time_t now)
Definition mlogger.cxx:5500
void close_history()
Definition mlogger.cxx:5518
INT open_history()
Definition mlogger.cxx:4855
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:8281
INT db_copy_json_save(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end)
Definition odb.cxx:10475
#define MIDAS_MAGIC
Definition midas.h:911
INT log_write(LOG_CHN *log_chn, EVENT_HEADER *pheader)
Definition mlogger.cxx:4527
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:8217
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:9037
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 4229 of file mlogger.cxx.

4230{
4231 INT status = SUCCESS;
4232
4233 log_chn->last_checked = ss_millitime();
4234
4235 if (log_chn->writer) {
4236 WriterInterface* wr = log_chn->writer;
4237
4239
4240 if (status != SUCCESS)
4241 return status;
4242
4243 /* write ODB dump */
4244 if (log_chn->settings.odb_dump)
4246
4247 /* update statistics */
4248 double incr = wr->fBytesOut - log_chn->statistics.bytes_written_subrun;
4249 if (incr < 0)
4250 incr = 0;
4251
4252 //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);
4253
4254 log_chn->statistics.bytes_written += incr;
4255 log_chn->statistics.bytes_written_subrun = wr->fBytesOut;
4256 log_chn->statistics.bytes_written_total += incr;
4257 } else {
4258 return SS_INVALID_FORMAT;
4259 }
4260#ifdef OBSOLETE
4261 } else if (equal_ustring(log_chn->settings.format, "ROOT")) {
4262#ifdef HAVE_ROOT
4263 log_chn->format = FORMAT_ROOT;
4265#else
4266 return SS_NO_ROOT;
4267#endif
4268 } else if (equal_ustring(log_chn->settings.format, "MIDAS")) {
4269 log_chn->format = FORMAT_MIDAS;
4271 } else
4272 return SS_INVALID_FORMAT;
4273#endif
4274 return status;
4275}
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 5608 of file mlogger.cxx.

5609{
5610 INT size, total_size, status, index;
5611 DWORD i;
5612 KEY key;
5614
5615 index = (INT) (POINTER_T) info;
5616
5617 time_t now = time(NULL);
5618
5619 /* check if over period */
5620 if (now - hist_log[index].last_log < hist_log[index].min_period)
5621 return;
5622
5623 for (i = 0, total_size = 0;; i++) {
5624 status = db_enum_key(hDB, hist_log[index].hKeyVar, i, &hKey);
5626 break;
5627
5628 db_get_key(hDB, hKey, &key);
5629 size = key.total_size;
5630 db_get_data(hDB, hKey, (char *) hist_log[index].buffer + total_size, &size, key.type);
5631 total_size += size;
5632 }
5633
5634 if (i != hist_log[index].n_var) {
5635 close_history();
5636 status = open_history();
5637 if (status != CM_SUCCESS) {
5638 printf("Error in history system, aborting.\n");
5640 exit(1);
5641 }
5642 return;
5643 }
5644
5646
5647 if (verbose)
5648 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);
5649
5650 for (unsigned h=0; h<mh.size(); h++)
5651 mh[h]->hs_write_event(hist_log[index].event_name, hist_log[index].last_log, total_size, hist_log[index].buffer);
5652
5654
5656 if (end_millitime - start_millitime > 3000)
5657 cm_msg(MINFO, "log_system_history", "History write operation took %d ms", end_millitime - start_millitime);
5658}
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:6539
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
Definition odb.cxx:6019
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 4527 of file mlogger.cxx.

4528{
4529 INT status = 0, size;
4532
4533 //printf("log_write %d\n", pevent->data_size + sizeof(EVENT_HEADER));
4534
4535 DWORD start_time = ss_millitime();
4536 int evt_size = pevent->data_size + sizeof(EVENT_HEADER);
4537
4538 if (log_chn->writer) {
4539 WriterInterface* wr = log_chn->writer;
4540 status = wr->wr_write(log_chn, pevent, evt_size);
4541
4542 if (status == SUCCESS) {
4543 /* update statistics */
4544 log_chn->statistics.events_written++;
4545 log_chn->statistics.bytes_written_uncompressed += evt_size;
4546 }
4547
4548 double incr = wr->fBytesOut - log_chn->statistics.bytes_written_subrun;
4549 if (incr < 0)
4550 incr = 0;
4551
4552 //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);
4553
4554 log_chn->statistics.bytes_written += incr;
4555 log_chn->statistics.bytes_written_subrun = wr->fBytesOut;
4556 log_chn->statistics.bytes_written_total += incr;
4557 }
4558#ifdef OBSOLETE
4559 } else {
4560 int written = 0;
4561
4562 if (log_chn->format == FORMAT_MIDAS) {
4563 written = midas_write(log_chn, pevent, pevent->data_size + sizeof(EVENT_HEADER));
4564#ifdef HAVE_ROOT
4565 } else if (log_chn->format == FORMAT_ROOT) {
4566 written = root_write(log_chn, pevent, pevent->data_size + sizeof(EVENT_HEADER));
4567#endif
4568 }
4569
4570 /* update statistics */
4571 if (written > 0) {
4572 log_chn->statistics.events_written++;
4573 log_chn->statistics.bytes_written_uncompressed += evt_size;
4574 log_chn->statistics.bytes_written += written;
4575 log_chn->statistics.bytes_written_total += written;
4576 log_chn->statistics.bytes_written_subrun += written;
4577 }
4578
4579 if (written < 0)
4581 else
4583 }
4584#endif
4585
4587 if (actual_time - start_time > 3000)
4588 cm_msg(MINFO, "log_write", "Write operation on \'%s\' took %d ms", log_chn->path.c_str(), actual_time - start_time);
4589
4590 if (status != SS_SUCCESS && !stop_requested) {
4591 cm_msg(MTALK, "log_write", "Error writing output file, stopping run");
4592 cm_msg(MERROR, "log_write", "Cannot write \'%s\', error %d, stopping run", log_chn->path.c_str(), status);
4593 stop_the_run(0);
4594
4595 return status;
4596 }
4597
4598 /* check if event limit is reached to stop run */
4600 log_chn->settings.event_limit > 0 &&
4601 log_chn->statistics.events_written >= log_chn->settings.event_limit) {
4603
4604 cm_msg(MTALK, "log_write", "stopping run after having received %1.0lf events",
4605 log_chn->settings.event_limit);
4606
4607 status = stop_the_run(1);
4608 return status;
4609 }
4610
4611 /* check if duration is reached for subrun */
4612 duration = 0;
4613 size = sizeof(duration);
4614 db_get_value(hDB, 0, "/Logger/Subrun duration", &duration, &size, TID_UINT32, TRUE);
4616 int run_number;
4617
4618 // cm_msg(MTALK, "main", "stopping subrun after %d seconds", duration);
4619
4620 size = sizeof(run_number);
4621 status = db_get_value(hDB, 0, "Runinfo/Run number", &run_number, &size, TID_INT32, TRUE);
4622 assert(status == SUCCESS);
4623
4624 stop_requested = TRUE; // avoid recursive call thourgh log_odb_dump
4626 log_chn->subrun_number++;
4627 log_chn->statistics.bytes_written_subrun = 0;
4633 }
4634
4635 /* check if byte limit is reached for subrun */
4636 if (!stop_requested && log_chn->settings.subrun_byte_limit > 0 &&
4637 log_chn->statistics.bytes_written_subrun >= log_chn->settings.subrun_byte_limit) {
4638 int run_number;
4639
4640 // cm_msg(MTALK, "main", "stopping subrun after %1.0lf bytes", log_chn->settings.subrun_byte_limit);
4641
4642 size = sizeof(run_number);
4643 status = db_get_value(hDB, 0, "Runinfo/Run number", &run_number, &size, TID_INT32, TRUE);
4644 assert(status == SUCCESS);
4645
4646 stop_requested = TRUE; // avoid recursive call thourgh log_odb_dump
4648 log_chn->subrun_number++;
4649 log_chn->statistics.bytes_written_subrun = 0;
4655 }
4656
4657 /* check if new subrun is requested manually */
4659 size = sizeof(next_subrun);
4660 db_get_value(hDB, 0, "/Logger/Next subrun", &next_subrun, &size, TID_BOOL, true);
4661 if (!stop_requested && next_subrun) {
4662 int run_number;
4663
4664 // cm_msg(MTALK, "main", "stopping subrun by user request");
4665
4666 size = sizeof(run_number);
4667 status = db_get_value(hDB, 0, "Runinfo/Run number", &run_number, &size, TID_INT32, TRUE);
4668 assert(status == SUCCESS);
4669
4670 stop_requested = TRUE; // avoid recursive call thourgh log_odb_dump
4672 log_chn->subrun_number++;
4673 log_chn->statistics.bytes_written_subrun = 0;
4679
4681 db_set_value(hDB, 0, "/Logger/Next subrun", &next_subrun, sizeof(next_subrun), 1, TID_BOOL);
4682 }
4683
4684 /* check if byte limit is reached to stop run */
4686 log_chn->settings.byte_limit > 0 &&
4687 log_chn->statistics.bytes_written >= log_chn->settings.byte_limit) {
4689
4690 cm_msg(MTALK, "log_write", "stopping run after having received %1.0lf mega bytes",
4691 log_chn->statistics.bytes_written / 1E6);
4692
4693 status = stop_the_run(1);
4694
4695 return status;
4696 }
4697
4698 /* stop run if less than 10MB free disk space */
4700 if (log_chn->type == LOG_TYPE_DISK && log_chn->do_disk_level && actual_time - log_chn->last_checked > DISK_CHECK_INTERVAL_MILLISEC) {
4701 log_chn->last_checked = actual_time;
4702
4703 const double MiB = 1024*1024;
4704 double disk_size = 0;
4705 double disk_free = 0;
4706
4708
4709 double limit = 10E6;
4710
4711 if (disk_size > 100E9) {
4712 limit = 1000E6;
4713 } else if (disk_size > 10E9) {
4714 limit = 100E6;
4715 }
4716
4717 if (disk_free < limit) {
4719 cm_msg(MTALK, "log_write", "disk nearly full, stopping the run");
4720 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);
4721
4722 status = stop_the_run(0);
4723 }
4724 }
4725
4726 return status;
4727}
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:3462
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:4073
int log_generate_file_name(LOG_CHN *log_chn)
Definition mlogger.cxx:5662
INT log_open(LOG_CHN *log_chn, INT run_number)
Definition mlogger.cxx:4229
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:4338
int stop_the_run(int restart)
Definition mlogger.cxx:4432
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:598
INT db_check_record(HNDLE hDB, HNDLE hKey, const char *keyname, const char *rec_str, BOOL correct)
Definition odb.cxx:12972
INT db_create_record(HNDLE hDB, HNDLE hKey, const char *orig_key_name, const char *init_str)
Definition odb.cxx:12800
void create_runlog_json_tree()
Definition mlogger.cxx:2647
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 6433 of file mlogger.cxx.

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

4368{
4370 static DWORD last_check_time = 0;
4371
4372 if (last_check_time == 0)
4374
4376 return SUCCESS;
4377
4379
4380 for (unsigned i = 0; i < log_channels.size(); i++) {
4382
4383 if (!chn->do_disk_level)
4384 continue;
4385
4387 }
4388
4389 return SUCCESS;
4390}
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 5500 of file mlogger.cxx.

5501{
5502 time_t flush_period_sec = 1; // flush once every 1 seconds
5503
5505
5506 if (verbose)
5507 printf("flush history buffers!\n");
5508
5509 for (unsigned h = 0; h < mh.size(); h++)
5510 mh[h]->hs_flush_buffers();
5511
5513 }
5514}
time_t last_history_flush
Definition mlogger.cxx:5498
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 3947 of file mlogger.cxx.

3948{
3949 if (code == CHECKSUM_NONE) {
3950 return chained;
3951 } else if (code == CHECKSUM_ZLIB) {
3952 return new WriterCRC32Zlib(log_chn, level, chained);
3953 } else if (code == CHECKSUM_CRC32C) {
3954 return new WriterCRC32C(log_chn, level, chained);
3955 } else if (code == CHECKSUM_SHA256) {
3956 return new WriterSHA256(log_chn, level, chained);
3957 } else if (code == CHECKSUM_SHA512) {
3958 return new WriterSHA512(log_chn, level, chained);
3959 } else {
3960 cm_msg(MERROR, "log_create_writer", "channel %s unknown checksum code %d", log_chn->path.c_str(), code);
3961 return chained;
3962 }
3963}
#define CHECKSUM_ZLIB
Definition mlogger.cxx:3942
#define CHECKSUM_CRC32C
Definition mlogger.cxx:3943
#define CHECKSUM_SHA256
Definition mlogger.cxx:3944
#define CHECKSUM_NONE
Definition mlogger.cxx:3941
#define CHECKSUM_SHA512
Definition mlogger.cxx:3945
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 3971 of file mlogger.cxx.

3972{
3973 if (code == COMPRESS_NONE) {
3974 return chained;
3975 } else if (code == COMPRESS_LZ4) {
3976 return new WriterLZ4(log_chn, chained);
3977 } else {
3978 cm_msg(MERROR, "log_create_writer", "channel %s unknown compression code %d", log_chn->path.c_str(), code);
3979 return chained;
3980 }
3981}
#define COMPRESS_NONE
Definition mlogger.cxx:3965
#define COMPRESS_LZ4
Definition mlogger.cxx:3967
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 3907 of file mlogger.cxx.

3908{
3909 std::string bzip2_command = "bzip2 -z";
3910
3911 if (log_chn->settings.bzip2_compression) {
3912 bzip2_command += " -";
3913 bzip2_command += IntToString(log_chn->settings.bzip2_compression);
3914 }
3915
3916 return new WriterPopen(log_chn, (bzip2_command + " > ").c_str(), ".bz2");
3917}
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 3919 of file mlogger.cxx.

3920{
3921 std::string pbzip2_command = "pbzip2 -c -z";
3922
3923 if (log_chn->settings.pbzip2_num_cpu) {
3924 pbzip2_command += " -p";
3925 pbzip2_command += IntToString(log_chn->settings.pbzip2_num_cpu);
3926 }
3927
3928 if (log_chn->settings.pbzip2_compression) {
3929 pbzip2_command += " -";
3930 pbzip2_command += IntToString(log_chn->settings.pbzip2_compression);
3931 }
3932
3933 if (strlen(log_chn->settings.pbzip2_options) > 0) {
3934 pbzip2_command += " ";
3935 pbzip2_command += log_chn->settings.pbzip2_options;
3936 }
3937
3938 return new WriterPopen(log_chn, (pbzip2_command + " > ").c_str(), ".bz2");
3939}
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:10527
INT db_save_xml(HNDLE hDB, HNDLE hKey, const char *filename)
Definition odb.cxx:9480
INT db_save(HNDLE hDB, HNDLE hKey, const char *filename, BOOL bRemote)
Definition odb.cxx:9245
BOOL ends_with_ustring(const char *str, const char *suffix)
Definition odb.cxx:3222
bool ends_with_char(const std::string &s, char c)
Definition midas.cxx:403
Here is the call graph for this function:
Here is the caller graph for this function:

◆ open_history()

INT open_history ( )

Definition at line 4855 of file mlogger.cxx.

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

6407{
6408 if (verbose)
6409 printf("write data event: req %d, evid %d, timestamp %d, size %d\n", request_id, pheader->event_id, pheader->time_stamp, pheader->data_size);
6410
6411 /* find logging channel for this request id */
6412 for (unsigned i = 0; i < log_channels.size(); i++) {
6414 if (chn->handle == 0 && chn->ftp_con == NULL)
6415 continue;
6416
6417 /* write normal events */
6418 if (chn->request_id == request_id) {
6419 log_write(chn, pheader);
6420 break;
6421 }
6422
6423 /* write messages */
6424 if (chn->msg_request_id == request_id) {
6425 log_write(chn, pheader);
6426 break;
6427 }
6428 }
6429}
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 4022 of file mlogger.cxx.

4023{
4024 std::string val = get_value(hDB, hSet, name);
4025 std::string sel;
4026 std::string def;
4027 int s = 0;
4028 s = check_add(s, CHECKSUM_NONE, val, "NONE", false, &def, &sel);
4029 s = check_add(s, CHECKSUM_CRC32C, val, "CRC32C", true, &def, &sel);
4030 s = check_add(s, CHECKSUM_SHA256, val, "SHA256", false, &def, &sel);
4031 s = check_add(s, CHECKSUM_SHA512, val, "SHA512", false, &def, &sel);
4032 s = check_add(s, CHECKSUM_ZLIB, val, "ZLIB", false, &def, &sel);
4033 if (sel == "")
4034 sel = "NONE";
4035 //set_value(hDB, hSet, name, sel, def);
4036 return s;
4037}
std::string get_value(HNDLE hDB, HNDLE hDir, const char *name)
Definition mlogger.cxx:3990
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:4010
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 4039 of file mlogger.cxx.

4040{
4041 std::string val = get_value(hDB, hSet, name);
4042 std::string sel;
4043 std::string def;
4044 int s = 0;
4045 s = check_add(s, COMPRESS_NONE, val, "none", false, &def, &sel);
4046 s = check_add(s, COMPRESS_ZLIB, val, "gzip", true, &def, &sel);
4047 s = check_add(s, COMPRESS_LZ4, val, "lz4", false, &def, &sel);
4048 s = check_add(s, COMPRESS_BZIP2, val, "bzip2", false, &def, &sel);
4049 s = check_add(s, COMPRESS_PBZIP2, val, "pbzip2", false, &def, &sel);
4050 if (sel == "")
4051 sel = "none";
4052 //set_value(hDB, hSet, name, sel, def);
4053 return s;
4054}
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 4056 of file mlogger.cxx.

4057{
4058 std::string val = get_value(hDB, hSet, name);
4059 std::string sel;
4060 std::string def;
4061 int s = 0;
4062 s = check_add(s, OUTPUT_NULL, val, "NULL", false, &def, &sel);
4063 s = check_add(s, OUTPUT_FILE, val, "FILE", true, &def, &sel);
4064 s = check_add(s, OUTPUT_FTP, val, "FTP", false, &def, &sel);
4065 s = check_add(s, OUTPUT_ROOT, val, "ROOT", false, &def, &sel);
4066 s = check_add(s, OUTPUT_PIPE, val, "PIPE", false, &def, &sel);
4067 if (sel == "")
4068 sel = "FILE";
4069 //set_value(hDB, hSet, name, sel, def);
4070 return s;
4071}
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 4001 of file mlogger.cxx.

4002{
4003 std::string s = set + " (one of:" + def + ")";
4004 int size = 256; // MUST match record definition // strlen(value);
4005 s.reserve(size);
4006 const char* value = s.c_str();
4007 db_set_value(hDB, hDir, name, value, size, 1, TID_STRING);
4008}
#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 4466 of file mlogger.cxx.

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

4433{
4434 int status, flag, size;
4435 char errstr[256];
4436
4437 if (restart) {
4438 size = sizeof(BOOL);
4439 flag = FALSE;
4440 db_get_value(hDB, 0, "/Logger/Auto restart", &flag, &size, TID_BOOL, TRUE);
4441
4442 if (flag) {
4444 auto_restart = 0;
4445 }
4446 }
4447
4449 stop_try_later = 0;
4450
4451 int trans_flag = get_trans_flag();
4452
4453 status = cm_transition(TR_STOP, 0, errstr, sizeof(errstr), trans_flag, verbose);
4455 cm_msg(MERROR, "stop_the_run", "another transition is in progress, will try again later");
4457 stop_try_later = ss_time_sec() + 10.0;
4458 } else if (status != CM_SUCCESS) {
4459 cm_msg(MERROR, "stop_the_run", "cannot stop the run, cm_transition() status %d, error: %s", status, errstr);
4460 return status;
4461 }
4462
4463 return status;
4464}
#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:1310
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 6380 of file mlogger.cxx.

6381{
6382 /* write transition event into history */
6384
6386
6388
6389 return CM_SUCCESS;
6390}
#define STATE_PAUSED
Definition midas.h:306
INT cm_msg_flush_buffer()
Definition midas.cxx:865
static int write_history(DWORD transition, DWORD run_number)
Definition mlogger.cxx:5890
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 6392 of file mlogger.cxx.

6393{
6394 /* write transition event into history */
6396
6398
6400
6401 return CM_SUCCESS;
6402}
#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 5924 of file mlogger.cxx.

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

6244{
6245 if (verbose)
6246 printf("tr_start_abort: run %d\n", run_number);
6247
6249
6250 for (unsigned i = 0; i < log_channels.size(); i++) {
6252 if (chn->handle && chn->type == LOG_TYPE_DISK) {
6253 cm_msg(MINFO, "tr_start_abort", "Deleting previous file \"%s\"", chn->path.c_str());
6254 unlink(chn->path.c_str());
6255 }
6256 }
6257
6259 close_buffers();
6260
6262
6264
6266
6267 return CM_SUCCESS;
6268}
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 6272 of file mlogger.cxx.

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

5907{
5908 int status;
5909 assert(info != NULL);
5911 int size = sizeof(CHN_SETTINGS);
5912 status = db_get_record1(hDB, log_chn->settings_hkey, &log_chn->settings, &size, 0, strcomb1(chn_settings_str).c_str());
5913 if (status != DB_SUCCESS) {
5914 cm_msg(MINFO, "watch_settings", "db_get_record(%s) status %d", log_chn->name.c_str(), status);
5915 return;
5916 }
5917
5918 if (verbose)
5919 printf("Channel %s settings updated\n", log_chn->name.c_str());
5920}
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 5890 of file mlogger.cxx.

5891{
5892 DWORD eb[2];
5893 eb[0] = transition;
5894 eb[1] = run_number;
5895
5896 time_t now = time(NULL);
5897
5898 for (unsigned h=0; h<mh.size(); h++)
5899 mh[h]->hs_write_event("Run transitions", now, sizeof(eb), (const char*)eb);
5900
5901 return SUCCESS;
5902}
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 // write column header line with variable names
2595 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links BOR", &hKeyRoot);
2596 for (int i = 0;; i++) {
2599 break;
2600 KEY key;
2601 db_get_key(hDB, hKey, &key);
2602 fprintf(f, "%s\t", key.name);
2603 }
2604 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links EOR", &hKeyRoot);
2605 for (int i = 0;; i++) {
2608 break;
2609 KEY key;
2610 db_get_key(hDB, hKey, &key);
2611 fprintf(f, "%s\t", key.name);
2612 }
2613 fprintf(f, "\n");
2614 fclose(f);
2615 }
2616
2617 // append data to logfile
2618 f = fopen(path, "at");
2619
2620 if (bor)
2621 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links BOR", &hKeyRoot);
2622 else
2623 db_find_key(hDB, 0, "/Logger/Runlog/ASCII/Links EOR", &hKeyRoot);
2624
2625 for (int i = 0;; i++) {
2628 break;
2629 KEY key;
2630 db_get_key(hDB, hKey, &key);
2631 int size = key.total_size;
2632 char* data = (char*)malloc(size);
2633 assert(data);
2634 db_get_data(hDB, hKey, data, &size, key.type);
2635 std::string str = db_sprintf(data, size, 0, key.type);
2636 //printf("BBB key %s size %d %d [%s]\n", key.name, size, (int)strlen(str), str);
2637 free(data);
2638 fprintf(f, "%s\t", str.c_str());
2639 }
2640 if (!bor)
2641 fprintf(f, "\n");
2642 fclose(f);
2643}
INT db_sprintf(char *string, const void *data, INT data_size, INT idx, DWORD type)
Definition odb.cxx:10843
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 2694 of file mlogger.cxx.

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