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