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"
6 #include "otsdaq/Macros/StringMacros.h"
8 #include "otsdaq/NetworkUtilities/TransceiverSocket.h"
20 #include "otsdaq/TableCore/TableGroupKey.h"
22 #define MACROS_DB_PATH std::string(__ENV__("SERVICE_DATA_PATH")) + "/MacroData/"
23 #define MACROS_HIST_PATH std::string(__ENV__("SERVICE_DATA_PATH")) + "/MacroHistory/"
24 #define MACROS_SEQUENCE_PATH std::string(__ENV__("SERVICE_DATA_PATH")) + "/MacroSequence/"
25 #define MACROS_EXPORT_PATH std::string("/MacroExport/")
26 #define USER_FEMACROTEST_PREF_PATH \
27 std::string(__ENV__("SERVICE_DATA_PATH")) + "/FEMacroTestPreferences/"
28 #define FEMACROTEST_PREF_FILETYPE "pref"
30 #define SEQUENCE_FILE_NAME \
31 std::string(__ENV__("SERVICE_DATA_PATH")) + "/OtsWizardData/sequence.dat"
32 #define SEQUENCE_OUT_FILE_NAME \
33 std::string(__ENV__("SERVICE_DATA_PATH")) + "/OtsWizardData/sequence.out"
38 #define __MF_SUBJECT__ "MacroMaker"
46 __SUP_COUT__ <<
"Constructing..." << __E__;
51 mkdir(((std::string)MACROS_DB_PATH).c_str(), 0755);
52 mkdir(((std::string)MACROS_HIST_PATH).c_str(), 0755);
53 mkdir(((std::string)MACROS_SEQUENCE_PATH).c_str(), 0755);
54 mkdir((__ENV__(
"SERVICE_DATA_PATH") + MACROS_EXPORT_PATH).c_str(), 0755);
55 mkdir(((std::string)USER_FEMACROTEST_PREF_PATH).c_str(), 0755);
58 &MacroMakerSupervisor::frontEndCommunicationRequest,
63 if(CorePropertySupervisorBase::allSupervisorInfo_.isMacroMakerMode())
65 __SUP_COUT__ <<
"Starting constructor for Macro Maker mode." << __E__;
67 xgi::bind(
this, &MacroMakerSupervisor::requestIcons,
"requestIcons");
68 xgi::bind(
this, &MacroMakerSupervisor::verification,
"Verify");
69 xgi::bind(
this, &MacroMakerSupervisor::tooltipRequest,
"TooltipRequest");
70 xgi::bind(
this, &MacroMakerSupervisor::requestWrapper,
"Request");
72 &MacroMakerSupervisor::supervisorSequenceCheck,
73 "SupervisorSequenceCheck",
76 __SUP_COUT__ <<
"Completed constructor for Macro Maker mode." << __E__;
79 __SUP_COUT__ <<
"Not Macro Maker only mode." << __E__;
85 if(CorePropertySupervisorBase::allSupervisorInfo_.isMacroMakerMode())
91 ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME);
96 FEPluginTypetoFEsMap_.clear();
97 FEtoSupervisorMap_.clear();
98 FEtoPluginTypeMap_.clear();
101 __SUP_COUT__ <<
"FEs for app MacroMakerFESupervisor"
107 .
getNode(
"MacroMakerFESupervisor")
108 .
getNode(
"LinkToSupervisorTable")
109 .
getNode(
"LinkToFEInterfaceTable")
112 for(
auto& fe : feChildren)
114 if(!fe.second.status())
117 __SUP_COUTV__(fe.first);
118 FEtoSupervisorMap_[fe.first] =
119 atoi(__ENV__(
"FE_SUPERVISOR_ID"));
121 std::string pluginType =
122 fe.second.getNode(
"FEInterfacePluginName").getValue();
123 FEPluginTypetoFEsMap_[pluginType].emplace(fe.first);
124 FEtoPluginTypeMap_[fe.first] = pluginType;
128 __SUP_COUTV__(StringMacros::mapToString(FEtoSupervisorMap_));
129 __SUP_COUTV__(StringMacros::mapToString(FEPluginTypetoFEsMap_));
130 __SUP_COUTV__(StringMacros::mapToString(FEtoPluginTypeMap_));
135 bool enableRemoteControl =
false;
138 __ENV__(
"OTS_MACROMAKER_UDP_PORT");
139 __ENV__(
"OTS_MACROMAKER_UDP_IP");
140 enableRemoteControl =
true;
142 catch(
const std::runtime_error& e)
144 __SUP_COUT__ <<
"Ignoring MacroMaker server env var error: " << e.what()
149 __SUP_COUT__ <<
"Ignoring unknown error reading OTS_MACROMAKER_UDP_PORT/"
150 "OTS_MACROMAKER_UDP_IP env vars."
154 if(enableRemoteControl)
156 __SUP_COUT_INFO__ <<
"Enabling remote control over UDP..." << __E__;
160 MacroMakerSupervisor::RemoteControlWorkLoop(s);
166 __SUP_COUT_INFO__ <<
"Remote control over UDP is disabled." << __E__;
169 __SUP_COUT__ <<
"Constructed." << __E__;
173 MacroMakerSupervisor::~MacroMakerSupervisor(
void) { destroy(); }
176 void MacroMakerSupervisor::init(
void)
181 allFESupervisorInfo_ =
182 SupervisorInfoMap(allSupervisorInfo_.getAllFETypeSupervisorInfo());
187 void MacroMakerSupervisor::destroy(
void)
199 void MacroMakerSupervisor::tooltipRequest(xgi::Input* in, xgi::Output* out)
201 cgicc::Cgicc cgi(in);
209 if(securityCode_.compare(submittedSequence) != 0)
211 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match!"
223 if(Command ==
"check")
231 else if(Command ==
"setNeverShow")
234 WebUsers::DEFAULT_ADMIN_USERNAME,
243 __COUT__ <<
"Command Request, " << Command <<
", not recognized." << __E__;
249 void MacroMakerSupervisor::verification(xgi::Input* in, xgi::Output* out)
251 cgicc::Cgicc cgi(in);
253 __COUT__ <<
"submittedSequence=" << submittedSequence <<
" " << time(0) << __E__;
255 std::string securityWarning =
"";
257 if(securityCode_.compare(submittedSequence) != 0)
259 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match!"
261 *out <<
"Invalid code.";
267 __COUT__ <<
"*** Successfully authenticated security sequence "
268 <<
"@ " << time(0) << __E__;
273 securityWarning =
"&secure=False";
277 *out <<
"<!DOCTYPE HTML><html lang='en'><head><title>ots MacroMaker mode</title>" <<
280 "<link rel='apple-touch-icon' sizes='57x57' href='/WebPath/images/otsdaqIcons/apple-icon-57x57.png'>\
281 <link rel='apple-touch-icon' sizes='60x60' href='/WebPath/images/otsdaqIcons/apple-icon-60x60.png'>\
282 <link rel='apple-touch-icon' sizes='72x72' href='/WebPath/images/otsdaqIcons/apple-icon-72x72.png'>\
283 <link rel='apple-touch-icon' sizes='76x76' href='/WebPath/images/otsdaqIcons/apple-icon-76x76.png'>\
284 <link rel='apple-touch-icon' sizes='114x114' href='/WebPath/images/otsdaqIcons/apple-icon-114x114.png'>\
285 <link rel='apple-touch-icon' sizes='120x120' href='/WebPath/images/otsdaqIcons/apple-icon-120x120.png'>\
286 <link rel='apple-touch-icon' sizes='144x144' href='/WebPath/images/otsdaqIcons/apple-icon-144x144.png'>\
287 <link rel='apple-touch-icon' sizes='152x152' href='/WebPath/images/otsdaqIcons/apple-icon-152x152.png'>\
288 <link rel='apple-touch-icon' sizes='180x180' href='/WebPath/images/otsdaqIcons/apple-icon-180x180.png'>\
289 <link rel='icon' type='image/png' sizes='192x192' href='/WebPath/images/otsdaqIcons/android-icon-192x192.png'>\
290 <link rel='icon' type='image/png' sizes='32x32' href='/WebPath/images/otsdaqIcons/favicon-32x32.png'>\
291 <link rel='icon' type='image/png' sizes='96x96' href='/WebPath/images/otsdaqIcons/favicon-96x96.png'>\
292 <link rel='icon' type='image/png' sizes='16x16' href='/WebPath/images/otsdaqIcons/favicon-16x16.png'>\
293 <link rel='manifest' href='/WebPath/images/otsdaqIcons/manifest.json'>\
294 <meta name='msapplication-TileColor' content='#ffffff'>\
295 <meta name='msapplication-TileImage' content='/ms-icon-144x144.png'>\
296 <meta name='theme-color' content='#ffffff'>"
300 <<
"<frameset col='100%' row='100%'><frame "
301 "src='/WebPath/html/MacroMakerSupervisor.html?urn="
302 << this->getApplicationDescriptor()->getLocalId() << securityWarning
303 <<
"'></frameset></html>";
307 void MacroMakerSupervisor::generateURL()
309 defaultSequence_ =
true;
312 FILE* fp = fopen((SEQUENCE_FILE_NAME).c_str(),
"r");
315 __SUP_COUT_INFO__ <<
"Sequence length file found: " << SEQUENCE_FILE_NAME
318 fgets(line, 100, fp);
319 sscanf(line,
"%d", &length);
324 defaultSequence_ =
false;
330 <<
"(Reverting to default wiz security) Sequence length file NOT found: "
331 << SEQUENCE_FILE_NAME << __E__;
335 __SUP_COUT__ <<
"Sequence length = " << length << __E__;
339 const char alphanum[] =
341 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
342 "abcdefghijklmnopqrstuvwxyz";
344 for(
int i = 0; i < length; ++i)
346 securityCode_ += alphanum[rand() % (
sizeof(alphanum) - 1)];
349 __SUP_COUT__ << __ENV__(
"HOSTNAME") <<
":" << __ENV__(
"PORT")
350 <<
"/urn:xdaq-application:lid="
351 << this->getApplicationDescriptor()->getLocalId()
352 <<
"/Verify?code=" << securityCode_ << __E__;
358 fp = fopen((SEQUENCE_OUT_FILE_NAME).c_str(),
"w");
361 fprintf(fp,
"%s", securityCode_.c_str());
365 __SUP_COUT_ERR__ <<
"Sequence output file NOT found: " << SEQUENCE_OUT_FILE_NAME
372 void MacroMakerSupervisor::requestIcons(xgi::Input* in, xgi::Output* out)
374 cgicc::Cgicc cgi(in);
379 if(securityCode_.compare(submittedSequence) != 0)
381 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match! "
387 __COUT__ <<
"***Successfully authenticated security sequence. " << time(0)
400 *out <<
"Macro Maker "
401 ",MM,0,1,icon-MacroMaker.png,/WebPath/html/"
402 "MacroMaker.html?urn=290,/"
404 ",CFG,0,1,icon-Configure.png,/WebPath/html/"
405 "FEMacroTest.html?urn=290,/"
407 <<
",Code Editor,CODE,0,1,icon-CodeEditor.png,/urn:xdaq-application:lid=240/,/"
411 std::string iconFile = std::string(__ENV__(
"USER_DATA")) +
"/MacroMakerModeIcons.dat";
412 __COUT__ <<
"Macro Maker mode user icons file: " << iconFile << __E__;
413 FILE* fp = fopen(iconFile.c_str(),
"r");
416 __COUT__ <<
"Macro Maker mode user icons loading from " << iconFile << __E__;
417 fseek(fp, 0, SEEK_END);
418 const unsigned long fileSize = ftell(fp);
419 std::string fileString(fileSize, 0);
421 if(fread(&fileString[0], 1, fileSize, fp) != fileSize)
423 __COUT_ERR__ <<
"Unable to read proper size string from icons file!" << __E__;
428 __COUTV__(fileString);
432 __COUT__ <<
"Macro Maker mode user icons file not found: " << iconFile << __E__;
439 xoap::MessageReference MacroMakerSupervisor::supervisorSequenceCheck(
440 xoap::MessageReference message)
445 SOAPUtilities::receive(message, parameters);
447 std::string submittedSequence = parameters.getValue(
"sequence");
451 std::map<std::string , WebUsers::permissionLevel_t> permissionMap;
453 if(securityCode_ == submittedSequence)
454 permissionMap.emplace(
455 std::pair<std::string /*groupName*/, WebUsers::permissionLevel_t>(
459 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match!"
462 permissionMap.emplace(
463 std::pair<std::string /*groupName*/, WebUsers::permissionLevel_t>(
464 WebUsers::DEFAULT_USER_GROUP, WebUsers::PERMISSION_LEVEL_INACTIVE));
471 return SOAPUtilities::makeSOAPMessageReference(
"SequenceResponse", retParameters);
481 std::string ipAddressForRemoteControlOverUDP = __ENV__(
482 "OTS_MACROMAKER_UDP_IP");
483 int portForRemoteControlOverUDP = atoi(__ENV__(
484 "OTS_MACROMAKER_UDP_PORT"));
485 __COUT_INFO__ <<
"OTS_MACROMAKER_UDP_IP = " << ipAddressForRemoteControlOverUDP
486 <<
", OTS_MACROMAKER_UDP_PORT = " << portForRemoteControlOverUDP
487 <<
" -- test with: ots_mm_udp_test " << ipAddressForRemoteControlOverUDP
488 <<
" " << portForRemoteControlOverUDP << __E__;
491 portForRemoteControlOverUDP);
499 __SS__ <<
"FATAL Console error. Could not initialize socket at ip '"
500 << ipAddressForRemoteControlOverUDP <<
"' and port "
501 << portForRemoteControlOverUDP
502 <<
". Perhaps it is already in use? Exiting Remote Control "
503 "SOAPUtilities::receive loop."
505 ss <<
"TIP: this IP/port comes from the env vars OTS_MACROMAKER_UDP_IP and "
506 "OTS_MACROMAKER_UDP_PORT. If two otsdaq subsystems (e.g. gateway and "
507 "a MacroMaker-mode instance) were launched with the same values on this "
508 "host, they collide here. Check with: ss -ulpn | grep "
509 << portForRemoteControlOverUDP
510 <<
" (a leftover xdaq.exe holding the port must be killed first)." << __E__;
516 __COUT__ <<
"UDP Remote Control workloop starting..." << __E__;
526 buffer, 0 , 1 ,
false ) !=
529 __COUT__ <<
"UDP Remote Control packet received of size = " << buffer.size()
535 if(buffer ==
"GetFrontendMacroInfo")
537 std::string macroPath = (std::string)MACROS_DB_PATH +
"NO-USER" +
"/";
538 mkdir(macroPath.c_str(), 0755);
539 std::string histPath =
540 (std::string)MACROS_HIST_PATH +
"NO-USER" +
"/";
541 mkdir(histPath.c_str(), 0755);
544 theSupervisor->getFEMacroList(xmldoc,
"NO-USER");
546 std::stringstream out;
550 __COUT__ <<
"out: " << out.str();
551 sock.acknowledge(out.str(),
556 else if(buffer.find(
"RunFrontendMacro") == 0)
560 std::vector<std::string> bufferFields =
562 if(bufferFields.size() < 8)
564 __SS__ <<
"Missing input arguments for running FE Macro: "
565 << bufferFields.size() <<
" vs 8 expected" << __E__;
569 std::string feClassSelected = bufferFields[1];
570 std::string feUIDSelected =
572 std::string macroType = bufferFields[3];
573 std::string macroName =
577 std::string outputArgs =
579 bool saveOutputs = bufferFields[7] ==
"1";
580 std::string username =
"NO-USER";
581 std::string userGroupPermission =
"allUsers: 255";
584 std::set<std::string> feUIDs;
586 std::string expandUID =
587 feUIDSelected.empty() ?
"*" : feUIDSelected;
592 for(
auto& feTypePair : theSupervisor->FEPluginTypetoFEsMap_)
594 if(feClassSelected.empty() || feClassSelected ==
"*" ||
595 feClassSelected == feTypePair.first)
596 for(
auto& uid : feTypePair.second)
605 auto group = std::make_shared<runFEMacroGroupStruct>();
606 group->historyFeClassSelected_ =
607 feClassSelected.empty() ?
"*" : feClassSelected;
608 group->historyFeUIDSelected_ =
609 feUIDSelected.empty() ?
"*" : feUIDSelected;
610 group->historyMacroType_ = macroType;
611 group->historyMacroName_ = macroName;
612 group->historyInputArgs_ = inputArgs;
613 group->historyOutputArgs_ = outputArgs;
614 group->historySaveOutputs_ = saveOutputs;
615 group->historyUsername_ = username;
617 for(
const std::string& uid : feUIDs)
618 group->tasks_.push_back(
619 std::make_shared<runFEMacroStruct>(xmldoc,
628 userGroupPermission));
631 std::lock_guard<std::mutex> lock(
632 theSupervisor->feMacroRunThreadStructMutex_);
633 group->groupID_ = ++theSupervisor->feMacroRunGroupIDCounter_;
634 if(theSupervisor->feMacroRunGroupIDCounter_ == 0)
635 group->groupID_ = ++theSupervisor->feMacroRunGroupIDCounter_;
637 for(
auto& task : group->tasks_)
639 task->bar_ = std::make_unique<ProgressBar>();
640 task->bar_->reset(macroName,
641 task->parameters_.feUIDSelected_);
643 theSupervisor->feMacroRunThreadStruct_.emplace_back(group);
646 std::thread([group, theSupervisor]() {
647 MacroMakerSupervisor::runFEMacroGroupSchedulerThread(
648 group, theSupervisor);
651 auto lastProgressSend = std::chrono::steady_clock::now();
652 while(!group->allDone())
656 auto now = std::chrono::steady_clock::now();
657 if(std::chrono::duration_cast<std::chrono::seconds>(
658 now - lastProgressSend)
661 lastProgressSend = now;
663 int totalProgress = 0;
666 std::lock_guard<std::mutex> lock(
667 theSupervisor->feMacroRunThreadStructMutex_);
668 for(
auto& task : group->tasks_)
671 if(task->feMacroRunDone_)
672 totalProgress += 100;
674 totalProgress += task->bar_->read();
679 (taskCount > 0) ? (totalProgress / taskCount) : 0;
684 sock.acknowledge(std::string(
"<progress>") +
685 std::to_string(percent) +
"</progress>",
691 std::string taskError;
692 for(
auto& task : group->tasks_)
694 if(task->parameters_.feMacroRunError_ !=
"")
696 taskError = task->parameters_.feMacroRunError_;
703 std::lock_guard<std::mutex> lock(
704 theSupervisor->feMacroRunThreadStructMutex_);
706 i < theSupervisor->feMacroRunThreadStruct_.size();
708 if(theSupervisor->feMacroRunThreadStruct_[i].get() ==
711 theSupervisor->feMacroRunThreadStruct_.erase(
712 theSupervisor->feMacroRunThreadStruct_.begin() + i);
717 if(!taskError.empty())
723 std::stringstream out;
727 __COUT__ <<
"out: " << out.str();
728 sock.acknowledge(out.str(),
735 __SS__ <<
"Unrecognized UDP command received: " << buffer << __E__;
739 catch(
const std::runtime_error& e)
741 __COUT_ERR__ <<
"Error during UDP command handling: " << e.what()
743 sock.acknowledge(std::string(
"Error: ") + e.what(),
true );
747 __COUT_ERR__ <<
"Unknown error caught during UDP command handling - "
750 sock.acknowledge(std::string(
"Error: ") +
"unknown error caught",
754 __COUT__ <<
"Done handling command '" << buffer <<
"'" << __E__;
764 void MacroMakerSupervisor::requestWrapper(xgi::Input* in, xgi::Output* out)
767 if(!CorePropertySupervisorBase::allSupervisorInfo_.isMacroMakerMode())
769 __SUP_COUTT__ <<
"Default request wrapper" << __E__;
770 return CoreSupervisorBase::requestWrapper(in, out);
774 __SUP_COUTT__ <<
"MacroMaker mode request handler!" << __E__;
778 cgicc::Cgicc cgiIn(in);
783 if(securityCode_.compare(submittedSequence) != 0)
785 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match! "
787 *out << WebUsers::REQ_NO_PERMISSION_RESPONSE.c_str();
792 __SUP_COUTT__ <<
"***Successfully authenticated security sequence. " << time(0)
799 __SUP_COUT_TYPE__(TLVL_DEBUG + 10) << __COUT_HDR__ <<
"requestType " << requestType
800 <<
" files: " << cgiIn.getFiles().size() << __E__;
803 WebUsers::RequestUserInfo userInfo(
809 userInfo.username_ =
"admin";
810 userInfo.displayName_ =
"Admin";
811 userInfo.usernameWithLock_ =
"admin";
812 userInfo.userSessionIndex_ = 0;
813 std::map<std::string , WebUsers::permissionLevel_t> initPermissions = {
818 __SUP_COUTT__ <<
"requestType: " << requestType << __E__;
819 else if(!userInfo.automatedCommand_)
820 __SUP_COUT__ <<
"requestType: " << requestType << __E__;
822 if(userInfo.NonXMLRequestType_)
828 catch(
const std::runtime_error& e)
830 __SUP_SS__ <<
"An error was encountered handling requestType '" << requestType
831 <<
"':" << e.what() << __E__;
832 __SUP_COUT_ERR__ <<
"\n" << ss.str();
836 __SUP_SS__ <<
"An unknown error was encountered handling requestType '"
837 << requestType <<
".' "
838 <<
"Please check the printouts to debug." << __E__;
843 catch(
const std::exception& e)
845 ss <<
"Exception message: " << e.what();
850 __SUP_COUT_ERR__ <<
"\n" << ss.str();
859 request(requestType, cgiIn, xmlOut, userInfo);
860 __SUP_COUTT__ <<
"Request '" << requestType <<
"' complete." << __E__;
862 catch(
const std::runtime_error& e)
864 __SUP_SS__ <<
"An error was encountered handling requestType '" << requestType
865 <<
"':" << e.what() << __E__;
866 __SUP_COUT_ERR__ <<
"\n" << ss.str();
867 xmlOut.addTextElementToData(
"Error", ss.str());
871 __SUP_SS__ <<
"An unknown error was encountered handling requestType '"
872 << requestType <<
".' "
873 <<
"Please check the printouts to debug." << __E__;
878 catch(
const std::exception& e)
880 ss <<
"Exception message: " << e.what();
885 __SUP_COUT_ERR__ <<
"\n" << ss.str();
886 xmlOut.addTextElementToData(
"Error", ss.str());
891 unsigned int occurance = 0;
895 __SUP_COUT_ERR__ <<
"'" << requestType <<
"' ERROR encountered: " << err
901 __SUP_COUTVS__(10, userInfo.NoXmlWhiteSpace_);
906 !userInfo.NoXmlWhiteSpace_ );
910 void MacroMakerSupervisor::request(
const std::string& requestType,
913 const WebUsers::RequestUserInfo& userInfo)
916 std::chrono::steady_clock::time_point requestStart = std::chrono::steady_clock::now();
917 time_t requestStartTime = time(0);
920 std::string username =
"";
921 for(
unsigned int i = 0; i < userInfo.username_.size(); ++i)
922 if((userInfo.username_[i] >=
'a' && userInfo.username_[i] <=
'z') ||
923 (userInfo.username_[i] >=
'A' && userInfo.username_[i] <=
'Z') ||
924 (userInfo.username_[i] >=
'0' && userInfo.username_[i] <=
'9') ||
925 userInfo.username_[i] >=
'-' || userInfo.username_[i] <=
'_')
926 username += userInfo.username_[i];
928 if(username.size() < 2)
930 __SUP_SS__ <<
"Illegal username '" << userInfo.username_ <<
"' received."
935 __SUP_COUT__ <<
"User name is " << userInfo.username_ <<
"." << __E__;
936 __SUP_COUT__ <<
"User permission level for request '" << requestType <<
"' is "
937 << unsigned(userInfo.permissionLevel_) <<
"." << __E__;
941 if(requestType ==
"loadFEHistory")
943 std::string histPath = (std::string)MACROS_HIST_PATH + userInfo.username_ +
"/";
944 mkdir(histPath.c_str(), 0755);
947 if(requestType ==
"loadFEMacroSequences")
949 std::string seqPath =
950 (std::string)MACROS_SEQUENCE_PATH + userInfo.username_ +
"/";
951 mkdir(seqPath.c_str(), 0755);
954 if(requestType ==
"getPermission")
956 xmlOut.addTextElementToData(
"Permission",
957 std::to_string(
unsigned(userInfo.permissionLevel_)));
960 std::string publicPath = (std::string)MACROS_DB_PATH +
"publicMacros/";
961 mkdir(publicPath.c_str(), 0755);
962 std::string exportPath =
963 __ENV__(
"SERVICE_DATA_PATH") + MACROS_EXPORT_PATH + userInfo.username_ +
"/";
964 mkdir(exportPath.c_str(), 0755);
967 handleRequest(requestType, xmlOut, cgiIn, userInfo);
969 __SUP_COUTT__ <<
"Total MacroMaker request time: "
970 << artdaq::TimeUtils::GetElapsedTime(requestStart) <<
" = "
971 << time(0) - requestStartTime <<
" seconds" << __E__;
973 catch(
const std::runtime_error& e)
975 __SS__ <<
"Error occurred handling request '" << requestType <<
"': " << e.what()
977 __SUP_COUT__ << ss.str();
978 xmlOut.addTextElementToData(
"Error", ss.str());
982 __SS__ <<
"Unknown error occurred handling request '" << requestType <<
"!'" << __E__;
987 catch(
const std::exception& e)
989 ss <<
"Exception message: " << e.what();
994 __SUP_COUT__ << ss.str();
995 xmlOut.addTextElementToData(
"Error", ss.str());
1000 void MacroMakerSupervisor::handleRequest(
const std::string Command,
1003 const WebUsers::RequestUserInfo& userInfo)
1005 if(Command ==
"FElist")
1008 std::string macroPath = (std::string)MACROS_DB_PATH + userInfo.username_ +
"/";
1009 mkdir(macroPath.c_str(), 0755);
1010 std::string histPath = (std::string)MACROS_HIST_PATH + userInfo.username_ +
"/";
1011 mkdir(histPath.c_str(), 0755);
1015 else if(Command ==
"writeData")
1016 writeData(xmldoc, cgi, userInfo.username_);
1017 else if(Command ==
"readData")
1018 readData(xmldoc, cgi, userInfo.username_);
1019 else if(Command ==
"createMacro")
1020 createMacro(xmldoc, cgi, userInfo.username_);
1021 else if(Command ==
"loadMacros")
1022 loadMacros(xmldoc, userInfo.username_);
1023 else if(Command ==
"loadHistory")
1024 loadHistory(xmldoc, userInfo.username_);
1025 else if(Command ==
"deleteMacro")
1026 deleteMacro(xmldoc, cgi, userInfo.username_);
1027 else if(Command ==
"editMacro")
1028 editMacro(xmldoc, cgi, userInfo.username_);
1029 else if(Command ==
"clearHistory")
1030 clearHistory(userInfo.username_);
1031 else if(Command ==
"exportMacro")
1032 exportMacro(xmldoc, cgi, userInfo.username_);
1033 else if(Command ==
"exportFEMacro")
1034 exportFEMacro(xmldoc, cgi, userInfo.username_);
1035 else if(Command ==
"getFEMacroList")
1039 std::string macroPath = (std::string)MACROS_DB_PATH + userInfo.username_ +
"/";
1040 mkdir(macroPath.c_str(), 0755);
1041 std::string histPath = (std::string)MACROS_HIST_PATH + userInfo.username_ +
"/";
1042 mkdir(histPath.c_str(), 0755);
1044 getFEMacroList(xmldoc, userInfo.username_);
1046 else if(Command ==
"runFEMacro")
1048 runFEMacro(xmldoc, cgi, userInfo);
1049 else if(Command ==
"loadFEHistory")
1051 loadFEHistory(xmldoc, userInfo.username_);
1052 else if(Command ==
"clearFEHistory")
1054 clearFEHistory(userInfo.username_);
1055 else if(Command ==
"loadFEMacroSequences")
1056 loadFEMacroSequences(xmldoc, userInfo.username_);
1057 else if(Command ==
"saveFEMacroSequence")
1058 saveFEMacroSequence(cgi, userInfo.username_);
1059 else if(Command ==
"getFEMacroSequence")
1060 getFEMacroSequence(xmldoc, cgi, userInfo.username_);
1061 else if(Command ==
"deleteFEMacroSequence")
1062 deleteFEMacroSequence(cgi, userInfo.username_);
1063 else if(Command ==
"makeSequencePublic")
1064 makeSequencePublic(cgi, userInfo.username_);
1065 else if(Command ==
"saveFEMacroTestPreferences")
1067 int twoColumnView = CgiDataUtilities::postDataAsInt(cgi,
"twoColumnView");
1068 int showSequencePane = CgiDataUtilities::postDataAsInt(cgi,
"showSequencePane");
1069 int dynamicDropdown = CgiDataUtilities::postDataAsInt(cgi,
"dynamicDropdown");
1071 if(userInfo.username_ ==
"")
1073 __SUP_COUT_ERR__ <<
"Invalid user found! user=" << userInfo.username_
1075 xmldoc.addTextElementToData(
"Error",
"Error - Invalid user found.");
1079 std::string fn = (std::string)USER_FEMACROTEST_PREF_PATH + userInfo.username_ +
1080 "." + (std::string)FEMACROTEST_PREF_FILETYPE;
1082 FILE* fp = fopen(fn.c_str(),
"w");
1086 __THROW__(ss.str() +
"Could not open file: " + fn);
1088 fprintf(fp,
"twoColumnView %d\n", twoColumnView);
1089 fprintf(fp,
"showSequencePane %d\n", showSequencePane);
1090 fprintf(fp,
"dynamicDropdown %d\n", dynamicDropdown);
1093 else if(Command ==
"loadFEMacroTestPreferences")
1095 if(userInfo.username_ ==
"")
1097 __SUP_COUT_ERR__ <<
"Invalid user found! user=" << userInfo.username_
1099 xmldoc.addTextElementToData(
"Error",
"Error - Invalid user found.");
1103 std::string fn = (std::string)USER_FEMACROTEST_PREF_PATH + userInfo.username_ +
1104 "." + (std::string)FEMACROTEST_PREF_FILETYPE;
1106 FILE* fp = fopen(fn.c_str(),
"r");
1109 __SUP_COUT__ <<
"Returning defaults." << __E__;
1110 xmldoc.addTextElementToData(
"twoColumnView",
"0");
1111 xmldoc.addTextElementToData(
"showSequencePane",
"0");
1112 xmldoc.addTextElementToData(
"dynamicDropdown",
"0");
1115 unsigned int twoColumnView = 0, showSequencePane = 0, dynamicDropdown = 0;
1116 fscanf(fp,
"%*s %u", &twoColumnView);
1117 fscanf(fp,
"%*s %u", &showSequencePane);
1118 fscanf(fp,
"%*s %u", &dynamicDropdown);
1122 sprintf(tmpStr,
"%u", twoColumnView);
1123 xmldoc.addTextElementToData(
"twoColumnView", tmpStr);
1124 sprintf(tmpStr,
"%u", showSequencePane);
1125 xmldoc.addTextElementToData(
"showSequencePane", tmpStr);
1126 sprintf(tmpStr,
"%u", dynamicDropdown);
1127 xmldoc.addTextElementToData(
"dynamicDropdown", tmpStr);
1130 xmldoc.addTextElementToData(
"Error",
1131 "Command '" + Command +
1132 "' not recognized by the Macro Maker Supervisor "
1133 "(was it intended for another Supervisor?).");
1137 xoap::MessageReference MacroMakerSupervisor::frontEndCommunicationRequest(
1138 xoap::MessageReference message)
1145 SOAPUtilities::receive(message, typeParameter);
1147 std::string type = typeParameter.getValue(
"type");
1149 std::string error =
"";
1151 if(type ==
"initFElist")
1153 __SUP_COUTV__(type);
1158 rxParameters.
addParameter(
"SubsystemCommonOverrideList");
1159 SOAPUtilities::receive(message, rxParameters);
1161 std::string groupName = rxParameters.getValue(
"groupName");
1162 std::string groupKey = rxParameters.getValue(
"groupKey");
1163 std::string subsystemCommonList = rxParameters.getValue(
"SubsystemCommonList");
1164 std::string subsystemCommonOverrideList =
1165 rxParameters.getValue(
"SubsystemCommonOverrideList");
1167 __SUP_COUTV__(groupName);
1168 __SUP_COUTV__(groupKey);
1169 __SUP_COUTV__(subsystemCommonList);
1170 __SUP_COUTV__(subsystemCommonOverrideList);
1173 std::map<std::string ,
TableVersion> mergeInTables, overrideTables;
1176 if(!subsystemCommonList.empty())
1178 subsystemCommonList =
1180 __COUT__ <<
"Transition parameter SubsystemCommonList: "
1181 << subsystemCommonList << __E__;
1188 if(!subsystemCommonOverrideList.empty())
1190 subsystemCommonOverrideList =
1192 __COUT__ <<
"Transition parameter SubsystemCommonOverrideList: "
1193 << subsystemCommonOverrideList << __E__;
1215 ConfigurationManager::LoadGroupType::ALL_TYPES,
1224 const SupervisorInfoMap& feTypeSupervisors =
1225 CorePropertySupervisorBase::allSupervisorInfo_.getAllFETypeSupervisorInfo();
1228 cfgMgr.
getNode(ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME);
1230 __SUP_COUT__ <<
"Number of FE Supervisors found = " << feTypeSupervisors.size()
1233 FEPluginTypetoFEsMap_.clear();
1234 FEtoSupervisorMap_.clear();
1235 FEtoPluginTypeMap_.clear();
1236 for(
auto& feApp : feTypeSupervisors)
1238 __SUP_COUTT__ <<
"FEs for app " << feApp.first <<
":"
1239 << feApp.second.getName() << __E__;
1241 auto feChildren = appsNode.
getNode(feApp.second.getName())
1242 .
getNode(
"LinkToSupervisorTable")
1243 .
getNode(
"LinkToFEInterfaceTable")
1246 for(
auto& fe : feChildren)
1248 if(!fe.second.status())
1251 __SUP_COUTTV__(fe.first);
1252 FEtoSupervisorMap_[fe.first] = feApp.first;
1254 std::string pluginType =
1255 fe.second.getNode(
"FEInterfacePluginName").getValue();
1256 FEPluginTypetoFEsMap_[pluginType].emplace(fe.first);
1257 FEtoPluginTypeMap_[fe.first] = pluginType;
1265 else if(type ==
"feSend" ||
1266 type ==
"feMacro" ||
1267 type ==
"feMacroMultiDimensionalStart" ||
1268 type ==
"feMacroMultiDimensionalCheck" ||
1269 type ==
"macroMultiDimensionalStart" ||
1270 type ==
"macroMultiDimensionalCheck")
1272 __SUP_COUTV__(type);
1275 SOAPUtilities::receive(message, rxParameters);
1277 std::string targetInterfaceID = rxParameters.getValue(
"targetInterfaceID");
1279 __SUP_COUTV__(targetInterfaceID);
1281 auto feIt = FEtoSupervisorMap_.find(targetInterfaceID);
1282 if(feIt == FEtoSupervisorMap_.end())
1284 __SUP_SS__ <<
"Destination front end interface ID '" << targetInterfaceID
1285 <<
"' was not found in the list of front ends." << __E__;
1289 unsigned int FESupervisorIndex = feIt->second;
1290 __SUP_COUT__ <<
"Found supervisor index: " << FESupervisorIndex << __E__;
1292 SupervisorInfoMap::iterator it = allFESupervisorInfo_.find(FESupervisorIndex);
1293 if(it == allFESupervisorInfo_.end())
1295 __SUP_SS__ <<
"Error transmitting request to FE Supervisor '"
1296 << targetInterfaceID <<
":" << FESupervisorIndex <<
".' \n\n"
1297 <<
"The FE Supervisor Index does not exist. Have you configured "
1298 "the state machine properly?"
1303 if(type ==
"macroMultiDimensionalStart")
1309 SOAPUtilities::receive(message, rxParameters);
1310 std::string macroName = rxParameters.getValue(
"macroName");
1311 __SUP_COUTV__(macroName);
1313 std::string macroString;
1314 loadMacro(macroName, macroString);
1318 SOAPUtilities::addParameters(message, parameters);
1323 __SUP_COUT_INFO__ <<
"Forwarding (fresh message) to LID="
1324 << it->second.getId() <<
" URL=" << it->second.getURL()
1330 SOAPCommand incomingCmd = SOAPUtilities::translate(message);
1331 xoap::MessageReference freshMessage =
1332 SOAPUtilities::makeSOAPMessageReference(
"FECommunication");
1336 incomingCmd.getParameters().getValue(
"requester"));
1337 fwdParams.
addParameter(
"targetInterfaceID", targetInterfaceID);
1338 if(type ==
"feMacro")
1341 "feMacroName", incomingCmd.getParameters().getValue(
"feMacroName"));
1343 incomingCmd.getParameters().getValue(
"inputArgs"));
1345 else if(type ==
"feSend")
1348 incomingCmd.getParameters().getValue(
"value"));
1350 else if(type ==
"feMacroMultiDimensionalStart")
1353 "feMacroName", incomingCmd.getParameters().getValue(
"feMacroName"));
1355 incomingCmd.getParameters().getValue(
"inputArgs"));
1357 "enableSavingOutput",
1358 incomingCmd.getParameters().getValue(
"enableSavingOutput"));
1361 incomingCmd.getParameters().getValue(
"outputFilePath"));
1364 incomingCmd.getParameters().getValue(
"outputFileRadix"));
1366 else if(type ==
"macroMultiDimensionalStart")
1369 incomingCmd.getParameters().getValue(
"macroName"));
1371 "macroString", incomingCmd.getParameters().getValue(
"macroString"));
1373 incomingCmd.getParameters().getValue(
"inputArgs"));
1375 "enableSavingOutput",
1376 incomingCmd.getParameters().getValue(
"enableSavingOutput"));
1379 incomingCmd.getParameters().getValue(
"outputFilePath"));
1382 incomingCmd.getParameters().getValue(
"outputFileRadix"));
1384 else if(type ==
"feMacroMultiDimensionalCheck")
1387 "feMacroName", incomingCmd.getParameters().getValue(
"feMacroName"));
1389 else if(type ==
"macroMultiDimensionalCheck")
1392 incomingCmd.getParameters().getValue(
"macroName"));
1394 SOAPUtilities::addParameters(freshMessage, fwdParams);
1396 xoap::MessageReference replyMessage = SOAPMessenger::sendWithSOAPReply(
1397 it->second.getDescriptor(), freshMessage);
1399 if(type !=
"feSend")
1401 std::string replyStr =
1402 SOAPUtilities::translate(replyMessage).getCommand();
1404 if(replyStr ==
"Fault")
1408 std::string fullReply;
1409 replyMessage->writeTo(fullReply);
1410 __SUP_COUT_WARN__ <<
"SOAP Fault detail for target '"
1411 << targetInterfaceID <<
"': " << fullReply
1419 return replyMessage;
1422 catch(
const xdaq::exception::Exception& e)
1424 __SUP_SS__ <<
"Error forwarding FE Communication request to FE Supervisor '"
1425 << targetInterfaceID <<
":" << FESupervisorIndex <<
".' "
1426 <<
"Have you configured the state machine properly?\n\n"
1427 << e.what() << __E__;
1433 __SUP_SS__ <<
"Unrecognized FE Communication type: " << type << __E__;
1437 return SOAPUtilities::makeSOAPMessageReference(
"Received");
1439 catch(
const std::runtime_error& e)
1441 __SUP_SS__ <<
"Error processing FE communication request: " << e.what() << __E__;
1442 __SUP_COUT_ERR__ << ss.str();
1444 xoap::MessageReference returnMessage =
1445 SOAPUtilities::makeSOAPMessageReference(
"Error");
1449 SOAPUtilities::addParameters(returnMessage, parameters);
1450 return returnMessage;
1454 xoap::MessageReference returnMessage =
1455 SOAPUtilities::makeSOAPMessageReference(
"Error");
1457 __SUP_SS__ <<
"Unknown error processing FE communication request." << __E__;
1462 catch(
const std::exception& e)
1464 ss <<
"Exception message: " << e.what();
1469 __SUP_COUT_ERR__ << ss.str();
1473 SOAPUtilities::addParameters(returnMessage, parameters);
1474 return returnMessage;
1480 __SUP_COUT__ <<
"Getting FE list!!!!!!!!!" << __E__;
1492 SupervisorInfoMap::const_iterator it;
1493 std::string oneInterface;
1494 std::string rxFEList;
1495 std::string rxFrontEndError;
1497 size_t lastColonIndex;
1501 for(
auto& appInfo : allFESupervisorInfo_)
1509 __SUP_COUT__ <<
"FESupervisor LID = " << appInfo.second.getId()
1510 <<
" name = " << appInfo.second.getName() << __E__;
1514 xoap::MessageReference retMsg =
1515 SOAPMessenger::sendWithSOAPReply(appInfo.second.getDescriptor(),
1516 "MacroMakerSupervisorRequest",
1518 SOAPUtilities::receive(retMsg, rxParameters);
1520 __SUP_COUT__ <<
"Received MacroMaker response: "
1521 << SOAPUtilities::translate(retMsg).getCommand() <<
"==>"
1522 << SOAPUtilities::translate(retMsg) << __E__;
1524 if(SOAPUtilities::translate(retMsg).getCommand() ==
"Fault")
1526 __SUP_SS__ <<
"Unrecognized command received!" << __E__;
1530 catch(
const xdaq::exception::Exception& e)
1532 __SUP_SS__ <<
"Error transmitting request to FE Supervisor LID = "
1533 << appInfo.second.getId() <<
" name = " << appInfo.second.getName()
1535 << e.what() << __E__;
1539 rxFEList = rxParameters.getValue(
"FEList");
1540 rxFrontEndError = rxParameters.getValue(
"frontEndError");
1542 __SUP_COUT__ <<
"FE List received: \n" << rxFEList << __E__;
1544 if(rxFrontEndError !=
"")
1546 __SUP_SS__ <<
"FE Errors received: \n" << rxFrontEndError << __E__;
1550 std::istringstream allInterfaces(rxFEList);
1551 while(std::getline(allInterfaces, oneInterface))
1553 __SUP_COUTV__(oneInterface);
1554 xmldoc.addTextElementToData(
"FE", oneInterface);
1556 lastColonIndex = oneInterface.rfind(
':');
1557 if(lastColonIndex == std::string::npos)
1559 __SUP_SS__ <<
"Last colon could not be found in " << oneInterface
1563 oneInterface = oneInterface.substr(lastColonIndex);
1565 __SUP_COUTV__(oneInterface);
1575 const std::string& username)
1577 __SUP_COUT__ <<
"MacroMaker writing..." << __E__;
1590 __SUP_COUT__ <<
"Write Address: " << Address <<
" Data: " << Data << __E__;
1591 __SUP_COUTV__(interfaces);
1593 std::string command =
"w:" + Address +
":" + Data;
1594 std::string format = addressFormatStr +
":" + dataFormatStr;
1595 appendCommandToHistory(command, format, time, interfaces, username);
1598 txParameters.
addParameter(
"Request",
"UniversalWrite");
1602 __SUP_COUT__ <<
"Here comes the array from multiselect box for WRITE, behold: \n"
1603 << supervisorIndexArray <<
"\n"
1604 << interfaceIndexArray << __E__;
1608 std::vector<std::string> interfaceIndices;
1609 std::istringstream f(interfaceIndexArray);
1611 while(getline(f, s,
','))
1612 interfaceIndices.push_back(s);
1613 std::vector<int> supervisorIndices;
1614 std::istringstream g(supervisorIndexArray);
1616 while(getline(g, t,
','))
1617 supervisorIndices.push_back(std::stoi(t));
1619 for(
unsigned int i = 0; i < supervisorIndices.size(); i++)
1621 unsigned int FESupervisorIndex = supervisorIndices[i];
1622 std::string interfaceIndex = interfaceIndices[i];
1624 txParameters.
addParameter(
"InterfaceID", interfaceIndex);
1626 __SUP_COUT__ <<
"The index of the supervisor instance is: " << FESupervisorIndex
1628 __SUP_COUT__ <<
"...and the interface ID is: " << interfaceIndex << __E__;
1630 SupervisorInfoMap::iterator it = allFESupervisorInfo_.find(FESupervisorIndex);
1631 if(it == allFESupervisorInfo_.end())
1633 __SUP_SS__ <<
"Error transmitting request to FE Supervisor '"
1634 << interfaceIndex <<
":" << FESupervisorIndex <<
".' \n\n"
1635 <<
"The FE Index doesn't exist. Have you configured the state "
1643 xoap::MessageReference replyMessage = SOAPMessenger::sendWithSOAPReply(
1644 it->second.getDescriptor(),
"MacroMakerSupervisorRequest", txParameters);
1646 __SUP_COUT__ <<
"Response received: "
1647 << SOAPUtilities::translate(replyMessage) << __E__;
1651 SOAPUtilities::receive(replyMessage, rxParameters);
1653 std::string error = rxParameters.getValue(
"Error");
1654 __SUP_COUTV__(error);
1659 __SUP_SS__ <<
"Error transmitting request to FE Supervisor '"
1660 << interfaceIndex <<
":" << FESupervisorIndex <<
".' "
1661 <<
"Have you configured the state machine properly?\n\n"
1666 catch(
const xdaq::exception::Exception& e)
1668 __SUP_SS__ <<
"Error transmitting request to FE Supervisor '"
1669 << interfaceIndex <<
":" << FESupervisorIndex <<
".' "
1670 <<
"Have you configured the state machine properly?\n\n"
1671 << e.what() << __E__;
1681 const std::string& username)
1683 __SUP_COUT__ <<
"@@@@@@@ MacroMaker wants to read data @@@@@@@@" << __E__;
1694 __SUP_COUT__ <<
"Read Address: " << Address << __E__;
1695 __SUP_COUTV__(interfaces);
1704 __SUP_COUT__ <<
"Here comes the array from multiselect box for READ, behold: "
1705 << supervisorIndexArray <<
"," << interfaceIndexArray << __E__;
1709 std::vector<std::string> interfaceIndices;
1710 std::istringstream f(interfaceIndexArray);
1712 while(getline(f, s,
','))
1713 interfaceIndices.push_back(s);
1714 std::vector<int> supervisorIndices;
1715 std::istringstream g(supervisorIndexArray);
1717 while(getline(g, t,
','))
1718 supervisorIndices.push_back(std::stoi(t));
1720 for(
unsigned int i = 0; i < supervisorIndices.size(); i++)
1722 unsigned int FESupervisorIndex = supervisorIndices[i];
1723 std::string interfaceIndex = interfaceIndices[i];
1725 txParameters.
addParameter(
"InterfaceID", interfaceIndex);
1727 __SUP_COUT__ <<
"The index of the supervisor instance is: " << FESupervisorIndex
1729 __SUP_COUT__ <<
"...and the interface ID is: " << interfaceIndex << __E__;
1731 SupervisorInfoMap::iterator it = allFESupervisorInfo_.find(FESupervisorIndex);
1732 if(it == allFESupervisorInfo_.end())
1734 __SUP_SS__ <<
"Error transmitting request to FE Supervisor '"
1735 << interfaceIndex <<
":" << FESupervisorIndex <<
".' \n\n"
1736 <<
"The FE Index doesn't exist. Have you configured the state "
1744 xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply(
1745 it->second.getDescriptor(),
"MacroMakerSupervisorRequest", txParameters);
1747 __SUP_COUT__ <<
"Response received: " << SOAPUtilities::translate(retMsg)
1752 SOAPUtilities::receive(retMsg, rxParameters);
1754 std::string error = rxParameters.getValue(
"Error");
1755 __SUP_COUTV__(error);
1760 __SUP_SS__ <<
"Error transmitting request to FE Supervisor '"
1761 << interfaceIndex <<
":" << FESupervisorIndex <<
".' "
1762 <<
"Have you configured the state machine properly?\n\n"
1767 catch(
const xdaq::exception::Exception& e)
1769 __SUP_SS__ <<
"Error transmitting request to FE Supervisor '"
1770 << interfaceIndex <<
":" << FESupervisorIndex <<
".' "
1771 <<
"Have you configured the state machine properly?\n\n"
1772 << e.what() << __E__;
1776 std::string dataReadResult = rxParameters.getValue(
"dataResult");
1777 __SUP_COUT__ <<
"Data reading result received: " << dataReadResult << __E__;
1778 xmldoc.addTextElementToData(
"readData", dataReadResult);
1779 std::string command =
"r:" + Address +
":" + dataReadResult;
1780 std::string format = addressFormatStr +
":" + dataFormatStr;
1781 appendCommandToHistory(command, format, time, interfaces, username);
1788 const std::string& username)
1790 __SUP_COUT__ <<
"MacroMaker wants to create a macro!!!!!!!!!" << __E__;
1799 __SUP_COUTV__(Name);
1800 __SUP_COUTV__(Sequence);
1801 __SUP_COUTV__(Notes);
1802 __SUP_COUTV__(Time);
1803 __SUP_COUTV__(isMacroPublic);
1804 __SUP_COUTV__(isMacroLSBF);
1806 __SUP_COUTV__(MACROS_DB_PATH);
1808 std::string fileName = Name +
".dat";
1809 std::string fullPath;
1810 if(isMacroPublic ==
"true")
1811 fullPath = (std::string)MACROS_DB_PATH +
"publicMacros/" + fileName;
1813 fullPath = (std::string)MACROS_DB_PATH + username +
"/" + fileName;
1815 __SUP_COUTV__(fullPath);
1817 std::ofstream macrofile(fullPath.c_str());
1818 if(macrofile.is_open())
1821 macrofile <<
"\"name\":\"" << Name <<
"\",\n";
1822 macrofile <<
"\"sequence\":\"" << Sequence <<
"\",\n";
1823 macrofile <<
"\"time\":\"" << Time <<
"\",\n";
1824 macrofile <<
"\"notes\":\"" << Notes <<
"\",\n";
1825 macrofile <<
"\"LSBF\":\"" << isMacroLSBF <<
"\"\n";
1826 macrofile <<
"}@" << __E__;
1831 __SUP_SS__ <<
"Unable to open file" << __E__;
1844 void MacroMakerSupervisor::loadMacro(
const std::string& macroName,
1845 std::string& macroString,
1846 const std::string& username )
1848 __SUP_COUTV__(macroName);
1851 std::string fullPath, line;
1853 for(
unsigned int i = 0; i < 2; ++i)
1856 fullPath = (std::string)MACROS_DB_PATH + username +
"/";
1858 fullPath = (std::string)MACROS_DB_PATH +
"publicMacros/";
1860 fullPath += macroName;
1861 if(macroName.find(
".dat") != macroName.size() - 4)
1863 __SUP_COUTV__(fullPath);
1865 std::ifstream read(fullPath.c_str());
1870 getline(read, line);
1871 macroString += line;
1878 __SUP_COUT__ <<
"Unable to open file: " << fullPath << __E__;
1882 if(macroString !=
"")
1886 if(macroString ==
"")
1888 __SUP_SS__ <<
"Unable to locate file for macro '" << macroName
1889 <<
"'... does it exist?" << __E__;
1891 ss <<
" Attempted username was '" << username <<
".'" << __E__;
1895 __SUP_COUTV__(macroString);
1899 void MacroMakerSupervisor::loadMacroNames(
1900 const std::string& username,
1901 std::pair<std::vector<std::string> ,
1902 std::vector<std::string> >& returnMacroNames)
1906 std::string fullPath = (std::string)MACROS_DB_PATH + username +
"/";
1907 if((dir = opendir(fullPath.c_str())) != NULL)
1910 while((ent = readdir(dir)) != NULL)
1913 if((
unsigned)strlen(ent->d_name) > 4)
1917 ((fullPath + (std::string)ent->d_name)).c_str());
1922 returnMacroNames.second.push_back(ent->d_name);
1925 __SUP_COUT__ <<
"Unable to open file" << __E__;
1932 __SUP_COUT__ <<
"Looping through privateMacros folder failed! Wrong directory"
1935 fullPath = (std::string)MACROS_DB_PATH +
"publicMacros/";
1936 if((dir = opendir(fullPath.c_str())) != NULL)
1939 while((ent = readdir(dir)) != NULL)
1942 if((
unsigned)strlen(ent->d_name) > 4)
1946 ((fullPath + (std::string)ent->d_name)).c_str());
1950 returnMacroNames.first.push_back(ent->d_name);
1954 __SUP_COUT__ <<
"Unable to open file" << __E__;
1961 __SUP_COUT__ << fullPath << __E__;
1962 __SUP_COUT__ <<
"Looping through MacroData folder failed! Wrong directory"
1970 const std::string& username)
1974 std::string returnStr =
"";
1975 std::string fullPath = (std::string)MACROS_DB_PATH + username +
"/";
1976 if((dir = opendir(fullPath.c_str())) != NULL)
1979 while((ent = readdir(dir)) != NULL)
1982 if((
unsigned)strlen(ent->d_name) > 4)
1986 ((fullPath + (std::string)ent->d_name)).c_str());
1989 std::stringstream buffer;
1992 getline(read, line);
1996 returnStr += buffer.str();
2001 __SUP_COUT__ <<
"Unable to open file" << __E__;
2004 std::string returnMacroStr = returnStr.substr(0, returnStr.size() - 1);
2006 __SUP_COUT__ <<
"Loading existing macros! " << returnMacroStr << __E__;
2009 xmldoc.addTextElementToData(
"returnMacroStr", returnMacroStr);
2013 __SUP_COUT__ <<
"Looping through privateMacros folder failed! Wrong directory"
2016 fullPath = (std::string)MACROS_DB_PATH +
"publicMacros/";
2018 if((dir = opendir(fullPath.c_str())) != NULL)
2021 while((ent = readdir(dir)) != NULL)
2024 if((
unsigned)strlen(ent->d_name) > 4)
2028 ((fullPath + (std::string)ent->d_name)).c_str());
2031 std::stringstream buffer;
2034 getline(read, line);
2038 returnStr += buffer.str();
2042 __SUP_COUT__ <<
"Unable to open file" << __E__;
2045 std::string returnPublicStr = returnStr.substr(0, returnStr.size() - 1);
2046 __SUP_COUT__ <<
"Loading existing public macros: " << returnPublicStr << __E__;
2048 xmldoc.addTextElementToData(
"returnPublicStr", returnPublicStr);
2052 __SUP_COUT__ << fullPath << __E__;
2053 __SUP_COUT__ <<
"Looping through MacroData folder failed! Wrong directory"
2059 void MacroMakerSupervisor::appendCommandToHistory(std::string Command,
2062 std::string Interfaces,
2063 const std::string& username)
2065 std::string fileName =
"history.hist";
2066 std::string fullPath = (std::string)MACROS_HIST_PATH + username +
"/" + fileName;
2067 __SUP_COUT__ << fullPath << __E__;
2068 std::ofstream histfile(fullPath.c_str(), std::ios::app);
2069 if(histfile.is_open())
2072 histfile <<
"\"Command\":\"" << Command <<
"\",\n";
2073 histfile <<
"\"Format\":\"" << Format <<
"\",\n";
2074 histfile <<
"\"Time\":\"" << Time <<
"\",\n";
2075 histfile <<
"\"Interfaces\":\"" << Interfaces <<
"\"\n";
2076 histfile <<
"}#" << __E__;
2081 __SUP_SS__ <<
"Unable to open history.hist at " << fullPath << __E__;
2087 void MacroMakerSupervisor::appendCommandToHistory(std::string feClass,
2089 std::string macroType,
2090 std::string macroName,
2091 std::string inputArgs,
2092 std::string outputArgs,
2094 const std::string& username,
2096 time_t completeTime)
2099 launchTime = time(0);
2100 if(completeTime == 0)
2101 completeTime = launchTime;
2103 std::string fileName =
"FEhistory.hist";
2104 std::string fullPath = (std::string)MACROS_HIST_PATH + username +
"/" + fileName;
2106 auto feHistoryIt = lastFeCommandToHistory_.find(username);
2108 (feHistoryIt != lastFeCommandToHistory_.end() &&
2109 feHistoryIt->second.size() == 7 && feHistoryIt->second[0] == feClass &&
2110 feHistoryIt->second[1] == feUID && feHistoryIt->second[2] == macroType &&
2111 feHistoryIt->second[3] == macroName && feHistoryIt->second[4] == inputArgs &&
2112 feHistoryIt->second[5] == outputArgs &&
2113 feHistoryIt->second[6] == (saveOutputs ?
"1" :
"0"));
2115 unsigned int repeatCount;
2116 time_t origLaunchTime;
2120 repeatCount = lastFeRepeatCount_[username] + 1;
2121 origLaunchTime = lastFeLaunchTime_[username];
2123 auto posIt = lastFeRecordFilePos_.find(username);
2124 if(posIt != lastFeRecordFilePos_.end() && posIt->second > 0)
2126 struct stat fileStat;
2127 if(stat(fullPath.c_str(), &fileStat) == 0 &&
2128 fileStat.st_size >= posIt->second)
2130 truncate(fullPath.c_str(), posIt->second);
2134 __SUP_COUTT__ <<
"Incrementing repeat count to " << repeatCount
2135 <<
" for command to history from user " << username << __E__;
2140 origLaunchTime = launchTime;
2143 struct stat fileStat;
2145 if(stat(fullPath.c_str(), &fileStat) == 0)
2146 filePos = fileStat.st_size;
2148 __SUP_COUT__ << fullPath << __E__;
2149 std::ofstream histfile(fullPath.c_str(), std::ios::app);
2150 if(histfile.is_open())
2153 histfile <<
"\"feClass\":\"" << feClass <<
"\",\n";
2154 histfile <<
"\"feUID\":\"" << feUID <<
"\",\n";
2155 histfile <<
"\"macroType\":\"" << macroType <<
"\",\n";
2156 histfile <<
"\"macroName\":\"" << macroName <<
"\",\n";
2157 histfile <<
"\"inputArgs\":\"" << inputArgs <<
"\",\n";
2158 histfile <<
"\"outputArgs\":\"" << outputArgs <<
"\",\n";
2159 histfile <<
"\"launchTime\":\"" << origLaunchTime <<
"\",\n";
2160 histfile <<
"\"completeTime\":\"" << completeTime <<
"\",\n";
2162 histfile <<
"\"repeatCount\":\"" << repeatCount <<
"\",\n";
2164 histfile <<
"\"saveOutputs\":\"" << 1 <<
"\"\n";
2166 histfile <<
"\"saveOutputs\":\"" << 0 <<
"\"\n";
2167 histfile <<
"}#" << __E__;
2170 lastFeCommandToHistory_[username].clear();
2171 feHistoryIt = lastFeCommandToHistory_.find(username);
2172 feHistoryIt->second.push_back(feClass);
2173 feHistoryIt->second.push_back(feUID);
2174 feHistoryIt->second.push_back(macroType);
2175 feHistoryIt->second.push_back(macroName);
2176 feHistoryIt->second.push_back(inputArgs);
2177 feHistoryIt->second.push_back(outputArgs);
2178 feHistoryIt->second.push_back((saveOutputs ?
"1" :
"0"));
2180 lastFeRepeatCount_[username] = repeatCount;
2181 lastFeRecordFilePos_[username] = filePos;
2182 lastFeLaunchTime_[username] = origLaunchTime;
2186 __SUP_SS__ <<
"Unable to open FEhistory.hist at " << fullPath << __E__;
2193 void MacroMakerSupervisor::loadFEMacroSequences(
HttpXmlDocument& xmldoc,
2194 const std::string& username)
2196 __SUP_COUT__ <<
"loadFEMacroSequences for " << username << __E__;
2199 std::string fullPath = (std::string)MACROS_SEQUENCE_PATH + username +
"/";
2200 std::string sequences =
"";
2201 __SUP_COUTV__(fullPath);
2202 if((dir = opendir(fullPath.c_str())) != NULL)
2205 while((ent = readdir(dir)) != NULL)
2209 ((fullPath + (std::string)ent->d_name)).c_str());
2213 sequences += ent->d_name + std::string(
";");
2216 __SUP_COUT__ <<
"Unable to open file" << __E__;
2222 __SUP_COUT__ <<
"Looping through MacroSequence/" + username +
2223 " folder failed! Invalid directory."
2227 if(username == WebUsers::DEFAULT_ADMIN_USERNAME)
2230 xmldoc.addTextElementToData(
"FEsequences", sequences);
2235 fullPath = (std::string)MACROS_SEQUENCE_PATH + WebUsers::DEFAULT_ADMIN_USERNAME +
"/";
2237 if((dir = opendir(fullPath.c_str())) != NULL)
2240 while((ent = readdir(dir)) != NULL)
2244 ((fullPath + (std::string)ent->d_name)).c_str());
2248 sequences += std::string(
"public/") + ent->d_name + std::string(
";");
2251 __SUP_COUT__ <<
"Unable to open file" << __E__;
2257 __SUP_COUT__ <<
"Looping through MacroSequence/" +
2258 WebUsers::DEFAULT_ADMIN_USERNAME +
2259 " folder failed! Invalid directory."
2264 xmldoc.addTextElementToData(
"FEsequences", sequences);
2268 void MacroMakerSupervisor::saveFEMacroSequence(cgicc::Cgicc& cgi,
2269 const std::string& username)
2274 std::string FEsequence =
2276 bool overwrite = CgiDataUtilities::getDataAsInt(cgi,
"overwrite");
2278 __SUP_COUTV__(overwrite);
2279 __SUP_COUTV__(name);
2280 __SUP_COUTV__(FEsequence);
2283 std::string fixedName =
"";
2284 for(
size_t i = 0; i < name.size(); ++i)
2285 if(!(name[i] ==
' ' || name[i] ==
'-' || name[i] ==
'_' ||
2286 (name[i] >=
'0' && name[i] <=
'9') || (name[i] >=
'A' && name[i] <=
'Z') ||
2287 (name[i] >=
'a' && name[i] <=
'z')))
2290 <<
"Illegal character in Sequence name (position " << i
2291 <<
") - only alphanumeric, spaces, dashes, and underscores allowed!"
2296 fixedName += name[i];
2297 __SUP_COUTV__(fixedName);
2299 std::string fullPath =
2300 (std::string)MACROS_SEQUENCE_PATH + username +
"/" + fixedName +
".dat";
2301 __SUP_COUTV__(fullPath);
2304 if(!overwrite && std::filesystem::exists(fullPath))
2306 __SUP_SS__ <<
"Please choose another Sequence name! A sequence with the same "
2307 "resulting filename already exists at "
2308 << fullPath << __E__;
2312 std::ofstream seqfile(fullPath.c_str());
2313 if(seqfile.is_open())
2315 seqfile << FEsequence << __E__;
2320 __SUP_SS__ <<
"Unable to open file to save FE Macro Sequence at " << fullPath
2327 void MacroMakerSupervisor::getFEMacroSequence(
HttpXmlDocument& xmldoc,
2329 const std::string& username)
2333 __SUP_COUTV__(name);
2335 bool isPublic = (name.find(
"public/") == 0 ? true :
false);
2336 __SUP_COUTV__(isPublic);
2339 std::string fixedName =
"";
2340 for(
size_t i = (isPublic ? std::string(
"public/").size() : 0); i < name.size(); ++i)
2341 if(!(name[i] ==
' ' || name[i] ==
'-' || name[i] ==
'_' ||
2342 (name[i] >=
'0' && name[i] <=
'9') || (name[i] >=
'A' && name[i] <=
'Z') ||
2343 (name[i] >=
'a' && name[i] <=
'z')))
2345 __COUT__ <<
"Illegal character in Sequence name (position " << i
2346 <<
") - only alphanumeric, spaces, dashes, and underscores allowed!"
2350 fixedName += name[i];
2351 __SUP_COUTV__(fixedName);
2354 std::string fullPath =
2355 (std::string)MACROS_SEQUENCE_PATH + username +
"/" + fixedName +
".dat";
2356 __SUP_COUT__ << fullPath << __E__;
2358 std::ifstream read(fullPath.c_str());
2360 unsigned long long fileSize;
2362 if(!isPublic && read.is_open())
2364 read.seekg(0, std::ios::end);
2365 fileSize = read.tellg();
2366 response =
new char[fileSize + 1];
2367 response[fileSize] =
'\0';
2368 read.seekg(0, std::ios::beg);
2371 read.read(response, fileSize);
2374 xmldoc.addTextElementToData(
"FEsequence", &response[0]);
2381 __SUP_COUT__ <<
"Unable to open " << fullPath <<
"! Trying public area..."
2385 std::string publicFullPath = (std::string)MACROS_SEQUENCE_PATH +
2386 WebUsers::DEFAULT_ADMIN_USERNAME +
"/" + fixedName +
2388 __SUP_COUT__ << publicFullPath << __E__;
2390 std::ifstream read(publicFullPath.c_str());
2392 unsigned long long fileSize;
2396 read.seekg(0, std::ios::end);
2397 fileSize = read.tellg();
2398 response =
new char[fileSize + 1];
2399 response[fileSize] =
'\0';
2400 read.seekg(0, std::ios::beg);
2403 read.read(response, fileSize);
2406 xmldoc.addTextElementToData(
"FEsequence", &response[0]);
2412 __SUP_SS__ <<
"Unable to open FE Macro Sequence at " << fullPath <<
" or "
2413 << publicFullPath << __E__;
2420 void MacroMakerSupervisor::deleteFEMacroSequence(cgicc::Cgicc& cgi,
2421 const std::string& username)
2425 __SUP_COUTV__(name);
2427 bool isPublic = (name.find(
"public/") == 0 ? true :
false);
2428 __SUP_COUTV__(isPublic);
2431 std::string fixedName =
"";
2432 for(
size_t i = (isPublic ? std::string(
"public/").size() : 0); i < name.size(); ++i)
2433 if(!(name[i] ==
' ' || name[i] ==
'-' || name[i] ==
'_' ||
2434 (name[i] >=
'0' && name[i] <=
'9') || (name[i] >=
'A' && name[i] <=
'Z') ||
2435 (name[i] >=
'a' && name[i] <=
'z')))
2437 __COUT__ <<
"Illegal character in Sequence name (position " << i
2438 <<
") - only alphanumeric, spaces, dashes, and underscores allowed!"
2442 fixedName += name[i];
2443 __SUP_COUTV__(fixedName);
2446 std::string fullPath =
2447 (std::string)MACROS_SEQUENCE_PATH + username +
"/" + fixedName +
".dat";
2449 fullPath = (std::string)MACROS_SEQUENCE_PATH + WebUsers::DEFAULT_ADMIN_USERNAME +
2450 "/" + fixedName +
".dat";
2451 __SUP_COUT__ << fullPath << __E__;
2454 if(!std::filesystem::exists(fullPath))
2457 <<
"The specified Sequence name does not exist! Looking for sequence file at "
2458 << fullPath << __E__;
2462 std::remove(fullPath.c_str());
2463 __SUP_COUT__ <<
"Successfully deleted " << fullPath << __E__;
2467 void MacroMakerSupervisor::makeSequencePublic(cgicc::Cgicc& cgi,
2468 const std::string& username)
2472 __SUP_COUTV__(name);
2474 bool isPublic = (name.find(
"public/") == 0 ? true :
false);
2475 __SUP_COUTV__(isPublic);
2478 __SUP_SS__ <<
"The specified Sequence name is already designated as public."
2484 std::string fixedName =
"";
2485 for(
size_t i = 0; i < name.size(); ++i)
2486 if(!(name[i] ==
' ' || name[i] ==
'-' || name[i] ==
'_' ||
2487 (name[i] >=
'0' && name[i] <=
'9') || (name[i] >=
'A' && name[i] <=
'Z') ||
2488 (name[i] >=
'a' && name[i] <=
'z')))
2490 __COUT__ <<
"Illegal character in Sequence name (position " << i
2491 <<
") - only alphanumeric, spaces, dashes, and underscores allowed!"
2495 fixedName += name[i];
2496 __SUP_COUTV__(fixedName);
2499 std::string source =
2500 (std::string)MACROS_SEQUENCE_PATH + username +
"/" + fixedName +
".dat";
2501 __SUP_COUT__ << source << __E__;
2502 std::string destination = (std::string)MACROS_SEQUENCE_PATH +
2503 WebUsers::DEFAULT_ADMIN_USERNAME +
"/" + fixedName +
".dat";
2504 __SUP_COUT__ << destination << __E__;
2506 if(std::filesystem::exists(destination))
2508 __SUP_SS__ <<
"The sequence name '" << fixedName
2509 <<
"' already exists in the admin/public location: " << destination
2515 std::filesystem::copy_file(
2516 source, destination, std::filesystem::copy_options::skip_existing);
2517 __SUP_COUT__ <<
"Successfully made " << fixedName
2518 <<
" public at path: " << destination << __E__;
2523 const std::string& username)
2525 std::string fileName = MACROS_HIST_PATH + username +
"/" +
"history.hist";
2527 std::ifstream read(fileName.c_str());
2528 __SUP_COUT__ << fileName << __E__;
2534 unsigned long long fileSz, i = 0, MAX_HISTORY_SIZE = 100000;
2538 read.seekg(0, std::ios::end);
2539 fileSz = read.tellg();
2540 returnStr =
new char[fileSz + 1];
2541 returnStr[fileSz] =
'\0';
2542 read.seekg(0, std::ios::beg);
2545 read.read(returnStr, fileSz);
2549 if(fileSz > MAX_HISTORY_SIZE)
2551 i = fileSz - MAX_HISTORY_SIZE;
2552 for(; i < fileSz; ++i)
2553 if(returnStr[i] ==
'#')
2562 FILE* fp = fopen(fileName.c_str(),
"w");
2566 __SS__ <<
"Big problem with macromaker history file: " << fileName
2570 fwrite(&returnStr[i], fileSz - i, 1, fp);
2574 __SUP_COUT__ <<
"Loading user history! " << __E__;
2577 returnStr[fileSz - 2] =
'\0';
2579 xmldoc.addTextElementToData(
"returnHistStr", &returnStr[i]);
2584 __SUP_COUT__ <<
"Unable to open history.hist" << __E__;
2590 const std::string& username)
2592 std::string fileName = MACROS_HIST_PATH + username +
"/" +
"FEhistory.hist";
2594 std::ifstream read(fileName.c_str());
2595 __SUP_COUT__ << fileName << __E__;
2597 if(!read.is_open() && username != WebUsers::DEFAULT_ADMIN_USERNAME)
2599 __SUP_COUT__ <<
"Unable to open FE history.hist.. Defaulting to admin's FE "
2600 "history as starting point."
2604 MACROS_HIST_PATH + WebUsers::DEFAULT_ADMIN_USERNAME +
"/" +
"FEhistory.hist";
2605 read.open(fileName.c_str());
2612 unsigned long long fileSize;
2613 unsigned long long i = 0;
2614 unsigned long long MAX_HISTORY_SIZE = 100000;
2617 read.seekg(0, std::ios::end);
2618 fileSize = read.tellg();
2619 returnStr =
new char[fileSize + 1];
2620 returnStr[fileSize] =
'\0';
2621 read.seekg(0, std::ios::beg);
2624 read.read(returnStr, fileSize);
2628 if(fileSize > MAX_HISTORY_SIZE)
2630 i = fileSize - MAX_HISTORY_SIZE;
2631 for(; i < fileSize; ++i)
2633 if(returnStr[i] ==
'#')
2643 FILE* fp = fopen(fileName.c_str(),
"w");
2647 __SS__ <<
"Big problem with FE history file: " << fileName << __E__;
2650 fwrite(&returnStr[i], fileSize - i, 1, fp);
2654 __SUP_COUT__ <<
"Loading user history! " << __E__;
2657 returnStr[fileSize - 2] =
'\0';
2659 xmldoc.addTextElementToData(
"returnHistStr", &returnStr[i]);
2664 __SUP_COUT__ <<
"Unable to open FE history.hist" << __E__;
2671 const std::string& username)
2676 std::string fileName = MacroName +
".dat";
2677 std::string fullPath;
2678 if(isMacroPublic ==
"true")
2679 fullPath = (std::string)MACROS_DB_PATH +
"publicMacros/" + fileName;
2681 fullPath = (std::string)MACROS_DB_PATH + username +
"/" + fileName;
2683 __SUP_COUT__ << fullPath << __E__;
2685 std::remove(fullPath.c_str());
2686 __SUP_COUT__ <<
"Successfully deleted " << MacroName;
2687 xmldoc.addTextElementToData(
"deletedMacroName", MacroName);
2693 const std::string& username)
2705 __SUP_COUTV__(oldMacroName);
2706 __SUP_COUTV__(newMacroName);
2707 __SUP_COUTV__(FESequence);
2708 __SUP_COUTV__(Notes);
2709 __SUP_COUTV__(Time);
2710 __SUP_COUTV__(isMacroPublic);
2711 __SUP_COUTV__(isMacroLSBF);
2713 __SUP_COUTV__(MACROS_DB_PATH);
2715 std::string fileName = oldMacroName +
".dat";
2716 std::string fullPath;
2717 if(isMacroPublic ==
"true")
2718 fullPath = (std::string)MACROS_DB_PATH +
"publicMacros/" + fileName;
2720 fullPath = (std::string)MACROS_DB_PATH + username +
"/" + fileName;
2722 __SUP_COUTV__(fullPath);
2724 std::ofstream macrofile(fullPath.c_str());
2725 if(macrofile.is_open())
2728 macrofile <<
"\"name\":\"" << newMacroName <<
"\",\n";
2729 macrofile <<
"\"FEsequence\":\"" << FESequence <<
"\",\n";
2730 macrofile <<
"\"time\":\"" << Time <<
"\",\n";
2731 macrofile <<
"\"notes\":\"" << Notes <<
"\",\n";
2732 macrofile <<
"\"LSBF\":\"" << isMacroLSBF <<
"\"\n";
2733 macrofile <<
"}@" << __E__;
2737 __SUP_COUT__ <<
"Unable to open file" << __E__;
2739 if(oldMacroName != newMacroName)
2743 rename((MACROS_DB_PATH + username +
"/" + oldMacroName +
".dat").c_str(),
2744 (MACROS_DB_PATH + username +
"/" + newMacroName +
".dat").c_str());
2746 xmldoc.addTextElementToData(
"newMacroName", newMacroName);
2748 xmldoc.addTextElementToData(
"newMacroName",
"ERROR");
2753 void MacroMakerSupervisor::clearHistory(
const std::string& username)
2755 std::string fileName =
"history.hist";
2756 std::string fullPath = (std::string)MACROS_HIST_PATH + username +
"/" + fileName;
2758 std::remove(fullPath.c_str());
2759 __SUP_COUT__ <<
"Successfully deleted " << fullPath;
2763 void MacroMakerSupervisor::clearFEHistory(
const std::string& username)
2765 std::string fileName =
"FEhistory.hist";
2766 std::string fullPath = (std::string)MACROS_HIST_PATH + username +
"/" + fileName;
2768 std::remove(fullPath.c_str());
2772 lastFeCommandToHistory_.erase(username);
2773 lastFeRepeatCount_.erase(username);
2774 lastFeRecordFilePos_.erase(username);
2775 lastFeLaunchTime_.erase(username);
2777 __SUP_COUT__ <<
"Successfully deleted " << fullPath;
2783 const std::string& username)
2788 std::string macroNotes =
2791 __SUP_COUTV__(pluginName);
2792 __SUP_COUTV__(macroName);
2793 __SUP_COUTV__(macroSequence);
2796 for(
unsigned int i = 0; i < macroNotes.length(); ++i)
2797 if(macroNotes[i] ==
'\r' || macroNotes[i] ==
'\n')
2798 macroNotes[i] =
' ';
2799 __SUP_COUTV__(macroNotes);
2801 std::stringstream ss(macroSequence);
2802 std::string command;
2803 std::vector<std::string> commands;
2805 while(getline(ss, command,
','))
2806 commands.push_back(command);
2810 std::map<std::string , std::set<std::string> >
2811 specialsCodeMap = CodeEditor::getSpecialsMap();
2814 auto specialsCodeMapIt = specialsCodeMap.find(CodeEditor::SPECIAL_TYPE_FEInterface);
2815 if(specialsCodeMapIt == specialsCodeMap.end())
2818 <<
"Could not find any FE Interface plugins in source code. Does MacroMaker "
2819 <<
"have access to the source code? Check that the Supervisor context places "
2821 <<
"location with access to the source code." << __E__;
2826 std::string headerFile = pluginName +
".h";
2827 std::string sourceFile = pluginName +
"_interface.cc";
2828 bool foundHeaderFile =
false;
2829 bool foundSourceFile =
false;
2830 for(
const auto& filePath : specialsCodeMapIt->second)
2832 if(!foundHeaderFile && filePath.find(headerFile) != std::string::npos)
2834 foundHeaderFile =
true;
2835 headerFile = filePath;
2836 __SUP_COUT__ <<
"found headerFile=" << filePath << __E__;
2838 if(!foundSourceFile && filePath.find(sourceFile) != std::string::npos)
2840 foundSourceFile =
true;
2841 sourceFile = filePath;
2842 __SUP_COUT__ <<
"found sourceFile=" << filePath << __E__;
2845 if(foundSourceFile && foundHeaderFile)
2849 if(!foundHeaderFile)
2851 __SS__ <<
"Could not find the header file for the FE Interface plugins at '"
2852 << headerFile <<
".' Does MacroMaker "
2853 <<
"have access to the source code? Check that the Supervisor context "
2854 "places MacroMaker in a "
2855 <<
"location with access to the source code." << __E__;
2858 if(!foundSourceFile)
2860 __SS__ <<
"Could not find the source file for the FE Interface plugins at '"
2861 << sourceFile <<
".' Does MacroMaker "
2862 <<
"have access to the source code? Check that the Supervisor context "
2863 "places MacroMaker in a "
2864 <<
"location with access to the source code." << __E__;
2877 char timeBuffer[100];
2880 struct tm* timeinfo;
2883 timeinfo = localtime(&rawtime);
2885 strftime(timeBuffer, 100,
"%b-%d-%Y %I:%M:%S", timeinfo);
2888 std::string contents;
2893 CodeEditor::readFile(CodeEditor::SOURCE_BASE_PATH, sourceFile, contents);
2897 xmldoc.addTextElementToData(
"sourceFile", sourceFile);
2898 xmldoc.addTextElementToData(
"headerFile", headerFile);
2901 if(contents.find(pluginName +
"::" + macroName) != std::string::npos)
2903 __SS__ <<
"The function definition '" << (pluginName +
"::" + macroName)
2904 <<
"(...)' already exists in the source file '" << sourceFile
2905 <<
".' Duplicate functions are not allowed - please rename the macro or "
2906 "modify the source file."
2911 std::stringstream codess;
2912 std::set<std::string> inArgNames, outArgNames;
2924 auto insertPos = contents.find(pluginName +
"::" + pluginName);
2925 if(insertPos == std::string::npos)
2927 __SS__ <<
"Could not find the code insert position in the source file '"
2928 << sourceFile <<
".' The FE plugin class constructor must be '"
2929 << pluginName <<
":" << pluginName <<
"' - is this the case?" << __E__;
2932 __SUP_COUTV__(insertPos);
2934 insertPos = contents.find(
"{", insertPos);
2935 if(insertPos == std::string::npos)
2937 __SS__ <<
"Could not find the code insert position in the source file '"
2939 <<
".' The FE plugin class constructor must begin with '{"
2940 <<
"' - is this the case?" << __E__;
2944 __SUP_COUTV__(insertPos);
2946 insert =
"\n\t//registration of FEMacro '" + macroName +
"' generated, " +
2947 timeBuffer +
", by '" + username +
"' using MacroMaker.\n\t" +
2948 "FEVInterface::registerFEMacroFunction(\"" + macroName +
2949 "\",//feMacroName \n\t\t" +
2950 "static_cast<FEVInterface::frontEndMacroFunction_t>(&" + pluginName +
2951 "::" + macroName +
"), //feMacroFunction \n\t\t" +
2952 "std::vector<std::string>{";
2955 for(
const auto& inArg : inArgNames)
2961 insert +=
"\"" + inArg +
"\"";
2964 insert +=
"}, //namesOfInputArgs \n\t\t";
2965 insert +=
"std::vector<std::string>{";
2968 for(
const auto& outArg : outArgNames)
2974 insert +=
"\"" + outArg +
"\"";
2977 insert +=
"}, //namesOfOutputArgs \n\t\t";
2978 insert +=
"1); //requiredUserPermissions \n\n";
2980 __SUP_COUTV__(insert);
2981 contents = contents.substr(0, insertPos) + insert + contents.substr(insertPos);
2986 auto insertPos = contents.rfind(
"DEFINE_OTS_INTERFACE");
2987 if(insertPos == std::string::npos)
2989 __SS__ <<
"Could not find the code insert position in the source file '"
2991 <<
".' The FE plugin class must end with a 'DEFINE_OTS_INTERFACE("
2992 << pluginName <<
")' - is this the case?" << __E__;
2995 __SUP_COUTV__(insertPos);
2999 "============================================================================"
3000 "============================================\n//" +
3001 macroName +
"\n" +
"//\tFEMacro '" + macroName +
"' generated, " +
3002 timeBuffer +
", by '" + username +
"' using MacroMaker.\n" +
3003 "//\tMacro Notes: " + macroNotes +
"\n" +
"void " + pluginName +
3004 "::" + macroName +
"(__ARGS__)\n{\n\t" +
3005 "__CFG_COUT__ << \"# of input args = \" << argsIn.size() << __E__; \n\t" +
3006 "__CFG_COUT__ << \"# of output args = \" << argsOut.size() << __E__; \n\t" +
3007 "for(auto &argIn:argsIn) \n\t\t" +
3008 "__CFG_COUT__ << argIn.first << \": \" << argIn.second << __E__; \n\n\t" +
3009 "//macro commands section \n" + codess.str() +
"\n\n\t" +
3010 "for(auto &argOut:argsOut) \n\t\t" +
3011 "__CFG_COUT__ << argOut.first << \": \" << argOut.second << __E__; \n\n" +
3012 "} //end " + macroName +
"()\n\n";
3015 CodeEditor::writeFile(CodeEditor::SOURCE_BASE_PATH,
3018 "MacroMaker-" + username,
3025 CodeEditor::readFile(CodeEditor::SOURCE_BASE_PATH, headerFile, contents);
3030 auto insertPos = contents.rfind(
"};");
3031 if(insertPos == std::string::npos)
3033 __SS__ <<
"Could not find the code insert position in the header file '"
3035 <<
".' The FE plugin class must end with a '};' - is this the case?"
3040 __SUP_COUTV__(insertPos);
3042 insert =
"\npublic: // FEMacro '" + macroName +
"' generated, " + timeBuffer +
3043 ", by '" + username +
"' using MacroMaker.\n\t" +
"void " + macroName +
3046 __SUP_COUTV__(insert);
3047 CodeEditor::writeFile(CodeEditor::SOURCE_BASE_PATH,
3050 "MacroMaker-" + username,
3060 const std::string& username)
3064 std::string macroNotes =
3067 __SUP_COUTV__(macroName);
3068 __SUP_COUTV__(macroSequence);
3071 for(
unsigned int i = 0; i < macroNotes.length(); ++i)
3072 if(macroNotes[i] ==
'\r' || macroNotes[i] ==
'\n')
3073 macroNotes[i] =
' ';
3074 __SUP_COUTV__(macroNotes);
3076 std::stringstream ss(macroSequence);
3077 std::string command;
3078 std::vector<std::string> commands;
3080 while(getline(ss, command,
','))
3081 commands.push_back(command);
3083 std::string fileName = macroName +
".cc";
3085 std::string fullPath =
3086 __ENV__(
"SERVICE_DATA_PATH") + MACROS_EXPORT_PATH + username +
"/" + fileName;
3087 __SUP_COUT__ << fullPath << __E__;
3088 std::ofstream exportFile(fullPath.c_str(), std::ios::trunc);
3089 if(exportFile.is_open())
3091 exportFile <<
"//Generated Macro Name:\t" << macroName <<
"\n";
3092 exportFile <<
"//Macro Notes: " << macroNotes <<
"\n";
3096 struct tm* timeinfo;
3100 timeinfo = localtime(&rawtime);
3102 strftime(buffer, 100,
"%b-%d-%Y %I:%M:%S", timeinfo);
3103 exportFile <<
"//Generated Time: \t\t" << buffer <<
"\n";
3106 exportFile <<
"//Paste this whole file into an interface to transfer Macro "
3109 createCode(exportFile, commands);
3113 xmldoc.addTextElementToData(
3115 "$USER_DATA/ServiceData/" + MACROS_EXPORT_PATH + username +
"/" + fileName);
3118 __SUP_COUT__ <<
"Unable to open file" << __E__;
3123 void MacroMakerSupervisor::createCode(std::ostream& out,
3124 const std::vector<std::string>& commands,
3125 const std::string& tabOffset,
3127 std::set<std::string>* inArgNames,
3128 std::set<std::string>* outArgNames)
3131 std::set<std::string > argInHasBeenInitializedSet;
3132 bool addressIsVariable, dataIsVariable;
3134 out << tabOffset <<
"{";
3137 << tabOffset <<
"\t"
3138 <<
"char *address \t= new char[universalAddressSize_]{0}; //create address "
3139 "buffer of interface size and init to all 0";
3141 << tabOffset <<
"\t"
3142 <<
"char *data \t\t= new char[universalDataSize_]{0}; //create data buffer "
3143 "of interface size and init to all 0";
3146 << tabOffset <<
"\t"
3147 <<
"uint64_t macroAddress; //create macro address buffer (size 8 bytes)";
3149 << tabOffset <<
"\t"
3150 <<
"uint64_t macroData; //create macro address buffer (size 8 bytes)";
3153 << tabOffset <<
"\t"
3154 <<
"std::map<std::string /*arg name*/,uint64_t /*arg val*/> macroArgs; //create "
3155 "map from arg name to 64-bit number";
3158 for(
unsigned int i = 0; i < commands.size(); i++)
3160 std::stringstream sst(commands[i]);
3162 std::vector<std::string>
3164 while(getline(sst, tokens,
':'))
3165 oneCommand.push_back(tokens);
3166 while(oneCommand.size() < 4)
3167 oneCommand.push_back(
"");
3195 addressIsVariable = isArgumentVariable(oneCommand[2]);
3196 dataIsVariable = isArgumentVariable(oneCommand[3]);
3198 __SUP_COUTV__(addressIsVariable);
3199 __SUP_COUTV__(dataIsVariable);
3201 out <<
"\n\n" << tabOffset <<
"\t// command-#" << i <<
": ";
3203 if(oneCommand[1][0] ==
'w' || oneCommand[1][0] ==
'r')
3205 if(oneCommand[1][0] ==
'w')
3207 else if(oneCommand[1][0] ==
'r')
3210 if(addressIsVariable)
3211 out << oneCommand[2];
3213 out <<
"0x" << oneCommand[2];
3214 out <<
" /*address*/,";
3218 out << oneCommand[3] <<
" /*data*/";
3219 else if(oneCommand[1][0] ==
'w')
3220 out <<
"0x" << oneCommand[3] <<
" /*data*/";
3221 else if(oneCommand[1][0] ==
'r')
3225 else if(oneCommand[1][0] ==
'd')
3227 out <<
"delay(" << oneCommand[2] <<
");\n";
3228 out << tabOffset <<
"\t"
3229 <<
"__CFG_COUT__ << \"Sleeping for... \" << " << oneCommand[2]
3230 <<
" << \" milliseconds \" << __E__;\n";
3231 out << tabOffset <<
"\t"
3232 <<
"usleep(" << oneCommand[2] <<
"*1000 /* microseconds */);\n";
3237 __SS__ <<
"FATAL ERROR: Unknown command '" << oneCommand[1]
3238 <<
"'... command is not w, r or d" << __E__;
3244 if(addressIsVariable)
3246 if(argInHasBeenInitializedSet.find(oneCommand[2]) ==
3247 argInHasBeenInitializedSet.end())
3249 argInHasBeenInitializedSet.emplace(oneCommand[2]);
3254 out << tabOffset <<
"\t"
3255 <<
"macroArgs[\"" << oneCommand[2]
3257 "theXDAQContextConfigTree_.getNode(theConfigurationPath_)."
3260 << tabOffset <<
"\t\t\"" << oneCommand[2]
3261 <<
"\").getValue<uint64_t>();";
3266 inArgNames->emplace(oneCommand[2]);
3269 out << tabOffset <<
"\t"
3270 <<
"macroArgs[\"" << oneCommand[2] <<
"\"] = __GET_ARG_IN__(\""
3271 << oneCommand[2] <<
"\", uint64_t);";
3274 out <<
"\t//get macro address argument";
3276 << tabOffset <<
"\tmemcpy(address,¯oArgs[\"" << oneCommand[2]
3277 <<
"\"],8); //copy macro address argument to buffer";
3281 out << tabOffset <<
"\t"
3282 <<
"macroAddress = 0x" << oneCommand[2]
3283 <<
"; memcpy(address,¯oAddress,8);"
3284 <<
"\t//copy macro address to buffer";
3289 if(oneCommand[1] ==
"w")
3293 if(argInHasBeenInitializedSet.find(oneCommand[3]) ==
3294 argInHasBeenInitializedSet
3297 argInHasBeenInitializedSet.emplace(oneCommand[3]);
3302 inArgNames->emplace(oneCommand[3]);
3306 << tabOffset <<
"\t"
3307 <<
"macroArgs[\"" << oneCommand[3]
3308 <<
"\"] = __GET_ARG_IN__(\"" << oneCommand[3]
3309 <<
"\", uint64_t); //initialize from input arguments";
3315 << tabOffset <<
"\t"
3316 <<
"macroArgs[\"" << oneCommand[3]
3318 "theXDAQContextConfigTree_.getNode(theConfigurationPath_)."
3321 << tabOffset <<
"\t\t\"" << oneCommand[3]
3322 <<
"\").getValue<uint64_t>(); //initialize from "
3323 "configuration tree";
3326 out <<
"\t//get macro data argument";
3328 << tabOffset <<
"\tmemcpy(data,¯oArgs[\"" << oneCommand[3]
3329 <<
"\"],8); //copy macro data argument to buffer";
3334 << tabOffset <<
"\t"
3335 <<
"macroData = 0x" << oneCommand[3] <<
"; memcpy(data,¯oData,8);"
3336 <<
"\t//copy macro data to buffer";
3339 << tabOffset <<
"\t"
3340 <<
"universalWrite(address,data);";
3345 << tabOffset <<
"\t"
3346 <<
"universalRead(address,data);";
3348 std::string outputArgName;
3351 outputArgName = oneCommand[3];
3355 sprintf(str,
"outArg%d", i);
3356 outputArgName = str;
3358 __SUP_COUTV__(outputArgName);
3360 out << tabOffset <<
"\t"
3361 <<
"memcpy(¯oArgs[\"" << outputArgName
3362 <<
"\"],data,8); //copy buffer to argument map";
3367 << tabOffset <<
"\t"
3368 <<
"__SET_ARG_OUT__(\"" << outputArgName <<
"\",macroArgs[\""
3369 << outputArgName <<
"\"]); //update output argument result";
3372 outArgNames->emplace(outputArgName);
3373 argInHasBeenInitializedSet.emplace(
3378 out <<
"\n\n" << tabOffset <<
"\tdelete[] address; //free the memory";
3379 out <<
"\n" << tabOffset <<
"\tdelete[] data; //free the memory";
3380 out <<
"\n" << tabOffset <<
"}";
3382 __SUP_COUT__ <<
"Done with code generation." << __E__;
3388 bool MacroMakerSupervisor::isArgumentVariable(
const std::string& argumentString)
3390 for(
unsigned int i = 0; i < argumentString.length(); ++i)
3393 if(!((argumentString[i] >=
'0' && argumentString[i] <=
'9') ||
3394 (argumentString[i] >=
'a' && argumentString[i] <=
'f') ||
3395 (argumentString[i] >=
'A' && argumentString[i] <=
'F')))
3410 std::string MacroMakerSupervisor::generateHexArray(
const std::string& sourceHexString,
3413 std::stringstream retSs;
3415 std::string srcHexStr = sourceHexString;
3416 __SUP_COUT__ <<
"Translating: \n";
3417 __SUP_COUT__ << srcHexStr << __E__;
3419 if(srcHexStr.size() % 2)
3420 srcHexStr =
"0" + srcHexStr;
3422 numOfBytes = srcHexStr.size() / 2;
3423 retSs <<
"[" << numOfBytes <<
"] = {";
3425 for(
int i = 0; i < numOfBytes * 2; i += 2)
3428 if(!((srcHexStr[i] >=
'0' && srcHexStr[i] <=
'9') ||
3429 (srcHexStr[i] >=
'a' && srcHexStr[i] <=
'f') ||
3430 (srcHexStr[i] >=
'A' && srcHexStr[i] <=
'F')) ||
3431 !((srcHexStr[i + 1] >=
'0' && srcHexStr[i + 1] <=
'9') ||
3432 (srcHexStr[i + 1] >=
'a' && srcHexStr[i + 1] <=
'f') ||
3433 (srcHexStr[i + 1] >=
'A' && srcHexStr[i + 1] <=
'F')))
3441 retSs <<
"0x" << srcHexStr[srcHexStr.size() - 1 - i - 1]
3442 << srcHexStr[srcHexStr.size() - 1 - i];
3446 __SUP_COUT__ << retSs.str() << __E__;
3454 const WebUsers::RequestUserInfo& userInfo)
3457 __SUP_COUTT__ << __E__;
3459 uint64_t NotDoneID = CgiDataUtilities::getDataAsUint64_t(cgi,
"NotDoneID");
3462 std::lock_guard<std::mutex> lock(feMacroRunThreadStructMutex_);
3464 __SUP_COUTT__ <<
"Checking NotDoneID = " << NotDoneID << __E__;
3466 time_t now = time(0);
3467 size_t target_i = -1;
3468 for(
size_t i = 0; i < feMacroRunThreadStruct_.size(); ++i)
3470 auto& group = feMacroRunThreadStruct_[i];
3471 if(group->groupID_ == NotDoneID)
3473 __SUP_COUTT__ <<
"Found group NotDoneID = " << NotDoneID << __E__;
3476 else if(group->allDone())
3479 time_t latestDone = 0;
3480 for(
const auto& t : group->tasks_)
3481 if(t->parameters_.doneTime_ > latestDone)
3482 latestDone = t->parameters_.doneTime_;
3483 if(latestDone >= 0 && now - latestDone > 5 * 60 )
3485 __SUP_COUTT__ <<
"Cleaning up completed group " << group->groupID_
3487 feMacroRunThreadStruct_.erase(feMacroRunThreadStruct_.begin() + i);
3491 else if(now - group->startTime_ > 5 * 60 )
3493 std::string targets;
3494 std::string feMacroName;
3495 for(
const auto& t : group->tasks_)
3497 if(!targets.empty())
3499 targets += t->parameters_.feUIDSelected_;
3500 if(feMacroName.empty())
3501 feMacroName = t->parameters_.macroName_;
3503 __SUP_COUT_WARN__ <<
"Found old FE Macro group that has not completed"
3504 <<
" (groupID=" << group->groupID_ <<
", targets=["
3505 << targets <<
"], FE macro name=" << feMacroName <<
")"
3511 if(target_i >= feMacroRunThreadStruct_.size())
3514 <<
"Attempted to check recent FE Macro run completion with invalid ID="
3516 <<
". Perhaps this FE Macro completed more than 5 minutes ago?" << __E__;
3520 auto& targetGroup = feMacroRunThreadStruct_[target_i];
3521 if(targetGroup->allDone())
3523 __SUP_COUT__ <<
"Found all done for group NotDoneID = " << NotDoneID << __E__;
3524 for(
auto& task : targetGroup->tasks_)
3526 task->bar_->complete();
3529 for(
auto& task : targetGroup->tasks_)
3531 if(task->parameters_.feMacroRunError_ !=
"")
3533 __SUP_SS__ << task->parameters_.feMacroRunError_;
3540 std::ostringstream oss;
3541 for(
auto& task : targetGroup->tasks_)
3542 task->parameters_.xmldoc_.outputXmlDocument(&oss);
3543 __SUP_COUTT__ <<
"xmldoc: " << oss.str() << __E__;
3545 for(
auto& task : targetGroup->tasks_)
3547 __SUP_COUT__ <<
"FE macro group complete." << __E__;
3551 __SUP_COUT__ <<
"Found still going for group NotDoneID = " << NotDoneID
3554 xmldoc.addNumberElementToData(
"NotDoneID", NotDoneID);
3557 for(
auto& task : targetGroup->tasks_)
3559 DOMElement* progParent = xmldoc.addTextElementToData(
3560 "feMacroProgress", task->parameters_.feUIDSelected_);
3561 if(task->feMacroRunDone_)
3567 int rp = task->realProgress_.load();
3571 "progress", std::to_string(rp), progParent);
3576 "progress", std::to_string(task->bar_->read()), progParent);
3586 std::string feUIDSelected =
3589 std::string macroName =
3593 bool saveOutputs = CgiDataUtilities::getDataAsInt(cgi,
"saveOutputs") == 1;
3595 __SUP_COUTTV__(feClassSelected);
3596 __SUP_COUTTV__(feUIDSelected);
3597 __SUP_COUTTV__(macroType);
3598 __SUP_COUTTV__(macroName);
3599 __SUP_COUTTV__(inputArgs);
3600 __SUP_COUTTV__(outputArgs);
3601 __SUP_COUTTV__(saveOutputs);
3602 __SUP_COUTTV__(userInfo.username_);
3606 std::set<std::string> feUIDs;
3608 std::string expandUID = feUIDSelected.empty() ?
"*" : feUIDSelected;
3609 if(expandUID !=
"*")
3616 for(
auto& feTypePair : FEPluginTypetoFEsMap_)
3618 if(feClassSelected.empty() || feClassSelected ==
"*" ||
3619 feClassSelected == feTypePair.first)
3620 for(
auto& uid : feTypePair.second)
3621 feUIDs.emplace(uid);
3625 feUIDs.emplace(feUIDSelected);
3630 auto group = std::make_shared<runFEMacroGroupStruct>();
3631 group->historyFeClassSelected_ = feClassSelected.empty() ?
"*" : feClassSelected;
3632 group->historyFeUIDSelected_ = feUIDSelected.empty() ?
"*" : feUIDSelected;
3633 group->historyMacroType_ = macroType;
3634 group->historyMacroName_ = macroName;
3635 group->historyInputArgs_ = inputArgs;
3636 group->historyOutputArgs_ = outputArgs;
3637 group->historySaveOutputs_ = saveOutputs;
3638 group->historyUsername_ = userInfo.username_;
3639 for(
const std::string& uid : feUIDs)
3641 group->tasks_.push_back(std::make_shared<runFEMacroStruct>(
3654 std::lock_guard<std::mutex> lock(feMacroRunThreadStructMutex_);
3655 group->groupID_ = ++feMacroRunGroupIDCounter_;
3656 if(feMacroRunGroupIDCounter_ == 0)
3658 ++feMacroRunGroupIDCounter_;
3660 for(
auto& task : group->tasks_)
3662 task->bar_ = std::make_unique<ProgressBar>();
3663 task->bar_->reset(macroName, task->parameters_.feUIDSelected_);
3665 feMacroRunThreadStruct_.emplace_back(group);
3668 std::thread([group,
this]() {
3669 MacroMakerSupervisor::runFEMacroGroupSchedulerThread(group,
this);
3678 size_t sleepTime = 10 * 1000;
3681 for(
int i = 0; i < 2; ++i)
3683 if(group->allDone())
3685 __SUP_COUTT__ <<
"All FE macro tasks marked done" << __E__;
3686 for(
const auto& task : group->tasks_)
3687 if(task->parameters_.doneTime_ > group->completeTime_)
3688 group->completeTime_ = task->parameters_.doneTime_;
3693 __SUP_COUTT__ <<
"FE macros not all done, sleeping..." << __E__;
3698 if(!group->allDone())
3700 xmldoc.addNumberElementToData(
"NotDoneID", group->groupID_);
3704 std::lock_guard<std::mutex> lock(feMacroRunThreadStructMutex_);
3705 for(
auto& task : group->tasks_)
3707 DOMElement* progParent = xmldoc.addTextElementToData(
3708 "feMacroProgress", task->parameters_.feUIDSelected_);
3709 if(task->feMacroRunDone_)
3715 int rp = task->realProgress_.load();
3719 "progress", std::to_string(rp), progParent);
3724 "progress", std::to_string(task->bar_->read()), progParent);
3732 for(
auto& task : group->tasks_)
3734 if(task->parameters_.feMacroRunError_ !=
"")
3736 __SUP_SS__ << task->parameters_.feMacroRunError_;
3743 std::ostringstream oss;
3744 for(
auto& task : group->tasks_)
3745 task->parameters_.xmldoc_.outputXmlDocument(
3746 &oss,
false ,
true );
3747 __SUP_COUTT__ <<
"xmldoc: " << oss.str() << __E__;
3749 for(
auto& task : group->tasks_)
3753 std::lock_guard<std::mutex> lock(feMacroRunThreadStructMutex_);
3754 for(
size_t i = 0; i < feMacroRunThreadStruct_.size(); ++i)
3756 if(feMacroRunThreadStruct_[i].get() == group.get())
3758 feMacroRunThreadStruct_.erase(feMacroRunThreadStruct_.begin() + i);
3763 __SUP_COUT__ <<
"All FE macros complete." << __E__;
3766 std::lock_guard<std::mutex> lock(feMacroRunThreadStructMutex_);
3767 for(
const auto& g : feMacroRunThreadStruct_)
3768 __SUP_COUTT__ <<
"[] groupID_ = " << g->groupID_ << __E__;
3772 catch(
const std::runtime_error& e)
3774 __SUP_SS__ <<
"Error processing FE communication request: " << e.what() << __E__;
3775 __SUP_COUT_ERR__ << ss.str();
3776 xmldoc.addTextElementToData(
"Error", ss.str());
3780 __SUP_SS__ <<
"Unknown error processing FE communication request." << __E__;
3785 catch(
const std::exception& e)
3787 ss <<
"Exception message: " << e.what();
3792 __SUP_COUT_ERR__ << ss.str();
3794 xmldoc.addTextElementToData(
"Error", ss.str());
3799 void MacroMakerSupervisor::runFEMacroGroupSchedulerThread(
3803 if(!group || !mmSupervisor || group->tasks_.empty())
3806 __COUT__ <<
"FE macro group scheduler started. groupID=" << group->groupID_
3807 <<
" tasks=" << group->tasks_.size() << __E__;
3809 std::size_t maxThreads = StringMacros::getConcurrencyCount();
3812 if(maxThreads > group->tasks_.size())
3813 maxThreads = group->tasks_.size();
3815 std::vector<std::pair<std::shared_ptr<runFEMacroStruct>, std::future<void>>> active;
3816 active.reserve(maxThreads);
3817 std::size_t nextTaskIndex = 0;
3819 auto launchTask = [&](std::shared_ptr<runFEMacroStruct> task) {
3820 active.emplace_back(task, std::async(std::launch::async, [task, mmSupervisor]() {
3821 MacroMakerSupervisor::runFEMacroThread(task,
3826 while(nextTaskIndex < group->tasks_.size() || !active.empty())
3828 while(nextTaskIndex < group->tasks_.size() && active.size() < maxThreads)
3829 launchTask(group->tasks_[nextTaskIndex++]);
3832 std::lock_guard<std::mutex> lock(mmSupervisor->feMacroRunThreadStructMutex_);
3833 for(
const auto& activeTask : active)
3834 if(activeTask.first && !activeTask.first->feMacroRunDone_ &&
3835 activeTask.first->bar_)
3836 activeTask.first->bar_->step();
3839 bool anyFinished =
false;
3840 for(
size_t i = 0; i < active.size();)
3842 if(active[i].second.wait_for(std::chrono::milliseconds(0)) ==
3843 std::future_status::ready)
3845 __COUTT__ <<
"FE macro group scheduler task complete. groupID="
3847 <<
" uid=" << active[i].first->parameters_.feUIDSelected_
3849 active[i].second.get();
3850 active.erase(active.begin() + i);
3861 for(
const auto& task : group->tasks_)
3862 if(task->parameters_.doneTime_ > group->completeTime_)
3863 group->completeTime_ = task->parameters_.doneTime_;
3865 if(!group->historySaved_)
3867 mmSupervisor->appendCommandToHistory(group->historyFeClassSelected_,
3868 group->historyFeUIDSelected_,
3869 group->historyMacroType_,
3870 group->historyMacroName_,
3871 group->historyInputArgs_,
3872 group->historyOutputArgs_,
3873 group->historySaveOutputs_,
3874 group->historyUsername_,
3876 group->completeTime_);
3877 group->historySaved_ =
true;
3880 __COUT__ <<
"FE macro group scheduler ended. groupID=" << group->groupID_ << __E__;
3882 catch(
const std::exception& e)
3884 __SS__ <<
"Error during FE macro group scheduler thread: " << e.what() << __E__;
3885 __COUT_ERR__ << ss.str();
3889 __COUT_ERR__ <<
"Unknown error during FE macro group scheduler thread." << __E__;
3894 void MacroMakerSupervisor::runFEMacroThread(
3895 std::shared_ptr<runFEMacroStruct> feMacroRunThreadStruct,
3899 feMacroRunThreadStruct->parameters_.threadID_ =
3900 std::hash<std::thread::id>{}(std::this_thread::get_id());
3902 __COUT__ <<
"runFEMacro thread started... threadid = " << std::this_thread::get_id()
3903 <<
" " << mmSupervisor <<
" getpid()=" << getpid()
3904 <<
" gettid()=" << gettid() << __E__;
3906 mmSupervisor->runFEMacro(feMacroRunThreadStruct->parameters_.xmldoc_,
3907 feMacroRunThreadStruct->parameters_.feClassSelected_,
3908 feMacroRunThreadStruct->parameters_.feUIDSelected_,
3909 feMacroRunThreadStruct->parameters_.macroType_,
3910 feMacroRunThreadStruct->parameters_.macroName_,
3911 feMacroRunThreadStruct->parameters_.inputArgs_,
3912 feMacroRunThreadStruct->parameters_.outputArgs_,
3913 feMacroRunThreadStruct->parameters_.saveOutputs_,
3914 feMacroRunThreadStruct->parameters_.runningUsername_,
3915 feMacroRunThreadStruct->parameters_.userGroupPermissions_,
3917 &feMacroRunThreadStruct->realProgress_);
3919 feMacroRunThreadStruct->parameters_.doneTime_ = time(0);
3920 feMacroRunThreadStruct->feMacroRunDone_ =
true;
3921 __COUT__ <<
"runFEMacro thread done. threadid = " << std::this_thread::get_id()
3925 catch(
const std::runtime_error& e)
3927 __SS__ <<
"Error during runFEMacro thread: " << e.what() << __E__;
3928 __COUT_ERR__ << ss.str();
3929 feMacroRunThreadStruct->parameters_.feMacroRunError_ = ss.str();
3930 feMacroRunThreadStruct->parameters_.doneTime_ = time(0);
3931 feMacroRunThreadStruct->feMacroRunDone_ =
true;
3935 __SS__ <<
"Unknown error during runFEMacro thread." << __E__;
3940 catch(
const std::exception& e)
3942 ss <<
"Exception message: " << e.what();
3947 __COUT_ERR__ << ss.str();
3948 feMacroRunThreadStruct->parameters_.feMacroRunError_ = ss.str();
3949 feMacroRunThreadStruct->parameters_.doneTime_ = time(0);
3950 feMacroRunThreadStruct->feMacroRunDone_ =
true;
3955 std::string feClassSelected,
3956 std::string feUIDSelected,
3957 const std::string& macroType,
3958 const std::string& macroName,
3959 const std::string& inputArgs,
3960 const std::string outputArgs,
3962 const std::string& username,
3963 const std::string& userGroupPermissions,
3965 std::atomic<int>* realProgressOut)
3967 __SUP_COUTV__(feClassSelected);
3968 __SUP_COUTV__(feUIDSelected);
3969 __SUP_COUTV__(macroType);
3970 __SUP_COUTV__(macroName);
3971 __SUP_COUTV__(inputArgs);
3972 __SUP_COUTV__(outputArgs);
3973 __SUP_COUTV__(saveOutputs);
3974 __SUP_COUTV__(username);
3975 __SUP_COUTV__(userGroupPermissions);
3977 time_t launchTime = time(0);
3978 auto saveHistoryIfRequested = [&]() {
3982 appendCommandToHistory(feClassSelected,
3992 saveToHistory =
false;
3995 std::set<std::string > feUIDs;
3997 if(feUIDSelected ==
"")
3998 feUIDSelected =
"*";
3999 if(feClassSelected ==
"")
4000 feClassSelected =
"*";
4002 if(feClassSelected ==
"" || feUIDSelected ==
"" || macroType ==
"" || macroName ==
"")
4004 __SUP_SS__ <<
"Illegal empty front-end parameter." << __E__;
4007 else if(feUIDSelected !=
"*")
4014 if(feClassSelected ==
"*")
4016 for(
auto& feTypePair : FEPluginTypetoFEsMap_)
4017 for(
auto& feUID : feTypePair.second)
4018 feUIDs.emplace(feUID);
4022 auto typeIt = FEPluginTypetoFEsMap_.find(feClassSelected);
4023 if(typeIt == FEPluginTypetoFEsMap_.end())
4025 __SUP_SS__ <<
"Illegal front-end type parameter '" << feClassSelected
4026 <<
"' not in list of types." << __E__;
4030 for(
auto& feUID : typeIt->second)
4031 feUIDs.emplace(feUID);
4037 std::string macroString;
4038 if(macroType ==
"public")
4039 loadMacro(macroName, macroString);
4040 else if(macroType ==
"private")
4041 loadMacro(macroName, macroString, username);
4043 __SUP_COUTV__(macroString);
4050 std::string filename =
"/macroOutput_" + std::to_string(time(0)) +
"_" +
4051 std::to_string(clock()) +
".txt";
4053 __SUP_COUTV__(filename);
4054 fp = fopen((CodeEditor::OTSDAQ_DATA_PATH + filename).c_str(),
"w");
4057 __SUP_SS__ <<
"Failed to open file to save macro output '"
4058 << CodeEditor::OTSDAQ_DATA_PATH << filename <<
"'..." << __E__;
4062 fprintf(fp,
"############################\n");
4064 "### Running '%s' at time %s\n",
4068 "### \t Target front-ends (count=%lu): %s\n",
4071 fprintf(fp,
"### \t\t Inputs: %s\n", inputArgs.c_str());
4072 fprintf(fp,
"############################\n\n\n");
4074 xmldoc.addTextElementToData(
"feMacroRunArgs_name",
"Filename");
4075 xmldoc.addTextElementToData(
"feMacroRunArgs_value",
4076 "$OTSDAQ_DATA/" + filename);
4080 for(
auto& feUID : feUIDs)
4082 auto feIt = FEtoSupervisorMap_.find(feUID);
4083 if(feIt == FEtoSupervisorMap_.end())
4085 __SUP_SS__ <<
"Destination front end interface ID '" << feUID
4086 <<
"' was not found in the list of front ends." << __E__;
4087 ss <<
"\n\nHere is the map:\n\n"
4092 unsigned int FESupervisorIndex = feIt->second;
4093 __SUP_COUT__ <<
"Found supervisor index: " << FESupervisorIndex << __E__;
4095 SupervisorInfoMap::iterator it = allFESupervisorInfo_.find(FESupervisorIndex);
4096 if(it == allFESupervisorInfo_.end())
4099 <<
"Error transmitting request to FE Supervisor '" << feUID <<
":"
4100 << FESupervisorIndex <<
".' \n\n"
4101 <<
"The FE Supervisor Index does not exist. Have you configured "
4102 "the state machine properly?"
4109 if(macroType ==
"fe")
4110 txParameters.
addParameter(
"Request",
"RunInterfaceMacro");
4112 txParameters.
addParameter(
"Request",
"RunMacroMakerMacro");
4114 if(macroType ==
"fe")
4123 txParameters.
addParameter(
"userPermissions", userGroupPermissions);
4135 "Running '%s' at time %s\n",
4139 "\t Target front-end: '%s::%s'\n",
4140 FEtoPluginTypeMap_[feUID].c_str(),
4143 "\t\t Inputs: %s\n",
4148 xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply(
4149 it->second.getDescriptor(),
4150 "MacroMakerSupervisorRequest",
4153 SOAPUtilities::receive(retMsg, rxParameters);
4160 std::string notDoneTaskID = rxParameters.getValue(
"NotDoneTaskID");
4161 int asyncPollCount = 0;
4162 useconds_t pollSleepUs = 100 * 1000;
4163 if(!notDoneTaskID.empty())
4165 usleep(pollSleepUs);
4167 while(notDoneTaskID !=
"")
4175 xoap::MessageReference pollRetMsg =
4176 SOAPMessenger::sendWithSOAPReply(it->second.getDescriptor(),
4177 "MacroMakerSupervisorRequest",
4185 SOAPUtilities::receive(pollRetMsg, rxParameters);
4190 std::string progressStr = rxParameters.getValue(
"Progress");
4191 if(!progressStr.empty())
4192 realProgressOut->store(std::stoi(progressStr));
4195 notDoneTaskID = rxParameters.getValue(
"NotDoneTaskID");
4197 if(!notDoneTaskID.empty())
4199 usleep(pollSleepUs);
4201 if(pollSleepUs > 2000 * 1000 )
4202 pollSleepUs = 2000 * 1000;
4208 std::string outputResults = rxParameters.getValue(
"outputArgs");
4209 std::string error = rxParameters.getValue(
"Error");
4212 __SUP_COUTT__ <<
"outputArgs = " << outputResults << __E__;
4216 __SS__ <<
"Attempted FE Macro Failed. Attempted target "
4217 <<
"was UID=" << feUID
4218 <<
" at feSupervisorID=" << FESupervisorIndex <<
"." << __E__;
4219 ss <<
"\n\n The error was:\n\n" << error << __E__;
4220 __SUP_COUT_ERR__ <<
"\n" << ss.str();
4221 xmldoc.addTextElementToData(
"Error", ss.str());
4222 saveHistoryIfRequested();
4229 DOMElement* feMacroExecParent =
4230 xmldoc.addTextElementToData(
"feMacroExec", macroName);
4236 "fe_type", FEtoPluginTypeMap_[feUID], feMacroExecParent);
4238 "fe_context", it->second.getContextName(), feMacroExecParent);
4240 "fe_supervisor", it->second.getName(), feMacroExecParent);
4242 "fe_hostname", it->second.getHostname(), feMacroExecParent);
4244 std::istringstream inputStream(outputResults);
4245 std::string splitVal, argName, argValue;
4246 while(getline(inputStream, splitVal,
';'))
4248 std::istringstream pairInputStream(splitVal);
4249 getline(pairInputStream, argName,
',');
4250 getline(pairInputStream, argValue,
',');
4255 "\t\t Output '%s' = %s\n",
4262 "outputArgs_name", argName, feMacroExecParent);
4264 "outputArgs_value", argValue, feMacroExecParent);
4266 __SUP_COUTT__ << argName <<
": " << argValue << __E__;
4270 __SUP_COUTT__ <<
"runFEMacro() chk3." << __E__;
4277 saveHistoryIfRequested();
4284 saveHistoryIfRequested();
4286 __SUP_COUT__ <<
"runFEMacro() done." << __E__;
4293 const std::string& username)
4295 __SUP_COUT__ <<
"Getting FE Macro list" << __E__;
4298 txParameters.
addParameter(
"Request",
"GetInterfaceMacros");
4303 std::string oneInterface;
4304 std::string rxFEMacros;
4308 for(
auto& appInfo : allFESupervisorInfo_)
4310 __SUP_COUT__ <<
"FESupervisor LID = " << appInfo.second.getId()
4311 <<
" name = " << appInfo.second.getName() << __E__;
4313 xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply(
4314 appInfo.second.getDescriptor(),
"MacroMakerSupervisorRequest", txParameters);
4315 SOAPUtilities::receive(retMsg, rxParameters);
4317 rxFEMacros = rxParameters.getValue(
"FEMacros");
4319 __SUP_COUT__ <<
"FE Macros received: \n" << rxFEMacros << __E__;
4321 std::istringstream allInterfaces(rxFEMacros);
4322 while(std::getline(allInterfaces, oneInterface))
4326 xmldoc.addTextElementToData(
"FEMacros", oneInterface);
4332 std::pair<std::vector<std::string> ,
4333 std::vector<std::string> >
4335 loadMacroNames(username, macroNames);
4337 __SUP_COUT__ <<
"Public macro count: " << macroNames.first.size() << __E__;
4338 __SUP_COUT__ <<
"Private macro count: " << macroNames.second.size() << __E__;
4340 std::string macroString;
4349 for(
int i = 0; i < 2; ++i)
4350 for(
auto& macroName : (i ? macroNames.second : macroNames.first))
4353 loadMacro(macroName, macroString, username);
4358 std::stringstream xmlMacroStream;
4359 xmlMacroStream << macro.macroName_;
4360 xmlMacroStream <<
":"
4362 xmlMacroStream <<
":" << macro.namesOfInputArguments_.size();
4363 for(
auto& inputArg : macro.namesOfInputArguments_)
4364 xmlMacroStream <<
":" << inputArg;
4365 xmlMacroStream <<
":" << macro.namesOfOutputArguments_.size();
4366 for(
auto& inputArg : macro.namesOfOutputArguments_)
4367 xmlMacroStream <<
":" << inputArg;
4369 xmldoc.addTextElementToData(i ?
"PrivateMacro" :
"PublicMacro",
4370 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)