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 1065 of file midas.cxx.

1065 {
1067 int new_allocated = 1024 + 2 * ((*allocated) + new_message_length);
1068 char buf[100];
1069 int buf_length;
1070
1071 //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);
1072
1073 if (*length + new_message_length + 100 > *allocated) {
1074 *messages = (char *) realloc(*messages, new_allocated);
1075 assert(*messages != NULL);
1077 }
1078
1079 if (*length > 0)
1080 if ((*messages)[(*length) - 1] != '\n') {
1081 (*messages)[*length] = '\n'; // separator between messages
1082 (*length) += 1;
1083 }
1084
1085 sprintf(buf, "%ld ", tstamp);
1086 buf_length = strlen(buf);
1087 memcpy(&((*messages)[*length]), buf, buf_length);
1088 (*length) += buf_length;
1089
1091 (*length) += new_message_length;
1092 (*messages)[*length] = 0; // make sure string is NUL terminated
1093}
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 455 of file midas.cxx.

456{
457 for (int i = 0; _error_table[i].code; i++) {
458 if (_error_table[i].code == code) {
459 return _error_table[i].string;
460 }
461 }
462
463 return msprintf("unlisted status code %d", code);
464}
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:410
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:1311
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 915 of file midas.cxx.

916{
917 DWORD ts = ss_time();
918
919 /* print argument list into message */
920 std::string message;
922 va_start(argptr, format);
923 message = cm_msg_format(message_type, filename, line, routine, format, &argptr);
924 va_end(argptr);
925
926 //printf("message [%s]\n", message.c_str());
927
928 /* call user function if set via cm_set_msg_print */
930 if (f != NULL && (message_type & _message_mask_user) != 0) {
931 if (message_type != MT_LOG) { // do not print MLOG messages
932 (*f)(message.c_str());
933 }
934 }
935
936 /* return if system mask is not set */
937 if ((message_type & _message_mask_system) == 0) {
938 return CM_SUCCESS;
939 }
940
941 gMsgBufMutex.lock();
942 gMsgBuf.push_back(msg_buffer_entry{ts, message_type, message});
943 gMsgBufMutex.unlock();
944
945 return CM_SUCCESS;
946}
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:3462
static std::mutex gMsgBufMutex
Definition midas.cxx:857
static std::deque< msg_buffer_entry > gMsgBuf
Definition midas.cxx:856
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:751
static std::atomic_int _message_mask_system
Definition midas.cxx:435
int(* MessagePrintCallback)(const char *)
Definition midas.cxx:431
static std::atomic< MessagePrintCallback > _message_print
Definition midas.cxx:433
static std::atomic_int _message_mask_user
Definition midas.cxx:436
Definition midas.cxx:850
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:973
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 973 of file midas.cxx.

974 {
976 std::string message;
977 static BOOL in_routine = FALSE;
978
979 /* avoid recursive calles */
980 if (in_routine)
981 return 0;
982
984
985 /* print argument list into message */
986 va_start(argptr, format);
987 message = cm_msg_format(message_type, filename, line, routine, format, &argptr);
988 va_end(argptr);
989
990 /* call user function if set via cm_set_msg_print */
992 if (f != NULL && (message_type & _message_mask_user) != 0)
993 (*f)(message.c_str());
994
995 /* return if system mask is not set */
996 if ((message_type & _message_mask_system) == 0) {
998 return CM_SUCCESS;
999 }
1000
1001 /* send message to SYSMSG */
1002 cm_msg_send_event(0, message_type, message.c_str());
1003
1004 /* log message */
1005 cm_msg_log(message_type, facility, message.c_str());
1006
1007 in_routine = FALSE;
1008
1009 return CM_SUCCESS;
1010}
#define FALSE
Definition cfortran.h:309
INT cm_msg_log(INT message_type, const char *facility, const char *message)
Definition midas.cxx:664
static INT cm_msg_send_event(DWORD ts, INT message_type, const char *send_message)
Definition midas.cxx:824
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 487 of file midas.cxx.

487 {
488 //printf("cm_msg_close_buffer!\n");
489 if (_msg_buffer) {
491 _msg_buffer = 0;
492 }
493 return CM_SUCCESS;
494}
INT bm_close_buffer(INT buffer_handle)
Definition midas.cxx:7096
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 467 of file midas.cxx.

467 {
468
469 return CM_SUCCESS;
470}
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 504 of file midas.cxx.

504 {
505 std::string path;
506
507 cm_msg_get_logfile("midas", 0, &path, NULL, NULL);
508
509 /* extract directory name from full path name of midas.log */
510 size_t pos = path.rfind(DIR_SEPARATOR);
511 if (pos != std::string::npos) {
512 path.resize(pos);
513 } else {
514 path = "";
515 }
516
517 //printf("cm_msg_facilities: path [%s]\n", path.c_str());
518
520
521 ss_file_find(path.c_str(), "*.log", &flist);
522
523 for (size_t i = 0; i < flist.size(); i++) {
524 const char *p = flist[i].c_str();
525 if (strchr(p, '_') == NULL && !(p[0] >= '0' && p[0] <= '9')) {
526 size_t pos = flist[i].rfind('.');
527 if (pos != std::string::npos) {
528 flist[i].resize(pos);
529 }
530 list->push_back(flist[i]);
531 }
532 }
533
534 return SUCCESS;
535}
#define SUCCESS
Definition mcstd.h:54
INT ss_file_find(const char *path, const char *pattern, char **plist)
Definition system.cxx:6713
void cm_msg_get_logfile(const char *fac, time_t t, std::string *filename, std::string *linkname, std::string *linktarget)
Definition midas.cxx:539
#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 865 of file midas.cxx.

865 {
866 int i;
867
868 //printf("cm_msg_flush_buffer!\n");
869
870 for (i = 0; i < 100; i++) {
872 {
873 std::lock_guard<std::mutex> lock(gMsgBufMutex);
874 if (gMsgBuf.empty())
875 break;
876 e = gMsgBuf.front();
877 gMsgBuf.pop_front();
878 // implicit unlock
879 }
880
881 /* log message */
882 cm_msg_log(e.message_type, "midas", e.message.c_str());
883
884 /* send message to SYSMSG */
885 int status = cm_msg_send_event(e.ts, e.message_type, e.message.c_str());
886 if (status != CM_SUCCESS)
887 return status;
888 }
889
890 return CM_SUCCESS;
891}
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 751 of file midas.cxx.

752{
753 /* strip path */
754 const char* pc = filename + strlen(filename);
755 while (*pc != '\\' && *pc != '/' && pc != filename)
756 pc--;
757 if (pc != filename)
758 pc++;
759
760 /* convert type to string */
761 std::string type_str;
762 if (message_type & MT_ERROR)
764 if (message_type & MT_INFO)
766 if (message_type & MT_DEBUG)
768 if (message_type & MT_USER)
770 if (message_type & MT_LOG)
772 if (message_type & MT_TALK)
774
775 std::string message;
776
777 /* print client name into string */
778 if (message_type == MT_USER)
779 message = msprintf("[%s] ", routine);
780 else {
781 std::string name = rpc_get_name();
782 if (name.length() > 0)
783 message = msprintf("[%s,%s] ", name.c_str(), type_str.c_str());
784 else
785 message = "";
786 }
787
788 /* preceed error messages with file and line info */
789 if (message_type == MT_ERROR) {
790 message += msprintf("[%s:%d:%s,%s] ", pc, line, routine, type_str.c_str());
791 } else if (message_type == MT_USER) {
792 message = msprintf("[%s,%s] ", routine, type_str.c_str());
793 }
794
795 int bufsize = 1024;
796 char* buf = (char*)malloc(bufsize);
797 assert(buf);
798
799 for (int i=0; i<10; i++) {
800 va_list ap;
801 va_copy(ap, *argptr);
802
803 /* print argument list into message */
804 int n = vsnprintf(buf, bufsize-1, format, ap);
805
806 //printf("vsnprintf [%s] %d %d\n", format, bufsize, n);
807
808 if (n < bufsize) {
809 break;
810 }
811
812 bufsize += 100;
813 bufsize *= 2;
814 buf = (char*)realloc(buf, bufsize);
815 assert(buf);
816 }
817
818 message += buf;
819 free(buf);
820
821 return message;
822}
#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:13084
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 539 of file midas.cxx.

539 {
540 HNDLE hDB;
541 int status;
542
544
545 // check for call to cm_msg() before MIDAS is fully initialized
546 // or after MIDAS is partially shutdown.
547 if (status != CM_SUCCESS) {
548 if (filename)
549 *filename = std::string(fac) + ".log";
550 if (linkname)
551 *linkname = "";
552 if (linktarget)
553 *linktarget = "";
554 return;
555 }
556
557 if (filename)
558 *filename = "";
559 if (linkname)
560 *linkname = "";
561 if (linktarget)
562 *linktarget = "";
563
564 std::string facility;
565 if (fac && fac[0])
566 facility = fac;
567 else
568 facility = "midas";
569
570 std::string message_format;
571 db_get_value_string(hDB, 0, "/Logger/Message file date format", 0, &message_format, TRUE);
572 if (message_format.find('%') != std::string::npos) {
573 /* replace stings such as %y%m%d with current date */
574 struct tm tms;
575
576 ss_tzset();
577 if (t == 0)
578 time(&t);
579 localtime_r(&t, &tms);
580
581 char de[256];
582 de[0] = '_';
583 strftime(de + 1, sizeof(de)-1, strchr(message_format.c_str(), '%'), &tms);
585 }
586
587 std::string message_dir;
588 db_get_value_string(hDB, 0, "/Logger/Message dir", 0, &message_dir, TRUE);
589 if (message_dir.empty()) {
590 db_get_value_string(hDB, 0, "/Logger/Data dir", 0, &message_dir, FALSE);
591 if (message_dir.empty()) {
593 if (message_dir.empty()) {
595 }
596 }
597 }
598
599 // prepend experiment directory
600 if (message_dir[0] != DIR_SEPARATOR)
602
603 if (message_dir.back() != DIR_SEPARATOR)
604 message_dir.push_back(DIR_SEPARATOR);
605
606 if (filename)
607 *filename = message_dir + facility + message_format + ".log";
608 if (!message_format.empty()) {
609 if (linkname)
610 *linkname = message_dir + facility + ".log";
611 if (linktarget)
612 *linktarget = facility + message_format + ".log";
613 }
614}
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition midas.cxx:3011
std::string cm_get_path()
Definition midas.cxx:1537
std::string ss_getcwd()
Definition system.cxx:5770
void ss_tzset()
Definition system.cxx:3355
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
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 664 of file midas.cxx.

664 {
665 INT status;
666
667 if (rpc_is_remote()) {
668 if (rpc_is_connected()) {
669 status = rpc_call(RPC_CM_MSG_LOG, message_type, facility, message);
670 if (status != RPC_SUCCESS) {
671 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);
672 }
673 return status;
674 } else {
675 fprintf(stderr, "cm_msg_log: Message \"%s\" not written to midas.log, no connection to mserver\n", message);
676 return RPC_NET_ERROR;
677 }
678 }
679
680 if (message_type != MT_DEBUG) {
681 std::string filename, linkname, linktarget;
682
684
685#ifdef OS_LINUX
686 if (!linkname.empty()) {
687 //printf("cm_msg_log: filename [%s] linkname [%s] linktarget [%s]\n", filename.c_str(), linkname.c_str(), linktarget.c_str());
688 // If filename does not exist, user just switched from non-date format to date format.
689 // In that case we must copy linkname to filename, otherwise messages might get lost.
690 if (ss_file_exist(linkname.c_str()) && !ss_file_link_exist(linkname.c_str())) {
691 ss_file_copy(linkname.c_str(), filename.c_str(), true);
692 }
693
694 unlink(linkname.c_str());
695 status = symlink(linktarget.c_str(), linkname.c_str());
696 if (status != 0) {
698 "cm_msg_log: Error: Cannot symlink message log file \'%s' to \'%s\', symlink() errno: %d (%s)\n",
699 linktarget.c_str(), linkname.c_str(), errno, strerror(errno));
700 }
701 }
702#endif
703
704 int fh = open(filename.c_str(), O_WRONLY | O_CREAT | O_APPEND | O_LARGEFILE, 0644);
705 if (fh < 0) {
707 "cm_msg_log: Message \"%s\" not written to midas.log because open(%s) failed with errno %d (%s)\n",
708 message, filename.c_str(), errno, strerror(errno));
709 } else {
710
711 struct timeval tv;
712 struct tm tms;
713
714 ss_tzset();
716 localtime_r(&tv.tv_sec, &tms);
717
718 char str[256];
719 strftime(str, sizeof(str), "%H:%M:%S", &tms);
720 sprintf(str + strlen(str), ".%03d ", (int) (tv.tv_usec / 1000));
721 strftime(str + strlen(str), sizeof(str), "%G/%m/%d", &tms);
722
723 std::string msg;
724 msg += str;
725 msg += " ";
726 msg += message;
727 msg += "\n";
728
729 /* avoid c++ complaint about comparison between
730 unsigned size_t returned by msg.length() and
731 signed ssize_t returned by write() */
732 ssize_t len = msg.length();
733
734 /* atomic write, no need to take a semaphore */
735 ssize_t wr = write(fh, msg.c_str(), len);
736
737 if (wr < 0) {
738 fprintf(stderr, "cm_msg_log: Message \"%s\" not written to \"%s\", write() error, errno %d (%s)\n", message, filename.c_str(), errno, strerror(errno));
739 } else if (wr != len) {
740 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);
741 }
742
743 close(fh);
744 }
745 }
746
747 return CM_SUCCESS;
748}
#define RPC_SUCCESS
Definition midas.h:698
#define RPC_NET_ERROR
Definition midas.h:701
int ss_file_exist(const char *path)
Definition system.cxx:7118
int ss_file_link_exist(const char *path)
Definition system.cxx:7154
int ss_file_copy(const char *src, const char *dst, bool append)
Definition system.cxx:7219
bool rpc_is_remote(void)
Definition midas.cxx:12761
bool rpc_is_connected(void)
Definition midas.cxx:12783
INT rpc_call(DWORD routine_id,...)
Definition midas.cxx:13663
#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 474 of file midas.cxx.

474 {
475 //printf("cm_msg_open_buffer!\n");
476 if (_msg_buffer == 0) {
478 if (status != BM_SUCCESS && status != BM_CREATED) {
479 return status;
480 }
481 }
482 return CM_SUCCESS;
483}
INT bm_open_buffer(const char *buffer_name, INT buffer_size, INT *buffer_handle)
Definition midas.cxx:6717
#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 1051 of file midas.cxx.

1051 {
1052 INT status, id;
1053
1054 // we should only come here after the message buffer
1055 // was opened by cm_connect_experiment()
1056 assert(_msg_buffer);
1057
1058 _msg_dispatch = func;
1059
1061
1062 return status;
1063}
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
#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 1334 of file midas.cxx.

1334 {
1335 int status;
1336 char *messages = NULL;
1337 int num_messages = 0;
1338
1339 if (rpc_is_remote())
1340 return rpc_call(RPC_CM_MSG_RETRIEVE, n_message, message, buf_size);
1341
1343
1344 if (messages) {
1345 mstrlcpy(message, messages, buf_size);
1346 int len = strlen(messages);
1347 if (len > buf_size)
1349 free(messages);
1350 }
1351
1352 return status;
1353}
#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:1264
#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 1096 of file midas.cxx.

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

1264 {
1265 std::string filename, linkname;
1266 INT n, i;
1268 int length = 0;
1269 int allocated = 0;
1270
1271 time(&filedate);
1273
1274 //printf("facility %s, filename \"%s\" \"%s\"\n", facility, filename, linkname);
1275
1276 // see if file exists, use linkname if not
1277 if (!linkname.empty()) {
1278 if (!ss_file_exist(filename.c_str()))
1279 filename = linkname;
1280 }
1281
1282 if (ss_file_exist(filename.c_str())) {
1283 cm_msg_retrieve1(filename.c_str(), t, n_message, messages, &length, &allocated, &n);
1284 } else {
1285 n = 0;
1286 }
1287
1288 /* if there is no symlink, then there is no additional log files to read */
1289 if (linkname.empty()) {
1290 *num_messages = n;
1291 return CM_SUCCESS;
1292 }
1293
1294 //printf("read more messages %d %d!\n", n, n_message);
1295
1296 int missing = 0;
1297 while (n < n_message) {
1298 filedate -= 3600 * 24; // go one day back
1299
1301
1302 //printf("read [%s] for time %d!\n", filename.c_str(), filedate);
1303
1304 if (ss_file_exist(filename.c_str())) {
1305 cm_msg_retrieve1(filename.c_str(), t, n_message - n, messages, &length, &allocated, &i);
1306 n += i;
1307 missing = 0;
1308 } else {
1309 missing++;
1310 }
1311
1312 // stop if ten consecutive files are not found
1313 if (missing > 10)
1314 break;
1315 }
1316
1317 *num_messages = n;
1318
1319 return CM_SUCCESS;
1320}
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:1096
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 824 of file midas.cxx.

824 {
825 //printf("cm_msg_send: ts %d, type %d, message [%s]\n", ts, message_type, send_message);
826
827 /* send event if not of type MLOG */
828 if (message_type != MT_LOG) {
829 if (_msg_buffer) {
830 /* copy message to event */
831 size_t len = strlen(send_message);
832 int event_length = sizeof(EVENT_HEADER) + len + 1;
833 char event[event_length];
834 EVENT_HEADER *pevent = (EVENT_HEADER *) event;
835
836 memcpy(event + sizeof(EVENT_HEADER), send_message, len + 1);
837
838 /* setup the event header and send the message */
839 bm_compose_event(pevent, EVENTID_MESSAGE, (WORD) message_type, len + 1, 0);
840 if (ts)
841 pevent->time_stamp = ts;
842 //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)));
843 bm_send_event(_msg_buffer, pevent, 0, BM_WAIT);
844 }
845 }
846
847 return CM_SUCCESS;
848}
INT bm_send_event(INT buffer_handle, const EVENT_HEADER *pevent, int unused, int timeout_msec)
Definition midas.cxx:9678
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
unsigned short int WORD
Definition mcstd.h:49
#define BM_WAIT
Definition midas.h:365
#define EVENTID_MESSAGE
Definition midas.h:902
DWORD time_stamp
Definition midas.h:855
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:7382
INT cm_set_msg_print(INT system_mask, INT user_mask, int(*func)(const char *))
Definition midas.cxx:647
static int message_print(const char *msg)
Definition mfe.cxx:1369
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 647 of file midas.cxx.

647 {
650 _message_print = func;
651
652 return BM_SUCCESS;
653}
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 856 of file midas.cxx.

◆ gMsgBufMutex

std::mutex gMsgBufMutex
static

Definition at line 857 of file midas.cxx.