artdaq  v3_04_01
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 #include "art/Persistency/Provenance/MasterProductRegistry.h"
16 #include "art/Persistency/Provenance/ProductMetaData.h"
17 #include "canvas/Persistency/Provenance/EventID.h"
18 #include "canvas/Persistency/Provenance/FileFormatVersion.h"
19 #include "canvas/Persistency/Provenance/ModuleDescription.h"
20 #include "canvas/Persistency/Provenance/Parentage.h"
21 #include "canvas/Persistency/Provenance/ProcessConfiguration.h"
22 #include "canvas/Persistency/Provenance/RunID.h"
23 #include "canvas/Persistency/Provenance/SubRunID.h"
24 #include "canvas/Persistency/Provenance/Timestamp.h"
25 #include "canvas/Utilities/Exception.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 
65  art::ProcessConfiguration*
66  fake_single_module_process(std::string const& tag,
67  std::string const& processName,
68  fhicl::ParameterSet const& moduleParams,
69  std::string const& release = art::getReleaseVersion()
70  );
71 
79  std::unique_ptr<art::BranchDescription>
80  fake_single_process_branch(std::string const& tag,
81  std::string const& processName,
82  std::string const& productInstanceName = std::string());
83 
87  void finalize();
88 
89  art::MasterProductRegistry productRegistry_;
90  //art::RootDictionaryManager rdm_;
91 };
92 
94  :
95  branchKeys_()
96  , processConfigurations_()
97  , productRegistry_()//,
98 // rdm_()
99 {
100  // We can only insert products registered in the MasterProductRegistry.
101  productRegistry_.addProduct(fake_single_process_branch("hlt", "HLT"));
102  productRegistry_.addProduct(fake_single_process_branch("prod", "PROD"));
103  productRegistry_.addProduct(fake_single_process_branch("test", "TEST"));
104  productRegistry_.addProduct(fake_single_process_branch("user", "USER"));
105  productRegistry_.addProduct(fake_single_process_branch("rick", "USER2", "rick"));
106 }
107 
108 void
110 {
111  productRegistry_.setFrozen();
112  art::ProductMetaData::create_instance(productRegistry_);
113 }
114 
115 art::ProcessConfiguration*
117 fake_single_module_process(std::string const& tag,
118  std::string const& processName,
119  fhicl::ParameterSet const& moduleParams,
120  std::string const& release
121 )
122 {
123  fhicl::ParameterSet processParams;
124  processParams.put(processName, moduleParams);
125  processParams.put<std::string>("process_name",
126  processName);
127  auto emplace_pair =
128  processConfigurations_.emplace(tag,
129  std::make_unique<art::ProcessConfiguration>(processName, processParams.id(), release, pass));
130  return emplace_pair.first->second.get();
131 }
132 
133 std::unique_ptr<art::BranchDescription>
135 fake_single_process_branch(std::string const& tag,
136  std::string const& processName,
137  std::string const& productInstanceName)
138 {
139  std::string moduleLabel = processName + "dummyMod";
140  std::string moduleClass("DummyModule");
141  fhicl::ParameterSet modParams;
142  modParams.put<std::string>("module_type", moduleClass);
143  modParams.put<std::string>("module_label", moduleLabel);
144  art::ProcessConfiguration* process =
145  fake_single_module_process(tag, processName, modParams);
146  art::ModuleDescription mod(modParams.id(),
147  moduleClass,
148  moduleLabel,
149  *process);
150  art::TypeID dummyType(typeid(int));
151  art::BranchDescription* result =
152  new art::BranchDescription(
153  art::InEvent,
154  art::TypeLabel(dummyType,
155  productInstanceName),
156  mod);
157 
158 
159  branchKeys_.insert(std::make_pair(tag, art::BranchKey(*result)));
160  return std::unique_ptr<art::BranchDescription>(result);
161 }
162 
167 {
172  {
173  static bool once(true);
174  if (once)
175  {
176  artdaq::configureMessageFacility("shared_memory_reader_t");
177  (void)reader(); // Force initialization.
178  art::ModuleDescription md(fhicl::ParameterSet().id(),
179  "_NAMEERROR_",
180  "_LABELERROR_",
181  *gf().processConfigurations_["daq"]);
182  // These _xERROR_ strings should never appear in branch names; they
183  // are here as tracers to help identify any failures in coding.
184  helper().registerProducts(gf().productRegistry_, md);
185  gf().finalize();
186  once = false;
187  }
188  }
189 
195  {
196  static MPRGlobalTestFixture mpr;
197  return mpr;
198  }
199 
204  art::ProductRegistryHelper& helper()
205  {
206  static art::ProductRegistryHelper s_helper;
207  return s_helper;
208  }
209 
214  art::SourceHelper& source_helper()
215  {
216  static std::unique_ptr<art::SourceHelper>
217  s_source_helper;
218  if (!s_source_helper)
219  {
220  fhicl::ParameterSet sourceParams;
221  std::string moduleType{ "DummySource" };
222  std::string moduleLabel{ "daq" };
223  sourceParams.put<std::string>("module_type", moduleType);
224  sourceParams.put<std::string>("module_label", moduleLabel);
225  auto pc_ptr = gf().fake_single_module_process(moduleLabel,
226  "TEST",
227  sourceParams);
228  art::ModuleDescription md(sourceParams.id(),
229  moduleType,
230  moduleLabel,
231  *pc_ptr);
232  s_source_helper = std::make_unique<art::SourceHelper>(md);
233  }
234  return *s_source_helper;
235  }
236 
241  uint32_t getKey()
242  {
243  static uint32_t key = static_cast<uint32_t>(std::hash<std::string>()("shared_memory_reader_t"));
244  return key;
245  }
250  uint32_t getBroadcastKey()
251  {
252  static uint32_t key = static_cast<uint32_t>(std::hash<std::string>()("shared_memory_reader_t BROADCAST"));
253  return key;
254  }
255 
261  {
262  writer();
263  fhicl::ParameterSet pset;
264  pset.put("shared_memory_key", getKey());
265  pset.put("broadcast_shared_memory_key", getBroadcastKey());
266  pset.put("max_event_size_bytes", 0x100000);
267  pset.put("buffer_count", 10);
269  s_reader(pset,
270  helper(),
271  source_helper(),
272  gf().productRegistry_);
273  static bool reader_initialized = false;
274  if (!reader_initialized)
275  {
276  s_reader.fragment_type_map_[1] = "ABCDEF";
277  helper().reconstitutes<artdaq::Fragments, art::InEvent>("daq", "ABCDEF");
278  reader_initialized = true;
279  }
280  return s_reader;
281  }
282 
288  {
289  fhicl::ParameterSet pset;
290  pset.put("shared_memory_key", getKey());
291  pset.put("broadcast_shared_memory_key", getBroadcastKey());
292  pset.put("max_event_size_bytes", 0x100000);
293  pset.put("art_analyzer_count", 0);
294  pset.put("stale_buffer_timeout_usec", 100000);
295  pset.put("expected_fragments_per_event", 1);
296  pset.put("buffer_count", 10);
298  s_writer(pset, pset);
299  return s_writer;
300 
301  }
302 };
303 
304 BOOST_FIXTURE_TEST_SUITE(shared_memory_reader_t, ShmRTestFixture)
305 
306 namespace
307 {
318  std::unique_ptr<art::RunPrincipal>&& run,
319  std::unique_ptr<art::SubRunPrincipal>&& subrun,
320  art::EventID const& eventid)
321  {
322  BOOST_REQUIRE(run || subrun == nullptr); // Sanity check.
323  std::vector<artdaq::Fragment::value_type> fakeData{ 1, 2, 3, 4 };
324  artdaq::FragmentPtr
325  tmpFrag(artdaq::Fragment::dataFrag(eventid.event(),
326  0,
327  fakeData.begin(),
328  fakeData.end()));
329  tmpFrag->setUserType(1);
330 
331  writer.startRun(eventid.run());
332 
333 
334  auto iter = tmpFrag->dataBegin();
335  std::ostringstream str;
336  str << "{";
337  while (iter != tmpFrag->dataEnd())
338  {
339  str << *iter << ", ";
340  ++iter;
341 
342  }
343  str << "}";
344  TLOG(TLVL_DEBUG) << "Fragment to art: " << str.str();
345 
346 
347  artdaq::FragmentPtr tempFrag;
348  auto sts = writer.AddFragment(std::move(tmpFrag), 1000000, tempFrag);
349  BOOST_REQUIRE_EQUAL(sts, true);
350 
351  while (writer.GetLockedBufferCount())
352  {
353  writer.sendMetrics();
354  usleep(100000);
355  }
356 
357  art::EventPrincipal* newevent = nullptr;
358  art::SubRunPrincipal* newsubrun = nullptr;
359  art::RunPrincipal* newrun = nullptr;
360  bool rc = reader.readNext(run.get(), subrun.get(), newrun, newsubrun, newevent);
361  BOOST_REQUIRE(rc);
362  if (run.get() && run->run() == eventid.run())
363  {
364  BOOST_CHECK(newrun == nullptr);
365  }
366  else
367  {
368  BOOST_CHECK(newrun);
369  BOOST_CHECK(newrun->id() == eventid.runID());
370  }
371  if (!newrun && subrun.get() && subrun->subRun() == eventid.subRun())
372  {
373  BOOST_CHECK(newsubrun == nullptr);
374  }
375  else
376  {
377  BOOST_CHECK(newsubrun);
378  BOOST_CHECK(newsubrun->id() == eventid.subRunID());
379  }
380  BOOST_CHECK(newevent);
381  BOOST_CHECK(newevent->id() == eventid);
382  art::Event e(*newevent, art::ModuleDescription());
383  art::Handle<std::vector<artdaq::Fragment>> h;
384  e.getByLabel("daq", "ABCDEF", h);
385  BOOST_CHECK(h.isValid());
386  BOOST_CHECK(h->size() == 1);
387 
388  auto iter2 = h->front().dataBegin();
389  std::ostringstream str2;
390  str2 << "{";
391  while (iter2 != h->front().dataEnd())
392  {
393  str2 << *iter2 << ", ";
394  ++iter2;
395 
396  }
397  str2 << "}";
398  TLOG(TLVL_DEBUG) << "Fragment from art: " << str2.str();
399 
400  BOOST_CHECK(std::equal(fakeData.begin(),
401  fakeData.end(),
402  h->front().dataBegin()));
403  delete(newrun);
404  delete(newsubrun);
405  delete(newevent);
406  }
407 }
408 
409 BOOST_AUTO_TEST_CASE(nonempty_event)
410 {
411  art::EventID eventid(2112, 1, 3);
412  art::Timestamp now;
413  basic_test(reader(), writer(),
414  std::unique_ptr<art::RunPrincipal>(source_helper().makeRunPrincipal(eventid.run(), now)),
415  std::unique_ptr<art::SubRunPrincipal>(source_helper().makeSubRunPrincipal(eventid.run(), eventid.subRun(), now)),
416  eventid);
417 }
418 
419 BOOST_AUTO_TEST_CASE(first_event)
420 {
421  art::EventID eventid(2112, 1, 3);
422  art::Timestamp now;
423  basic_test(reader(), writer(),
424  nullptr,
425  nullptr,
426  eventid);
427 }
428 
429 BOOST_AUTO_TEST_CASE(new_subrun)
430 {
431  art::EventID eventid(2112, 1, 3);
432  art::Timestamp now;
433  basic_test(reader(), writer(),
434  std::unique_ptr<art::RunPrincipal>(source_helper().makeRunPrincipal(eventid.run(), now)),
435  std::unique_ptr<art::SubRunPrincipal>(source_helper().makeSubRunPrincipal(eventid.run(), 0, now)),
436  eventid);
437 }
438 
439 BOOST_AUTO_TEST_CASE(new_run)
440 {
441  art::EventID eventid(2112, 1, 3);
442  art::Timestamp now;
443  basic_test(reader(), writer(),
444  std::unique_ptr<art::RunPrincipal>(source_helper().makeRunPrincipal(eventid.run() - 1, now)),
445  std::unique_ptr<art::SubRunPrincipal>(source_helper().makeSubRunPrincipal(eventid.run() - 1,
446  eventid.subRun(),
447  now)),
448  eventid);
449 }
450 
451 BOOST_AUTO_TEST_CASE(end_of_data)
452 {
453  // Tell 'reader' the name of the file we are to read. This is pretty
454  // much irrelevant for SharedMemoryReader, but we'll stick to the
455  // interface demanded by Source<T>...
456  std::string const fakeFileName("no such file exists");
457  art::FileBlock* pFile = nullptr;
458  reader().readFile(fakeFileName, pFile);
459  BOOST_CHECK(pFile);
460  BOOST_CHECK(pFile->fileFormatVersion() == art::FileFormatVersion(1, "RawEvent2011"));
461  BOOST_CHECK(pFile->tree() == nullptr);
462 
463  BOOST_CHECK(!pFile->fastClonable());
464  // Test the end-of-data handling. Reading an end-of-data should result in readNext() returning false,
465  // and should return null pointers for new-run, -subrun and -event.
466  // Prepare our 'previous run/subrun/event'..
467  art::RunID runid(2112);
468  art::SubRunID subrunid(2112, 1);
469  art::EventID eventid(2112, 1, 3);
470  art::Timestamp now;
471  std::unique_ptr<art::RunPrincipal> run(source_helper().makeRunPrincipal(runid.run(), now));
472  std::unique_ptr<art::SubRunPrincipal> subrun(source_helper().makeSubRunPrincipal(runid.run(), subrunid.subRun(), now));
473  std::unique_ptr<art::EventPrincipal> event(source_helper().makeEventPrincipal(runid.run(),
474  subrunid.subRun(),
475  eventid.event(),
476  now));
477  writer().endOfData();
478  art::EventPrincipal* newevent = nullptr;
479  art::SubRunPrincipal* newsubrun = nullptr;
480  art::RunPrincipal* newrun = nullptr;
481  bool rc = reader().readNext(run.get(), subrun.get(), newrun, newsubrun, newevent);
482  BOOST_CHECK(!rc);
483  BOOST_CHECK(newrun == nullptr);
484  BOOST_CHECK(newsubrun == nullptr);
485  BOOST_CHECK(newevent == nullptr);
486 }
487 
488 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.
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::ProcessConfiguration * fake_single_module_process(std::string const &tag, std::string const &processName, fhicl::ParameterSet const &moduleParams, std::string const &release=art::getReleaseVersion())
Create the ProcessConfiguration for a single module art process.
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.