artdaq  v3_00_01
shared_memory_reader_t.cc
1 #include "artdaq/ArtModules/detail/SharedMemoryReader.hh"
2 #include "artdaq/DAQrate/SharedMemoryEventManager.hh"
3 
4 #include "art/Framework/Core/FileBlock.h"
5 //#include "art/Framework/Core/RootDictionaryManager.h"
6 #include "art/Framework/IO/Sources/SourceHelper.h"
7 #include "art/Framework/Principal/Event.h"
8 #include "art/Framework/Principal/EventPrincipal.h"
9 #include "art/Framework/Principal/Handle.h"
10 #include "art/Framework/Principal/RunPrincipal.h"
11 #include "art/Framework/Principal/SubRunPrincipal.h"
12 //#include "art/Persistency/Provenance/BranchIDListHelper.h"
13 #include "art/Persistency/Provenance/BranchIDListRegistry.h"
14 #include "art/Persistency/Provenance/MasterProductRegistry.h"
15 #include "art/Persistency/Provenance/ProductMetaData.h"
16 #include "canvas/Persistency/Provenance/EventID.h"
17 #include "canvas/Persistency/Provenance/FileFormatVersion.h"
18 #include "canvas/Persistency/Provenance/ModuleDescription.h"
19 #include "canvas/Persistency/Provenance/Parentage.h"
20 #include "canvas/Persistency/Provenance/ProcessConfiguration.h"
21 #include "canvas/Persistency/Provenance/RunID.h"
22 #include "canvas/Persistency/Provenance/SubRunID.h"
23 #include "canvas/Persistency/Provenance/Timestamp.h"
24 #include "canvas/Utilities/Exception.h"
25 #include "canvas/Utilities/GetPassID.h"
26 #include "art/Version/GetReleaseVersion.h"
27 #include "artdaq-core/Data/Fragment.hh"
28 #include "artdaq-core/Utilities/configureMessageFacility.hh"
29 #include "fhiclcpp/make_ParameterSet.h"
30 
31 #define BOOST_TEST_MODULE shared_memory_reader_t
32 #include <boost/test/auto_unit_test.hpp>
33 
34 #include <iostream>
35 #include <memory>
36 #include <string>
37 
42 {
43 public:
48 
52  typedef std::map<std::string, art::BranchKey> BKmap_t;
53 
55  std::map<std::string, std::unique_ptr<art::ProcessConfiguration>> processConfigurations_;
56 
66  art::ProcessConfiguration*
67  fake_single_module_process(std::string const& tag,
68  std::string const& processName,
69  fhicl::ParameterSet const& moduleParams,
70  std::string const& release = art::getReleaseVersion(),
71  std::string const& pass = art::getPassID());
72 
80  std::unique_ptr<art::BranchDescription>
81  fake_single_process_branch(std::string const& tag,
82  std::string const& processName,
83  std::string const& productInstanceName = std::string());
84 
88  void finalize();
89 
90  art::MasterProductRegistry productRegistry_;
91  //art::RootDictionaryManager rdm_;
92 };
93 
95  :
96  branchKeys_()
97  , processConfigurations_()
98  , productRegistry_()//,
99 // rdm_()
100 {
101  // We can only insert products registered in the MasterProductRegistry.
102  productRegistry_.addProduct(fake_single_process_branch("hlt", "HLT"));
103  productRegistry_.addProduct(fake_single_process_branch("prod", "PROD"));
104  productRegistry_.addProduct(fake_single_process_branch("test", "TEST"));
105  productRegistry_.addProduct(fake_single_process_branch("user", "USER"));
106  productRegistry_.addProduct(fake_single_process_branch("rick", "USER2", "rick"));
107 }
108 
109 void
111 {
112  productRegistry_.setFrozen();
113 #if ART_HEX_VERSION >= 0x20703
114  art::BranchIDListRegistry::updateFromProductRegistry(productRegistry_);
115 #else
116  art::BranchIDListHelper::updateRegistries(productRegistry_);
117 #endif
118  art::ProductMetaData::create_instance(productRegistry_);
119 }
120 
121 art::ProcessConfiguration*
123 fake_single_module_process(std::string const& tag,
124  std::string const& processName,
125  fhicl::ParameterSet const& moduleParams,
126  std::string const& release,
127  std::string const& pass)
128 {
129  fhicl::ParameterSet processParams;
130  processParams.put(processName, moduleParams);
131  processParams.put<std::string>("process_name",
132  processName);
133  auto emplace_pair =
134  processConfigurations_.emplace(tag,
135  std::make_unique<art::ProcessConfiguration>(processName, processParams.id(), release, pass));
136  return emplace_pair.first->second.get();
137 }
138 
139 std::unique_ptr<art::BranchDescription>
141 fake_single_process_branch(std::string const& tag,
142  std::string const& processName,
143  std::string const& productInstanceName)
144 {
145  std::string moduleLabel = processName + "dummyMod";
146  std::string moduleClass("DummyModule");
147  fhicl::ParameterSet modParams;
148  modParams.put<std::string>("module_type", moduleClass);
149  modParams.put<std::string>("module_label", moduleLabel);
150  art::ProcessConfiguration* process =
151  fake_single_module_process(tag, processName, modParams);
152  art::ModuleDescription mod(modParams.id(),
153  moduleClass,
154  moduleLabel,
155  *process);
156  art::TypeID dummyType(typeid(int));
157  art::BranchDescription* result =
158  new art::BranchDescription(
159 # if ART_HEX_VERSION >= 0x20703
160  art::InEvent,
161  art::TypeLabel(dummyType,
162  productInstanceName),
163 # else
164  art::TypeLabel(art::InEvent,
165  dummyType,
166  productInstanceName),
167 # endif
168  mod);
169 
170 
171  branchKeys_.insert(std::make_pair(tag, art::BranchKey(*result)));
172  return std::unique_ptr<art::BranchDescription>(result);
173 }
174 
179 {
184  {
185  static bool once(true);
186  if (once)
187  {
188  artdaq::configureMessageFacility("shared_memory_reader_t");
189  (void)reader(); // Force initialization.
190  art::ModuleDescription md(fhicl::ParameterSet().id(),
191  "_NAMEERROR_",
192  "_LABELERROR_",
193  *gf().processConfigurations_["daq"]);
194  // These _xERROR_ strings should never appear in branch names; they
195  // are here as tracers to help identify any failures in coding.
196  helper().registerProducts(gf().productRegistry_, md);
197  gf().finalize();
198  once = false;
199  }
200  }
201 
207  {
208  static MPRGlobalTestFixture mpr;
209  return mpr;
210  }
211 
216  art::ProductRegistryHelper& helper()
217  {
218  static art::ProductRegistryHelper s_helper;
219  return s_helper;
220  }
221 
226  art::SourceHelper& source_helper()
227  {
228  static std::unique_ptr<art::SourceHelper>
229  s_source_helper;
230  if (!s_source_helper)
231  {
232  fhicl::ParameterSet sourceParams;
233  std::string moduleType{ "DummySource" };
234  std::string moduleLabel{ "daq" };
235  sourceParams.put<std::string>("module_type", moduleType);
236  sourceParams.put<std::string>("module_label", moduleLabel);
237  auto pc_ptr = gf().fake_single_module_process(moduleLabel,
238  "TEST",
239  sourceParams);
240  art::ModuleDescription md(sourceParams.id(),
241  moduleType,
242  moduleLabel,
243  *pc_ptr);
244  s_source_helper = std::make_unique<art::SourceHelper>(md);
245  }
246  return *s_source_helper;
247  }
248 
253  uint32_t getKey()
254  {
255  static uint32_t key = static_cast<uint32_t>(std::hash<std::string>()("shared_memory_reader_t"));
256  return key;
257  }
262  uint32_t getBroadcastKey()
263  {
264  static uint32_t key = static_cast<uint32_t>(std::hash<std::string>()("shared_memory_reader_t BROADCAST"));
265  return key;
266  }
267 
273  {
274  writer();
275  fhicl::ParameterSet pset;
276  pset.put("shared_memory_key", getKey());
277  pset.put("broadcast_shared_memory_key", getBroadcastKey());
278  pset.put("max_event_size_bytes", 0x100000);
279  pset.put("buffer_count", 10);
281  s_reader(pset,
282  helper(),
283  source_helper(),
284  gf().productRegistry_);
285  static bool reader_initialized = false;
286  if (!reader_initialized)
287  {
288  s_reader.fragment_type_map_[1] = "ABCDEF";
289  helper().reconstitutes<artdaq::Fragments, art::InEvent>("daq", "ABCDEF");
290  reader_initialized = true;
291  }
292  return s_reader;
293  }
294 
300  {
301  fhicl::ParameterSet pset;
302  pset.put("shared_memory_key", getKey());
303  pset.put("broadcast_shared_memory_key", getBroadcastKey());
304  pset.put("max_event_size_bytes", 0x100000);
305  pset.put("art_analyzer_count", 0);
306  pset.put("stale_buffer_timeout_usec", 100000);
307  pset.put("expected_fragments_per_event", 1);
308  pset.put("buffer_count", 10);
310  s_writer(pset,pset);
311  return s_writer;
312 
313  }
314 };
315 
316 BOOST_FIXTURE_TEST_SUITE(shared_memory_reader_t, ShmRTestFixture)
317 
318 namespace
319 {
330  std::unique_ptr<art::RunPrincipal>&& run,
331  std::unique_ptr<art::SubRunPrincipal>&& subrun,
332  art::EventID const& eventid)
333  {
334  BOOST_REQUIRE(run || subrun == nullptr); // Sanity check.
335  std::vector<artdaq::Fragment::value_type> fakeData{ 1, 2, 3, 4 };
336  artdaq::FragmentPtr
337  tmpFrag(artdaq::Fragment::dataFrag(eventid.event(),
338  0,
339  fakeData.begin(),
340  fakeData.end()));
341  tmpFrag->setUserType(1);
342 
343  writer.startRun(eventid.run());
344 
345 
346  auto iter = tmpFrag->dataBegin();
347  std::ostringstream str;
348  str << "{";
349  while (iter != tmpFrag->dataEnd())
350  {
351  str << std::to_string(*iter) << ", ";
352  ++iter;
353 
354  }
355  str << "}";
356  TLOG_DEBUG("shared_memory_reader_t") <<"Fragment to art: "<< str.str() << TLOG_ENDL;
357 
358 
359  artdaq::FragmentPtr tempFrag;
360  auto sts = writer.AddFragment(std::move(tmpFrag), 1000000, tempFrag);
361  BOOST_REQUIRE_EQUAL(sts,true);
362 
363  while (writer.GetLockedBufferCount())
364  {
365  writer.sendMetrics();
366  usleep(100000);
367  }
368 
369  art::EventPrincipal* newevent = nullptr;
370  art::SubRunPrincipal* newsubrun = nullptr;
371  art::RunPrincipal* newrun = nullptr;
372  bool rc = reader.readNext(run.get(), subrun.get(), newrun, newsubrun, newevent);
373  BOOST_REQUIRE(rc);
374  if (run.get() && run->run() == eventid.run())
375  {
376  BOOST_CHECK(newrun == nullptr);
377  }
378  else
379  {
380  BOOST_CHECK(newrun);
381  BOOST_CHECK(newrun->id() == eventid.runID());
382  }
383  if (!newrun && subrun.get() && subrun->subRun() == eventid.subRun())
384  {
385  BOOST_CHECK(newsubrun == nullptr);
386  }
387  else
388  {
389  BOOST_CHECK(newsubrun);
390  BOOST_CHECK(newsubrun->id() == eventid.subRunID());
391  }
392  BOOST_CHECK(newevent);
393  BOOST_CHECK(newevent->id() == eventid);
394  art::Event e(*newevent, art::ModuleDescription());
395  art::Handle<std::vector<artdaq::Fragment>> h;
396  e.getByLabel("daq", "ABCDEF", h);
397  BOOST_CHECK(h.isValid());
398  BOOST_CHECK(h->size() == 1);
399 
400  auto iter2 = h->front().dataBegin();
401  std::ostringstream str2;
402  str2 << "{";
403  while(iter2 != h->front().dataEnd())
404  {
405  str2 << std::to_string(*iter2) << ", ";
406  ++iter2;
407 
408  }
409  str2 << "}";
410  TLOG_DEBUG("shared_memory_reader_t") << "Fragment from art: " << str2.str() << TLOG_ENDL;
411 
412  BOOST_CHECK(std::equal(fakeData.begin(),
413  fakeData.end(),
414  h->front().dataBegin()));
415  delete(newrun);
416  delete(newsubrun);
417  delete(newevent);
418  }
419 }
420 
421 BOOST_AUTO_TEST_CASE(nonempty_event)
422 {
423  art::EventID eventid(2112, 1, 3);
424  art::Timestamp now;
425  basic_test(reader(),writer(),
426  std::unique_ptr<art::RunPrincipal>(source_helper().makeRunPrincipal(eventid.run(), now)),
427  std::unique_ptr<art::SubRunPrincipal>(source_helper().makeSubRunPrincipal(eventid.run(), eventid.subRun(), now)),
428  eventid);
429 }
430 
431 BOOST_AUTO_TEST_CASE(first_event)
432 {
433  art::EventID eventid(2112, 1, 3);
434  art::Timestamp now;
435  basic_test(reader(), writer(),
436  nullptr,
437  nullptr,
438  eventid);
439 }
440 
441 BOOST_AUTO_TEST_CASE(new_subrun)
442 {
443  art::EventID eventid(2112, 1, 3);
444  art::Timestamp now;
445  basic_test(reader(), writer(),
446  std::unique_ptr<art::RunPrincipal>(source_helper().makeRunPrincipal(eventid.run(), now)),
447  std::unique_ptr<art::SubRunPrincipal>(source_helper().makeSubRunPrincipal(eventid.run(), 0, now)),
448  eventid);
449 }
450 
451 BOOST_AUTO_TEST_CASE(new_run)
452 {
453  art::EventID eventid(2112, 1, 3);
454  art::Timestamp now;
455  basic_test(reader(), writer(),
456  std::unique_ptr<art::RunPrincipal>(source_helper().makeRunPrincipal(eventid.run() - 1, now)),
457  std::unique_ptr<art::SubRunPrincipal>(source_helper().makeSubRunPrincipal(eventid.run() - 1,
458  eventid.subRun(),
459  now)),
460  eventid);
461 }
462 
463 BOOST_AUTO_TEST_CASE(end_of_data)
464 {
465  // Tell 'reader' the name of the file we are to read. This is pretty
466  // much irrelevant for SharedMemoryReader, but we'll stick to the
467  // interface demanded by Source<T>...
468  std::string const fakeFileName("no such file exists");
469  art::FileBlock* pFile = nullptr;
470  reader().readFile(fakeFileName, pFile);
471  BOOST_CHECK(pFile);
472  BOOST_CHECK(pFile->fileFormatVersion() == art::FileFormatVersion(1, "RawEvent2011"));
473  BOOST_CHECK(pFile->tree() == nullptr);
474 
475  BOOST_CHECK(!pFile->fastClonable());
476  // Test the end-of-data handling. Reading an end-of-data should result in readNext() returning false,
477  // and should return null pointers for new-run, -subrun and -event.
478  // Prepare our 'previous run/subrun/event'..
479  art::RunID runid(2112);
480  art::SubRunID subrunid(2112, 1);
481  art::EventID eventid(2112, 1, 3);
482  art::Timestamp now;
483  std::unique_ptr<art::RunPrincipal> run(source_helper().makeRunPrincipal(runid.run(), now));
484  std::unique_ptr<art::SubRunPrincipal> subrun(source_helper().makeSubRunPrincipal(runid.run(), subrunid.subRun(), now));
485  std::unique_ptr<art::EventPrincipal> event(source_helper().makeEventPrincipal(runid.run(),
486  subrunid.subRun(),
487  eventid.event(),
488  now));
489  writer().endOfData();
490  art::EventPrincipal* newevent = nullptr;
491  art::SubRunPrincipal* newsubrun = nullptr;
492  art::RunPrincipal* newrun = nullptr;
493  bool rc = reader().readNext(run.get(), subrun.get(), newrun, newsubrun, newevent);
494  BOOST_CHECK(!rc);
495  BOOST_CHECK(newrun == nullptr);
496  BOOST_CHECK(newsubrun == nullptr);
497  BOOST_CHECK(newevent == nullptr);
498 }
499 
500 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.