artdaq  v3_00_01
RootNetOutput_module.cc
1 #include "art/Framework/Core/ModuleMacros.h"
2 #include "art/Framework/Core/OutputModule.h"
3 #include "art/Framework/Principal/EventPrincipal.h"
4 #include "art/Framework/Principal/OutputHandle.h"
5 #include "art/Framework/Principal/RunPrincipal.h"
6 #include "art/Framework/Principal/SubRunPrincipal.h"
7 #include "art/Framework/Services/Registry/ServiceHandle.h"
8 #if ART_HEX_VERSION >= 0x20703
9 # include <iterator>
10 #else
11 # include "art/Persistency/Provenance/BranchIDListHelper.h"
12 #endif
13 #include "art/Persistency/Provenance/BranchIDListRegistry.h"
14 #include "art/Persistency/Provenance/ProcessHistoryRegistry.h"
15 #include "art/Persistency/Provenance/ProductMetaData.h"
16 
17 #include "canvas/Persistency/Provenance/BranchDescription.h"
18 #include "canvas/Persistency/Provenance/BranchIDList.h"
19 #include "canvas/Persistency/Provenance/BranchKey.h"
20 #include "canvas/Persistency/Provenance/History.h"
21 #include "canvas/Persistency/Provenance/ParentageRegistry.h"
22 #include "canvas/Persistency/Provenance/ProcessConfiguration.h"
23 #include "canvas/Persistency/Provenance/ProcessConfigurationID.h"
24 #include "canvas/Persistency/Provenance/ProcessHistoryID.h"
25 #include "canvas/Persistency/Provenance/ProductList.h"
26 #include "canvas/Persistency/Provenance/ProductProvenance.h"
27 #include "canvas/Persistency/Provenance/RunAuxiliary.h"
28 #include "canvas/Persistency/Provenance/SubRunAuxiliary.h"
29 #include "canvas/Utilities/DebugMacros.h"
30 #include "canvas/Utilities/Exception.h"
31 #include "cetlib/column_width.h"
32 #include "cetlib/lpad.h"
33 #include "cetlib/rpad.h"
34 #include <algorithm>
35 #include "fhiclcpp/ParameterSet.h"
36 #include "fhiclcpp/ParameterSetID.h"
37 #include "fhiclcpp/ParameterSetRegistry.h"
38 
39 #define TRACE_NAME "RootNetOutput"
40 
41 #define TLVL_OPENFILE 5
42 #define TLVL_CLOSEFILE 6
43 #define TLVL_RESPONDTOCLOSEINPUTFILE 7
44 #define TLVL_RESPONDTOCLOSEOUTPUTFILE 8
45 #define TLVL_ENDJOB 9
46 #define TLVL_SENDINIT 10
47 #define TLVL_SENDINIT_VERBOSE1 32
48 #define TLVL_SENDINIT_VERBOSE2 33
49 #define TLVL_WRITEDATAPRODUCTS 11
50 #define TLVL_WRITEDATAPRODUCTS_VERBOSE 34
51 #define TLVL_WRITE 12
52 #define TLVL_WRITERUN 13
53 #define TLVL_WRITESUBRUN 14
54 #define TLVL_WRITESUBRUN_VERBOSE 35
55 
56 
57 #include "artdaq/DAQdata/Globals.hh"
58 #include "artdaq/ArtModules/NetMonTransportService.h"
59 #include "artdaq-core/Data/detail/ParentageMap.hh"
60 #include "artdaq/DAQdata/NetMonHeader.hh"
61 
62 #include <iomanip>
63 #include <iostream>
64 #include <sstream>
65 #include <string>
66 #include <vector>
67 
68 #include <unistd.h>
69 
70 #include <TClass.h>
71 #include <TMessage.h>
72 
73 # define CONST_WRITE
74 
75 namespace art
76 {
77  class RootNetOutput;
78 }
79 
80 
86 class art::RootNetOutput : public OutputModule
87 {
88 public:
96  explicit RootNetOutput(fhicl::ParameterSet const& ps);
97 
101  ~RootNetOutput();
102 
103 private:
104  virtual void openFile(FileBlock const&);
105 
106  virtual void closeFile();
107 
108  virtual void respondToCloseInputFile(FileBlock const&);
109 
110  virtual void respondToCloseOutputFiles(FileBlock const&);
111 
112  virtual void endJob();
113 
114  virtual void write(EventPrincipal CONST_WRITE&);
115 
116  virtual void writeRun(RunPrincipal CONST_WRITE&);
117 
118  virtual void writeSubRun(SubRunPrincipal CONST_WRITE&);
119 
120  void writeDataProducts(TBufferFile&, const Principal&,
121  std::vector<BranchKey*>&);
122 
123 private:
124  bool initMsgSent_;
125 };
126 
128 RootNetOutput(fhicl::ParameterSet const& ps)
129  : OutputModule(ps)
130  , initMsgSent_(false)
131 {
132  TLOG_DEBUG("RootNetOutput") << "Begin: RootNetOutput::RootNetOutput(ParameterSet const& ps)" << TLOG_ENDL;
133  ServiceHandle<NetMonTransportService> transport;
134  transport->connect();
135  TLOG_DEBUG("RootNetOutput") << "End: RootNetOutput::RootNetOutput(ParameterSet const& ps)" << TLOG_ENDL;
136 }
137 
140 {
141  TLOG_DEBUG("RootNetOutput") << "Begin: RootNetOutput::~RootNetOutput()" << TLOG_ENDL;
142  ServiceHandle<NetMonTransportService> transport;
143  transport->disconnect();
144  TLOG_DEBUG("RootNetOutput") << "End: RootNetOutput::~RootNetOutput()" << TLOG_ENDL;
145 }
146 
147 void
148 art::RootNetOutput::
149 openFile(FileBlock const&)
150 {
151  TLOG_ARB(TLVL_OPENFILE, "RootNetOutput") << "Begin/End: RootNetOutput::openFile(const FileBlock&)" << TLOG_ENDL;
152 }
153 
154 void
155 art::RootNetOutput::
156 closeFile()
157 {
158  TLOG_ARB(TLVL_CLOSEFILE, "RootNetOutput") << "Begin/End: RootNetOutput::closeFile()" << TLOG_ENDL;
159 }
160 
161 void
162 art::RootNetOutput::
163 respondToCloseInputFile(FileBlock const&)
164 {
165  TLOG_ARB(TLVL_RESPONDTOCLOSEINPUTFILE, "RootNetOutput") << "Begin/End: RootNetOutput::"
166  "respondToCloseOutputFiles(FileBlock const&)" << TLOG_ENDL;
167 }
168 
169 void
170 art::RootNetOutput::
171 respondToCloseOutputFiles(FileBlock const&)
172 {
173  TLOG_ARB(TLVL_RESPONDTOCLOSEOUTPUTFILE, "RootNetOutput") << "Begin/End: RootNetOutput::"
174  "respondToCloseOutputFiles(FileBlock const&)" << TLOG_ENDL;
175 }
176 
177 static
178 void
179 send_shutdown_message()
180 {
181  // 4/1/2016, ELF: Apparently, all this function does is make things not work.
182  // At this point in the state machine, RHandles and SHandles have already been
183  // destructed. Calling sendMessage will cause SHandles to reconnect itself,
184  // but the other end will never recieve the message.
185 }
186 
187 void
188 art::RootNetOutput::
189 endJob()
190 {
191  TLOG_ARB(TLVL_ENDJOB, "RootNetOutput") << "Begin: RootNetOutput::endJob()" << TLOG_ENDL;
192  send_shutdown_message();
193  TLOG_ARB(TLVL_ENDJOB, "RootNetOutput") << "End: RootNetOutput::endJob()" << TLOG_ENDL;
194 }
195 
196 //#pragma GCC push_options
197 //#pragma GCC optimize ("O0")
198 static
199 void
200 send_init_message()
201 {
202  TLOG_ARB(TLVL_SENDINIT, "RootNetOutput") << "Begin: RootNetOutput static send_init_message()" << TLOG_ENDL;
203  //
204  // Get the classes we will need.
205  //
206  //static TClass* string_class = TClass::GetClass("std::string");
207  //if (string_class == nullptr) {
208  // throw art::Exception(art::errors::DictionaryNotFound) <<
209  // "RootNetOutput static send_init_message(): "
210  // "Could not get TClass for std::string!";
211  //}
212  static TClass* product_list_class = TClass::GetClass(
213  "std::map<art::BranchKey,art::BranchDescription>");
214  if (product_list_class == nullptr)
215  {
216  throw art::Exception(art::errors::DictionaryNotFound) <<
217  "RootNetOutput static send_init_message(): "
218  "Could not get TClass for "
219  "map<art::BranchKey,art::BranchDescription>!";
220  }
221  //typedef std::map<const ProcessHistoryID,ProcessHistory> ProcessHistoryMap;
222  //TClass* process_history_map_class = TClass::GetClass(
223  // "std::map<const art::ProcessHistoryID,art::ProcessHistory>");
224  //FIXME: Replace the "2" here with a use of the proper enum value!
225  static TClass* process_history_map_class = TClass::GetClass(
226  "std::map<const art::Hash<2>,art::ProcessHistory>");
227  if (process_history_map_class == nullptr)
228  {
229  throw art::Exception(art::errors::DictionaryNotFound) <<
230  "RootNetOutput static send_init_message(): "
231  "Could not get class for "
232  "std::map<const art::Hash<2>,art::ProcessHistory>!";
233  }
234  //static TClass* parentage_map_class = TClass::GetClass(
235  // "std::map<const art::ParentageID,art::Parentage>");
236  //FIXME: Replace the "5" here with a use of the proper enum value!
237  static TClass* parentage_map_class = TClass::GetClass("art::ParentageMap");
238  if (parentage_map_class == nullptr)
239  {
240  throw art::Exception(art::errors::DictionaryNotFound) <<
241  "RootNetOutput static send_init_message(): "
242  "Could not get class for ParentageMap.";
243  }
244  //
245  // Construct and send the init message.
246  //
247  TBufferFile msg(TBuffer::kWrite);
248  msg.SetWriteMode();
249  //
250  // Stream the message type code.
251  //
252  TLOG_ARB(TLVL_SENDINIT, "RootNetOutput") << "RootNetOutput static send_init_message(): Streaming message type code ..." << TLOG_ENDL;
253  msg.WriteULong(1);
254  TLOG_ARB(TLVL_SENDINIT, "RootNetOutput") << "RootNetOutput static send_init_message(): Finished streaming message type code." << TLOG_ENDL;
255 
256  //
257  // Stream the ParameterSetRegistry.
258  //
259  unsigned long ps_cnt = fhicl::ParameterSetRegistry::size();
260  TLOG_ARB(TLVL_SENDINIT, "RootNetOutput") << "RootNetOutput static send_init_message(): parameter set count: " + std::to_string(ps_cnt) << TLOG_ENDL;
261  msg.WriteULong(ps_cnt);
262  TLOG_ARB(TLVL_SENDINIT, "RootNetOutput") << "RootNetOutput static send_init_message(): Streaming parameter sets ..." << TLOG_ENDL;
263  for (
264 # if ART_HEX_VERSION >= 0x20703
265  auto I = std::begin(fhicl::ParameterSetRegistry::get()),
266  E = std::end(fhicl::ParameterSetRegistry::get());
267 # else
268  auto I = fhicl::ParameterSetRegistry::begin(),
269  E = fhicl::ParameterSetRegistry::end();
270 # endif
271  I != E; ++I)
272  {
273  std::string pset_str = I->second.to_string();
274  //msg.WriteObjectAny(&pset_str, string_class);
275  msg.WriteStdString(pset_str);
276  }
277  TLOG_ARB(TLVL_SENDINIT, "RootNetOutput") << "RootNetOutput static send_init_message(): Finished streaming parameter sets." << TLOG_ENDL;
278 
279  //
280  // Stream the MasterProductRegistry.
281  //
282  TLOG_ARB(TLVL_SENDINIT, "RootNetOutput") << "RootNetOutput static send_init_message(): Streaming MasterProductRegistry ..." << TLOG_ENDL;
283  art::ProductList productList(
284  art::ProductMetaData::instance().productList());
285  msg.WriteObjectAny(&productList, product_list_class);
286  TLOG_ARB(TLVL_SENDINIT, "RootNetOutput") << "RootNetOutput static send_init_message(): Finished streaming MasterProductRegistry." << TLOG_ENDL;
287 
288  //
289  // Dump The BranchIDListRegistry
290  //
291 # if ART_HEX_VERSION >= 0x20703
292  art::BranchIDLists const * bilr =
293  &art::BranchIDListRegistry::instance().data();
294 # else
295  art::BranchIDLists* bilr =
296  &art::BranchIDListRegistry::instance()->data();
297 # endif
298  TLOG_ARB(TLVL_SENDINIT_VERBOSE1, "RootNetOutput") << "RootNetOutput static send_init_message(): Content of BranchIDLists" << TLOG_ENDL;
299  int max_bli = bilr->size();
300  TLOG_ARB(TLVL_SENDINIT_VERBOSE1, "RootNetOutput") << "RootNetOutput static send_init_message(): max_bli: " << max_bli << TLOG_ENDL;
301  for (int i = 0; i < max_bli; ++i)
302  {
303  int max_prdidx = (*bilr)[i].size();
304  TLOG_ARB(TLVL_SENDINIT_VERBOSE1, "RootNetOutput") << "RootNetOutput static send_init_message(): max_prdidx: " << max_prdidx << TLOG_ENDL;
305  for (int j = 0; j < max_prdidx; ++j)
306  {
307  TLOG_ARB(TLVL_SENDINIT_VERBOSE1, "RootNetOutput") << "RootNetOutput static send_init_message(): bli: " << i << " prdidx: " << j << " bid: 0x" << std::hex << static_cast<unsigned long>((*bilr)[i][j]) << std::dec << TLOG_ENDL;
308  }
309  }
310 
311 # if ART_HEX_VERSION >= 0x20703
312  art::ProcessHistoryMap phr;
313  for (auto const& pr : art::ProcessHistoryRegistry::get()) {
314  phr.emplace(pr);
315  }
316 # endif
317  //
318  // Dump the ProcessHistoryRegistry.
319  //
320  TLOG_ARB(TLVL_SENDINIT_VERBOSE2, "RootNetOutput") << "RootNetOutput static send_init_message(): Dumping ProcessHistoryRegistry ..." << TLOG_ENDL;
321  //typedef std::map<const ProcessHistoryID,ProcessHistory>
322  // ProcessHistoryMap;
323 # if ART_HEX_VERSION < 0x20703
324  art::ProcessHistoryMap const& phr = art::ProcessHistoryRegistry::get();
325 # endif
326  TLOG_ARB(TLVL_SENDINIT_VERBOSE2, "RootNetOutput") << "RootNetOutput static send_init_message(): phr: size: " << std::to_string(phr.size()) << TLOG_ENDL;
327  for (auto I = phr.begin(), E = phr.end(); I != E; ++I)
328  {
329  std::ostringstream OS;
330  I->first.print(OS);
331  TLOG_ARB(TLVL_SENDINIT_VERBOSE2, "RootNetOutput") << "RootNetOutput static send_init_message(): phr: id: '" << OS.str() << "'" << TLOG_ENDL;
332  }
333  //
334  // Stream the ProcessHistoryRegistry.
335  //
336  TLOG_ARB(TLVL_SENDINIT, "RootNetOutput") << "RootNetOutput static send_init_message(): Streaming ProcessHistoryRegistry ..." << TLOG_ENDL;
337  //typedef std::map<const ProcessHistoryID,ProcessHistory>
338  // ProcessHistoryMap;
339 # if ART_HEX_VERSION >= 0x20703
340  const art::ProcessHistoryMap& phm = phr;
341 # else
342  const art::ProcessHistoryMap& phm = art::ProcessHistoryRegistry::get();
343 # endif
344  TLOG_ARB(TLVL_SENDINIT, "RootNetOutput") << "RootNetOutput static send_init_message(): phm: size: " << std::to_string(phm.size()) << TLOG_ENDL;
345  msg.WriteObjectAny(&phm, process_history_map_class);
346  TLOG_ARB(TLVL_SENDINIT, "RootNetOutput") << "RootNetOutput static send_init_message(): Finished streaming ProcessHistoryRegistry." << TLOG_ENDL;
347 
348  //
349  // Stream the ParentageRegistry.
350  //
351  TLOG_ARB(TLVL_SENDINIT, "RootNetOutput") << "static send_init_message(): Streaming ParentageRegistry ..." << TLOG_ENDL;
352 # if ART_HEX_VERSION >= 0x20703
353  art::ParentageMap parentageMap{};
354  for (auto const& pr : art::ParentageRegistry::get()) {
355  parentageMap.emplace(pr.first, pr.second);
356  }
357 # else
358  const art::ParentageMap& parentageMap = art::ParentageRegistry::get();
359 # endif
360 
361  msg.WriteObjectAny(&parentageMap, parentage_map_class);
362 
363  TLOG_ARB(TLVL_SENDINIT, "RootNetOutput") << "static send_init_message(): Finished streaming ParentageRegistry." << TLOG_ENDL;
364 
365  //
366  //
367  // Send init message.
368  //
369  art::ServiceHandle<NetMonTransportService> transport;
370  if (!transport.get())
371  {
372  TLOG_ERROR("RootNetOutput") << "Could not get handle to NetMonTransportService!" << TLOG_ENDL;
373  return;
374  }
375  TLOG_ARB(TLVL_SENDINIT, "RootNetOutput") << "RootNetOutput static send_init_message(): Sending the init message to " << std::to_string(transport->dataReceiverCount()) << " data receivers ..." << TLOG_ENDL;
376  for (size_t idx = 0; idx < transport->dataReceiverCount(); ++idx)
377  {
378  transport->sendMessage(idx, artdaq::Fragment::InitFragmentType, msg);
379  }
380  TLOG_ARB(TLVL_SENDINIT, "RootNetOutput") << "RootNetOutput static send_init_message(): Init message(s) sent." << TLOG_ENDL;
381 
382  TLOG_ARB(TLVL_SENDINIT, "RootNetOutput") << "End: RootNetOutput static send_init_message()" << TLOG_ENDL;
383 }
384 
385 //#pragma GCC pop_options
386 
387 void
388 art::RootNetOutput::
389 writeDataProducts(TBufferFile& msg, const Principal& principal,
390  std::vector<BranchKey*>& bkv)
391 {
392  TLOG_ARB(TLVL_WRITEDATAPRODUCTS, "RootNetOutput") << "Begin: RootNetOutput::writeDataProducts(...)" << TLOG_ENDL;
393  //
394  // Fetch the class dictionaries we need for
395  // writing out the data products.
396  //
397  static TClass* branch_key_class = TClass::GetClass("art::BranchKey");
398  if (branch_key_class == nullptr)
399  {
400  throw art::Exception(art::errors::DictionaryNotFound) <<
401  "RootNetOutput::writeDataProducts(...): "
402  "Could not get TClass for art::BranchKey!";
403  }
404  static TClass* prdprov_class = TClass::GetClass("art::ProductProvenance");
405  if (prdprov_class == nullptr)
406  {
407  throw art::Exception(art::errors::DictionaryNotFound) <<
408  "RootNetOutput::writeDataProducts(...): "
409  "Could not get TClass for art::ProductProvenance!";
410  }
411  //
412  // Calculate the data product count.
413  //
414  unsigned long prd_cnt = 0;
415  //std::map<art::BranchID, std::shared_ptr<art::Group>>::const_iterator
416  for (auto I = principal.begin(), E = principal.end(); I != E; ++I)
417  {
418  if (I->second->productUnavailable() || !selected(I->second->productDescription()))
419  {
420  continue;
421  }
422  ++prd_cnt;
423  }
424  //
425  // Write the data product count.
426  //
427  TLOG_ARB(TLVL_WRITEDATAPRODUCTS, "RootNetOutput") << "RootNetOutput::writeDataProducts(...): Streaming product count: " + std::to_string(prd_cnt) << TLOG_ENDL;
428  msg.WriteULong(prd_cnt);
429  TLOG_ARB(TLVL_WRITEDATAPRODUCTS, "RootNetOutput") << "RootNetOutput::writeDataProducts(...): Finished streaming product count." << TLOG_ENDL;
430 
431  //
432  // Loop over the groups in the RunPrincipal and
433  // write out the data products.
434  //
435  // Note: We need this vector of keys because the ROOT I/O mechanism
436  // requires that each object inserted in the message has a
437  // unique address, so we force that by holding on to each
438  // branch key manufactured in the loop until after we are
439  // done constructing the message.
440  //
441  bkv.reserve(prd_cnt);
442  //std::map<art::BranchID, std::shared_ptr<art::Group>>::const_iterator
443  for (auto I = principal.begin(), E = principal.end(); I != E; ++I)
444  {
445  if (I->second->productUnavailable() || !selected(I->second->productDescription()))
446  {
447  continue;
448  }
449  const BranchDescription& bd(I->second->productDescription());
450  bkv.push_back(new BranchKey(bd));
451  TLOG_ARB(TLVL_WRITEDATAPRODUCTS_VERBOSE, "RootNetOutput") << "RootNetOutput::writeDataProducts(...): Dumping branch key of class: '"
452  << bkv.back()->friendlyClassName_
453  << "' modlbl: '"
454  << bkv.back()->moduleLabel_
455  << "' instnm: '"
456  << bkv.back()->productInstanceName_
457  << "' procnm: '"
458  << bkv.back()->processName_
459  << "'" << TLOG_ENDL;
460  TLOG_ARB(TLVL_WRITEDATAPRODUCTS, "RootNetOutput") << "RootNetOutput::writeDataProducts(...): "
461  "Streaming branch key of class: '"
462  << bd.producedClassName()
463  << "' modlbl: '"
464  << bd.moduleLabel()
465  << "' instnm: '"
466  << bd.productInstanceName()
467  << "' procnm: '"
468  << bd.processName()
469  << "'" << TLOG_ENDL;
470  msg.WriteObjectAny(bkv.back(), branch_key_class);
471  TLOG_ARB(TLVL_WRITEDATAPRODUCTS, "RootNetOutput") << "RootNetOutput::writeDataProducts(...): "
472  "Streaming product of class: '"
473  << bd.producedClassName()
474  << "' modlbl: '"
475  << bd.moduleLabel()
476  << "' instnm: '"
477  << bd.productInstanceName()
478  << "' procnm: '"
479  << bd.processName()
480  << "'" << TLOG_ENDL;
481  OutputHandle oh = principal.getForOutput(bd.branchID(), true);
482  const EDProduct* prd = oh.wrapper();
483  msg.WriteObjectAny(prd, TClass::GetClass(bd.wrappedName().c_str()));
484  TLOG_ARB(TLVL_WRITEDATAPRODUCTS, "RootNetOutput") << "RootNetOutput::writeDataProducts(...): "
485  "Streaming product provenance of class: '"
486  << bd.producedClassName()
487  << "' modlbl: '"
488  << bd.moduleLabel()
489  << "' instnm: '"
490  << bd.productInstanceName()
491  << "' procnm: '"
492  << bd.processName()
493  << "'" << TLOG_ENDL;
494  const ProductProvenance* prdprov =
495  I->second->productProvenancePtr().get();
496  msg.WriteObjectAny(prdprov, prdprov_class);
497  }
498  TLOG_ARB(TLVL_WRITEDATAPRODUCTS, "RootNetOutput") << "End: RootNetOutput::writeDataProducts(...)" << TLOG_ENDL;
499 }
500 
501 void
502 art::RootNetOutput::
503 write(CONST_WRITE EventPrincipal& ep)
504 {
505  //
506  // Write an Event message.
507  //
508  TLOG_ARB(TLVL_WRITE, "RootNetOutput") << "Begin: RootNetOutput::write(const EventPrincipal& ep)" << TLOG_ENDL;
509  if (!initMsgSent_)
510  {
511  send_init_message();
512  initMsgSent_ = true;
513  }
514  //
515  // Get root classes needed for I/O.
516  //
517  static TClass* run_aux_class = TClass::GetClass("art::RunAuxiliary");
518  if (run_aux_class == nullptr)
519  {
520  throw art::Exception(art::errors::DictionaryNotFound) <<
521  "RootNetOutput::write(const EventPrincipal& ep): "
522  "Could not get TClass for art::RunAuxiliary!";
523  }
524  static TClass* subrun_aux_class = TClass::GetClass("art::SubRunAuxiliary");
525  if (subrun_aux_class == nullptr)
526  {
527  throw art::Exception(art::errors::DictionaryNotFound) <<
528  "RootNetOutput::write(const EventPrincipal& ep): "
529  "Could not get TClass for art::SubRunAuxiliary!";
530  }
531  static TClass* event_aux_class = TClass::GetClass("art::EventAuxiliary");
532  if (event_aux_class == nullptr)
533  {
534  throw art::Exception(art::errors::DictionaryNotFound) <<
535  "RootNetOutput::write(const EventPrincipal& ep): "
536  "Could not get TClass for art::EventAuxiliary!";
537  }
538  static TClass* history_class = TClass::GetClass("art::History");
539  if (history_class == nullptr)
540  {
541  throw art::Exception(art::errors::DictionaryNotFound) <<
542  "RootNetOutput::write(const EventPrincipal& ep): "
543  "Could not get TClass for art::History!";
544  }
545  //
546  // Setup message buffer.
547  //
548  TBufferFile msg(TBuffer::kWrite);
549  msg.SetWriteMode();
550  //
551  // Write message type code.
552  //
553  TLOG_ARB(TLVL_WRITE, "RootNetOutput") << "RootNetOutput::write(const EventPrincipal& ep): Streaming message type code ..." << TLOG_ENDL;
554  msg.WriteULong(4);
555  TLOG_ARB(TLVL_WRITE, "RootNetOutput") << "RootNetOutput::write(const EventPrincipal& ep): Finished streaming message type code." << TLOG_ENDL;
556 
557  //
558  // Write RunAuxiliary.
559  //
560  TLOG_ARB(TLVL_WRITE, "RootNetOutput") << "RootNetOutput::write(const EventPrincipal& ep): Streaming RunAuxiliary ..." << TLOG_ENDL;
561  msg.WriteObjectAny(&ep.subRunPrincipal().runPrincipal().aux(),
562  run_aux_class);
563  TLOG_ARB(TLVL_WRITE, "RootNetOutput") << "RootNetOutput::write(const EventPrincipal& ep): Finished streaming RunAuxiliary." << TLOG_ENDL;
564 
565  //
566  // Write SubRunAuxiliary.
567  //
568  TLOG_ARB(TLVL_WRITE, "RootNetOutput") << "RootNetOutput::write(const EventPrincipal& ep): Streaming SubRunAuxiliary ..." << TLOG_ENDL;
569  msg.WriteObjectAny(&ep.subRunPrincipal().aux(),
570  subrun_aux_class);
571  TLOG_ARB(TLVL_WRITE, "RootNetOutput") << "RootNetOutput::write(const EventPrincipal& ep): Finished streaming SubRunAuxiliary." << TLOG_ENDL;
572 
573  //
574  // Write EventAuxiliary.
575  //
576  {
577  TLOG_ARB(TLVL_WRITE, "RootNetOutput") << "RootNetOutput::write(const EventPrincipal& ep): Streaming EventAuxiliary ..." << TLOG_ENDL;
578  msg.WriteObjectAny(&ep.aux(), event_aux_class);
579  TLOG_ARB(TLVL_WRITE, "RootNetOutput") << "RootNetOutput::write(const EventPrincipal& ep): Finished streaming EventAuxiliary." << TLOG_ENDL;
580  }
581  //
582  // Write History.
583  //
584  {
585  TLOG_ARB(TLVL_WRITE, "RootNetOutput") << "RootNetOutput::write(const EventPrincipal& ep): Streaming History ..." << TLOG_ENDL;
586  msg.WriteObjectAny(&ep.history(), history_class);
587  TLOG_ARB(TLVL_WRITE, "RootNetOutput") << "RootNetOutput::write(const EventPrincipal& ep): Finished streaming History." << TLOG_ENDL;
588  }
589  //
590  // Write data products.
591  //
592  std::vector<BranchKey*> bkv;
593  writeDataProducts(msg, ep, bkv);
594  //
595  // Send message.
596  //
597  {
598  ServiceHandle<NetMonTransportService> transport;
599  if (!transport.get())
600  {
601  TLOG_ERROR("RootNetOutput") << "Could not get handle to NetMonTransportService!" << TLOG_ENDL;
602  return;
603  }
604  TLOG_ARB(TLVL_WRITE, "RootNetOutput") << "RootNetOutput::write(const EventPrincipal& ep): Sending a message ..." << TLOG_ENDL;
605  transport->sendMessage(ep.id().event(), artdaq::Fragment::DataFragmentType, msg);
606  TLOG_ARB(TLVL_WRITE, "RootNetOutput") << "RootNetOutput::write(const EventPrincipal& ep): Message sent." << TLOG_ENDL;
607  }
608  //
609  // Delete the branch keys we created for the message.
610  //
611  for (auto I = bkv.begin(), E = bkv.end(); I != E; ++I)
612  {
613  delete *I;
614  *I = 0;
615  }
616  TLOG_ARB(TLVL_WRITE, "RootNetOutput") << "End: RootNetOutput::write(const EventPrincipal& ep)" << TLOG_ENDL;
617 }
618 
619 void
620 art::RootNetOutput::
621 writeRun(CONST_WRITE RunPrincipal& rp)
622 {
623  //
624  // Write an EndRun message.
625  //
626  TLOG_ARB(TLVL_WRITERUN, "RootNetOutput") << "Begin: RootNetOutput::writeRun(const RunPrincipal& rp)" << TLOG_ENDL;
627  (void)rp;
628  if (!initMsgSent_)
629  {
630  send_init_message();
631  initMsgSent_ = true;
632  }
633 #if 0
634  //
635  // Fetch the class dictionaries we need for
636  // writing out the auxiliary information.
637  //
638  static TClass* run_aux_class = TClass::GetClass("art::RunAuxiliary");
639  assert(run_aux_class != nullptr && "writeRun: Could not get TClass for art::RunAuxiliary!");
640  //
641  // Begin preparing message.
642  //
643  TBufferFile msg(TBuffer::kWrite);
644  msg.SetWriteMode();
645  //
646  // Write message type code.
647  //
648  {
649  TLOG_ARB(TLVL_WRITERUN, "RootNetOutput") << "writeRun: streaming message type code ..." << TLOG_ENDL;
650  msg.WriteULong(2);
651  TLOG_ARB(TLVL_WRITERUN, "RootNetOutput") << "writeRun: finished streaming message type code." << TLOG_ENDL;
652  }
653  //
654  // Write RunAuxiliary.
655  //
656  {
657  TLOG_ARB(TLVL_WRITERUN, "RootNetOutput") << "writeRun: streaming RunAuxiliary ..." << TLOG_ENDL;
658  TLOG_ARB(TLVL_WRITERUN_VERBOSE, "RootNetOutput") << "writeRun: dumping ProcessHistoryRegistry ..." << TLOG_ENDL;
659  //typedef std::map<const ProcessHistoryID,ProcessHistory>
660  // ProcessHistoryMap;
661  art::ProcessHistoryMap const& phr =
662  art::ProcessHistoryRegistry::get();
663  TLOG_ARB(TLVL_WRITERUN_VERBOSE, "RootNetOutput") << "writeRun: phr: size: " << phr.size() << TLOG_ENDL;
664  for (auto I = phr.begin(), E = phr.end(); I != E; ++I) {
665  std::ostringstream OS;
666  I->first.print(OS);
667  TLOG_ARB(TLVL_WRITERUN_VERBOSE, "RootNetOutput") << "writeRun: phr: id: '" << OS.str() << "'" << TLOG_ENDL;
668  OS.str("");
669  TLOG_ARB(TLVL_WRITERUN_VERBOSE, "RootNetOutput") << "writeRun: phr: data.size(): " << I->second.data().size() << TLOG_ENDL;
670  if (I->second.data().size()) {
671  I->second.data().back().id().print(OS);
672  TLOG_ARB(TLVL_WRITERUN_VERBOSE, "RootNetOutput") << "writeRun: phr: data.back().id(): '" << OS.str() << "'" << TLOG_ENDL;
673  }
674  }
675  if (!rp.aux().processHistoryID().isValid()) {
676  TLOG_ARB(TLVL_WRITERUN_VERBOSE, "RootNetOutput") << "writeRun: ProcessHistoryID: 'INVALID'" << TLOG_ENDL;
677  }
678  else {
679  std::ostringstream OS;
680  rp.aux().processHistoryID().print(OS);
681  TLOG_ARB(TLVL_WRITERUN_VERBOSE, "RootNetOutput") << "writeRun: ProcessHistoryID: '" << OS.str() << "'" << TLOG_ENDL;
682  OS.str("");
683  const ProcessHistory& processHistory =
684  ProcessHistoryRegistry::get(rp.aux().processHistoryID());
685  if (processHistory.data().size()) {
686  // FIXME: Print something special on invalid id() here!
687  processHistory.data().back().id().print(OS);
688  TLOG_ARB(TLVL_WRITERUN_VERBOSE, "RootNetOutput") << "writeRun: ProcessConfigurationID: '" << OS.str() << "'" << TLOG_ENDL;
689  OS.str("");
690  TLOG_ARB(TLVL_WRITERUN_VERBOSE, "RootNetOutput") << "writeRun: ProcessConfiguration: '" << processHistory.data().back() << TLOG_ENDL;
691  }
692  }
693  msg.WriteObjectAny(&rp.aux(), run_aux_class);
694  TLOG_ARB(TLVL_WRITERUN, "RootNetOutput") << "writeRun: streamed RunAuxiliary." << TLOG_ENDL;
695  }
696  //
697  // Write data products.
698  //
699  std::vector<BranchKey*> bkv;
700  writeDataProducts(msg, rp, bkv);
701  //
702  // Send message.
703  //
704  {
705  ServiceHandle<NetMonTransportService> transport;
706  if (!transport.get())
707  {
708  TLOG_ERROR("RootNetOutput") << "Could not get handle to NetMonTransportService!" << TLOG_ENDL;
709  return;
710  }
711  TLOG_ARB(TLVL_WRITERUN, "RootNetOutput") << "writeRun: sending a message ..." << TLOG_ENDL;
712  transport->sendMessage(0, artdaq::Fragment::EndOfRunFragmentType, msg);
713  TLOG_ARB(TLVL_WRITERUN, "RootNetOutput") << "writeRun: message sent." << TLOG_ENDL;
714  }
715  //
716  // Delete the branch keys we created for the message.
717  //
718  for (auto I = bkv.begin(), E = bkv.end(); I != E; ++I) {
719  delete *I;
720  *I = 0;
721  }
722 #endif // 0
723  TLOG_ARB(TLVL_WRITERUN, "RootNetOutput") << "End: RootNetOutput::writeRun(const RunPrincipal& rp)" << TLOG_ENDL;
724 }
725 
726 void
727 art::RootNetOutput::writeSubRun(CONST_WRITE SubRunPrincipal& srp)
728 {
729  //
730  // Write an EndSubRun message.
731  //
732  TLOG_ARB(TLVL_WRITESUBRUN, "RootNetOutput") << "Begin: RootNetOutput::writeSubRun(const SubRunPrincipal& srp)" << TLOG_ENDL;
733  if (!initMsgSent_)
734  {
735  send_init_message();
736  initMsgSent_ = true;
737  }
738  //
739  // Fetch the class dictionaries we need for
740  // writing out the auxiliary information.
741  //
742  static TClass* subrun_aux_class = TClass::GetClass("art::SubRunAuxiliary");
743  if (subrun_aux_class == nullptr)
744  {
745  throw art::Exception(art::errors::DictionaryNotFound) <<
746  "RootNetOutput::writeSubRun: "
747  "Could not get TClass for art::SubRunAuxiliary!";
748  }
749  //
750  // Begin preparing message.
751  //
752  TBufferFile msg(TBuffer::kWrite);
753  msg.SetWriteMode();
754  //
755  // Write message type code.
756  //
757  {
758  TLOG_ARB(TLVL_WRITESUBRUN, "RootNetOutput") << "RootNetOutput::writeSubRun: streaming message type code ..." << TLOG_ENDL;
759  msg.WriteULong(3);
760  TLOG_ARB(TLVL_WRITESUBRUN, "RootNetOutput") << "RootNetOutput::writeSubRun: finished streaming message type code." << TLOG_ENDL;
761  }
762  //
763  // Write SubRunAuxiliary.
764  //
765  {
766  TLOG_ARB(TLVL_WRITESUBRUN, "RootNetOutput") << "RootNetOutput::writeSubRun: streaming SubRunAuxiliary ..." << TLOG_ENDL;
767 
768  TLOG_ARB(TLVL_WRITESUBRUN_VERBOSE, "RootNetOutput") << "RootNetOutput::writeSubRun: dumping ProcessHistoryRegistry ..." << TLOG_ENDL;
769  //typedef std::map<const ProcessHistoryID,ProcessHistory>
770  // ProcessHistoryMap;
771 # if ART_HEX_VERSION >= 0x20703
772  for (auto I = std::begin(art::ProcessHistoryRegistry::get())
773  , E = std::end(art::ProcessHistoryRegistry::get()); I != E; ++I)
774 # else
775  art::ProcessHistoryMap const& phr =
776  art::ProcessHistoryRegistry::get();
777  TLOG_ARB(TLVL_WRITESUBRUN_VERBOSE, "RootNetOutput") << "RootNetOutput::writeSubRun: phr: size: " << std::to_string(phr.size()) << TLOG_ENDL;
778  for (auto I = phr.begin(), E = phr.end(); I != E; ++I)
779 # endif
780  {
781  std::ostringstream OS;
782  I->first.print(OS);
783  TLOG_ARB(TLVL_WRITESUBRUN_VERBOSE, "RootNetOutput") << "RootNetOutput::writeSubRun: phr: id: '" << OS.str() << "'" << TLOG_ENDL;
784  OS.str("");
785  TLOG_ARB(TLVL_WRITESUBRUN_VERBOSE, "RootNetOutput") << "RootNetOutput::writeSubRun: phr: data.size(): " << std::to_string(I->second.data().size()) << TLOG_ENDL;
786  if (I->second.data().size())
787  {
788  I->second.data().back().id().print(OS);
789  TLOG_ARB(TLVL_WRITESUBRUN_VERBOSE, "RootNetOutput") << "RootNetOutput::writeSubRun: phr: data.back().id(): '" << OS.str() << "'" << TLOG_ENDL;
790  }
791  }
792  if (!srp.aux().processHistoryID().isValid())
793  {
794  TLOG_ARB(TLVL_WRITESUBRUN_VERBOSE, "RootNetOutput") << "RootNetOutput::writeSubRun: ProcessHistoryID: 'INVALID'" << TLOG_ENDL;
795  }
796  else
797  {
798  std::ostringstream OS;
799  srp.aux().processHistoryID().print(OS);
800  TLOG_ARB(TLVL_WRITESUBRUN_VERBOSE, "RootNetOutput") << "RootNetOutput::writeSubRun: ProcessHistoryID: '" << OS.str() << "'" << TLOG_ENDL;
801  OS.str("");
802 # if ART_HEX_VERSION >= 0x20703
803  ProcessHistory processHistory;
804  ProcessHistoryRegistry::get(srp.aux().processHistoryID(), processHistory);
805 # else
806  const ProcessHistory& processHistory =
807  ProcessHistoryRegistry::get(srp.aux().processHistoryID());
808 # endif
809  if (processHistory.data().size())
810  {
811  // FIXME: Print something special on invalid id() here!
812  processHistory.data().back().id().print(OS);
813  TLOG_ARB(TLVL_WRITESUBRUN_VERBOSE, "RootNetOutput") << "RootNetOutput::writeSubRun: ProcessConfigurationID: '" << OS.str() << "'" << TLOG_ENDL;
814  OS.str("");
815  OS << processHistory.data().back();
816  TLOG_ARB(TLVL_WRITESUBRUN_VERBOSE, "RootNetOutput") << "RootNetOutput::writeSubRun: ProcessConfiguration: '" << OS.str() << TLOG_ENDL;
817  }
818  }
819  msg.WriteObjectAny(&srp.aux(), subrun_aux_class);
820  TLOG_ARB(TLVL_WRITESUBRUN, "RootNetOutput") << "RootNetOutput::writeSubRun: streamed SubRunAuxiliary." << TLOG_ENDL;
821  }
822  //
823  // Write data products.
824  //
825  std::vector<BranchKey*> bkv;
826  writeDataProducts(msg, srp, bkv);
827  //
828  // Send message.
829  //
830  ServiceHandle<NetMonTransportService> transport;
831  if (!transport.get())
832  {
833  TLOG_ERROR("RootNetOutput") << "Could not get handle to NetMonTransportService!" << TLOG_ENDL;
834  return;
835  }
836  TLOG_ARB(TLVL_WRITESUBRUN, "RootNetOutput") << "RootNetOutput::writeSubRun: Sending the EndOfSubrun message to " << std::to_string(transport->dataReceiverCount()) << " data receivers ..." << TLOG_ENDL;
837  for (size_t idx = 0; idx < transport->dataReceiverCount(); ++idx)
838  {
839  transport->sendMessage(idx, artdaq::Fragment::EndOfSubrunFragmentType, msg);
840  }
841  TLOG_ARB(TLVL_WRITESUBRUN, "RootNetOutput") << "RootNetOutput::writeSubRun: EndOfSubrun message(s) sent." << TLOG_ENDL;
842 
843  // Disconnecting will cause EOD fragments to be generated which will
844  // allow components downstream to flush data and clean up.
845  transport->disconnect();
846 
847  //
848  // Delete the branch keys we created for the message.
849  //
850  for (auto I = bkv.begin(), E = bkv.end(); I != E; ++I)
851  {
852  delete *I;
853  *I = 0;
854  }
855  TLOG_ARB(TLVL_WRITESUBRUN, "RootNetOutput") << "End: RootNetOutput::writeSubRun(const SubRunPrincipal& srp)" << TLOG_ENDL;
856 }
857 
858 DEFINE_ART_MODULE(art::RootNetOutput)
~RootNetOutput()
RootNetOutput Destructor.
An art::OutputModule which sends events using DataSenderManager. This module is designed for transpor...
RootNetOutput(fhicl::ParameterSet const &ps)
RootNetOutput Constructor.