1 #include "otsdaq-utilities/Console/ConsoleSupervisor.h"
2 #include <xdaq/NamespaceURI.h>
3 #include "otsdaq/CgiDataUtilities/CgiDataUtilities.h"
4 #include "otsdaq/Macros/CoutMacros.h"
5 #include "otsdaq/MessageFacility/MessageFacility.h"
6 #include "otsdaq/NetworkUtilities/ReceiverSocket.h"
7 #include "otsdaq/XmlUtilities/HttpXmlDocument.h"
24 #define USER_CONSOLE_PREF_PATH \
25 std::string(__ENV__("SERVICE_DATA_PATH")) + "/ConsolePreferences/"
26 #define USER_CONSOLE_SNAPSHOT_PATH \
27 std::string(__ENV__("SERVICE_DATA_PATH")) + "/ConsoleSnapshots/"
28 #define USERS_PREFERENCES_FILETYPE "pref"
29 #define CUSTOM_COUNT_LIST_FILENAME std::string("CustomCountList.dat")
31 #define QUIET_CFG_FILE \
32 std::string(__ENV__("USER_DATA")) + \
33 "/MessageFacilityConfigurations/" \
36 #define CONSOLE_SPECIAL_ERROR \
37 std::string("|30-Aug-2019 15:30:17 CDT|0|||Error|Console||-1||ConsoleSupervisor|") + \
38 std::string(__FILE__) + std::string("|") + std::to_string(__LINE__) + \
40 #define CONSOLE_SPECIAL_WARNING \
42 "|30-Aug-2019 15:30:17 CDT|0|||Warning|Console||-1||ConsoleSupervisor|") + \
43 std::string(__FILE__) + std::string("|") + std::to_string(__LINE__) + \
47 #define __MF_SUBJECT__ "Console"
49 #define CONSOLE_MISSED_NEEDLE "Console missed * packet(s)"
61 const std::string ConsoleSupervisor::ConsoleMessageStruct::LABEL_TRACE =
"TRACE";
62 const std::string ConsoleSupervisor::ConsoleMessageStruct::LABEL_TRACE_PLUS =
"TRACE+";
65 ConsoleSupervisor::ConsoleMessageStruct::fieldNames({
66 {FieldType::TIMESTAMP,
"Timestamp"},
67 {FieldType::SEQID,
"SequenceID"},
68 {FieldType::LEVEL,
"Level"},
69 {FieldType::LABEL,
"Label"},
70 {FieldType::SOURCEID,
"SourceID"},
71 {FieldType::HOSTNAME,
"Hostname"},
72 {FieldType::SOURCE,
"Source"},
73 {FieldType::FILE,
"File"},
74 {FieldType::LINE,
"Line"},
75 {FieldType::MSG,
"Msg"},
79 ConsoleSupervisor::ConsoleSupervisor(xdaq::ApplicationStub* stub)
82 , maxMessageCount_(100000)
83 , maxClientMessageRequest_(500)
85 __SUP_COUT__ <<
"Constructor started." << __E__;
90 mkdir(((std::string)USER_CONSOLE_PREF_PATH).c_str(), 0755);
91 mkdir(((std::string)USER_CONSOLE_SNAPSHOT_PATH).c_str(), 0755);
94 this, &ConsoleSupervisor::resetConsoleCounts,
"ResetConsoleCounts", XDAQ_NS_URI);
106 loadCustomCountList();
107 if(priorityCustomTriggerList_.size() ==
110 addCustomTriggeredAction(CONSOLE_MISSED_NEEDLE,
"System Message");
117 __SUP_COUT__ <<
"Constructor complete." << __E__;
122 ConsoleSupervisor::~ConsoleSupervisor(
void) { destroy(); }
124 void ConsoleSupervisor::init(
void)
129 ConsoleSupervisor::messageFacilityReceiverWorkLoop(cs);
136 void ConsoleSupervisor::destroy(
void)
142 xoap::MessageReference ConsoleSupervisor::resetConsoleCounts(
143 xoap::MessageReference )
145 __COUT_INFO__ <<
"Resetting Console Error/Warn/Info counts and preparing for new "
151 std::lock_guard<std::mutex> lock(messageMutex_);
153 firstErrorMessageTime_ = 0;
154 lastErrorMessageTime_ = 0;
156 firstWarnMessageTime_ = 0;
157 lastWarnMessageTime_ = 0;
159 firstInfoMessageTime_ = 0;
160 lastInfoMessageTime_ = 0;
162 return SOAPUtilities::makeSOAPMessageReference(
"Done");
172 __COUT__ <<
"Starting workloop based on config file: " << QUIET_CFG_FILE << __E__;
174 std::string configFile = QUIET_CFG_FILE;
175 FILE* fp = fopen(configFile.c_str(),
"r");
178 __SS__ <<
"File with port info could not be loaded: " << QUIET_CFG_FILE << __E__;
179 __COUT__ <<
"\n" << ss.str();
186 sscanf(tmp,
"%*s %d", &myport);
190 sscanf(tmp,
"%*s %s", myip);
196 rsock.initialize(0x1400000 );
202 std::lock_guard<std::mutex> lock(cs->messageMutex_);
208 __SS__ <<
"FATAL Console error. Could not initialize socket on port "
210 <<
". Perhaps the port is already in use? Check for multiple stale "
211 "instances of otsdaq processes, or notify admins."
212 <<
" Multiple instances of otsdaq on the same node should be "
213 "possible, but port numbers must be unique."
219 __SS__ <<
"FATAL Console error. Could not initialize socket on port " << myport
220 <<
". Perhaps it is already in use? Exiting Console receive loop."
222 __COUT__ << ss.str();
224 cs->messages_.emplace_back(CONSOLE_SPECIAL_ERROR + ss.str(),
226 cs->priorityCustomTriggerList_);
228 cs->messages_.back().setTime(time(0));
229 if(cs->messages_.size() > cs->maxMessageCount_)
231 cs->messages_.erase(cs->messages_.begin());
239 int heartbeatCount = 0;
240 int selfGeneratedMessageCount = 0;
242 std::map<unsigned int, unsigned int> sourceLastSequenceID;
245 long long newSourceId;
246 uint32_t newSequenceId;
250 __COUT__ <<
"DEBUG messages look like this." << __E__;
259 buffer, 1 , 0 ,
false ) !=
263 if(buffer.size() == 1)
271 __COUT__ <<
"Console has first message." << __E__;
275 __COUT_INFO__ <<
"INFO messages look like this and mean 'something "
276 "occurred of which you should be aware.'"
278 __COUT_WARN__ <<
"WARNING messages look like this and mean 'something "
279 "suboptimal occurred and could be fixed.'"
281 __COUT_ERR__ <<
"ERROR messages look like this and mean 'something wrong "
282 "occurred and should be fixed.'"
295 if(selfGeneratedMessageCount)
296 --selfGeneratedMessageCount;
304 std::lock_guard<std::mutex> lock(cs->messageMutex_);
308 while(c < buffer.size())
312 cs->messages_.emplace_back(&(buffer.c_str()[c]),
314 cs->priorityCustomTriggerList_);
315 if(cs->messages_.back().hasCustomTriggerMatchAction())
316 cs->customTriggerActionQueue_.push(
317 cs->messages_.back().getCustomTriggerMatch());
320 if(cs->messages_.back().getLevel() ==
"Error")
322 if(cs->errorCount_ == 0)
324 cs->firstErrorMessageTime_ = time(0);
325 cs->firstErrorMessage_ = cs->messages_.back().getMsg();
328 cs->lastErrorMessageTime_ = time(0);
330 cs->lastErrorMessage_ = cs->messages_.back().getMsg();
332 else if(cs->messages_.back().getLevel() ==
"Warning")
334 if(cs->warnCount_ == 0)
336 cs->firstWarnMessageTime_ = time(0);
337 cs->firstWarnMessage_ = cs->messages_.back().getMsg();
339 cs->lastWarnMessageTime_ = time(0);
341 cs->lastWarnMessage_ = cs->messages_.back().getMsg();
343 else if(cs->messages_.back().getLevel() ==
"Info")
345 if(cs->infoCount_ == 0)
347 cs->firstInfoMessageTime_ = time(0);
348 cs->firstInfoMessage_ = cs->messages_.back().getMsg();
350 cs->lastInfoMessageTime_ = time(0);
352 cs->lastInfoMessage_ = cs->messages_.back().getMsg();
356 newSourceId = cs->messages_.back().getSourceIDAsNumber();
357 newSequenceId = cs->messages_.back().getSequenceIDAsNumber();
364 (newSourceId != -1 &&
365 sourceLastSequenceID.find(newSourceId) !=
368 ((newSequenceId == 0 && sourceLastSequenceID[newSourceId] !=
371 sourceLastSequenceID[newSourceId] + 1))
375 std::stringstream missedSs;
376 missedSs <<
"Console missed "
377 << (newSequenceId - 1) -
378 (sourceLastSequenceID[newSourceId] + 1) + 1
379 <<
" packet(s) [" << sourceLastSequenceID[newSourceId]
380 <<
" -> " << newSequenceId <<
"] from "
381 << cs->messages_.back().getSource() <<
":" << newSourceId
382 <<
"! (uptime: " << cs->getSupervisorUptime() <<
" s)"
384 __SS__ << missedSs.str();
385 std::cout << ss.str();
389 if(cs->getSupervisorUptime() > 20 &&
390 sourceLastSequenceID[newSourceId] !=
395 cs->messages_.emplace_back(
396 CONSOLE_SPECIAL_WARNING + missedSs.str(),
398 cs->priorityCustomTriggerList_);
400 cs->messages_.back().setTime(time(0));
402 if(cs->priorityCustomTriggerList_.size())
404 cs->customTriggerActionQueue_.push(
405 cs->priorityCustomTriggerList_
407 cs->priorityCustomTriggerList_[0]
409 cs->customTriggerActionQueue_.back()
410 .triggeredMessageCountIndex =
411 cs->messages_.back().getCount();
412 cs->messages_.back().setCustomTriggerMatch(
413 cs->customTriggerActionQueue_.back());
419 sourceLastSequenceID[newSourceId] = newSequenceId;
422 while(cs->messages_.size() > 0 &&
423 cs->messages_.size() > cs->maxMessageCount_)
425 if(i < cs->maxMessageCount_ /
427 (cs->messages_[i].getLevel() ==
"Error" ||
428 cs->messages_[i].getLevel() ==
"Warning" ||
429 cs->messages_[i].getLevel() ==
"Info"))
435 cs->messages_.erase(cs->messages_.begin() + i);
438 c += strlen(&(buffer.c_str()[c])) + 1;
452 (heartbeatCount < 60 * 5 &&
453 heartbeatCount % 60 == 59))
455 ++selfGeneratedMessageCount;
456 __COUT__ <<
"Console is alive and waiting... (if no messages, next "
457 "heartbeat is in two minutes)"
460 else if(heartbeatCount % (60 * 30) == 59)
462 ++selfGeneratedMessageCount;
463 __COUT__ <<
"Console is alive and waiting a long time... (if no "
464 "messages, next heartbeat is in one hour)"
475 if(i == 120 || selfGeneratedMessageCount == 5)
478 __COUTV__(selfGeneratedMessageCount);
479 __COUT__ <<
"No messages received at Console Supervisor. Exiting Console "
480 "messageFacilityReceiverWorkLoop"
485 if(cs->customTriggerActionQueue_.size() && !cs->customTriggerActionThreadExists_)
487 cs->customTriggerActionThreadExists_ =
true;
491 ConsoleSupervisor::customTriggerActionThread(c);
500 catch(
const std::runtime_error& e)
502 __COUT_ERR__ <<
"Error caught at Console Supervisor thread: " << e.what() << __E__;
506 __COUT_ERR__ <<
"Unknown error caught at Console Supervisor thread." << __E__;
515 __COUT__ <<
"Starting customTriggerActionThread" << __E__;
516 CustomTriggeredAction_t triggeredAction;
522 std::lock_guard<std::mutex> lock(cs->messageMutex_);
523 if(cs->customTriggerActionQueue_.size())
525 triggeredAction = cs->customTriggerActionQueue_.front();
526 cs->customTriggerActionQueue_.pop();
530 if(triggeredAction.action.size())
532 __COUTS__(2) <<
"Handling action '" << triggeredAction.action
533 <<
"' on custom count search string: "
537 cs->doTriggeredAction(triggeredAction);
540 triggeredAction.action =
"";
541 triggeredAction.triggeredMessageCountIndex =
548 catch(
const std::runtime_error& e)
550 __COUT_ERR__ <<
"Error caught at Console Supervisor Action thread: " << e.what()
555 __COUT_ERR__ <<
"Unknown error caught at Console Supervisor Action thread." << __E__;
559 void ConsoleSupervisor::doTriggeredAction(
const CustomTriggeredAction_t& triggeredAction)
561 __SUP_COUT_INFO__ <<
"Launching Triggered Action '" << triggeredAction.action
562 <<
"' fired on custom count search string: "
579 __SUP_SS__ <<
"Unrecognized triggered action '" << triggeredAction.action
580 <<
",' valid actions are "
586 constexpr time_t TRIGGER_SYSTEM_MESSAGE_COOLDOWN_S = 5 * 60;
587 bool sendSystemMessage =
588 (triggeredAction.action !=
"Count Only") &&
589 (time(0) - lastTriggeredSystemMessageTime_ >= TRIGGER_SYSTEM_MESSAGE_COOLDOWN_S);
591 if(triggeredAction.action !=
"Count Only" && !sendSystemMessage)
592 __SUP_COUT_INFO__ <<
"Suppressing repeated system message for triggered action '"
593 << triggeredAction.action <<
"' (cooldown "
594 << TRIGGER_SYSTEM_MESSAGE_COOLDOWN_S <<
"s)" << __E__;
596 if(sendSystemMessage)
598 lastTriggeredSystemMessageTime_ = time(0);
599 theRemoteWebUsers_.sendSystemMessage(
601 "In the Console Supervisor, a custom count fired the action '" +
602 triggeredAction.action +
"' on the search string '" +
607 if(triggeredAction.action ==
"Halt")
612 "Console-triggered FSM Halt", 0, 0);
616 theRemoteWebUsers_.sendSystemMessage(
618 "FSM Halt from Console Supervisor Triggered Action has failed!");
620 __SUP_COUTV__(
"FSM Halt triggered from console");
622 else if(triggeredAction.action ==
"Pause")
627 "Console-triggered FSM Pause", 1, 0);
631 theRemoteWebUsers_.sendSystemMessage(
633 "FSM Pause from Console Supervisor Triggered Action has failed!");
635 __SUP_COUTV__(
"FSM Pause triggered from console");
637 else if(triggeredAction.action ==
"Stop")
642 "Console-triggered FSM Stop", 0, 1);
644 catch(
const std::exception& e)
646 theRemoteWebUsers_.sendSystemMessage(
648 "FSM Stop from Console Supervisor Triggered Action has failed!");
650 __SUP_COUTV__(
"FSM Stop triggered from console");
652 else if(triggeredAction.action ==
"Run Script")
654 std::string triggerScriptPath =
"";
655 std::string scriptResult =
"";
658 triggerScriptPath = __ENV__(
"OTS_CUSTOM_TRIGGER_SCRIPT");
659 triggerScriptPath =
"source " + triggerScriptPath;
661 __COUT_INFO__ <<
"The Script " << triggerScriptPath
662 <<
" Was launched, here is the result " << scriptResult;
666 __SS__ <<
"Trigger script path not defined! Please use environment variable "
667 "'OTS_CUSTOM_TRIGGER_SCRIPT' or contact admins."
677 void ConsoleSupervisor::addCustomTriggeredAction(
const std::string& triggerNeedle,
678 const std::string& triggerAction,
680 uint32_t triggerOnCount,
684 __SUP_COUTV__(
"Adding custom triggered action");
685 __SUP_COUTV__(triggerNeedle);
686 __SUP_COUTV__(triggerAction);
687 __SUP_COUTV__(priority);
688 __SUP_COUTV__(triggerOnCount);
689 __SUP_COUTV__(doLoop);
690 __SUP_COUTV__(isArmed);
692 bool allAsterisks =
true;
693 for(
const auto& c : triggerNeedle)
696 allAsterisks =
false;
701 __SUP_SS__ <<
"Illegal empty Search String value for the new Custom Count and "
702 "Action! Please enter a valid Search String (* wildcards are "
703 "allowed, e.g. \"value = * seconds\")."
709 uint32_t currentPriority = -1;
710 for(
const auto& customTrigger : priorityCustomTriggerList_)
716 __SUP_SS__ <<
"Failure! Can not add Custom Count Search String that already "
719 <<
"' already existing at priority = " << currentPriority << __E__;
724 if(priority >= priorityCustomTriggerList_.size())
725 priority = priorityCustomTriggerList_.size();
726 if(priority == 0 && triggerNeedle != CONSOLE_MISSED_NEEDLE)
728 __SUP_SS__ <<
"Illegal priority position of '" << priority
729 <<
"' requested. Please enter a priority value greater than 0. "
730 "Position 0 is reserved for identifying missing messages at the "
731 "Console Supervisor. Note: the action for missing messages, at "
732 "priority 0, may be customized by the user."
736 __SUP_COUTV__(priority);
749 __SUP_SS__ <<
"Unrecognized triggered action '" << triggerAction
750 <<
",' valid actions are "
756 priorityCustomTriggerList_.insert(priorityCustomTriggerList_.begin() + priority,
757 CustomTriggeredAction_t());
764 priorityCustomTriggerList_[priority].needleSubstrings,
767 priorityCustomTriggerList_[priority].action = triggerAction;
768 priorityCustomTriggerList_[priority].triggerOnCount = triggerOnCount;
769 priorityCustomTriggerList_[priority].doLoop = doLoop;
770 priorityCustomTriggerList_[priority].isArmed = isArmed;
772 __SUP_COUT__ <<
"Added custom count: '"
774 priorityCustomTriggerList_[priority].needleSubstrings,
"*")
775 <<
"' at priority: " << priority
776 <<
" triggered every: " << triggerOnCount <<
" occurrences";
778 __SUP_COUT__ <<
" and will loop.";
780 __SUP_COUT__ <<
" and will not loop.";
781 __SUP_COUT__ << __E__;
789 uint32_t ConsoleSupervisor::modifyCustomTriggeredAction(
const std::string& currentNeedle,
790 const std::string& modifyType,
791 const std::string& setNeedle,
792 const std::string& setAction,
793 uint32_t setPriority,
794 uint32_t setTriggerOnCount,
798 __SUP_COUTV__(currentNeedle);
799 __SUP_COUTV__(modifyType);
800 __SUP_COUTV__(setNeedle);
801 __SUP_COUTV__(setAction);
802 __SUP_COUTV__(setPriority);
803 __SUP_COUTV__(setTriggerOnCount);
804 __SUP_COUTV__(setDoLoop);
805 __SUP_COUTV__(setIsArmed);
808 uint32_t currentPriority = -1;
810 for(
const auto& customTrigger : priorityCustomTriggerList_)
821 __SUP_COUTV__(currentPriority);
824 __SUP_SS__ <<
"Attempt to modify Custom Count Search String failed. Could not "
825 "find specified Search String '"
826 << currentNeedle <<
"' in prioritized list." << __E__;
830 if(modifyType ==
"Deletion")
832 if(currentPriority == 0)
834 __SUP_SS__ <<
"Illegal deletion requested of priority position 0. Position 0 "
835 "is reserved for identifying missing messages at the Console "
836 "Supervisor. Note: the action of priority 0 may be customized "
837 "by the user, but it can not be deleted."
842 __SUP_COUT__ <<
"Deleting custom count: "
844 priorityCustomTriggerList_[currentPriority].needleSubstrings,
847 << priorityCustomTriggerList_[currentPriority].action
848 <<
" and priority: " << currentPriority << __E__;
849 priorityCustomTriggerList_.erase(priorityCustomTriggerList_.begin() +
854 if(modifyType ==
"Priority" || modifyType ==
"All")
856 if(setPriority >= priorityCustomTriggerList_.size())
857 setPriority = priorityCustomTriggerList_.size();
858 if(setPriority == 0 && setNeedle != CONSOLE_MISSED_NEEDLE)
860 __SUP_SS__ <<
"Illegal priority position of '" << setPriority
861 <<
"' requested. Position 0 is reserved for identifying missing "
862 "messages at the Console Supervisor. Note: the action of "
863 "priority 0 may be customized by the user."
869 setPriority = currentPriority;
871 if(modifyType ==
"Action" || modifyType ==
"All")
883 __SUP_SS__ <<
"Unrecognized custom count action '" << setAction
884 <<
",' valid actions are "
889 priorityCustomTriggerList_[currentPriority].action = setAction;
892 if(modifyType ==
"Search String" || modifyType ==
"All")
895 priorityCustomTriggerList_[currentPriority].needleSubstrings.clear();
898 priorityCustomTriggerList_[currentPriority].needleSubstrings,
903 if(modifyType ==
"Trigger on Count" || modifyType ==
"All")
906 priorityCustomTriggerList_[currentPriority].triggerOnCount = setTriggerOnCount;
908 if(modifyType ==
"Do Loop" || modifyType ==
"All")
911 priorityCustomTriggerList_[currentPriority].doLoop = setDoLoop;
913 if(modifyType ==
"Arm Trigger" || modifyType ==
"All")
916 priorityCustomTriggerList_[currentPriority].isArmed = setIsArmed;
919 if(currentPriority != setPriority)
922 priorityCustomTriggerList_.insert(
923 priorityCustomTriggerList_.begin() + setPriority,
924 priorityCustomTriggerList_[currentPriority]);
927 if(currentPriority >= setPriority)
930 priorityCustomTriggerList_.erase(priorityCustomTriggerList_.begin() +
933 if(currentPriority < setPriority)
937 __SUP_COUT__ <<
"Modified '" << modifyType <<
"' custom count: "
939 priorityCustomTriggerList_[setPriority].needleSubstrings, {
'*'})
940 <<
" now w/action: " << priorityCustomTriggerList_[setPriority].action
941 <<
" and at priority: " << setPriority << __E__;
947 void ConsoleSupervisor::loadCustomCountList()
950 __SUP_COUT__ <<
"loadCustomCountList() from "
951 << USER_CONSOLE_PREF_PATH + CUSTOM_COUNT_LIST_FILENAME << __E__;
953 FILE* fp = fopen((USER_CONSOLE_PREF_PATH + CUSTOM_COUNT_LIST_FILENAME).c_str(),
"r");
956 __SUP_COUT__ <<
"Ignoring missing Custom Count list file at path: "
957 << (USER_CONSOLE_PREF_PATH + CUSTOM_COUNT_LIST_FILENAME) << __E__;
960 priorityCustomTriggerList_.clear();
967 size_t triggerOnCount = 0;
969 bool isArmed =
false;
970 while(fgets(line, 1000, fp))
976 line[strlen(line) - 1] =
'\0';
986 priority = std::stoi(line);
988 triggerOnCount = std::stoi(line);
990 doLoop = std::stoi(line) > 0 ? true :
false;
993 isArmed = std::stoi(line) > 0 ? true :
false;
994 __SUP_COUTTV__(needle);
995 __SUP_COUTTV__(priority);
996 __SUP_COUTTV__(action);
997 __SUP_COUTTV__(triggerOnCount);
998 __SUP_COUTTV__(doLoop);
999 __SUP_COUTTV__(isArmed);
1002 CONSOLE_MISSED_NEEDLE)
1003 addCustomTriggeredAction(
1004 CONSOLE_MISSED_NEEDLE,
"System Message", 0, 1,
false,
true);
1005 addCustomTriggeredAction(
1006 needle, action, priority, triggerOnCount, doLoop, isArmed);
1015 void ConsoleSupervisor::saveCustomCountList()
1017 __SUP_COUT__ <<
"saveCustomCountList()" << __E__;
1019 FILE* fp = fopen((USER_CONSOLE_PREF_PATH + CUSTOM_COUNT_LIST_FILENAME).c_str(),
"w");
1022 __SUP_SS__ <<
"Failed to create Custom Count list file at path: "
1023 << (USER_CONSOLE_PREF_PATH + CUSTOM_COUNT_LIST_FILENAME) << __E__;
1026 unsigned int priority = 0;
1027 for(
auto& customCount : priorityCustomTriggerList_)
1032 fprintf(fp,
"%s\n", customCount.action.c_str());
1033 fprintf(fp,
"%d\n", priority);
1034 fprintf(fp,
"%zu\n", customCount.triggerOnCount);
1035 fprintf(fp,
"%s\n", customCount.doLoop ?
"1" :
"0");
1036 fprintf(fp,
"%s\n", customCount.isArmed ?
"1" :
"0");
1043 void ConsoleSupervisor::defaultPage(xgi::Input* , xgi::Output* out)
1047 *out <<
"<!DOCTYPE HTML><html lang='en'><frameset col='100%' row='100%'><frame "
1048 "src='/WebPath/html/Console.html?urn="
1049 << getApplicationDescriptor()->getLocalId() <<
"'></frameset></html>";
1057 CorePropertySupervisorBase::setSupervisorProperty(
1058 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes,
1067 cgicc::Cgicc& cgiIn,
1069 const WebUsers::RequestUserInfo& userInfo)
1092 if(requestType ==
"GetConsoleMsgs")
1097 if(lastUpdateCountStr ==
"")
1099 __SUP_COUT_ERR__ <<
"Invalid Parameters! lastUpdateCount="
1100 << lastUpdateCountStr << __E__;
1101 xmlOut.addTextElementToData(
"Error",
1102 "Error - Invalid parameters for GetConsoleMsgs.");
1106 size_t lastUpdateCount = std::stoull(lastUpdateCountStr);
1110 insertMessageRefresh(&xmlOut, lastUpdateCount);
1112 else if(requestType ==
"PrependHistoricMessages")
1114 size_t earliestOnhandMessageCount =
1115 CgiDataUtilities::postDataAsInt(cgiIn,
"earlyCount");
1116 __SUP_COUTV__(earliestOnhandMessageCount);
1117 prependHistoricMessages(&xmlOut, earliestOnhandMessageCount);
1119 else if(requestType ==
"SaveUserPreferences")
1121 int colorIndex = CgiDataUtilities::postDataAsInt(cgiIn,
"colorIndex");
1122 int showSideBar = CgiDataUtilities::postDataAsInt(cgiIn,
"showSideBar");
1123 int noWrap = CgiDataUtilities::postDataAsInt(cgiIn,
"noWrap");
1124 int messageOnly = CgiDataUtilities::postDataAsInt(cgiIn,
"messageOnly");
1125 int hideLineNumers = CgiDataUtilities::postDataAsInt(cgiIn,
"hideLineNumers");
1126 int noHost = CgiDataUtilities::postDataAsInt(cgiIn,
"noHost");
1136 if(userInfo.username_ ==
"")
1138 __SUP_COUT_ERR__ <<
"Invalid user found! user=" << userInfo.username_
1140 xmlOut.addTextElementToData(
"Error",
1141 "Error - InvauserInfo.username_user found.");
1145 std::string fn = (std::string)USER_CONSOLE_PREF_PATH + userInfo.username_ +
"." +
1146 (std::string)USERS_PREFERENCES_FILETYPE;
1149 FILE* fp = fopen(fn.c_str(),
"w");
1153 __THROW__(ss.str() +
"Could not open file: " + fn);
1155 fprintf(fp,
"colorIndex %d\n", colorIndex);
1156 fprintf(fp,
"showSideBar %d\n", showSideBar);
1157 fprintf(fp,
"noWrap %d\n", noWrap);
1158 fprintf(fp,
"messageOnly %d\n", messageOnly);
1159 fprintf(fp,
"hideLineNumers %d\n", hideLineNumers);
1160 fprintf(fp,
"noHost %d\n", noHost);
1163 else if(requestType ==
"LoadUserPreferences")
1167 unsigned int colorIndex, showSideBar, noWrap, messageOnly, hideLineNumers, noHost;
1169 if(userInfo.username_ ==
"")
1171 __SUP_COUT_ERR__ <<
"Invalid user found! user=" << userInfo.username_
1173 xmlOut.addTextElementToData(
"Error",
"Error - Invalid user found.");
1177 std::string fn = (std::string)USER_CONSOLE_PREF_PATH + userInfo.username_ +
"." +
1178 (std::string)USERS_PREFERENCES_FILETYPE;
1182 FILE* fp = fopen(fn.c_str(),
"r");
1186 __SUP_COUT__ <<
"Returning defaults." << __E__;
1187 xmlOut.addTextElementToData(
"colorIndex",
"0");
1188 xmlOut.addTextElementToData(
"showSideBar",
"0");
1189 xmlOut.addTextElementToData(
"noWrap",
"1");
1190 xmlOut.addTextElementToData(
"messageOnly",
"0");
1191 xmlOut.addTextElementToData(
"hideLineNumers",
"1");
1192 xmlOut.addTextElementToData(
"noHost",
"1");
1195 fscanf(fp,
"%*s %u", &colorIndex);
1196 fscanf(fp,
"%*s %u", &showSideBar);
1197 fscanf(fp,
"%*s %u", &noWrap);
1198 fscanf(fp,
"%*s %u", &messageOnly);
1199 fscanf(fp,
"%*s %u", &hideLineNumers);
1200 if(fscanf(fp,
"%*s %u", &noHost) != 1)
1210 sprintf(tmpStr,
"%u", colorIndex);
1211 xmlOut.addTextElementToData(
"colorIndex", tmpStr);
1212 sprintf(tmpStr,
"%u", showSideBar);
1213 xmlOut.addTextElementToData(
"showSideBar", tmpStr);
1214 sprintf(tmpStr,
"%u", noWrap);
1215 xmlOut.addTextElementToData(
"noWrap", tmpStr);
1216 sprintf(tmpStr,
"%u", messageOnly);
1217 xmlOut.addTextElementToData(
"messageOnly", tmpStr);
1218 sprintf(tmpStr,
"%u", hideLineNumers);
1219 xmlOut.addTextElementToData(
"hideLineNumers", tmpStr);
1220 sprintf(tmpStr,
"%u", noHost);
1221 xmlOut.addTextElementToData(
"noHost", tmpStr);
1223 else if(requestType ==
"GetTraceLevels")
1225 __SUP_COUT__ <<
"requestType " << requestType << __E__;
1228 txParameters.
addParameter(
"Request",
"GetTraceLevels");
1236 traceMapToXDAQHostname_.clear();
1238 std::string traceList =
"";
1239 auto& allTraceApps = allSupervisorInfo_.getAllTraceControllerSupervisorInfo();
1240 __SUP_COUT__ <<
"Querying " << allTraceApps.size()
1241 <<
" TRACE controller supervisor(s) for TRACE levels. Hosts: ";
1243 std::stringstream appHosts;
1244 for(
const auto& appInfo : allTraceApps)
1245 appHosts << appInfo.first <<
"(" << appInfo.second.getClass() <<
") ";
1246 __SUP_COUT__ << appHosts.str() << __E__;
1248 for(
const auto& appInfo : allTraceApps)
1250 __SUP_COUT__ <<
"Supervisor hostname = " << appInfo.first <<
"/"
1251 << appInfo.second.getId()
1252 <<
" name = " << appInfo.second.getName()
1253 <<
" class = " << appInfo.second.getClass()
1254 <<
" hostname = " << appInfo.second.getHostname() << __E__;
1257 xoap::MessageReference retMsg =
1258 SOAPMessenger::sendWithSOAPReply(appInfo.second.getDescriptor(),
1259 "TRACESupervisorRequest",
1261 SOAPUtilities::receive(retMsg, rxParameters);
1262 __SUP_COUT__ <<
"Received TRACE response: "
1263 << SOAPUtilities::translate(retMsg).getCommand() <<
" ==> "
1264 << SOAPUtilities::translate(retMsg) << __E__;
1266 if(SOAPUtilities::translate(retMsg).getCommand() ==
"Fault")
1268 __SUP_SS__ <<
"Unrecognized command at destination TRACE Supervisor "
1270 << appInfo.first <<
"/" << appInfo.second.getId()
1271 <<
" name = " << appInfo.second.getName()
1272 <<
" class = " << appInfo.second.getClass()
1273 <<
" hostname = " << appInfo.second.getHostname() << __E__;
1276 else if(SOAPUtilities::translate(retMsg).getCommand() ==
"TRACEFault")
1278 __SUP_SS__ <<
"Error received: " << rxParameters.getValue(
"Error")
1283 catch(
const xdaq::exception::Exception& e)
1285 __SUP_SS__ <<
"Error transmitting request to TRACE Supervisor LID = "
1286 << appInfo.second.getId()
1287 <<
" name = " << appInfo.second.getName() <<
". \n\n"
1288 << e.what() << __E__;
1289 __SUP_COUT_ERR__ << ss.str();
1293 std::vector<std::string> traceHostnameArr;
1294 __COUTTV__(rxParameters.getValue(
"TRACEHostnameList"));
1296 rxParameters.getValue(
"TRACEHostnameList"), traceHostnameArr, {
';'});
1297 for(
const auto& traceHostname : traceHostnameArr)
1299 if(traceHostname ==
"")
1301 traceMapToXDAQHostname_[traceHostname] = appInfo.first;
1309 __COUTTV__(rxParameters.getValue(
"TRACEList"));
1310 traceList += rxParameters.getValue(
"TRACEList");
1313 __SUP_COUT__ <<
"TRACE hostname map received: \n"
1315 __SUP_COUT__ <<
"TRACE List received: \n" << traceList << __E__;
1316 xmlOut.addTextElementToData(
"traceList", traceList);
1318 else if(requestType ==
"SetTraceLevels")
1320 __SUP_COUT__ <<
"requestType " << requestType << __E__;
1322 std::string individualValues =
1329 __SUP_COUTV__(individualValues);
1330 __SUP_COUTV__(setMode);
1332 __SUP_COUTV__(setValueMSB);
1333 __SUP_COUTV__(setValueLSB);
1335 std::map<std::string , std::string > hostToLabelMap;
1337 auto& allTraceApps = allSupervisorInfo_.getAllTraceControllerSupervisorInfo();
1344 std::string modifiedTraceList =
"";
1345 std::string xdaqHostname;
1347 for(
auto& hostLabelsPair : hostToLabelMap)
1351 __SUP_COUTV__(hostLabelsPair.first);
1352 __SUP_COUTV__(hostLabelsPair.second);
1357 xdaqHostname = traceMapToXDAQHostname_.at(hostLabelsPair.first);
1361 __SUP_SS__ <<
"Could not find the translation from TRACE hostname '"
1362 << hostLabelsPair.first <<
"' to xdaq Context hostname."
1364 ss <<
"Here is the existing map (size=" << traceMapToXDAQHostname_.size()
1370 __SUP_COUTV__(xdaqHostname);
1372 auto& appInfo = allTraceApps.at(xdaqHostname);
1373 __SUP_COUT__ <<
"Supervisor hostname = " << hostLabelsPair.first <<
"/"
1374 << xdaqHostname <<
":" << appInfo.getId()
1375 <<
" name = " << appInfo.getName()
1376 <<
" class = " << appInfo.getClass()
1377 <<
" hostname = " << appInfo.getHostname() << __E__;
1381 txParameters.
addParameter(
"Request",
"SetTraceLevels");
1382 txParameters.
addParameter(
"IndividualValues", individualValues);
1383 txParameters.
addParameter(
"Host", hostLabelsPair.first);
1385 txParameters.
addParameter(
"Labels", hostLabelsPair.second);
1389 xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply(
1390 appInfo.getDescriptor(),
"TRACESupervisorRequest", txParameters);
1391 SOAPUtilities::receive(retMsg, rxParameters);
1392 __SUP_COUT__ <<
"Received TRACE response: "
1393 << SOAPUtilities::translate(retMsg).getCommand() <<
" ==> "
1394 << SOAPUtilities::translate(retMsg) << __E__;
1396 if(SOAPUtilities::translate(retMsg).getCommand() ==
"Fault")
1398 __SUP_SS__ <<
"Unrecognized command at destination TRACE Supervisor "
1400 << hostLabelsPair.first <<
"/" << appInfo.getId()
1401 <<
" name = " << appInfo.getName()
1402 <<
" class = " << appInfo.getClass()
1403 <<
" hostname = " << appInfo.getHostname() << __E__;
1406 else if(SOAPUtilities::translate(retMsg).getCommand() ==
"TRACEFault")
1408 __SUP_SS__ <<
"Error received: " << rxParameters.getValue(
"Error")
1413 catch(
const xdaq::exception::Exception& e)
1415 __SUP_SS__ <<
"Error transmitting request to TRACE Supervisor LID = "
1416 << appInfo.getId() <<
" name = " << appInfo.getName()
1418 << e.what() << __E__;
1422 modifiedTraceList +=
1423 ";" + hostLabelsPair.first;
1427 modifiedTraceList += rxParameters.getValue(
"TRACEList");
1431 __SUP_COUT__ <<
"mod'd TRACE List received: \n" << modifiedTraceList << __E__;
1432 xmlOut.addTextElementToData(
"modTraceList", modifiedTraceList);
1434 else if(requestType ==
"GetTriggerStatus")
1436 __SUP_COUT__ <<
"requestType " << requestType << __E__;
1438 txParameters.
addParameter(
"Request",
"GetTriggerStatus");
1445 std::string traceTriggerStatus =
"";
1446 auto& allTraceApps = allSupervisorInfo_.getAllTraceControllerSupervisorInfo();
1447 for(
const auto& appInfo : allTraceApps)
1449 __SUP_COUT__ <<
"Supervisor hostname = " << appInfo.first <<
"/"
1450 << appInfo.second.getId()
1451 <<
" name = " << appInfo.second.getName()
1452 <<
" class = " << appInfo.second.getClass()
1453 <<
" hostname = " << appInfo.second.getHostname() << __E__;
1456 xoap::MessageReference retMsg =
1457 SOAPMessenger::sendWithSOAPReply(appInfo.second.getDescriptor(),
1458 "TRACESupervisorRequest",
1460 SOAPUtilities::receive(retMsg, rxParameters);
1461 __SUP_COUT__ <<
"Received TRACE response: "
1462 << SOAPUtilities::translate(retMsg).getCommand() <<
" ==> "
1463 << SOAPUtilities::translate(retMsg) << __E__;
1465 if(SOAPUtilities::translate(retMsg).getCommand() ==
"Fault")
1467 __SUP_SS__ <<
"Unrecognized command at destination TRACE Supervisor "
1469 << appInfo.first <<
"/" << appInfo.second.getId()
1470 <<
" name = " << appInfo.second.getName()
1471 <<
" class = " << appInfo.second.getClass()
1472 <<
" hostname = " << appInfo.second.getHostname() << __E__;
1475 else if(SOAPUtilities::translate(retMsg).getCommand() ==
"TRACEFault")
1477 __SUP_SS__ <<
"Error received: " << rxParameters.getValue(
"Error")
1482 catch(
const xdaq::exception::Exception& e)
1484 __SUP_SS__ <<
"Error transmitting request to TRACE Supervisor LID = "
1485 << appInfo.second.getId()
1486 <<
" name = " << appInfo.second.getName() <<
". \n\n"
1487 << e.what() << __E__;
1491 traceTriggerStatus += rxParameters.getValue(
"TRACETriggerStatus");
1494 __SUP_COUT__ <<
"TRACE Trigger Status received: \n"
1495 << traceTriggerStatus << __E__;
1496 xmlOut.addTextElementToData(
"traceTriggerStatus", traceTriggerStatus);
1498 else if(requestType ==
"SetTriggerEnable")
1500 __SUP_COUT__ <<
"requestType " << requestType << __E__;
1504 __SUP_COUTV__(hostList);
1506 std::vector<std::string > hosts;
1508 auto& allTraceApps = allSupervisorInfo_.getAllTraceControllerSupervisorInfo();
1515 std::string modifiedTriggerStatus =
"";
1516 std::string xdaqHostname;
1518 for(
auto& host : hosts)
1522 __SUP_COUTV__(host);
1529 xdaqHostname = traceMapToXDAQHostname_.at(host);
1533 __SUP_SS__ <<
"Could not find the translation from TRACE hostname '"
1534 << host <<
"' to xdaq Context hostname." << __E__;
1535 ss <<
"Here is the existing map (size=" << traceMapToXDAQHostname_.size()
1541 __SUP_COUTV__(xdaqHostname);
1543 auto& appInfo = allTraceApps.at(xdaqHostname);
1544 __SUP_COUT__ <<
"Supervisor hostname = " << host <<
"/" << xdaqHostname <<
":"
1545 << appInfo.getId() <<
" name = " << appInfo.getName()
1546 <<
" class = " << appInfo.getClass()
1547 <<
" hostname = " << appInfo.getHostname() << __E__;
1551 txParameters.
addParameter(
"Request",
"SetTriggerEnable");
1554 xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply(
1555 appInfo.getDescriptor(),
"TRACESupervisorRequest", txParameters);
1556 SOAPUtilities::receive(retMsg, rxParameters);
1557 __SUP_COUT__ <<
"Received TRACE response: "
1558 << SOAPUtilities::translate(retMsg).getCommand() <<
" ==> "
1559 << SOAPUtilities::translate(retMsg) << __E__;
1561 if(SOAPUtilities::translate(retMsg).getCommand() ==
"Fault")
1563 __SUP_SS__ <<
"Unrecognized command at destination TRACE Supervisor "
1565 << host <<
"/" << appInfo.getId()
1566 <<
" name = " << appInfo.getName()
1567 <<
" class = " << appInfo.getClass()
1568 <<
" hostname = " << appInfo.getHostname() << __E__;
1571 else if(SOAPUtilities::translate(retMsg).getCommand() ==
"TRACEFault")
1573 __SUP_SS__ <<
"Error received: " << rxParameters.getValue(
"Error")
1578 catch(
const xdaq::exception::Exception& e)
1580 __SUP_SS__ <<
"Error transmitting request to TRACE Supervisor LID = "
1581 << appInfo.getId() <<
" name = " << appInfo.getName()
1583 << e.what() << __E__;
1587 modifiedTriggerStatus += rxParameters.getValue(
"TRACETriggerStatus");
1590 __SUP_COUT__ <<
"mod'd TRACE Trigger Status received: \n"
1591 << modifiedTriggerStatus << __E__;
1592 xmlOut.addTextElementToData(
"modTriggerStatus", modifiedTriggerStatus);
1594 else if(requestType ==
"ResetTRACE")
1596 __SUP_COUT__ <<
"requestType " << requestType << __E__;
1600 __SUP_COUTV__(hostList);
1602 std::vector<std::string > hosts;
1604 auto& allTraceApps = allSupervisorInfo_.getAllTraceControllerSupervisorInfo();
1611 std::string modifiedTriggerStatus =
"";
1612 std::string xdaqHostname;
1614 for(
auto& host : hosts)
1618 __SUP_COUTV__(host);
1625 xdaqHostname = traceMapToXDAQHostname_.at(host);
1629 __SUP_SS__ <<
"Could not find the translation from TRACE hostname '"
1630 << host <<
"' to xdaq Context hostname." << __E__;
1631 ss <<
"Here is the existing map (size=" << traceMapToXDAQHostname_.size()
1637 __SUP_COUTV__(xdaqHostname);
1639 auto& appInfo = allTraceApps.at(xdaqHostname);
1640 __SUP_COUT__ <<
"Supervisor hostname = " << host <<
"/" << xdaqHostname <<
":"
1641 << appInfo.getId() <<
" name = " << appInfo.getName()
1642 <<
" class = " << appInfo.getClass()
1643 <<
" hostname = " << appInfo.getHostname() << __E__;
1650 xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply(
1651 appInfo.getDescriptor(),
"TRACESupervisorRequest", txParameters);
1652 SOAPUtilities::receive(retMsg, rxParameters);
1653 __SUP_COUT__ <<
"Received TRACE response: "
1654 << SOAPUtilities::translate(retMsg).getCommand() <<
" ==> "
1655 << SOAPUtilities::translate(retMsg) << __E__;
1657 if(SOAPUtilities::translate(retMsg).getCommand() ==
"Fault")
1659 __SUP_SS__ <<
"Unrecognized command at destination TRACE Supervisor "
1661 << host <<
"/" << appInfo.getId()
1662 <<
" name = " << appInfo.getName()
1663 <<
" class = " << appInfo.getClass()
1664 <<
" hostname = " << appInfo.getHostname() << __E__;
1667 else if(SOAPUtilities::translate(retMsg).getCommand() ==
"TRACEFault")
1669 __SUP_SS__ <<
"Error received: " << rxParameters.getValue(
"Error")
1674 catch(
const xdaq::exception::Exception& e)
1676 __SUP_SS__ <<
"Error transmitting request to TRACE Supervisor LID = "
1677 << appInfo.getId() <<
" name = " << appInfo.getName()
1679 << e.what() << __E__;
1683 modifiedTriggerStatus += rxParameters.getValue(
"TRACETriggerStatus");
1686 __SUP_COUT__ <<
"mod'd TRACE Trigger Status received: \n"
1687 << modifiedTriggerStatus << __E__;
1688 xmlOut.addTextElementToData(
"modTriggerStatus", modifiedTriggerStatus);
1690 else if(requestType ==
"EnableTRACE")
1692 __SUP_COUT__ <<
"requestType " << requestType << __E__;
1697 __SUP_COUTV__(hostList);
1698 __SUP_COUTV__(enable);
1700 std::vector<std::string > hosts;
1702 auto& allTraceApps = allSupervisorInfo_.getAllTraceControllerSupervisorInfo();
1709 std::string modifiedTriggerStatus =
"";
1710 std::string xdaqHostname;
1712 for(
auto& host : hosts)
1716 __SUP_COUTV__(host);
1723 xdaqHostname = traceMapToXDAQHostname_.at(host);
1727 __SUP_SS__ <<
"Could not find the translation from TRACE hostname '"
1728 << host <<
"' to xdaq Context hostname." << __E__;
1729 ss <<
"Here is the existing map (size=" << traceMapToXDAQHostname_.size()
1735 __SUP_COUTV__(xdaqHostname);
1737 auto& appInfo = allTraceApps.at(xdaqHostname);
1738 __SUP_COUT__ <<
"Supervisor hostname = " << host <<
"/" << xdaqHostname <<
":"
1739 << appInfo.getId() <<
" name = " << appInfo.getName()
1740 <<
" class = " << appInfo.getClass()
1741 <<
" hostname = " << appInfo.getHostname() << __E__;
1749 xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply(
1750 appInfo.getDescriptor(),
"TRACESupervisorRequest", txParameters);
1751 SOAPUtilities::receive(retMsg, rxParameters);
1752 __SUP_COUT__ <<
"Received TRACE response: "
1753 << SOAPUtilities::translate(retMsg).getCommand() <<
" ==> "
1754 << SOAPUtilities::translate(retMsg) << __E__;
1756 if(SOAPUtilities::translate(retMsg).getCommand() ==
"Fault")
1758 __SUP_SS__ <<
"Unrecognized command at destination TRACE Supervisor "
1760 << host <<
"/" << appInfo.getId()
1761 <<
" name = " << appInfo.getName()
1762 <<
" class = " << appInfo.getClass()
1763 <<
" hostname = " << appInfo.getHostname() << __E__;
1766 else if(SOAPUtilities::translate(retMsg).getCommand() ==
"TRACEFault")
1768 __SUP_SS__ <<
"Error received: " << rxParameters.getValue(
"Error")
1773 catch(
const xdaq::exception::Exception& e)
1775 __SUP_SS__ <<
"Error transmitting request to TRACE Supervisor LID = "
1776 << appInfo.getId() <<
" name = " << appInfo.getName()
1778 << e.what() << __E__;
1782 modifiedTriggerStatus += rxParameters.getValue(
"TRACETriggerStatus");
1785 __SUP_COUT__ <<
"mod'd TRACE Trigger Status received: \n"
1786 << modifiedTriggerStatus << __E__;
1787 xmlOut.addTextElementToData(
"modTriggerStatus", modifiedTriggerStatus);
1789 else if(requestType ==
"GetTraceSnapshot")
1791 __SUP_COUT__ <<
"requestType " << requestType << __E__;
1797 __SUP_COUTV__(hostList);
1798 __SUP_COUTV__(filterFor);
1799 __SUP_COUTV__(filterOut);
1801 std::vector<std::string > hosts;
1803 auto& allTraceApps = allSupervisorInfo_.getAllTraceControllerSupervisorInfo();
1811 std::string modifiedTriggerStatus =
"";
1812 std::string xdaqHostname;
1814 for(
auto& host : hosts)
1818 __SUP_COUTV__(host);
1825 xdaqHostname = traceMapToXDAQHostname_.at(host);
1829 __SUP_SS__ <<
"Could not find the translation from TRACE hostname '"
1830 << host <<
"' to xdaq Context hostname." << __E__;
1831 ss <<
"Here is the existing map (size=" << traceMapToXDAQHostname_.size()
1837 __SUP_COUTV__(xdaqHostname);
1839 auto& appInfo = allTraceApps.at(xdaqHostname);
1840 __SUP_COUT__ <<
"Supervisor hostname = " << host <<
"/" << xdaqHostname <<
":"
1841 << appInfo.getId() <<
" name = " << appInfo.getName()
1842 <<
" class = " << appInfo.getClass()
1843 <<
" hostname = " << appInfo.getHostname() << __E__;
1852 xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply(
1853 appInfo.getDescriptor(),
"TRACESupervisorRequest", txParameters);
1854 SOAPUtilities::receive(retMsg, rxParameters);
1855 __SUP_COUT__ <<
"Received TRACE response: "
1856 << SOAPUtilities::translate(retMsg).getCommand() << __E__;
1859 if(SOAPUtilities::translate(retMsg).getCommand() ==
"Fault")
1861 __SUP_SS__ <<
"Unrecognized command at destination TRACE Supervisor "
1863 << host <<
"/" << appInfo.getId()
1864 <<
" name = " << appInfo.getName()
1865 <<
" class = " << appInfo.getClass()
1866 <<
" hostname = " << appInfo.getHostname() << __E__;
1869 else if(SOAPUtilities::translate(retMsg).getCommand() ==
"TRACEFault")
1871 __SUP_SS__ <<
"Error received: " << rxParameters.getValue(
"Error")
1876 catch(
const xdaq::exception::Exception& e)
1878 __SUP_SS__ <<
"Error transmitting request to TRACE Supervisor LID = "
1879 << appInfo.getId() <<
" name = " << appInfo.getName()
1881 << e.what() << __E__;
1885 modifiedTriggerStatus += rxParameters.getValue(
"TRACETriggerStatus");
1886 xmlOut.addTextElementToData(
"host", host);
1887 std::string snapshot = rxParameters.getValue(
"TRACESnapshot");
1896 std::string filename =
1897 USER_CONSOLE_SNAPSHOT_PATH +
"snapshot_" + host +
".txt";
1898 __SUP_COUTV__(filename);
1899 FILE* fp = fopen(filename.c_str(),
"w");
1902 __SUP_SS__ <<
"Failed to create snapshot file: " << filename << __E__;
1906 "TRACE Snapshot taken at %s\n",
1909 if(snapshot.size() > 5 && snapshot[2] !=
'i')
1914 " idx us_tod delta pid tid cpu "
1915 " trcname lvl r msg \n");
1917 "----- ---------------- ----------- ------ ------ --- "
1918 "-------------------------------------- --- - "
1919 "--------------------------\n");
1921 fprintf(fp,
"%s", snapshot.c_str());
1926 __SUP_COUT__ <<
"mod'd TRACE Trigger Status received: \n"
1927 << modifiedTriggerStatus << __E__;
1928 xmlOut.addTextElementToData(
"modTriggerStatus", modifiedTriggerStatus);
1930 else if(requestType ==
"GetCustomCountsAndActions" ||
1931 requestType ==
"AddCustomCountsAndAction" ||
1932 requestType ==
"ModifyCustomCountsAndAction")
1934 __SUP_COUT__ <<
"requestType " << requestType
1935 <<
" size=" << priorityCustomTriggerList_.size() << __E__;
1940 std::lock_guard<std::mutex> lock(messageMutex_);
1942 if(requestType ==
"AddCustomCountsAndAction" ||
1943 requestType ==
"ModifyCustomCountsAndAction")
1947 uint32_t priority = CgiDataUtilities::postDataAsInt(cgiIn,
"priority");
1950 uint32_t triggerOnCount =
1951 CgiDataUtilities::postDataAsInt(cgiIn,
"triggerOnCount");
1953 CgiDataUtilities::postDataAsInt(cgiIn,
"doLoop") > 0 ? true :
false;
1955 CgiDataUtilities::postDataAsInt(cgiIn,
"isArmed") > 0 ? true :
false;
1957 __SUP_COUTV__(needle);
1958 __SUP_COUTV__(priority);
1959 __SUP_COUTV__(action);
1960 __SUP_COUTV__(triggerOnCount);
1961 __SUP_COUTV__(doLoop);
1962 __SUP_COUTV__(isArmed);
1964 if(requestType ==
"ModifyCustomCountsAndAction")
1968 std::string currentNeedle =
1972 std::vector<std::string> csvNeedles =
1974 for(
size_t i = csvNeedles.size() - 1; i < csvNeedles.size(); --i)
1976 if(csvNeedles[i].size() == 0)
1979 priority = modifyCustomTriggeredAction(
1991 addCustomTriggeredAction(
1992 needle, action, priority, triggerOnCount, doLoop, isArmed);
1994 saveCustomCountList();
1998 size_t untriggeredCount =
2001 for(
const auto& customCount : priorityCustomTriggerList_)
2003 xercesc::DOMElement* customCountParent =
2004 xmlOut.addTextElementToData(
"customCount",
"");
2006 if(customCount.occurrences < untriggeredCount)
2007 untriggeredCount -= customCount.occurrences;
2010 __SUP_SS__ <<
"Impossible custom count; notify admins! "
2011 << customCount.occurrences <<
" > " << untriggeredCount
2023 "count", std::to_string(customCount.occurrences), customCountParent);
2025 "action", customCount.action, customCountParent);
2027 std::to_string(customCount.triggerOnCount),
2030 "doLoop", std::to_string(customCount.doLoop), customCountParent);
2032 "isArmed", std::to_string(customCount.isArmed), customCountParent);
2036 xercesc::DOMElement* customCountParent =
2037 xmlOut.addTextElementToData(
"customCount",
"");
2040 "count", std::to_string(untriggeredCount), customCountParent);
2048 __SUP_SS__ <<
"requestType Request, " << requestType
2049 <<
", not recognized by the Console Supervisor (was it intended for "
2050 "another Supervisor?)."
2065 std::stringstream ss;
2068 CorePropertySupervisorBase::getSupervisorUptime()));
2076 ss <<
", Errors: " << errorCount_;
2077 ss <<
", Warns: " << warnCount_;
2078 ss <<
", Last Error ("
2082 << (lastErrorMessageTime_ ? StringMacros::encodeURIComponent(lastErrorMessage_)
2084 ss <<
", Last Warn ("
2088 << (lastWarnMessageTime_ ? StringMacros::encodeURIComponent(lastWarnMessage_)
2090 ss <<
", Last Info ("
2094 << (lastInfoMessageTime_ ? StringMacros::encodeURIComponent(lastInfoMessage_)
2096 ss <<
", Info #: " << infoCount_;
2097 ss <<
", First Error ("
2098 << (firstErrorMessageTime_
2102 << (firstErrorMessageTime_ ? StringMacros::encodeURIComponent(firstErrorMessage_)
2104 ss <<
", First Warn ("
2108 << (firstWarnMessageTime_ ? StringMacros::encodeURIComponent(firstWarnMessage_)
2110 ss <<
", First Info ("
2114 << (firstInfoMessageTime_ ? StringMacros::encodeURIComponent(firstInfoMessage_)
2144 const size_t lastUpdateCount)
2148 if(messages_.size() == 0)
2152 if(lastUpdateCount > messages_.back().getCount() && lastUpdateCount != (
size_t)-1)
2154 __SS__ <<
"Invalid lastUpdateCount: " << lastUpdateCount
2155 <<
" messagesArray size = " << messages_.back().getCount() << __E__;
2161 std::lock_guard<std::mutex> lock(messageMutex_);
2163 xmlOut->addTextElementToData(
"last_update_count",
2164 std::to_string(messages_.back().getCount()));
2166 refreshParent_ = xmlOut->addTextElementToData(
"messages",
"");
2168 bool requestOutOfSync =
false;
2169 std::string requestOutOfSyncMsg;
2171 size_t refreshReadPointer = 0;
2172 if(lastUpdateCount != (
size_t)-1)
2174 while(refreshReadPointer < messages_.size() &&
2175 messages_[refreshReadPointer].getCount() <= lastUpdateCount)
2177 ++refreshReadPointer;
2181 if(refreshReadPointer >= messages_.size())
2185 if(messages_.size() - refreshReadPointer > maxClientMessageRequest_)
2191 refreshReadPointer = messages_.size() - maxClientMessageRequest_;
2203 xmlOut->addTextElementToData(
2204 "earliest_update_count",
2205 std::to_string(messages_[refreshReadPointer].getCount()));
2207 std::string messagesJson =
"[";
2210 for(; refreshReadPointer < messages_.size(); ++refreshReadPointer)
2212 auto msg = messages_[refreshReadPointer];
2213 if(msg.getCount() < lastUpdateCount)
2215 if(!requestOutOfSync)
2217 requestOutOfSync =
true;
2218 __SS__ <<
"Request is out of sync! Message count should be more recent! "
2219 << msg.getCount() <<
" < " << lastUpdateCount << __E__;
2220 requestOutOfSyncMsg = ss.str();
2227 addMessageToResponse(messagesJson, msg);
2228 __COUTTV__(messagesJson.size());
2232 messagesJson +=
"]";
2236 if(requestOutOfSync)
2237 __SUP_COUT__ << requestOutOfSyncMsg;
2261 void ConsoleSupervisor::prependHistoricMessages(
HttpXmlDocument* xmlOut,
2262 const size_t earliestOnhandMessageCount)
2266 if(messages_.size() == 0)
2270 if(earliestOnhandMessageCount >= messages_.back().getCount())
2273 <<
"Invalid claim from user request of earliest onhand message sequence ID = "
2274 << earliestOnhandMessageCount
2275 <<
". Latest existing sequence ID = " << messages_.back().getCount()
2276 <<
". Was the Console Supervisor restarted?" << __E__;
2282 std::lock_guard<std::mutex> lock(messageMutex_);
2284 refreshParent_ = xmlOut->addTextElementToData(
"messages",
"");
2286 size_t refreshReadPointer = 0;
2287 size_t readCountStart = earliestOnhandMessageCount - maxClientMessageRequest_;
2288 if(readCountStart >= messages_.back().getCount())
2292 while(refreshReadPointer < messages_.size() &&
2293 messages_[refreshReadPointer].getCount() < readCountStart)
2295 ++refreshReadPointer;
2298 if(refreshReadPointer >= messages_.size())
2301 xmlOut->addTextElementToData(
"earliest_update_count",
2302 std::to_string(readCountStart));
2304 std::string messagesJson =
"[";
2308 for(; refreshReadPointer < messages_.size(); ++refreshReadPointer)
2310 auto msg = messages_[refreshReadPointer];
2311 if(messages_[refreshReadPointer].getCount() >= earliestOnhandMessageCount)
2314 addMessageToResponse(messagesJson, msg);
2318 messagesJson +=
"]";
2329 for(
auto& field : msg.fields)
2331 if(field.first == ConsoleMessageStruct::FieldType::SOURCEID)
2335 if(field.first == ConsoleMessageStruct::FieldType::TIMESTAMP)
2342 "message_" + ConsoleMessageStruct::fieldNames.at(field.first),
2355 "message_Count", std::to_string(msg.getCount()), refreshParent_);
2367 void ConsoleSupervisor::addMessageToResponse(std::string& xmlValue,
2370 if(xmlValue.size() &&
2371 xmlValue[xmlValue.size() - 1] !=
'[')
2376 for(
auto& field : msg.fields)
2378 if(field.first == ConsoleMessageStruct::FieldType::SOURCEID)
2382 if(field.first == ConsoleMessageStruct::FieldType::TIMESTAMP)
2388 if(field.first == ConsoleMessageStruct::FieldType::MSG ||
2389 field.first == ConsoleMessageStruct::FieldType::SOURCE)
2390 xmlValue +=
"\"" + ConsoleMessageStruct::fieldNames.at(field.first) +
2393 xmlValue +=
"\"" + ConsoleMessageStruct::fieldNames.at(field.first) +
2394 "\":\"" + field.second +
"\",";
2398 xmlValue +=
"\"Level\":\"" + msg.getLevel() +
"\",";
2402 xmlValue +=
"\"Time\":\"" + msg.getTime() +
"\",";
2406 xmlValue +=
"\"Count\":\"" + std::to_string(msg.getCount()) +
"\",";
2410 xmlValue +=
"\"Custom\":\"" +
2412 msg.getCustomTriggerMatch().needleSubstrings, {
'*'})) +
static std::string postData(cgicc::Cgicc &cgi, const std::string &needle)
virtual void forceSupervisorPropertyValues(void) override
virtual void request(const std::string &requestType, cgicc::Cgicc &cgiIn, HttpXmlDocument &xmlOut, const WebUsers::RequestUserInfo &userInfo) override
static const std::set< std::string > CUSTOM_TRIGGER_ACTIONS
Count always happens, and System Message always happens for FSM commands.
virtual std::string getStatusProgressDetail(void) override
void sendAsyncExceptionToGateway(const std::string &errMsg, bool isPauseException, bool isStopException)
void addParameter(const std::string name, const std::string value)
xercesc::DOMElement * addTextElementToParent(const std::string &childName, const std::string &childText, xercesc::DOMElement *parent)
void INIT_MF(const char *name)
@ SEQID
sequence ID is incrementing number independent from each source
static std::string getTimestampString(const std::string &linuxTimeInSeconds)
static void getVectorFromString(const std::string &inputString, std::vector< std::string > &listToReturn, const std::set< char > &delimiter={',', '|', '&'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'}, std::vector< char > *listOfDelimiters=0, bool decodeURIComponents=false)
static std::string exec(const char *cmd)
static std::string setToString(const std::set< T > &setToReturn, const std::string &delimeter=", ")
static std::string escapeString(std::string inString, bool allowWhiteSpace=false, bool forHtml=false)
static std::string vectorToString(const std::vector< T > &setToReturn, const std::string &delimeter=", ")
static std::string mapToString(const std::map< std::string, T > &mapToReturn, const std::string &primaryDelimeter=", ", const std::string &secondaryDelimeter=": ")
static void getMapFromString(const std::string &inputString, std::map< S, T > &mapToReturn, const std::set< char > &pairPairDelimiter={',', '|', '&'}, const std::set< char > &nameValueDelimiter={'=', ':'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'})
static std::string getTimeDurationString(const time_t durationInSeconds=time(0))
static std::string decodeURIComponent(const std::string &data)