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
00031 }
00032 if (!ReadyForWrite(overwrite))
00033 {
00034 int64_t loopCount = 0;
00035 size_t sleepTime = 1000;
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 int artdaq::SharedMemoryFragmentManager::ReadFragment(Fragment& fragment)
00068 {
00069 TLOG(14) << "ReadFragment BEGIN";
00070 detail::RawFragmentHeader tmpHdr;
00071
00072 TLOG(14) << "Reading Fragment Header";
00073 auto sts = ReadFragmentHeader(tmpHdr);
00074 if (sts != 0) return sts;
00075 fragment.resize(tmpHdr.word_count - tmpHdr.num_words());
00076 memcpy(fragment.headerAddress(), &tmpHdr, tmpHdr.num_words() * sizeof(artdaq::RawDataType));
00077 TLOG(14) << "Reading Fragment Body";
00078 return ReadFragmentData(fragment.headerAddress() + tmpHdr.num_words(), tmpHdr.word_count - tmpHdr.num_words());
00079 }
00080
00081 int artdaq::SharedMemoryFragmentManager::ReadFragmentHeader(detail::RawFragmentHeader& header)
00082 {
00083 if (!IsValid()) return -3;
00084
00085 size_t hdrSize = artdaq::detail::RawFragmentHeader::num_words() * sizeof(artdaq::RawDataType);
00086 active_buffer_ = GetBufferForReading();
00087
00088 if (active_buffer_ == -1) return -1;
00089
00090 auto sts = Read(active_buffer_, &header, hdrSize);
00091 if (!sts) {
00092 TLOG(TLVL_ERROR) << "ReadFragmentData: Buffer " << active_buffer_ << " returned bad status code from Read";
00093 MarkBufferEmpty(active_buffer_);
00094 active_buffer_ = -1;
00095 return -2;
00096 }
00097
00098 return 0;
00099 }
00100
00101 int artdaq::SharedMemoryFragmentManager::ReadFragmentData(RawDataType* destination, size_t words)
00102 {
00103 if (!IsValid() || active_buffer_ == -1 || !CheckBuffer(active_buffer_, BufferSemaphoreFlags::Reading)) {
00104 TLOG(TLVL_ERROR) << "ReadFragmentData: Buffer " << active_buffer_ << " failed status checks: IsValid()=" << std::boolalpha << IsValid() << ", CheckBuffer=" << CheckBuffer(active_buffer_, BufferSemaphoreFlags::Reading);
00105 return -3;
00106 }
00107
00108 auto sts = Read(active_buffer_, destination, words * sizeof(RawDataType));
00109 if (!sts) {
00110 TLOG(TLVL_ERROR) << "ReadFragmentData: Buffer " << active_buffer_ << " returned bad status code from Read";
00111 MarkBufferEmpty(active_buffer_);
00112 active_buffer_ = -1;
00113 return -2;
00114 }
00115
00116 MarkBufferEmpty(active_buffer_);
00117 active_buffer_ = -1;
00118 return 0;
00119 }