MIDAS
Loading...
Searching...
No Matches
Message Functions (msg_xxx)

Classes

struct  msg_buffer_entry
 

Functions

std::string cm_get_error (INT code)
 
int cm_msg_early_init (void)
 
int cm_msg_open_buffer (void)
 
int cm_msg_close_buffer (void)
 
INT EXPRT cm_msg_facilities (STRING_LIST *list)
 
void cm_msg_get_logfile (const char *fac, time_t t, std::string *filename, std::string *linkname, std::string *linktarget)
 
INT cm_set_msg_print (INT system_mask, INT user_mask, int(*func)(const char *))
 
INT cm_msg_log (INT message_type, const char *facility, const char *message)
 
static std::string cm_msg_format (INT message_type, const char *filename, INT line, const char *routine, const char *format, va_list *argptr)
 
static INT cm_msg_send_event (DWORD ts, INT message_type, const char *send_message)
 
INT cm_msg_flush_buffer ()
 
INT cm_msg (INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
 
INT cm_msg1 (INT message_type, const char *filename, INT line, const char *facility, const char *routine, const char *format,...)
 
INT cm_msg_register (EVENT_HANDLER *func)
 
static void add_message (char **messages, int *length, int *allocated, time_t tstamp, const char *new_message)
 
static int cm_msg_retrieve1 (const char *filename, time_t t, INT n_messages, char **messages, int *length, int *allocated, int *num_messages)
 
INT cm_msg_retrieve2 (const char *facility, time_t t, INT n_message, char **messages, int *num_messages)
 
INT cm_msg_retrieve (INT n_message, char *message, INT buf_size)
 

Variables

static std::deque< msg_buffer_entrygMsgBuf
 
static std::mutex gMsgBufMutex
 

Detailed Description

dox dox


Function Documentation

◆ add_message()

static void add_message ( char **  messages,
int length,
int allocated,
time_t  tstamp,
const char new_message 
)
static

Definition at line 1080 of file midas.cxx.

1080 {
1082 int new_allocated = 1024 + 2 * ((*allocated) + new_message_length);
1083 char buf[100];
1084 int buf_length;
1085
1086 //printf("add_message: new message %d, length %d, new end: %d, allocated: %d, maybe reallocate size %d\n", new_message_length, *length, *length + new_message_length, *allocated, new_allocated);
1087
1088 if (*length + new_message_length + 100 > *allocated) {
1089 *messages = (char *) realloc(*messages, new_allocated);
1090 assert(*messages != NULL);
1092 }
1093
1094 if (*length > 0)
1095 if ((*messages)[(*length) - 1] != '\n') {
1096 (*messages)[*length] = '\n'; // separator between messages
1097 (*length) += 1;
1098 }
1099
1100 sprintf(buf, "%ld ", tstamp);
1101 buf_length = strlen(buf);
1102 memcpy(&((*messages)[*length]), buf, buf_length);
1103 (*length) += buf_length;
1104
1106 (*length) += new_message_length;
1107 (*messages)[*length] = 0; // make sure string is NUL terminated
1108}
TH1X EXPRT * h1_book(const char *name, const char *title, int bins, double min, double max)
Definition rmidas.h:24
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cm_get_error()

std::string cm_get_error ( INT  code)

Convert error code to string. Used after cm_connect_experiment to print error string in command line programs or windows programs.

Parameters
codeError code as defined in midas.h
stringError string
Returns
CM_SUCCESS

Definition at line 468 of file midas.cxx.

469{
470 for (int i = 0; _error_table[i].code; i++) {
471 if (_error_table[i].code == code) {
472 return _error_table[i].string;
473 }
474 }
475
476 return msprintf("unlisted status code %d", code);
477}
INT i
Definition mdump.cxx:32
static const ERROR_TABLE _error_table[]
Definition midas.cxx:270
std::string msprintf(const char *format,...)
Definition midas.cxx:419
const char * string
Definition midas.cxx:267
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cm_msg()

INT cm_msg ( INT  message_type,
const char filename,
INT  line,
const char routine,
const char format,
  ... 
)

This routine can be called whenever an internal error occurs or an informative message is produced. Different message types can be enabled or disabled by setting the type bits via cm_set_msg_print().

Attention
Do not add the "\n" escape carriage control at the end of the formated line as it is already added by the client on the receiving side.
...
cm_msg(MINFO, "my program", "This is a information message only);
cm_msg(MERROR, "my program", "This is an error message with status:%d", my_status);
cm_msg(MTALK, "my_program", My program is Done!");
...
#define MINFO
Definition midas.h:560
MY my
Definition mdsupport.cxx:96
#define message(type, str)
DWORD status
Definition odbhist.cxx:39
double d
Definition system.cxx:1313
Parameters
message_type(See midas_macro).
filenameName of source file where error occured
lineLine number where error occured
routineRoutine name.
formatmessage to printout, ... Parameters like for printf()
Returns
CM_SUCCESS

Definition at line 930 of file midas.cxx.

931{
932 DWORD ts = ss_time();
933
934 /* print argument list into message */
935 std::string message;
937 va_start(argptr, format);
938 message = cm_msg_format(message_type, filename, line, routine, format, &argptr);
939 va_end(argptr);
940
941 //printf("message [%s]\n", message.c_str());
942
943 /* call user function if set via cm_set_msg_print */
945 if (f != NULL && (message_type & _message_mask_user) != 0) {
946 if (message_type != MT_LOG) { // do not print MLOG messages
947 (*f)(message.c_str());
948 }
949 }
950
951 /* return if system mask is not set */
952 if ((message_type & _message_mask_system) == 0) {
953 return CM_SUCCESS;
954 }
955
956 gMsgBufMutex.lock();
957 gMsgBuf.push_back(msg_buffer_entry{ts, message_type, message});
958 gMsgBufMutex.unlock();
959
960 return CM_SUCCESS;
961}
TRIGGER_SETTINGS ts
#define CM_SUCCESS
Definition midas.h:582
unsigned int DWORD
Definition mcstd.h:51
#define MT_LOG
Definition midas.h:546
DWORD ss_time()
Definition system.cxx:3534
static std::mutex gMsgBufMutex
Definition midas.cxx:872
static std::deque< msg_buffer_entry > gMsgBuf
Definition midas.cxx:871
static std::string cm_msg_format(INT message_type, const char *filename, INT line, const char *routine, const char *format, va_list *argptr)
Definition midas.cxx:764
static std::atomic_int _message_mask_system
Definition midas.cxx:448
int(* MessagePrintCallback)(const char *)
Definition midas.cxx:444
static std::atomic< MessagePrintCallback > _message_print
Definition midas.cxx:446
static std::atomic_int _message_mask_user
Definition midas.cxx:449
Definition midas.cxx:865
Here is the call graph for this function:

◆ cm_msg1()

INT cm_msg1 ( INT  message_type,
const char filename,
INT  line,
const char facility,
const char routine,
const char format,
  ... 
)

This routine is similar to cm_msg(). It differs from cm_msg() only by the logging destination being a file given through the argument list i.e:facility

Attention
Do not add the "\n" escape carriage control at the end of the formated line as it is already added by the client on the receiving side. The first arg in the following example uses the predefined macro MINFO which handles automatically the first 3 arguments of the function (see midas_macro).
...
cm_msg1(MINFO, "my_log_file", "my_program"," My message status:%d", status);
...
//----- File my_log_file.log
Thu Nov 8 17:59:28 2001 [my_program] My message status:1
INT cm_msg1(INT message_type, const char *filename, INT line, const char *facility, const char *routine, const char *format,...)
Definition midas.cxx:988
Parameters
message_typeSee midas_macro.
filenameName of source file where error occured
lineLine number where error occured
facilityLogging file name
routineRoutine name
formatmessage to printout, ... Parameters like for printf()
Returns
CM_SUCCESS

Definition at line 988 of file midas.cxx.

989 {
991 std::string message;
992 static BOOL in_routine = FALSE;
993
994 /* avoid recursive calles */
995 if (in_routine)
996 return 0;
997
999
1000 /* print argument list into message */
1001 va_start(argptr, format);
1002 message = cm_msg_format(message_type, filename, line, routine, format, &argptr);
1003 va_end(argptr);
1004
1005 /* call user function if set via cm_set_msg_print */
1007 if (f != NULL && (message_type & _message_mask_user) != 0)
1008 (*f)(message.c_str());
1009
1010 /* return if system mask is not set */
1011 if ((message_type & _message_mask_system) == 0) {
1012 in_routine = FALSE;
1013 return CM_SUCCESS;
1014 }
1015
1016 /* send message to SYSMSG */
1017 cm_msg_send_event(0, message_type, message.c_str());
1018
1019 /* log message */
1020 cm_msg_log(message_type, facility, message.c_str());
1021
1022 in_routine = FALSE;
1023
1024 return CM_SUCCESS;
1025}
#define FALSE
Definition cfortran.h:309
INT cm_msg_log(INT message_type, const char *facility, const char *message)
Definition midas.cxx:677
static INT cm_msg_send_event(DWORD ts, INT message_type, const char *send_message)
Definition midas.cxx:839
DWORD BOOL
Definition midas.h:105
#define TRUE
Definition midas.h:182
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cm_msg_close_buffer()

int cm_msg_close_buffer ( void  )

Definition at line 500 of file midas.cxx.

500 {
501 //printf("cm_msg_close_buffer!\n");
502 if (_msg_buffer) {
504 _msg_buffer = 0;
505 }
506 return CM_SUCCESS;
507}
INT bm_close_buffer(INT buffer_handle)
Definition midas.cxx:7119
static INT _msg_buffer
Definition midas.cxx:198
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cm_msg_early_init()

int cm_msg_early_init ( void  )

Definition at line 480 of file midas.cxx.

480 {
481
482 return CM_SUCCESS;
483}
Here is the caller graph for this function:

◆ cm_msg_facilities()

INT EXPRT cm_msg_facilities ( STRING_LIST list)

Retrieve list of message facilities by searching logfiles on disk

Parameters
listList of facilities
Returns
status SUCCESS

Definition at line 517 of file midas.cxx.

517 {
518 std::string path;
519
520 cm_msg_get_logfile("midas", 0, &path, NULL, NULL);
521
522 /* extract directory name from full path name of midas.log */
523 size_t pos = path.rfind(DIR_SEPARATOR);
524 if (pos != std::string::npos) {
525 path.resize(pos);
526 } else {
527 path = "";
528 }
529
530 //printf("cm_msg_facilities: path [%s]\n", path.c_str());
531
533
534 ss_file_find(path.c_str(), "*.log", &flist);
535
536 for (size_t i = 0; i < flist.size(); i++) {
537 const char *p = flist[i].c_str();
538 if (strchr(p, '_') == NULL && !(p[0] >= '0' && p[0] <= '9')) {
539 size_t pos = flist[i].rfind('.');
540 if (pos != std::string::npos) {
541 flist[i].resize(pos);
542 }
543 list->push_back(flist[i]);
544 }
545 }
546
547 return SUCCESS;
548}
#define SUCCESS
Definition mcstd.h:54
INT ss_file_find(const char *path, const char *pattern, char **plist)
Definition system.cxx:6791
void cm_msg_get_logfile(const char *fac, time_t t, std::string *filename, std::string *linkname, std::string *linktarget)
Definition midas.cxx:552
#define DIR_SEPARATOR
Definition midas.h:193
std::vector< std::string > STRING_LIST
Definition midas.h:246
static te_expr * list(state *s)
Definition tinyexpr.c:567
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cm_msg_flush_buffer()

INT cm_msg_flush_buffer ( void  )

This routine can be called to process messages buffered by cm_msg(). Normally it is called from cm_yield() and cm_disconnect_experiment() to make sure all accumulated messages are processed.

Definition at line 880 of file midas.cxx.

880 {
881 int i;
882
883 //printf("cm_msg_flush_buffer!\n");
884
885 for (i = 0; i < 100; i++) {
887 {
888 std::lock_guard<std::mutex> lock(gMsgBufMutex);
889 if (gMsgBuf.empty())
890 break;
891 e = gMsgBuf.front();
892 gMsgBuf.pop_front();
893 // implicit unlock
894 }
895
896 /* log message */
897 cm_msg_log(e.message_type, "midas", e.message.c_str());
898
899 /* send message to SYSMSG */
900 int status = cm_msg_send_event(e.ts, e.message_type, e.message.c_str());
901 if (status != CM_SUCCESS)
902 return status;
903 }
904
905 return CM_SUCCESS;
906}
static double e(void)
Definition tinyexpr.c:136
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cm_msg_format()

static std::string cm_msg_format ( INT  message_type,
const char filename,
INT  line,
const char routine,
const char format,
va_list argptr 
)
static

Definition at line 764 of file midas.cxx.

765{
766 /* strip path */
767 const char* pc = filename + strlen(filename);
768 while (*pc != '\\' && *pc != '/' && pc != filename)
769 pc--;
770 if (pc != filename)
771 pc++;
772
773 /* convert type to string */
774 std::string type_str;
775 if (message_type & MT_ERROR)
777 if (message_type & MT_INFO)
779 if (message_type & MT_DEBUG)
781 if (message_type & MT_USER)
783 if (message_type & MT_LOG)
785 if (message_type & MT_TALK)
787
788 std::string message;
789
790 /* print client name into string */
791 if (message_type == MT_USER)
792 message = msprintf("[%s] ", routine);
793 else {
794 std::string name = rpc_get_name();
795 if (name.length() > 0)
796 message = msprintf("[%s,%s] ", name.c_str(), type_str.c_str());
797 else
798 message = "";
799 }
800
801 /* preceed error messages with file and line info */
802 if (message_type == MT_ERROR) {
803 message += msprintf("[%s:%d:%s,%s] ", pc, line, routine, type_str.c_str());
804 } else if (message_type == MT_USER) {
805 message = msprintf("[%s,%s] ", routine, type_str.c_str());
806 }
807
808 int bufsize = 1024;
809 char* buf = (char*)malloc(bufsize);
810 assert(buf);
811
812 for (int i=0; i<10; i++) {
813 va_list ap;
814 va_copy(ap, *argptr);
815
816 /* print argument list into message */
817 int n = vsnprintf(buf, bufsize-1, format, ap);
818
819 //printf("vsnprintf [%s] %d %d\n", format, bufsize, n);
820
821 va_end(ap);
822
823 if (n < bufsize) {
824 break;
825 }
826
827 bufsize += 100;
828 bufsize *= 2;
829 buf = (char*)realloc(buf, bufsize);
830 assert(buf);
831 }
832
833 message += buf;
834 free(buf);
835
836 return message;
837}
#define MT_LOG_STR
Definition midas.h:555
#define MT_INFO_STR
Definition midas.h:552
#define MT_INFO
Definition midas.h:543
#define MT_DEBUG_STR
Definition midas.h:553
#define MT_TALK
Definition midas.h:547
#define MT_USER
Definition midas.h:545
#define MT_USER_STR
Definition midas.h:554
#define MT_TALK_STR
Definition midas.h:556
#define MT_DEBUG
Definition midas.h:544
#define MT_ERROR
Definition midas.h:542
#define MT_ERROR_STR
Definition midas.h:551
std::string rpc_get_name()
Definition midas.cxx:13122
DWORD n[4]
Definition mana.cxx:247
#define name(x)
Definition midas_macro.h:24
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cm_msg_get_logfile()

void cm_msg_get_logfile ( const char fac,
time_t  t,
std::string *  filename,
std::string *  linkname,
std::string *  linktarget 
)

Definition at line 552 of file midas.cxx.

552 {
553 HNDLE hDB;
554 int status;
555
557
558 // check for call to cm_msg() before MIDAS is fully initialized
559 // or after MIDAS is partially shutdown.
560 if (status != CM_SUCCESS) {
561 if (filename)
562 *filename = std::string(fac) + ".log";
563 if (linkname)
564 *linkname = "";
565 if (linktarget)
566 *linktarget = "";
567 return;
568 }
569
570 if (filename)
571 *filename = "";
572 if (linkname)
573 *linkname = "";
574 if (linktarget)
575 *linktarget = "";
576
577 std::string facility;
578 if (fac && fac[0])
579 facility = fac;
580 else
581 facility = "midas";
582
583 std::string message_format;
584 db_get_value_string(hDB, 0, "/Logger/Message file date format", 0, &message_format, TRUE);
585 if (message_format.find('%') != std::string::npos) {
586 /* replace stings such as %y%m%d with current date */
587 struct tm tms;
588
589 ss_tzset();
590 if (t == 0)
591 time(&t);
592 localtime_r(&t, &tms);
593
594 char de[256];
595 de[0] = '_';
596 strftime(de + 1, sizeof(de)-1, strchr(message_format.c_str(), '%'), &tms);
598 }
599
600 std::string message_dir;
601 db_get_value_string(hDB, 0, "/Logger/Message dir", 0, &message_dir, TRUE);
602 if (message_dir.empty()) {
603 db_get_value_string(hDB, 0, "/Logger/Data dir", 0, &message_dir, FALSE);
604 if (message_dir.empty()) {
606 if (message_dir.empty()) {
608 }
609 }
610 }
611
612 // prepend experiment directory
613 if (message_dir[0] != DIR_SEPARATOR)
615
616 if (message_dir.back() != DIR_SEPARATOR)
617 message_dir.push_back(DIR_SEPARATOR);
618
619 if (filename)
620 *filename = message_dir + facility + message_format + ".log";
621 if (!message_format.empty()) {
622 if (linkname)
623 *linkname = message_dir + facility + ".log";
624 if (linktarget)
625 *linktarget = facility + message_format + ".log";
626 }
627}
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition midas.cxx:3026
std::string cm_get_path()
Definition midas.cxx:1552
std::string ss_getcwd()
Definition system.cxx:5848
void ss_tzset()
Definition system.cxx:3427
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:13948
HNDLE hDB
main ODB handle
Definition mana.cxx:207
INT HNDLE
Definition midas.h:132
MUTEX_T * tm
Definition odbedit.cxx:39
static double fac(double a)
Definition tinyexpr.c:137
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cm_msg_log()

INT cm_msg_log ( INT  message_type,
const char facility,
const char message 
)

Write message to logging file. Called by cm_msg.

Attention
May burn your fingers
Parameters
message_typeMessage type
messageMessage string
facilityMessage facility, filename in which messages will be written
Returns
CM_SUCCESS

Definition at line 677 of file midas.cxx.

677 {
678 INT status;
679
680 if (rpc_is_remote()) {
681 if (rpc_is_connected()) {
682 status = rpc_call(RPC_CM_MSG_LOG, message_type, facility, message);
683 if (status != RPC_SUCCESS) {
684 fprintf(stderr, "cm_msg_log: Message \"%s\" not written to midas.log because rpc_call(RPC_CM_MSG_LOG) failed with status %d\n", message, status);
685 }
686 return status;
687 } else {
688 fprintf(stderr, "cm_msg_log: Message \"%s\" not written to midas.log, no connection to mserver\n", message);
689 return RPC_NET_ERROR;
690 }
691 }
692
693 if (message_type != MT_DEBUG) {
694 std::string filename, linkname, linktarget;
695
697
698#ifdef OS_LINUX
699 if (!linkname.empty()) {
700 //printf("cm_msg_log: filename [%s] linkname [%s] linktarget [%s]\n", filename.c_str(), linkname.c_str(), linktarget.c_str());
701 // If filename does not exist, user just switched from non-date format to date format.
702 // In that case we must copy linkname to filename, otherwise messages might get lost.
703 if (ss_file_exist(linkname.c_str()) && !ss_file_link_exist(linkname.c_str())) {
704 ss_file_copy(linkname.c_str(), filename.c_str(), true);
705 }
706
707 unlink(linkname.c_str());
708 status = symlink(linktarget.c_str(), linkname.c_str());
709 if (status != 0) {
711 "cm_msg_log: Error: Cannot symlink message log file \'%s' to \'%s\', symlink() errno: %d (%s)\n",
712 linktarget.c_str(), linkname.c_str(), errno, strerror(errno));
713 }
714 }
715#endif
716
717 int fh = open(filename.c_str(), O_WRONLY | O_CREAT | O_APPEND | O_LARGEFILE, 0644);
718 if (fh < 0) {
720 "cm_msg_log: Message \"%s\" not written to midas.log because open(%s) failed with errno %d (%s)\n",
721 message, filename.c_str(), errno, strerror(errno));
722 } else {
723
724 struct timeval tv;
725 struct tm tms;
726
727 ss_tzset();
729 localtime_r(&tv.tv_sec, &tms);
730
731 char str[256];
732 strftime(str, sizeof(str), "%H:%M:%S", &tms);
733 sprintf(str + strlen(str), ".%03d ", (int) (tv.tv_usec / 1000));
734 strftime(str + strlen(str), sizeof(str), "%G/%m/%d", &tms);
735
736 std::string msg;
737 msg += str;
738 msg += " ";
739 msg += message;
740 msg += "\n";
741
742 /* avoid c++ complaint about comparison between
743 unsigned size_t returned by msg.length() and
744 signed ssize_t returned by write() */
745 ssize_t len = msg.length();
746
747 /* atomic write, no need to take a semaphore */
748 ssize_t wr = write(fh, msg.c_str(), len);
749
750 if (wr < 0) {
751 fprintf(stderr, "cm_msg_log: Message \"%s\" not written to \"%s\", write() error, errno %d (%s)\n", message, filename.c_str(), errno, strerror(errno));
752 } else if (wr != len) {
753 fprintf(stderr, "cm_msg_log: Message \"%s\" not written to \"%s\", short write() wrote %d instead of %d bytes\n", message, filename.c_str(), (int)wr, (int)len);
754 }
755
756 close(fh);
757 }
758 }
759
760 return CM_SUCCESS;
761}
#define RPC_SUCCESS
Definition midas.h:699
#define RPC_NET_ERROR
Definition midas.h:702
int ss_file_exist(const char *path)
Definition system.cxx:7196
int ss_file_link_exist(const char *path)
Definition system.cxx:7232
int ss_file_copy(const char *src, const char *dst, bool append)
Definition system.cxx:7297
bool rpc_is_remote(void)
Definition midas.cxx:12799
bool rpc_is_connected(void)
Definition midas.cxx:12821
INT rpc_call(DWORD routine_id,...)
Definition midas.cxx:13701
#define RPC_CM_MSG_LOG
Definition mrpc.h:25
#define O_LARGEFILE
Definition midas.h:210
int INT
Definition midas.h:129
#define write(n, a, f, d)
int gettimeofday(struct timeval *tp, void *tzp)
timeval tv
Definition msysmon.cxx:1095
char str[256]
Definition odbhist.cxx:33
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cm_msg_open_buffer()

int cm_msg_open_buffer ( void  )

Definition at line 487 of file midas.cxx.

487 {
488 //printf("cm_msg_open_buffer!\n");
489 if (_msg_buffer == 0) {
491 if (status != BM_SUCCESS && status != BM_CREATED) {
492 return status;
493 }
494 }
495 return CM_SUCCESS;
496}
INT bm_open_buffer(const char *buffer_name, INT buffer_size, INT *buffer_handle)
Definition midas.cxx:6740
#define BM_SUCCESS
Definition midas.h:605
#define BM_CREATED
Definition midas.h:606
#define MESSAGE_BUFFER_NAME
Definition msystem.h:111
#define MESSAGE_BUFFER_SIZE
Definition msystem.h:110
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cm_msg_register()

INT cm_msg_register ( EVENT_HANDLER func)

Register a dispatch function for receiving system messages.

Definition at line 1066 of file midas.cxx.

1066 {
1067 INT status, id;
1068
1069 // we should only come here after the message buffer
1070 // was opened by cm_connect_experiment()
1071 assert(_msg_buffer);
1072
1073 _msg_dispatch = func;
1074
1076
1077 return status;
1078}
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:8488
#define GET_NONBLOCKING
Definition midas.h:322
#define TRIGGER_ALL
Definition midas.h:538
#define EVENTID_ALL
Definition midas.h:537
static EVENT_HANDLER * _msg_dispatch
Definition midas.cxx:199
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cm_msg_retrieve()

INT cm_msg_retrieve ( INT  n_message,
char message,
INT  buf_size 
)

Retrieve newest messages from "midas" facility log file

Parameters
n_messageNumber of messages to retrieve
messagebuf_size bytes of messages, separated by
characters. The returned number of bytes is normally smaller than the initial buf_size, since only full lines are returned.
*buf_sizeSize of message buffer to fill
Returns
CM_SUCCESS, CM_TRUNCATED

Definition at line 1349 of file midas.cxx.

1349 {
1350 int status;
1351 char *messages = NULL;
1352 int num_messages = 0;
1353
1354 if (rpc_is_remote())
1355 return rpc_call(RPC_CM_MSG_RETRIEVE, n_message, message, buf_size);
1356
1358
1359 if (messages) {
1360 mstrlcpy(message, messages, buf_size);
1361 int len = strlen(messages);
1362 if (len > buf_size)
1364 free(messages);
1365 }
1366
1367 return status;
1368}
#define CM_TRUNCATED
Definition midas.h:596
INT cm_msg_retrieve2(const char *facility, time_t t, INT n_message, char **messages, int *num_messages)
Definition midas.cxx:1279
#define RPC_CM_MSG_RETRIEVE
Definition mrpc.h:32
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cm_msg_retrieve1()

static int cm_msg_retrieve1 ( const char filename,
time_t  t,
INT  n_messages,
char **  messages,
int length,
int allocated,
int num_messages 
)
static

Definition at line 1111 of file midas.cxx.

1112 {
1113 BOOL stop;
1114 int fh;
1115 char *p, str[1000];
1116 struct stat stat_buf;
1118
1119 ss_tzset(); // required by localtime_r()
1120
1121 *num_messages = 0;
1122
1123 fh = open(filename, O_RDONLY | O_TEXT, 0644);
1124 if (fh < 0) {
1125 cm_msg(MERROR, "cm_msg_retrieve1", "Cannot open log file \"%s\", errno %d (%s)", filename, errno,
1126 strerror(errno));
1127 return SS_FILE_ERROR;
1128 }
1129
1130 /* read whole file into memory */
1131 fstat(fh, &stat_buf);
1132 ssize_t size = stat_buf.st_size;
1133
1134 /* if file is too big, only read tail of file */
1135 ssize_t maxsize = 10 * 1024 * 1024;
1136 if (size > maxsize) {
1138 //printf("lseek status %d, errno %d (%s)\n", status, errno, strerror(errno));
1139 size = maxsize;
1140 }
1141
1142 char *buffer = (char *) malloc(size + 1);
1143
1144 if (buffer == NULL) {
1145 cm_msg(MERROR, "cm_msg_retrieve1", "Cannot malloc %d bytes to read log file \"%s\", errno %d (%s)", (int) size,
1146 filename, errno, strerror(errno));
1147 close(fh);
1148 return SS_FILE_ERROR;
1149 }
1150
1151 ssize_t rd = read(fh, buffer, size);
1152
1153 if (rd != size) {
1154 cm_msg(MERROR, "cm_msg_retrieve1", "Cannot read %d bytes from log file \"%s\", read() returned %d, errno %d (%s)",
1155 (int) size, filename, (int) rd, errno, strerror(errno));
1156 close(fh);
1157 return SS_FILE_ERROR;
1158 }
1159
1160 buffer[size] = 0;
1161 close(fh);
1162
1163 p = buffer + size - 1;
1165 stop = FALSE;
1166
1167 while (*p == '\n' || *p == '\r')
1168 p--;
1169
1170 int n;
1171 for (n = 0; !stop && p > buffer;) {
1172
1173 /* go to beginning of line */
1174 int i;
1175 for (i = 0; p != buffer && (*p != '\n' && *p != '\r'); i++)
1176 p--;
1177
1178 /* limit line length to sizeof(str) */
1179 if (i >= (int) sizeof(str))
1180 i = sizeof(str) - 1;
1181
1182 if (p == buffer) {
1183 i++;
1184 memcpy(str, p, i);
1185 } else
1186 memcpy(str, p + 1, i);
1187 str[i] = 0;
1188 if (strchr(str, '\n'))
1189 *strchr(str, '\n') = 0;
1190 if (strchr(str, '\r'))
1191 *strchr(str, '\r') = 0;
1192 mstrlcat(str, "\n", sizeof(str));
1193
1194 // extract time tag
1195 time_t now;
1196 time(&now);
1197
1198 struct tm tms;
1199 localtime_r(&now, &tms); // must call tzset() beforehand!
1200
1201 if (str[0] >= '0' && str[0] <= '9') {
1202 // new format
1203 tms.tm_hour = atoi(str);
1204 tms.tm_min = atoi(str + 3);
1205 tms.tm_sec = atoi(str + 6);
1206 tms.tm_year = atoi(str + 13) - 1900;
1207 tms.tm_mon = atoi(str + 18) - 1;
1208 tms.tm_mday = atoi(str + 21);
1209 } else {
1210 // old format
1211 tms.tm_hour = atoi(str + 11);
1212 tms.tm_min = atoi(str + 14);
1213 tms.tm_sec = atoi(str + 17);
1214 tms.tm_year = atoi(str + 20) - 1900;
1215 for (i = 0; i < 12; i++)
1216 if (strncmp(str + 4, mname[i], 3) == 0)
1217 break;
1218 tms.tm_mon = i;
1219 tms.tm_mday = atoi(str + 8);
1220 }
1221 tstamp = ss_mktime(&tms);
1222 if (tstamp != -1)
1224
1225 // for new messages (n=0!), stop when t reached
1226 if (n_messages == 0) {
1227 if (tstamp_valid < t)
1228 break;
1229 }
1230
1231 // for old messages, stop when all messages belonging to tstamp_last are sent
1232 if (n_messages != 0) {
1234 break;
1235 }
1236
1237 if (t == 0 || tstamp == -1 ||
1238 (n_messages > 0 && tstamp <= t) ||
1239 (n_messages == 0 && tstamp >= t)) {
1240
1241 n++;
1242
1244 }
1245
1246 while (*p == '\n' || *p == '\r')
1247 p--;
1248
1249 if (n_messages == 1)
1250 stop = TRUE;
1251 else if (n_messages > 1) {
1252 // continue collecting messages until time stamp differs from current one
1253 if (n == n_messages)
1255
1256 // if all messages without time tags, just return after n
1257 if (n == n_messages && tstamp_valid == 0)
1258 break;
1259 }
1260 }
1261
1262 free(buffer);
1263
1264 *num_messages = n;
1265
1266 return CM_SUCCESS;
1267}
#define SS_FILE_ERROR
Definition midas.h:670
#define MERROR
Definition midas.h:559
#define O_TEXT
Definition msystem.h:227
time_t ss_mktime(struct tm *tms)
Definition system.cxx:3437
static void add_message(char **messages, int *length, int *allocated, time_t tstamp, const char *new_message)
Definition midas.cxx:1080
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
Definition midas.cxx:930
const char * mname[]
Definition midas.cxx:144
#define read(n, a, f)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cm_msg_retrieve2()

INT cm_msg_retrieve2 ( const char facility,
time_t  t,
INT  n_message,
char **  messages,
int num_messages 
)

Retrieve old messages from log file

Parameters
facilityLogging facility ("midas", "chat", "lazy", ...)
tReturn messages logged before and including time t, value 0 means start with newest messages
min_messagesMinimum number of messages to return
messagesmessages, newest first, separated by
characters. caller should free() this buffer at the end.
num_messagesNumber of messages returned
Returns
CM_SUCCESS

Definition at line 1279 of file midas.cxx.

1279 {
1280 std::string filename, linkname;
1281 INT n, i;
1283 int length = 0;
1284 int allocated = 0;
1285
1286 time(&filedate);
1288
1289 //printf("facility %s, filename \"%s\" \"%s\"\n", facility, filename, linkname);
1290
1291 // see if file exists, use linkname if not
1292 if (!linkname.empty()) {
1293 if (!ss_file_exist(filename.c_str()))
1294 filename = linkname;
1295 }
1296
1297 if (ss_file_exist(filename.c_str())) {
1298 cm_msg_retrieve1(filename.c_str(), t, n_message, messages, &length, &allocated, &n);
1299 } else {
1300 n = 0;
1301 }
1302
1303 /* if there is no symlink, then there is no additional log files to read */
1304 if (linkname.empty()) {
1305 *num_messages = n;
1306 return CM_SUCCESS;
1307 }
1308
1309 //printf("read more messages %d %d!\n", n, n_message);
1310
1311 int missing = 0;
1312 while (n < n_message) {
1313 filedate -= 3600 * 24; // go one day back
1314
1316
1317 //printf("read [%s] for time %d!\n", filename.c_str(), filedate);
1318
1319 if (ss_file_exist(filename.c_str())) {
1320 cm_msg_retrieve1(filename.c_str(), t, n_message - n, messages, &length, &allocated, &i);
1321 n += i;
1322 missing = 0;
1323 } else {
1324 missing++;
1325 }
1326
1327 // stop if ten consecutive files are not found
1328 if (missing > 10)
1329 break;
1330 }
1331
1332 *num_messages = n;
1333
1334 return CM_SUCCESS;
1335}
static int cm_msg_retrieve1(const char *filename, time_t t, INT n_messages, char **messages, int *length, int *allocated, int *num_messages)
Definition midas.cxx:1111
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cm_msg_send_event()

static INT cm_msg_send_event ( DWORD  ts,
INT  message_type,
const char send_message 
)
static

Definition at line 839 of file midas.cxx.

839 {
840 //printf("cm_msg_send: ts %d, type %d, message [%s]\n", ts, message_type, send_message);
841
842 /* send event if not of type MLOG */
843 if (message_type != MT_LOG) {
844 if (_msg_buffer) {
845 /* copy message to event */
846 size_t len = strlen(send_message);
847 int event_length = sizeof(EVENT_HEADER) + len + 1;
848 char event[event_length];
849 EVENT_HEADER *pevent = (EVENT_HEADER *) event;
850
851 memcpy(event + sizeof(EVENT_HEADER), send_message, len + 1);
852
853 /* setup the event header and send the message */
854 bm_compose_event(pevent, EVENTID_MESSAGE, (WORD) message_type, len + 1, 0);
855 if (ts)
856 pevent->time_stamp = ts;
857 //printf("cm_msg_send_event: len %d, header %d, allocated %d, data_size %d, bm_send_event %p+%d\n", (int)len, (int)sizeof(EVENT_HEADER), event_length, pevent->data_size, pevent, (int)(pevent->data_size + sizeof(EVENT_HEADER)));
858 bm_send_event(_msg_buffer, pevent, 0, BM_WAIT);
859 }
860 }
861
862 return CM_SUCCESS;
863}
INT bm_send_event(INT buffer_handle, const EVENT_HEADER *pevent, int unused, int timeout_msec)
Definition midas.cxx:9701
INT bm_compose_event(EVENT_HEADER *event_header, short int event_id, short int trigger_mask, DWORD data_size, DWORD serial)
Definition midas.cxx:8304
unsigned short int WORD
Definition mcstd.h:49
#define BM_WAIT
Definition midas.h:365
#define EVENTID_MESSAGE
Definition midas.h:903
DWORD time_stamp
Definition midas.h:856
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cm_set_msg_print()

INT cm_set_msg_print ( INT  system_mask,
INT  user_mask,
int(*)(const char *)  func 
)

Set message masks. When a message is generated by calling cm_msg(), it can got to two destinatinons. First a user defined callback routine and second to the "SYSMSG" buffer.

A user defined callback receives all messages which satisfy the user_mask.

int message_print(const char *msg)
{
char str[160];
memset(str, ' ', 159);
str[159] = 0;
if (msg[0] == '[')
msg = strchr(msg, ']')+2;
memcpy(str, msg, strlen(msg));
ss_printf(0, 20, str);
return 0;
}
...
...
#define MT_ALL
Definition midas.h:549
void ss_printf(INT x, INT y, const char *format,...)
Definition system.cxx:7460
INT cm_set_msg_print(INT system_mask, INT user_mask, int(*func)(const char *))
Definition midas.cxx:660
static int message_print(const char *msg)
Definition mfe.cxx:1348
Parameters
system_maskBit masks for MERROR, MINFO etc. to send system messages.
user_maskBit masks for MERROR, MINFO etc. to send messages to the user callback.
funcFunction which receives all printout. By setting "puts", messages are just printed to the screen.
Returns
CM_SUCCESS

Definition at line 660 of file midas.cxx.

660 {
663 _message_print = func;
664
665 return BM_SUCCESS;
666}
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ gMsgBuf

std::deque<msg_buffer_entry> gMsgBuf
static

Definition at line 871 of file midas.cxx.

◆ gMsgBufMutex

std::mutex gMsgBufMutex
static

Definition at line 872 of file midas.cxx.