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