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