1 #include "otsdaq-utilities/MacroMaker/MacroMakerSupervisor.h"
3 #include "otsdaq/CodeEditor/CodeEditor.h"
4 #include "otsdaq/ConfigurationInterface/ConfigurationManager.h"
5 #include "otsdaq/FECore/FEVInterface.h"
7 #include "otsdaq/NetworkUtilities/TransceiverSocket.h"
18 #include "otsdaq/TableCore/TableGroupKey.h"
20 #define MACROS_DB_PATH std::string(__ENV__("SERVICE_DATA_PATH")) + "/MacroData/"
21 #define MACROS_HIST_PATH std::string(__ENV__("SERVICE_DATA_PATH")) + "/MacroHistory/"
22 #define MACROS_SEQUENCE_PATH std::string(__ENV__("SERVICE_DATA_PATH")) + "/MacroSequence/"
23 #define MACROS_EXPORT_PATH std::string("/MacroExport/")
25 #define SEQUENCE_FILE_NAME \
26 std::string(__ENV__("SERVICE_DATA_PATH")) + "/OtsWizardData/sequence.dat"
27 #define SEQUENCE_OUT_FILE_NAME \
28 std::string(__ENV__("SERVICE_DATA_PATH")) + "/OtsWizardData/sequence.out"
33 #define __MF_SUBJECT__ "MacroMaker"
41 __SUP_COUT__ <<
"Constructing..." << __E__;
46 mkdir(((std::string)MACROS_DB_PATH).c_str(), 0755);
47 mkdir(((std::string)MACROS_HIST_PATH).c_str(), 0755);
48 mkdir(((std::string)MACROS_SEQUENCE_PATH).c_str(), 0755);
49 mkdir((__ENV__(
"SERVICE_DATA_PATH") + MACROS_EXPORT_PATH).c_str(), 0755);
52 &MacroMakerSupervisor::frontEndCommunicationRequest,
57 if(CorePropertySupervisorBase::allSupervisorInfo_.isMacroMakerMode())
59 __SUP_COUT__ <<
"Starting constructor for Macro Maker mode." << __E__;
61 xgi::bind(
this, &MacroMakerSupervisor::requestIcons,
"requestIcons");
62 xgi::bind(
this, &MacroMakerSupervisor::verification,
"Verify");
63 xgi::bind(
this, &MacroMakerSupervisor::tooltipRequest,
"TooltipRequest");
64 xgi::bind(
this, &MacroMakerSupervisor::requestWrapper,
"Request");
66 &MacroMakerSupervisor::supervisorSequenceCheck,
67 "SupervisorSequenceCheck",
70 __SUP_COUT__ <<
"Completed constructor for Macro Maker mode." << __E__;
73 __SUP_COUT__ <<
"Not Macro Maker only mode." << __E__;
79 if(CorePropertySupervisorBase::allSupervisorInfo_.isMacroMakerMode())
85 ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME);
90 FEPluginTypetoFEsMap_.clear();
91 FEtoSupervisorMap_.clear();
92 FEtoPluginTypeMap_.clear();
95 __SUP_COUT__ <<
"FEs for app MacroMakerFESupervisor"
101 .
getNode(
"MacroMakerFESupervisor")
102 .
getNode(
"LinkToSupervisorTable")
103 .
getNode(
"LinkToFEInterfaceTable")
106 for(
auto& fe : feChildren)
108 if(!fe.second.status())
111 __SUP_COUTV__(fe.first);
112 FEtoSupervisorMap_[fe.first] =
113 atoi(__ENV__(
"FE_SUPERVISOR_ID"));
115 std::string pluginType =
116 fe.second.getNode(
"FEInterfacePluginName").getValue();
117 FEPluginTypetoFEsMap_[pluginType].emplace(fe.first);
118 FEtoPluginTypeMap_[fe.first] = pluginType;
122 __SUP_COUTV__(StringMacros::mapToString(FEtoSupervisorMap_));
123 __SUP_COUTV__(StringMacros::mapToString(FEPluginTypetoFEsMap_));
124 __SUP_COUTV__(StringMacros::mapToString(FEtoPluginTypeMap_));
129 bool enableRemoteControl =
false;
132 __ENV__(
"OTS_MACROMAKER_UDP_PORT");
133 __ENV__(
"OTS_MACROMAKER_UDP_IP");
134 enableRemoteControl =
true;
136 catch(
const std::runtime_error& e)
138 __SUP_COUT__ <<
"Ignoring MacroMaker server env var error: " << e.what()
143 __SUP_COUT__ <<
"Ignoring unknown error reading OTS_MACROMAKER_UDP_PORT/"
144 "OTS_MACROMAKER_UDP_IP env vars."
148 if(enableRemoteControl)
150 __SUP_COUT_INFO__ <<
"Enabling remote control over UDP..." << __E__;
154 MacroMakerSupervisor::RemoteControlWorkLoop(s);
160 __SUP_COUT_INFO__ <<
"Remote control over UDP is disabled." << __E__;
163 __SUP_COUT__ <<
"Constructed." << __E__;
167 MacroMakerSupervisor::~MacroMakerSupervisor(
void) { destroy(); }
170 void MacroMakerSupervisor::init(
void)
175 allFESupervisorInfo_ =
176 SupervisorInfoMap(allSupervisorInfo_.getAllFETypeSupervisorInfo());
181 void MacroMakerSupervisor::destroy(
void)
193 void MacroMakerSupervisor::tooltipRequest(xgi::Input* in, xgi::Output* out)
195 cgicc::Cgicc cgi(in);
203 if(securityCode_.compare(submittedSequence) != 0)
205 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match!"
217 if(Command ==
"check")
225 else if(Command ==
"setNeverShow")
228 WebUsers::DEFAULT_ADMIN_USERNAME,
237 __COUT__ <<
"Command Request, " << Command <<
", not recognized." << __E__;
243 void MacroMakerSupervisor::verification(xgi::Input* in, xgi::Output* out)
245 cgicc::Cgicc cgi(in);
247 __COUT__ <<
"submittedSequence=" << submittedSequence <<
" " << time(0) << __E__;
249 std::string securityWarning =
"";
251 if(securityCode_.compare(submittedSequence) != 0)
253 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match!"
255 *out <<
"Invalid code.";
261 __COUT__ <<
"*** Successfully authenticated security sequence "
262 <<
"@ " << time(0) << __E__;
267 securityWarning =
"&secure=False";
271 *out <<
"<!DOCTYPE HTML><html lang='en'><head><title>ots MacroMaker mode</title>" <<
274 "<link rel='apple-touch-icon' sizes='57x57' href='/WebPath/images/otsdaqIcons/apple-icon-57x57.png'>\
275 <link rel='apple-touch-icon' sizes='60x60' href='/WebPath/images/otsdaqIcons/apple-icon-60x60.png'>\
276 <link rel='apple-touch-icon' sizes='72x72' href='/WebPath/images/otsdaqIcons/apple-icon-72x72.png'>\
277 <link rel='apple-touch-icon' sizes='76x76' href='/WebPath/images/otsdaqIcons/apple-icon-76x76.png'>\
278 <link rel='apple-touch-icon' sizes='114x114' href='/WebPath/images/otsdaqIcons/apple-icon-114x114.png'>\
279 <link rel='apple-touch-icon' sizes='120x120' href='/WebPath/images/otsdaqIcons/apple-icon-120x120.png'>\
280 <link rel='apple-touch-icon' sizes='144x144' href='/WebPath/images/otsdaqIcons/apple-icon-144x144.png'>\
281 <link rel='apple-touch-icon' sizes='152x152' href='/WebPath/images/otsdaqIcons/apple-icon-152x152.png'>\
282 <link rel='apple-touch-icon' sizes='180x180' href='/WebPath/images/otsdaqIcons/apple-icon-180x180.png'>\
283 <link rel='icon' type='image/png' sizes='192x192' href='/WebPath/images/otsdaqIcons/android-icon-192x192.png'>\
284 <link rel='icon' type='image/png' sizes='32x32' href='/WebPath/images/otsdaqIcons/favicon-32x32.png'>\
285 <link rel='icon' type='image/png' sizes='96x96' href='/WebPath/images/otsdaqIcons/favicon-96x96.png'>\
286 <link rel='icon' type='image/png' sizes='16x16' href='/WebPath/images/otsdaqIcons/favicon-16x16.png'>\
287 <link rel='manifest' href='/WebPath/images/otsdaqIcons/manifest.json'>\
288 <meta name='msapplication-TileColor' content='#ffffff'>\
289 <meta name='msapplication-TileImage' content='/ms-icon-144x144.png'>\
290 <meta name='theme-color' content='#ffffff'>"
294 <<
"<frameset col='100%' row='100%'><frame "
295 "src='/WebPath/html/MacroMakerSupervisor.html?urn="
296 << this->getApplicationDescriptor()->getLocalId() << securityWarning
297 <<
"'></frameset></html>";
301 void MacroMakerSupervisor::generateURL()
303 defaultSequence_ =
true;
306 FILE* fp = fopen((SEQUENCE_FILE_NAME).c_str(),
"r");
309 __SUP_COUT_INFO__ <<
"Sequence length file found: " << SEQUENCE_FILE_NAME
312 fgets(line, 100, fp);
313 sscanf(line,
"%d", &length);
318 defaultSequence_ =
false;
324 <<
"(Reverting to default wiz security) Sequence length file NOT found: "
325 << SEQUENCE_FILE_NAME << __E__;
329 __SUP_COUT__ <<
"Sequence length = " << length << __E__;
333 const char alphanum[] =
335 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
336 "abcdefghijklmnopqrstuvwxyz";
338 for(
int i = 0; i < length; ++i)
340 securityCode_ += alphanum[rand() % (
sizeof(alphanum) - 1)];
343 __SUP_COUT__ << __ENV__(
"HOSTNAME") <<
":" << __ENV__(
"PORT")
344 <<
"/urn:xdaq-application:lid="
345 << this->getApplicationDescriptor()->getLocalId()
346 <<
"/Verify?code=" << securityCode_ << __E__;
352 fp = fopen((SEQUENCE_OUT_FILE_NAME).c_str(),
"w");
355 fprintf(fp,
"%s", securityCode_.c_str());
359 __SUP_COUT_ERR__ <<
"Sequence output file NOT found: " << SEQUENCE_OUT_FILE_NAME
366 void MacroMakerSupervisor::requestIcons(xgi::Input* in, xgi::Output* out)
368 cgicc::Cgicc cgi(in);
373 if(securityCode_.compare(submittedSequence) != 0)
375 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match! "
381 __COUT__ <<
"***Successfully authenticated security sequence. " << time(0)
394 *out <<
"Macro Maker "
395 ",MM,0,1,icon-MacroMaker.png,/WebPath/html/"
396 "MacroMaker.html?urn=290,/"
398 ",CFG,0,1,icon-Configure.png,/WebPath/html/"
399 "FEMacroTest.html?urn=290,/"
401 <<
",Code Editor,CODE,0,1,icon-CodeEditor.png,/urn:xdaq-application:lid=240/,/"
405 std::string iconFile = std::string(__ENV__(
"USER_DATA")) +
"/MacroMakerModeIcons.dat";
406 __COUT__ <<
"Macro Maker mode user icons file: " << iconFile << __E__;
407 FILE* fp = fopen(iconFile.c_str(),
"r");
410 __COUT__ <<
"Macro Maker mode user icons loading from " << iconFile << __E__;
411 fseek(fp, 0, SEEK_END);
412 const unsigned long fileSize = ftell(fp);
413 std::string fileString(fileSize, 0);
415 if(fread(&fileString[0], 1, fileSize, fp) != fileSize)
417 __COUT_ERR__ <<
"Unable to read proper size string from icons file!" << __E__;
422 __COUTV__(fileString);
426 __COUT__ <<
"Macro Maker mode user icons file not found: " << iconFile << __E__;
433 xoap::MessageReference MacroMakerSupervisor::supervisorSequenceCheck(
434 xoap::MessageReference message)
439 SOAPUtilities::receive(message, parameters);
441 std::string submittedSequence = parameters.getValue(
"sequence");
445 std::map<std::string , WebUsers::permissionLevel_t> permissionMap;
447 if(securityCode_ == submittedSequence)
448 permissionMap.emplace(
449 std::pair<std::string /*groupName*/, WebUsers::permissionLevel_t>(
453 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match!"
456 permissionMap.emplace(
457 std::pair<std::string /*groupName*/, WebUsers::permissionLevel_t>(
458 WebUsers::DEFAULT_USER_GROUP, WebUsers::PERMISSION_LEVEL_INACTIVE));
465 return SOAPUtilities::makeSOAPMessageReference(
"SequenceResponse", retParameters);
475 std::string ipAddressForRemoteControlOverUDP = __ENV__(
476 "OTS_MACROMAKER_UDP_IP");
477 int portForRemoteControlOverUDP = atoi(__ENV__(
478 "OTS_MACROMAKER_UDP_PORT"));
479 bool acknowledgementEnabled =
482 __COUTV__(ipAddressForRemoteControlOverUDP);
483 __COUTV__(portForRemoteControlOverUDP);
484 __COUTV__(acknowledgementEnabled);
487 portForRemoteControlOverUDP);
495 __SS__ <<
"FATAL Console error. Could not initialize socket at ip '"
496 << ipAddressForRemoteControlOverUDP <<
"' and port "
497 << portForRemoteControlOverUDP
498 <<
". Perhaps it is already in use? Exiting Remote Control "
499 "SOAPUtilities::receive loop."
506 __COUT__ <<
"UDP Remote Control workloop starting..." << __E__;
516 buffer, 0 , 1 ,
false ) !=
519 __COUT__ <<
"UDP Remote Control packet received of size = " << buffer.size()
525 if(buffer ==
"GetFrontendMacroInfo")
527 std::string macroPath = (std::string)MACROS_DB_PATH +
"NO-USER" +
"/";
528 mkdir(macroPath.c_str(), 0755);
529 std::string histPath =
530 (std::string)MACROS_HIST_PATH +
"NO-USER" +
"/";
531 mkdir(histPath.c_str(), 0755);
534 theSupervisor->getFEMacroList(xmldoc,
"NO-USER");
536 std::stringstream out;
540 __COUT__ <<
"out: " << out.str();
541 sock.acknowledge(out.str(),
546 else if(buffer.find(
"RunFrontendMacro") == 0)
550 std::vector<std::string> bufferFields =
552 if(bufferFields.size() < 8)
554 __SS__ <<
"Missing input arguments for running FE Macro: "
555 << bufferFields.size() <<
" vs 8 expected" << __E__;
559 std::string feClassSelected = bufferFields[1];
560 std::string feUIDSelected =
562 std::string macroType = bufferFields[3];
563 std::string macroName =
567 std::string outputArgs =
569 bool saveOutputs = bufferFields[7] ==
"1";
570 std::string username =
"NO-USER";
571 std::string userGroupPermission =
"allUsers: 255";
574 std::set<std::string> feUIDs;
576 std::string expandUID =
577 feUIDSelected.empty() ?
"*" : feUIDSelected;
582 for(
auto& feTypePair : theSupervisor->FEPluginTypetoFEsMap_)
584 if(feClassSelected.empty() || feClassSelected ==
"*" ||
585 feClassSelected == feTypePair.first)
586 for(
auto& uid : feTypePair.second)
595 auto group = std::make_shared<runFEMacroGroupStruct>();
596 group->historyFeClassSelected_ =
597 feClassSelected.empty() ?
"*" : feClassSelected;
598 group->historyFeUIDSelected_ =
599 feUIDSelected.empty() ?
"*" : feUIDSelected;
600 group->historyMacroType_ = macroType;
601 group->historyMacroName_ = macroName;
602 group->historyInputArgs_ = inputArgs;
603 group->historyOutputArgs_ = outputArgs;
604 group->historySaveOutputs_ = saveOutputs;
605 group->historyUsername_ = username;
607 for(
const std::string& uid : feUIDs)
608 group->tasks_.push_back(
609 std::make_shared<runFEMacroStruct>(xmldoc,
618 userGroupPermission));
621 std::lock_guard<std::mutex> lock(
622 theSupervisor->feMacroRunThreadStructMutex_);
623 group->groupID_ = ++theSupervisor->feMacroRunGroupIDCounter_;
624 if(theSupervisor->feMacroRunGroupIDCounter_ == 0)
625 group->groupID_ = ++theSupervisor->feMacroRunGroupIDCounter_;
627 for(
auto& task : group->tasks_)
629 task->bar_ = std::make_unique<ProgressBar>();
630 task->bar_->reset(macroName,
631 task->parameters_.feUIDSelected_);
633 theSupervisor->feMacroRunThreadStruct_.emplace_back(group);
636 std::thread([group, theSupervisor]() {
637 MacroMakerSupervisor::runFEMacroGroupSchedulerThread(
638 group, theSupervisor);
641 auto lastProgressSend = std::chrono::steady_clock::now();
642 while(!group->allDone())
646 auto now = std::chrono::steady_clock::now();
647 if(std::chrono::duration_cast<std::chrono::seconds>(
648 now - lastProgressSend)
651 lastProgressSend = now;
653 int totalProgress = 0;
656 std::lock_guard<std::mutex> lock(
657 theSupervisor->feMacroRunThreadStructMutex_);
658 for(
auto& task : group->tasks_)
661 if(task->feMacroRunDone_)
662 totalProgress += 100;
664 totalProgress += task->bar_->read();
669 (taskCount > 0) ? (totalProgress / taskCount) : 0;
674 sock.acknowledge(std::string(
"<progress>") +
675 std::to_string(percent) +
"</progress>",
681 std::string taskError;
682 for(
auto& task : group->tasks_)
684 if(task->parameters_.feMacroRunError_ !=
"")
686 taskError = task->parameters_.feMacroRunError_;
693 std::lock_guard<std::mutex> lock(
694 theSupervisor->feMacroRunThreadStructMutex_);
696 i < theSupervisor->feMacroRunThreadStruct_.size();
698 if(theSupervisor->feMacroRunThreadStruct_[i].get() ==
701 theSupervisor->feMacroRunThreadStruct_.erase(
702 theSupervisor->feMacroRunThreadStruct_.begin() + i);
707 if(!taskError.empty())
713 std::stringstream out;
717 __COUT__ <<
"out: " << out.str();
718 sock.acknowledge(out.str(),
725 __SS__ <<
"Unrecognized UDP command received: " << buffer << __E__;
729 catch(
const std::runtime_error& e)
731 __COUT_ERR__ <<
"Error during UDP command handling: " << e.what()
733 sock.acknowledge(std::string(
"Error: ") + e.what(),
true );
737 __COUT_ERR__ <<
"Unknown error caught during UDP command handling - "
740 sock.acknowledge(std::string(
"Error: ") +
"unknown error caught",
744 __COUT__ <<
"Done handling command '" << buffer <<
"'" << __E__;
754 void MacroMakerSupervisor::requestWrapper(xgi::Input* in, xgi::Output* out)
757 if(!CorePropertySupervisorBase::allSupervisorInfo_.isMacroMakerMode())
759 __SUP_COUTT__ <<
"Default request wrapper" << __E__;
760 return CoreSupervisorBase::requestWrapper(in, out);
764 __SUP_COUTT__ <<
"MacroMaker mode request handler!" << __E__;
768 cgicc::Cgicc cgiIn(in);
773 if(securityCode_.compare(submittedSequence) != 0)
775 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match! "
777 *out << WebUsers::REQ_NO_PERMISSION_RESPONSE.c_str();
782 __SUP_COUTT__ <<
"***Successfully authenticated security sequence. " << time(0)
789 __SUP_COUT_TYPE__(TLVL_DEBUG + 10) << __COUT_HDR__ <<
"requestType " << requestType
790 <<
" files: " << cgiIn.getFiles().size() << __E__;
793 WebUsers::RequestUserInfo userInfo(
799 userInfo.username_ =
"admin";
800 userInfo.displayName_ =
"Admin";
801 userInfo.usernameWithLock_ =
"admin";
802 userInfo.userSessionIndex_ = 0;
803 std::map<std::string , WebUsers::permissionLevel_t> initPermissions = {
808 __SUP_COUTT__ <<
"requestType: " << requestType << __E__;
809 else if(!userInfo.automatedCommand_)
810 __SUP_COUT__ <<
"requestType: " << requestType << __E__;
812 if(userInfo.NonXMLRequestType_)
818 catch(
const std::runtime_error& e)
820 __SUP_SS__ <<
"An error was encountered handling requestType '" << requestType
821 <<
"':" << e.what() << __E__;
822 __SUP_COUT_ERR__ <<
"\n" << ss.str();
826 __SUP_SS__ <<
"An unknown error was encountered handling requestType '"
827 << requestType <<
".' "
828 <<
"Please check the printouts to debug." << __E__;
833 catch(
const std::exception& e)
835 ss <<
"Exception message: " << e.what();
840 __SUP_COUT_ERR__ <<
"\n" << ss.str();
849 request(requestType, cgiIn, xmlOut, userInfo);
850 __SUP_COUTT__ <<
"Request '" << requestType <<
"' complete." << __E__;
852 catch(
const std::runtime_error& e)
854 __SUP_SS__ <<
"An error was encountered handling requestType '" << requestType
855 <<
"':" << e.what() << __E__;
856 __SUP_COUT_ERR__ <<
"\n" << ss.str();
857 xmlOut.addTextElementToData(
"Error", ss.str());
861 __SUP_SS__ <<
"An unknown error was encountered handling requestType '"
862 << requestType <<
".' "
863 <<
"Please check the printouts to debug." << __E__;
868 catch(
const std::exception& e)
870 ss <<
"Exception message: " << e.what();
875 __SUP_COUT_ERR__ <<
"\n" << ss.str();
876 xmlOut.addTextElementToData(
"Error", ss.str());
881 unsigned int occurance = 0;
885 __SUP_COUT_ERR__ <<
"'" << requestType <<
"' ERROR encountered: " << err
891 __SUP_COUTVS__(10, userInfo.NoXmlWhiteSpace_);
896 !userInfo.NoXmlWhiteSpace_ );
900 void MacroMakerSupervisor::request(
const std::string& requestType,
903 const WebUsers::RequestUserInfo& userInfo)
906 std::chrono::steady_clock::time_point requestStart = std::chrono::steady_clock::now();
907 time_t requestStartTime = time(0);
910 std::string username =
"";
911 for(
unsigned int i = 0; i < userInfo.username_.size(); ++i)
912 if((userInfo.username_[i] >=
'a' && userInfo.username_[i] <=
'z') ||
913 (userInfo.username_[i] >=
'A' && userInfo.username_[i] <=
'Z') ||
914 (userInfo.username_[i] >=
'0' && userInfo.username_[i] <=
'9') ||
915 userInfo.username_[i] >=
'-' || userInfo.username_[i] <=
'_')
916 username += userInfo.username_[i];
918 if(username.size() < 2)
920 __SUP_SS__ <<
"Illegal username '" << userInfo.username_ <<
"' received."
925 __SUP_COUT__ <<
"User name is " << userInfo.username_ <<
"." << __E__;
926 __SUP_COUT__ <<
"User permission level for request '" << requestType <<
"' is "
927 << unsigned(userInfo.permissionLevel_) <<
"." << __E__;
931 if(requestType ==
"loadFEHistory")
933 std::string histPath = (std::string)MACROS_HIST_PATH + userInfo.username_ +
"/";
934 mkdir(histPath.c_str(), 0755);
937 if(requestType ==
"loadFEMacroSequences")
939 std::string seqPath =
940 (std::string)MACROS_SEQUENCE_PATH + userInfo.username_ +
"/";
941 mkdir(seqPath.c_str(), 0755);
944 if(requestType ==
"getPermission")
946 xmlOut.addTextElementToData(
"Permission",
947 std::to_string(
unsigned(userInfo.permissionLevel_)));
950 std::string publicPath = (std::string)MACROS_DB_PATH +
"publicMacros/";
951 mkdir(publicPath.c_str(), 0755);
952 std::string exportPath =
953 __ENV__(
"SERVICE_DATA_PATH") + MACROS_EXPORT_PATH + userInfo.username_ +
"/";
954 mkdir(exportPath.c_str(), 0755);
957 handleRequest(requestType, xmlOut, cgiIn, userInfo);
959 __SUP_COUTT__ <<
"Total MacroMaker request time: "
960 << artdaq::TimeUtils::GetElapsedTime(requestStart) <<
" = "
961 << time(0) - requestStartTime <<
" seconds" << __E__;
963 catch(
const std::runtime_error& e)
965 __SS__ <<
"Error occurred handling request '" << requestType <<
"': " << e.what()
967 __SUP_COUT__ << ss.str();
968 xmlOut.addTextElementToData(
"Error", ss.str());
972 __SS__ <<
"Unknown error occurred handling request '" << requestType <<
"!'" << __E__;
977 catch(
const std::exception& e)
979 ss <<
"Exception message: " << e.what();
984 __SUP_COUT__ << ss.str();
985 xmlOut.addTextElementToData(
"Error", ss.str());
990 void MacroMakerSupervisor::handleRequest(
const std::string Command,
993 const WebUsers::RequestUserInfo& userInfo)
995 if(Command ==
"FElist")
998 std::string macroPath = (std::string)MACROS_DB_PATH + userInfo.username_ +
"/";
999 mkdir(macroPath.c_str(), 0755);
1000 std::string histPath = (std::string)MACROS_HIST_PATH + userInfo.username_ +
"/";
1001 mkdir(histPath.c_str(), 0755);
1005 else if(Command ==
"writeData")
1006 writeData(xmldoc, cgi, userInfo.username_);
1007 else if(Command ==
"readData")
1008 readData(xmldoc, cgi, userInfo.username_);
1009 else if(Command ==
"createMacro")
1010 createMacro(xmldoc, cgi, userInfo.username_);
1011 else if(Command ==
"loadMacros")
1012 loadMacros(xmldoc, userInfo.username_);
1013 else if(Command ==
"loadHistory")
1014 loadHistory(xmldoc, userInfo.username_);
1015 else if(Command ==
"deleteMacro")
1016 deleteMacro(xmldoc, cgi, userInfo.username_);
1017 else if(Command ==
"editMacro")
1018 editMacro(xmldoc, cgi, userInfo.username_);
1019 else if(Command ==
"clearHistory")
1020 clearHistory(userInfo.username_);
1021 else if(Command ==
"exportMacro")
1022 exportMacro(xmldoc, cgi, userInfo.username_);
1023 else if(Command ==
"exportFEMacro")
1024 exportFEMacro(xmldoc, cgi, userInfo.username_);
1025 else if(Command ==
"getFEMacroList")
1029 std::string macroPath = (std::string)MACROS_DB_PATH + userInfo.username_ +
"/";
1030 mkdir(macroPath.c_str(), 0755);
1031 std::string histPath = (std::string)MACROS_HIST_PATH + userInfo.username_ +
"/";
1032 mkdir(histPath.c_str(), 0755);
1034 getFEMacroList(xmldoc, userInfo.username_);
1036 else if(Command ==
"runFEMacro")
1038 runFEMacro(xmldoc, cgi, userInfo);
1039 else if(Command ==
"loadFEHistory")
1041 loadFEHistory(xmldoc, userInfo.username_);
1042 else if(Command ==
"clearFEHistory")
1044 clearFEHistory(userInfo.username_);
1045 else if(Command ==
"loadFEMacroSequences")
1046 loadFEMacroSequences(xmldoc, userInfo.username_);
1047 else if(Command ==
"saveFEMacroSequence")
1048 saveFEMacroSequence(cgi, userInfo.username_);
1049 else if(Command ==
"getFEMacroSequence")
1050 getFEMacroSequence(xmldoc, cgi, userInfo.username_);
1051 else if(Command ==
"deleteFEMacroSequence")
1052 deleteFEMacroSequence(cgi, userInfo.username_);
1053 else if(Command ==
"makeSequencePublic")
1054 makeSequencePublic(cgi, userInfo.username_);
1056 xmldoc.addTextElementToData(
"Error",
1057 "Command '" + Command +
1058 "' not recognized by the Macro Maker Supervisor "
1059 "(was it intended for another Supervisor?).");
1063 xoap::MessageReference MacroMakerSupervisor::frontEndCommunicationRequest(
1064 xoap::MessageReference message)
1068 __SUP_COUT__ <<
"FE Request received: " << SOAPUtilities::translate(message) << __E__;
1072 SOAPUtilities::receive(message, typeParameter);
1074 std::string type = typeParameter.getValue(
"type");
1076 std::string error =
"";
1078 if(type ==
"initFElist")
1080 __SUP_COUTV__(type);
1085 rxParameters.
addParameter(
"SubsystemCommonOverrideList");
1086 SOAPUtilities::receive(message, rxParameters);
1088 std::string groupName = rxParameters.getValue(
"groupName");
1089 std::string groupKey = rxParameters.getValue(
"groupKey");
1090 std::string subsystemCommonList = rxParameters.getValue(
"SubsystemCommonList");
1091 std::string subsystemCommonOverrideList =
1092 rxParameters.getValue(
"SubsystemCommonOverrideList");
1094 __SUP_COUTV__(groupName);
1095 __SUP_COUTV__(groupKey);
1096 __SUP_COUTV__(subsystemCommonList);
1097 __SUP_COUTV__(subsystemCommonOverrideList);
1100 std::map<std::string ,
TableVersion> mergeInTables, overrideTables;
1103 if(!subsystemCommonList.empty())
1105 subsystemCommonList =
1107 __COUT__ <<
"Transition parameter SubsystemCommonList: "
1108 << subsystemCommonList << __E__;
1115 if(!subsystemCommonOverrideList.empty())
1117 subsystemCommonOverrideList =
1119 __COUT__ <<
"Transition parameter SubsystemCommonOverrideList: "
1120 << subsystemCommonOverrideList << __E__;
1142 ConfigurationManager::LoadGroupType::ALL_TYPES,
1151 const SupervisorInfoMap& feTypeSupervisors =
1152 CorePropertySupervisorBase::allSupervisorInfo_.getAllFETypeSupervisorInfo();
1155 cfgMgr.
getNode(ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME);
1157 __SUP_COUT__ <<
"Number of FE Supervisors found = " << feTypeSupervisors.size()
1160 FEPluginTypetoFEsMap_.clear();
1161 FEtoSupervisorMap_.clear();
1162 FEtoPluginTypeMap_.clear();
1163 for(
auto& feApp : feTypeSupervisors)
1165 __SUP_COUT__ <<
"FEs for app " << feApp.first <<
":" << feApp.second.getName()
1168 auto feChildren = appsNode.
getNode(feApp.second.getName())
1169 .
getNode(
"LinkToSupervisorTable")
1170 .
getNode(
"LinkToFEInterfaceTable")
1173 for(
auto& fe : feChildren)
1175 if(!fe.second.status())
1178 __SUP_COUTV__(fe.first);
1179 FEtoSupervisorMap_[fe.first] = feApp.first;
1181 std::string pluginType =
1182 fe.second.getNode(
"FEInterfacePluginName").getValue();
1183 FEPluginTypetoFEsMap_[pluginType].emplace(fe.first);
1184 FEtoPluginTypeMap_[fe.first] = pluginType;
1192 else if(type ==
"feSend" ||
1193 type ==
"feMacro" ||
1194 type ==
"feMacroMultiDimensionalStart" ||
1195 type ==
"feMacroMultiDimensionalCheck" ||
1196 type ==
"macroMultiDimensionalStart" ||
1197 type ==
"macroMultiDimensionalCheck")
1199 __SUP_COUTV__(type);
1202 SOAPUtilities::receive(message, rxParameters);
1204 std::string targetInterfaceID = rxParameters.getValue(
"targetInterfaceID");
1206 __SUP_COUTV__(targetInterfaceID);
1208 auto feIt = FEtoSupervisorMap_.find(targetInterfaceID);
1209 if(feIt == FEtoSupervisorMap_.end())
1211 __SUP_SS__ <<
"Destination front end interface ID '" << targetInterfaceID
1212 <<
"' was not found in the list of front ends." << __E__;
1216 unsigned int FESupervisorIndex = feIt->second;
1217 __SUP_COUT__ <<
"Found supervisor index: " << FESupervisorIndex << __E__;
1219 SupervisorInfoMap::iterator it = allFESupervisorInfo_.find(FESupervisorIndex);
1220 if(it == allFESupervisorInfo_.end())
1222 __SUP_SS__ <<
"Error transmitting request to FE Supervisor '"
1223 << targetInterfaceID <<
":" << FESupervisorIndex <<
".' \n\n"
1224 <<
"The FE Supervisor Index does not exist. Have you configured "
1225 "the state machine properly?"
1230 if(type ==
"macroMultiDimensionalStart")
1236 SOAPUtilities::receive(message, rxParameters);
1237 std::string macroName = rxParameters.getValue(
"macroName");
1238 __SUP_COUTV__(macroName);
1240 std::string macroString;
1241 loadMacro(macroName, macroString);
1245 SOAPUtilities::addParameters(message, parameters);
1250 __SUP_COUT__ <<
"Forwarding request: " << SOAPUtilities::translate(message)
1253 xoap::MessageReference replyMessage =
1254 SOAPMessenger::sendWithSOAPReply(it->second.getDescriptor(), message);
1256 if(type !=
"feSend")
1258 __SUP_COUT__ <<
"Forwarding FE Macro response: "
1259 << SOAPUtilities::translate(replyMessage) << __E__;
1261 return replyMessage;
1264 catch(
const xdaq::exception::Exception& e)
1266 __SUP_SS__ <<
"Error forwarding FE Communication request to FE Supervisor '"
1267 << targetInterfaceID <<
":" << FESupervisorIndex <<
".' "
1268 <<
"Have you configured the state machine properly?\n\n"
1269 << e.what() << __E__;
1275 __SUP_SS__ <<
"Unrecognized FE Communication type: " << type << __E__;
1279 return SOAPUtilities::makeSOAPMessageReference(
"Received");
1281 catch(
const std::runtime_error& e)
1283 __SUP_SS__ <<
"Error processing FE communication request: " << e.what() << __E__;
1284 __SUP_COUT_ERR__ << ss.str();
1286 xoap::MessageReference returnMessage =
1287 SOAPUtilities::makeSOAPMessageReference(
"Error");
1291 SOAPUtilities::addParameters(returnMessage, parameters);
1292 return returnMessage;
1296 xoap::MessageReference returnMessage =
1297 SOAPUtilities::makeSOAPMessageReference(
"Error");
1299 __SUP_SS__ <<
"Unknown error processing FE communication request." << __E__;
1304 catch(
const std::exception& e)
1306 ss <<
"Exception message: " << e.what();
1311 __SUP_COUT_ERR__ << ss.str();
1315 SOAPUtilities::addParameters(returnMessage, parameters);
1316 return returnMessage;
1322 __SUP_COUT__ <<
"Getting FE list!!!!!!!!!" << __E__;
1334 SupervisorInfoMap::const_iterator it;
1335 std::string oneInterface;
1336 std::string rxFEList;
1337 std::string rxFrontEndError;
1339 size_t lastColonIndex;
1343 for(
auto& appInfo : allFESupervisorInfo_)
1351 __SUP_COUT__ <<
"FESupervisor LID = " << appInfo.second.getId()
1352 <<
" name = " << appInfo.second.getName() << __E__;
1356 xoap::MessageReference retMsg =
1357 SOAPMessenger::sendWithSOAPReply(appInfo.second.getDescriptor(),
1358 "MacroMakerSupervisorRequest",
1360 SOAPUtilities::receive(retMsg, rxParameters);
1362 __SUP_COUT__ <<
"Received MacroMaker response: "
1363 << SOAPUtilities::translate(retMsg).getCommand() <<
"==>"
1364 << SOAPUtilities::translate(retMsg) << __E__;
1366 if(SOAPUtilities::translate(retMsg).getCommand() ==
"Fault")
1368 __SUP_SS__ <<
"Unrecognized command received!" << __E__;
1372 catch(
const xdaq::exception::Exception& e)
1374 __SUP_SS__ <<
"Error transmitting request to FE Supervisor LID = "
1375 << appInfo.second.getId() <<
" name = " << appInfo.second.getName()
1377 << e.what() << __E__;
1381 rxFEList = rxParameters.getValue(
"FEList");
1382 rxFrontEndError = rxParameters.getValue(
"frontEndError");
1384 __SUP_COUT__ <<
"FE List received: \n" << rxFEList << __E__;
1386 if(rxFrontEndError !=
"")
1388 __SUP_SS__ <<
"FE Errors received: \n" << rxFrontEndError << __E__;
1392 std::istringstream allInterfaces(rxFEList);
1393 while(std::getline(allInterfaces, oneInterface))
1395 __SUP_COUTV__(oneInterface);
1396 xmldoc.addTextElementToData(
"FE", oneInterface);
1398 lastColonIndex = oneInterface.rfind(
':');
1399 if(lastColonIndex == std::string::npos)
1401 __SUP_SS__ <<
"Last colon could not be found in " << oneInterface
1405 oneInterface = oneInterface.substr(lastColonIndex);
1407 __SUP_COUTV__(oneInterface);
1417 const std::string& username)
1419 __SUP_COUT__ <<
"MacroMaker writing..." << __E__;
1432 __SUP_COUT__ <<
"Write Address: " << Address <<
" Data: " << Data << __E__;
1433 __SUP_COUTV__(interfaces);
1435 std::string command =
"w:" + Address +
":" + Data;
1436 std::string format = addressFormatStr +
":" + dataFormatStr;
1437 appendCommandToHistory(command, format, time, interfaces, username);
1440 txParameters.
addParameter(
"Request",
"UniversalWrite");
1444 __SUP_COUT__ <<
"Here comes the array from multiselect box for WRITE, behold: \n"
1445 << supervisorIndexArray <<
"\n"
1446 << interfaceIndexArray << __E__;
1450 std::vector<std::string> interfaceIndices;
1451 std::istringstream f(interfaceIndexArray);
1453 while(getline(f, s,
','))
1454 interfaceIndices.push_back(s);
1455 std::vector<int> supervisorIndices;
1456 std::istringstream g(supervisorIndexArray);
1458 while(getline(g, t,
','))
1459 supervisorIndices.push_back(std::stoi(t));
1461 for(
unsigned int i = 0; i < supervisorIndices.size(); i++)
1463 unsigned int FESupervisorIndex = supervisorIndices[i];
1464 std::string interfaceIndex = interfaceIndices[i];
1466 txParameters.
addParameter(
"InterfaceID", interfaceIndex);
1468 __SUP_COUT__ <<
"The index of the supervisor instance is: " << FESupervisorIndex
1470 __SUP_COUT__ <<
"...and the interface ID is: " << interfaceIndex << __E__;
1472 SupervisorInfoMap::iterator it = allFESupervisorInfo_.find(FESupervisorIndex);
1473 if(it == allFESupervisorInfo_.end())
1475 __SUP_SS__ <<
"Error transmitting request to FE Supervisor '"
1476 << interfaceIndex <<
":" << FESupervisorIndex <<
".' \n\n"
1477 <<
"The FE Index doesn't exist. Have you configured the state "
1485 xoap::MessageReference replyMessage = SOAPMessenger::sendWithSOAPReply(
1486 it->second.getDescriptor(),
"MacroMakerSupervisorRequest", txParameters);
1488 __SUP_COUT__ <<
"Response received: "
1489 << SOAPUtilities::translate(replyMessage) << __E__;
1493 SOAPUtilities::receive(replyMessage, rxParameters);
1495 std::string error = rxParameters.getValue(
"Error");
1496 __SUP_COUTV__(error);
1501 __SUP_SS__ <<
"Error transmitting request to FE Supervisor '"
1502 << interfaceIndex <<
":" << FESupervisorIndex <<
".' "
1503 <<
"Have you configured the state machine properly?\n\n"
1508 catch(
const xdaq::exception::Exception& e)
1510 __SUP_SS__ <<
"Error transmitting request to FE Supervisor '"
1511 << interfaceIndex <<
":" << FESupervisorIndex <<
".' "
1512 <<
"Have you configured the state machine properly?\n\n"
1513 << e.what() << __E__;
1523 const std::string& username)
1525 __SUP_COUT__ <<
"@@@@@@@ MacroMaker wants to read data @@@@@@@@" << __E__;
1536 __SUP_COUT__ <<
"Read Address: " << Address << __E__;
1537 __SUP_COUTV__(interfaces);
1546 __SUP_COUT__ <<
"Here comes the array from multiselect box for READ, behold: "
1547 << supervisorIndexArray <<
"," << interfaceIndexArray << __E__;
1551 std::vector<std::string> interfaceIndices;
1552 std::istringstream f(interfaceIndexArray);
1554 while(getline(f, s,
','))
1555 interfaceIndices.push_back(s);
1556 std::vector<int> supervisorIndices;
1557 std::istringstream g(supervisorIndexArray);
1559 while(getline(g, t,
','))
1560 supervisorIndices.push_back(std::stoi(t));
1562 for(
unsigned int i = 0; i < supervisorIndices.size(); i++)
1564 unsigned int FESupervisorIndex = supervisorIndices[i];
1565 std::string interfaceIndex = interfaceIndices[i];
1567 txParameters.
addParameter(
"InterfaceID", interfaceIndex);
1569 __SUP_COUT__ <<
"The index of the supervisor instance is: " << FESupervisorIndex
1571 __SUP_COUT__ <<
"...and the interface ID is: " << interfaceIndex << __E__;
1573 SupervisorInfoMap::iterator it = allFESupervisorInfo_.find(FESupervisorIndex);
1574 if(it == allFESupervisorInfo_.end())
1576 __SUP_SS__ <<
"Error transmitting request to FE Supervisor '"
1577 << interfaceIndex <<
":" << FESupervisorIndex <<
".' \n\n"
1578 <<
"The FE Index doesn't exist. Have you configured the state "
1586 xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply(
1587 it->second.getDescriptor(),
"MacroMakerSupervisorRequest", txParameters);
1589 __SUP_COUT__ <<
"Response received: " << SOAPUtilities::translate(retMsg)
1594 SOAPUtilities::receive(retMsg, rxParameters);
1596 std::string error = rxParameters.getValue(
"Error");
1597 __SUP_COUTV__(error);
1602 __SUP_SS__ <<
"Error transmitting request to FE Supervisor '"
1603 << interfaceIndex <<
":" << FESupervisorIndex <<
".' "
1604 <<
"Have you configured the state machine properly?\n\n"
1609 catch(
const xdaq::exception::Exception& e)
1611 __SUP_SS__ <<
"Error transmitting request to FE Supervisor '"
1612 << interfaceIndex <<
":" << FESupervisorIndex <<
".' "
1613 <<
"Have you configured the state machine properly?\n\n"
1614 << e.what() << __E__;
1618 std::string dataReadResult = rxParameters.getValue(
"dataResult");
1619 __SUP_COUT__ <<
"Data reading result received: " << dataReadResult << __E__;
1620 xmldoc.addTextElementToData(
"readData", dataReadResult);
1621 std::string command =
"r:" + Address +
":" + dataReadResult;
1622 std::string format = addressFormatStr +
":" + dataFormatStr;
1623 appendCommandToHistory(command, format, time, interfaces, username);
1630 const std::string& username)
1632 __SUP_COUT__ <<
"MacroMaker wants to create a macro!!!!!!!!!" << __E__;
1641 __SUP_COUTV__(Name);
1642 __SUP_COUTV__(Sequence);
1643 __SUP_COUTV__(Notes);
1644 __SUP_COUTV__(Time);
1645 __SUP_COUTV__(isMacroPublic);
1646 __SUP_COUTV__(isMacroLSBF);
1648 __SUP_COUTV__(MACROS_DB_PATH);
1650 std::string fileName = Name +
".dat";
1651 std::string fullPath;
1652 if(isMacroPublic ==
"true")
1653 fullPath = (std::string)MACROS_DB_PATH +
"publicMacros/" + fileName;
1655 fullPath = (std::string)MACROS_DB_PATH + username +
"/" + fileName;
1657 __SUP_COUTV__(fullPath);
1659 std::ofstream macrofile(fullPath.c_str());
1660 if(macrofile.is_open())
1663 macrofile <<
"\"name\":\"" << Name <<
"\",\n";
1664 macrofile <<
"\"sequence\":\"" << Sequence <<
"\",\n";
1665 macrofile <<
"\"time\":\"" << Time <<
"\",\n";
1666 macrofile <<
"\"notes\":\"" << Notes <<
"\",\n";
1667 macrofile <<
"\"LSBF\":\"" << isMacroLSBF <<
"\"\n";
1668 macrofile <<
"}@" << __E__;
1673 __SUP_SS__ <<
"Unable to open file" << __E__;
1686 void MacroMakerSupervisor::loadMacro(
const std::string& macroName,
1687 std::string& macroString,
1688 const std::string& username )
1690 __SUP_COUTV__(macroName);
1693 std::string fullPath, line;
1695 for(
unsigned int i = 0; i < 2; ++i)
1698 fullPath = (std::string)MACROS_DB_PATH + username +
"/";
1700 fullPath = (std::string)MACROS_DB_PATH +
"publicMacros/";
1702 fullPath += macroName;
1703 if(macroName.find(
".dat") != macroName.size() - 4)
1705 __SUP_COUTV__(fullPath);
1707 std::ifstream read(fullPath.c_str());
1712 getline(read, line);
1713 macroString += line;
1720 __SUP_COUT__ <<
"Unable to open file: " << fullPath << __E__;
1724 if(macroString !=
"")
1728 if(macroString ==
"")
1730 __SUP_SS__ <<
"Unable to locate file for macro '" << macroName
1731 <<
"'... does it exist?" << __E__;
1733 ss <<
" Attempted username was '" << username <<
".'" << __E__;
1737 __SUP_COUTV__(macroString);
1741 void MacroMakerSupervisor::loadMacroNames(
1742 const std::string& username,
1743 std::pair<std::vector<std::string> ,
1744 std::vector<std::string> >& returnMacroNames)
1748 std::string fullPath = (std::string)MACROS_DB_PATH + username +
"/";
1749 if((dir = opendir(fullPath.c_str())) != NULL)
1752 while((ent = readdir(dir)) != NULL)
1755 if((
unsigned)strlen(ent->d_name) > 4)
1759 ((fullPath + (std::string)ent->d_name)).c_str());
1764 returnMacroNames.second.push_back(ent->d_name);
1767 __SUP_COUT__ <<
"Unable to open file" << __E__;
1774 __SUP_COUT__ <<
"Looping through privateMacros folder failed! Wrong directory"
1777 fullPath = (std::string)MACROS_DB_PATH +
"publicMacros/";
1778 if((dir = opendir(fullPath.c_str())) != NULL)
1781 while((ent = readdir(dir)) != NULL)
1784 if((
unsigned)strlen(ent->d_name) > 4)
1788 ((fullPath + (std::string)ent->d_name)).c_str());
1792 returnMacroNames.first.push_back(ent->d_name);
1796 __SUP_COUT__ <<
"Unable to open file" << __E__;
1803 __SUP_COUT__ << fullPath << __E__;
1804 __SUP_COUT__ <<
"Looping through MacroData folder failed! Wrong directory"
1812 const std::string& username)
1816 std::string returnStr =
"";
1817 std::string fullPath = (std::string)MACROS_DB_PATH + username +
"/";
1818 if((dir = opendir(fullPath.c_str())) != NULL)
1821 while((ent = readdir(dir)) != NULL)
1824 if((
unsigned)strlen(ent->d_name) > 4)
1828 ((fullPath + (std::string)ent->d_name)).c_str());
1831 std::stringstream buffer;
1834 getline(read, line);
1838 returnStr += buffer.str();
1843 __SUP_COUT__ <<
"Unable to open file" << __E__;
1846 std::string returnMacroStr = returnStr.substr(0, returnStr.size() - 1);
1848 __SUP_COUT__ <<
"Loading existing macros! " << returnMacroStr << __E__;
1851 xmldoc.addTextElementToData(
"returnMacroStr", returnMacroStr);
1855 __SUP_COUT__ <<
"Looping through privateMacros folder failed! Wrong directory"
1858 fullPath = (std::string)MACROS_DB_PATH +
"publicMacros/";
1860 if((dir = opendir(fullPath.c_str())) != NULL)
1863 while((ent = readdir(dir)) != NULL)
1866 if((
unsigned)strlen(ent->d_name) > 4)
1870 ((fullPath + (std::string)ent->d_name)).c_str());
1873 std::stringstream buffer;
1876 getline(read, line);
1880 returnStr += buffer.str();
1884 __SUP_COUT__ <<
"Unable to open file" << __E__;
1887 std::string returnPublicStr = returnStr.substr(0, returnStr.size() - 1);
1888 __SUP_COUT__ <<
"Loading existing public macros: " << returnPublicStr << __E__;
1890 xmldoc.addTextElementToData(
"returnPublicStr", returnPublicStr);
1894 __SUP_COUT__ << fullPath << __E__;
1895 __SUP_COUT__ <<
"Looping through MacroData folder failed! Wrong directory"
1901 void MacroMakerSupervisor::appendCommandToHistory(std::string Command,
1904 std::string Interfaces,
1905 const std::string& username)
1907 std::string fileName =
"history.hist";
1908 std::string fullPath = (std::string)MACROS_HIST_PATH + username +
"/" + fileName;
1909 __SUP_COUT__ << fullPath << __E__;
1910 std::ofstream histfile(fullPath.c_str(), std::ios::app);
1911 if(histfile.is_open())
1914 histfile <<
"\"Command\":\"" << Command <<
"\",\n";
1915 histfile <<
"\"Format\":\"" << Format <<
"\",\n";
1916 histfile <<
"\"Time\":\"" << Time <<
"\",\n";
1917 histfile <<
"\"Interfaces\":\"" << Interfaces <<
"\"\n";
1918 histfile <<
"}#" << __E__;
1923 __SUP_SS__ <<
"Unable to open history.hist at " << fullPath << __E__;
1929 void MacroMakerSupervisor::appendCommandToHistory(std::string feClass,
1931 std::string macroType,
1932 std::string macroName,
1933 std::string inputArgs,
1934 std::string outputArgs,
1936 const std::string& username,
1938 time_t completeTime)
1941 launchTime = time(0);
1942 if(completeTime == 0)
1943 completeTime = launchTime;
1946 auto feHistoryIt = lastFeCommandToHistory_.find(username);
1947 if(feHistoryIt != lastFeCommandToHistory_.end() && feHistoryIt->second.size() == 7 &&
1948 feHistoryIt->second[0] == feClass && feHistoryIt->second[1] == feUID &&
1949 feHistoryIt->second[2] == macroType && feHistoryIt->second[3] == macroName &&
1950 feHistoryIt->second[4] == inputArgs && feHistoryIt->second[5] == outputArgs &&
1951 feHistoryIt->second[6] == (saveOutputs ?
"1" :
"0"))
1953 __SUP_COUTT__ <<
"Not saving repeat command to history from user " << username
1958 std::string fileName =
"FEhistory.hist";
1959 std::string fullPath = (std::string)MACROS_HIST_PATH + username +
"/" + fileName;
1960 __SUP_COUT__ << fullPath << __E__;
1961 std::ofstream histfile(fullPath.c_str(), std::ios::app);
1962 if(histfile.is_open())
1965 histfile <<
"\"feClass\":\"" << feClass <<
"\",\n";
1966 histfile <<
"\"feUID\":\"" << feUID <<
"\",\n";
1967 histfile <<
"\"macroType\":\"" << macroType <<
"\",\n";
1968 histfile <<
"\"macroName\":\"" << macroName <<
"\",\n";
1969 histfile <<
"\"inputArgs\":\"" << inputArgs <<
"\",\n";
1970 histfile <<
"\"outputArgs\":\"" << outputArgs <<
"\",\n";
1971 histfile <<
"\"launchTime\":\"" << launchTime <<
"\",\n";
1972 histfile <<
"\"completeTime\":\"" << completeTime <<
"\",\n";
1974 histfile <<
"\"saveOutputs\":\"" << 1 <<
"\"\n";
1976 histfile <<
"\"saveOutputs\":\"" << 0 <<
"\"\n";
1977 histfile <<
"}#" << __E__;
1980 lastFeCommandToHistory_[username].clear();
1981 feHistoryIt = lastFeCommandToHistory_.find(username);
1982 feHistoryIt->second.push_back(feClass);
1983 feHistoryIt->second.push_back(feUID);
1984 feHistoryIt->second.push_back(macroType);
1985 feHistoryIt->second.push_back(macroName);
1986 feHistoryIt->second.push_back(inputArgs);
1987 feHistoryIt->second.push_back(outputArgs);
1988 feHistoryIt->second.push_back((saveOutputs ?
"1" :
"0"));
1992 __SUP_SS__ <<
"Unable to open FEhistory.hist at " << fullPath << __E__;
1999 void MacroMakerSupervisor::loadFEMacroSequences(
HttpXmlDocument& xmldoc,
2000 const std::string& username)
2002 __SUP_COUT__ <<
"loadFEMacroSequences for " << username << __E__;
2005 std::string fullPath = (std::string)MACROS_SEQUENCE_PATH + username +
"/";
2006 std::string sequences =
"";
2007 __SUP_COUTV__(fullPath);
2008 if((dir = opendir(fullPath.c_str())) != NULL)
2011 while((ent = readdir(dir)) != NULL)
2015 ((fullPath + (std::string)ent->d_name)).c_str());
2019 sequences += ent->d_name + std::string(
";");
2022 __SUP_COUT__ <<
"Unable to open file" << __E__;
2028 __SUP_COUT__ <<
"Looping through MacroSequence/" + username +
2029 " folder failed! Invalid directory."
2033 if(username == WebUsers::DEFAULT_ADMIN_USERNAME)
2036 xmldoc.addTextElementToData(
"FEsequences", sequences);
2041 fullPath = (std::string)MACROS_SEQUENCE_PATH + WebUsers::DEFAULT_ADMIN_USERNAME +
"/";
2043 if((dir = opendir(fullPath.c_str())) != NULL)
2046 while((ent = readdir(dir)) != NULL)
2050 ((fullPath + (std::string)ent->d_name)).c_str());
2054 sequences += std::string(
"public/") + ent->d_name + std::string(
";");
2057 __SUP_COUT__ <<
"Unable to open file" << __E__;
2063 __SUP_COUT__ <<
"Looping through MacroSequence/" +
2064 WebUsers::DEFAULT_ADMIN_USERNAME +
2065 " folder failed! Invalid directory."
2070 xmldoc.addTextElementToData(
"FEsequences", sequences);
2074 void MacroMakerSupervisor::saveFEMacroSequence(cgicc::Cgicc& cgi,
2075 const std::string& username)
2080 std::string FEsequence =
2082 bool overwrite = CgiDataUtilities::getDataAsInt(cgi,
"overwrite");
2084 __SUP_COUTV__(overwrite);
2085 __SUP_COUTV__(name);
2086 __SUP_COUTV__(FEsequence);
2089 std::string fixedName =
"";
2090 for(
size_t i = 0; i < name.size(); ++i)
2091 if(!(name[i] ==
' ' || name[i] ==
'-' || name[i] ==
'_' ||
2092 (name[i] >=
'0' && name[i] <=
'9') || (name[i] >=
'A' && name[i] <=
'Z') ||
2093 (name[i] >=
'a' && name[i] <=
'z')))
2096 <<
"Illegal character in Sequence name (position " << i
2097 <<
") - only alphanumeric, spaces, dashes, and underscores allowed!"
2102 fixedName += name[i];
2103 __SUP_COUTV__(fixedName);
2105 std::string fullPath =
2106 (std::string)MACROS_SEQUENCE_PATH + username +
"/" + fixedName +
".dat";
2107 __SUP_COUTV__(fullPath);
2110 if(!overwrite && std::filesystem::exists(fullPath))
2112 __SUP_SS__ <<
"Please choose another Sequence name! A sequence with the same "
2113 "resulting filename already exists at "
2114 << fullPath << __E__;
2118 std::ofstream seqfile(fullPath.c_str());
2119 if(seqfile.is_open())
2121 seqfile << FEsequence << __E__;
2126 __SUP_SS__ <<
"Unable to open file to save FE Macro Sequence at " << fullPath
2133 void MacroMakerSupervisor::getFEMacroSequence(
HttpXmlDocument& xmldoc,
2135 const std::string& username)
2139 __SUP_COUTV__(name);
2141 bool isPublic = (name.find(
"public/") == 0 ? true :
false);
2142 __SUP_COUTV__(isPublic);
2145 std::string fixedName =
"";
2146 for(
size_t i = (isPublic ? std::string(
"public/").size() : 0); i < name.size(); ++i)
2147 if(!(name[i] ==
' ' || name[i] ==
'-' || name[i] ==
'_' ||
2148 (name[i] >=
'0' && name[i] <=
'9') || (name[i] >=
'A' && name[i] <=
'Z') ||
2149 (name[i] >=
'a' && name[i] <=
'z')))
2151 __COUT__ <<
"Illegal character in Sequence name (position " << i
2152 <<
") - only alphanumeric, spaces, dashes, and underscores allowed!"
2156 fixedName += name[i];
2157 __SUP_COUTV__(fixedName);
2160 std::string fullPath =
2161 (std::string)MACROS_SEQUENCE_PATH + username +
"/" + fixedName +
".dat";
2162 __SUP_COUT__ << fullPath << __E__;
2164 std::ifstream read(fullPath.c_str());
2166 unsigned long long fileSize;
2168 if(!isPublic && read.is_open())
2170 read.seekg(0, std::ios::end);
2171 fileSize = read.tellg();
2172 response =
new char[fileSize + 1];
2173 response[fileSize] =
'\0';
2174 read.seekg(0, std::ios::beg);
2177 read.read(response, fileSize);
2180 xmldoc.addTextElementToData(
"FEsequence", &response[0]);
2187 __SUP_COUT__ <<
"Unable to open " << fullPath <<
"! Trying public area..."
2191 std::string publicFullPath = (std::string)MACROS_SEQUENCE_PATH +
2192 WebUsers::DEFAULT_ADMIN_USERNAME +
"/" + fixedName +
2194 __SUP_COUT__ << publicFullPath << __E__;
2196 std::ifstream read(publicFullPath.c_str());
2198 unsigned long long fileSize;
2202 read.seekg(0, std::ios::end);
2203 fileSize = read.tellg();
2204 response =
new char[fileSize + 1];
2205 response[fileSize] =
'\0';
2206 read.seekg(0, std::ios::beg);
2209 read.read(response, fileSize);
2212 xmldoc.addTextElementToData(
"FEsequence", &response[0]);
2218 __SUP_SS__ <<
"Unable to open FE Macro Sequence at " << fullPath <<
" or "
2219 << publicFullPath << __E__;
2226 void MacroMakerSupervisor::deleteFEMacroSequence(cgicc::Cgicc& cgi,
2227 const std::string& username)
2231 __SUP_COUTV__(name);
2233 bool isPublic = (name.find(
"public/") == 0 ? true :
false);
2234 __SUP_COUTV__(isPublic);
2237 std::string fixedName =
"";
2238 for(
size_t i = (isPublic ? std::string(
"public/").size() : 0); i < name.size(); ++i)
2239 if(!(name[i] ==
' ' || name[i] ==
'-' || name[i] ==
'_' ||
2240 (name[i] >=
'0' && name[i] <=
'9') || (name[i] >=
'A' && name[i] <=
'Z') ||
2241 (name[i] >=
'a' && name[i] <=
'z')))
2243 __COUT__ <<
"Illegal character in Sequence name (position " << i
2244 <<
") - only alphanumeric, spaces, dashes, and underscores allowed!"
2248 fixedName += name[i];
2249 __SUP_COUTV__(fixedName);
2252 std::string fullPath =
2253 (std::string)MACROS_SEQUENCE_PATH + username +
"/" + fixedName +
".dat";
2255 fullPath = (std::string)MACROS_SEQUENCE_PATH + WebUsers::DEFAULT_ADMIN_USERNAME +
2256 "/" + fixedName +
".dat";
2257 __SUP_COUT__ << fullPath << __E__;
2260 if(!std::filesystem::exists(fullPath))
2263 <<
"The specified Sequence name does not exist! Looking for sequence file at "
2264 << fullPath << __E__;
2268 std::remove(fullPath.c_str());
2269 __SUP_COUT__ <<
"Successfully deleted " << fullPath << __E__;
2273 void MacroMakerSupervisor::makeSequencePublic(cgicc::Cgicc& cgi,
2274 const std::string& username)
2278 __SUP_COUTV__(name);
2280 bool isPublic = (name.find(
"public/") == 0 ? true :
false);
2281 __SUP_COUTV__(isPublic);
2284 __SUP_SS__ <<
"The specified Sequence name is already designated as public."
2290 std::string fixedName =
"";
2291 for(
size_t i = 0; i < name.size(); ++i)
2292 if(!(name[i] ==
' ' || name[i] ==
'-' || name[i] ==
'_' ||
2293 (name[i] >=
'0' && name[i] <=
'9') || (name[i] >=
'A' && name[i] <=
'Z') ||
2294 (name[i] >=
'a' && name[i] <=
'z')))
2296 __COUT__ <<
"Illegal character in Sequence name (position " << i
2297 <<
") - only alphanumeric, spaces, dashes, and underscores allowed!"
2301 fixedName += name[i];
2302 __SUP_COUTV__(fixedName);
2305 std::string source =
2306 (std::string)MACROS_SEQUENCE_PATH + username +
"/" + fixedName +
".dat";
2307 __SUP_COUT__ << source << __E__;
2308 std::string destination = (std::string)MACROS_SEQUENCE_PATH +
2309 WebUsers::DEFAULT_ADMIN_USERNAME +
"/" + fixedName +
".dat";
2310 __SUP_COUT__ << destination << __E__;
2312 if(std::filesystem::exists(destination))
2314 __SUP_SS__ <<
"The sequence name '" << fixedName
2315 <<
"' already exists in the admin/public location: " << destination
2321 std::filesystem::copy_file(
2322 source, destination, std::filesystem::copy_options::skip_existing);
2323 __SUP_COUT__ <<
"Successfully made " << fixedName
2324 <<
" public at path: " << destination << __E__;
2329 const std::string& username)
2331 std::string fileName = MACROS_HIST_PATH + username +
"/" +
"history.hist";
2333 std::ifstream read(fileName.c_str());
2334 __SUP_COUT__ << fileName << __E__;
2340 unsigned long long fileSz, i = 0, MAX_HISTORY_SIZE = 100000;
2344 read.seekg(0, std::ios::end);
2345 fileSz = read.tellg();
2346 returnStr =
new char[fileSz + 1];
2347 returnStr[fileSz] =
'\0';
2348 read.seekg(0, std::ios::beg);
2351 read.read(returnStr, fileSz);
2355 if(fileSz > MAX_HISTORY_SIZE)
2357 i = fileSz - MAX_HISTORY_SIZE;
2358 for(; i < fileSz; ++i)
2359 if(returnStr[i] ==
'#')
2368 FILE* fp = fopen(fileName.c_str(),
"w");
2372 __SS__ <<
"Big problem with macromaker history file: " << fileName
2376 fwrite(&returnStr[i], fileSz - i, 1, fp);
2380 __SUP_COUT__ <<
"Loading user history! " << __E__;
2383 returnStr[fileSz - 2] =
'\0';
2385 xmldoc.addTextElementToData(
"returnHistStr", &returnStr[i]);
2390 __SUP_COUT__ <<
"Unable to open history.hist" << __E__;
2396 const std::string& username)
2398 std::string fileName = MACROS_HIST_PATH + username +
"/" +
"FEhistory.hist";
2400 std::ifstream read(fileName.c_str());
2401 __SUP_COUT__ << fileName << __E__;
2403 if(!read.is_open() && username != WebUsers::DEFAULT_ADMIN_USERNAME)
2405 __SUP_COUT__ <<
"Unable to open FE history.hist.. Defaulting to admin's FE "
2406 "history as starting point."
2410 MACROS_HIST_PATH + WebUsers::DEFAULT_ADMIN_USERNAME +
"/" +
"FEhistory.hist";
2411 read.open(fileName.c_str());
2418 unsigned long long fileSize;
2419 unsigned long long i = 0;
2420 unsigned long long MAX_HISTORY_SIZE = 100000;
2423 read.seekg(0, std::ios::end);
2424 fileSize = read.tellg();
2425 returnStr =
new char[fileSize + 1];
2426 returnStr[fileSize] =
'\0';
2427 read.seekg(0, std::ios::beg);
2430 read.read(returnStr, fileSize);
2434 if(fileSize > MAX_HISTORY_SIZE)
2436 i = fileSize - MAX_HISTORY_SIZE;
2437 for(; i < fileSize; ++i)
2439 if(returnStr[i] ==
'#')
2449 FILE* fp = fopen(fileName.c_str(),
"w");
2453 __SS__ <<
"Big problem with FE history file: " << fileName << __E__;
2456 fwrite(&returnStr[i], fileSize - i, 1, fp);
2460 __SUP_COUT__ <<
"Loading user history! " << __E__;
2463 returnStr[fileSize - 2] =
'\0';
2465 xmldoc.addTextElementToData(
"returnHistStr", &returnStr[i]);
2470 __SUP_COUT__ <<
"Unable to open FE history.hist" << __E__;
2477 const std::string& username)
2482 std::string fileName = MacroName +
".dat";
2483 std::string fullPath;
2484 if(isMacroPublic ==
"true")
2485 fullPath = (std::string)MACROS_DB_PATH +
"publicMacros/" + fileName;
2487 fullPath = (std::string)MACROS_DB_PATH + username +
"/" + fileName;
2489 __SUP_COUT__ << fullPath << __E__;
2491 std::remove(fullPath.c_str());
2492 __SUP_COUT__ <<
"Successfully deleted " << MacroName;
2493 xmldoc.addTextElementToData(
"deletedMacroName", MacroName);
2499 const std::string& username)
2511 __SUP_COUTV__(oldMacroName);
2512 __SUP_COUTV__(newMacroName);
2513 __SUP_COUTV__(FESequence);
2514 __SUP_COUTV__(Notes);
2515 __SUP_COUTV__(Time);
2516 __SUP_COUTV__(isMacroPublic);
2517 __SUP_COUTV__(isMacroLSBF);
2519 __SUP_COUTV__(MACROS_DB_PATH);
2521 std::string fileName = oldMacroName +
".dat";
2522 std::string fullPath;
2523 if(isMacroPublic ==
"true")
2524 fullPath = (std::string)MACROS_DB_PATH +
"publicMacros/" + fileName;
2526 fullPath = (std::string)MACROS_DB_PATH + username +
"/" + fileName;
2528 __SUP_COUTV__(fullPath);
2530 std::ofstream macrofile(fullPath.c_str());
2531 if(macrofile.is_open())
2534 macrofile <<
"\"name\":\"" << newMacroName <<
"\",\n";
2535 macrofile <<
"\"FEsequence\":\"" << FESequence <<
"\",\n";
2536 macrofile <<
"\"time\":\"" << Time <<
"\",\n";
2537 macrofile <<
"\"notes\":\"" << Notes <<
"\",\n";
2538 macrofile <<
"\"LSBF\":\"" << isMacroLSBF <<
"\"\n";
2539 macrofile <<
"}@" << __E__;
2543 __SUP_COUT__ <<
"Unable to open file" << __E__;
2545 if(oldMacroName != newMacroName)
2549 rename((MACROS_DB_PATH + username +
"/" + oldMacroName +
".dat").c_str(),
2550 (MACROS_DB_PATH + username +
"/" + newMacroName +
".dat").c_str());
2552 xmldoc.addTextElementToData(
"newMacroName", newMacroName);
2554 xmldoc.addTextElementToData(
"newMacroName",
"ERROR");
2559 void MacroMakerSupervisor::clearHistory(
const std::string& username)
2561 std::string fileName =
"history.hist";
2562 std::string fullPath = (std::string)MACROS_HIST_PATH + username +
"/" + fileName;
2564 std::remove(fullPath.c_str());
2565 __SUP_COUT__ <<
"Successfully deleted " << fullPath;
2569 void MacroMakerSupervisor::clearFEHistory(
const std::string& username)
2571 std::string fileName =
"FEhistory.hist";
2572 std::string fullPath = (std::string)MACROS_HIST_PATH + username +
"/" + fileName;
2574 std::remove(fullPath.c_str());
2575 __SUP_COUT__ <<
"Successfully deleted " << fullPath;
2581 const std::string& username)
2586 std::string macroNotes =
2589 __SUP_COUTV__(pluginName);
2590 __SUP_COUTV__(macroName);
2591 __SUP_COUTV__(macroSequence);
2594 for(
unsigned int i = 0; i < macroNotes.length(); ++i)
2595 if(macroNotes[i] ==
'\r' || macroNotes[i] ==
'\n')
2596 macroNotes[i] =
' ';
2597 __SUP_COUTV__(macroNotes);
2599 std::stringstream ss(macroSequence);
2600 std::string command;
2601 std::vector<std::string> commands;
2603 while(getline(ss, command,
','))
2604 commands.push_back(command);
2608 std::map<std::string , std::set<std::string> >
2609 specialsCodeMap = CodeEditor::getSpecialsMap();
2612 auto specialsCodeMapIt = specialsCodeMap.find(CodeEditor::SPECIAL_TYPE_FEInterface);
2613 if(specialsCodeMapIt == specialsCodeMap.end())
2616 <<
"Could not find any FE Interface plugins in source code. Does MacroMaker "
2617 <<
"have access to the source code? Check that the Supervisor context places "
2619 <<
"location with access to the source code." << __E__;
2624 std::string headerFile = pluginName +
".h";
2625 std::string sourceFile = pluginName +
"_interface.cc";
2626 bool foundHeaderFile =
false;
2627 bool foundSourceFile =
false;
2628 for(
const auto& filePath : specialsCodeMapIt->second)
2630 if(!foundHeaderFile && filePath.find(headerFile) != std::string::npos)
2632 foundHeaderFile =
true;
2633 headerFile = filePath;
2634 __SUP_COUT__ <<
"found headerFile=" << filePath << __E__;
2636 if(!foundSourceFile && filePath.find(sourceFile) != std::string::npos)
2638 foundSourceFile =
true;
2639 sourceFile = filePath;
2640 __SUP_COUT__ <<
"found sourceFile=" << filePath << __E__;
2643 if(foundSourceFile && foundHeaderFile)
2647 if(!foundHeaderFile)
2649 __SS__ <<
"Could not find the header file for the FE Interface plugins at '"
2650 << headerFile <<
".' Does MacroMaker "
2651 <<
"have access to the source code? Check that the Supervisor context "
2652 "places MacroMaker in a "
2653 <<
"location with access to the source code." << __E__;
2656 if(!foundSourceFile)
2658 __SS__ <<
"Could not find the source file for the FE Interface plugins at '"
2659 << sourceFile <<
".' Does MacroMaker "
2660 <<
"have access to the source code? Check that the Supervisor context "
2661 "places MacroMaker in a "
2662 <<
"location with access to the source code." << __E__;
2675 char timeBuffer[100];
2678 struct tm* timeinfo;
2681 timeinfo = localtime(&rawtime);
2683 strftime(timeBuffer, 100,
"%b-%d-%Y %I:%M:%S", timeinfo);
2686 std::string contents;
2691 CodeEditor::readFile(CodeEditor::SOURCE_BASE_PATH, sourceFile, contents);
2695 xmldoc.addTextElementToData(
"sourceFile", sourceFile);
2696 xmldoc.addTextElementToData(
"headerFile", headerFile);
2699 if(contents.find(pluginName +
"::" + macroName) != std::string::npos)
2701 __SS__ <<
"The function definition '" << (pluginName +
"::" + macroName)
2702 <<
"(...)' already exists in the source file '" << sourceFile
2703 <<
".' Duplicate functions are not allowed - please rename the macro or "
2704 "modify the source file."
2709 std::stringstream codess;
2710 std::set<std::string> inArgNames, outArgNames;
2722 auto insertPos = contents.find(pluginName +
"::" + pluginName);
2723 if(insertPos == std::string::npos)
2725 __SS__ <<
"Could not find the code insert position in the source file '"
2726 << sourceFile <<
".' The FE plugin class constructor must be '"
2727 << pluginName <<
":" << pluginName <<
"' - is this the case?" << __E__;
2730 __SUP_COUTV__(insertPos);
2732 insertPos = contents.find(
"{", insertPos);
2733 if(insertPos == std::string::npos)
2735 __SS__ <<
"Could not find the code insert position in the source file '"
2737 <<
".' The FE plugin class constructor must begin with '{"
2738 <<
"' - is this the case?" << __E__;
2742 __SUP_COUTV__(insertPos);
2744 insert =
"\n\t//registration of FEMacro '" + macroName +
"' generated, " +
2745 timeBuffer +
", by '" + username +
"' using MacroMaker.\n\t" +
2746 "FEVInterface::registerFEMacroFunction(\"" + macroName +
2747 "\",//feMacroName \n\t\t" +
2748 "static_cast<FEVInterface::frontEndMacroFunction_t>(&" + pluginName +
2749 "::" + macroName +
"), //feMacroFunction \n\t\t" +
2750 "std::vector<std::string>{";
2753 for(
const auto& inArg : inArgNames)
2759 insert +=
"\"" + inArg +
"\"";
2762 insert +=
"}, //namesOfInputArgs \n\t\t";
2763 insert +=
"std::vector<std::string>{";
2766 for(
const auto& outArg : outArgNames)
2772 insert +=
"\"" + outArg +
"\"";
2775 insert +=
"}, //namesOfOutputArgs \n\t\t";
2776 insert +=
"1); //requiredUserPermissions \n\n";
2778 __SUP_COUTV__(insert);
2779 contents = contents.substr(0, insertPos) + insert + contents.substr(insertPos);
2784 auto insertPos = contents.rfind(
"DEFINE_OTS_INTERFACE");
2785 if(insertPos == std::string::npos)
2787 __SS__ <<
"Could not find the code insert position in the source file '"
2789 <<
".' The FE plugin class must end with a 'DEFINE_OTS_INTERFACE("
2790 << pluginName <<
")' - is this the case?" << __E__;
2793 __SUP_COUTV__(insertPos);
2797 "============================================================================"
2798 "============================================\n//" +
2799 macroName +
"\n" +
"//\tFEMacro '" + macroName +
"' generated, " +
2800 timeBuffer +
", by '" + username +
"' using MacroMaker.\n" +
2801 "//\tMacro Notes: " + macroNotes +
"\n" +
"void " + pluginName +
2802 "::" + macroName +
"(__ARGS__)\n{\n\t" +
2803 "__CFG_COUT__ << \"# of input args = \" << argsIn.size() << __E__; \n\t" +
2804 "__CFG_COUT__ << \"# of output args = \" << argsOut.size() << __E__; \n\t" +
2805 "for(auto &argIn:argsIn) \n\t\t" +
2806 "__CFG_COUT__ << argIn.first << \": \" << argIn.second << __E__; \n\n\t" +
2807 "//macro commands section \n" + codess.str() +
"\n\n\t" +
2808 "for(auto &argOut:argsOut) \n\t\t" +
2809 "__CFG_COUT__ << argOut.first << \": \" << argOut.second << __E__; \n\n" +
2810 "} //end " + macroName +
"()\n\n";
2813 CodeEditor::writeFile(CodeEditor::SOURCE_BASE_PATH,
2816 "MacroMaker-" + username,
2823 CodeEditor::readFile(CodeEditor::SOURCE_BASE_PATH, headerFile, contents);
2828 auto insertPos = contents.rfind(
"};");
2829 if(insertPos == std::string::npos)
2831 __SS__ <<
"Could not find the code insert position in the header file '"
2833 <<
".' The FE plugin class must end with a '};' - is this the case?"
2838 __SUP_COUTV__(insertPos);
2840 insert =
"\npublic: // FEMacro '" + macroName +
"' generated, " + timeBuffer +
2841 ", by '" + username +
"' using MacroMaker.\n\t" +
"void " + macroName +
2844 __SUP_COUTV__(insert);
2845 CodeEditor::writeFile(CodeEditor::SOURCE_BASE_PATH,
2848 "MacroMaker-" + username,
2858 const std::string& username)
2862 std::string macroNotes =
2865 __SUP_COUTV__(macroName);
2866 __SUP_COUTV__(macroSequence);
2869 for(
unsigned int i = 0; i < macroNotes.length(); ++i)
2870 if(macroNotes[i] ==
'\r' || macroNotes[i] ==
'\n')
2871 macroNotes[i] =
' ';
2872 __SUP_COUTV__(macroNotes);
2874 std::stringstream ss(macroSequence);
2875 std::string command;
2876 std::vector<std::string> commands;
2878 while(getline(ss, command,
','))
2879 commands.push_back(command);
2881 std::string fileName = macroName +
".cc";
2883 std::string fullPath =
2884 __ENV__(
"SERVICE_DATA_PATH") + MACROS_EXPORT_PATH + username +
"/" + fileName;
2885 __SUP_COUT__ << fullPath << __E__;
2886 std::ofstream exportFile(fullPath.c_str(), std::ios::trunc);
2887 if(exportFile.is_open())
2889 exportFile <<
"//Generated Macro Name:\t" << macroName <<
"\n";
2890 exportFile <<
"//Macro Notes: " << macroNotes <<
"\n";
2894 struct tm* timeinfo;
2898 timeinfo = localtime(&rawtime);
2900 strftime(buffer, 100,
"%b-%d-%Y %I:%M:%S", timeinfo);
2901 exportFile <<
"//Generated Time: \t\t" << buffer <<
"\n";
2904 exportFile <<
"//Paste this whole file into an interface to transfer Macro "
2907 createCode(exportFile, commands);
2911 xmldoc.addTextElementToData(
2913 "$USER_DATA/ServiceData/" + MACROS_EXPORT_PATH + username +
"/" + fileName);
2916 __SUP_COUT__ <<
"Unable to open file" << __E__;
2921 void MacroMakerSupervisor::createCode(std::ostream& out,
2922 const std::vector<std::string>& commands,
2923 const std::string& tabOffset,
2925 std::set<std::string>* inArgNames,
2926 std::set<std::string>* outArgNames)
2929 std::set<std::string > argInHasBeenInitializedSet;
2930 bool addressIsVariable, dataIsVariable;
2932 out << tabOffset <<
"{";
2935 << tabOffset <<
"\t"
2936 <<
"char *address \t= new char[universalAddressSize_]{0}; //create address "
2937 "buffer of interface size and init to all 0";
2939 << tabOffset <<
"\t"
2940 <<
"char *data \t\t= new char[universalDataSize_]{0}; //create data buffer "
2941 "of interface size and init to all 0";
2944 << tabOffset <<
"\t"
2945 <<
"uint64_t macroAddress; //create macro address buffer (size 8 bytes)";
2947 << tabOffset <<
"\t"
2948 <<
"uint64_t macroData; //create macro address buffer (size 8 bytes)";
2951 << tabOffset <<
"\t"
2952 <<
"std::map<std::string /*arg name*/,uint64_t /*arg val*/> macroArgs; //create "
2953 "map from arg name to 64-bit number";
2956 for(
unsigned int i = 0; i < commands.size(); i++)
2958 std::stringstream sst(commands[i]);
2960 std::vector<std::string>
2962 while(getline(sst, tokens,
':'))
2963 oneCommand.push_back(tokens);
2964 while(oneCommand.size() < 4)
2965 oneCommand.push_back(
"");
2993 addressIsVariable = isArgumentVariable(oneCommand[2]);
2994 dataIsVariable = isArgumentVariable(oneCommand[3]);
2996 __SUP_COUTV__(addressIsVariable);
2997 __SUP_COUTV__(dataIsVariable);
2999 out <<
"\n\n" << tabOffset <<
"\t// command-#" << i <<
": ";
3001 if(oneCommand[1][0] ==
'w' || oneCommand[1][0] ==
'r')
3003 if(oneCommand[1][0] ==
'w')
3005 else if(oneCommand[1][0] ==
'r')
3008 if(addressIsVariable)
3009 out << oneCommand[2];
3011 out <<
"0x" << oneCommand[2];
3012 out <<
" /*address*/,";
3016 out << oneCommand[3] <<
" /*data*/";
3017 else if(oneCommand[1][0] ==
'w')
3018 out <<
"0x" << oneCommand[3] <<
" /*data*/";
3019 else if(oneCommand[1][0] ==
'r')
3023 else if(oneCommand[1][0] ==
'd')
3025 out <<
"delay(" << oneCommand[2] <<
");\n";
3026 out << tabOffset <<
"\t"
3027 <<
"__CFG_COUT__ << \"Sleeping for... \" << " << oneCommand[2]
3028 <<
" << \" milliseconds \" << __E__;\n";
3029 out << tabOffset <<
"\t"
3030 <<
"usleep(" << oneCommand[2] <<
"*1000 /* microseconds */);\n";
3035 __SS__ <<
"FATAL ERROR: Unknown command '" << oneCommand[1]
3036 <<
"'... command is not w, r or d" << __E__;
3042 if(addressIsVariable)
3044 if(argInHasBeenInitializedSet.find(oneCommand[2]) ==
3045 argInHasBeenInitializedSet.end())
3047 argInHasBeenInitializedSet.emplace(oneCommand[2]);
3052 out << tabOffset <<
"\t"
3053 <<
"macroArgs[\"" << oneCommand[2]
3055 "theXDAQContextConfigTree_.getNode(theConfigurationPath_)."
3058 << tabOffset <<
"\t\t\"" << oneCommand[2]
3059 <<
"\").getValue<uint64_t>();";
3064 inArgNames->emplace(oneCommand[2]);
3067 out << tabOffset <<
"\t"
3068 <<
"macroArgs[\"" << oneCommand[2] <<
"\"] = __GET_ARG_IN__(\""
3069 << oneCommand[2] <<
"\", uint64_t);";
3072 out <<
"\t//get macro address argument";
3074 << tabOffset <<
"\tmemcpy(address,¯oArgs[\"" << oneCommand[2]
3075 <<
"\"],8); //copy macro address argument to buffer";
3079 out << tabOffset <<
"\t"
3080 <<
"macroAddress = 0x" << oneCommand[2]
3081 <<
"; memcpy(address,¯oAddress,8);"
3082 <<
"\t//copy macro address to buffer";
3087 if(oneCommand[1] ==
"w")
3091 if(argInHasBeenInitializedSet.find(oneCommand[3]) ==
3092 argInHasBeenInitializedSet
3095 argInHasBeenInitializedSet.emplace(oneCommand[3]);
3100 inArgNames->emplace(oneCommand[3]);
3104 << tabOffset <<
"\t"
3105 <<
"macroArgs[\"" << oneCommand[3]
3106 <<
"\"] = __GET_ARG_IN__(\"" << oneCommand[3]
3107 <<
"\", uint64_t); //initialize from input arguments";
3113 << tabOffset <<
"\t"
3114 <<
"macroArgs[\"" << oneCommand[3]
3116 "theXDAQContextConfigTree_.getNode(theConfigurationPath_)."
3119 << tabOffset <<
"\t\t\"" << oneCommand[3]
3120 <<
"\").getValue<uint64_t>(); //initialize from "
3121 "configuration tree";
3124 out <<
"\t//get macro data argument";
3126 << tabOffset <<
"\tmemcpy(data,¯oArgs[\"" << oneCommand[3]
3127 <<
"\"],8); //copy macro data argument to buffer";
3132 << tabOffset <<
"\t"
3133 <<
"macroData = 0x" << oneCommand[3] <<
"; memcpy(data,¯oData,8);"
3134 <<
"\t//copy macro data to buffer";
3137 << tabOffset <<
"\t"
3138 <<
"universalWrite(address,data);";
3143 << tabOffset <<
"\t"
3144 <<
"universalRead(address,data);";
3146 std::string outputArgName;
3149 outputArgName = oneCommand[3];
3153 sprintf(str,
"outArg%d", i);
3154 outputArgName = str;
3156 __SUP_COUTV__(outputArgName);
3158 out << tabOffset <<
"\t"
3159 <<
"memcpy(¯oArgs[\"" << outputArgName
3160 <<
"\"],data,8); //copy buffer to argument map";
3165 << tabOffset <<
"\t"
3166 <<
"__SET_ARG_OUT__(\"" << outputArgName <<
"\",macroArgs[\""
3167 << outputArgName <<
"\"]); //update output argument result";
3170 outArgNames->emplace(outputArgName);
3171 argInHasBeenInitializedSet.emplace(
3176 out <<
"\n\n" << tabOffset <<
"\tdelete[] address; //free the memory";
3177 out <<
"\n" << tabOffset <<
"\tdelete[] data; //free the memory";
3178 out <<
"\n" << tabOffset <<
"}";
3180 __SUP_COUT__ <<
"Done with code generation." << __E__;
3186 bool MacroMakerSupervisor::isArgumentVariable(
const std::string& argumentString)
3188 for(
unsigned int i = 0; i < argumentString.length(); ++i)
3191 if(!((argumentString[i] >=
'0' && argumentString[i] <=
'9') ||
3192 (argumentString[i] >=
'a' && argumentString[i] <=
'f') ||
3193 (argumentString[i] >=
'A' && argumentString[i] <=
'F')))
3208 std::string MacroMakerSupervisor::generateHexArray(
const std::string& sourceHexString,
3211 std::stringstream retSs;
3213 std::string srcHexStr = sourceHexString;
3214 __SUP_COUT__ <<
"Translating: \n";
3215 __SUP_COUT__ << srcHexStr << __E__;
3217 if(srcHexStr.size() % 2)
3218 srcHexStr =
"0" + srcHexStr;
3220 numOfBytes = srcHexStr.size() / 2;
3221 retSs <<
"[" << numOfBytes <<
"] = {";
3223 for(
int i = 0; i < numOfBytes * 2; i += 2)
3226 if(!((srcHexStr[i] >=
'0' && srcHexStr[i] <=
'9') ||
3227 (srcHexStr[i] >=
'a' && srcHexStr[i] <=
'f') ||
3228 (srcHexStr[i] >=
'A' && srcHexStr[i] <=
'F')) ||
3229 !((srcHexStr[i + 1] >=
'0' && srcHexStr[i + 1] <=
'9') ||
3230 (srcHexStr[i + 1] >=
'a' && srcHexStr[i + 1] <=
'f') ||
3231 (srcHexStr[i + 1] >=
'A' && srcHexStr[i + 1] <=
'F')))
3239 retSs <<
"0x" << srcHexStr[srcHexStr.size() - 1 - i - 1]
3240 << srcHexStr[srcHexStr.size() - 1 - i];
3244 __SUP_COUT__ << retSs.str() << __E__;
3252 const WebUsers::RequestUserInfo& userInfo)
3255 __SUP_COUTT__ << __E__;
3257 uint64_t NotDoneID = CgiDataUtilities::getDataAsUint64_t(cgi,
"NotDoneID");
3260 std::lock_guard<std::mutex> lock(feMacroRunThreadStructMutex_);
3262 __SUP_COUT__ <<
"Checking if recent FE macro group has completed for NotDoneID = "
3263 << NotDoneID << __E__;
3265 for(
const auto& g : feMacroRunThreadStruct_)
3266 __SUP_COUTT__ <<
"[] groupID_ = " << g->groupID_ << __E__;
3268 time_t now = time(0);
3269 size_t target_i = -1;
3270 for(
size_t i = 0; i < feMacroRunThreadStruct_.size(); ++i)
3272 auto& group = feMacroRunThreadStruct_[i];
3273 if(group->groupID_ == NotDoneID)
3275 __SUP_COUTT__ <<
"Found group NotDoneID = " << NotDoneID << __E__;
3278 else if(group->allDone())
3281 time_t latestDone = 0;
3282 for(
const auto& t : group->tasks_)
3283 if(t->parameters_.doneTime_ > latestDone)
3284 latestDone = t->parameters_.doneTime_;
3285 if(latestDone >= 0 && now - latestDone > 5 * 60 )
3287 __SUP_COUTT__ <<
"Cleaning up completed group " << group->groupID_
3289 feMacroRunThreadStruct_.erase(feMacroRunThreadStruct_.begin() + i);
3293 else if(now - group->startTime_ > 5 * 60 )
3295 std::string targets;
3296 std::string feMacroName;
3297 for(
const auto& t : group->tasks_)
3299 if(!targets.empty())
3301 targets += t->parameters_.feUIDSelected_;
3302 if(feMacroName.empty())
3303 feMacroName = t->parameters_.macroName_;
3305 __SUP_COUT_WARN__ <<
"Found old FE Macro group that has not completed"
3306 <<
" (groupID=" << group->groupID_ <<
", targets=["
3307 << targets <<
"], FE macro name=" << feMacroName <<
")"
3313 if(target_i >= feMacroRunThreadStruct_.size())
3316 <<
"Attempted to check recent FE Macro run completion with invalid ID="
3318 <<
". Perhaps this FE Macro completed more than 5 minutes ago?" << __E__;
3322 auto& targetGroup = feMacroRunThreadStruct_[target_i];
3323 if(targetGroup->allDone())
3325 __SUP_COUT__ <<
"Found all done for group NotDoneID = " << NotDoneID << __E__;
3326 for(
auto& task : targetGroup->tasks_)
3328 task->bar_->complete();
3331 for(
auto& task : targetGroup->tasks_)
3333 if(task->parameters_.feMacroRunError_ !=
"")
3335 __SUP_SS__ << task->parameters_.feMacroRunError_;
3342 std::ostringstream oss;
3343 for(
auto& task : targetGroup->tasks_)
3344 task->parameters_.xmldoc_.outputXmlDocument(&oss);
3345 __SUP_COUTT__ <<
"xmldoc: " << oss.str() << __E__;
3347 for(
auto& task : targetGroup->tasks_)
3349 __SUP_COUT__ <<
"FE macro group complete." << __E__;
3353 __SUP_COUT__ <<
"Found still going for group NotDoneID = " << NotDoneID
3356 xmldoc.addNumberElementToData(
"NotDoneID", NotDoneID);
3359 for(
auto& task : targetGroup->tasks_)
3361 DOMElement* progParent = xmldoc.addTextElementToData(
3362 "feMacroProgress", task->parameters_.feUIDSelected_);
3363 if(task->feMacroRunDone_)
3372 "progress", std::to_string(task->bar_->read()), progParent);
3382 std::string feUIDSelected =
3385 std::string macroName =
3389 bool saveOutputs = CgiDataUtilities::getDataAsInt(cgi,
"saveOutputs") == 1;
3391 __SUP_COUTTV__(feClassSelected);
3392 __SUP_COUTTV__(feUIDSelected);
3393 __SUP_COUTTV__(macroType);
3394 __SUP_COUTTV__(macroName);
3395 __SUP_COUTTV__(inputArgs);
3396 __SUP_COUTTV__(outputArgs);
3397 __SUP_COUTTV__(saveOutputs);
3398 __SUP_COUTTV__(userInfo.username_);
3402 std::set<std::string> feUIDs;
3404 std::string expandUID = feUIDSelected.empty() ?
"*" : feUIDSelected;
3405 if(expandUID !=
"*")
3412 for(
auto& feTypePair : FEPluginTypetoFEsMap_)
3414 if(feClassSelected.empty() || feClassSelected ==
"*" ||
3415 feClassSelected == feTypePair.first)
3416 for(
auto& uid : feTypePair.second)
3417 feUIDs.emplace(uid);
3421 feUIDs.emplace(feUIDSelected);
3426 auto group = std::make_shared<runFEMacroGroupStruct>();
3427 group->historyFeClassSelected_ = feClassSelected.empty() ?
"*" : feClassSelected;
3428 group->historyFeUIDSelected_ = feUIDSelected.empty() ?
"*" : feUIDSelected;
3429 group->historyMacroType_ = macroType;
3430 group->historyMacroName_ = macroName;
3431 group->historyInputArgs_ = inputArgs;
3432 group->historyOutputArgs_ = outputArgs;
3433 group->historySaveOutputs_ = saveOutputs;
3434 group->historyUsername_ = userInfo.username_;
3435 for(
const std::string& uid : feUIDs)
3437 group->tasks_.push_back(std::make_shared<runFEMacroStruct>(
3450 std::lock_guard<std::mutex> lock(feMacroRunThreadStructMutex_);
3451 group->groupID_ = ++feMacroRunGroupIDCounter_;
3452 if(feMacroRunGroupIDCounter_ == 0)
3454 ++feMacroRunGroupIDCounter_;
3456 for(
auto& task : group->tasks_)
3458 task->bar_ = std::make_unique<ProgressBar>();
3459 task->bar_->reset(macroName, task->parameters_.feUIDSelected_);
3461 feMacroRunThreadStruct_.emplace_back(group);
3464 std::thread([group,
this]() {
3465 MacroMakerSupervisor::runFEMacroGroupSchedulerThread(group,
this);
3468 size_t sleepTime = 10 * 1000;
3471 for(
int i = 0; i < 6; ++i)
3473 if(group->allDone())
3475 __SUP_COUTT__ <<
"All FE macro tasks marked done" << __E__;
3476 for(
const auto& task : group->tasks_)
3477 if(task->parameters_.doneTime_ > group->completeTime_)
3478 group->completeTime_ = task->parameters_.doneTime_;
3483 __SUP_COUTT__ <<
"FE macros not all done, sleeping..." << __E__;
3485 if(sleepTime > 1000 * 1000 )
3486 sleepTime = 1000 * 1000;
3491 if(!group->allDone())
3493 xmldoc.addNumberElementToData(
"NotDoneID", group->groupID_);
3497 std::lock_guard<std::mutex> lock(feMacroRunThreadStructMutex_);
3498 for(
auto& task : group->tasks_)
3500 DOMElement* progParent = xmldoc.addTextElementToData(
3501 "feMacroProgress", task->parameters_.feUIDSelected_);
3502 if(task->feMacroRunDone_)
3511 "progress", std::to_string(task->bar_->read()), progParent);
3519 for(
auto& task : group->tasks_)
3521 if(task->parameters_.feMacroRunError_ !=
"")
3523 __SUP_SS__ << task->parameters_.feMacroRunError_;
3530 std::ostringstream oss;
3531 for(
auto& task : group->tasks_)
3532 task->parameters_.xmldoc_.outputXmlDocument(
3533 &oss,
false ,
true );
3534 __SUP_COUTT__ <<
"xmldoc: " << oss.str() << __E__;
3536 for(
auto& task : group->tasks_)
3540 std::lock_guard<std::mutex> lock(feMacroRunThreadStructMutex_);
3541 for(
size_t i = 0; i < feMacroRunThreadStruct_.size(); ++i)
3543 if(feMacroRunThreadStruct_[i].get() == group.get())
3545 feMacroRunThreadStruct_.erase(feMacroRunThreadStruct_.begin() + i);
3550 __SUP_COUT__ <<
"All FE macros complete." << __E__;
3553 std::lock_guard<std::mutex> lock(feMacroRunThreadStructMutex_);
3554 for(
const auto& g : feMacroRunThreadStruct_)
3555 __SUP_COUTT__ <<
"[] groupID_ = " << g->groupID_ << __E__;
3559 catch(
const std::runtime_error& e)
3561 __SUP_SS__ <<
"Error processing FE communication request: " << e.what() << __E__;
3562 __SUP_COUT_ERR__ << ss.str();
3563 xmldoc.addTextElementToData(
"Error", ss.str());
3567 __SUP_SS__ <<
"Unknown error processing FE communication request." << __E__;
3572 catch(
const std::exception& e)
3574 ss <<
"Exception message: " << e.what();
3579 __SUP_COUT_ERR__ << ss.str();
3581 xmldoc.addTextElementToData(
"Error", ss.str());
3586 void MacroMakerSupervisor::runFEMacroGroupSchedulerThread(
3590 if(!group || !mmSupervisor || group->tasks_.empty())
3593 __COUT__ <<
"FE macro group scheduler started. groupID=" << group->groupID_
3594 <<
" tasks=" << group->tasks_.size() << __E__;
3596 std::size_t maxThreads = std::thread::hardware_concurrency();
3599 if(maxThreads > group->tasks_.size())
3600 maxThreads = group->tasks_.size();
3602 std::vector<std::pair<std::shared_ptr<runFEMacroStruct>, std::future<void>>> active;
3603 active.reserve(maxThreads);
3604 std::size_t nextTaskIndex = 0;
3606 auto launchTask = [&](std::shared_ptr<runFEMacroStruct> task) {
3607 active.emplace_back(task, std::async(std::launch::async, [task, mmSupervisor]() {
3608 MacroMakerSupervisor::runFEMacroThread(task,
3613 while(nextTaskIndex < group->tasks_.size() || !active.empty())
3615 while(nextTaskIndex < group->tasks_.size() && active.size() < maxThreads)
3616 launchTask(group->tasks_[nextTaskIndex++]);
3619 std::lock_guard<std::mutex> lock(mmSupervisor->feMacroRunThreadStructMutex_);
3620 for(
const auto& activeTask : active)
3621 if(activeTask.first && !activeTask.first->feMacroRunDone_ &&
3622 activeTask.first->bar_)
3623 activeTask.first->bar_->step();
3626 bool anyFinished =
false;
3627 for(
size_t i = 0; i < active.size();)
3629 if(active[i].second.wait_for(std::chrono::milliseconds(0)) ==
3630 std::future_status::ready)
3632 __COUTT__ <<
"FE macro group scheduler task complete. groupID="
3634 <<
" uid=" << active[i].first->parameters_.feUIDSelected_
3636 active[i].second.get();
3637 active.erase(active.begin() + i);
3648 for(
const auto& task : group->tasks_)
3649 if(task->parameters_.doneTime_ > group->completeTime_)
3650 group->completeTime_ = task->parameters_.doneTime_;
3652 if(!group->historySaved_)
3654 mmSupervisor->appendCommandToHistory(group->historyFeClassSelected_,
3655 group->historyFeUIDSelected_,
3656 group->historyMacroType_,
3657 group->historyMacroName_,
3658 group->historyInputArgs_,
3659 group->historyOutputArgs_,
3660 group->historySaveOutputs_,
3661 group->historyUsername_,
3663 group->completeTime_);
3664 group->historySaved_ =
true;
3667 __COUT__ <<
"FE macro group scheduler ended. groupID=" << group->groupID_ << __E__;
3669 catch(
const std::exception& e)
3671 __SS__ <<
"Error during FE macro group scheduler thread: " << e.what() << __E__;
3672 __COUT_ERR__ << ss.str();
3676 __COUT_ERR__ <<
"Unknown error during FE macro group scheduler thread." << __E__;
3681 void MacroMakerSupervisor::runFEMacroThread(
3682 std::shared_ptr<runFEMacroStruct> feMacroRunThreadStruct,
3686 feMacroRunThreadStruct->parameters_.threadID_ =
3687 std::hash<std::thread::id>{}(std::this_thread::get_id());
3689 __COUT__ <<
"runFEMacro thread started... threadid = " << std::this_thread::get_id()
3690 <<
" " << mmSupervisor <<
" getpid()=" << getpid()
3691 <<
" gettid()=" << gettid() << __E__;
3693 mmSupervisor->runFEMacro(feMacroRunThreadStruct->parameters_.xmldoc_,
3694 feMacroRunThreadStruct->parameters_.feClassSelected_,
3695 feMacroRunThreadStruct->parameters_.feUIDSelected_,
3696 feMacroRunThreadStruct->parameters_.macroType_,
3697 feMacroRunThreadStruct->parameters_.macroName_,
3698 feMacroRunThreadStruct->parameters_.inputArgs_,
3699 feMacroRunThreadStruct->parameters_.outputArgs_,
3700 feMacroRunThreadStruct->parameters_.saveOutputs_,
3701 feMacroRunThreadStruct->parameters_.runningUsername_,
3702 feMacroRunThreadStruct->parameters_.userGroupPermissions_,
3705 feMacroRunThreadStruct->parameters_.doneTime_ = time(0);
3706 feMacroRunThreadStruct->feMacroRunDone_ =
true;
3707 __COUT__ <<
"runFEMacro thread done. threadid = " << std::this_thread::get_id()
3711 catch(
const std::runtime_error& e)
3713 __SS__ <<
"Error during runFEMacro thread: " << e.what() << __E__;
3714 __COUT_ERR__ << ss.str();
3715 feMacroRunThreadStruct->parameters_.feMacroRunError_ = ss.str();
3716 feMacroRunThreadStruct->parameters_.doneTime_ = time(0);
3717 feMacroRunThreadStruct->feMacroRunDone_ =
true;
3721 __SS__ <<
"Unknown error during runFEMacro thread." << __E__;
3726 catch(
const std::exception& e)
3728 ss <<
"Exception message: " << e.what();
3733 __COUT_ERR__ << ss.str();
3734 feMacroRunThreadStruct->parameters_.feMacroRunError_ = ss.str();
3735 feMacroRunThreadStruct->parameters_.doneTime_ = time(0);
3736 feMacroRunThreadStruct->feMacroRunDone_ =
true;
3741 std::string feClassSelected,
3742 std::string feUIDSelected,
3743 const std::string& macroType,
3744 const std::string& macroName,
3745 const std::string& inputArgs,
3746 const std::string outputArgs,
3748 const std::string& username,
3749 const std::string& userGroupPermissions,
3752 __SUP_COUTV__(feClassSelected);
3753 __SUP_COUTV__(feUIDSelected);
3754 __SUP_COUTV__(macroType);
3755 __SUP_COUTV__(macroName);
3756 __SUP_COUTV__(inputArgs);
3757 __SUP_COUTV__(outputArgs);
3758 __SUP_COUTV__(saveOutputs);
3759 __SUP_COUTV__(username);
3760 __SUP_COUTV__(userGroupPermissions);
3762 time_t launchTime = time(0);
3763 auto saveHistoryIfRequested = [&]() {
3767 appendCommandToHistory(feClassSelected,
3777 saveToHistory =
false;
3780 std::set<std::string > feUIDs;
3782 if(feUIDSelected ==
"")
3783 feUIDSelected =
"*";
3784 if(feClassSelected ==
"")
3785 feClassSelected =
"*";
3787 if(feClassSelected ==
"" || feUIDSelected ==
"" || macroType ==
"" || macroName ==
"")
3789 __SUP_SS__ <<
"Illegal empty front-end parameter." << __E__;
3792 else if(feUIDSelected !=
"*")
3799 if(feClassSelected ==
"*")
3801 for(
auto& feTypePair : FEPluginTypetoFEsMap_)
3802 for(
auto& feUID : feTypePair.second)
3803 feUIDs.emplace(feUID);
3807 auto typeIt = FEPluginTypetoFEsMap_.find(feClassSelected);
3808 if(typeIt == FEPluginTypetoFEsMap_.end())
3810 __SUP_SS__ <<
"Illegal front-end type parameter '" << feClassSelected
3811 <<
"' not in list of types." << __E__;
3815 for(
auto& feUID : typeIt->second)
3816 feUIDs.emplace(feUID);
3822 std::string macroString;
3823 if(macroType ==
"public")
3824 loadMacro(macroName, macroString);
3825 else if(macroType ==
"private")
3826 loadMacro(macroName, macroString, username);
3828 __SUP_COUTV__(macroString);
3835 std::string filename =
"/macroOutput_" + std::to_string(time(0)) +
"_" +
3836 std::to_string(clock()) +
".txt";
3838 __SUP_COUTV__(filename);
3839 fp = fopen((CodeEditor::OTSDAQ_DATA_PATH + filename).c_str(),
"w");
3842 __SUP_SS__ <<
"Failed to open file to save macro output '"
3843 << CodeEditor::OTSDAQ_DATA_PATH << filename <<
"'..." << __E__;
3847 fprintf(fp,
"############################\n");
3849 "### Running '%s' at time %s\n",
3853 "### \t Target front-ends (count=%lu): %s\n",
3856 fprintf(fp,
"### \t\t Inputs: %s\n", inputArgs.c_str());
3857 fprintf(fp,
"############################\n\n\n");
3859 xmldoc.addTextElementToData(
"feMacroRunArgs_name",
"Filename");
3860 xmldoc.addTextElementToData(
"feMacroRunArgs_value",
3861 "$OTSDAQ_DATA/" + filename);
3865 for(
auto& feUID : feUIDs)
3867 auto feIt = FEtoSupervisorMap_.find(feUID);
3868 if(feIt == FEtoSupervisorMap_.end())
3870 __SUP_SS__ <<
"Destination front end interface ID '" << feUID
3871 <<
"' was not found in the list of front ends." << __E__;
3872 ss <<
"\n\nHere is the map:\n\n"
3877 unsigned int FESupervisorIndex = feIt->second;
3878 __SUP_COUT__ <<
"Found supervisor index: " << FESupervisorIndex << __E__;
3880 SupervisorInfoMap::iterator it = allFESupervisorInfo_.find(FESupervisorIndex);
3881 if(it == allFESupervisorInfo_.end())
3884 <<
"Error transmitting request to FE Supervisor '" << feUID <<
":"
3885 << FESupervisorIndex <<
".' \n\n"
3886 <<
"The FE Supervisor Index does not exist. Have you configured "
3887 "the state machine properly?"
3894 if(macroType ==
"fe")
3895 txParameters.
addParameter(
"Request",
"RunInterfaceMacro");
3897 txParameters.
addParameter(
"Request",
"RunMacroMakerMacro");
3899 if(macroType ==
"fe")
3908 txParameters.
addParameter(
"userPermissions", userGroupPermissions);
3918 "Running '%s' at time %s\n",
3922 "\t Target front-end: '%s::%s'\n",
3923 FEtoPluginTypeMap_[feUID].c_str(),
3926 "\t\t Inputs: %s\n",
3931 xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply(
3932 it->second.getDescriptor(),
3933 "MacroMakerSupervisorRequest",
3936 __SUP_COUT__ <<
"Received response message: "
3937 << SOAPUtilities::translate(retMsg) << __E__;
3939 SOAPUtilities::receive(retMsg, rxParameters);
3941 __SUP_COUT__ <<
"Received it " << __E__;
3944 std::string outputResults = rxParameters.getValue(
"outputArgs");
3945 std::string error = rxParameters.getValue(
"Error");
3948 __SUP_COUT__ <<
"outputArgs = " << outputResults << __E__;
3952 __SS__ <<
"Attempted FE Macro Failed. Attempted target "
3953 <<
"was UID=" << feUID
3954 <<
" at feSupervisorID=" << FESupervisorIndex <<
"." << __E__;
3955 ss <<
"\n\n The error was:\n\n" << error << __E__;
3956 __SUP_COUT_ERR__ <<
"\n" << ss.str();
3957 xmldoc.addTextElementToData(
"Error", ss.str());
3958 saveHistoryIfRequested();
3965 DOMElement* feMacroExecParent =
3966 xmldoc.addTextElementToData(
"feMacroExec", macroName);
3972 "fe_type", FEtoPluginTypeMap_[feUID], feMacroExecParent);
3974 "fe_context", it->second.getContextName(), feMacroExecParent);
3976 "fe_supervisor", it->second.getName(), feMacroExecParent);
3978 "fe_hostname", it->second.getHostname(), feMacroExecParent);
3980 std::istringstream inputStream(outputResults);
3981 std::string splitVal, argName, argValue;
3982 while(getline(inputStream, splitVal,
';'))
3984 std::istringstream pairInputStream(splitVal);
3985 getline(pairInputStream, argName,
',');
3986 getline(pairInputStream, argValue,
',');
3991 "\t\t Output '%s' = %s\n",
3998 "outputArgs_name", argName, feMacroExecParent);
4000 "outputArgs_value", argValue, feMacroExecParent);
4002 __SUP_COUT__ << argName <<
": " << argValue << __E__;
4006 __SUP_COUTT__ <<
"runFEMacro() chk3." << __E__;
4013 saveHistoryIfRequested();
4020 saveHistoryIfRequested();
4022 __SUP_COUT__ <<
"runFEMacro() done." << __E__;
4029 const std::string& username)
4031 __SUP_COUT__ <<
"Getting FE Macro list" << __E__;
4034 txParameters.
addParameter(
"Request",
"GetInterfaceMacros");
4039 std::string oneInterface;
4040 std::string rxFEMacros;
4044 for(
auto& appInfo : allFESupervisorInfo_)
4046 __SUP_COUT__ <<
"FESupervisor LID = " << appInfo.second.getId()
4047 <<
" name = " << appInfo.second.getName() << __E__;
4049 xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply(
4050 appInfo.second.getDescriptor(),
"MacroMakerSupervisorRequest", txParameters);
4051 SOAPUtilities::receive(retMsg, rxParameters);
4053 rxFEMacros = rxParameters.getValue(
"FEMacros");
4055 __SUP_COUT__ <<
"FE Macros received: \n" << rxFEMacros << __E__;
4057 std::istringstream allInterfaces(rxFEMacros);
4058 while(std::getline(allInterfaces, oneInterface))
4062 xmldoc.addTextElementToData(
"FEMacros", oneInterface);
4068 std::pair<std::vector<std::string> ,
4069 std::vector<std::string> >
4071 loadMacroNames(username, macroNames);
4073 __SUP_COUT__ <<
"Public macro count: " << macroNames.first.size() << __E__;
4074 __SUP_COUT__ <<
"Private macro count: " << macroNames.second.size() << __E__;
4076 std::string macroString;
4085 for(
int i = 0; i < 2; ++i)
4086 for(
auto& macroName : (i ? macroNames.second : macroNames.first))
4089 loadMacro(macroName, macroString, username);
4094 std::stringstream xmlMacroStream;
4095 xmlMacroStream << macro.macroName_;
4096 xmlMacroStream <<
":"
4098 xmlMacroStream <<
":" << macro.namesOfInputArguments_.size();
4099 for(
auto& inputArg : macro.namesOfInputArguments_)
4100 xmlMacroStream <<
":" << inputArg;
4101 xmlMacroStream <<
":" << macro.namesOfOutputArguments_.size();
4102 for(
auto& inputArg : macro.namesOfOutputArguments_)
4103 xmlMacroStream <<
":" << inputArg;
4105 xmldoc.addTextElementToData(i ?
"PrivateMacro" :
"PublicMacro",
4106 xmlMacroStream.str());
static std::string postData(cgicc::Cgicc &cgi, const std::string &needle)
static std::string getOrPostData(cgicc::Cgicc &cgi, const std::string &needle)
static std::string getData(cgicc::Cgicc &cgi, const std::string &needle)
ConfigurationTree getNode(const std::string &nodeString, bool doNotThrowOnBrokenUIDLinks=false) const
void loadTableGroup(const std::string &tableGroupName, const TableGroupKey &tableGroupKey, bool doActivate=false, std::map< std::string, TableVersion > *groupMembers=0, ProgressBar *progressBar=0, std::string *accumulateWarnings=0, std::string *groupComment=0, std::string *groupAuthor=0, std::string *groupCreateTime=0, bool doNotLoadMember=false, std::string *groupTypeString=0, std::map< std::string, std::string > *groupAliases=0, ConfigurationManager::LoadGroupType groupTypeToLoad=ConfigurationManager::LoadGroupType::ALL_TYPES, bool ignoreVersionTracking=false, std::map< std::string, TableVersion > mergeInTables={}, std::map< std::string, TableVersion > overrideTables={})
ConfigurationTree getNode(const std::string &nodeName, bool doNotThrowOnBrokenUIDLinks=false) const
std::vector< std::pair< std::string, ConfigurationTree > > getChildren(std::map< std::string, std::string > filterMap=std::map< std::string, std::string >(), bool byPriority=false, bool onlyStatusTrue=false) const
void getRequestUserInfo(WebUsers::RequestUserInfo &requestUserInfo)
friend friend class MacroMakerSupervisor
virtual void nonXmlRequest(const std::string &requestType, cgicc::Cgicc &cgiIn, std::ostream &out, const WebUsers::RequestUserInfo &userInfo)
void copyDataChildren(HttpXmlDocument &document)
std::string getMatchingValue(const std::string &field, const unsigned int occurance=0)
void outputXmlDocument(std::ostringstream *out, bool dispStdOut=false, bool allowWhiteSpace=false, bool printErrors=false)
virtual void forceSupervisorPropertyValues(void) override
override to force supervisor property values (and ignore user settings)
void addParameter(const std::string name, const std::string value)
static void tooltipSetNeverShowForUsername(const std::string &username, HttpXmlDocument *xmldoc, const std::string &srcFile, const std::string &srcFunc, const std::string &srcId, bool doNeverShow, bool temporarySilence)
static void tooltipCheckForUsername(const std::string &username, HttpXmlDocument *xmldoc, const std::string &srcFile, const std::string &srcFunc, const std::string &srcId)
xercesc::DOMElement * addTextElementToParent(const std::string &childName, const std::string &childText, xercesc::DOMElement *parent)
void INIT_MF(const char *name)
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 void getSetFromString(const std::string &inputString, std::set< std::string > &setToReturn, const std::set< char > &delimiter={',', '|', '&'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'})
static std::string setToString(const std::set< T > &setToReturn, const std::string &delimeter=", ")
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 decodeURIComponent(const std::string &data)