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