2 #include "artdaq-core/Core/SharedMemoryEventReceiver.hh"
5 #include "artdaq-core/Data/Fragment.hh"
6 #define TRACE_NAME "SharedMemoryEventReceiver"
7 #include "TRACE/tracemf.h"
10 : current_read_buffer_(-1)
12 , current_header_(nullptr)
13 , current_data_source_(nullptr)
15 , broadcasts_(broadcast_shm_key)
17 TLOG(TLVL_DEBUG + 33) <<
"SharedMemoryEventReceiver CONSTRUCTOR";
22 TLOG(TLVL_DEBUG + 33) <<
"ReadyForRead BEGIN timeout_us=" << timeout_us;
23 if (current_read_buffer_ != -1 && (current_data_source_ !=
nullptr) && (current_header_ !=
nullptr))
25 TLOG(TLVL_DEBUG + 33) <<
"ReadyForRead Returning true because already reading buffer";
31 uint64_t time_diff = 0;
32 uint64_t max_sleep = 5000000;
34 while (first || time_diff < timeout_us)
36 if (broadcasts_.ReadyForRead())
38 buf = broadcasts_.GetBufferForReading();
39 current_data_source_ = &broadcasts_;
41 else if (!broadcast && data_.ReadyForRead())
43 buf = data_.GetBufferForReading();
44 current_data_source_ = &data_;
46 if (buf != -1 && (current_data_source_ !=
nullptr))
48 current_read_buffer_ = buf;
49 current_data_source_->ResetReadPos(buf);
51 TLOG(TLVL_DEBUG + 33) <<
"ReadyForRead Found buffer, returning true. event hdr sequence_id=" << current_header_->
sequence_id;
54 if (current_data_source_ == &broadcasts_)
57 auto types = GetFragmentTypes(err);
71 current_data_source_ =
nullptr;
74 if (broadcasts_.IsEndOfData() || data_.IsEndOfData())
76 TLOG(TLVL_DEBUG + 33) <<
"End-Of-Data condition detected, returning false";
81 auto sleep_time = time_diff;
82 if (sleep_time < 10000) sleep_time = 10000;
83 if (sleep_time > max_sleep) sleep_time = max_sleep;
86 TLOG(TLVL_DEBUG + 33) <<
"ReadyForRead returning false";
92 TLOG(TLVL_DEBUG + 33) <<
"ReadHeader BEGIN";
93 if (current_read_buffer_ != -1 && (current_data_source_ !=
nullptr))
98 TLOG(TLVL_WARNING) <<
"Buffer was in incorrect state, resetting";
99 current_data_source_ =
nullptr;
100 current_read_buffer_ = -1;
101 current_header_ =
nullptr;
105 TLOG(TLVL_DEBUG + 33) <<
"Already have buffer, returning stored header";
106 return current_header_;
111 if (current_read_buffer_ == -1 || (current_header_ ==
nullptr) || (current_data_source_ ==
nullptr))
113 throw cet::exception(
"AccessViolation") <<
"Cannot call GetFragmentTypes when not currently reading a buffer! Call ReadHeader() first!";
119 return std::set<Fragment::type_t>();
122 current_data_source_->ResetReadPos(current_read_buffer_);
124 auto output = std::set<Fragment::type_t>();
126 while (current_data_source_->MoreDataInBuffer(current_read_buffer_))
131 return std::set<Fragment::type_t>();
134 output.insert(fragHdr->type);
135 current_data_source_->IncrementReadPos(current_read_buffer_, fragHdr->word_count *
sizeof(
RawDataType));
143 if ((current_data_source_ ==
nullptr) || (current_header_ ==
nullptr) || current_read_buffer_ == -1)
145 throw cet::exception(
"AccessViolation") <<
"Cannot call GetFragmentsByType when not currently reading a buffer! Call ReadHeader() first!";
153 current_data_source_->ResetReadPos(current_read_buffer_);
156 std::unique_ptr<Fragments> output(
new Fragments());
158 while (current_data_source_->MoreDataInBuffer(current_read_buffer_))
169 current_data_source_->Read(current_read_buffer_, output->back().headerAddress(), fragHdr->word_count *
sizeof(
RawDataType));
170 output->back().autoResize();
174 current_data_source_->IncrementReadPos(current_read_buffer_, fragHdr->word_count *
sizeof(
RawDataType));
181 std::string artdaq::SharedMemoryEventReceiver::printBuffers_(
SharedMemoryManager* data_source)
183 std::ostringstream ostr;
184 for (
size_t ii = 0; ii < data_source->
size(); ++ii)
186 ostr <<
"Buffer " << ii <<
": " << std::endl;
189 void* end_ptr =
static_cast<uint8_t*
>(data_ptr) + data_source->
BufferDataSize(ii);
191 TLOG_DEBUG(33) <<
"Buffer " << ii <<
": data_ptr: " << data_ptr <<
", end_ptr: " << end_ptr;
193 while (data_ptr < end_ptr)
196 ostr <<
" Fragment " << fragHdr->
fragment_id <<
": Sequence ID: " << fragHdr->sequence_id <<
", Type:" << fragHdr->type;
201 ostr <<
", Size: " << fragHdr->word_count <<
" words." << std::endl;
202 data_ptr =
static_cast<uint8_t*
>(data_ptr) + fragHdr->word_count *
sizeof(
RawDataType);
204 TLOG_DEBUG(33) <<
"Buffer " << ii <<
": After reading Fragment of size " <<
static_cast<int>(fragHdr->word_count *
sizeof(
RawDataType)) <<
" data_ptr: " << data_ptr <<
", end_ptr: " << end_ptr;
212 std::ostringstream ostr;
213 ostr << data_.toString() << std::endl;
215 ostr <<
"Data Buffer Fragment Counts: " << std::endl;
216 ostr << printBuffers_(&data_);
218 if (data_.GetKey() != broadcasts_.GetKey())
220 ostr <<
"Broadcast Buffer Fragment Counts: " << std::endl;
221 ostr << printBuffers_(&broadcasts_);
229 TLOG(TLVL_DEBUG + 33) <<
"ReleaseBuffer BEGIN";
232 if (current_data_source_ !=
nullptr)
234 current_data_source_->MarkBufferEmpty(current_read_buffer_,
false,
false);
237 catch (cet::exception
const& e)
239 TLOG(TLVL_WARNING) <<
"A cet::exception occured while trying to release the buffer: " << e;
243 TLOG(TLVL_ERROR) <<
"An unknown exception occured while trying to release the buffer";
245 current_read_buffer_ = -1;
246 current_header_ =
nullptr;
247 current_data_source_ =
nullptr;
248 TLOG(TLVL_DEBUG + 33) <<
"ReleaseBuffer END";
static constexpr type_t InvalidFragmentType
Copy InvalidFragmentType from RawFragmentHeader.
std::vector< Fragment > Fragments
A std::vector of Fragment objects.
void ReleaseBuffer()
Release the buffer currently being read to the Empty state.
detail::RawFragmentHeader::type_t type_t
typedef for type_t from RawFragmentHeader
static constexpr type_t InitFragmentType
Copy InitFragmentType from RawFragmentHeader.
size_t BufferDataSize(int buffer)
Get the current size of the buffer's data.
The buffer is currently being read from.
The SharedMemoryManager creates a Shared Memory area which is divided into a number of fixed-size buf...
SharedMemoryEventReceiver(uint32_t shm_key, uint32_t broadcast_shm_key)
Connect to a Shared Memory segment using the given parameters.
size_t size() const
Get the number of buffers in the shared memory segment.
detail::RawFragmentHeader::RawDataType RawDataType
The RawDataType (currently a 64-bit integer) is the basic unit of data representation within artdaq ...
std::set< Fragment::type_t > GetFragmentTypes(bool &err)
Get a set of Fragment Types present in the event.
bool ReadyForRead(bool broadcast=false, size_t timeout_us=1000000)
Determine whether an event is available for reading.
std::string toString()
Write out information about the Shared Memory to a string.
void * GetBufferStart(int buffer)
Get a pointer to the start position of the buffer.
detail::RawEventHeader * ReadHeader(bool &err)
Get the Event header.
uint64_t gettimeofday_us()
Get the current time of day in microseconds (from gettimeofday system call)
std::unique_ptr< Fragments > GetFragmentsByType(bool &err, Fragment::type_t type)
Get a pointer to the Fragments of a given type in the event.