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