artdaq  v3_01_00
shared_memory_reader_t.cc
1 #define TRACE_NAME "shared_memory_reader_t"
2 
3 #include "artdaq/ArtModules/detail/SharedMemoryReader.hh"
4 #include "artdaq/DAQrate/SharedMemoryEventManager.hh"
5 
6 #include "art/Framework/Core/FileBlock.h"
7 //#include "art/Framework/Core/RootDictionaryManager.h"
8 #include "art/Framework/IO/Sources/SourceHelper.h"
9 #include "art/Framework/Principal/Event.h"
10 #include "art/Framework/Principal/EventPrincipal.h"
11 #include "art/Framework/Principal/Handle.h"
12 #include "art/Framework/Principal/RunPrincipal.h"
13 #include "art/Framework/Principal/SubRunPrincipal.h"
14 //#include "art/Persistency/Provenance/BranchIDListHelper.h"
15 #if ART_HEX_VERSION < 0x20900
16 #include "art/Persistency/Provenance/BranchIDListRegistry.h"
17 #include "canvas/Utilities/GetPassID.h"
18 #endif
19 #include "art/Persistency/Provenance/MasterProductRegistry.h"
20 #include "art/Persistency/Provenance/ProductMetaData.h"
21 #include "canvas/Persistency/Provenance/EventID.h"
22 #include "canvas/Persistency/Provenance/FileFormatVersion.h"
23 #include "canvas/Persistency/Provenance/ModuleDescription.h"
24 #include "canvas/Persistency/Provenance/Parentage.h"
25 #include "canvas/Persistency/Provenance/ProcessConfiguration.h"
26 #include "canvas/Persistency/Provenance/RunID.h"
27 #include "canvas/Persistency/Provenance/SubRunID.h"
28 #include "canvas/Persistency/Provenance/Timestamp.h"
29 #include "canvas/Utilities/Exception.h"
30 #include "art/Version/GetReleaseVersion.h"
31 #include "artdaq-core/Data/Fragment.hh"
32 #include "artdaq-core/Utilities/configureMessageFacility.hh"
33 #include "fhiclcpp/make_ParameterSet.h"
34 
35 #define BOOST_TEST_MODULE shared_memory_reader_t
36 #include <boost/test/auto_unit_test.hpp>
37 
38 #include <iostream>
39 #include <memory>
40 #include <string>
41 
46 {
47 public:
52 
56  typedef std::map<std::string, art::BranchKey> BKmap_t;
57 
59  std::map<std::string, std::unique_ptr<art::ProcessConfiguration>> processConfigurations_;
60 
70  art::ProcessConfiguration*
71  fake_single_module_process(std::string const& tag,
72  std::string const& processName,
73  fhicl::ParameterSet const& moduleParams,
74  std::string const& release = art::getReleaseVersion()
75 #if ART_HEX_VERSION < 0x20800
76  , std::string const& pass = art::getPassID()
77 #endif
78  );
79 
87  std::unique_ptr<art::BranchDescription>
88  fake_single_process_branch(std::string const& tag,
89  std::string const& processName,
90  std::string const& productInstanceName = std::string());
91 
95  void finalize();
96 
97  art::MasterProductRegistry productRegistry_;
98  //art::RootDictionaryManager rdm_;
99 };
100 
102  :
103  branchKeys_()
104  , processConfigurations_()
105  , productRegistry_()//,
106 // rdm_()
107 {
108  // We can only insert products registered in the MasterProductRegistry.
109  productRegistry_.addProduct(fake_single_process_branch("hlt", "HLT"));
110  productRegistry_.addProduct(fake_single_process_branch("prod", "PROD"));
111  productRegistry_.addProduct(fake_single_process_branch("test", "TEST"));
112  productRegistry_.addProduct(fake_single_process_branch("user", "USER"));
113  productRegistry_.addProduct(fake_single_process_branch("rick", "USER2", "rick"));
114 }
115 
116 void
118 {
119  productRegistry_.setFrozen();
120 #if ART_HEX_VERSION < 0x20900
121 #if ART_HEX_VERSION >= 0x20703
122  art::BranchIDListRegistry::updateFromProductRegistry(productRegistry_);
123 #else
124  art::BranchIDListHelper::updateRegistries(productRegistry_);
125 #endif
126 #endif
127  art::ProductMetaData::create_instance(productRegistry_);
128 }
129 
130 art::ProcessConfiguration*
132 fake_single_module_process(std::string const& tag,
133  std::string const& processName,
134  fhicl::ParameterSet const& moduleParams,
135  std::string const& release
136 #if ART_HEX_VERSION < 0x20800
137  , std::string const& pass
138 #endif
139 )
140 {
141  fhicl::ParameterSet processParams;
142  processParams.put(processName, moduleParams);
143  processParams.put<std::string>("process_name",
144  processName);
145  auto emplace_pair =
146  processConfigurations_.emplace(tag,
147  std::make_unique<art::ProcessConfiguration>(processName, processParams.id(), release, pass));
148  return emplace_pair.first->second.get();
149 }
150 
151 std::unique_ptr<art::BranchDescription>
153 fake_single_process_branch(std::string const& tag,
154  std::string const& processName,
155  std::string const& productInstanceName)
156 {
157  std::string moduleLabel = processName + "dummyMod";
158  std::string moduleClass("DummyModule");
159  fhicl::ParameterSet modParams;
160  modParams.put<std::string>("module_type", moduleClass);
161  modParams.put<std::string>("module_label", moduleLabel);
162  art::ProcessConfiguration* process =
163  fake_single_module_process(tag, processName, modParams);
164  art::ModuleDescription mod(modParams.id(),
165  moduleClass,
166  moduleLabel,
167  *process);
168  art::TypeID dummyType(typeid(int));
169  art::BranchDescription* result =
170  new art::BranchDescription(
171 # if ART_HEX_VERSION >= 0x20703
172  art::InEvent,
173  art::TypeLabel(dummyType,
174  productInstanceName),
175 # else
176  art::TypeLabel(art::InEvent,
177  dummyType,
178  productInstanceName),
179 # endif
180  mod);
181 
182 
183  branchKeys_.insert(std::make_pair(tag, art::BranchKey(*result)));
184  return std::unique_ptr<art::BranchDescription>(result);
185 }
186 
191 {
196  {
197  static bool once(true);
198  if (once)
199  {
200  artdaq::configureMessageFacility("shared_memory_reader_t");
201  (void)reader(); // Force initialization.
202  art::ModuleDescription md(fhicl::ParameterSet().id(),
203  "_NAMEERROR_",
204  "_LABELERROR_",
205  *gf().processConfigurations_["daq"]);
206  // These _xERROR_ strings should never appear in branch names; they
207  // are here as tracers to help identify any failures in coding.
208  helper().registerProducts(gf().productRegistry_, md);
209  gf().finalize();
210  once = false;
211  }
212  }
213 
219  {
220  static MPRGlobalTestFixture mpr;
221  return mpr;
222  }
223 
228  art::ProductRegistryHelper& helper()
229  {
230  static art::ProductRegistryHelper s_helper;
231  return s_helper;
232  }
233 
238  art::SourceHelper& source_helper()
239  {
240  static std::unique_ptr<art::SourceHelper>
241  s_source_helper;
242  if (!s_source_helper)
243  {
244  fhicl::ParameterSet sourceParams;
245  std::string moduleType{ "DummySource" };
246  std::string moduleLabel{ "daq" };
247  sourceParams.put<std::string>("module_type", moduleType);
248  sourceParams.put<std::string>("module_label", moduleLabel);
249  auto pc_ptr = gf().fake_single_module_process(moduleLabel,
250  "TEST",
251  sourceParams);
252  art::ModuleDescription md(sourceParams.id(),
253  moduleType,
254  moduleLabel,
255  *pc_ptr);
256  s_source_helper = std::make_unique<art::SourceHelper>(md);
257  }
258  return *s_source_helper;
259  }
260 
265  uint32_t getKey()
266  {
267  static uint32_t key = static_cast<uint32_t>(std::hash<std::string>()("shared_memory_reader_t"));
268  return key;
269  }
274  uint32_t getBroadcastKey()
275  {
276  static uint32_t key = static_cast<uint32_t>(std::hash<std::string>()("shared_memory_reader_t BROADCAST"));
277  return key;
278  }
279 
285  {
286  writer();
287  fhicl::ParameterSet pset;
288  pset.put("shared_memory_key", getKey());
289  pset.put("broadcast_shared_memory_key", getBroadcastKey());
290  pset.put("max_event_size_bytes", 0x100000);
291  pset.put("buffer_count", 10);
293  s_reader(pset,
294  helper(),
295  source_helper(),
296  gf().productRegistry_);
297  static bool reader_initialized = false;
298  if (!reader_initialized)
299  {
300  s_reader.fragment_type_map_[1] = "ABCDEF";
301  helper().reconstitutes<artdaq::Fragments, art::InEvent>("daq", "ABCDEF");
302  reader_initialized = true;
303  }
304  return s_reader;
305  }
306 
312  {
313  fhicl::ParameterSet pset;
314  pset.put("shared_memory_key", getKey());
315  pset.put("broadcast_shared_memory_key", getBroadcastKey());
316  pset.put("max_event_size_bytes", 0x100000);
317  pset.put("art_analyzer_count", 0);
318  pset.put("stale_buffer_timeout_usec", 100000);
319  pset.put("expected_fragments_per_event", 1);
320  pset.put("buffer_count", 10);
322  s_writer(pset,pset);
323  return s_writer;
324 
325  }
326 };
327 
328 BOOST_FIXTURE_TEST_SUITE(shared_memory_reader_t, ShmRTestFixture)
329 
330 namespace
331 {
342  std::unique_ptr<art::RunPrincipal>&& run,
343  std::unique_ptr<art::SubRunPrincipal>&& subrun,
344  art::EventID const& eventid)
345  {
346  BOOST_REQUIRE(run || subrun == nullptr); // Sanity check.
347  std::vector<artdaq::Fragment::value_type> fakeData{ 1, 2, 3, 4 };
348  artdaq::FragmentPtr
349  tmpFrag(artdaq::Fragment::dataFrag(eventid.event(),
350  0,
351  fakeData.begin(),
352  fakeData.end()));
353  tmpFrag->setUserType(1);
354 
355  writer.startRun(eventid.run());
356 
357 
358  auto iter = tmpFrag->dataBegin();
359  std::ostringstream str;
360  str << "{";
361  while (iter != tmpFrag->dataEnd())
362  {
363  str << std::to_string(*iter) << ", ";
364  ++iter;
365 
366  }
367  str << "}";
368  TLOG(TLVL_DEBUG) <<"Fragment to art: "<< str.str() ;
369 
370 
371  artdaq::FragmentPtr tempFrag;
372  auto sts = writer.AddFragment(std::move(tmpFrag), 1000000, tempFrag);
373  BOOST_REQUIRE_EQUAL(sts,true);
374 
375  while (writer.GetLockedBufferCount())
376  {
377  writer.sendMetrics();
378  usleep(100000);
379  }
380 
381  art::EventPrincipal* newevent = nullptr;
382  art::SubRunPrincipal* newsubrun = nullptr;
383  art::RunPrincipal* newrun = nullptr;
384  bool rc = reader.readNext(run.get(), subrun.get(), newrun, newsubrun, newevent);
385  BOOST_REQUIRE(rc);
386  if (run.get() && run->run() == eventid.run())
387  {
388  BOOST_CHECK(newrun == nullptr);
389  }
390  else
391  {
392  BOOST_CHECK(newrun);
393  BOOST_CHECK(newrun->id() == eventid.runID());
394  }
395  if (!newrun && subrun.get() && subrun->subRun() == eventid.subRun())
396  {
397  BOOST_CHECK(newsubrun == nullptr);
398  }
399  else
400  {
401  BOOST_CHECK(newsubrun);
402  BOOST_CHECK(newsubrun->id() == eventid.subRunID());
403  }
404  BOOST_CHECK(newevent);
405  BOOST_CHECK(newevent->id() == eventid);
406  art::Event e(*newevent, art::ModuleDescription());
407  art::Handle<std::vector<artdaq::Fragment>> h;
408  e.getByLabel("daq", "ABCDEF", h);
409  BOOST_CHECK(h.isValid());
410  BOOST_CHECK(h->size() == 1);
411 
412  auto iter2 = h->front().dataBegin();
413  std::ostringstream str2;
414  str2 << "{";
415  while(iter2 != h->front().dataEnd())
416  {
417  str2 << std::to_string(*iter2) << ", ";
418  ++iter2;
419 
420  }
421  str2 << "}";
422  TLOG(TLVL_DEBUG) << "Fragment from art: " << str2.str() ;
423 
424  BOOST_CHECK(std::equal(fakeData.begin(),
425  fakeData.end(),
426  h->front().dataBegin()));
427  delete(newrun);
428  delete(newsubrun);
429  delete(newevent);
430  }
431 }
432 
433 BOOST_AUTO_TEST_CASE(nonempty_event)
434 {
435  art::EventID eventid(2112, 1, 3);
436  art::Timestamp now;
437  basic_test(reader(),writer(),
438  std::unique_ptr<art::RunPrincipal>(source_helper().makeRunPrincipal(eventid.run(), now)),
439  std::unique_ptr<art::SubRunPrincipal>(source_helper().makeSubRunPrincipal(eventid.run(), eventid.subRun(), now)),
440  eventid);
441 }
442 
443 BOOST_AUTO_TEST_CASE(first_event)
444 {
445  art::EventID eventid(2112, 1, 3);
446  art::Timestamp now;
447  basic_test(reader(), writer(),
448  nullptr,
449  nullptr,
450  eventid);
451 }
452 
453 BOOST_AUTO_TEST_CASE(new_subrun)
454 {
455  art::EventID eventid(2112, 1, 3);
456  art::Timestamp now;
457  basic_test(reader(), writer(),
458  std::unique_ptr<art::RunPrincipal>(source_helper().makeRunPrincipal(eventid.run(), now)),
459  std::unique_ptr<art::SubRunPrincipal>(source_helper().makeSubRunPrincipal(eventid.run(), 0, now)),
460  eventid);
461 }
462 
463 BOOST_AUTO_TEST_CASE(new_run)
464 {
465  art::EventID eventid(2112, 1, 3);
466  art::Timestamp now;
467  basic_test(reader(), writer(),
468  std::unique_ptr<art::RunPrincipal>(source_helper().makeRunPrincipal(eventid.run() - 1, now)),
469  std::unique_ptr<art::SubRunPrincipal>(source_helper().makeSubRunPrincipal(eventid.run() - 1,
470  eventid.subRun(),
471  now)),
472  eventid);
473 }
474 
475 BOOST_AUTO_TEST_CASE(end_of_data)
476 {
477  // Tell 'reader' the name of the file we are to read. This is pretty
478  // much irrelevant for SharedMemoryReader, but we'll stick to the
479  // interface demanded by Source<T>...
480  std::string const fakeFileName("no such file exists");
481  art::FileBlock* pFile = nullptr;
482  reader().readFile(fakeFileName, pFile);
483  BOOST_CHECK(pFile);
484  BOOST_CHECK(pFile->fileFormatVersion() == art::FileFormatVersion(1, "RawEvent2011"));
485  BOOST_CHECK(pFile->tree() == nullptr);
486 
487  BOOST_CHECK(!pFile->fastClonable());
488  // Test the end-of-data handling. Reading an end-of-data should result in readNext() returning false,
489  // and should return null pointers for new-run, -subrun and -event.
490  // Prepare our 'previous run/subrun/event'..
491  art::RunID runid(2112);
492  art::SubRunID subrunid(2112, 1);
493  art::EventID eventid(2112, 1, 3);
494  art::Timestamp now;
495  std::unique_ptr<art::RunPrincipal> run(source_helper().makeRunPrincipal(runid.run(), now));
496  std::unique_ptr<art::SubRunPrincipal> subrun(source_helper().makeSubRunPrincipal(runid.run(), subrunid.subRun(), now));
497  std::unique_ptr<art::EventPrincipal> event(source_helper().makeEventPrincipal(runid.run(),
498  subrunid.subRun(),
499  eventid.event(),
500  now));
501  writer().endOfData();
502  art::EventPrincipal* newevent = nullptr;
503  art::SubRunPrincipal* newsubrun = nullptr;
504  art::RunPrincipal* newrun = nullptr;
505  bool rc = reader().readNext(run.get(), subrun.get(), newrun, newsubrun, newevent);
506  BOOST_CHECK(!rc);
507  BOOST_CHECK(newrun == nullptr);
508  BOOST_CHECK(newsubrun == nullptr);
509  BOOST_CHECK(newevent == nullptr);
510 }
511 
512 BOOST_AUTO_TEST_SUITE_END()
SharedMemoryReader Test Fixture.
std::map< std::string, std::unique_ptr< art::ProcessConfiguration > > processConfigurations_
Configurations.
The SharedMemoryReader is a class which implements the methods needed by art::Source.
void finalize()
Finalizes the ProductRegistry.
size_t GetLockedBufferCount()
Returns the number of buffers currently owned by this manager.
The SharedMemoryEventManager is a SharedMemoryManger which tracks events as they are built...
ShmRTestFixture()
ShmRTestFixture Constructor.
artdaq::SharedMemoryEventManager & writer()
Get the instance of the SharedMemoryEventManager.
art::MasterProductRegistry productRegistry_
MasterProductRegistry instance.
uint32_t getBroadcastKey()
Gets the key for the broadcast shared memory segment.
art::ProcessConfiguration * fake_single_module_process(std::string const &tag, std::string const &processName, fhicl::ParameterSet const &moduleParams, std::string const &release=art::getReleaseVersion(), std::string const &pass=art::getPassID())
Create the ProcessConfiguration for a single module art process.
void basic_test(artdaq::detail::SharedMemoryReader<> &reader, artdaq::SharedMemoryEventManager &writer, std::unique_ptr< art::RunPrincipal > &&run, std::unique_ptr< art::SubRunPrincipal > &&subrun, art::EventID const &eventid)
Run a basic checkout of the SharedMemoryReader.
std::unique_ptr< art::BranchDescription > fake_single_process_branch(std::string const &tag, std::string const &processName, std::string const &productInstanceName=std::string())
Create a BranchDescription for a process.
MasterProductRegistry Test Fixture.
uint32_t getKey()
Gets the key for the shared memory segment.
void sendMetrics()
Send metrics to the MetricManager, if one has been instantiated in the application.
std::map< std::string, art::BranchKey > BKmap_t
BKmap_t associates a string with a art::BranchKey.
MPRGlobalTestFixture()
MPRGlobalTestFixture Constructor.
artdaq::detail::SharedMemoryReader & reader()
Get an artdaq::detail::SharedMemoryReader object, creating a static instance if necessary.
bool readNext(art::RunPrincipal *const &inR, art::SubRunPrincipal *const &inSR, art::RunPrincipal *&outR, art::SubRunPrincipal *&outSR, art::EventPrincipal *&outE)
Dequeue a RawEvent and declare its Fragment contents to art, creating Run, SubRun, and EventPrincipal objects as necessary.
BKmap_t branchKeys_
Keys in this test fixture.
std::map< Fragment::type_t, std::string > fragment_type_map_
The Fragment type names that this SharedMemoryReader knows about.
MPRGlobalTestFixture & gf()
Get a MPRGlobalTestFixture, creating a static instance if necessary.
art::SourceHelper & source_helper()
Get an art::SourceHelper object, creating a static instance if necessary.
art::ProductRegistryHelper & helper()
Get an art::ProductRegistryHelper, creating a static instance if necessary.
void startRun(run_id_t runID)
Start a Run.