$treeview $search $mathjax $extrastylesheet
otsdaq_utilities
v2_03_00
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #include "otsdaq-utilities/MacroMaker/MacroMakerSupervisor.h" 00002 00003 //#include "otsdaq-core/MessageFacility/MessageFacility.h" 00004 //#include "otsdaq-core/Macros/CoutMacros.h" 00005 //#include "otsdaq-core/CgiDataUtilities/CgiDataUtilities.h" 00006 //#include "otsdaq-core/XmlUtilities/HttpXmlDocument.h" 00007 //#include "otsdaq-core/SOAPUtilities/SOAPUtilities.h" 00008 //#include "otsdaq-core/SOAPUtilities/SOAPParameters.h" 00009 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h" 00010 //#include "otsdaq-core/Macros/CoutMacros.h" 00011 00012 #include "otsdaq-core/FECore/FEVInterface.h" 00013 00014 #include "otsdaq-core/CodeEditor/CodeEditor.h" 00015 00016 //#include <xdaq/NamespaceURI.h> 00017 //#include <string> 00018 //#include <vector> 00019 //#include <iostream> 00020 #include <fstream> 00021 //#include <sstream> 00022 #include <dirent.h> //for DIR 00023 #include <stdio.h> //for file rename 00024 #include <sys/stat.h> //for mkdir 00025 #include <cstdio> 00026 #include <thread> //for std::thread 00027 #include "otsdaq-core/TableCore/TableGroupKey.h" 00028 00029 #define MACROS_DB_PATH std::string(getenv("SERVICE_DATA_PATH")) + "/MacroData/" 00030 #define MACROS_HIST_PATH std::string(getenv("SERVICE_DATA_PATH")) + "/MacroHistory/" 00031 #define MACROS_EXPORT_PATH std::string(getenv("SERVICE_DATA_PATH")) + "/MacroExport/" 00032 00033 using namespace ots; 00034 00035 #undef __MF_SUBJECT__ 00036 #define __MF_SUBJECT__ "MacroMaker" 00037 00038 XDAQ_INSTANTIATOR_IMPL(MacroMakerSupervisor) 00039 00040 //======================================================================================================================== 00041 MacroMakerSupervisor::MacroMakerSupervisor(xdaq::ApplicationStub* stub) 00042 : CoreSupervisorBase(stub) 00043 { 00044 INIT_MF("MacroMaker"); 00045 00046 // make macro directories in case they don't exist 00047 mkdir(((std::string)MACROS_DB_PATH).c_str(), 0755); 00048 mkdir(((std::string)MACROS_HIST_PATH).c_str(), 0755); 00049 mkdir(((std::string)MACROS_EXPORT_PATH).c_str(), 0755); 00050 00051 xoap::bind(this, 00052 &MacroMakerSupervisor::frontEndCommunicationRequest, 00053 "FECommunication", 00054 XDAQ_NS_URI); 00055 00056 init(); 00057 } 00058 00059 //======================================================================================================================== 00060 MacroMakerSupervisor::~MacroMakerSupervisor(void) { destroy(); } 00061 00062 //======================================================================================================================== 00063 void MacroMakerSupervisor::init(void) 00064 { 00065 // called by constructor 00066 00067 // MacroMaker should consider all FE compatible types.. 00068 allFESupervisorInfo_ = allSupervisorInfo_.getAllFETypeSupervisorInfo(); 00069 } 00070 00071 //======================================================================================================================== 00072 void MacroMakerSupervisor::destroy(void) 00073 { 00074 // called by destructor 00075 } 00076 00077 //======================================================================================================================== 00078 // forceSupervisorPropertyValues 00079 // override to force supervisor property values (and ignore user settings) 00080 void MacroMakerSupervisor::forceSupervisorPropertyValues() 00081 { 00082 // CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.NeedUsernameRequestTypes, 00083 // "getPermission"); 00084 } 00085 00086 //======================================================================================================================== 00087 void MacroMakerSupervisor::request(const std::string& requestType, 00088 cgicc::Cgicc& cgiIn, 00089 HttpXmlDocument& xmlOut, 00090 const WebUsers::RequestUserInfo& userInfo) try 00091 { 00092 __SUP_COUT__ << "User name is " << userInfo.username_ << "." << __E__; 00093 __SUP_COUT__ << "User permission level for request '" << requestType << "' is " 00094 << unsigned(userInfo.permissionLevel_) << "." << __E__; 00095 00096 // handle request per requestType 00097 if(requestType == "getPermission") 00098 { 00099 xmlOut.addTextElementToData("Permission", 00100 std::to_string(unsigned(userInfo.permissionLevel_))); 00101 00102 // create macro maker folders for the user (the first time a user authenticates 00103 // with macro maker) 00104 std::string macroPath = (std::string)MACROS_DB_PATH + userInfo.username_ + "/"; 00105 mkdir(macroPath.c_str(), 0755); 00106 std::string histPath = (std::string)MACROS_HIST_PATH + userInfo.username_ + "/"; 00107 mkdir(histPath.c_str(), 0755); 00108 std::string publicPath = (std::string)MACROS_DB_PATH + "publicMacros/"; 00109 mkdir(publicPath.c_str(), 0755); 00110 std::string exportPath = 00111 (std::string)MACROS_EXPORT_PATH + userInfo.username_ + "/"; 00112 mkdir(exportPath.c_str(), 0755); 00113 } 00114 else 00115 handleRequest(requestType, xmlOut, cgiIn, userInfo.username_); 00116 } 00117 catch(const std::runtime_error& e) 00118 { 00119 __SS__ << "Error occurred handling request '" << requestType << "': " << e.what() 00120 << __E__; 00121 __SUP_COUT__ << ss.str(); 00122 xmlOut.addTextElementToData("Error", ss.str()); 00123 } 00124 catch(...) 00125 { 00126 __SS__ << "Unknown error occurred handling request '" << requestType << "!'" << __E__; 00127 __SUP_COUT__ << ss.str(); 00128 xmlOut.addTextElementToData("Error", ss.str()); 00129 } 00130 00131 //======================================================================================================================== 00132 void MacroMakerSupervisor::handleRequest(const std::string Command, 00133 HttpXmlDocument& xmldoc, 00134 cgicc::Cgicc& cgi, 00135 const std::string& username) 00136 { 00137 if(Command == "FElist") //called by MacroMaker GUI 00138 getFElist(xmldoc); 00139 else if(Command == "writeData") //called by MacroMaker GUI 00140 writeData(xmldoc, cgi, username); 00141 else if(Command == "readData") //called by MacroMaker GUI 00142 readData(xmldoc, cgi, username); 00143 else if(Command == "createMacro") //called by MacroMaker GUI 00144 createMacro(xmldoc, cgi, username); 00145 else if(Command == "loadMacros") //called by MacroMaker GUI 00146 loadMacros(xmldoc, username); 00147 else if(Command == "loadHistory") //called by MacroMaker GUI 00148 loadHistory(xmldoc, username); 00149 else if(Command == "deleteMacro") //called by MacroMaker GUI 00150 deleteMacro(xmldoc, cgi, username); 00151 else if(Command == "editMacro") //called by MacroMaker GUI 00152 editMacro(xmldoc, cgi, username); 00153 else if(Command == "clearHistory") //called by MacroMaker GUI 00154 clearHistory(username); 00155 else if(Command == "exportMacro") //called by MacroMaker GUI 00156 exportMacro(xmldoc, cgi, username); 00157 else if(Command == "exportFEMacro") //called by MacroMaker GUI 00158 exportFEMacro(xmldoc, cgi, username); 00159 else if(Command == "getFEMacroList") //called by FE Macro Test and returns FE Macros and Macro Maker Macros 00160 getFEMacroList(xmldoc, username); 00161 else if(Command == "runFEMacro") //called by FE Macro Test returns FE Macros and Macro Maker Macros 00162 runFEMacro(xmldoc, cgi, username); 00163 else 00164 xmldoc.addTextElementToData("Error", "Unrecognized command '" + Command + "'"); 00165 } 00166 00167 //======================================================================================================================== 00168 xoap::MessageReference MacroMakerSupervisor::frontEndCommunicationRequest( 00169 xoap::MessageReference message) try 00170 { 00171 __SUP_COUT__ << "FE Request received: " << SOAPUtilities::translate(message) << __E__; 00172 00173 SOAPParameters typeParameter, rxParameters; // params for xoap to recv 00174 typeParameter.addParameter("type"); 00175 SOAPUtilities::receive(message, typeParameter); 00176 00177 std::string type = typeParameter.getValue("type"); 00178 00179 std::string error = ""; 00180 00181 if(type == "initFElist") // gateway initializes during configure 00182 { 00183 __SUP_COUTV__(type); 00184 00185 rxParameters.addParameter("groupName"); 00186 rxParameters.addParameter("groupKey"); 00187 SOAPUtilities::receive(message, rxParameters); 00188 00189 std::string groupName = rxParameters.getValue("groupName"); 00190 std::string groupKey = rxParameters.getValue("groupKey"); 00191 00192 __SUP_COUTV__(groupName); 00193 __SUP_COUTV__(groupKey); 00194 00195 ConfigurationManager cfgMgr; 00196 cfgMgr.loadTableGroup(groupName, TableGroupKey(groupKey), true); 00197 00198 // for each FESupervisor 00199 // get all front end children 00200 00201 const SupervisorInfoMap& feTypeSupervisors = 00202 CorePropertySupervisorBase::allSupervisorInfo_.getAllFETypeSupervisorInfo(); 00203 00204 ConfigurationTree appsNode = cfgMgr.getNode(ConfigurationManager::XDAQ_APPLICATION_TABLE_NAME); 00205 00206 __SUP_COUT__ << "Number of FE Supervisors found = " << 00207 feTypeSupervisors.size() << __E__; 00208 00209 FEPluginTypetoFEsMap_.clear(); //reset 00210 FEtoSupervisorMap_.clear(); //reset 00211 FEtoPluginTypeMap_.clear(); //reset 00212 for(auto& feApp : feTypeSupervisors) 00213 { 00214 __SUP_COUT__ << "FEs for app " << feApp.first << ":" << feApp.second.getName() 00215 << __E__; 00216 00217 auto feChildren = appsNode.getNode(feApp.second.getName()) 00218 .getNode("LinkToSupervisorTable") 00219 .getNode("LinkToFEInterfaceTable") 00220 .getChildren(); 00221 00222 for(auto& fe : feChildren) 00223 { 00224 __SUP_COUTV__(fe.first); 00225 FEtoSupervisorMap_[fe.first] = feApp.first; 00226 00227 std::string pluginType = 00228 fe.second.getNode("FEInterfacePluginName").getValue(); 00229 FEPluginTypetoFEsMap_[pluginType].emplace(fe.first); 00230 FEtoPluginTypeMap_[fe.first] = pluginType; 00231 } 00232 } 00233 00234 __SUP_COUTV__(StringMacros::mapToString(FEtoSupervisorMap_)); 00235 __SUP_COUTV__(StringMacros::mapToString(FEPluginTypetoFEsMap_)); 00236 __SUP_COUTV__(StringMacros::mapToString(FEtoPluginTypeMap_)); 00237 } 00238 else if(type == "feSend" || // from front-ends 00239 type == "feMacro" || // from front-ends 00240 type == "feMacroMultiDimensionalStart" || // from iterator 00241 type == "feMacroMultiDimensionalCheck" || // from iterator 00242 type == "macroMultiDimensionalStart" || // from iterator 00243 type == "macroMultiDimensionalCheck") // from iterator 00244 { 00245 __SUP_COUTV__(type); 00246 00247 rxParameters.addParameter("targetInterfaceID"); 00248 SOAPUtilities::receive(message, rxParameters); 00249 00250 std::string targetInterfaceID = rxParameters.getValue("targetInterfaceID"); 00251 00252 __SUP_COUTV__(targetInterfaceID); 00253 00254 auto feIt = FEtoSupervisorMap_.find(targetInterfaceID); 00255 if(feIt == FEtoSupervisorMap_.end()) 00256 { 00257 __SUP_SS__ << "Destination front end interface ID '" << targetInterfaceID 00258 << "' was not found in the list of front ends." << __E__; 00259 __SUP_SS_THROW__; 00260 } 00261 00262 unsigned int FESupervisorIndex = feIt->second; 00263 __SUP_COUT__ << "Found supervisor index: " << FESupervisorIndex << __E__; 00264 00265 SupervisorInfoMap::iterator it = allFESupervisorInfo_.find(FESupervisorIndex); 00266 if(it == allFESupervisorInfo_.end()) 00267 { 00268 __SUP_SS__ << "Error transmitting request to FE Supervisor '" 00269 << targetInterfaceID << ":" << FESupervisorIndex << ".' \n\n" 00270 << "The FE Supervisor Index does not exist. Have you configured " 00271 "the state machine properly?" 00272 << __E__; 00273 __SUP_SS_THROW__; 00274 } 00275 00276 if(type == "macroMultiDimensionalStart") 00277 { 00278 // add Macro sequence (and check macro exists) 00279 00280 SOAPParameters rxParameters; 00281 rxParameters.addParameter("macroName"); 00282 SOAPUtilities::receive(message, rxParameters); 00283 std::string macroName = rxParameters.getValue("macroName"); 00284 __SUP_COUTV__(macroName); 00285 00286 std::string macroString; 00287 loadMacro(macroName, macroString); 00288 00289 SOAPParameters parameters; 00290 parameters.addParameter("macroString", macroString); 00291 SOAPUtilities::addParameters(message, parameters); 00292 } 00293 00294 try 00295 { 00296 __SUP_COUT__ << "Forwarding request: " << SOAPUtilities::translate(message) 00297 << __E__; 00298 00299 xoap::MessageReference replyMessage = 00300 SOAPMessenger::sendWithSOAPReply(it->second.getDescriptor(), message); 00301 00302 if(type != "feSend") 00303 { 00304 __SUP_COUT__ << "Forwarding FE Macro response: " 00305 << SOAPUtilities::translate(replyMessage) << __E__; 00306 00307 return replyMessage; 00308 } 00309 } 00310 catch(const xdaq::exception::Exception& e) 00311 { 00312 __SUP_SS__ << "Error forwarding FE Communication request to FE Supervisor '" 00313 << targetInterfaceID << ":" << FESupervisorIndex << ".' " 00314 << "Have you configured the state machine properly?\n\n" 00315 << e.what() << __E__; 00316 __SUP_SS_THROW__; 00317 } 00318 } 00319 else 00320 { 00321 __SUP_SS__ << "Unrecognized FE Communication type: " << type << __E__; 00322 __SUP_SS_THROW__; 00323 } 00324 00325 return SOAPUtilities::makeSOAPMessageReference("Received"); 00326 } // end frontEndCommunicationRequest() 00327 catch(const std::runtime_error& e) 00328 { 00329 __SUP_SS__ << "Error processing FE communication request: " << e.what() << __E__; 00330 __SUP_COUT_ERR__ << ss.str(); 00331 00332 xoap::MessageReference returnMessage = 00333 SOAPUtilities::makeSOAPMessageReference("Error"); 00334 00335 SOAPParameters parameters; 00336 parameters.addParameter("Error", ss.str()); 00337 SOAPUtilities::addParameters(returnMessage, parameters); 00338 return returnMessage; 00339 } 00340 catch(...) 00341 { 00342 xoap::MessageReference returnMessage = 00343 SOAPUtilities::makeSOAPMessageReference("Error"); 00344 00345 __SUP_SS__ << "Unknown error processing FE communication request." << __E__; 00346 __SUP_COUT_ERR__ << ss.str(); 00347 00348 SOAPParameters parameters; 00349 parameters.addParameter("Error", ss.str()); 00350 SOAPUtilities::addParameters(returnMessage, parameters); 00351 return returnMessage; 00352 } // end frontEndCommunicationRequest() catch 00353 00354 //======================================================================================================================== 00355 void MacroMakerSupervisor::getFElist(HttpXmlDocument& xmldoc) 00356 { 00357 __SUP_COUT__ << "Getting FE list!!!!!!!!!" << __E__; 00358 00359 SOAPParameters txParameters; // params for xoap to send 00360 txParameters.addParameter("Request", "GetInterfaces"); 00361 00362 SOAPParameters rxParameters; // params for xoap to recv 00363 rxParameters.addParameter("FEList"); 00364 00365 SupervisorInfoMap::const_iterator it; 00366 std::string oneInterface; 00367 std::string rxFEList; 00368 00369 size_t lastColonIndex; 00370 00371 // for each list of FE Supervisors, 00372 // loop through each FE Supervisors and get FE interfaces list 00373 for(auto& appInfo : allFESupervisorInfo_) 00374 { 00375 // __SUP_COUT__ << "Number of " << listPair.first << " = " << 00376 // listPair.second.size() << __E__; 00377 // 00378 // for (it = listPair.second.begin(); it != listPair.second.end(); it++) 00379 // { 00380 00381 __SUP_COUT__ << "FESupervisor LID = " << appInfo.second.getId() 00382 << " name = " << appInfo.second.getName() << __E__; 00383 00384 try 00385 { 00386 xoap::MessageReference retMsg = 00387 SOAPMessenger::sendWithSOAPReply(appInfo.second.getDescriptor(), 00388 "MacroMakerSupervisorRequest", 00389 txParameters); 00390 SOAPUtilities::receive(retMsg, rxParameters); 00391 } 00392 catch(const xdaq::exception::Exception& e) 00393 { 00394 __SS__ << "Error transmitting request to FE Supervisor LID = " 00395 << appInfo.second.getId() << " name = " << appInfo.second.getName() 00396 << ". \n\n" 00397 << e.what() << __E__; 00398 __SUP_COUT_ERR__ << ss.str(); 00399 return; 00400 } 00401 00402 rxFEList = rxParameters.getValue("FEList"); 00403 00404 __SUP_COUT__ << "FE List received: \n" << rxFEList << __E__; 00405 00406 std::istringstream allInterfaces(rxFEList); 00407 while(std::getline(allInterfaces, oneInterface)) 00408 { 00409 __SUP_COUTV__(oneInterface); 00410 xmldoc.addTextElementToData("FE", oneInterface); 00411 00412 lastColonIndex = oneInterface.rfind(':'); 00413 if(lastColonIndex == std::string::npos) 00414 { 00415 __SUP_SS__ << "Last colon could not be found in " << oneInterface 00416 << __E__; 00417 __SS_THROW__; 00418 } 00419 oneInterface = oneInterface.substr(lastColonIndex); 00420 00421 __SUP_COUTV__(oneInterface); 00422 } // end FE extract loop 00423 00424 } // end ask Supervisors for their FE list loop 00425 00426 } // end getFEList() 00427 00428 //======================================================================================================================== 00429 void MacroMakerSupervisor::writeData(HttpXmlDocument& xmldoc, 00430 cgicc::Cgicc& cgi, 00431 const std::string& username) 00432 { 00433 __SUP_COUT__ << "MacroMaker writing..." << __E__; 00434 00435 std::string Address = CgiDataUtilities::getData(cgi, "Address"); 00436 std::string Data = CgiDataUtilities::getData(cgi, "Data"); 00437 std::string interfaceIndexArray = CgiDataUtilities::getData(cgi, "interfaceIndex"); 00438 std::string supervisorIndexArray = CgiDataUtilities::getData(cgi, "supervisorIndex"); 00439 std::string time = 00440 CgiDataUtilities::decodeURIComponent(CgiDataUtilities::getData(cgi, "time")); 00441 std::string addressFormatStr = CgiDataUtilities::getData(cgi, "addressFormatStr"); 00442 std::string dataFormatStr = CgiDataUtilities::getData(cgi, "dataFormatStr"); 00443 00444 std::string interfaces = CgiDataUtilities::postData(cgi, "interfaces"); 00445 00446 __SUP_COUT__ << "Write Address: " << Address << " Data: " << Data << __E__; 00447 __SUP_COUTV__(interfaces); 00448 00449 std::string command = "w:" + Address + ":" + Data; 00450 std::string format = addressFormatStr + ":" + dataFormatStr; 00451 appendCommandToHistory(command, format, time, interfaces, username); 00452 00453 SOAPParameters txParameters; // params for xoap to send 00454 txParameters.addParameter("Request", "UniversalWrite"); 00455 txParameters.addParameter("Address", Address); 00456 txParameters.addParameter("Data", Data); 00457 00458 __SUP_COUT__ << "Here comes the array from multiselect box for WRITE, behold: \n" 00459 << supervisorIndexArray << "\n" 00460 << interfaceIndexArray << __E__; 00461 00464 std::vector<std::string> interfaceIndices; 00465 std::istringstream f(interfaceIndexArray); 00466 std::string s; 00467 while(getline(f, s, ',')) 00468 interfaceIndices.push_back(s); 00469 std::vector<int> supervisorIndices; 00470 std::istringstream g(supervisorIndexArray); 00471 std::string t; 00472 while(getline(g, t, ',')) 00473 supervisorIndices.push_back(std::stoi(t)); 00474 00475 for(unsigned int i = 0; i < supervisorIndices.size(); i++) 00476 { 00477 unsigned int FESupervisorIndex = supervisorIndices[i]; 00478 std::string interfaceIndex = interfaceIndices[i]; 00479 00480 txParameters.addParameter("InterfaceID", interfaceIndex); 00481 00482 __SUP_COUT__ << "The index of the supervisor instance is: " << FESupervisorIndex 00483 << __E__; 00484 __SUP_COUT__ << "...and the interface ID is: " << interfaceIndex << __E__; 00485 00486 SupervisorInfoMap::iterator it = allFESupervisorInfo_.find(FESupervisorIndex); 00487 if(it == allFESupervisorInfo_.end()) 00488 { 00489 __SUP_SS__ << "Error transmitting request to FE Supervisor '" 00490 << interfaceIndex << ":" << FESupervisorIndex << ".' \n\n" 00491 << "The FE Index doesn't exist. Have you configured the state " 00492 "machine properly?" 00493 << __E__; 00494 __SUP_SS_THROW__; 00495 } 00496 00497 try 00498 { 00499 xoap::MessageReference replyMessage = SOAPMessenger::sendWithSOAPReply( 00500 it->second.getDescriptor(), "MacroMakerSupervisorRequest", txParameters); 00501 00502 __SUP_COUT__ << "Response received: " 00503 << SOAPUtilities::translate(replyMessage) << __E__; 00504 00505 SOAPParameters rxParameters; 00506 rxParameters.addParameter("Error"); 00507 SOAPUtilities::receive(replyMessage, rxParameters); 00508 00509 std::string error = rxParameters.getValue("Error"); 00510 __SUP_COUTV__(error); 00511 00512 if(error != "") 00513 { 00514 // error occurred! 00515 __SUP_SS__ << "Error transmitting request to FE Supervisor '" 00516 << interfaceIndex << ":" << FESupervisorIndex << ".' " 00517 << "Have you configured the state machine properly?\n\n" 00518 << error << __E__; 00519 __SUP_SS_THROW__; 00520 } 00521 } 00522 catch(const xdaq::exception::Exception& e) 00523 { 00524 __SUP_SS__ << "Error transmitting request to FE Supervisor '" 00525 << interfaceIndex << ":" << FESupervisorIndex << ".' " 00526 << "Have you configured the state machine properly?\n\n" 00527 << e.what() << __E__; 00528 __SUP_SS_THROW__; 00529 } 00530 00531 } // end FE Supervisor loop 00532 } // end writeData() 00533 00534 //======================================================================================================================== 00535 void MacroMakerSupervisor::readData(HttpXmlDocument& xmldoc, 00536 cgicc::Cgicc& cgi, 00537 const std::string& username) 00538 { 00539 __SUP_COUT__ << "@@@@@@@ MacroMaker wants to read data @@@@@@@@" << __E__; 00540 std::string Address = CgiDataUtilities::getData(cgi, "Address"); 00541 std::string interfaceIndexArray = CgiDataUtilities::getData(cgi, "interfaceIndex"); 00542 std::string supervisorIndexArray = CgiDataUtilities::getData(cgi, "supervisorIndex"); 00543 std::string time = 00544 CgiDataUtilities::decodeURIComponent(CgiDataUtilities::getData(cgi, "time")); 00545 std::string addressFormatStr = CgiDataUtilities::getData(cgi, "addressFormatStr"); 00546 std::string dataFormatStr = CgiDataUtilities::getData(cgi, "dataFormatStr"); 00547 00548 std::string interfaces = CgiDataUtilities::postData(cgi, "interfaces"); 00549 00550 __SUP_COUT__ << "Read Address: " << Address << __E__; 00551 __SUP_COUTV__(interfaces); 00552 00553 SOAPParameters txParameters; // params for xoap to send 00554 txParameters.addParameter("Request", "UniversalRead"); 00555 txParameters.addParameter("Address", Address); 00556 00557 SOAPParameters rxParameters; 00558 rxParameters.addParameter("dataResult"); 00559 rxParameters.addParameter("Error"); 00560 __SUP_COUT__ << "Here comes the array from multiselect box for READ, behold: " 00561 << supervisorIndexArray << "," << interfaceIndexArray << __E__; 00562 00565 std::vector<std::string> interfaceIndices; 00566 std::istringstream f(interfaceIndexArray); 00567 std::string s; 00568 while(getline(f, s, ',')) 00569 interfaceIndices.push_back(s); 00570 std::vector<int> supervisorIndices; 00571 std::istringstream g(supervisorIndexArray); 00572 std::string t; 00573 while(getline(g, t, ',')) 00574 supervisorIndices.push_back(std::stoi(t)); 00575 00576 for(unsigned int i = 0; i < supervisorIndices.size(); i++) 00577 { 00578 unsigned int FESupervisorIndex = supervisorIndices[i]; 00579 std::string interfaceIndex = interfaceIndices[i]; 00580 00581 txParameters.addParameter("InterfaceID", interfaceIndex); 00582 00583 __SUP_COUT__ << "The index of the supervisor instance is: " << FESupervisorIndex 00584 << __E__; 00585 __SUP_COUT__ << "...and the interface ID is: " << interfaceIndex << __E__; 00586 00587 SupervisorInfoMap::iterator it = allFESupervisorInfo_.find(FESupervisorIndex); 00588 if(it == allFESupervisorInfo_.end()) 00589 { 00590 __SUP_SS__ << "Error transmitting request to FE Supervisor '" 00591 << interfaceIndex << ":" << FESupervisorIndex << ".' \n\n" 00592 << "The FE Index doesn't exist. Have you configured the state " 00593 "machine properly?" 00594 << __E__; 00595 __SUP_SS_THROW__; 00596 } 00597 00598 try 00599 { 00600 xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply( 00601 it->second.getDescriptor(), "MacroMakerSupervisorRequest", txParameters); 00602 00603 __SUP_COUT__ << "Response received: " << SOAPUtilities::translate(retMsg) 00604 << __E__; 00605 00606 // SOAPParameters rxParameters; 00607 // rxParameters.addParameter("Error"); 00608 SOAPUtilities::receive(retMsg, rxParameters); 00609 00610 std::string error = rxParameters.getValue("Error"); 00611 __SUP_COUTV__(error); 00612 00613 if(error != "") 00614 { 00615 // error occurred! 00616 __SUP_SS__ << "Error transmitting request to FE Supervisor '" 00617 << interfaceIndex << ":" << FESupervisorIndex << ".' " 00618 << "Have you configured the state machine properly?\n\n" 00619 << error << __E__; 00620 __SUP_SS_THROW__; 00621 } 00622 } 00623 catch(const xdaq::exception::Exception& e) 00624 { 00625 __SUP_SS__ << "Error transmitting request to FE Supervisor '" 00626 << interfaceIndex << ":" << FESupervisorIndex << ".' " 00627 << "Have you configured the state machine properly?\n\n" 00628 << e.what() << __E__; 00629 __SUP_SS_THROW__; 00630 } 00631 00632 std::string dataReadResult = rxParameters.getValue("dataResult"); 00633 __SUP_COUT__ << "Data reading result received: " << dataReadResult << __E__; 00634 xmldoc.addTextElementToData("readData", dataReadResult); 00635 std::string command = "r:" + Address + ":" + dataReadResult; 00636 std::string format = addressFormatStr + ":" + dataFormatStr; 00637 appendCommandToHistory(command, format, time, interfaces, username); 00638 } 00639 } 00640 00641 //======================================================================================================================== 00642 void MacroMakerSupervisor::createMacro(HttpXmlDocument& xmldoc, 00643 cgicc::Cgicc& cgi, 00644 const std::string& username) 00645 { 00646 __SUP_COUT__ << "MacroMaker wants to create a macro!!!!!!!!!" << __E__; 00647 std::string Name = CgiDataUtilities::postData(cgi, "Name"); 00648 std::string Sequence = CgiDataUtilities::postData(cgi, "Sequence"); 00649 std::string Time = CgiDataUtilities::postData(cgi, "Time"); 00650 std::string Notes = 00651 CgiDataUtilities::decodeURIComponent(CgiDataUtilities::postData(cgi, "Notes")); 00652 std::string isMacroPublic = CgiDataUtilities::getData(cgi, "isPublic"); 00653 std::string isMacroLSBF = CgiDataUtilities::getData(cgi, "isLSBF"); 00654 00655 __SUP_COUTV__(Name); 00656 __SUP_COUTV__(Sequence); 00657 __SUP_COUTV__(Notes); 00658 __SUP_COUTV__(Time); 00659 __SUP_COUTV__(isMacroPublic); 00660 __SUP_COUTV__(isMacroLSBF); 00661 00662 __SUP_COUTV__(MACROS_DB_PATH); 00663 00664 std::string fileName = Name + ".dat"; 00665 std::string fullPath; 00666 if(isMacroPublic == "true") 00667 fullPath = (std::string)MACROS_DB_PATH + "publicMacros/" + fileName; 00668 else 00669 fullPath = (std::string)MACROS_DB_PATH + username + "/" + fileName; 00670 00671 __SUP_COUTV__(fullPath); 00672 00673 std::ofstream macrofile(fullPath.c_str()); 00674 if(macrofile.is_open()) 00675 { 00676 macrofile << "{\n"; 00677 macrofile << "\"name\":\"" << Name << "\",\n"; 00678 macrofile << "\"sequence\":\"" << Sequence << "\",\n"; 00679 macrofile << "\"time\":\"" << Time << "\",\n"; 00680 macrofile << "\"notes\":\"" << Notes << "\",\n"; 00681 macrofile << "\"LSBF\":\"" << isMacroLSBF << "\"\n"; 00682 macrofile << "}@" << __E__; 00683 macrofile.close(); 00684 } 00685 else 00686 __SUP_COUT__ << "Unable to open file" << __E__; 00687 } // end createMacro() 00688 00689 //======================================================================================================================== 00690 // loadMacro 00691 // Load macro string from file. 00692 // look in public macros and username (if given) 00693 // for the macroName. 00694 // 00695 // If found, return by reference 00696 // Else, throw exception 00697 void MacroMakerSupervisor::loadMacro(const std::string& macroName, 00698 std::string& macroString, 00699 const std::string& username /*=""*/) 00700 { 00701 __SUP_COUTV__(macroName); 00702 00703 // first check public folder, then user 00704 std::string fullPath, line; 00705 macroString = ""; 00706 for(unsigned int i = 0; i < 2; ++i) 00707 { 00708 if(i == 1) 00709 fullPath = (std::string)MACROS_DB_PATH + username + "/"; 00710 else 00711 fullPath = (std::string)MACROS_DB_PATH + "publicMacros/"; 00712 00713 fullPath += macroName; 00714 if(macroName.find(".dat") != macroName.size() - 4) 00715 fullPath += ".dat"; 00716 __SUP_COUTV__(fullPath); 00717 00718 std::ifstream read(fullPath.c_str()); // reading a file 00719 if(read.is_open()) 00720 { 00721 while(!read.eof()) 00722 { 00723 getline(read, line); 00724 macroString += line; 00725 } 00726 00727 read.close(); 00728 } 00729 else // file does not exist 00730 { 00731 __SUP_COUT__ << "Unable to open file: " << fullPath << __E__; 00732 continue; 00733 } 00734 00735 if(macroString != "") 00736 break; // macro has been found! 00737 } // end load from path loop 00738 00739 if(macroString == "") 00740 { 00741 __SUP_SS__ << "Unable to locate file for macro '" << macroName 00742 << "'... does it exist?" << __E__; 00743 if(username != "") 00744 ss << " Attempted username was '" << username << ".'" << __E__; 00745 __SUP_SS_THROW__; 00746 } 00747 00748 __SUP_COUTV__(macroString); 00749 } // end loadMacro() 00750 00751 //======================================================================================================================== 00752 void MacroMakerSupervisor::loadMacroNames( 00753 const std::string& username, 00754 std::pair<std::vector<std::string> /*public macros*/, 00755 std::vector<std::string> /*private macros*/>& returnMacroNames) 00756 { 00757 DIR* dir; 00758 struct dirent* ent; 00759 std::string fullPath = (std::string)MACROS_DB_PATH + username + "/"; 00760 if((dir = opendir(fullPath.c_str())) != NULL) 00761 { 00762 /* print all the files and directories within directory */ 00763 while((ent = readdir(dir)) != NULL) 00764 { 00765 /* File name validation check */ 00766 if((unsigned)strlen(ent->d_name) > 4) 00767 { 00768 std::string line; 00769 std::ifstream read( 00770 ((fullPath + (std::string)ent->d_name)).c_str()); // reading a file 00771 if(read.is_open()) 00772 { 00773 read.close(); 00774 //private macro found 00775 returnMacroNames.second.push_back(ent->d_name); 00776 } 00777 else 00778 __SUP_COUT__ << "Unable to open file" << __E__; 00779 } 00780 } 00781 closedir(dir); 00782 } 00783 else 00784 { 00785 __SUP_COUT__ << "Looping through privateMacros folder failed! Wrong directory" 00786 << __E__; 00787 } 00788 fullPath = (std::string)MACROS_DB_PATH + "publicMacros/"; 00789 if((dir = opendir(fullPath.c_str())) != NULL) 00790 { 00791 /* print all the files and directories within directory */ 00792 while((ent = readdir(dir)) != NULL) 00793 { 00794 /* File name validation check */ 00795 if((unsigned)strlen(ent->d_name) > 4) 00796 { 00797 std::string line; 00798 std::ifstream read( 00799 ((fullPath + (std::string)ent->d_name)).c_str()); // reading a file 00800 if(read.is_open()) 00801 { 00802 //public macro found 00803 returnMacroNames.first.push_back(ent->d_name); 00804 read.close(); 00805 } 00806 else 00807 __SUP_COUT__ << "Unable to open file" << __E__; 00808 } 00809 } 00810 closedir(dir); 00811 } 00812 else 00813 { 00814 __SUP_COUT__ << fullPath << __E__; 00815 __SUP_COUT__ << "Looping through MacroData folder failed! Wrong directory" 00816 << __E__; 00817 } 00818 00819 } //end loadMacroNames 00820 00821 //======================================================================================================================== 00822 void MacroMakerSupervisor::loadMacros(HttpXmlDocument& xmldoc, 00823 const std::string& username) 00824 { 00825 DIR* dir; 00826 struct dirent* ent; 00827 std::string returnStr = ""; 00828 std::string fullPath = (std::string)MACROS_DB_PATH + username + "/"; 00829 if((dir = opendir(fullPath.c_str())) != NULL) 00830 { 00831 /* print all the files and directories within directory */ 00832 while((ent = readdir(dir)) != NULL) 00833 { 00834 /* File name validation check */ 00835 if((unsigned)strlen(ent->d_name) > 4) 00836 { 00837 std::string line; 00838 std::ifstream read( 00839 ((fullPath + (std::string)ent->d_name)).c_str()); // reading a file 00840 if(read.is_open()) 00841 { 00842 std::stringstream buffer; 00843 while(!read.eof()) 00844 { 00845 getline(read, line); 00846 buffer << line; 00847 //__SUP_COUT__ << line << __E__; 00848 } 00849 returnStr += buffer.str(); 00850 00851 read.close(); 00852 } 00853 else 00854 __SUP_COUT__ << "Unable to open file" << __E__; 00855 } 00856 } 00857 std::string returnMacroStr = returnStr.substr(0, returnStr.size() - 1); 00858 00859 __SUP_COUT__ << "Loading existing macros! " << returnMacroStr << __E__; 00860 00861 closedir(dir); 00862 xmldoc.addTextElementToData("returnMacroStr", returnMacroStr); 00863 } 00864 else 00865 { 00866 __SUP_COUT__ << "Looping through privateMacros folder failed! Wrong directory" 00867 << __E__; 00868 } 00869 fullPath = (std::string)MACROS_DB_PATH + "publicMacros/"; 00870 returnStr = ""; 00871 if((dir = opendir(fullPath.c_str())) != NULL) 00872 { 00873 /* print all the files and directories within directory */ 00874 while((ent = readdir(dir)) != NULL) 00875 { 00876 /* File name validation check */ 00877 if((unsigned)strlen(ent->d_name) > 4) 00878 { 00879 std::string line; 00880 std::ifstream read( 00881 ((fullPath + (std::string)ent->d_name)).c_str()); // reading a file 00882 if(read.is_open()) 00883 { 00884 std::stringstream buffer; 00885 while(!read.eof()) 00886 { 00887 getline(read, line); 00888 buffer << line; 00889 //__SUP_COUT__ << line << __E__; 00890 } 00891 returnStr += buffer.str(); 00892 read.close(); 00893 } 00894 else 00895 __SUP_COUT__ << "Unable to open file" << __E__; 00896 } 00897 } 00898 std::string returnPublicStr = returnStr.substr(0, returnStr.size() - 1); 00899 __SUP_COUT__ << "Loading existing public macros: " << returnPublicStr << __E__; 00900 closedir(dir); 00901 xmldoc.addTextElementToData("returnPublicStr", returnPublicStr); 00902 } 00903 else 00904 { 00905 __SUP_COUT__ << fullPath << __E__; 00906 __SUP_COUT__ << "Looping through MacroData folder failed! Wrong directory" 00907 << __E__; 00908 } 00909 } // end loadMacros() 00910 00911 //======================================================================================================================== 00912 void MacroMakerSupervisor::appendCommandToHistory(std::string Command, 00913 std::string Format, 00914 std::string Time, 00915 std::string Interfaces, 00916 const std::string& username) 00917 { 00918 std::string fileName = "history.hist"; 00919 std::string fullPath = (std::string)MACROS_HIST_PATH + username + "/" + fileName; 00920 __SUP_COUT__ << fullPath << __E__; 00921 std::ofstream histfile(fullPath.c_str(), std::ios::app); 00922 if(histfile.is_open()) 00923 { 00924 histfile << "{\n"; 00925 histfile << "\"Command\":\"" << Command << "\",\n"; 00926 histfile << "\"Format\":\"" << Format << "\",\n"; 00927 histfile << "\"Time\":\"" << Time << "\",\n"; 00928 histfile << "\"Interfaces\":\"" << Interfaces << "\"\n"; 00929 histfile << "}#" << __E__; 00930 histfile.close(); 00931 } 00932 else 00933 __SUP_COUT__ << "Unable to open history.hist" << __E__; 00934 } 00935 00936 //======================================================================================================================== 00937 void MacroMakerSupervisor::loadHistory(HttpXmlDocument& xmldoc, 00938 const std::string& username) 00939 { 00940 std::string fileName = MACROS_HIST_PATH + username + "/" + "history.hist"; 00941 00942 std::ifstream read(fileName.c_str()); // reading a file 00943 __SUP_COUT__ << fileName << __E__; 00944 00945 if(read.is_open()) 00946 { 00947 std::string line; 00948 char* returnStr; 00949 unsigned long long fileSz, i = 0, MAX_HISTORY_SIZE = 100000; 00950 00951 // get length of file to reserve the string size 00952 // and to cap history size 00953 read.seekg(0, std::ios::end); 00954 fileSz = read.tellg(); 00955 returnStr = new char[fileSz + 1]; 00956 returnStr[fileSz] = '\0'; 00957 read.seekg(0, std::ios::beg); 00958 00959 // read data as a block: 00960 read.read(returnStr, fileSz); 00961 read.close(); 00962 00963 // find i such that new string size is less than 00964 if(fileSz > MAX_HISTORY_SIZE) 00965 { 00966 i = fileSz - MAX_HISTORY_SIZE; 00967 for(; i < fileSz; ++i) 00968 if(returnStr[i] == '#') 00969 { 00970 i += 2; 00971 break; // skip new line character also to get to next record 00972 } 00973 if(i > fileSz) 00974 i = fileSz; 00975 00976 // write back to file truncated history 00977 FILE* fp = fopen(fileName.c_str(), "w"); 00978 if(!fp) 00979 { 00980 __SS__ << "Big problem with macromaker history file: " << fileName 00981 << __E__; 00982 __SS_THROW__; 00983 } 00984 fwrite(&returnStr[i], fileSz - i, 1, fp); 00985 fclose(fp); 00986 } 00987 00988 __SUP_COUT__ << "Loading user history! " << __E__; 00989 00990 if(fileSz > 1) 00991 returnStr[fileSz - 2] = '\0'; // remove final newline and last # 00992 00993 xmldoc.addTextElementToData("returnHistStr", &returnStr[i]); 00994 00995 delete[] returnStr; 00996 } 00997 else 00998 00999 __SUP_COUT__ << "Unable to open history.hist" << __E__; 01000 } 01001 01002 //======================================================================================================================== 01003 void MacroMakerSupervisor::deleteMacro(HttpXmlDocument& xmldoc, 01004 cgicc::Cgicc& cgi, 01005 const std::string& username) 01006 { 01007 std::string MacroName = CgiDataUtilities::getData(cgi, "MacroName"); 01008 std::string isMacroPublic = CgiDataUtilities::getData(cgi, "isPublic"); 01009 01010 std::string fileName = MacroName + ".dat"; 01011 std::string fullPath; 01012 if(isMacroPublic == "true") 01013 fullPath = (std::string)MACROS_DB_PATH + "publicMacros/" + fileName; 01014 else 01015 fullPath = (std::string)MACROS_DB_PATH + username + "/" + fileName; 01016 01017 __SUP_COUT__ << fullPath << __E__; 01018 01019 std::remove(fullPath.c_str()); 01020 __SUP_COUT__ << "Successfully deleted " << MacroName; 01021 xmldoc.addTextElementToData("deletedMacroName", MacroName); 01022 } 01023 01024 //======================================================================================================================== 01025 void MacroMakerSupervisor::editMacro(HttpXmlDocument& xmldoc, 01026 cgicc::Cgicc& cgi, 01027 const std::string& username) 01028 { 01029 std::string oldMacroName = CgiDataUtilities::postData(cgi, "oldMacroName"); 01030 std::string newMacroName = CgiDataUtilities::postData(cgi, "newMacroName"); 01031 std::string Sequence = CgiDataUtilities::postData(cgi, "Sequence"); 01032 std::string Time = CgiDataUtilities::postData(cgi, "Time"); 01033 std::string Notes = 01034 CgiDataUtilities::decodeURIComponent(CgiDataUtilities::postData(cgi, "Notes")); 01035 01036 std::string isMacroPublic = CgiDataUtilities::getData(cgi, "isPublic"); 01037 std::string isMacroLSBF = CgiDataUtilities::getData(cgi, "isLSBF"); 01038 01039 __SUP_COUTV__(oldMacroName); 01040 __SUP_COUTV__(newMacroName); 01041 __SUP_COUTV__(Sequence); 01042 __SUP_COUTV__(Notes); 01043 __SUP_COUTV__(Time); 01044 __SUP_COUTV__(isMacroPublic); 01045 __SUP_COUTV__(isMacroLSBF); 01046 01047 __SUP_COUTV__(MACROS_DB_PATH); 01048 01049 std::string fileName = oldMacroName + ".dat"; 01050 std::string fullPath; 01051 if(isMacroPublic == "true") 01052 fullPath = (std::string)MACROS_DB_PATH + "publicMacros/" + fileName; 01053 else 01054 fullPath = (std::string)MACROS_DB_PATH + username + "/" + fileName; 01055 01056 __SUP_COUTV__(fullPath); 01057 01058 std::ofstream macrofile(fullPath.c_str()); 01059 if(macrofile.is_open()) 01060 { 01061 macrofile << "{\n"; 01062 macrofile << "\"name\":\"" << newMacroName << "\",\n"; 01063 macrofile << "\"sequence\":\"" << Sequence << "\",\n"; 01064 macrofile << "\"time\":\"" << Time << "\",\n"; 01065 macrofile << "\"notes\":\"" << Notes << "\",\n"; 01066 macrofile << "\"LSBF\":\"" << isMacroLSBF << "\"\n"; 01067 macrofile << "}@" << __E__; 01068 macrofile.close(); 01069 } 01070 else 01071 __SUP_COUT__ << "Unable to open file" << __E__; 01072 01073 if(oldMacroName != newMacroName) // renaming macro 01074 { 01075 int result; 01076 result = 01077 rename((MACROS_DB_PATH + username + "/" + oldMacroName + ".dat").c_str(), 01078 (MACROS_DB_PATH + username + "/" + newMacroName + ".dat").c_str()); 01079 if(result == 0) 01080 xmldoc.addTextElementToData("newMacroName", newMacroName); 01081 else 01082 xmldoc.addTextElementToData("newMacroName", "ERROR"); 01083 } 01084 } 01085 01086 //======================================================================================================================== 01087 void MacroMakerSupervisor::clearHistory(const std::string& username) 01088 { 01089 std::string fileName = "history.hist"; 01090 std::string fullPath = (std::string)MACROS_HIST_PATH + username + "/" + fileName; 01091 01092 std::remove(fullPath.c_str()); 01093 __SUP_COUT__ << "Successfully deleted " << fullPath; 01094 } 01095 01096 //======================================================================================================================== 01097 void MacroMakerSupervisor::exportFEMacro(HttpXmlDocument& xmldoc, 01098 cgicc::Cgicc& cgi, 01099 const std::string& username) 01100 { 01101 std::string macroName = CgiDataUtilities::getData(cgi, "MacroName"); 01102 std::string pluginName = CgiDataUtilities::getData(cgi, "PluginName"); 01103 std::string macroSequence = CgiDataUtilities::postData(cgi, "MacroSequence"); 01104 std::string macroNotes = CgiDataUtilities::decodeURIComponent( 01105 CgiDataUtilities::postData(cgi, "MacroNotes")); 01106 01107 __SUP_COUTV__(pluginName); 01108 __SUP_COUTV__(macroName); 01109 __SUP_COUTV__(macroSequence); 01110 01111 // replace all special characters with white space 01112 for(unsigned int i = 0; i < macroNotes.length(); ++i) 01113 if(macroNotes[i] == '\r' || macroNotes[i] == '\n') 01114 macroNotes[i] = ' '; 01115 __SUP_COUTV__(macroNotes); 01116 01117 std::stringstream ss(macroSequence); 01118 std::string command; 01119 std::vector<std::string> commands; 01120 01121 while(getline(ss, command, ',')) 01122 commands.push_back(command); 01123 01124 __SUP_COUTV__(StringMacros::vectorToString(commands)); 01125 01126 std::map<std::string /*special type*/, std::set<std::string> /*special file paths*/> 01127 specialsCodeMap = CodeEditor::getSpecialsMap(); 01128 01129 //__SUP_COUTV__(StringMacros::mapToString(specialsCodeMap)); 01130 auto specialsCodeMapIt = specialsCodeMap.find(CodeEditor::SPECIAL_TYPE_FEInterface); 01131 if(specialsCodeMapIt == specialsCodeMap.end()) 01132 { 01133 __SS__ 01134 << "Could not find any FE Interface plugins in source code. Does MacroMaker " 01135 << "have access to the source code? Check that the Supervisor context places " 01136 "MacroMaker in a " 01137 << "location with access to the source code." << __E__; 01138 __SS_THROW__; 01139 } 01140 01141 // find first .h and .cc with the plugin name 01142 std::string headerFile = pluginName + ".h"; 01143 std::string sourceFile = pluginName + "_interface.cc"; 01144 bool foundHeaderFile = false; 01145 bool foundSourceFile = false; 01146 for(const auto& filePath : specialsCodeMapIt->second) 01147 { 01148 if(!foundHeaderFile && filePath.find(headerFile) != std::string::npos) 01149 { 01150 foundHeaderFile = true; 01151 headerFile = filePath; 01152 __SUP_COUT__ << "found headerFile=" << filePath << __E__; 01153 } 01154 if(!foundSourceFile && filePath.find(sourceFile) != std::string::npos) 01155 { 01156 foundSourceFile = true; 01157 sourceFile = filePath; 01158 __SUP_COUT__ << "found sourceFile=" << filePath << __E__; 01159 } 01160 01161 if(foundSourceFile && foundHeaderFile) 01162 break; 01163 } // end file search loop 01164 01165 if(!foundHeaderFile) 01166 { 01167 __SS__ << "Could not find the header file for the FE Interface plugins at '" 01168 << headerFile << ".' Does MacroMaker " 01169 << "have access to the source code? Check that the Supervisor context " 01170 "places MacroMaker in a " 01171 << "location with access to the source code." << __E__; 01172 __SS_THROW__; 01173 } 01174 if(!foundSourceFile) 01175 { 01176 __SS__ << "Could not find the source file for the FE Interface plugins at '" 01177 << sourceFile << ".' Does MacroMaker " 01178 << "have access to the source code? Check that the Supervisor context " 01179 "places MacroMaker in a " 01180 << "location with access to the source code." << __E__; 01181 __SS_THROW__; 01182 } 01183 01184 // at this point have header and source file, now add FE Macro 01185 // Steps for each file: 01186 // - read current file 01187 // - find insert point 01188 // - open file for writing 01189 // - write original file up to insert point 01190 // - insert new code 01191 // - write remaining original file 01192 01193 char timeBuffer[100]; 01194 { // get time string 01195 time_t rawtime; 01196 struct tm* timeinfo; 01197 01198 time(&rawtime); 01199 timeinfo = localtime(&rawtime); 01200 01201 strftime(timeBuffer, 100, "%b-%d-%Y %I:%M:%S", timeinfo); 01202 } 01203 01204 std::string contents; 01205 std::string insert; 01206 01208 // handle source file modifications 01209 CodeEditor::readFile(CodeEditor::SOURCE_BASE_PATH,sourceFile, contents); 01210 //__SUP_COUTV__(contents); 01211 01212 // return file locations, for the user to inspect on error 01213 xmldoc.addTextElementToData("sourceFile", sourceFile); 01214 xmldoc.addTextElementToData("headerFile", headerFile); 01215 01216 // check for duplicate functions 01217 if(contents.find(pluginName + "::" + macroName) != std::string::npos) 01218 { 01219 __SS__ << "The function definition '" << (pluginName + "::" + macroName) 01220 << "(...)' already exists in the source file '" << sourceFile 01221 << ".' Duplicate functions are not allowed - please rename the macro or " 01222 "modify the source file." 01223 << __E__; 01224 __SS_THROW__; 01225 } 01226 01227 std::stringstream codess; 01228 std::set<std::string> inArgNames, outArgNames; 01229 createCode(codess, 01230 commands, 01231 "\t" /*tabOffset*/, 01232 true /*forFeMacro*/, 01233 &inArgNames, 01234 &outArgNames); 01235 __SUP_COUTV__(StringMacros::setToString(inArgNames)); 01236 __SUP_COUTV__(StringMacros::setToString(outArgNames)); 01237 01238 // find start of constructor and register macro 01239 { 01240 auto insertPos = contents.find(pluginName + "::" + pluginName); 01241 if(insertPos == std::string::npos) 01242 { 01243 __SS__ << "Could not find the code insert position in the source file '" 01244 << sourceFile << ".' The FE plugin class constructor must be '" 01245 << pluginName << ":" << pluginName << "' - is this the case?" << __E__; 01246 __SS_THROW__; 01247 } 01248 __SUP_COUTV__(insertPos); 01249 // find opening bracket after constructor name 01250 insertPos = contents.find("{", insertPos); 01251 if(insertPos == std::string::npos) 01252 { 01253 __SS__ << "Could not find the code insert position in the source file '" 01254 << sourceFile 01255 << ".' The FE plugin class constructor must begin with '{" 01256 << "' - is this the case?" << __E__; 01257 __SS_THROW__; 01258 } 01259 ++insertPos; // go past { 01260 __SUP_COUTV__(insertPos); 01261 01262 insert = "\n\t//registration of FEMacro '" + macroName + "' generated, " + 01263 timeBuffer + ", by '" + username + "' using MacroMaker.\n\t" + 01264 "FEVInterface::registerFEMacroFunction(\"" + macroName + 01265 "\",//feMacroName \n\t\t" + 01266 "static_cast<FEVInterface::frontEndMacroFunction_t>(&" + pluginName + 01267 "::" + macroName + "), //feMacroFunction \n\t\t" + 01268 "std::vector<std::string>{"; 01269 { // insert input argument names 01270 bool first = true; 01271 for(const auto& inArg : inArgNames) 01272 { 01273 if(first) 01274 first = false; 01275 else 01276 insert += ","; 01277 insert += "\"" + inArg + "\""; 01278 } 01279 } 01280 insert += "}, //namesOfInputArgs \n\t\t"; 01281 insert += "std::vector<std::string>{"; 01282 { // insert output argument names 01283 bool first = true; 01284 for(const auto& outArg : outArgNames) 01285 { 01286 if(first) 01287 first = false; 01288 else 01289 insert += ","; 01290 insert += "\"" + outArg + "\""; 01291 } 01292 } 01293 insert += "}, //namesOfOutputArgs \n\t\t"; 01294 insert += "1); //requiredUserPermissions \n\n"; 01295 01296 __SUP_COUTV__(insert); 01297 contents = contents.substr(0, insertPos) + insert + contents.substr(insertPos); 01298 } 01299 01300 // find end of source to append FE Macro function 01301 { 01302 auto insertPos = contents.rfind("DEFINE_OTS_INTERFACE"); 01303 if(insertPos == std::string::npos) 01304 { 01305 __SS__ << "Could not find the code insert position in the source file '" 01306 << sourceFile 01307 << ".' The FE plugin class must end with a 'DEFINE_OTS_INTERFACE(" 01308 << pluginName << ")' - is this the case?" << __E__; 01309 __SS_THROW__; 01310 } 01311 __SUP_COUTV__(insertPos); 01312 01313 insert = 01314 "\n//" 01315 "============================================================================" 01316 "============================================\n//" + 01317 macroName + "\n" + "//\tFEMacro '" + macroName + "' generated, " + 01318 timeBuffer + ", by '" + username + "' using MacroMaker.\n" + 01319 "//\tMacro Notes: " + macroNotes + "\n" + "void " + pluginName + 01320 "::" + macroName + "(__ARGS__)\n{\n\t" + 01321 "__CFG_COUT__ << \"# of input args = \" << argsIn.size() << __E__; \n\t" + 01322 "__CFG_COUT__ << \"# of output args = \" << argsOut.size() << __E__; \n\t" + 01323 "for(auto &argIn:argsIn) \n\t\t" + 01324 "__CFG_COUT__ << argIn.first << \": \" << argIn.second << __E__; \n\n\t" + 01325 "//macro commands section \n" + codess.str() + "\n\n\t" + 01326 "for(auto &argOut:argsOut) \n\t\t" + 01327 "__CFG_COUT__ << argOut.first << \": \" << argOut.second << __E__; \n\n" + 01328 "} //end " + macroName + "()\n\n"; 01329 01330 //__SUP_COUTV__(insert); 01331 CodeEditor::writeFile(CodeEditor::SOURCE_BASE_PATH, 01332 sourceFile, contents, "MacroMaker-" + username, insertPos, insert); 01333 } 01334 01336 // handle include file insertions 01337 CodeEditor::readFile(CodeEditor::SOURCE_BASE_PATH, headerFile, contents); 01338 //__SUP_COUTV__(contents); 01339 01340 // find end of class by looking for last }; 01341 { 01342 auto insertPos = contents.rfind("};"); 01343 if(insertPos == std::string::npos) 01344 { 01345 __SS__ << "Could not find the code insert position in the header file '" 01346 << headerFile 01347 << ".' The FE plugin class must end with a '};' - is this the case?" 01348 << __E__; 01349 __SS_THROW__; 01350 } 01351 01352 __SUP_COUTV__(insertPos); 01353 01354 insert = "\npublic: // FEMacro '" + macroName + "' generated, " + timeBuffer + 01355 ", by '" + username + "' using MacroMaker.\n\t" + "void " + macroName + 01356 "\t(__ARGS__);\n"; 01357 01358 __SUP_COUTV__(insert); 01359 CodeEditor::writeFile(CodeEditor::SOURCE_BASE_PATH, 01360 headerFile, contents, "MacroMaker-" + username, insertPos, insert); 01361 } 01362 01363 } // end exportFEMacro () 01364 01365 //======================================================================================================================== 01366 void MacroMakerSupervisor::exportMacro(HttpXmlDocument& xmldoc, 01367 cgicc::Cgicc& cgi, 01368 const std::string& username) 01369 { 01370 std::string macroName = CgiDataUtilities::getData(cgi, "MacroName"); 01371 std::string macroSequence = CgiDataUtilities::postData(cgi, "MacroSequence"); 01372 std::string macroNotes = CgiDataUtilities::decodeURIComponent( 01373 CgiDataUtilities::postData(cgi, "MacroNotes")); 01374 01375 __SUP_COUTV__(macroName); 01376 __SUP_COUTV__(macroSequence); 01377 01378 // replace all special characters with white space 01379 for(unsigned int i = 0; i < macroNotes.length(); ++i) 01380 if(macroNotes[i] == '\r' || macroNotes[i] == '\n') 01381 macroNotes[i] = ' '; 01382 __SUP_COUTV__(macroNotes); 01383 01384 std::stringstream ss(macroSequence); 01385 std::string command; 01386 std::vector<std::string> commands; 01387 01388 while(getline(ss, command, ',')) 01389 commands.push_back(command); 01390 01391 std::string fileName = macroName + ".cc"; 01392 01393 std::string fullPath = (std::string)MACROS_EXPORT_PATH + username + "/" + fileName; 01394 __SUP_COUT__ << fullPath << __E__; 01395 std::ofstream exportFile(fullPath.c_str(), std::ios::trunc); 01396 if(exportFile.is_open()) 01397 { 01398 exportFile << "//Generated Macro Name:\t" << macroName << "\n"; 01399 exportFile << "//Macro Notes: " << macroNotes << "\n"; 01400 01401 { 01402 time_t rawtime; 01403 struct tm* timeinfo; 01404 char buffer[100]; 01405 01406 time(&rawtime); 01407 timeinfo = localtime(&rawtime); 01408 01409 strftime(buffer, 100, "%b-%d-%Y %I:%M:%S", timeinfo); 01410 exportFile << "//Generated Time: \t\t" << buffer << "\n"; 01411 } 01412 01413 exportFile << "//Paste this whole file into an interface to transfer Macro " 01414 "functionality.\n"; 01415 01416 createCode(exportFile, commands); 01417 01418 exportFile.close(); 01419 01420 xmldoc.addTextElementToData("ExportFile", fullPath); 01421 } 01422 else 01423 __SUP_COUT__ << "Unable to open file" << __E__; 01424 } 01425 01426 //======================================================================================================================== 01427 // createCode 01428 void MacroMakerSupervisor::createCode(std::ostream& out, 01429 const std::vector<std::string>& commands, 01430 const std::string& tabOffset, 01431 bool forFeMacro, 01432 std::set<std::string>* inArgNames, 01433 std::set<std::string>* outArgNames) 01434 { 01435 int numOfHexBytes; 01436 std::set<std::string /*argInName*/> argInHasBeenInitializedSet; 01437 bool addressIsVariable, dataIsVariable; 01438 01439 out << tabOffset << "{"; 01440 01441 out << "\n" 01442 << tabOffset << "\t" 01443 << "char *address \t= new char[universalAddressSize_]{0}; //create address " 01444 "buffer of interface size and init to all 0"; 01445 out << "\n" 01446 << tabOffset << "\t" 01447 << "char *data \t\t= new char[universalDataSize_]{0}; //create data buffer " 01448 "of interface size and init to all 0"; 01449 01450 out << "\n" 01451 << tabOffset << "\t" 01452 << "uint64_t macroAddress; //create macro address buffer (size 8 bytes)"; 01453 out << "\n" 01454 << tabOffset << "\t" 01455 << "uint64_t macroData; //create macro address buffer (size 8 bytes)"; 01456 01457 out << "\n" 01458 << tabOffset << "\t" 01459 << "std::map<std::string /*arg name*/,uint64_t /*arg val*/> macroArgs; //create " 01460 "map from arg name to 64-bit number"; 01461 01462 // loop through each macro command 01463 for(unsigned int i = 0; i < commands.size(); i++) 01464 { 01465 std::stringstream sst(commands[i]); 01466 std::string tokens; 01467 std::vector<std::string> 01468 oneCommand; // 4 fields: cmd index | cmd type | addr | data 01469 while(getline(sst, tokens, ':')) 01470 oneCommand.push_back(tokens); 01471 while(oneCommand.size() < 4) 01472 oneCommand.push_back(""); // fill out the 4 fields 01473 01474 __SUP_COUTV__(StringMacros::vectorToString(oneCommand)); 01475 01476 // make this: 01477 // std::map<std::string,uint64_t> macroArgs; 01478 // { 01479 // uint64_t address = 0x1001; //create address buffer 01480 // uint64_t data = 0x100203; //create data buffer 01481 // 01482 // universalWrite(address,data); 01483 // universalRead(address,data); 01484 // } 01485 // 01486 // //if variable, first time init 01487 // { 01488 // address = 01489 // theXDAQContextConfigTree_.getNode(theConfigurationPath_).getNode("variableName").getValue<uint64_t>(); 01490 // or 01491 // address = __GET_ARG_IN__("variableName",uint64_t); 01492 // } 01493 // 01494 // //if variable, second time use macroArgs 01495 // { 01496 // address = macroArgs["variableName"]; 01497 // data = macroArgs["variableName"]; 01498 // } 01499 01500 addressIsVariable = isArgumentVariable(oneCommand[2]); 01501 dataIsVariable = isArgumentVariable(oneCommand[3]); 01502 01503 __SUP_COUTV__(addressIsVariable); 01504 __SUP_COUTV__(dataIsVariable); 01505 01506 out << "\n\n" << tabOffset << "\t// command-#" << i << ": "; 01507 01508 if(oneCommand[1][0] == 'w' || oneCommand[1][0] == 'r') 01509 { 01510 if(oneCommand[1][0] == 'w') 01511 out << "Write("; 01512 else if(oneCommand[1][0] == 'r') 01513 out << "Read("; 01514 01515 if(addressIsVariable) 01516 out << oneCommand[2]; 01517 else // literal hex address 01518 out << "0x" << oneCommand[2]; 01519 out << " /*address*/,"; 01520 01521 if(dataIsVariable) // read or write can have variable data, sink or source 01522 // respectively 01523 out << oneCommand[3] << " /*data*/"; 01524 else if(oneCommand[1][0] == 'w') // literal hex data 01525 out << "0x" << oneCommand[3] << " /*data*/"; 01526 else if(oneCommand[1][0] == 'r') // just reading to buffer 01527 out << "data"; 01528 out << ");\n"; 01529 } 01530 else if(oneCommand[1][0] == 'd') 01531 { 01532 out << "delay(" << oneCommand[2] << ");\n"; 01533 out << tabOffset << "\t" 01534 << "__CFG_COUT__ << \"Sleeping for... \" << " << oneCommand[2] 01535 << " << \" milliseconds \" << __E__;\n"; 01536 out << tabOffset << "\t" 01537 << "usleep(" << oneCommand[2] << "*1000 /* microseconds */);\n"; 01538 continue; 01539 } 01540 else 01541 { 01542 __SS__ << "FATAL ERROR: Unknown command '" << oneCommand[1] 01543 << "'... command is not w, r or d" << __E__; 01544 __SS_THROW__; 01545 } 01546 01548 // handle address 01549 if(addressIsVariable) // handle address as variable 01550 { 01551 if(argInHasBeenInitializedSet.find(oneCommand[2]) == 01552 argInHasBeenInitializedSet.end()) // only initialize input argument once 01553 { 01554 argInHasBeenInitializedSet.emplace(oneCommand[2]); 01555 01556 if(!forFeMacro) 01557 { 01558 // get address from configuration Tree 01559 out << tabOffset << "\t" 01560 << "macroArgs[\"" << oneCommand[2] 01561 << "\"] = " 01562 "theXDAQContextConfigTree_.getNode(theConfigurationPath_)." 01563 "getNode(" 01564 << "\n" 01565 << tabOffset << "\t\t\"" << oneCommand[2] 01566 << "\").getValue<uint64_t>();"; 01567 } 01568 else 01569 { 01570 if(inArgNames) 01571 inArgNames->emplace(oneCommand[2]); 01572 01573 // get address from arguments 01574 out << tabOffset << "\t" 01575 << "macroArgs[\"" << oneCommand[2] << "\"] = __GET_ARG_IN__(\"" 01576 << oneCommand[2] << "\", uint64_t);"; 01577 } 01578 } 01579 out << "\t//get macro address argument"; 01580 out << "\n" 01581 << tabOffset << "\tmemcpy(address,¯oArgs[\"" << oneCommand[2] 01582 << "\"],8); //copy macro address argument to buffer"; 01583 } 01584 else // handle address as literal 01585 { 01586 out << tabOffset << "\t" 01587 << "macroAddress = 0x" << oneCommand[2] 01588 << "; memcpy(address,¯oAddress,8);" 01589 << "\t//copy macro address to buffer"; 01590 } 01591 01593 // handle data 01594 if(oneCommand[1] == "w") // if write, handle data too 01595 { 01596 if(dataIsVariable) // handle data as variable 01597 { 01598 if(argInHasBeenInitializedSet.find(oneCommand[3]) == 01599 argInHasBeenInitializedSet 01600 .end()) // only initialize input argument once 01601 { 01602 argInHasBeenInitializedSet.emplace(oneCommand[3]); 01603 01604 if(forFeMacro) 01605 { 01606 if(inArgNames) 01607 inArgNames->emplace(oneCommand[3]); 01608 01609 // get data from arguments 01610 out << "\n" 01611 << tabOffset << "\t" 01612 << "macroArgs[\"" << oneCommand[3] 01613 << "\"] = __GET_ARG_IN__(\"" << oneCommand[3] 01614 << "\", uint64_t); //initialize from input arguments"; 01615 } 01616 else 01617 { 01618 // get data from configuration Tree 01619 out << "\n" 01620 << tabOffset << "\t" 01621 << "macroArgs[\"" << oneCommand[3] 01622 << "\"] = " 01623 "theXDAQContextConfigTree_.getNode(theConfigurationPath_)." 01624 "getNode(" 01625 << "\n" 01626 << tabOffset << "\t\t\"" << oneCommand[3] 01627 << "\").getValue<uint64_t>(); //initialize from " 01628 "configuration tree"; 01629 } 01630 } 01631 out << "\t//get macro data argument"; 01632 out << "\n" 01633 << tabOffset << "\tmemcpy(data,¯oArgs[\"" << oneCommand[3] 01634 << "\"],8); //copy macro data argument to buffer"; 01635 } 01636 else // handle data as literal 01637 { 01638 out << "\n" 01639 << tabOffset << "\t" 01640 << "macroData = 0x" << oneCommand[3] << "; memcpy(data,¯oData,8);" 01641 << "\t//copy macro data to buffer"; 01642 } 01643 out << "\n" 01644 << tabOffset << "\t" 01645 << "universalWrite(address,data);"; 01646 } 01647 else 01648 { 01649 out << "\n" 01650 << tabOffset << "\t" 01651 << "universalRead(address,data);"; 01652 01653 std::string outputArgName; 01654 01655 if(dataIsVariable) // handle data as variable 01656 outputArgName = oneCommand[3]; 01657 else // give each read data a unique argument name 01658 { 01659 char str[20]; 01660 sprintf(str, "outArg%d", i); 01661 outputArgName = str; // use command index for uniqueness 01662 } 01663 __SUP_COUTV__(outputArgName); 01664 01665 out << tabOffset << "\t" 01666 << "memcpy(¯oArgs[\"" << outputArgName 01667 << "\"],data,8); //copy buffer to argument map"; 01668 01669 // copy read data to output args 01670 if(forFeMacro) 01671 out << "\n" 01672 << tabOffset << "\t" 01673 << "__SET_ARG_OUT__(\"" << outputArgName << "\",macroArgs[\"" 01674 << outputArgName << "\"]); //update output argument result"; 01675 01676 if(outArgNames) 01677 outArgNames->emplace(outputArgName); 01678 argInHasBeenInitializedSet.emplace( 01679 outputArgName); // mark initialized since value has been read 01680 } 01681 } // end command loop 01682 01683 out << "\n\n" << tabOffset << "\tdelete[] address; //free the memory"; 01684 out << "\n" << tabOffset << "\tdelete[] data; //free the memory"; 01685 out << "\n" << tabOffset << "}"; 01686 01687 __SUP_COUT__ << "Done with code generation." << __E__; 01688 } // end createCode() 01689 01690 //======================================================================================================================== 01691 // isArgumentVariable 01692 // returns true if string should be interpreted as a variable for MacroMaker 01693 bool MacroMakerSupervisor::isArgumentVariable(const std::string& argumentString) 01694 { 01695 for(unsigned int i = 0; i < argumentString.length(); ++i) 01696 { 01697 // detect non-hex 01698 if(!((argumentString[i] >= '0' && argumentString[i] <= '9') || 01699 (argumentString[i] >= 'a' && argumentString[i] <= 'f') || 01700 (argumentString[i] >= 'A' && argumentString[i] <= 'F'))) 01701 return true; 01702 } 01703 return false; 01704 } // end isArgumentVariable() 01705 //======================================================================================================================== 01706 // generateHexArray 01707 // returns a char array initializer 01708 // something like this 01709 // "[8] = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09};" 01710 // ..depending a size of source string 01711 // 01712 // FIXME -- identify variables in a better way from macromaker...! 01713 // for now just assume a non hex is a variable name 01714 // return -1 size 01715 std::string MacroMakerSupervisor::generateHexArray(const std::string& sourceHexString, 01716 int& numOfBytes) 01717 { 01718 std::stringstream retSs; 01719 01720 std::string srcHexStr = sourceHexString; 01721 __SUP_COUT__ << "Translating: \n"; 01722 __SUP_COUT__ << srcHexStr << __E__; 01723 01724 if(srcHexStr.size() % 2) // if odd, make even 01725 srcHexStr = "0" + srcHexStr; 01726 01727 numOfBytes = srcHexStr.size() / 2; 01728 retSs << "[" << numOfBytes << "] = {"; 01729 01730 for(int i = 0; i < numOfBytes * 2; i += 2) 01731 { 01732 // detect non-hex 01733 if(!((srcHexStr[i] >= '0' && srcHexStr[i] <= '9') || 01734 (srcHexStr[i] >= 'a' && srcHexStr[i] <= 'f') || 01735 (srcHexStr[i] >= 'A' && srcHexStr[i] <= 'F')) || 01736 !((srcHexStr[i + 1] >= '0' && srcHexStr[i + 1] <= '9') || 01737 (srcHexStr[i + 1] >= 'a' && srcHexStr[i + 1] <= 'f') || 01738 (srcHexStr[i + 1] >= 'A' && srcHexStr[i + 1] <= 'F'))) 01739 { 01740 numOfBytes = -1; 01741 return srcHexStr; 01742 } 01743 01744 if(i != 0) 01745 retSs << ", "; 01746 retSs << "0x" << srcHexStr[srcHexStr.size() - 1 - i - 1] 01747 << srcHexStr[srcHexStr.size() - 1 - i]; 01748 } 01749 retSs << "};"; 01750 01751 __SUP_COUT__ << retSs.str() << __E__; 01752 01753 return retSs.str(); 01754 } 01755 01756 //======================================================================================================================== 01757 void MacroMakerSupervisor::runFEMacro(HttpXmlDocument& xmldoc, cgicc::Cgicc& cgi, 01758 const std::string& username) 01759 try 01760 { 01761 __SUP_COUT__ << __E__; 01762 01763 //unsigned int feSupervisorID = CgiDataUtilities::getDataAsInt(cgi, "feSupervisorID"); 01764 std::string feClassSelected= CgiDataUtilities::getData(cgi, "feClassSelected"); 01765 std::string feUIDSelected = CgiDataUtilities::getData(cgi, "feUIDSelected"); 01766 std::string macroType = CgiDataUtilities::getData(cgi, "macroType"); 01767 std::string macroName = CgiDataUtilities::getData(cgi, "macroName"); 01768 std::string inputArgs = CgiDataUtilities::postData(cgi, "inputArgs"); 01769 std::string outputArgs = CgiDataUtilities::postData(cgi, "outputArgs"); 01770 bool saveOutputs = CgiDataUtilities::getDataAsInt(cgi, "saveOutputs")==1; 01771 01772 //__SUP_COUTV__(feSupervisorID); 01773 __SUP_COUTV__(feClassSelected); 01774 __SUP_COUTV__(feUIDSelected); 01775 __SUP_COUTV__(macroType); 01776 __SUP_COUTV__(macroName); 01777 __SUP_COUTV__(inputArgs); 01778 __SUP_COUTV__(outputArgs); 01779 __SUP_COUTV__(saveOutputs); 01780 01781 std::set<std::string /*feUID*/> feUIDs; 01782 01783 if(feUIDSelected == "") feUIDSelected = "*"; //treat empty as all 01784 if(feClassSelected == "") feClassSelected = "*"; //treat empty as all 01785 01786 if(feClassSelected == "" || feUIDSelected == "" || macroType == "" || 01787 macroName == "") 01788 { 01789 __SUP_SS__ << "Illegal empty front-end parameter." << __E__; 01790 __SUP_SS_THROW__; 01791 } 01792 else if(feUIDSelected != "*") 01793 feUIDs.emplace(feUIDSelected); 01794 else // * all case 01795 { 01796 //add all FEs for type 01797 if(feClassSelected == "*") 01798 { 01799 for(auto& feTypePair:FEPluginTypetoFEsMap_) 01800 for(auto& feUID:feTypePair.second) 01801 feUIDs.emplace(feUID); 01802 } 01803 else 01804 { 01805 auto typeIt = FEPluginTypetoFEsMap_.find(feClassSelected); 01806 if(typeIt == FEPluginTypetoFEsMap_.end()) 01807 { 01808 __SUP_SS__ << "Illegal front-end type parameter '" << 01809 feClassSelected << "' not in list of types." << __E__; 01810 __SUP_SS_THROW__; 01811 } 01812 01813 for(auto& feUID:typeIt->second) 01814 feUIDs.emplace(feUID); 01815 } 01816 } 01817 01818 __SUP_COUTV__(StringMacros::setToString(feUIDs)); 01819 01820 std::string macroString; 01821 if(macroType == "public") 01822 loadMacro(macroName,macroString); 01823 else if(macroType == "private") 01824 loadMacro(macroName,macroString,username); 01825 01826 __SUP_COUTV__(macroString); 01827 01828 FILE *fp = 0; 01829 try 01830 { 01831 if(saveOutputs) 01832 { 01833 std::string filename = "/macroOutput_" + 01834 std::to_string(time(0)) + "_" + std::to_string(clock()) + ".txt"; 01835 01836 __SUP_COUTV__(filename); 01837 fp = fopen((CodeEditor::OTSDAQ_DATA_PATH + filename).c_str(),"w"); 01838 if(!fp) 01839 { 01840 __SUP_SS__ << "Failed to open file to save macro output '" << 01841 CodeEditor::OTSDAQ_DATA_PATH << 01842 filename << "'..." << __E__; 01843 __SUP_SS_THROW__; 01844 } 01845 01846 fprintf(fp,"############################\n"); 01847 fprintf(fp,"### Running '%s' at time %s\n",macroName.c_str(), 01848 StringMacros::getTimestampString().c_str()); 01849 fprintf(fp,"### \t Target front-ends (count=%lu): %s\n", 01850 feUIDs.size(),StringMacros::setToString(feUIDs).c_str()); 01851 fprintf(fp,"### \t\t Inputs: %s\n",inputArgs.c_str()); 01852 fprintf(fp,"############################\n\n\n"); 01853 01854 01855 xmldoc.addTextElementToData("outputArgs_name", "Filename"); 01856 xmldoc.addTextElementToData("outputArgs_value", 01857 "$OTSDAQ_DATA/" + filename); 01858 } 01859 01860 01861 //do for all target front-ends 01862 for(auto& feUID:feUIDs) 01863 { 01864 auto feIt = FEtoSupervisorMap_.find(feUID); 01865 if(feIt == FEtoSupervisorMap_.end()) 01866 { 01867 __SUP_SS__ << "Destination front end interface ID '" << feUID 01868 << "' was not found in the list of front ends." << __E__; 01869 ss << "\n\nHere is the map:\n\n" << StringMacros::mapToString(FEtoSupervisorMap_) << __E__; 01870 __SUP_SS_THROW__; 01871 } 01872 01873 unsigned int FESupervisorIndex = feIt->second; 01874 __SUP_COUT__ << "Found supervisor index: " << FESupervisorIndex << __E__; 01875 01876 SupervisorInfoMap::iterator it = allFESupervisorInfo_.find(FESupervisorIndex); 01877 if(it == allFESupervisorInfo_.end()) 01878 { 01879 __SUP_SS__ << "Error transmitting request to FE Supervisor '" 01880 << feUID << ":" << FESupervisorIndex << ".' \n\n" 01881 << "The FE Supervisor Index does not exist. Have you configured " 01882 "the state machine properly?" 01883 << __E__; 01884 __SUP_SS_THROW__; 01885 } 01886 01887 // send command to chosen FE and await response 01888 SOAPParameters txParameters; // params for xoap to send 01889 if(macroType == "fe") 01890 txParameters.addParameter("Request", "RunInterfaceMacro"); 01891 else 01892 txParameters.addParameter("Request", "RunMacroMakerMacro"); 01893 txParameters.addParameter("InterfaceID", feUID); 01894 if(macroType == "fe") 01895 txParameters.addParameter("feMacroName", macroName); 01896 else 01897 { 01898 txParameters.addParameter("macroName", macroName); 01899 txParameters.addParameter("macroString", macroString); 01900 } 01901 txParameters.addParameter("inputArgs", inputArgs); 01902 txParameters.addParameter("outputArgs", outputArgs); 01903 01904 SOAPParameters rxParameters; // params for xoap to recv 01905 //rxParameters.addParameter("success"); 01906 rxParameters.addParameter("outputArgs"); 01907 rxParameters.addParameter("Error"); 01908 01909 if(saveOutputs) 01910 { 01911 fprintf(fp,"Running '%s' at time %s\n",macroName.c_str(), 01912 StringMacros::getTimestampString().c_str()); 01913 fprintf(fp,"\t Target front-end: '%s::%s'\n", 01914 FEtoPluginTypeMap_[feUID].c_str(),feUID.c_str()); 01915 fprintf(fp,"\t\t Inputs: %s\n",inputArgs.c_str()); 01916 } 01917 01918 // have FE supervisor descriptor, so send 01919 xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply( 01920 it->second.getDescriptor(), // supervisor descriptor 01921 "MacroMakerSupervisorRequest", 01922 txParameters); 01923 01924 01925 __SUP_COUT__ << "Received response message: " 01926 << SOAPUtilities::translate(retMsg) << __E__; 01927 01928 SOAPUtilities::receive(retMsg, rxParameters); 01929 01930 __SUP_COUT__ << "Received it " << __E__; 01931 01932 //bool success = rxParameters.getValue("success") == "1"; 01933 std::string outputResults = rxParameters.getValue("outputArgs"); 01934 std::string error = rxParameters.getValue("Error"); 01935 01936 //__SUP_COUT__ << "rx success = " << success << __E__; 01937 __SUP_COUT__ << "outputArgs = " << outputResults << __E__; 01938 01939 if(error != "") 01940 { 01941 __SS__ << "Attempted FE Macro Failed. Attempted target " 01942 << "was UID=" << feUID << " at feSupervisorID=" << FESupervisorIndex << "." 01943 << __E__; 01944 ss << "\n\n The error was:\n\n" << error << __E__; 01945 __SUP_COUT_ERR__ << "\n" << ss.str(); 01946 xmldoc.addTextElementToData("Error", ss.str()); 01947 01948 return; 01949 } 01950 01951 // build output arguments 01952 // parse args, colon-separated pairs, and then comma-separated 01953 { 01954 std::istringstream inputStream(outputResults); 01955 std::string splitVal, argName, argValue; 01956 while(getline(inputStream, splitVal, ';')) 01957 { 01958 std::istringstream pairInputStream(splitVal); 01959 getline(pairInputStream, argName, ','); 01960 getline(pairInputStream, argValue, ','); 01961 01962 if(saveOutputs) 01963 { 01964 fprintf(fp,"\t\t Output '%s' = %s\n", 01965 argName.c_str(),argValue.c_str()); 01966 } 01967 else 01968 { 01969 xmldoc.addTextElementToData("outputArgs_name", argName); 01970 xmldoc.addTextElementToData("outputArgs_value", argValue); 01971 } 01972 __SUP_COUT__ << argName << ": " << argValue << __E__; 01973 } 01974 } 01975 } //end target front-end loop 01976 } 01977 catch(...) //handle file close on error 01978 { 01979 if(fp) fclose(fp); 01980 throw; 01981 } 01982 01983 if(fp) fclose(fp); 01984 01985 } //end runFEMacro() 01986 catch(const std::runtime_error& e) 01987 { 01988 __SUP_SS__ << "Error processing FE communication request: " << 01989 e.what() << __E__; 01990 __SUP_COUT_ERR__ << ss.str(); 01991 xmldoc.addTextElementToData("Error", ss.str()); 01992 } 01993 catch(...) 01994 { 01995 __SUP_SS__ << "Unknown error processing FE communication request." << __E__; 01996 __SUP_COUT_ERR__ << ss.str(); 01997 01998 xmldoc.addTextElementToData("Error", ss.str()); 01999 } // end runFEMacro() catch 02000 02001 //======================================================================================================================== 02002 void MacroMakerSupervisor::getFEMacroList(HttpXmlDocument& xmldoc, 02003 const std::string& username) 02004 { 02005 __SUP_COUT__ << "Getting FE Macro list" << __E__; 02006 02007 SOAPParameters txParameters; // params for xoap to send 02008 txParameters.addParameter("Request", "GetInterfaceMacros"); 02009 02010 SOAPParameters rxParameters; // params for xoap to recv 02011 rxParameters.addParameter("FEMacros"); 02012 02013 std::string oneInterface; 02014 std::string rxFEMacros; 02015 02016 // for each list of FE Supervisors, 02017 // get all FE specific macros 02018 for(auto& appInfo : allFESupervisorInfo_) 02019 { 02020 __SUP_COUT__ << "FESupervisor LID = " << appInfo.second.getId() 02021 << " name = " << appInfo.second.getName() << __E__; 02022 02023 xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply( 02024 appInfo.second.getDescriptor(), "MacroMakerSupervisorRequest", txParameters); 02025 SOAPUtilities::receive(retMsg, rxParameters); 02026 02027 rxFEMacros = rxParameters.getValue("FEMacros"); 02028 02029 __SUP_COUT__ << "FE Macros received: \n" << rxFEMacros << __E__; 02030 02031 std::istringstream allInterfaces(rxFEMacros); 02032 while(std::getline(allInterfaces, oneInterface)) 02033 { 02034 //__SUP_COUT__ << oneInterface << __E__; 02035 //__SUP_COUT__ << appInfo.second.getId() << __E__; 02036 xmldoc.addTextElementToData("FEMacros", oneInterface); 02037 // xmldoc.outputXmlDocument(0,true); 02038 } 02039 } 02040 02041 // add macros to response 02042 std::pair<std::vector<std::string> /*public macros*/, 02043 std::vector<std::string> /*private macros*/> macroNames; 02044 loadMacroNames(username,macroNames); 02045 02046 __SUP_COUT__ << "Public macro count: " << macroNames.first.size() << __E__; 02047 __SUP_COUT__ << "Private macro count: " << macroNames.second.size() << __E__; 02048 02049 std::string macroString; 02050 //make xml ':' separated fields: 02051 // macro name 02052 // permissions string 02053 // number of inputs 02054 // inputs separated by : 02055 // number of outputs 02056 // outputs separated by : 02057 02058 02059 for(int i=0;i<2;++i) //first is public, then private 02060 for(auto& macroName:(i?macroNames.second:macroNames.first)) 02061 { 02062 //get macro string 02063 loadMacro(macroName,macroString,username); 02064 02065 // extract macro object 02066 FEVInterface::macroStruct_t macro(macroString); 02067 02068 std::stringstream xmlMacroStream; 02069 xmlMacroStream << macro.macroName_; 02070 xmlMacroStream << ":" << "1"; //permissions string 02071 xmlMacroStream << ":" << macro.namesOfInputArguments_.size(); 02072 for(auto& inputArg:macro.namesOfInputArguments_) 02073 xmlMacroStream << ":" << inputArg; 02074 xmlMacroStream << ":" << macro.namesOfOutputArguments_.size(); 02075 for(auto& inputArg:macro.namesOfOutputArguments_) 02076 xmlMacroStream << ":" << inputArg; 02077 02078 xmldoc.addTextElementToData(i?"PrivateMacro":"PublicMacro", xmlMacroStream.str()); 02079 } 02080 02081 02082 return; 02083 }