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