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