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