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