2 #include "artdaq-core/Core/SharedMemoryEventReceiver.hh"
4 #include "artdaq-core/Data/Fragment.hh"
6 #define TRACE_NAME "SharedMemoryEventReceiver"
12 : current_read_buffer_(-1)
14 , current_header_(nullptr)
15 , current_data_source_(nullptr)
17 , broadcasts_(broadcast_shm_key)
19 TLOG_TRACE(
"SharedMemoryEventReceiver") <<
"SharedMemoryEventReceiver CONSTRUCTOR" << TLOG_ENDL;
24 TLOG_TRACE(
"SharedMemoryEventReceiver") <<
"ReadyForRead BEGIN" << TLOG_ENDL;
25 if (current_read_buffer_ != -1 && current_data_source_ && current_header_)
27 TLOG_TRACE(
"SharedMemoryEventReceiver") <<
"ReadyForRead Returning true because already reading buffer" << TLOG_ENDL;
35 if (broadcasts_.ReadyForRead())
37 buf = broadcasts_.GetBufferForReading();
38 current_data_source_ = &broadcasts_;
40 else if (!broadcast && data_.ReadyForRead())
42 buf = data_.GetBufferForReading();
43 current_data_source_ = &data_;
45 if (buf != -1 && current_data_source_)
47 TLOG_TRACE(
"SharedMemoryEventReceiver") <<
"ReadyForRead Found buffer, returning true" << TLOG_ENDL;
48 current_read_buffer_ = buf;
49 current_data_source_->ResetReadPos(buf);
53 if (current_data_source_ == &broadcasts_)
56 auto types = GetFragmentTypes(err);
70 current_data_source_ =
nullptr;
72 TLOG_TRACE(
"SharedMemoryEventReceiver") <<
"ReadyForRead returning false" << TLOG_ENDL;
78 TLOG_TRACE(
"SharedMemoryEventReceiver") <<
"ReadHeader BEGIN" << TLOG_ENDL;
79 if (current_read_buffer_ != -1 && current_data_source_)
84 TLOG_WARNING(
"SharedMemoryEventReceiver") <<
"Buffer was in incorrect state, resetting" << TLOG_ENDL;
85 current_data_source_ =
nullptr;
86 current_read_buffer_ = -1;
87 current_header_ =
nullptr;
91 TLOG_TRACE(
"SharedMemoryEventReceiver") <<
"Already have buffer, returning stored header" << TLOG_ENDL;
92 return current_header_;
97 if (current_read_buffer_ == -1 || !current_header_ || !current_data_source_)
throw cet::exception(
"AccessViolation") <<
"Cannot call GetFragmentTypes when not currently reading a buffer! Call ReadHeader() first!";
100 if (err)
return std::set<Fragment::type_t>();
102 current_data_source_->ResetReadPos(current_read_buffer_);
104 auto output = std::set<Fragment::type_t>();
106 while (current_data_source_->MoreDataInBuffer(current_read_buffer_))
109 if (err)
return std::set<Fragment::type_t>();
111 output.insert(fragHdr->type);
112 current_data_source_->IncrementReadPos(current_read_buffer_, fragHdr->word_count *
sizeof(
RawDataType));
121 if (!current_data_source_ || !current_header_ || current_read_buffer_ == -1)
throw cet::exception(
"AccessViolation") <<
"Cannot call GetFragmentsByType when not currently reading a buffer! Call ReadHeader() first!";
123 if (err)
return nullptr;
125 current_data_source_->ResetReadPos(current_read_buffer_);
128 std::unique_ptr<Fragments> output(
new Fragments());
130 while (current_data_source_->MoreDataInBuffer(current_read_buffer_))
133 if (err)
return nullptr;
138 current_data_source_->Read(current_read_buffer_, output->back().headerAddress(), fragHdr->word_count *
sizeof(
RawDataType));
139 output->back().autoResize();
143 current_data_source_->IncrementReadPos(current_read_buffer_, fragHdr->word_count *
sizeof(
RawDataType));
147 return std::move(output);
150 std::string artdaq::SharedMemoryEventReceiver::printBuffers_(
SharedMemoryManager* data_source)
152 std::ostringstream ostr;
153 for (
size_t ii = 0; ii < data_source->
size(); ++ii)
155 ostr <<
"Buffer " << std::to_string(ii) <<
": " << std::endl;
163 ostr <<
" Fragment " << std::to_string(fragHdr->fragment_id) <<
": Sequence ID: " << std::to_string(fragHdr->sequence_id) <<
", Type:" << std::to_string(fragHdr->type);
164 if (fragHdr->MakeVerboseSystemTypeMap().count(fragHdr->type))
166 ostr <<
" (" << fragHdr->MakeVerboseSystemTypeMap()[fragHdr->type] <<
")";
168 ostr <<
", Size: " << std::to_string(fragHdr->word_count) <<
" words." << std::endl;
178 std::ostringstream ostr;
179 ostr << data_.toString() << std::endl;
181 ostr <<
"Data Buffer Fragment Counts: " << std::endl;
182 ostr << printBuffers_(&data_);
184 if (data_.GetKey() != broadcasts_.GetKey())
186 ostr <<
"Broadcast Buffer Fragment Counts: " << std::endl;
187 ostr << printBuffers_(&broadcasts_);
195 TLOG_TRACE(
"SharedMemoryEventReceiver") <<
"ReleaseBuffer BEGIN" << TLOG_ENDL;
198 current_data_source_->MarkBufferEmpty(current_read_buffer_);
200 catch (cet::exception e)
202 TLOG_WARNING(
"SharedMemoryEventReceiver") <<
"A cet::exception occured while trying to release the buffer: " << e << TLOG_ENDL;
206 TLOG_ERROR(
"SharedMemoryEventReceiver") <<
"An unknown exception occured while trying to release the buffer" << TLOG_ENDL;
208 current_read_buffer_ = -1;
209 current_header_ =
nullptr;
210 current_data_source_ =
nullptr;
211 TLOG_TRACE(
"SharedMemoryEventReceiver") <<
"ReleaseBuffer END" << TLOG_ENDL;
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.
void IncrementReadPos(int buffer, size_t read)
Increment the read position for a given buffer.
detail::RawFragmentHeader::type_t type_t
typedef for type_t from RawFragmentHeader
void ResetReadPos(int buffer)
Set the read position of the given buffer to the beginning of the buffer.
bool MoreDataInBuffer(int buffer)
Determine if more data is available to be read, based on the read position and data size...
static constexpr type_t InitFragmentType
Copy InitFragmentType from RawFragmentHeader.
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.
void * GetReadPos(int buffer)
Get a pointer to the current read position of the buffer.
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.
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.