00001 #ifndef artdaq_ArtModules_detail_SharedMemoryReader_hh
00002 #define artdaq_ArtModules_detail_SharedMemoryReader_hh
00003
00004 #include "artdaq/DAQdata/Globals.hh"
00005 #include "art/Framework/Core/Frameworkfwd.h"
00006
00007 #include "art/Framework/Core/FileBlock.h"
00008 #include "art/Framework/Core/ProductRegistryHelper.h"
00009 #include "art/Framework/IO/Sources/SourceHelper.h"
00010 #include "art/Framework/Principal/EventPrincipal.h"
00011 #include "art/Framework/Principal/RunPrincipal.h"
00012 #include "art/Framework/Principal/SubRunPrincipal.h"
00013 #include "artdaq-core/Core/SharedMemoryManager.hh"
00014 #include "artdaq-core/Utilities/TimeUtils.hh"
00015 #include "fhiclcpp/ParameterSet.h"
00016 #include "artdaq-core/Data/Fragment.hh"
00017 #include "artdaq-core/Data/ContainerFragment.hh"
00018 #include "artdaq-core/Core/SharedMemoryEventReceiver.hh"
00019 #include "art/Framework/IO/Sources/put_product_in_principal.h"
00020 #include "canvas/Persistency/Provenance/FileFormatVersion.h"
00021 #include <sys/time.h>
00022
00023
00024 #include <string>
00025 #include <map>
00026 #include "artdaq-core/Data/RawEvent.hh"
00027
00028 namespace artdaq
00029 {
00030 namespace detail
00031 {
00035 template<std::map<artdaq::Fragment::type_t, std::string> getDefaultTypes() = artdaq::Fragment::MakeSystemTypeMap >
00036 struct SharedMemoryReader
00037 {
00041 SharedMemoryReader(SharedMemoryReader const&) = delete;
00042
00047 SharedMemoryReader& operator=(SharedMemoryReader const&) = delete;
00048
00049 art::SourceHelper const& pmaker;
00050 std::unique_ptr<SharedMemoryEventReceiver> incoming_events;
00051 double waiting_time;
00052 bool resume_after_timeout;
00053 std::string pretend_module_name;
00054 std::string unidentified_instance_name;
00055 bool shutdownMsgReceived;
00056 bool outputFileCloseNeeded;
00057 size_t bytesRead;
00058
00059
00060
00075 SharedMemoryReader(fhicl::ParameterSet const& ps,
00076 art::ProductRegistryHelper& help,
00077 art::SourceHelper const& pm)
00078 : pmaker(pm)
00079 , waiting_time(ps.get<double>("waiting_time", 86400.0))
00080 , resume_after_timeout(ps.get<bool>("resume_after_timeout", true))
00081 , pretend_module_name(ps.get<std::string>("raw_data_label", "daq"))
00082 , unidentified_instance_name("unidentified")
00083 , shutdownMsgReceived(false)
00084 , outputFileCloseNeeded(false)
00085 , bytesRead(0)
00086 , fragment_type_map_(getDefaultTypes())
00087 , readNext_calls_(0)
00088 {
00089
00090
00091
00092
00093
00094
00095 incoming_events.reset(new SharedMemoryEventReceiver(ps.get<uint32_t>("shared_memory_key", 0xBEE70000 + getppid()), ps.get<uint32_t>("broadcast_shared_memory_key", 0xCEE70000 + getppid())));
00096
00097 help.reconstitutes<Fragments, art::InEvent>(pretend_module_name, unidentified_instance_name);
00098 for (auto it = fragment_type_map_.begin(); it != fragment_type_map_.end(); ++it)
00099 {
00100 help.reconstitutes<Fragments, art::InEvent>(pretend_module_name, it->second);
00101 help.reconstitutes<Fragments, art::InEvent>(pretend_module_name, "Container" + it->second);
00102 }
00103 auto extraTypes = ps.get<std::vector<std::pair<Fragment::type_t, std::string>>>("fragment_type_map", std::vector<std::pair<Fragment::type_t, std::string>>());
00104 for (auto it = extraTypes.begin(); it != extraTypes.end(); ++it)
00105 {
00106 fragment_type_map_[it->first] = it->second;
00107 help.reconstitutes<Fragments, art::InEvent>(pretend_module_name, it->second);
00108 help.reconstitutes<Fragments, art::InEvent>(pretend_module_name, "Container" + it->second);
00109 }
00110 TLOG_INFO("SharedMemoryReader") << "SharedMemoryReader initialized with ParameterSet: " << ps.to_string() ;
00111
00112
00113
00114
00115 }
00116
00125 SharedMemoryReader(fhicl::ParameterSet const& ps,
00126 art::ProductRegistryHelper& help,
00127 art::SourceHelper const& pm,
00128 art::MasterProductRegistry&) : SharedMemoryReader(ps, help, pm)
00129 {}
00130
00134 virtual ~SharedMemoryReader() = default;
00135
00139 void closeCurrentFile() {}
00140
00145 void readFile(std::string const&, art::FileBlock*& fb)
00146 {
00147 TLOG_ARB(5, "SharedMemoryReader") <<"readFile enter/start";
00148 fb = new art::FileBlock(art::FileFormatVersion(1, "RawEvent2011"), "nothing");
00149 }
00150
00155 bool hasMoreData() const { return (!shutdownMsgReceived); }
00156
00167 bool readNext(art::RunPrincipal* const & inR,
00168 art::SubRunPrincipal* const & inSR,
00169 art::RunPrincipal*& outR,
00170 art::SubRunPrincipal*& outSR,
00171 art::EventPrincipal*& outE)
00172 {
00173 TLOG_DEBUG("SharedMemoryReader") << "readNext BEGIN" ;
00174
00175
00176
00177
00178
00179 outR = 0;
00180 outSR = 0;
00181 outE = 0;
00182
00183
00184
00185
00186
00187
00188 if (shutdownMsgReceived) return false;
00189
00190 start:
00191 bool keep_looping = true;
00192 bool got_event = false;
00193 auto sleepTimeUsec = waiting_time * 1000;
00194 if (sleepTimeUsec > 100000) sleepTimeUsec = 100000;
00195 while (keep_looping)
00196 {
00197 keep_looping = false;
00198 auto start_time = std::chrono::steady_clock::now();
00199 while (!got_event && TimeUtils::GetElapsedTimeMicroseconds(start_time) < 1000)
00200 {
00201
00202 got_event = incoming_events->ReadyForRead();
00203 }
00204 while (!got_event && TimeUtils::GetElapsedTime(start_time) < waiting_time)
00205 {
00206 got_event = incoming_events->ReadyForRead();
00207 if (!got_event)
00208 {
00209 usleep(sleepTimeUsec);
00210
00211 }
00212 }
00213 if (!got_event)
00214 {
00215 TLOG_INFO("SharedMemoryReader")
00216 << "InputFailure: Reading timed out in SharedMemoryReader::readNext()" ;
00217 keep_looping = resume_after_timeout;
00218 }
00219 }
00220
00221 if (!got_event)
00222 {
00223 TLOG_INFO("SharedMemoryReader") << "Did not receive an event from Shared Memory, returning false" ;
00224 shutdownMsgReceived = true;
00225 return false;
00226 }
00227 TLOG_DEBUG("SharedMemoryReader") << "Got Event!" ;
00228
00229 auto errflag = false;
00230 auto evtHeader = incoming_events->ReadHeader(errflag);
00231 if (errflag) goto start;
00232 auto fragmentTypes = incoming_events->GetFragmentTypes(errflag);
00233 if (errflag) goto start;
00234 if (fragmentTypes.size() == 0)
00235 {
00236 TLOG_ERROR("SharedMemoryReader") << "Event has no Fragments! Aborting!" ;
00237 incoming_events->ReleaseBuffer();
00238 return false;
00239 }
00240 auto firstFragmentType = *fragmentTypes.begin();
00241 TLOG_DEBUG("SharedMemoryReader") << "First Fragment type is " << (int)firstFragmentType << " (" << fragment_type_map_[firstFragmentType] << ")" ;
00242
00243
00244
00245
00246
00247
00248 if (firstFragmentType == Fragment::EndOfDataFragmentType)
00249 {
00250 TLOG_DEBUG("SharedMemoryReader") << "Received shutdown message, returning false" ;
00251 shutdownMsgReceived = true;
00252 incoming_events->ReleaseBuffer();
00253 return false;
00254 }
00255
00256 size_t qsize = incoming_events->ReadReadyCount();
00257
00258
00259
00260
00261 art::Timestamp currentTime = time(0);
00262
00263
00264 if (inR == 0 || inR->run() != evtHeader->run_id)
00265 {
00266 outR = pmaker.makeRunPrincipal(evtHeader->run_id,
00267 currentTime);
00268 }
00269
00270 if (firstFragmentType == Fragment::EndOfRunFragmentType)
00271 {
00272 art::EventID const evid(art::EventID::flushEvent());
00273 outR = pmaker.makeRunPrincipal(evid.runID(), currentTime);
00274 outSR = pmaker.makeSubRunPrincipal(evid.subRunID(), currentTime);
00275 outE = pmaker.makeEventPrincipal(evid, currentTime);
00276 incoming_events->ReleaseBuffer();
00277 return true;
00278 }
00279 else if (firstFragmentType == Fragment::EndOfSubrunFragmentType)
00280 {
00281
00282 if (inR == 0 || inR->run() != evtHeader->run_id)
00283 {
00284 outSR = pmaker.makeSubRunPrincipal(evtHeader->run_id,
00285 evtHeader->subrun_id,
00286 currentTime);
00287 art::EventID const evid(art::EventID::flushEvent(outSR->id()));
00288 outE = pmaker.makeEventPrincipal(evid, currentTime);
00289 }
00290 else
00291 {
00292
00293
00294
00295
00296 if (inSR != 0 && !inSR->id().isFlush() && inSR->subRun() == evtHeader->subrun_id)
00297 {
00298 art::EventID const evid(art::EventID::flushEvent(inR->id()));
00299 outSR = pmaker.makeSubRunPrincipal(evid.subRunID(), currentTime);
00300 outE = pmaker.makeEventPrincipal(evid, currentTime);
00301
00302
00303
00304 }
00305 else
00306 {
00307 outSR = pmaker.makeSubRunPrincipal(evtHeader->run_id,
00308 evtHeader->subrun_id,
00309 currentTime);
00310 art::EventID const evid(art::EventID::flushEvent(outSR->id()));
00311 outE = pmaker.makeEventPrincipal(evid, currentTime);
00312
00313
00314 }
00315 outR = 0;
00316 }
00317
00318 incoming_events->ReleaseBuffer();
00319 return true;
00320 }
00321
00322
00323 art::SubRunID subrun_check(evtHeader->run_id, evtHeader->subrun_id);
00324 if (inSR == 0 || subrun_check != inSR->id())
00325 {
00326 outSR = pmaker.makeSubRunPrincipal(evtHeader->run_id,
00327 evtHeader->subrun_id,
00328 currentTime);
00329 }
00330 outE = pmaker.makeEventPrincipal(evtHeader->run_id,
00331 evtHeader->subrun_id,
00332 evtHeader->event_id,
00333 currentTime);
00334
00335
00336 std::map<Fragment::type_t, std::string>::const_iterator iter_end =
00337 fragment_type_map_.end();
00338 for (auto& type_code : fragmentTypes)
00339 {
00340 std::map<Fragment::type_t, std::string>::const_iterator iter =
00341 fragment_type_map_.find(type_code);
00342 auto product = incoming_events->GetFragmentsByType(errflag, type_code);
00343 if (errflag) goto start;
00344 for (auto &frag : *product)
00345 bytesRead += frag.sizeBytes();
00346 if (iter != iter_end)
00347 {
00348 if (type_code == artdaq::Fragment::ContainerFragmentType)
00349 {
00350 std::unordered_map<std::string, std::unique_ptr<Fragments>> derived_fragments;
00351 derived_fragments[iter->second] = std::make_unique<Fragments>();
00352
00353 for (size_t ii = 0; ii < product->size(); ++ii)
00354 {
00355 ContainerFragment cf(product->at(ii));
00356 auto contained_type = fragment_type_map_.find(cf.fragment_type());
00357 if (contained_type != iter_end)
00358 {
00359 auto label = iter->second + contained_type->second;
00360 if (!derived_fragments.count(label))
00361 {
00362 derived_fragments[label] = std::make_unique<Fragments>();
00363 }
00364 derived_fragments[label]->emplace_back(std::move(product->at(ii)));
00365 }
00366 else
00367 {
00368 derived_fragments[iter->second]->emplace_back(std::move(product->at(ii)));
00369 }
00370 }
00371
00372 for (auto& type : derived_fragments)
00373 {
00374 put_product_in_principal(std::move(type.second),
00375 *outE,
00376 pretend_module_name,
00377 type.first);
00378 }
00379
00380 }
00381 else
00382 {
00383 put_product_in_principal(std::move(product),
00384 *outE,
00385 pretend_module_name,
00386 iter->second);
00387 }
00388 }
00389 else
00390 {
00391 put_product_in_principal(std::move(product),
00392 *outE,
00393 pretend_module_name,
00394 unidentified_instance_name);
00395 TLOG_WARNING("SharedMemoryReader")
00396 << "UnknownFragmentType: The product instance name mapping for fragment type \""
00397 << ((int)type_code) << "\" is not known. Fragments of this "
00398 << "type will be stored in the event with an instance name of \""
00399 << unidentified_instance_name << "\"." ;
00400 }
00401 }
00402 incoming_events->ReleaseBuffer();
00403 TLOG_ARB(10, "SharedMemoryReader") << "readNext: bytesRead=" << bytesRead << " qsize=" << qsize << " cap=" << incoming_events->size() << " metricMan=" << (void*)metricMan ;
00404 if (metricMan)
00405 {
00406 metricMan->sendMetric("bytesRead", bytesRead, "B", 5, MetricMode::Accumulate, "", true);
00407 metricMan->sendMetric("queue%Used", static_cast<unsigned long int>(qsize * 100 / incoming_events->size()), "%", 5, MetricMode::LastPoint, "", true);
00408 }
00409
00410 return true;
00411 }
00412
00413 std::map<Fragment::type_t, std::string> fragment_type_map_;
00414 unsigned readNext_calls_;
00415 };
00416 }
00417 }
00418
00419
00420 #endif