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