otsdaq  v2_01_00
DataLoggerApp.cc
1 #include "otsdaq/DataLoggerApp/DataLoggerApp.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 #include <boost/exception/all.hpp>
29 
30 using namespace ots;
31 
32 XDAQ_INSTANTIATOR_IMPL(DataLoggerApp)
33 
34 //========================================================================================================================
35 DataLoggerApp::DataLoggerApp(xdaq::ApplicationStub * s)
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 )
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 )
132 {}
133 
134 //========================================================================================================================
135 void DataLoggerApp::stateMachineResultXgiHandler(xgi::Input* in, xgi::Output* out )
136 {}
137 
138 //========================================================================================================================
139 xoap::MessageReference DataLoggerApp::stateMachineXoapHandler(xoap::MessageReference message )
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 )
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)
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 {
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 DataLoggerApp::stateInitial(toolbox::fsm::FiniteStateMachine& fsm)
190 {
191 
192 }
193 
194 //========================================================================================================================
195 void DataLoggerApp::stateHalted(toolbox::fsm::FiniteStateMachine& fsm)
196 {
197 
198 }
199 
200 //========================================================================================================================
201 void DataLoggerApp::stateRunning(toolbox::fsm::FiniteStateMachine& fsm)
202 {
203 
204 }
205 
206 //========================================================================================================================
207 void DataLoggerApp::stateConfigured(toolbox::fsm::FiniteStateMachine& fsm)
208 {
209 
210 }
211 
212 //========================================================================================================================
213 void DataLoggerApp::statePaused(toolbox::fsm::FiniteStateMachine& fsm)
214 {
215 
216 }
217 
218 //========================================================================================================================
219 void DataLoggerApp::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 DataLoggerApp::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 DataLoggerApp::transitionConfiguring(toolbox::Event::Reference e)
246 {
247 
248  std::cout << __COUT_HDR_FL__ << "ARTDAQDataLogger 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:{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\"}";
274  //ONLY 1 BOARD READER
275  // 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\"}";
276  //2 BOARD READERS
277  //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\"}";
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  theDataLoggerInterface_->initialize(pset, 0, 0);
318  mf::LogInfo("DataLoggerInterface") << "ARTDAQDataLogger SUPERVISOR DONE CONFIGURING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
319 
320 }
321 
322 //========================================================================================================================
323 void DataLoggerApp::transitionHalting(toolbox::Event::Reference e)
324 {
325  // theDataLoggerInterface_->shutdown(0);
326 }
327 
328 //========================================================================================================================
329 void DataLoggerApp::transitionInitializing(toolbox::Event::Reference e)
330 {
331 
332 }
333 
334 //========================================================================================================================
335 void DataLoggerApp::transitionPausing(toolbox::Event::Reference e)
336 {
337  theDataLoggerInterface_->pause(0, 0);
338 }
339 
340 //========================================================================================================================
341 void DataLoggerApp::transitionResuming(toolbox::Event::Reference e)
342 {
343  theDataLoggerInterface_->resume(0, 0);
344 }
345 
346 //========================================================================================================================
347 void DataLoggerApp::transitionStarting(toolbox::Event::Reference e)
348 {
349  auto runnumber= SOAPUtilities::translate(theStateMachine_.getCurrentMessage()).getParameters().getValue("RunNumber");
350  try {
351  art::RunID runId((art::RunNumber_t)boost::lexical_cast<art::RunNumber_t>(runnumber));
352  theDataLoggerInterface_->start(runId,0,0);
353  }
354  catch(const boost::exception& e)
355  {
356  std::cerr << "Error parsing string to art::RunNumber_t: " << runnumber << std::endl;
357  exit(1);
358  }
359 }
360 
361 //========================================================================================================================
362 void DataLoggerApp::transitionStopping(toolbox::Event::Reference e)
363 {
364  theDataLoggerInterface_->stop(0,0);
365  theDataLoggerInterface_->shutdown(0);
366 }