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

1079 {
1081 int new_allocated = 1024 + 2 * ((*allocated) + new_message_length);
1082 char buf[100];
1083 int buf_length;
1084
1085 //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);
1086
1087 if (*length + new_message_length + 100 > *allocated) {
1088 *messages = (char *) realloc(*messages, new_allocated);
1089 assert(*messages != NULL);
1091 }
1092
1093 if (*length > 0)
1094 if ((*messages)[(*length) - 1] != '\n') {
1095 (*messages)[*length] = '\n'; // separator between messages
1096 (*length) += 1;
1097 }
1098
1099 sprintf(buf, "%ld ", tstamp);
1100 buf_length = strlen(buf);
1101 memcpy(&((*messages)[*length]), buf, buf_length);
1102 (*length) += buf_length;
1103
1105 (*length) += new_message_length;
1106 (*messages)[*length] = 0; // make sure string is NUL terminated
1107}
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 467 of file midas.cxx.

468{
469 for (int i = 0; _error_table[i].code; i++) {
470 if (_error_table[i].code == code) {
471 return _error_table[i].string;
472 }
473 }
474
475 return msprintf("unlisted status code %d", code);
476}
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 929 of file midas.cxx.

930{
931 DWORD ts = ss_time();
932
933 /* print argument list into message */
934 std::string message;
936 va_start(argptr, format);
937 message = cm_msg_format(message_type, filename, line, routine, format, &argptr);
938 va_end(argptr);
939
940 //printf("message [%s]\n", message.c_str());
941
942 /* call user function if set via cm_set_msg_print */
944 if (f != NULL && (message_type & _message_mask_user) != 0) {
945 if (message_type != MT_LOG) { // do not print MLOG messages
946 (*f)(message.c_str());
947 }
948 }
949
950 /* return if system mask is not set */
951 if ((message_type & _message_mask_system) == 0) {
952 return CM_SUCCESS;
953 }
954
955 gMsgBufMutex.lock();
956 gMsgBuf.push_back(msg_buffer_entry{ts, message_type, message});
957 gMsgBufMutex.unlock();
958
959 return CM_SUCCESS;
960}
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:871
static std::deque< msg_buffer_entry > gMsgBuf
Definition midas.cxx:870
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:763
static std::atomic_int _message_mask_system
Definition midas.cxx:447
int(* MessagePrintCallback)(const char *)
Definition midas.cxx:443
static std::atomic< MessagePrintCallback > _message_print
Definition midas.cxx:445
static std::atomic_int _message_mask_user
Definition midas.cxx:448
Definition midas.cxx:864
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:987
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 987 of file midas.cxx.

988 {
990 std::string message;
991 static BOOL in_routine = FALSE;
992
993 /* avoid recursive calles */
994 if (in_routine)
995 return 0;
996
998
999 /* print argument list into message */
1000 va_start(argptr, format);
1001 message = cm_msg_format(message_type, filename, line, routine, format, &argptr);
1002 va_end(argptr);
1003
1004 /* call user function if set via cm_set_msg_print */
1006 if (f != NULL && (message_type & _message_mask_user) != 0)
1007 (*f)(message.c_str());
1008
1009 /* return if system mask is not set */
1010 if ((message_type & _message_mask_system) == 0) {
1011 in_routine = FALSE;
1012 return CM_SUCCESS;
1013 }
1014
1015 /* send message to SYSMSG */
1016 cm_msg_send_event(0, message_type, message.c_str());
1017
1018 /* log message */
1019 cm_msg_log(message_type, facility, message.c_str());
1020
1021 in_routine = FALSE;
1022
1023 return CM_SUCCESS;
1024}
#define FALSE
Definition cfortran.h:309
INT cm_msg_log(INT message_type, const char *facility, const char *message)
Definition midas.cxx:676
static INT cm_msg_send_event(DWORD ts, INT message_type, const char *send_message)
Definition midas.cxx:838
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 499 of file midas.cxx.

499 {
500 //printf("cm_msg_close_buffer!\n");
501 if (_msg_buffer) {
503 _msg_buffer = 0;
504 }
505 return CM_SUCCESS;
506}
INT bm_close_buffer(INT buffer_handle)
Definition midas.cxx:7118
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 479 of file midas.cxx.

479 {
480
481 return CM_SUCCESS;
482}
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 516 of file midas.cxx.

516 {
517 std::string path;
518
519 cm_msg_get_logfile("midas", 0, &path, NULL, NULL);
520
521 /* extract directory name from full path name of midas.log */
522 size_t pos = path.rfind(DIR_SEPARATOR);
523 if (pos != std::string::npos) {
524 path.resize(pos);
525 } else {
526 path = "";
527 }
528
529 //printf("cm_msg_facilities: path [%s]\n", path.c_str());
530
532
533 ss_file_find(path.c_str(), "*.log", &flist);
534
535 for (size_t i = 0; i < flist.size(); i++) {
536 const char *p = flist[i].c_str();
537 if (strchr(p, '_') == NULL && !(p[0] >= '0' && p[0] <= '9')) {
538 size_t pos = flist[i].rfind('.');
539 if (pos != std::string::npos) {
540 flist[i].resize(pos);
541 }
542 list->push_back(flist[i]);
543 }
544 }
545
546 return SUCCESS;
547}
#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:551
#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 879 of file midas.cxx.

879 {
880 int i;
881
882 //printf("cm_msg_flush_buffer!\n");
883
884 for (i = 0; i < 100; i++) {
886 {
887 std::lock_guard<std::mutex> lock(gMsgBufMutex);
888 if (gMsgBuf.empty())
889 break;
890 e = gMsgBuf.front();
891 gMsgBuf.pop_front();
892 // implicit unlock
893 }
894
895 /* log message */
896 cm_msg_log(e.message_type, "midas", e.message.c_str());
897
898 /* send message to SYSMSG */
899 int status = cm_msg_send_event(e.ts, e.message_type, e.message.c_str());
900 if (status != CM_SUCCESS)
901 return status;
902 }
903
904 return CM_SUCCESS;
905}
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 763 of file midas.cxx.

764{
765 /* strip path */
766 const char* pc = filename + strlen(filename);
767 while (*pc != '\\' && *pc != '/' && pc != filename)
768 pc--;
769 if (pc != filename)
770 pc++;
771
772 /* convert type to string */
773 std::string type_str;
774 if (message_type & MT_ERROR)
776 if (message_type & MT_INFO)
778 if (message_type & MT_DEBUG)
780 if (message_type & MT_USER)
782 if (message_type & MT_LOG)
784 if (message_type & MT_TALK)
786
787 std::string message;
788
789 /* print client name into string */
790 if (message_type == MT_USER)
791 message = msprintf("[%s] ", routine);
792 else {
793 std::string name = rpc_get_name();
794 if (name.length() > 0)
795 message = msprintf("[%s,%s] ", name.c_str(), type_str.c_str());
796 else
797 message = "";
798 }
799
800 /* preceed error messages with file and line info */
801 if (message_type == MT_ERROR) {
802 message += msprintf("[%s:%d:%s,%s] ", pc, line, routine, type_str.c_str());
803 } else if (message_type == MT_USER) {
804 message = msprintf("[%s,%s] ", routine, type_str.c_str());
805 }
806
807 int bufsize = 1024;
808 char* buf = (char*)malloc(bufsize);
809 assert(buf);
810
811 for (int i=0; i<10; i++) {
812 va_list ap;
813 va_copy(ap, *argptr);
814
815 /* print argument list into message */
816 int n = vsnprintf(buf, bufsize-1, format, ap);
817
818 //printf("vsnprintf [%s] %d %d\n", format, bufsize, n);
819
820 va_end(ap);
821
822 if (n < bufsize) {
823 break;
824 }
825
826 bufsize += 100;
827 bufsize *= 2;
828 buf = (char*)realloc(buf, bufsize);
829 assert(buf);
830 }
831
832 message += buf;
833 free(buf);
834
835 return message;
836}
#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:13106
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 551 of file midas.cxx.

551 {
552 HNDLE hDB;
553 int status;
554
556
557 // check for call to cm_msg() before MIDAS is fully initialized
558 // or after MIDAS is partially shutdown.
559 if (status != CM_SUCCESS) {
560 if (filename)
561 *filename = std::string(fac) + ".log";
562 if (linkname)
563 *linkname = "";
564 if (linktarget)
565 *linktarget = "";
566 return;
567 }
568
569 if (filename)
570 *filename = "";
571 if (linkname)
572 *linkname = "";
573 if (linktarget)
574 *linktarget = "";
575
576 std::string facility;
577 if (fac && fac[0])
578 facility = fac;
579 else
580 facility = "midas";
581
582 std::string message_format;
583 db_get_value_string(hDB, 0, "/Logger/Message file date format", 0, &message_format, TRUE);
584 if (message_format.find('%') != std::string::npos) {
585 /* replace stings such as %y%m%d with current date */
586 struct tm tms;
587
588 ss_tzset();
589 if (t == 0)
590 time(&t);
591 localtime_r(&t, &tms);
592
593 char de[256];
594 de[0] = '_';
595 strftime(de + 1, sizeof(de)-1, strchr(message_format.c_str(), '%'), &tms);
597 }
598
599 std::string message_dir;
600 db_get_value_string(hDB, 0, "/Logger/Message dir", 0, &message_dir, TRUE);
601 if (message_dir.empty()) {
602 db_get_value_string(hDB, 0, "/Logger/Data dir", 0, &message_dir, FALSE);
603 if (message_dir.empty()) {
605 if (message_dir.empty()) {
607 }
608 }
609 }
610
611 // prepend experiment directory
612 if (message_dir[0] != DIR_SEPARATOR)
614
615 if (message_dir.back() != DIR_SEPARATOR)
616 message_dir.push_back(DIR_SEPARATOR);
617
618 if (filename)
619 *filename = message_dir + facility + message_format + ".log";
620 if (!message_format.empty()) {
621 if (linkname)
622 *linkname = message_dir + facility + ".log";
623 if (linktarget)
624 *linktarget = facility + message_format + ".log";
625 }
626}
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition midas.cxx:3025
std::string cm_get_path()
Definition midas.cxx:1551
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:13945
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 676 of file midas.cxx.

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

486 {
487 //printf("cm_msg_open_buffer!\n");
488 if (_msg_buffer == 0) {
490 if (status != BM_SUCCESS && status != BM_CREATED) {
491 return status;
492 }
493 }
494 return CM_SUCCESS;
495}
INT bm_open_buffer(const char *buffer_name, INT buffer_size, INT *buffer_handle)
Definition midas.cxx:6739
#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 1065 of file midas.cxx.

1065 {
1066 INT status, id;
1067
1068 // we should only come here after the message buffer
1069 // was opened by cm_connect_experiment()
1070 assert(_msg_buffer);
1071
1072 _msg_dispatch = func;
1073
1075
1076 return status;
1077}
INT bm_request_event(HNDLE buffer_handle, short int event_id, short int trigger_mask, INT sampling_type, HNDLE *request_id, EVENT_HANDLER *func)
Definition midas.cxx:8487
#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 1348 of file midas.cxx.

1348 {
1349 int status;
1350 char *messages = NULL;
1351 int num_messages = 0;
1352
1353 if (rpc_is_remote())
1354 return rpc_call(RPC_CM_MSG_RETRIEVE, n_message, message, buf_size);
1355
1357
1358 if (messages) {
1359 mstrlcpy(message, messages, buf_size);
1360 int len = strlen(messages);
1361 if (len > buf_size)
1363 free(messages);
1364 }
1365
1366 return status;
1367}
#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:1278
#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 1110 of file midas.cxx.

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

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

838 {
839 //printf("cm_msg_send: ts %d, type %d, message [%s]\n", ts, message_type, send_message);
840
841 /* send event if not of type MLOG */
842 if (message_type != MT_LOG) {
843 if (_msg_buffer) {
844 /* copy message to event */
845 size_t len = strlen(send_message);
846 int event_length = sizeof(EVENT_HEADER) + len + 1;
847 char event[event_length];
848 EVENT_HEADER *pevent = (EVENT_HEADER *) event;
849
850 memcpy(event + sizeof(EVENT_HEADER), send_message, len + 1);
851
852 /* setup the event header and send the message */
853 bm_compose_event(pevent, EVENTID_MESSAGE, (WORD) message_type, len + 1, 0);
854 if (ts)
855 pevent->time_stamp = ts;
856 //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)));
857 bm_send_event(_msg_buffer, pevent, 0, BM_WAIT);
858 }
859 }
860
861 return CM_SUCCESS;
862}
INT bm_send_event(INT buffer_handle, const EVENT_HEADER *pevent, int unused, int timeout_msec)
Definition midas.cxx:9700
INT bm_compose_event(EVENT_HEADER *event_header, short int event_id, short int trigger_mask, DWORD data_size, DWORD serial)
Definition midas.cxx:8303
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:7460
INT cm_set_msg_print(INT system_mask, INT user_mask, int(*func)(const char *))
Definition midas.cxx:659
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 659 of file midas.cxx.

659 {
662 _message_print = func;
663
664 return BM_SUCCESS;
665}
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 870 of file midas.cxx.

◆ gMsgBufMutex

std::mutex gMsgBufMutex
static

Definition at line 871 of file midas.cxx.