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