$treeview $search $mathjax $extrastylesheet
artdaq_core
v3_04_20a
$projectbrief
|
$projectbrief
|
$searchbox |
00001 00002 #include "artdaq-core/Core/SharedMemoryEventReceiver.hh" 00003 00004 #include "artdaq-core/Data/Fragment.hh" 00005 #include <sys/time.h> 00006 #define TRACE_NAME "SharedMemoryEventReceiver" 00007 #include "tracemf.h" 00008 00009 using std::string; 00010 00011 artdaq::SharedMemoryEventReceiver::SharedMemoryEventReceiver(uint32_t shm_key, uint32_t broadcast_shm_key) 00012 : current_read_buffer_(-1) 00013 , initialized_(false) 00014 , current_header_(nullptr) 00015 , current_data_source_(nullptr) 00016 , data_(shm_key) 00017 , broadcasts_(broadcast_shm_key) 00018 { 00019 TLOG(TLVL_TRACE) << "SharedMemoryEventReceiver CONSTRUCTOR" ; 00020 } 00021 00022 bool artdaq::SharedMemoryEventReceiver::ReadyForRead(bool broadcast, size_t timeout_us) 00023 { 00024 TLOG(TLVL_TRACE) << "ReadyForRead BEGIN timeout_us=" << timeout_us ; 00025 if (current_read_buffer_ != -1 && current_data_source_ && current_header_) 00026 { 00027 TLOG(TLVL_TRACE) << "ReadyForRead Returning true because already reading buffer" ; 00028 return true; 00029 } 00030 00031 bool first = true; 00032 auto start_time = TimeUtils::gettimeofday_us(); 00033 uint64_t time_diff = 0; 00034 int buf = -1; 00035 while (first || time_diff < timeout_us) 00036 { 00037 if (broadcasts_.ReadyForRead()) 00038 { 00039 buf = broadcasts_.GetBufferForReading(); 00040 current_data_source_ = &broadcasts_; 00041 } 00042 else if (!broadcast && data_.ReadyForRead()) 00043 { 00044 buf = data_.GetBufferForReading(); 00045 current_data_source_ = &data_; 00046 } 00047 if (buf != -1 && current_data_source_) 00048 { 00049 current_read_buffer_ = buf; 00050 current_data_source_->ResetReadPos(buf); 00051 current_header_ = reinterpret_cast<detail::RawEventHeader*>(current_data_source_->GetReadPos(buf)); 00052 TLOG(TLVL_TRACE) << "ReadyForRead Found buffer, returning true. event hdr sequence_id=" << current_header_->sequence_id; 00053 00054 // Ignore any Init fragments after the first 00055 if (current_data_source_ == &broadcasts_) 00056 { 00057 bool err; 00058 auto types = GetFragmentTypes(err); 00059 if (!err && types.count(Fragment::type_t(Fragment::InitFragmentType)) && initialized_) 00060 { 00061 ReleaseBuffer(); 00062 continue; 00063 } 00064 else if (!err && types.count(Fragment::type_t(Fragment::InitFragmentType))) 00065 { 00066 initialized_ = true; 00067 } 00068 } 00069 00070 return true; 00071 } 00072 current_data_source_ = nullptr; 00073 first = false; 00074 00075 time_diff = TimeUtils::gettimeofday_us() - start_time; 00076 usleep(time_diff < 10000 ? time_diff : 10000 ); 00077 } 00078 TLOG(TLVL_TRACE) << "ReadyForRead returning false" ; 00079 return false; 00080 } 00081 00082 artdaq::detail::RawEventHeader* artdaq::SharedMemoryEventReceiver::ReadHeader(bool& err) 00083 { 00084 TLOG(TLVL_TRACE) << "ReadHeader BEGIN" ; 00085 if (current_read_buffer_ != -1 && current_data_source_) 00086 { 00087 err = !current_data_source_->CheckBuffer(current_read_buffer_, SharedMemoryManager::BufferSemaphoreFlags::Reading); 00088 if (err) 00089 { 00090 TLOG(TLVL_WARNING) << "Buffer was in incorrect state, resetting" ; 00091 current_data_source_ = nullptr; 00092 current_read_buffer_ = -1; 00093 current_header_ = nullptr; 00094 return nullptr; 00095 } 00096 } 00097 TLOG(TLVL_TRACE) << "Already have buffer, returning stored header" ; 00098 return current_header_; 00099 } 00100 00101 std::set<artdaq::Fragment::type_t> artdaq::SharedMemoryEventReceiver::GetFragmentTypes(bool& err) 00102 { 00103 if (current_read_buffer_ == -1 || !current_header_ || !current_data_source_) throw cet::exception("AccessViolation") << "Cannot call GetFragmentTypes when not currently reading a buffer! Call ReadHeader() first!"; 00104 00105 err = !current_data_source_->CheckBuffer(current_read_buffer_, SharedMemoryManager::BufferSemaphoreFlags::Reading); 00106 if (err) return std::set<Fragment::type_t>(); 00107 00108 current_data_source_->ResetReadPos(current_read_buffer_); 00109 current_data_source_->IncrementReadPos(current_read_buffer_, sizeof(detail::RawEventHeader)); 00110 auto output = std::set<Fragment::type_t>(); 00111 00112 while (current_data_source_->MoreDataInBuffer(current_read_buffer_)) 00113 { 00114 err = !current_data_source_->CheckBuffer(current_read_buffer_, SharedMemoryManager::BufferSemaphoreFlags::Reading); 00115 if (err) return std::set<Fragment::type_t>(); 00116 auto fragHdr = reinterpret_cast<artdaq::detail::RawFragmentHeader*>(current_data_source_->GetReadPos(current_read_buffer_)); 00117 output.insert(fragHdr->type); 00118 current_data_source_->IncrementReadPos(current_read_buffer_, fragHdr->word_count * sizeof(RawDataType)); 00119 } 00120 00121 return output; 00122 } 00123 00124 00125 std::unique_ptr<artdaq::Fragments> artdaq::SharedMemoryEventReceiver::GetFragmentsByType(bool& err, Fragment::type_t type) 00126 { 00127 if (!current_data_source_ || !current_header_ || current_read_buffer_ == -1) throw cet::exception("AccessViolation") << "Cannot call GetFragmentsByType when not currently reading a buffer! Call ReadHeader() first!"; 00128 err = !current_data_source_->CheckBuffer(current_read_buffer_, SharedMemoryManager::BufferSemaphoreFlags::Reading); 00129 if (err) return nullptr; 00130 00131 current_data_source_->ResetReadPos(current_read_buffer_); 00132 current_data_source_->IncrementReadPos(current_read_buffer_, sizeof(detail::RawEventHeader)); 00133 00134 std::unique_ptr<Fragments> output(new Fragments()); 00135 00136 while (current_data_source_->MoreDataInBuffer(current_read_buffer_)) 00137 { 00138 err = !current_data_source_->CheckBuffer(current_read_buffer_, SharedMemoryManager::BufferSemaphoreFlags::Reading); 00139 if (err) return nullptr; 00140 auto fragHdr = reinterpret_cast<artdaq::detail::RawFragmentHeader*>(current_data_source_->GetReadPos(current_read_buffer_)); 00141 if (fragHdr->type == type || type == Fragment::InvalidFragmentType) 00142 { 00143 output->emplace_back(fragHdr->word_count - detail::RawFragmentHeader::num_words()); 00144 current_data_source_->Read(current_read_buffer_, output->back().headerAddress(), fragHdr->word_count * sizeof(RawDataType)); 00145 output->back().autoResize(); 00146 } 00147 else 00148 { 00149 current_data_source_->IncrementReadPos(current_read_buffer_, fragHdr->word_count * sizeof(RawDataType)); 00150 } 00151 } 00152 00153 return output; 00154 } 00155 00156 std::string artdaq::SharedMemoryEventReceiver::printBuffers_(SharedMemoryManager* data_source) 00157 { 00158 std::ostringstream ostr; 00159 for (size_t ii = 0; ii < data_source->size(); ++ii) 00160 { 00161 ostr << "Buffer " << ii << ": " << std::endl; 00162 00163 data_source->ResetReadPos(ii); 00164 data_source->IncrementReadPos(ii, sizeof(detail::RawEventHeader)); 00165 00166 while (data_source->MoreDataInBuffer(ii)) 00167 { 00168 auto fragHdr = reinterpret_cast<artdaq::detail::RawFragmentHeader*>(data_source->GetReadPos(ii)); 00169 ostr << " Fragment " << fragHdr->fragment_id << ": Sequence ID: " << fragHdr->sequence_id << ", Type:" << fragHdr->type; 00170 if (fragHdr->MakeVerboseSystemTypeMap().count(fragHdr->type)) 00171 { 00172 ostr << " (" << fragHdr->MakeVerboseSystemTypeMap()[fragHdr->type] << ")"; 00173 } 00174 ostr << ", Size: " << fragHdr->word_count << " words." << std::endl; 00175 data_source->IncrementReadPos(ii, fragHdr->word_count * sizeof(RawDataType)); 00176 } 00177 00178 } 00179 return ostr.str(); 00180 } 00181 00182 std::string artdaq::SharedMemoryEventReceiver::toString() 00183 { 00184 std::ostringstream ostr; 00185 ostr << data_.toString() << std::endl; 00186 00187 ostr << "Data Buffer Fragment Counts: " << std::endl; 00188 ostr << printBuffers_(&data_); 00189 00190 if (data_.GetKey() != broadcasts_.GetKey()) 00191 { 00192 ostr << "Broadcast Buffer Fragment Counts: " << std::endl; 00193 ostr << printBuffers_(&broadcasts_); 00194 } 00195 00196 return ostr.str(); 00197 } 00198 00199 void artdaq::SharedMemoryEventReceiver::ReleaseBuffer() 00200 { 00201 TLOG(TLVL_TRACE) << "ReleaseBuffer BEGIN" ; 00202 try 00203 { 00204 if(current_data_source_) current_data_source_->MarkBufferEmpty(current_read_buffer_); 00205 } 00206 catch (cet::exception const& e) 00207 { 00208 TLOG(TLVL_WARNING) << "A cet::exception occured while trying to release the buffer: " << e ; 00209 } 00210 catch (...) 00211 { 00212 TLOG(TLVL_ERROR) << "An unknown exception occured while trying to release the buffer" ; 00213 } 00214 current_read_buffer_ = -1; 00215 current_header_ = nullptr; 00216 current_data_source_ = nullptr; 00217 TLOG(TLVL_TRACE) << "ReleaseBuffer END" ; 00218 }