$treeview $search $mathjax $extrastylesheet
artdaq_core
v3_06_01
$projectbrief
|
$projectbrief
|
$searchbox |
00001 00002 #define TRACE_NAME "SharedMemoryFragmentManager" 00003 #include "artdaq-core/Core/SharedMemoryFragmentManager.hh" 00004 #include "tracemf.h" 00005 00006 artdaq::SharedMemoryFragmentManager::SharedMemoryFragmentManager(uint32_t shm_key, size_t buffer_count, size_t max_buffer_size, size_t buffer_timeout_us) 00007 : SharedMemoryManager(shm_key, buffer_count, max_buffer_size, buffer_timeout_us) 00008 , active_buffer_(-1) 00009 { 00010 } 00011 00012 bool artdaq::SharedMemoryFragmentManager::ReadyForWrite(bool overwrite) 00013 { 00014 TLOG(12) << "ReadyForWrite: active_buffer is " << active_buffer_; 00015 if (active_buffer_ != -1) 00016 { 00017 return true; 00018 } 00019 active_buffer_ = GetBufferForWriting(overwrite); 00020 00021 return active_buffer_ != -1; 00022 } 00023 00024 int artdaq::SharedMemoryFragmentManager::WriteFragment(Fragment&& fragment, bool overwrite, size_t timeout_us) 00025 { 00026 if (!IsValid() || IsEndOfData()) 00027 { 00028 TLOG(TLVL_WARNING) << "WriteFragment: Shared memory is not connected! Attempting reconnect..."; 00029 auto sts = Attach(timeout_us); 00030 if (!sts) 00031 { 00032 return -1; 00033 } 00034 TLOG(TLVL_INFO) << "WriteFragment: Shared memory was successfully reconnected"; 00035 } 00036 00037 auto waitStart = std::chrono::steady_clock::now(); 00038 while (!ReadyForWrite(overwrite) && TimeUtils::GetElapsedTimeMicroseconds(waitStart) < 1000) 00039 { 00040 // BURN THAT CPU! 00041 } 00042 if (!ReadyForWrite(overwrite)) 00043 { 00044 int64_t loopCount = 0; 00045 size_t sleepTime = 1000; // microseconds 00046 int64_t nloops = (timeout_us - 1000) / sleepTime; 00047 00048 while (!ReadyForWrite(overwrite) && (!overwrite || timeout_us == 0 || loopCount < nloops)) 00049 { 00050 if (!IsValid() || IsEndOfData()) 00051 { 00052 TLOG(TLVL_WARNING) << "WriteFragment: Shared memory is not connected! Attempting reconnect..."; 00053 auto sts = Attach(timeout_us); 00054 if (!sts) 00055 { 00056 return -1; 00057 } 00058 TLOG(TLVL_INFO) << "WriteFragment: Shared memory was successfully reconnected"; 00059 } 00060 usleep(sleepTime); 00061 ++loopCount; 00062 } 00063 } 00064 if (!ReadyForWrite(overwrite)) 00065 { 00066 TLOG(TLVL_WARNING) << "No available buffers after waiting for " << TimeUtils::GetElapsedTimeMicroseconds(waitStart) << " us."; 00067 return -3; 00068 } 00069 00070 TLOG(13) << "Sending fragment with seqID=" << fragment.sequenceID() << " using buffer " << active_buffer_; 00071 artdaq::RawDataType* fragAddr = fragment.headerAddress(); 00072 size_t fragSize = fragment.size() * sizeof(artdaq::RawDataType); 00073 00074 auto sts = Write(active_buffer_, fragAddr, fragSize); 00075 if (sts == fragSize) 00076 { 00077 TLOG(13) << "Done sending Fragment with seqID=" << fragment.sequenceID() << " using buffer " << active_buffer_; 00078 MarkBufferFull(active_buffer_); 00079 active_buffer_ = -1; 00080 return 0; 00081 } 00082 active_buffer_ = -1; 00083 TLOG(TLVL_ERROR) << "Unexpected status from SharedMemory Write call!"; 00084 return -2; 00085 } 00086 00087 // NOT currently (2018-07-22) used! ReadFragmentHeader and ReadFragmentData 00088 // (below) are called directly 00089 int artdaq::SharedMemoryFragmentManager::ReadFragment(Fragment& fragment) 00090 { 00091 TLOG(14) << "ReadFragment BEGIN"; 00092 detail::RawFragmentHeader tmpHdr; 00093 00094 TLOG(14) << "Reading Fragment Header"; 00095 auto sts = ReadFragmentHeader(tmpHdr); 00096 if (sts != 0) 00097 { 00098 return sts; 00099 } 00100 fragment.resize(tmpHdr.word_count - tmpHdr.num_words()); 00101 memcpy(fragment.headerAddress(), &tmpHdr, tmpHdr.num_words() * sizeof(artdaq::RawDataType)); 00102 TLOG(14) << "Reading Fragment Body - of frag w/ seqID=" << tmpHdr.sequence_id; 00103 return ReadFragmentData(fragment.headerAddress() + tmpHdr.num_words(), tmpHdr.word_count - tmpHdr.num_words()); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 00104 } 00105 00106 int artdaq::SharedMemoryFragmentManager::ReadFragmentHeader(detail::RawFragmentHeader& header) 00107 { 00108 if (!IsValid()) 00109 { 00110 TLOG(22) << "ReadFragmentHeader: !IsValid(), returning -3"; 00111 return -3; 00112 } 00113 00114 size_t hdrSize = artdaq::detail::RawFragmentHeader::num_words() * sizeof(artdaq::RawDataType); 00115 active_buffer_ = GetBufferForReading(); 00116 00117 if (active_buffer_ == -1) 00118 { 00119 TLOG(22) << "ReadFragmentHeader: active_buffer==-1, returning -1"; 00120 return -1; 00121 } 00122 00123 auto sts = Read(active_buffer_, &header, hdrSize); 00124 if (!sts) 00125 { 00126 TLOG(TLVL_ERROR) << "ReadFragmentHeader: Buffer " << active_buffer_ << " returned bad status code from Read"; 00127 MarkBufferEmpty(active_buffer_); 00128 active_buffer_ = -1; 00129 return -2; 00130 } 00131 00132 TLOG(22) << "ReadFragmentHeader: read active_buffer_=" << active_buffer_ << " sequence_id=" << header.sequence_id; 00133 return 0; 00134 } 00135 00136 int artdaq::SharedMemoryFragmentManager::ReadFragmentData(RawDataType* destination, size_t words) 00137 { 00138 if (!IsValid() || active_buffer_ == -1 || !CheckBuffer(active_buffer_, BufferSemaphoreFlags::Reading)) 00139 { 00140 TLOG(TLVL_ERROR) << "ReadFragmentData: Buffer " << active_buffer_ << " failed status checks: IsValid()=" << std::boolalpha << IsValid() << ", CheckBuffer=" << CheckBuffer(active_buffer_, BufferSemaphoreFlags::Reading); 00141 return -3; 00142 } 00143 00144 auto sts = Read(active_buffer_, destination, words * sizeof(RawDataType)); 00145 if (!sts) 00146 { 00147 TLOG(TLVL_ERROR) << "ReadFragmentData: Buffer " << active_buffer_ << " returned bad status code from Read"; 00148 MarkBufferEmpty(active_buffer_); 00149 active_buffer_ = -1; 00150 return -2; 00151 } 00152 00153 MarkBufferEmpty(active_buffer_); 00154 active_buffer_ = -1; 00155 return 0; 00156 }