otsdaq  v2_01_00
DispatcherApp.cc
1 #include "otsdaq/DispatcherApp/DispatcherApp.h"
2 #include "otsdaq-core/MessageFacility/MessageFacility.h"
3 #include "otsdaq-core/Macros/CoutMacros.h"
4 #include "otsdaq-core/XmlUtilities/HttpXmlDocument.h"
5 #include "otsdaq-core/SOAPUtilities/SOAPUtilities.h"
6 #include "otsdaq-core/SOAPUtilities/SOAPCommand.h"
7 
8 #include "otsdaq-core/ConfigurationDataFormats/ConfigurationGroupKey.h"
9 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
10 #include "otsdaq-core/ConfigurationPluginDataFormats/XDAQContextConfiguration.h"
11 
12 #include <toolbox/fsm/FailedEvent.h>
13 
14 #include <xdaq/NamespaceURI.h>
15 #include <xoap/Method.h>
16 
17 #include "artdaq/DAQdata/Globals.hh"
18 #include <memory>
19 #include "messagefacility/MessageLogger/MessageLogger.h"
20 #include "artdaq-core/Utilities/configureMessageFacility.hh"
21 #include "cetlib/exception.h"
22 #include "artdaq/BuildInfo/GetPackageBuildInfo.hh"
23 #include "fhiclcpp/make_ParameterSet.h"
24 
25 #include <fstream>
26 #include <iostream>
27 #include <cassert>
28 
29 using namespace ots;
30 
31 XDAQ_INSTANTIATOR_IMPL(DispatcherApp)
32 
33 //========================================================================================================================
34 DispatcherApp::DispatcherApp(xdaq::ApplicationStub * s)
35  : xdaq::Application(s)
36  , SOAPMessenger(this)
37  , stateMachineWorkLoopManager_(toolbox::task::bind(this, &DispatcherApp::stateMachineThread, "StateMachine"))
38  , stateMachineSemaphore_(toolbox::BSem::FULL)
39  , theConfigurationManager_(new ConfigurationManager)//(Singleton<ConfigurationManager>::getInstance()) //I always load the full config but if I want to load a partial configuration (new ConfigurationManager)
40  , XDAQContextConfigurationName_(theConfigurationManager_->__GET_CONFIG__(XDAQContextConfiguration)->getConfigurationName())
41  , supervisorConfigurationPath_("INITIALIZED INSIDE THE CONTRUCTOR BECAUSE IT NEEDS supervisorContextUID_ and supervisorApplicationUID_")
42  , supervisorContextUID_("INITIALIZED INSIDE THE CONTRUCTOR TO LAUNCH AN EXCEPTION")
43  , supervisorApplicationUID_("INITIALIZED INSIDE THE CONTRUCTOR TO LAUNCH AN EXCEPTION")
44 {
45  INIT_MF("DispatcherApp");
46  xgi::bind(this, &DispatcherApp::Default, "Default");
47  xgi::bind(this, &DispatcherApp::stateMachineXgiHandler, "StateMachineXgiHandler");
48 
49  xoap::bind(this, &DispatcherApp::stateMachineStateRequest, "StateMachineStateRequest", XDAQ_NS_URI);
50  xoap::bind(this, &DispatcherApp::stateMachineErrorMessageRequest, "StateMachineErrorMessageRequest", XDAQ_NS_URI);
51 
52  try
53  {
54  supervisorContextUID_ = theConfigurationManager_->__GET_CONFIG__(XDAQContextConfiguration)->getContextUID(getApplicationContext()->getContextDescriptor()->getURL());
55  }
56  catch (...)
57  {
58  __COUT_ERR__ << "XDAQ Supervisor could not access it's configuration through the Configuration Context Group." <<
59  " The XDAQContextConfigurationName = " << XDAQContextConfigurationName_ <<
60  ". The supervisorApplicationUID = " << supervisorApplicationUID_ << std::endl;
61  throw;
62  }
63  try
64  {
65  supervisorApplicationUID_ = theConfigurationManager_->__GET_CONFIG__(XDAQContextConfiguration)->getApplicationUID
66  (
67  getApplicationContext()->getContextDescriptor()->getURL(),
68  getApplicationDescriptor()->getLocalId()
69  );
70  }
71  catch (...)
72  {
73  __COUT_ERR__ << "XDAQ Supervisor could not access it's configuration through the Configuration Application Group."
74  << " The supervisorApplicationUID = " << supervisorApplicationUID_ << std::endl;
75  throw;
76  }
77  supervisorConfigurationPath_ = "/" + supervisorContextUID_ + "/LinkToApplicationConfiguration/" + supervisorApplicationUID_ + "/LinkToSupervisorConfiguration";
78 
79  setStateMachineName(supervisorApplicationUID_);
80  init();
81 }
82 
83 //========================================================================================================================
84 DispatcherApp::~DispatcherApp(void)
85 {
86  destroy();
87 }
88 //========================================================================================================================
89 void DispatcherApp::init(void)
90 {
91  std::cout << __COUT_HDR_FL__ << "ARTDAQDispatcher SUPERVISOR INIT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
92  allSupervisorInfo_.init(getApplicationContext());
93  artdaq::configureMessageFacility("Dispatcher");
94 
95  // initialization
96 
97  std::cout << __COUT_HDR_FL__ << "ARTDAQDispatcher SUPERVISOR INIT4!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
98  std::string name = "Dispatcher";
99  unsigned short port = 5300;
100  // artdaq::setMsgFacAppName(supervisorApplicationUID_, port);
101  artdaq::setMsgFacAppName(name, port);
102  // mf::LogDebug(supervisorApplicationUID_) << "artdaq version " <<
103  mf::LogDebug(name + "Supervisor") << "artdaq version " <<
104  artdaq::GetPackageBuildInfo::getPackageBuildInfo().getPackageVersion()
105  << ", built " <<
106  artdaq::GetPackageBuildInfo::getPackageBuildInfo().getBuildTimestamp();
107 
108  // create the DispatcherInterface
109  app_name = name;
110  my_rank = this->getApplicationDescriptor()->getLocalId();
111  theDispatcherInterface_ = new artdaq::DispatcherApp();
112  //theDispatcherInterface_ = new DispatcherInterface(mpiSentry_->rank(), local_group_comm, supervisorApplicationUID_ );
113 }
114 
115 //========================================================================================================================
116 void DispatcherApp::destroy(void)
117 {
118  delete theDispatcherInterface_;
119 }
120 
121 //========================================================================================================================
122 void DispatcherApp::Default(xgi::Input * in, xgi::Output * out)
123 {
124 
125  *out << "<!DOCTYPE HTML><html lang='en'><frameset col='100%' row='100%'><frame src='/WebPath/html/DispatcherApp.html?urn=" <<
126  this->getApplicationDescriptor()->getLocalId() << "'></frameset></html>";
127 }
128 
129 //========================================================================================================================
130 void DispatcherApp::stateMachineXgiHandler(xgi::Input * in, xgi::Output * out)
131 {}
132 
133 //========================================================================================================================
134 void DispatcherApp::stateMachineResultXgiHandler(xgi::Input* in, xgi::Output* out)
135 {}
136 
137 //========================================================================================================================
138 xoap::MessageReference DispatcherApp::stateMachineXoapHandler(xoap::MessageReference message)
139 {
140  std::cout << __COUT_HDR_FL__ << "Soap Handler!" << std::endl;
141  stateMachineWorkLoopManager_.removeProcessedRequests();
142  stateMachineWorkLoopManager_.processRequest(message);
143  std::cout << __COUT_HDR_FL__ << "Done - Soap Handler!" << std::endl;
144  return message;
145 }
146 
147 //========================================================================================================================
148 xoap::MessageReference DispatcherApp::stateMachineResultXoapHandler(xoap::MessageReference message)
149 {
150  std::cout << __COUT_HDR_FL__ << "Soap Handler!" << std::endl;
151  //stateMachineWorkLoopManager_.removeProcessedRequests();
152  //stateMachineWorkLoopManager_.processRequest(message);
153  std::cout << __COUT_HDR_FL__ << "Done - Soap Handler!" << std::endl;
154  return message;
155 }
156 
157 //========================================================================================================================
158 bool DispatcherApp::stateMachineThread(toolbox::task::WorkLoop* workLoop)
159 {
160  stateMachineSemaphore_.take();
161  std::cout << __COUT_HDR_FL__ << "Re-sending message..." << SOAPUtilities::translate(stateMachineWorkLoopManager_.getMessage(workLoop)).getCommand() << std::endl;
162  std::string reply = send(this->getApplicationDescriptor(), stateMachineWorkLoopManager_.getMessage(workLoop));
163  stateMachineWorkLoopManager_.report(workLoop, reply, 100, true);
164  std::cout << __COUT_HDR_FL__ << "Done with message" << std::endl;
165  stateMachineSemaphore_.give();
166  return false;//execute once and automatically remove the workloop so in WorkLoopManager the try workLoop->remove(job_) could be commented out
167  //return true;//go on and then you must do the workLoop->remove(job_) in WorkLoopManager
168 }
169 
170 //========================================================================================================================
171 xoap::MessageReference DispatcherApp::stateMachineStateRequest(xoap::MessageReference message)
172 {
173  std::cout << __COUT_HDR_FL__ << theStateMachine_.getCurrentStateName() << std::endl;
174  return SOAPUtilities::makeSOAPMessageReference(theStateMachine_.getCurrentStateName());
175 }
176 
177 //========================================================================================================================
178 xoap::MessageReference DispatcherApp::stateMachineErrorMessageRequest(xoap::MessageReference message)
179 
180 {
181  __COUT__ << "theStateMachine_.getErrorMessage() = " << theStateMachine_.getErrorMessage() << std::endl;
182 
183  SOAPParameters retParameters;
184  retParameters.addParameter("ErrorMessage", theStateMachine_.getErrorMessage());
185  return SOAPUtilities::makeSOAPMessageReference("stateMachineErrorMessageRequestReply", retParameters);
186 }
187 
188 //========================================================================================================================
189 void DispatcherApp::stateInitial(toolbox::fsm::FiniteStateMachine& fsm)
190 {
191 
192 }
193 
194 //========================================================================================================================
195 void DispatcherApp::stateHalted(toolbox::fsm::FiniteStateMachine& fsm)
196 {
197 
198 }
199 
200 //========================================================================================================================
201 void DispatcherApp::stateRunning(toolbox::fsm::FiniteStateMachine& fsm)
202 {
203 
204 }
205 
206 //========================================================================================================================
207 void DispatcherApp::stateConfigured(toolbox::fsm::FiniteStateMachine& fsm)
208 {
209 
210 }
211 
212 //========================================================================================================================
213 void DispatcherApp::statePaused(toolbox::fsm::FiniteStateMachine& fsm)
214 {
215 
216 }
217 
218 //========================================================================================================================
219 void DispatcherApp::inError(toolbox::fsm::FiniteStateMachine & fsm)
220 {
221  std::cout << __COUT_HDR_FL__ << "Fsm current state: " << theStateMachine_.getCurrentStateName() << std::endl;
222  //rcmsStateNotifier_.stateChanged("Error", "");
223 }
224 
225 //========================================================================================================================
226 void DispatcherApp::enteringError(toolbox::Event::Reference e)
227 {
228  std::cout << __COUT_HDR_FL__ << "Fsm current state: " << theStateMachine_.getCurrentStateName() << std::endl;
229  toolbox::fsm::FailedEvent& failedEvent = dynamic_cast<toolbox::fsm::FailedEvent&>(*e);
230  std::ostringstream error;
231  error << "Failure performing transition from "
232  << failedEvent.getFromState()
233  << " to "
234  << failedEvent.getToState()
235  << " exception: " << failedEvent.getException().what();
236  std::cout << __COUT_HDR_FL__ << error.str() << std::endl;
237  //diagService_->reportError(errstr.str(),DIAGERROR);
238 
239 }
240 
241 
242 #define ARTDAQ_FCL_PATH std::string(getenv("USER_DATA")) + "/"+ "ARTDAQConfigurations/"
243 #define ARTDAQ_FILE_PREAMBLE "aggregator"
244 //========================================================================================================================
245 void DispatcherApp::transitionConfiguring(toolbox::Event::Reference e)
246 {
247 
248  std::cout << __COUT_HDR_FL__ << "ARTDAQDispatcher SUPERVISOR CONFIGURING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl;
249  std::cout << __COUT_HDR_FL__ << SOAPUtilities::translate(theStateMachine_.getCurrentMessage()) << std::endl;
250 
251  std::pair<std::string /*group name*/, ConfigurationGroupKey> theGroup(
252  SOAPUtilities::translate(theStateMachine_.getCurrentMessage()).
253  getParameters().getValue("ConfigurationGroupName"),
254  ConfigurationGroupKey(SOAPUtilities::translate(theStateMachine_.getCurrentMessage()).
255  getParameters().getValue("ConfigurationGroupKey")));
256 
257  __COUT__ << "Configuration group name: " << theGroup.first << " key: " <<
258  theGroup.second << std::endl;
259 
260  theConfigurationManager_->loadConfigurationGroup(
261  theGroup.first,
262  theGroup.second, true);
263 
264 
265  std::string path = "";
266  char* dirMRB = getenv("MRB_BUILDDIR");
267  char* dirP = getenv("OTSDAQ_DIR");
268 
269  if (dirMRB) { path = std::string(dirMRB) + "/otsdaq_demo/"; }
270  else if (dirP) { path = std::string(dirP) + "/"; }
271 
272  //Now that the configuration manager has all the necessary configurations I can create all objects dependent of the configuration
273  //std::string configString = "daq:{Dispatcher:{event_builder_count:2 event_queue_depth:20 event_queue_wait_time:5 expected_events_per_bunch:1 file_duration:0 file_event_count:0 file_size_MB:0 first_event_builder_rank:2 mpi_buffer_count:8 print_event_store_stats:true xmlrpc_client_list:\";http://localhost:5603/RPC2,3;http://localhost:5604/RPC2,3;http://localhost:5605/RPC2,4;http://localhost:5606/RPC2,4;http://localhost:5601/RPC2,5;http://localhost:5602/RPC2,5\"} max_fragment_size_words:2.097152e6} outputs:{normalOutput:{fileName:\"/data/otsdata/data/artdaqots_r%06r_sr%02s_%to.root\" module_type:\"RootOutput\"}} physics:{my_output_modules:[\"normalOutput\"] p2:[\"BuildInfo\"] producers:{BuildInfo:{instance_name:\"ArtdaqOts\" module_type:\"ArtdaqOtsBuildInfo\"}}} process_name:\"DAQAG\" services:{Timing:{summaryOnly:true} scheduler:{fileMode:\"NOMERGE\"} user:{NetMonTransportServiceInterface:{max_fragment_size_words:2.097152e6 service_provider:\"NetMonTransportService\"}}} source:{module_type:\"NetMonInput\"}";
274  //ONLY 1 BOARD READER
275  // std::string configString = "daq:{Dispatcher:{event_builder_count:1 event_queue_depth:20 event_queue_wait_time:5 expected_events_per_bunch:1 file_duration:0 file_event_count:0 file_size_MB:0 first_event_builder_rank:1 mpi_buffer_count:8 print_event_store_stats:true xmlrpc_client_list:\";http://localhost:5100/RPC2,3;http://localhost:5101/RPC2,3;http://localhost:5200/RPC2,4;http://localhost:5201/RPC2,4;http://localhost:5300/RPC2,5;http://localhost:5301/RPC2,5\"} max_fragment_size_words:2.097152e6} outputs:{normalOutput:{fileName:\""+path+"artdaqots_r%06r_sr%02s_%to.root\" module_type:\"RootOutput\"}} physics:{my_output_modules:[\"normalOutput\"] p2:[\"BuildInfo\"] a1:[\"wf\"] producers:{BuildInfo:{instance_name:\"ArtdaqOts\" module_type:\"ArtdaqOtsBuildInfo\"}} analyzers:{wf: {module_type:\"WFViewer\" fragment_ids:[0] fragment_type_labels:[ \"DataGen\" ] prescale:60 write_to_file:true fileName:\""+path+"otsdaqdemo_onmon.root\"}}} process_name:\"DAQAG\" services:{Timing:{summaryOnly:true} scheduler:{fileMode:\"NOMERGE\" errorOnFailureToPut: false} NetMonTransportServiceInterface:{max_fragment_size_words:2097152 service_provider:\"NetMonTransportService\"}} source:{module_type:\"NetMonInput\"}";
276  //2 BOARD READERS
277  //std::string configString = "daq:{Dispatcher:{event_builder_count:1 event_queue_depth:20 event_queue_wait_time:5 expected_events_per_bunch:1 file_duration:0 file_event_count:0 file_size_MB:0 first_event_builder_rank:1 mpi_buffer_count:8 print_event_store_stats:true xmlrpc_client_list:\";http://localhost:5100/RPC2,3;http://localhost:5101/RPC2,3;http://localhost:5200/RPC2,4;http://localhost:5201/RPC2,4;http://localhost:5300/RPC2,5;http://localhost:5301/RPC2,5\"} max_fragment_size_words:2.097152e6} outputs:{normalOutput:{fileName:\""+path+"artdaqots_r%06r_sr%02s_%to.root\" module_type:\"RootOutput\"}} physics:{my_output_modules:[\"normalOutput\"] p2:[\"BuildInfo\"] a1:[\"wf\"] producers:{BuildInfo:{instance_name:\"ArtdaqOts\" module_type:\"ArtdaqOtsBuildInfo\"}} analyzers:{wf: {module_type:\"WFViewer\" fragment_ids:[0] fragment_type_labels:[ \"DataGen\" ] prescale:60 write_to_file:true fileName:\""+path+"otsdaqdemo_onmon.root\"}}} process_name:\"DAQAG\" services:{Timing:{summaryOnly:true} scheduler:{fileMode:\"NOMERGE\" errorOnFailureToPut: false} NetMonTransportServiceInterface:{max_fragment_size_words:2097152 service_provider:\"NetMonTransportService\"}} source:{module_type:\"NetMonInput\"}";
278 
279  fhicl::ParameterSet pset;
280  //fhicl::make_ParameterSet(configString, pset);
281 
282  std::string filename = ARTDAQ_FCL_PATH + ARTDAQ_FILE_PREAMBLE + "-";
283  std::string uid = theConfigurationManager_->getNode(XDAQContextConfigurationName_).getNode(supervisorConfigurationPath_).getValue();
284 
285  __COUT__ << "uid: " << uid << std::endl;
286  for (unsigned int i = 0; i < uid.size(); ++i)
287  if ((uid[i] >= 'a' && uid[i] <= 'z') ||
288  (uid[i] >= 'A' && uid[i] <= 'Z') ||
289  (uid[i] >= '0' && uid[i] <= '9')) //only allow alpha numeric in file name
290  filename += uid[i];
291  filename += ".fcl";
292 
293 
294  __COUT__ << std::endl;
295  __COUT__ << std::endl;
296  __COUT__ << "filename: " << filename << std::endl;
297 
298  std::string fileFclString;
299  {
300  std::ifstream in(filename, std::ios::in | std::ios::binary);
301  if (in)
302  {
303  std::string contents;
304  in.seekg(0, std::ios::end);
305  fileFclString.resize(in.tellg());
306  in.seekg(0, std::ios::beg);
307  in.read(&fileFclString[0], fileFclString.size());
308  in.close();
309  }
310  }
311 
312  __COUT__ << fileFclString << std::endl;
313  fhicl::make_ParameterSet(fileFclString, pset);
314  //fhicl::make_ParameterSet(theConfigurationManager_->getNode(XDAQContextConfigurationName_).getNode(supervisorConfigurationPath_).getNode("ConfigurationString").getValue<std::string>(), pset);
315 
316 
317  theDispatcherInterface_->initialize(pset, 0, 0);
318  mf::LogInfo("DispatcherInterface") << "ARTDAQDispatcher SUPERVISOR DONE CONFIGURING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
319 
320 }
321 
322 //========================================================================================================================
323 void DispatcherApp::transitionHalting(toolbox::Event::Reference e)
324 {
325  //theDispatcherInterface_->shutdown(45);
326 }
327 
328 //========================================================================================================================
329 void DispatcherApp::transitionInitializing(toolbox::Event::Reference e)
330 {
331 
332 }
333 
334 //========================================================================================================================
335 void DispatcherApp::transitionPausing(toolbox::Event::Reference e)
336 {
337  theDispatcherInterface_->pause(0, 0);
338 }
339 
340 //========================================================================================================================
341 void DispatcherApp::transitionResuming(toolbox::Event::Reference e)
342 {
343  theDispatcherInterface_->resume(0, 0);
344 }
345 
346 //========================================================================================================================
347 void DispatcherApp::transitionStarting(toolbox::Event::Reference e)
348 {
349  art::RunID runId((art::RunNumber_t)boost::lexical_cast<art::RunNumber_t>(SOAPUtilities::translate(theStateMachine_.getCurrentMessage()).getParameters().getValue("RunNumber")));
350  theDispatcherInterface_->start(runId, 0, 0);
351 }
352 
353 //========================================================================================================================
354 void DispatcherApp::transitionStopping(toolbox::Event::Reference e)
355 {
356  theDispatcherInterface_->stop(45, 0);
357  theDispatcherInterface_->shutdown(45);
358 }