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