2 #include "artdaq-core/Core/SharedMemoryEventReceiver.hh"
5 #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(TLVL_TRACE) <<
"SharedMemoryEventReceiver CONSTRUCTOR";
24 TLOG(TLVL_TRACE) <<
"ReadyForRead BEGIN timeout_us=" << timeout_us;
25 if (current_read_buffer_ != -1 && (current_data_source_ !=
nullptr) && (current_header_ !=
nullptr))
27 TLOG(TLVL_TRACE) <<
"ReadyForRead Returning true because already reading buffer";
33 uint64_t time_diff = 0;
34 uint64_t max_sleep = 5000000;
36 while (first || time_diff < timeout_us)
38 if (broadcasts_.ReadyForRead())
40 buf = broadcasts_.GetBufferForReading();
41 current_data_source_ = &broadcasts_;
43 else if (!broadcast && data_.ReadyForRead())
45 buf = data_.GetBufferForReading();
46 current_data_source_ = &data_;
48 if (buf != -1 && (current_data_source_ !=
nullptr))
50 current_read_buffer_ = buf;
51 current_data_source_->ResetReadPos(buf);
53 TLOG(TLVL_TRACE) <<
"ReadyForRead Found buffer, returning true. event hdr sequence_id=" << current_header_->
sequence_id;
56 if (current_data_source_ == &broadcasts_)
59 auto types = GetFragmentTypes(err);
73 current_data_source_ =
nullptr;
76 if (broadcasts_.IsEndOfData() || data_.IsEndOfData())
78 TLOG(TLVL_TRACE) <<
"End-Of-Data condition detected, returning false";
83 auto sleep_time = time_diff;
84 if (sleep_time < 10000) sleep_time = 10000;
85 if (sleep_time > max_sleep) sleep_time = max_sleep;
88 TLOG(TLVL_TRACE) <<
"ReadyForRead returning false";
94 TLOG(TLVL_TRACE) <<
"ReadHeader BEGIN";
95 if (current_read_buffer_ != -1 && (current_data_source_ !=
nullptr))
100 TLOG(TLVL_WARNING) <<
"Buffer was in incorrect state, resetting";
101 current_data_source_ =
nullptr;
102 current_read_buffer_ = -1;
103 current_header_ =
nullptr;
107 TLOG(TLVL_TRACE) <<
"Already have buffer, returning stored header";
108 return current_header_;
113 if (current_read_buffer_ == -1 || (current_header_ ==
nullptr) || (current_data_source_ ==
nullptr))
115 throw cet::exception(
"AccessViolation") <<
"Cannot call GetFragmentTypes when not currently reading a buffer! Call ReadHeader() first!";
121 return std::set<Fragment::type_t>();
124 current_data_source_->ResetReadPos(current_read_buffer_);
126 auto output = std::set<Fragment::type_t>();
128 while (current_data_source_->MoreDataInBuffer(current_read_buffer_))
133 return std::set<Fragment::type_t>();
136 output.insert(fragHdr->type);
137 current_data_source_->IncrementReadPos(current_read_buffer_, fragHdr->word_count *
sizeof(
RawDataType));
145 if ((current_data_source_ ==
nullptr) || (current_header_ ==
nullptr) || current_read_buffer_ == -1)
147 throw cet::exception(
"AccessViolation") <<
"Cannot call GetFragmentsByType when not currently reading a buffer! Call ReadHeader() first!";
155 current_data_source_->ResetReadPos(current_read_buffer_);
158 std::unique_ptr<Fragments> output(
new Fragments());
160 while (current_data_source_->MoreDataInBuffer(current_read_buffer_))
171 current_data_source_->Read(current_read_buffer_, output->back().headerAddress(), fragHdr->word_count *
sizeof(
RawDataType));
172 output->back().autoResize();
176 current_data_source_->IncrementReadPos(current_read_buffer_, fragHdr->word_count *
sizeof(
RawDataType));
183 std::string artdaq::SharedMemoryEventReceiver::printBuffers_(
SharedMemoryManager* data_source)
185 std::ostringstream ostr;
186 for (
size_t ii = 0; ii < data_source->
size(); ++ii)
188 ostr <<
"Buffer " << ii <<
": " << std::endl;
196 ostr <<
" Fragment " << fragHdr->
fragment_id <<
": Sequence ID: " << fragHdr->sequence_id <<
", Type:" << fragHdr->type;
201 ostr <<
", Size: " << fragHdr->word_count <<
" words." << std::endl;
210 std::ostringstream ostr;
211 ostr << data_.toString() << std::endl;
213 ostr <<
"Data Buffer Fragment Counts: " << std::endl;
214 ostr << printBuffers_(&data_);
216 if (data_.GetKey() != broadcasts_.GetKey())
218 ostr <<
"Broadcast Buffer Fragment Counts: " << std::endl;
219 ostr << printBuffers_(&broadcasts_);
227 TLOG(TLVL_TRACE) <<
"ReleaseBuffer BEGIN";
230 if (current_data_source_ !=
nullptr)
232 current_data_source_->MarkBufferEmpty(current_read_buffer_,
false,
false);
235 catch (cet::exception
const& e)
237 TLOG(TLVL_WARNING) <<
"A cet::exception occured while trying to release the buffer: " << e;
241 TLOG(TLVL_ERROR) <<
"An unknown exception occured while trying to release the buffer";
243 current_read_buffer_ = -1;
244 current_header_ =
nullptr;
245 current_data_source_ =
nullptr;
246 TLOG(TLVL_TRACE) <<
"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.
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.