$treeview $search $mathjax $extrastylesheet
otsdaq
v2_03_00
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h" 00002 #include "otsdaq-core/Macros/TablePluginMacros.h" 00003 #include "otsdaq-core/TablePluginDataFormats/XDAQContextTable.h" 00004 00005 #include <stdio.h> 00006 #include <fstream> // std::fstream 00007 #include <iostream> 00008 00009 using namespace ots; 00010 00011 #define XDAQ_RUN_FILE \ 00012 std::string(getenv("XDAQ_CONFIGURATION_DATA_PATH")) + "/" + \ 00013 std::string(getenv("XDAQ_CONFIGURATION_XML")) + ".xml" 00014 #define APP_PRIORITY_FILE \ 00015 std::string(getenv("XDAQ_CONFIGURATION_DATA_PATH")) + "/" + \ 00016 "xdaqAppStateMachinePriority" 00017 00018 //#define XDAQ_SCRIPT std::string(getenv("XDAQ_CONFIGURATION_DATA_PATH")) + 00019 //"/"+ "StartXDAQ_gen.sh" #define ARTDAQ_MPI_SCRIPT 00020 // std::string(getenv("XDAQ_CONFIGURATION_DATA_PATH")) + "/"+ "StartMPI_gen.sh" 00021 00022 const std::string XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS = 00023 "ots::Supervisor"; // still allowed for now, in StartOTS 00024 const std::string XDAQContextTable::GATEWAY_SUPERVISOR_CLASS = "ots::GatewaySupervisor"; 00025 const std::string XDAQContextTable::WIZARD_SUPERVISOR_CLASS = "ots::WizardSupervisor"; 00026 const std::set<std::string> XDAQContextTable::FETypeClassNames_ = { 00027 "ots::FESupervisor", 00028 "ots::FEDataManagerSupervisor", 00029 "ots::ARTDAQFEDataManagerSupervisor"}; 00030 const std::set<std::string> XDAQContextTable::DMTypeClassNames_ = { 00031 "ots::DataManagerSupervisor", 00032 "ots::FEDataManagerSupervisor", 00033 "ots::ARTDAQFEDataManagerSupervisor"}; 00034 const std::set<std::string> XDAQContextTable::LogbookTypeClassNames_ = { 00035 "ots::LogbookSupervisor"}; 00036 const std::set<std::string> XDAQContextTable::MacroMakerTypeClassNames_ = { 00037 "ots::MacroMakerSupervisor"}; 00038 const std::set<std::string> XDAQContextTable::ChatTypeClassNames_ = { 00039 "ots::ChatSupervisor"}; 00040 const std::set<std::string> XDAQContextTable::ConsoleTypeClassNames_ = { 00041 "ots::ConsoleSupervisor"}; 00042 const std::set<std::string> XDAQContextTable::ConfigurationGUITypeClassNames_ = { 00043 "ots::TableGUISupervisor"}; 00044 00045 const std::string XDAQContextTable::ARTDAQ_OFFSET_PORT = "OffsetPort"; 00046 00047 const uint8_t XDAQContextTable::XDAQApplication::DEFAULT_PRIORITY = 100; 00048 00049 //======================================================================================================================== 00050 XDAQContextTable::XDAQContextTable(void) : TableBase("XDAQContextTable") 00051 { 00053 // WARNING: the names used in C++ MUST match the Table INFO // 00055 00056 // <?xml version="1.0" encoding="UTF-8" standalone="no" ?> 00057 // <ROOT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 00058 // xsi:noNamespaceSchemaLocation="TableInfo.xsd"> <TABLE 00059 // Name="XDAQContextTable"> <VIEW Name="XDAQ_CONTEXT_TABLE" 00060 // Type="File,Database,DatabaseTest"> 00061 // <COLUMN Type="UID" Name="ContextUID" 00062 // StorageName="CONTEXT_UID" DataType="VARCHAR2"/> 00063 // <COLUMN Type="ChildLink-0" Name="LinkToApplicationTable" 00064 // StorageName="LINK_TO_APPLICATION_TABLE" DataType="VARCHAR2"/> 00065 // <COLUMN Type="ChildLinkGroupID-0" Name="ApplicationGroupID" 00066 // StorageName="APPLICATION_GROUP_ID" DataType="VARCHAR2"/> 00067 // <COLUMN Type="OnOff" Name="Status" 00068 // StorageName="STATUS" DataType="VARCHAR2"/> 00069 // <COLUMN Type="Data" Name="Id" 00070 // StorageName="ID" DataType="VARCHAR2"/> 00071 // <COLUMN Type="Data" Name="Address" 00072 // StorageName="ADDRESS" DataType="VARCHAR2"/> 00073 // <COLUMN Type="Data" Name="Port" 00074 // StorageName="PORT" DataType="VARCHAR2"/> 00075 // <COLUMN Type="Data" Name="ARTDAQDataPort" 00076 // StorageName="ARTDAQ_DATA_PORT" DataType="VARCHAR2"/> 00077 // <COLUMN Type="Comment" Name="CommentDescription" 00078 // StorageName="COMMENT_DESCRIPTION" DataType="VARCHAR2"/> 00079 // <COLUMN Type="Author" Name="Author" 00080 // StorageName="AUTHOR" DataType="VARCHAR2"/> 00081 // <COLUMN Type="Timestamp" Name="RecordInsertionTime" 00082 // StorageName="RECORD_INSERTION_TIME" DataType="TIMESTAMP WITH 00083 // TIMEZONE"/> 00084 // </VIEW> 00085 // </TABLE> 00086 // </ROOT> 00087 } 00088 00089 //======================================================================================================================== 00090 XDAQContextTable::~XDAQContextTable(void) {} 00091 00092 //======================================================================================================================== 00093 void XDAQContextTable::init(ConfigurationManager* configManager) 00094 { 00095 //__COUT__ << "init" << __E__; 00096 extractContexts(configManager); 00097 00098 { 00100 // generate xdaq run parameter file 00101 std::fstream fs; 00102 fs.open(XDAQ_RUN_FILE, std::fstream::out | std::fstream::trunc); 00103 if(fs.fail()) 00104 { 00105 __SS__ << "Failed to open XDAQ run file: " << XDAQ_RUN_FILE << __E__; 00106 __SS_THROW__; 00107 } 00108 outputXDAQXML((std::ostream&)fs); 00109 fs.close(); 00110 } 00111 } 00112 00113 //======================================================================================================================== 00114 // isARTDAQContext 00115 bool XDAQContextTable::isARTDAQContext(const std::string& contextUID) 00116 { 00117 return (contextUID.find("ART") == 0 || contextUID.find("ARTDAQ") == 0); 00118 } 00119 00120 //======================================================================================================================== 00121 std::map<std::string /*contextUID*/, 00122 std::pair<std::string /*host_name*/, unsigned int /*rank*/>> 00123 XDAQContextTable::getARTDAQAppRankMap() const 00124 { 00125 std::map<std::string /*contextUID*/, 00126 std::pair<std::string /*host_name*/, unsigned int /*rank*/>> 00127 returnMap; 00128 00129 if(artdaqBoardReaders_.size() == 0 && artdaqEventBuilders_.size() == 0 && 00130 artdaqAggregators_.size() == 0) 00131 { 00132 __COUT_WARN__ << "Assuming since there are 0 active ARTDAQ context UID(s), we " 00133 "can ignore empty rank map." 00134 << __E__; 00135 return returnMap; 00136 } 00137 00138 for(auto& i : artdaqBoardReaders_) 00139 returnMap.emplace( 00140 std::make_pair(contexts_[i].contextUID_, 00141 std::make_pair(contexts_[i].address_, 00142 getARTDAQAppRank(contexts_[i].contextUID_)))); 00143 00144 for(auto& i : artdaqEventBuilders_) 00145 returnMap.emplace( 00146 std::make_pair(contexts_[i].contextUID_, 00147 std::make_pair(contexts_[i].address_, 00148 getARTDAQAppRank(contexts_[i].contextUID_)))); 00149 00150 for(auto& i : artdaqAggregators_) 00151 returnMap.emplace( 00152 std::make_pair(contexts_[i].contextUID_, 00153 std::make_pair(contexts_[i].address_, 00154 getARTDAQAppRank(contexts_[i].contextUID_)))); 00155 00156 return returnMap; 00157 } // end getARTDAQAppRankMap 00158 00159 //======================================================================================================================== 00160 // getARTDAQAppRank 00161 // looks through all active artdaq contexts for UID 00162 // throws exception if not found 00163 // 00164 // if contextUID == "X" (which happens automatically for broken link) 00165 // then highest possible rank plus 1 is returned 00166 unsigned int XDAQContextTable::getARTDAQAppRank(const std::string& contextUID) const 00167 { 00168 if(artdaqBoardReaders_.size() == 0 && artdaqEventBuilders_.size() == 0 && 00169 artdaqAggregators_.size() == 0) 00170 { 00171 __COUT_WARN__ << "Assuming since there are 0 active ARTDAQ context UID(s), we " 00172 "can ignore rank failure." 00173 << __E__; 00174 return -1; 00175 } 00176 00177 // define local "lambda" getRank function 00178 auto localGetRank = [](const XDAQContext& context) -> unsigned int { 00179 if(context.applications_.size() != 1) 00180 { 00181 __SS__ << "Invalid number of ARTDAQ applications in context '" 00182 << context.contextUID_ << ".' Must be 1. Currently is " 00183 << context.applications_.size() << "." << __E__; 00184 __SS_THROW__; 00185 } 00186 00187 return context.applications_[0].id_; 00188 }; 00189 00190 for(auto& i : artdaqBoardReaders_) 00191 if(contexts_[i].contextUID_ == contextUID) 00192 return localGetRank(contexts_[i]); 00193 00194 for(auto& i : artdaqEventBuilders_) 00195 if(contexts_[i].contextUID_ == contextUID) 00196 return localGetRank(contexts_[i]); 00197 00198 for(auto& i : artdaqAggregators_) 00199 if(contexts_[i].contextUID_ == contextUID) 00200 return localGetRank(contexts_[i]); 00201 00202 // if (contextUID == "X") 00203 // return -1; //assume disconnected link should not error? 00204 00205 __SS__ << "ARTDAQ rank could not be found for context UID '" << contextUID << ".'" 00206 << __E__; 00207 __SS_THROW__; // should never happen! 00208 } // end getARTDAQAppRank() 00209 00210 //======================================================================================================================== 00211 std::string XDAQContextTable::getContextAddress(const std::string& contextUID, 00212 bool wantHttp) const 00213 { 00214 if(contextUID == "X") 00215 return ""; 00216 for(auto& context : contexts_) 00217 { 00218 if(context.contextUID_ == contextUID) 00219 { 00220 if(wantHttp) 00221 return context.address_; 00222 auto address = context.address_; 00223 if(address.find("http://") == 0) 00224 { 00225 address = address.replace(0, 7, ""); 00226 } 00227 if(address.find("https://") == 0) 00228 { 00229 address = address.replace(0, 8, ""); 00230 } 00231 return address; 00232 } 00233 } 00234 return ""; 00235 } 00236 00237 unsigned int XDAQContextTable::getARTDAQDataPort( 00238 const ConfigurationManager* configManager, const std::string& contextUID) const 00239 { 00240 if(contextUID == "X") 00241 return 0; 00242 for(auto& context : contexts_) 00243 { 00244 if(context.contextUID_ == contextUID) 00245 { 00246 if(context.applications_.size() != 1) 00247 { 00248 __SS__ << "Invalid number of ARTDAQ applications in context '" 00249 << contextUID << ".' Must be 1. Currently is " 00250 << context.applications_.size() << "." << __E__; 00251 __SS_THROW__; 00252 } 00253 00254 //Board Reader port is through Processor table 00255 if(context.applications_[0].class_ == "ots::ARTDAQDataManagerSupervisor" || 00256 context.applications_[0].class_ == "ots::ARTDAQFEDataManagerSupervisor") 00257 { 00258 auto processors = 00259 getSupervisorConfigNode(configManager, 00260 context.contextUID_, 00261 context.applications_[0].applicationUID_) 00262 .getNode("LinkToDataBufferTable") 00263 .getChildren()[0] 00264 .second.getNode("LinkToDataProcessorTable") 00265 .getChildren(); 00266 00267 std::string processorType; 00268 00269 // take first board reader processor (could be Consumer or Producer) 00270 for(auto& processor : processors) 00271 { 00272 processorType = processor.second.getNode("ProcessorPluginName") 00273 .getValue<std::string>(); 00274 __COUTV__(processorType); 00275 00276 if(processorType == "ARTDAQConsumer" || 00277 processorType == "ARTDAQProducer") 00278 return processor.second.getNode("LinkToProcessorTable") 00279 .getNode(XDAQContextTable::ARTDAQ_OFFSET_PORT) 00280 .getValue<unsigned int>(); 00281 } 00282 00283 __SS__ << "No ARTDAQ processor was found while looking for data port." 00284 << __E__; 00285 __SS_THROW__; 00286 } 00287 // else, Builder or Aggregator 00288 return getSupervisorConfigNode(configManager, 00289 context.contextUID_, 00290 context.applications_[0].applicationUID_) 00291 .getNode(XDAQContextTable::ARTDAQ_OFFSET_PORT) 00292 .getValue<unsigned int>(); 00293 } 00294 } 00295 return 0; 00296 } 00297 00298 //======================================================================================================================== 00299 std::vector<const XDAQContextTable::XDAQContext*> 00300 XDAQContextTable::getBoardReaderContexts() const 00301 { 00302 std::vector<const XDAQContext*> retVec; 00303 for(auto& i : artdaqBoardReaders_) 00304 retVec.push_back(&contexts_[i]); 00305 return retVec; 00306 } 00307 //======================================================================================================================== 00308 std::vector<const XDAQContextTable::XDAQContext*> 00309 XDAQContextTable::getEventBuilderContexts() const 00310 { 00311 std::vector<const XDAQContext*> retVec; 00312 for(auto& i : artdaqEventBuilders_) 00313 retVec.push_back(&contexts_[i]); 00314 return retVec; 00315 } 00316 //======================================================================================================================== 00317 std::vector<const XDAQContextTable::XDAQContext*> 00318 XDAQContextTable::getAggregatorContexts() const 00319 { 00320 std::vector<const XDAQContext*> retVec; 00321 for(auto& i : artdaqAggregators_) 00322 retVec.push_back(&contexts_[i]); 00323 return retVec; 00324 } 00325 00326 //======================================================================================================================== 00327 ConfigurationTree XDAQContextTable::getContextNode( 00328 const ConfigurationManager* configManager, const std::string& contextUID) const 00329 { 00330 return configManager->__SELF_NODE__.getNode(contextUID); 00331 } 00332 00333 //======================================================================================================================== 00334 ConfigurationTree XDAQContextTable::getApplicationNode( 00335 const ConfigurationManager* configManager, 00336 const std::string& contextUID, 00337 const std::string& appUID) const 00338 { 00339 return configManager->__SELF_NODE__.getNode( 00340 contextUID + "/" + colContext_.colLinkToApplicationTable_ + "/" + appUID); 00341 } 00342 00343 //======================================================================================================================== 00344 ConfigurationTree XDAQContextTable::getSupervisorConfigNode( 00345 const ConfigurationManager* configManager, 00346 const std::string& contextUID, 00347 const std::string& appUID) const 00348 { 00349 return configManager->__SELF_NODE__.getNode( 00350 contextUID + "/" + colContext_.colLinkToApplicationTable_ + "/" + appUID + "/" + 00351 colApplication_.colLinkToSupervisorTable_); 00352 } 00353 00354 //======================================================================================================================== 00355 // extractContexts 00356 // Could be called by other tables if they need to access the context. 00357 // This doesn't re-write config files, it just re-makes constructs in software. 00358 void XDAQContextTable::extractContexts(ConfigurationManager* configManager) 00359 { 00360 //__COUT__ << "*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*" << __E__; 00361 //__COUT__ << configManager->__SELF_NODE__ << __E__; 00362 00363 // __COUT__ << configManager->getNode(this->getTableName()).getValueAsString() 00364 // << __E__; 00365 00366 auto children = configManager->__SELF_NODE__.getChildren(); 00367 00368 contexts_.clear(); // reset 00369 // artdaqContexts_.clear(); 00370 00371 artdaqBoardReaders_.clear(); 00372 artdaqEventBuilders_.clear(); 00373 artdaqAggregators_.clear(); 00374 00375 // Enforce that app IDs do not repeat! 00376 // Note: this is important because there are maps in MacroMaker and 00377 // SupervisorDescriptorInfoBase that rely on localId() as key 00378 std::set<unsigned int /*appId*/> appIdSet; 00379 00380 for(auto& child : children) 00381 { 00382 contexts_.push_back(XDAQContext()); 00383 //__COUT__ << child.first << __E__; 00384 // __COUT__ << child.second.getNode(colContextUID_) << __E__; 00385 00386 contexts_.back().contextUID_ = child.first; 00387 00388 contexts_.back().sourceConfig_ = 00389 child.second.getTableName() + "_v" + 00390 child.second.getTableVersion().toString() + " @ " + 00391 std::to_string(child.second.getTableCreationTime()); 00392 child.second.getNode(colContext_.colContextUID_) 00393 .getValue(contexts_.back().contextUID_); 00394 child.second.getNode(colContext_.colStatus_).getValue(contexts_.back().status_); 00395 child.second.getNode(colContext_.colId_).getValue(contexts_.back().id_); 00396 child.second.getNode(colContext_.colAddress_).getValue(contexts_.back().address_); 00397 child.second.getNode(colContext_.colPort_).getValue(contexts_.back().port_); 00398 // child.second.getNode(colContext_.colARTDAQDataPort_).getValue(contexts_.back().artdaqDataPort_); 00399 00400 //__COUT__ << contexts_.back().address_ << __E__; 00401 auto appLink = child.second.getNode(colContext_.colLinkToApplicationTable_); 00402 if(appLink.isDisconnected()) 00403 { 00404 __SS__ << "Application link is disconnected!" << __E__; 00405 __SS_THROW__; 00406 } 00407 00408 // add xdaq applications to this context 00409 auto appChildren = appLink.getChildren(); 00410 for(auto appChild : appChildren) 00411 { 00412 //__COUT__ << "Loop: " << child.first << "/" << appChild.first << __E__; 00413 00414 contexts_.back().applications_.push_back(XDAQApplication()); 00415 00416 contexts_.back().applications_.back().applicationGroupID_ = child.first; 00417 contexts_.back().applications_.back().sourceConfig_ = 00418 appChild.second.getTableName() + "_v" + 00419 appChild.second.getTableVersion().toString() + " @ " + 00420 std::to_string(appChild.second.getTableCreationTime()); 00421 00422 appChild.second.getNode(colApplication_.colApplicationUID_) 00423 .getValue(contexts_.back().applications_.back().applicationUID_); 00424 appChild.second.getNode(colApplication_.colStatus_) 00425 .getValue(contexts_.back().applications_.back().status_); 00426 appChild.second.getNode(colApplication_.colClass_) 00427 .getValue(contexts_.back().applications_.back().class_); 00428 appChild.second.getNode(colApplication_.colId_) 00429 .getValue(contexts_.back().applications_.back().id_); 00430 00431 // assert Gateway is 200 00432 if((contexts_.back().applications_.back().id_ == 200 && 00433 contexts_.back().applications_.back().class_ != 00434 XDAQContextTable::GATEWAY_SUPERVISOR_CLASS && 00435 contexts_.back().applications_.back().class_ != 00436 XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS) || 00437 (contexts_.back().applications_.back().id_ != 200 && 00438 (contexts_.back().applications_.back().class_ == 00439 XDAQContextTable::GATEWAY_SUPERVISOR_CLASS || 00440 contexts_.back().applications_.back().class_ == 00441 XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS))) 00442 { 00443 __SS__ << "XDAQ Application ID of 200 is reserved for the Gateway " 00444 "Supervisor " 00445 << XDAQContextTable::GATEWAY_SUPERVISOR_CLASS 00446 << ". Conflict specifically at id=" 00447 << contexts_.back().applications_.back().id_ << " appName=" 00448 << contexts_.back().applications_.back().applicationUID_ << __E__; 00449 __SS_THROW__; 00450 } 00451 00452 // assert NO app id repeats if context/app enabled 00453 if(contexts_.back().status_ && contexts_.back().applications_.back().status_) 00454 { 00455 // assert NO app id repeats 00456 if(appIdSet.find(contexts_.back().applications_.back().id_) != 00457 appIdSet.end()) 00458 { 00459 __SS__ << "XDAQ Application IDs are not unique. Specifically at id=" 00460 << contexts_.back().applications_.back().id_ << " appName=" 00461 << contexts_.back().applications_.back().applicationUID_ 00462 << __E__; 00463 __COUT_ERR__ << "\n" << ss.str(); 00464 __SS_THROW__; 00465 } 00466 appIdSet.insert(contexts_.back().applications_.back().id_); 00467 } 00468 00469 // convert defaults to values 00470 if(appChild.second.getNode(colApplication_.colInstance_).isDefaultValue()) 00471 contexts_.back().applications_.back().instance_ = 1; 00472 else 00473 appChild.second.getNode(colApplication_.colInstance_) 00474 .getValue(contexts_.back().applications_.back().instance_); 00475 00476 if(appChild.second.getNode(colApplication_.colNetwork_).isDefaultValue()) 00477 contexts_.back().applications_.back().network_ = "local"; 00478 else 00479 appChild.second.getNode(colApplication_.colNetwork_) 00480 .getValue(contexts_.back().applications_.back().network_); 00481 00482 if(appChild.second.getNode(colApplication_.colGroup_).isDefaultValue()) 00483 contexts_.back().applications_.back().group_ = "daq"; 00484 else 00485 appChild.second.getNode(colApplication_.colGroup_) 00486 .getValue(contexts_.back().applications_.back().group_); 00487 00488 appChild.second.getNode(colApplication_.colModule_) 00489 .getValue(contexts_.back().applications_.back().module_); 00490 00491 // force deprecated Supervisor to GatewaySupervisor class 00492 if(contexts_.back().applications_.back().class_ == 00493 XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS) 00494 { 00495 contexts_.back().applications_.back().class_ = 00496 XDAQContextTable::GATEWAY_SUPERVISOR_CLASS; 00497 __COUT__ << "Fixing deprecated Supervisor class from " 00498 << XDAQContextTable::DEPRECATED_SUPERVISOR_CLASS << " to " 00499 << (contexts_.back().applications_.back().class_); 00500 } 00501 if(contexts_.back().applications_.back().module_.find("libSupervisor.so") != 00502 std::string::npos) 00503 { 00504 __COUT__ << "Fixing deprecated Supervisor class from " 00505 << contexts_.back().applications_.back().module_ << " to "; 00506 contexts_.back().applications_.back().module_ = 00507 contexts_.back().applications_.back().module_.substr( 00508 0, 00509 contexts_.back().applications_.back().module_.size() - 00510 std::string("Supervisor.so").size()) + 00511 "GatewaySupervisor.so"; 00512 std::cout << contexts_.back().applications_.back().module_ << __E__; 00513 } 00514 00515 try 00516 { 00517 appChild.second.getNode(colApplication_.colConfigurePriority_) 00518 .getValue(contexts_.back() 00519 .applications_.back() 00520 .stateMachineCommandPriority_["Configure"]); 00521 appChild.second.getNode(colApplication_.colStartPriority_) 00522 .getValue(contexts_.back() 00523 .applications_.back() 00524 .stateMachineCommandPriority_["Start"]); 00525 appChild.second.getNode(colApplication_.colStopPriority_) 00526 .getValue(contexts_.back() 00527 .applications_.back() 00528 .stateMachineCommandPriority_["Stop"]); 00529 } 00530 catch(...) 00531 { 00532 __COUT__ << "Ignoring missing state machine priorities..." << __E__; 00533 } 00534 00535 auto appPropertyLink = 00536 appChild.second.getNode(colApplication_.colLinkToPropertyTable_); 00537 if(!appPropertyLink.isDisconnected()) 00538 { 00539 // add xdaq application properties to this context 00540 00541 auto appPropertyChildren = appPropertyLink.getChildren(); 00542 00543 //__COUT__ << "appPropertyChildren.size() " << appPropertyChildren.size() 00544 //<< __E__; 00545 00546 for(auto appPropertyChild : appPropertyChildren) 00547 { 00548 contexts_.back().applications_.back().properties_.push_back( 00549 XDAQApplicationProperty()); 00550 contexts_.back().applications_.back().properties_.back().status_ = 00551 appPropertyChild.second.getNode(colAppProperty_.colStatus_) 00552 .getValue<bool>(); 00553 contexts_.back().applications_.back().properties_.back().name_ = 00554 appPropertyChild.second.getNode(colAppProperty_.colPropertyName_) 00555 .getValue<std::string>(); 00556 contexts_.back().applications_.back().properties_.back().type_ = 00557 appPropertyChild.second.getNode(colAppProperty_.colPropertyType_) 00558 .getValue<std::string>(); 00559 contexts_.back().applications_.back().properties_.back().value_ = 00560 appPropertyChild.second.getNode(colAppProperty_.colPropertyValue_) 00561 .getValue<std::string>(); 00562 00563 //__COUT__ << 00564 // contexts_.back().applications_.back().properties_.back().name_ << 00565 // __E__; 00566 } 00567 } 00568 // else 00569 // __COUT__ << "Disconnected." << __E__; 00570 } 00571 00572 // check artdaq type 00573 if(isARTDAQContext(contexts_.back().contextUID_)) 00574 { 00575 // artdaqContexts_.push_back(contexts_.size() - 1); 00576 00577 if(contexts_.back().applications_.size() != 1) 00578 { 00579 __SS__ << "ARTDAQ Context '" << contexts_.back().contextUID_ 00580 << "' must have one Application! " 00581 << contexts_.back().applications_.size() << " were found. " 00582 << __E__; 00583 __SS_THROW__; 00584 } 00585 00586 if(!contexts_.back().status_) 00587 continue; // skip if disabled 00588 00589 if(contexts_.back().applications_[0].class_ == // if board reader 00590 "ots::ARTDAQDataManagerSupervisor" || 00591 contexts_.back().applications_[0].class_ == // if board reader 00592 "ots::ARTDAQFEDataManagerSupervisor") 00593 artdaqBoardReaders_.push_back(contexts_.size() - 1); 00594 else if(contexts_.back().applications_[0].class_ == // if event builder 00595 "ots::EventBuilderApp") 00596 artdaqEventBuilders_.push_back(contexts_.size() - 1); 00597 else if(contexts_.back().applications_[0].class_ == // if aggregator 00598 "ots::DataLoggerApp" || 00599 contexts_.back().applications_[0].class_ == // if aggregator 00600 "ots::DispatcherApp") 00601 artdaqAggregators_.push_back(contexts_.size() - 1); 00602 else 00603 { 00604 __SS__ << "ARTDAQ Context must be have Application of an allowed class " 00605 "type:\n" 00606 << "\tots::ARTDAQDataManagerSupervisor (Board Reader)\n" 00607 << "\tots::ARTDAQFEDataManagerSupervisor (Board Reader)\n" 00608 << "\tots::EventBuilderApp (Event Builder)\n" 00609 << "\tots::DataLoggerApp (Aggregator)\n" 00610 << "\tots::DispatcherApp (Aggregator)\n" 00611 << "\nClass found was " << contexts_.back().applications_[0].class_ 00612 << __E__; 00613 __SS_THROW__; 00614 } 00615 } 00616 } 00617 } 00618 00619 //======================================================================================================================== 00620 // void XDAQContextTable::outputXDAQScript(std::ostream &out) 00621 //{ 00622 /* 00623 the file will look something like this: 00624 #!/bin/sh 00625 00626 echo 00627 echo 00628 00629 echo "Launching XDAQ contexts..." 00630 00631 #for each XDAQ context 00632 xdaq.exe -p ${CONTEXT_PORT} -e ${XDAQ_ARGS} & 00633 00634 */ 00635 00636 // out << "#!/bin/sh\n\n"; 00637 // 00638 // out << "echo\necho\n\n"; 00639 // 00640 // out << "echo \"Launching XDAQ contexts...\"\n\n"; 00641 // out << "#for each XDAQ context\n"; 00642 // 00643 // 00644 // std::stringstream ss; 00645 // int count = 0; 00646 // //for each non-"ART" or "ARTDAQ" context make a xdaq entry 00647 // for(XDAQContext &context:contexts_) 00648 // { 00649 // if(isARTDAQContext(context.contextUID_)) 00650 // continue; //skip if UID does identify as artdaq 00651 // 00652 // if(!context.status_) 00653 // continue; //skip if disabled 00654 // 00655 // //at this point we have a xdaq context.. so make an xdaq entry 00656 // 00657 // ++count; 00658 // ss << "echo \"xdaq.exe -p " << 00659 // context.port_ << " -e ${XDAQ_ARGS} &\"\n"; 00660 // ss << "xdaq.exe -p " << 00661 // context.port_ << " -e ${XDAQ_ARGS} & " << 00662 // "#" << context.contextUID_ << "\n"; 00663 // } 00664 // 00665 // 00666 // if(count == 0) //if no artdaq contexts at all 00667 // { 00668 // out << "echo \"No XDAQ (non-artdaq) contexts found.\"\n\n"; 00669 // out << "echo\necho\n"; 00670 // return; 00671 // } 00672 // 00673 // out << ss.str(); 00674 // 00675 // out << "\n\n"; 00676 //} 00677 00679 // void XDAQContextTable::outputARTDAQScript(std::ostream &out) 00680 //{ 00681 /* 00682 the file will look something like this: 00683 #!/bin/sh 00684 00685 00686 echo 00687 echo 00688 while [ 1 ]; do 00689 00690 echo "Cleaning up old MPI instance..." 00691 killall mpirun 00692 00693 00694 echo "Starting mpi run..." 00695 echo "$1" 00696 echo 00697 echo 00698 00699 echo mpirun $1 \ 00700 -np 1 xdaq.exe -p ${ARTDAQ_BOARDREADER_PORT1} -e ${XDAQ_ARGS} : 00701 \ 00702 -np 1 xdaq.exe -p ${ARTDAQ_BOARDREADER_PORT2} -e ${XDAQ_ARGS} : 00703 \ 00704 -np 1 xdaq.exe -p ${ARTDAQ_BUILDER_PORT} -e ${XDAQ_ARGS} : 00705 \ -np 1 xdaq.exe -p ${ARTDAQ_AGGREGATOR_PORT} -e ${XDAQ_ARGS} & 00706 00707 echo 00708 echo 00709 00710 ret=mpirun $1 \ 00711 -np 1 xdaq.exe -p ${ARTDAQ_BOARDREADER_PORT1} -e ${XDAQ_ARGS} : \ 00712 -np 1 xdaq.exe -p ${ARTDAQ_BOARDREADER_PORT2} -e ${XDAQ_ARGS} : \ 00713 -np 1 xdaq.exe -p ${ARTDAQ_BUILDER_PORT} -e ${XDAQ_ARGS} : \ 00714 -np 1 xdaq.exe -p ${ARTDAQ_AGGREGATOR_PORT} -e ${XDAQ_ARGS} 00715 00716 if [ $ret -eq 0 ]; then 00717 exit 00718 fi 00719 00720 done 00721 */ 00722 00723 // __COUT__ << artdaqContexts_.size() << " total artdaq context(s)." << __E__; 00724 // __COUT__ << artdaqBoardReaders_.size() << " active artdaq board reader(s)." << 00725 // __E__; 00726 // __COUT__ << artdaqEventBuilders_.size() << " active artdaq event builder(s)." << 00727 // __E__; 00728 // __COUT__ << artdaqAggregators_.size() << " active artdaq aggregator(s)." << __E__; 00729 // 00730 // out << "#!/bin/sh\n\n"; 00731 // 00732 // out << "\techo\n\techo\n\n"; 00733 // //out << "while [ 1 ]; do\n\n"; 00734 // 00735 // //out << "\techo \"Cleaning up old MPI instance...\"\n"; 00736 // 00737 // out << "\techo \"" << 00738 // artdaqContexts_.size() << " artdaq Contexts." << 00739 // "\"\n"; 00740 // out << "\techo \"\t" << 00741 // artdaqBoardReaders_.size() << " artdaq board readers." << 00742 // "\"\n"; 00743 // out << "\techo \"\t" << 00744 // artdaqEventBuilders_.size() << " artdaq event builders." << 00745 // "\"\n"; 00746 // out << "\techo \"\t" << 00747 // artdaqAggregators_.size() << " artdaq aggregators_." << 00748 // "\"\n"; 00749 // 00750 // //out << "\tkillall mpirun\n"; 00751 // out << "\techo\n\techo\n\n"; 00752 // 00753 // out << "\techo \"Starting mpi run...\"\n"; 00754 // out << "\techo \"$1\"\n\techo\n\techo\n\n"; 00755 // 00756 // 00757 // 00758 // std::stringstream ss,ssUID; 00759 // int count = 0; 00760 // 00761 // //ss << "\tret=`mpirun $1 \\\n"; ` 00762 // 00763 // ss << "\tmpirun $1 \\\n"; 00764 // 00765 // //for each "ART" or "ARTDAQ" context make an mpi entry 00766 // //make an mpi entry for board readers, then event builders, then aggregators 00767 // 00768 // for(auto &i:artdaqBoardReaders_) 00769 // { 00770 // if(count++) //add line breaks if not first context 00771 // ss << ": \\\n"; 00772 // 00773 // ss << " -np 1 xdaq.exe -p " << 00774 // contexts_[i].port_ << " -e ${XDAQ_ARGS} "; 00775 // 00776 // ssUID << "\n\t#board reader \t context.port_ \t " << contexts_[i].port_ << 00777 // ": \t" << contexts_[i].contextUID_; 00778 // } 00779 // 00780 // for(auto &i:artdaqEventBuilders_) 00781 // { 00782 // if(count++) //add line breaks if not first context 00783 // ss << ": \\\n"; 00784 // 00785 // ss << " -np 1 xdaq.exe -p " << 00786 // contexts_[i].port_ << " -e ${XDAQ_ARGS} "; 00787 // 00788 // ssUID << "\n\t#event builder \t context.port_ \t " << contexts_[i].port_ << 00789 // ": \t" << contexts_[i].contextUID_; 00790 // } 00791 // 00792 // for(auto &i:artdaqAggregators_) 00793 // { 00794 // if(count++) //add line breaks if not first context 00795 // ss << ": \\\n"; 00796 // 00797 // ss << " -np 1 xdaq.exe -p " << 00798 // contexts_[i].port_ << " -e ${XDAQ_ARGS} "; 00799 // 00800 // ssUID << "\n\t#aggregator \t context.port_ \t " << contexts_[i].port_ << 00801 // ": \t" << contexts_[i].contextUID_; 00802 // } 00803 // 00804 // 00805 // if(count == 0) //if no artdaq contexts at all 00806 // { 00807 // out << "\techo \"No ARTDAQ contexts found. So no mpirun necessary.\"\n\n"; 00808 // out << "\techo\necho\n"; 00809 // return; 00810 // } 00811 // 00812 // out << "\techo \"" << ss.str() << "\""; //print mpirun 00813 // out << "\t\n\techo\n\techo\n\n"; 00814 // out << ssUID.str() << "\n\n"; 00815 // out << ss.str(); //run mpirun 00816 // 00817 // out << "\n\n"; 00818 // //out << ""\tif [ ${ret:-1} -eq 0 ]; then\n\t\texit\n\tfi\n"; 00819 // //out << "\ndone\n"; 00820 //} 00821 // 00822 // 00824 // void XDAQContextTable::outputAppPriority(std::ostream &out, const std::string& 00825 // stateMachineCommand) 00826 //{ 00827 // //output app ID and priority order [1:255] pairs.. new line separated 00828 // // 0/undefined gets translated to 100 00829 // 00830 // for (XDAQContext &context : contexts_) 00831 // for (XDAQApplication &app : context.applications_) 00832 // { 00833 // out << app.id_ << "\n"; 00834 // 00835 // if(app.stateMachineCommandPriority_.find(stateMachineCommand) == 00836 // app.stateMachineCommandPriority_.end()) out << 100; else 00837 // out << ((app.stateMachineCommandPriority_[stateMachineCommand])? 00838 // app.stateMachineCommandPriority_[stateMachineCommand]:100); 00839 // 00840 // out << "\n"; 00841 // } 00842 //} 00843 00844 //======================================================================================================================== 00845 void XDAQContextTable::outputXDAQXML(std::ostream& out) 00846 { 00847 // each generated context will look something like this: 00848 //<xc:Context id="0" url="http://${SUPERVISOR_SERVER}:${PORT}"> 00852 //</xc:Context> 00853 00854 // print xml header information and declare xc partition 00855 out << "<?xml version='1.0'?>\n" 00856 << "<xc:Partition \txmlns:xsi\t= \"http://www.w3.org/2001/XMLSchema-instance\"\n" 00857 << "\t\txmlns:soapenc\t= \"http://schemas.xmlsoap.org/soap/encoding/\"\n" 00858 << "\t\txmlns:xc\t= " 00859 "\"http://xdaq.web.cern.ch/xdaq/xsd/2004/XMLConfiguration-30\">\n\n"; 00860 00861 // print partition open 00862 // for each context 00863 // open context 00864 // for each app in context 00865 // print application 00866 // print module 00867 // close context 00868 // close partition 00869 00870 char tmp[200]; 00871 for(XDAQContext& context : contexts_) 00872 { 00873 //__COUT__ << context.contextUID_ << __E__; 00874 00875 sprintf(tmp, 00876 "\t<!-- ContextUID='%s' sourceConfig='%s' -->", 00877 context.contextUID_.c_str(), 00878 context.sourceConfig_.c_str()); 00879 out << tmp << "\n"; 00880 00881 if(!context.status_) // comment out if disabled 00882 out << "\t<!--\n"; 00883 00884 sprintf(tmp, 00885 "\t<xc:Context id=\"%u\" url=\"%s:%u\">", 00886 context.id_, 00887 context.address_.c_str(), 00888 context.port_); 00889 out << tmp << "\n\n"; 00890 00891 for(XDAQApplication& app : context.applications_) 00892 { 00893 //__COUT__ << app.id_ << __E__; 00894 00895 if(context.status_) 00896 { 00897 sprintf( 00898 tmp, 00899 "\t\t<!-- Application GroupID = '%s' UID='%s' sourceConfig='%s' -->", 00900 app.applicationGroupID_.c_str(), 00901 app.applicationUID_.c_str(), 00902 app.sourceConfig_.c_str()); 00903 out << tmp << "\n"; 00904 00905 if(!app.status_) // comment out if disabled 00906 out << "\t\t<!--\n"; 00907 } 00908 00909 sprintf(tmp, 00910 "\t\t<xc:Application class=\"%s\" id=\"%u\" instance=\"%u\" " 00911 "network=\"%s\" group=\"%s\">\n", 00912 app.class_.c_str(), 00913 app.id_, 00914 app.instance_, 00915 app.network_.c_str(), 00916 app.group_.c_str()); 00917 out << tmp; 00918 00920 int foundColon = app.class_.rfind(':'); 00921 if(foundColon >= 0) 00922 ++foundColon; 00923 else 00924 { 00925 __SS__ << "Illegal XDAQApplication class name value of '" << app.class_ 00926 << "' - please check the entry for app ID = " << app.id_ << __E__; 00927 __SS_THROW__; 00928 } 00929 out << "\t\t\t<properties xmlns=\"urn:xdaq-application:" 00930 << app.class_.substr(foundColon) << "\" xsi:type=\"soapenc:Struct\">\n"; 00931 00932 //__COUT__ << "app.properties_ " << app.properties_.size() << __E__; 00933 for(XDAQApplicationProperty& appProperty : app.properties_) 00934 { 00935 if(appProperty.type_ == "ots::SupervisorProperty") 00936 continue; // skip ots Property values 00937 00938 if(!appProperty.status_) 00939 out << "\t\t\t\t<!--\n"; 00940 00941 sprintf(tmp, 00942 "\t\t\t\t<%s xsi:type=\"%s\">%s</%s>\n", 00943 appProperty.name_.c_str(), 00944 appProperty.type_.c_str(), 00945 appProperty.value_.c_str(), 00946 appProperty.name_.c_str()); 00947 out << tmp; 00948 00949 if(!appProperty.status_) 00950 out << "\t\t\t\t-->\n"; 00951 } 00952 out << "\t\t\t</properties>\n"; 00954 00955 out << "\t\t</xc:Application>\n"; 00956 00957 sprintf(tmp, "\t\t<xc:Module>%s</xc:Module>\n", app.module_.c_str()); 00958 out << tmp; 00959 00960 if(context.status_ && !app.status_) 00961 out << "\t\t-->\n"; 00962 out << "\n"; 00963 00964 // __COUT__ << "DONE" << __E__; 00965 } 00966 00967 out << "\t</xc:Context>\n"; 00968 if(!context.status_) 00969 out << "\t-->\n"; 00970 out << "\n"; 00971 } 00972 00973 //__COUT__ << "DONE" << __E__; 00974 out << "</xc:Partition>\n\n\n"; 00975 } 00976 00977 //======================================================================================================================== 00978 std::string XDAQContextTable::getContextUID(const std::string& url) const 00979 { 00980 for(auto context : contexts_) 00981 { 00982 if(!context.status_) 00983 continue; 00984 00985 if(url == context.address_ + ":" + std::to_string(context.port_)) 00986 return context.contextUID_; 00987 } 00988 return ""; 00989 } 00990 00991 //======================================================================================================================== 00992 std::string XDAQContextTable::getApplicationUID(const std::string& url, 00993 unsigned int id) const 00994 { 00995 //__COUTV__(url); __COUTV__(id); 00996 for(auto context : contexts_) 00997 { 00998 //__COUT__ << "Checking " << (context.address_ + ":" + 00999 // std::to_string(context.port_)) << __E__; 01000 //__COUTV__(context.status_); 01001 01002 if(!context.status_) 01003 continue; 01004 01005 //__COUT__ << "Checking " << (context.address_ + ":" + 01006 // std::to_string(context.port_)) << __E__; 01007 if(url == context.address_ + ":" + std::to_string(context.port_)) 01008 for(auto application : context.applications_) 01009 { 01010 //__COUTV__(application.status_); __COUTV__(application.id_); 01011 if(!application.status_) 01012 continue; 01013 01014 if(application.id_ == id) 01015 { 01016 return application.applicationUID_; 01017 } 01018 } 01019 } 01020 return ""; 01021 } 01022 01023 DEFINE_OTS_TABLE(XDAQContextTable)