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