artdaq_core  v3_04_09
SharedMemoryFragmentManager.cc
1 
2 #define TRACE_NAME "SharedMemoryFragmentManager"
3 #include "artdaq-core/Core/SharedMemoryFragmentManager.hh"
4 #include "tracemf.h"
5 
6 
7 artdaq::SharedMemoryFragmentManager::SharedMemoryFragmentManager(uint32_t shm_key, size_t buffer_count, size_t max_buffer_size, size_t buffer_timeout_us)
8  : SharedMemoryManager(shm_key, buffer_count, max_buffer_size, buffer_timeout_us)
9  , active_buffer_(-1)
10 {
11 
12 }
13 
15 {
16  TLOG(12) << "ReadyForWrite: active_buffer is " << active_buffer_;
17  if (active_buffer_ != -1) return true;
18  active_buffer_ = GetBufferForWriting(overwrite);
19 
20  return active_buffer_ != -1;
21 }
22 
23 int artdaq::SharedMemoryFragmentManager::WriteFragment(Fragment&& fragment, bool overwrite, size_t timeout_us)
24 {
25  if (!IsValid()) { return -1; }
26 
27  auto waitStart = std::chrono::steady_clock::now();
28  while (!ReadyForWrite(overwrite) && TimeUtils::GetElapsedTimeMicroseconds(waitStart) < 1000)
29  {
30  // BURN THAT CPU!
31  }
32  if (!ReadyForWrite(overwrite))
33  {
34  int64_t loopCount = 0;
35  size_t sleepTime = 1000; // microseconds
36  int64_t nloops = (timeout_us - 1000) / sleepTime;
37 
38  while (!ReadyForWrite(overwrite) && (!overwrite || timeout_us == 0 || loopCount < nloops))
39  {
40  usleep(sleepTime);
41  ++loopCount;
42  }
43  }
44  if (!ReadyForWrite(overwrite))
45  {
46  TLOG(TLVL_WARNING) << "No available buffers after waiting for " << TimeUtils::GetElapsedTimeMicroseconds(waitStart) << " us.";
47  return -3;
48  }
49 
50  TLOG(13) << "Sending fragment with seqID=" << fragment.sequenceID() << " using buffer " << active_buffer_;
51  artdaq::RawDataType* fragAddr = fragment.headerAddress();
52  size_t fragSize = fragment.size() * sizeof(artdaq::RawDataType);
53 
54  auto sts = Write(active_buffer_, fragAddr, fragSize);
55  if (sts == fragSize)
56  {
57  TLOG(13) << "Done sending Fragment with seqID=" << fragment.sequenceID() << " using buffer " << active_buffer_;
58  MarkBufferFull(active_buffer_);
59  active_buffer_ = -1;
60  return 0;
61  }
62  active_buffer_ = -1;
63  TLOG(TLVL_ERROR) << "Unexpected status from SharedMemory Write call!";
64  return -2;
65 }
66 
67 
68 // NOT currently (2018-07-22) used! ReadFragmentHeader and ReadFragmentData
69 // (below) are called directly
71 {
72  TLOG(14) << "ReadFragment BEGIN";
74 
75  TLOG(14) << "Reading Fragment Header";
76  auto sts = ReadFragmentHeader(tmpHdr);
77  if (sts != 0) return sts;
78  fragment.resize(tmpHdr.word_count - tmpHdr.num_words());
79  memcpy(fragment.headerAddress(), &tmpHdr, tmpHdr.num_words() * sizeof(artdaq::RawDataType));
80  TLOG(14) << "Reading Fragment Body - of frag w/ seqID="<<tmpHdr.sequence_id;
81  return ReadFragmentData(fragment.headerAddress() + tmpHdr.num_words(), tmpHdr.word_count - tmpHdr.num_words());
82 }
83 
85 {
86  if (!IsValid()) {
87  TLOG(22) << "ReadFragmentHeader: !IsValid(), returning -3";
88  return -3;
89  }
90 
92  active_buffer_ = GetBufferForReading();
93 
94  if (active_buffer_ == -1) {
95  TLOG(22) << "ReadFragmentHeader: active_buffer==-1, returning -1";
96  return -1;
97  }
98 
99  auto sts = Read(active_buffer_, &header, hdrSize);
100  if (!sts) {
101  TLOG(TLVL_ERROR) << "ReadFragmentHeader: Buffer " << active_buffer_ << " returned bad status code from Read";
102  MarkBufferEmpty(active_buffer_);
103  active_buffer_ = -1;
104  return -2;
105  }
106 
107  TLOG(22) << "ReadFragmentHeader: read active_buffer_="<<active_buffer_<<" sequence_id="<<header.sequence_id;
108  return 0;
109 }
110 
112 {
113  if (!IsValid() || active_buffer_ == -1 || !CheckBuffer(active_buffer_, BufferSemaphoreFlags::Reading)) {
114  TLOG(TLVL_ERROR) << "ReadFragmentData: Buffer " << active_buffer_ << " failed status checks: IsValid()=" << std::boolalpha << IsValid() << ", CheckBuffer=" << CheckBuffer(active_buffer_, BufferSemaphoreFlags::Reading);
115  return -3;
116  }
117 
118  auto sts = Read(active_buffer_, destination, words * sizeof(RawDataType));
119  if (!sts) {
120  TLOG(TLVL_ERROR) << "ReadFragmentData: Buffer " << active_buffer_ << " returned bad status code from Read";
121  MarkBufferEmpty(active_buffer_);
122  active_buffer_ = -1;
123  return -2;
124  }
125 
126  MarkBufferEmpty(active_buffer_);
127  active_buffer_ = -1;
128  return 0;
129 }
RawDataType word_count
number of RawDataType words in this Fragment
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 sequence_id
The 48-bit sequence_id uniquely identifies events within the artdaq system.
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:43
void resize(std::size_t sz)
Resize the data payload to hold sz RawDataType words.
Definition: Fragment.hh:984
SharedMemoryFragmentManager(uint32_t shm_key, size_t buffer_count, size_t max_buffer_size, size_t buffer_timeout_us=100 *1000000)
SharedMemoryFragmentManager Constructor.
The SharedMemoryManager creates a Shared Memory area which is divided into a number of fixed-size buf...
int WriteFragment(Fragment &&fragment, bool overwrite, size_t timeout_us)
Write a Fragment to the Shared Memory.
detail::RawFragmentHeader::RawDataType RawDataType
The RawDataType (currently a 64-bit integer) is the basic unit of data representation within artdaq ...
Definition: Fragment.hh:39
int ReadFragmentHeader(detail::RawFragmentHeader &header)
Read a Fragment Header from the Shared Memory.
int ReadFragment(Fragment &fragment)
Read a Fragment from the Shared Memory.
bool ReadyForWrite(bool overwrite) override
Check if a buffer is ready for writing, and if so, reserves it for use.
A Fragment contains the data from one piece of the DAQ system for one event The artdaq::Fragment is t...
Definition: Fragment.hh:84
int ReadFragmentData(RawDataType *destination, size_t words)
Read Fragment Data from the Shared Memory.
RawDataType * headerAddress()
Gets the address of the header.
Definition: Fragment.hh:1141