artdaq_core  v3_06_00
SharedMemoryFragmentManager_t.cc
1 #define TRACE_NAME "SharedMemoryFragmentManager_t"
2 
3 #include <memory>
4 
5 #include "artdaq-core/Core/SharedMemoryFragmentManager.hh"
6 #include "artdaq-core/Utilities/configureMessageFacility.hh"
7 #include "tracemf.h"
8 
9 #define BOOST_TEST_MODULE(SharedMemoryFragmentManager_t)
10 #include "SharedMemoryTestShims.hh"
11 #include "cetlib/quiet_unit_test.hpp"
12 #include "cetlib_except/exception.h"
13 
14 BOOST_AUTO_TEST_SUITE(SharedMemoryFragmentManager_test)
15 
16 BOOST_AUTO_TEST_CASE(Construct)
17 {
18  artdaq::configureMessageFacility("SharedMemoryFragmentManager_t", true, true);
19  TLOG(TLVL_INFO) << "BEGIN TEST Construct";
20  artdaq::SharedMemoryFragmentManager man(GetRandomKey(0xF4A6), 10, 0x1000);
21  BOOST_REQUIRE_EQUAL(man.IsValid(), true);
22  BOOST_REQUIRE_EQUAL(man.GetMyId(), 0);
23  BOOST_REQUIRE_EQUAL(man.size(), 10);
24  BOOST_REQUIRE_EQUAL(man.GetAttachedCount(), 1);
25  TLOG(TLVL_INFO) << "END TEST Construct";
26 }
27 
28 BOOST_AUTO_TEST_CASE(Attach)
29 {
30  TLOG(TLVL_INFO) << "BEGIN TEST Attach";
31  uint32_t key = GetRandomKey(0xF4A6);
32  artdaq::SharedMemoryFragmentManager man(key, 10, 0x1000);
34 
35  BOOST_REQUIRE_EQUAL(man.IsValid(), true);
36  BOOST_REQUIRE_EQUAL(man.GetMyId(), 0);
37  BOOST_REQUIRE_EQUAL(man.size(), 10);
38  BOOST_REQUIRE_EQUAL(man.GetAttachedCount(), 2);
39 
40  BOOST_REQUIRE_EQUAL(man2.IsValid(), true);
41  BOOST_REQUIRE_EQUAL(man2.GetMyId(), 1);
42  BOOST_REQUIRE_EQUAL(man2.size(), 10);
43  BOOST_REQUIRE_EQUAL(man2.GetAttachedCount(), 2);
44  TLOG(TLVL_INFO) << "END TEST Attach";
45 }
46 
47 BOOST_AUTO_TEST_CASE(Reattach)
48 {
49  TLOG(TLVL_INFO) << "BEGIN TEST Reattach";
50  uint32_t key = GetRandomKey(0xF4A6);
51  std::unique_ptr<artdaq::SharedMemoryFragmentManager> man(new artdaq::SharedMemoryFragmentManager(key, 10, 0x1000));
52  std::unique_ptr<artdaq::SharedMemoryFragmentManager> man2(new artdaq::SharedMemoryFragmentManager(key));
53 
54  BOOST_REQUIRE_EQUAL(man->IsValid(), true);
55  BOOST_REQUIRE_EQUAL(man->GetMyId(), 0);
56  BOOST_REQUIRE_EQUAL(man->size(), 10);
57  BOOST_REQUIRE_EQUAL(man->GetAttachedCount(), 2);
58 
59  BOOST_REQUIRE_EQUAL(man2->IsValid(), true);
60  BOOST_REQUIRE_EQUAL(man2->GetMyId(), 1);
61  BOOST_REQUIRE_EQUAL(man2->size(), 10);
62  BOOST_REQUIRE_EQUAL(man2->GetAttachedCount(), 2);
63 
64  man2.reset(nullptr);
65  BOOST_REQUIRE_EQUAL(man->IsValid(), true);
66  BOOST_REQUIRE_EQUAL(man->GetAttachedCount(), 1);
67 
68  man2 = std::make_unique<artdaq::SharedMemoryFragmentManager>(key);
69  BOOST_REQUIRE_EQUAL(man->IsValid(), true);
70  BOOST_REQUIRE_EQUAL(man->GetMyId(), 0);
71  BOOST_REQUIRE_EQUAL(man->size(), 10);
72  BOOST_REQUIRE_EQUAL(man->GetAttachedCount(), 2);
73 
74  BOOST_REQUIRE_EQUAL(man2->IsValid(), true);
75  BOOST_REQUIRE_EQUAL(man2->GetMyId(), 2);
76  BOOST_REQUIRE_EQUAL(man2->size(), 10);
77  BOOST_REQUIRE_EQUAL(man2->GetAttachedCount(), 2);
78 
79  man.reset(nullptr);
80  BOOST_REQUIRE_EQUAL(man2->IsValid(), true);
81  BOOST_REQUIRE_EQUAL(man2->IsEndOfData(), true);
82  BOOST_REQUIRE_EQUAL(man2->GetMyId(), 2);
83  BOOST_REQUIRE_EQUAL(man2->size(), 10);
84  BOOST_REQUIRE_EQUAL(man2->GetAttachedCount(), 1);
85 
86  man2->Attach();
87  BOOST_REQUIRE_EQUAL(man2->IsValid(), false);
88 
89  man = std::make_unique<artdaq::SharedMemoryFragmentManager>(key, 10, 0x1000);
90  BOOST_REQUIRE_EQUAL(man->IsValid(), true);
91  BOOST_REQUIRE_EQUAL(man->GetMyId(), 0);
92  BOOST_REQUIRE_EQUAL(man->size(), 10);
93  BOOST_REQUIRE_EQUAL(man->GetAttachedCount(), 1);
94 
95  man2->Attach();
96  BOOST_REQUIRE_EQUAL(man2->IsValid(), true);
97  BOOST_REQUIRE_EQUAL(man2->GetMyId(), 1);
98  BOOST_REQUIRE_EQUAL(man2->size(), 10);
99  BOOST_REQUIRE_EQUAL(man->GetAttachedCount(), 2);
100  BOOST_REQUIRE_EQUAL(man2->GetAttachedCount(), 2);
101 
102  TLOG(TLVL_INFO) << "END TEST Reattach";
103 }
104 
105 BOOST_AUTO_TEST_CASE(DataFlow)
106 {
107  TLOG(TLVL_INFO) << "BEGIN TEST DataFlow";
108  TLOG(TLVL_DEBUG) << "Initializing SharedMemoryFragmentManagers for DataFlow test";
109  uint32_t key = GetRandomKey(0xF4A6);
110  artdaq::SharedMemoryFragmentManager man(key, 10, 0x1000);
112 
113  auto fragSizeWords = 0x1000 / sizeof(artdaq::RawDataType) - artdaq::detail::RawFragmentHeader::num_words() - 1;
114 
115  TLOG(TLVL_DEBUG) << "Creating test Fragment";
116  artdaq::Fragment frag(fragSizeWords);
117  frag.setSequenceID(0x10);
118  frag.setFragmentID(0x20);
120  frag.setSystemType(type);
121  frag.setTimestamp(0x30);
122  for (size_t ii = 0; ii < fragSizeWords; ++ii)
123  {
124  *(frag.dataBegin() + ii) = ii;
125  }
126 
127  TLOG(TLVL_DEBUG) << "Writing Test Fragment to Shared Memory";
128  auto fragSize = frag.size();
129  man.WriteFragment(std::move(frag), false, 0);
130 
131  TLOG(TLVL_DEBUG) << "Reading Test Fragment Header";
133  auto sts = man2.ReadFragmentHeader(header);
134 
135  TLOG(TLVL_DEBUG) << "Checking Test Fragment Header Contents";
136  BOOST_REQUIRE_EQUAL(sts, 0);
137  BOOST_REQUIRE_EQUAL(header.word_count, fragSize);
138  BOOST_REQUIRE_EQUAL(header.sequence_id, 0x10);
139  BOOST_REQUIRE_EQUAL(header.fragment_id, 0x20);
140  BOOST_REQUIRE_EQUAL(header.type, type);
141  BOOST_REQUIRE_EQUAL(header.timestamp, 0x30);
142 
143  TLOG(TLVL_DEBUG) << "Reading Test Fragment data";
144  artdaq::Fragment frag2(header.word_count);
145  sts = man2.ReadFragmentData(frag2.dataBegin(), header.word_count - header.num_words());
146 
147  TLOG(TLVL_DEBUG) << "Checking Test Fragment contents";
148  BOOST_REQUIRE_EQUAL(sts, 0);
149  for (size_t ii = 0; ii < fragSizeWords; ++ii)
150  {
151  BOOST_REQUIRE_EQUAL(ii, *(frag2.dataBegin() + ii));
152  }
153  TLOG(TLVL_DEBUG) << "SharedMemoryFragmentManager DataFlow test complete";
154  TLOG(TLVL_INFO) << "END TEST DataFlow";
155 }
156 
157 BOOST_AUTO_TEST_CASE(WholeFragment)
158 {
159  TLOG(TLVL_INFO) << "BEGIN TEST WholeFragment";
160  TLOG(TLVL_DEBUG) << "Initializing SharedMemoryFragmentManagers for WholeFragment Test";
161  uint32_t key = GetRandomKey(0xF4A6);
162  artdaq::SharedMemoryFragmentManager man(key, 10, 0x1000);
164 
165  auto fragSizeWords = 0x1000 / sizeof(artdaq::RawDataType) - artdaq::detail::RawFragmentHeader::num_words() - 1;
166 
167  TLOG(TLVL_DEBUG) << "Creating test Fragment";
168  artdaq::Fragment frag(fragSizeWords);
169  frag.setSequenceID(0x10);
170  frag.setFragmentID(0x20);
172  frag.setSystemType(type);
173  frag.setTimestamp(0x30);
174  for (size_t ii = 0; ii < fragSizeWords; ++ii)
175  {
176  *(frag.dataBegin() + ii) = ii;
177  }
178 
179  TLOG(TLVL_DEBUG) << "Writing Test Fragment to Shared Memory";
180  auto fragSize = frag.size();
181  man.WriteFragment(std::move(frag), false, 0);
182 
183  TLOG(TLVL_DEBUG) << "Reading Test Fragment Header";
184  artdaq::Fragment recvdFrag;
185  auto sts = man2.ReadFragment(recvdFrag);
186 
187  TLOG(TLVL_DEBUG) << "Checking Test Fragment Header Contents";
188  BOOST_REQUIRE_EQUAL(sts, 0);
189  BOOST_REQUIRE_EQUAL(recvdFrag.size(), fragSize);
190  BOOST_REQUIRE_EQUAL(recvdFrag.sequenceID(), 0x10);
191  BOOST_REQUIRE_EQUAL(recvdFrag.fragmentID(), 0x20);
192  BOOST_REQUIRE_EQUAL(recvdFrag.type(), type);
193  BOOST_REQUIRE_EQUAL(recvdFrag.timestamp(), 0x30);
194 
195  TLOG(TLVL_DEBUG) << "Checking Test Fragment Data Contents";
196  for (size_t ii = 0; ii < fragSizeWords; ++ii)
197  {
198  //TLOG(TLVL_DEBUG) << *(frag.dataBegin() + ii) << " =?= " << *(recvdFrag.dataBegin() + ii) ;
199  BOOST_REQUIRE_EQUAL(ii, *(recvdFrag.dataBegin() + ii));
200  }
201  TLOG(TLVL_DEBUG) << "SharedMemoryFragmentManager WholeFragment test complete";
202  TLOG(TLVL_INFO) << "END TEST WholeFragment";
203 }
204 
205 BOOST_AUTO_TEST_CASE(Timeout)
206 {
207  TLOG(TLVL_INFO) << "BEGIN TEST Timeout";
208  TLOG(TLVL_DEBUG) << "Initializing SharedMemoryFragmentManagers for Timeout Test";
209  uint32_t key = GetRandomKey(0xF4A6);
210  artdaq::SharedMemoryFragmentManager man(key, 1, 0x1000);
211 
212  auto fragSizeWords = 0x1000 / sizeof(artdaq::RawDataType) - artdaq::detail::RawFragmentHeader::num_words() - 1;
213 
214  TLOG(TLVL_DEBUG) << "Creating test Fragment";
215  artdaq::Fragment frag(fragSizeWords);
216  frag.setSequenceID(0x10);
217  frag.setFragmentID(0x20);
219  frag.setSystemType(type);
220  frag.setTimestamp(0x30);
221  for (size_t ii = 0; ii < fragSizeWords; ++ii)
222  {
223  *(frag.dataBegin() + ii) = ii;
224  }
225 
226  TLOG(TLVL_DEBUG) << "Reserving buffer to cause timeout to happen";
227  auto ret = man.GetBufferForWriting(true);
228  BOOST_REQUIRE_EQUAL(ret, 0);
229 
230  TLOG(TLVL_DEBUG) << "Attempting to write Fragment to Shared Memory. This should time out.";
231  auto start_time = std::chrono::steady_clock::now();
232  ret = man.WriteFragment(std::move(frag), true, 100000);
233  auto duration = artdaq::TimeUtils::GetElapsedTimeMicroseconds(start_time);
234 
235  BOOST_REQUIRE_EQUAL(ret, -3);
236  BOOST_REQUIRE_GE(duration, 100000);
237 
238  TLOG(TLVL_DEBUG) << "SharedMemoryFragmentManager Timeout test complete";
239  TLOG(TLVL_INFO) << "END TEST Timeout";
240 }
241 
242 BOOST_AUTO_TEST_SUITE_END()
RawDataType word_count
number of RawDataType words in this Fragment
RawDataType type
The type of the fragment, either system or user-defined.
std::size_t size() const
Gets the size of the Fragment, from the Fragment header.
Definition: Fragment.hh:840
The SharedMemoryFragmentManager is a SharedMemoryManager that deals with Fragment transfers using a S...
static constexpr std::size_t num_words()
Returns the number of RawDataType words present in the header.
The RawFragmentHeader class contains the basic fields used by artdaq for routing Fragment objects thr...
RawDataType timestamp
The 64-bit timestamp field is the output of a user-defined clock used for building time-correlated ev...
RawDataType sequence_id
The 48-bit sequence_id uniquely identifies events within the artdaq system.
sequence_id_t sequenceID() const
Sequence ID of the Fragment, from the Fragment header.
Definition: Fragment.hh:865
timestamp_t timestamp() const
Timestamp of the Fragment, from the Fragment header.
Definition: Fragment.hh:877
constexpr size_t GetElapsedTimeMicroseconds(std::chrono::steady_clock::time_point then, std::chrono::steady_clock::time_point now=std::chrono::steady_clock::now())
Gets the number of microseconds in the given time interval
Definition: TimeUtils.hh:41
static constexpr type_t DataFragmentType
Copy DataFragmentType from RawFragmentHeader.
Definition: Fragment.hh:149
RawDataType fragment_id
The fragment_id uniquely identifies a particular piece of hardware within the artdaq system...
iterator dataBegin()
Return an iterator to the beginning of the data payload (after header and metadata) ...
Definition: Fragment.hh:1070
type_t type() const
Type of the Fragment, from the Fragment header.
Definition: Fragment.hh:853
void configureMessageFacility(char const *progname, bool useConsole=true, bool printDebug=false)
Configure and start the message facility. Provide the program name so that messages will be appropria...
detail::RawFragmentHeader::RawDataType RawDataType
The RawDataType (currently a 64-bit integer) is the basic unit of data representation within artdaq ...
Definition: Fragment.hh:40
A Fragment contains the data from one piece of the DAQ system for one event The artdaq::Fragment is t...
Definition: Fragment.hh:85
fragment_id_t fragmentID() const
Fragment ID of the Fragment, from the Fragment header.
Definition: Fragment.hh:871