$treeview $search $mathjax $extrastylesheet
otsdaq_utilities
v2_03_00
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #ifndef _ots_ConsoleSupervisor_h_ 00002 #define _ots_ConsoleSupervisor_h_ 00003 00004 #include "otsdaq-core/CoreSupervisors/CoreSupervisorBase.h" 00005 00006 #include <mutex> //for std::mutex 00007 00008 namespace ots 00009 { 00010 // ConsoleSupervisor 00011 // This class handles the presentation of Message Facility printouts to the web desktop 00012 // Console 00013 class ConsoleSupervisor : public CoreSupervisorBase 00014 { 00015 public: 00016 public: 00017 XDAQ_INSTANTIATOR(); 00018 00019 ConsoleSupervisor(xdaq::ApplicationStub* s); 00020 virtual ~ConsoleSupervisor(void); 00021 00022 void init(void); 00023 void destroy(void); 00024 00025 virtual void defaultPage(xgi::Input* in, xgi::Output* out) override; 00026 virtual void request(const std::string& requestType, 00027 cgicc::Cgicc& cgiIn, 00028 HttpXmlDocument& xmlOut, 00029 const WebUsers::RequestUserInfo& userInfo) override; 00030 00031 virtual void forceSupervisorPropertyValues(void) override; // override to force 00032 // supervisor property 00033 // values (and ignore user 00034 // settings) 00035 00036 private: 00037 static void messageFacilityReceiverWorkLoop(ConsoleSupervisor* cs); 00038 void insertMessageRefresh(HttpXmlDocument* xmldoc, 00039 const clock_t lastUpdateClock, 00040 const unsigned int lastUpdateIndex); 00041 00042 // UDP Message Format: 00043 // UDPMFMESSAGE|TIMESTAMP|SEQNUM|HOSTNAME|HOSTADDR|SEVERITY|CATEGORY|APPLICATION|PID|ITERATION|MODULE|(FILE|LINE)|MESSAGE 00044 // FILE and LINE are only printed for s67+ 00045 struct ConsoleMessageStruct 00046 { 00047 ConsoleMessageStruct() 00048 { 00049 buffer.resize(BUFFER_SZ); 00050 timeStamp = 0; // use this being 0 to indicate uninitialized 00051 countStamp = (time_t)-1; // this is still a valid countStamp, just unlikely 00052 // to be reached 00053 00054 // init fields to position -1 (for unknown) 00055 // NOTE: must be in order of appearance in buffer 00056 fields[SEQID].set("SequenceID", 2, -1); 00057 fields[LEVEL].set("Level", 5, -1); 00058 fields[LABEL].set("Label", 6, -1); 00059 fields[SOURCEID].set("SourceID", 7, -1); // number 00060 fields[SOURCE].set("Source", 9, -1); 00061 //fields[MSG].set( 00062 // "Msg", 10, -1); 00063 // the message facility contents have changed! 00064 #if MESSAGEFACILITY_HEX_VERSION >= 0x20201 00065 fields[MSG].set("Msg", 12, -1); 00066 #else 00067 fields[MSG].set("Msg", 10, -1); 00068 #endif 00069 } 00070 00071 void set(const std::string& msg, const time_t count) 00072 { 00073 buffer = (std::string)(msg.substr(0, BUFFER_SZ)); // clip to BUFFER_SZ 00074 00075 timeStamp = time(0); // get time of msg 00076 countStamp = count; // get "unique" incrementing id for message 00077 00078 // find fields 00079 int i = 0, m = 0; 00080 size_t p = 0; 00081 00082 // if first field is position 0, mark it complete 00083 if(fields[i].markerCount == 0) 00084 fields[i++].posInString = 0; 00085 00086 // loop until no more markers 00087 while((p = buffer.find('|', p)) != std::string::npos) 00088 { 00089 ++m; // found next marker 00090 00091 if(i < (int)fields.size() && 00092 m == fields[i].markerCount) // found marker for field 00093 fields[i++].posInString = 00094 p + 1; // set position in string and move on to next field 00095 00096 // change all | to \0 so strings are terminated 00097 buffer[p] = '\0'; 00098 00099 // handle special Level/Label case (where | is missing) 00100 if(i == LABEL && p + 1 + strlen(&buffer[p + 1]) != msg.length()) 00101 { 00102 // std::cout << "LEN = " << strlen(&buffer[p+1]) << __E__; 00103 // std::cout << "buff = " <<(&buffer[p+1]) << __E__; 00104 fields[i++].posInString = p + 2 + strlen(&buffer[p + 1]); 00105 } 00106 } 00107 00108 // debug 00109 // std::cout << ":::::" << msg << "\n"; 00110 // for(auto &f: fields) 00111 // { 00112 // std::cout << f.fieldName << ": "; 00113 // std::cout << (char *)&buffer[f.posInString] << std::endl; 00114 // } 00115 } 00116 00117 const char* getMsg() { return (char*)&buffer[fields[MSG].posInString]; } 00118 const char* getLabel() { return (char*)&buffer[fields[LABEL].posInString]; } 00119 const char* getLevel() { return (char*)&buffer[fields[LEVEL].posInString]; } 00120 const char* getSourceID() { return (char*)&buffer[fields[SOURCEID].posInString]; } 00121 const long long getSourceIDAsNumber() 00122 { 00123 // signed to allow -1 to ignore sequence number 00124 long long srcid; 00125 sscanf((char*)&buffer[fields[SOURCEID].posInString], 00126 "%lld", 00127 &srcid); // signed long long 00128 return srcid; 00129 } 00130 const char* getSource() { return (char*)&buffer[fields[SOURCE].posInString]; } 00131 const char* getSequenceID() { return (char*)&buffer[fields[SEQID].posInString]; } 00132 const unsigned int getSequenceIDAsNumber() 00133 { 00134 unsigned long long longSeqid; 00135 sscanf((char*)&buffer[fields[SEQID].posInString], 00136 "%llu", 00137 &longSeqid); // unsigned long long 00138 // Eric says this field is a "C++ int" which can change based on OS from 32 to 00139 // 64?... then convert to unsigned int for our sanity 00140 return (unsigned int)longSeqid; 00141 } 00142 00143 const char* getField(int i) { return (char*)&buffer[fields[i].posInString]; } 00144 const time_t getTime() { return timeStamp; } 00145 const time_t getCount() { return countStamp; } 00146 00147 // define field structure 00148 struct FieldStruct 00149 { 00150 void set(const std::string& fn, const int mc, const int ps) 00151 { 00152 fieldName = fn; 00153 markerCount = mc; 00154 posInString = ps; 00155 } 00156 00157 std::string fieldName; 00158 int markerCount; 00159 int posInString; 00160 }; 00161 00162 // define field index enum alias 00163 enum 00164 { // must be in order of appearance in buffer 00165 SEQID, 00166 LEVEL, // aka SEVERITY 00167 LABEL, 00168 SOURCEID, 00169 SOURCE, 00170 MSG, 00171 }; 00172 00173 const int BUFFER_SZ = 5000; 00174 std::array<FieldStruct, 6> fields; 00175 00176 private: 00177 std::string buffer; 00178 time_t timeStamp; 00179 time_t countStamp; 00180 }; 00181 00182 std::array<ConsoleMessageStruct, 100> messages_; 00183 std::mutex messageMutex_; 00184 volatile unsigned int writePointer_; // use volatile to avoid compiler optimizations 00185 time_t messageCount_; //"unique" incrementing ID for messages 00186 00187 // members for the refresh handler, ConsoleSupervisor::insertMessageRefresh 00188 unsigned int refreshReadPointer_; 00189 char refreshTempStr_[50]; 00190 unsigned int refreshIndex_; 00191 xercesc::DOMElement* refreshParent_; 00192 time_t refreshCurrentLastCount_; 00193 }; 00194 } 00195 00196 #endif