00001 #ifndef ARTDAQ_DAQRATE_SHAREDMEMORYEVENTMANAGER_HH
00002 #define ARTDAQ_DAQRATE_SHAREDMEMORYEVENTMANAGER_HH
00003
00004 #include "artdaq/DAQdata/Globals.hh"
00005 #include "artdaq-core/Core/SharedMemoryManager.hh"
00006 #include "artdaq-core/Data/RawEvent.hh"
00007 #include "artdaq/DAQrate/RequestSender.hh"
00008 #include <set>
00009 #include <deque>
00010 #include <fstream>
00011 #include <iomanip>
00012 #include "fhiclcpp/fwd.h"
00013 #include "artdaq/Application/StatisticsHelper.hh"
00014 #define ART_SUPPORTS_DUPLICATE_EVENTS 0
00015
00016 namespace artdaq {
00017
00021 class art_config_file
00022 {
00023 public:
00028 art_config_file(fhicl::ParameterSet ps) : file_name_(std::tmpnam(nullptr))
00029 {
00030 std::ofstream of(file_name_, std::ofstream::trunc);
00031 of << ps.to_string();
00032
00033
00034
00035
00036
00037
00038
00039 if (!ps.has_key("services.message"))
00040 {
00041 of << " services.message: { " << generateMessageFacilityConfiguration("art") << "} ";
00042 }
00043
00044
00045
00046 of.close();
00047 }
00048 ~art_config_file() { remove(file_name_.c_str()); }
00053 std::string getFileName() const { return file_name_; }
00054 private:
00055 std::string file_name_;
00056 };
00057
00061 class SharedMemoryEventManager : public SharedMemoryManager
00062 {
00063 public:
00064 typedef RawEvent::run_id_t run_id_t;
00065 typedef RawEvent::subrun_id_t subrun_id_t;
00066 typedef Fragment::sequence_id_t sequence_id_t;
00067 typedef std::map<sequence_id_t, RawEvent_ptr> EventMap;
00068
00098 SharedMemoryEventManager(fhicl::ParameterSet pset, fhicl::ParameterSet art_pset);
00102 virtual ~SharedMemoryEventManager();
00103
00104 private:
00111 bool AddFragment(detail::RawFragmentHeader frag, void* dataPtr);
00112
00113 public:
00121 bool AddFragment(FragmentPtr frag, size_t timeout_usec, FragmentPtr& outfrag);
00122
00129 RawDataType* WriteFragmentHeader(detail::RawFragmentHeader frag, bool dropIfNoBuffersAvailable = false);
00130
00135 void DoneWritingFragment(detail::RawFragmentHeader frag);
00136
00141 size_t GetIncompleteEventCount() { return active_buffers_.size(); }
00142
00147 size_t GetPendingEventCount() { return pending_buffers_.size(); }
00148
00153 size_t GetLockedBufferCount() { return GetBuffersOwnedByManager().size(); }
00154
00159 size_t GetArtEventCount() { return subrun_event_count_; }
00160
00167 size_t GetFragmentCount(Fragment::sequence_id_t seqID, Fragment::type_t type = Fragment::InvalidFragmentType);
00168
00175 size_t GetFragmentCountInBuffer(int buffer, Fragment::type_t type = Fragment::InvalidFragmentType);
00176
00180 void RunArt(std::shared_ptr<art_config_file> config_file, pid_t& pid_out);
00184 void StartArt();
00185
00191 pid_t StartArtProcess(fhicl::ParameterSet pset);
00192
00197 void ShutdownArtProcesses(std::set<pid_t> pids);
00198
00205 void ReconfigureArt(fhicl::ParameterSet art_pset, run_id_t newRun = 0, int n_art_processes = -1);
00206
00216 bool endOfData();
00217
00222 void startRun(run_id_t runID);
00223
00227 void startSubrun();
00228
00233 run_id_t runID() const { return run_id_; }
00234
00239 subrun_id_t subrunID() const { return subrun_id_; }
00240
00245 bool endRun();
00246
00251 bool endSubrun();
00252
00256 void sendMetrics();
00257
00262 void setRequestMode(detail::RequestMessageMode mode) { requests_.SetRequestMode(mode); }
00263
00268 void setOverwrite(bool overwrite) { overwrite_mode_ = overwrite; }
00269
00273 void SetInitFragment(FragmentPtr frag);
00274
00279 uint32_t GetBroadcastKey() { return broadcasts_.GetKey(); }
00280
00285 RawDataType* GetDroppedDataAddress() { return dropped_data_->dataBegin(); }
00286
00287 private:
00288 size_t num_art_processes_;
00289 size_t const num_fragments_per_event_;
00290 size_t const queue_size_;
00291 run_id_t run_id_;
00292 subrun_id_t subrun_id_;
00293
00294 std::set<int> active_buffers_;
00295 std::set<int> pending_buffers_;
00296 std::unordered_map<Fragment::sequence_id_t, size_t> released_incomplete_events_;
00297
00298 bool update_run_ids_;
00299 bool overwrite_mode_;
00300 bool send_init_fragments_;
00301
00302 std::unordered_map<int, std::atomic<int>> buffer_writes_pending_;
00303 std::unordered_map<int, std::mutex> buffer_mutexes_;
00304 static std::mutex sequence_id_mutex_;
00305
00306 int incomplete_event_report_interval_ms_;
00307 std::chrono::steady_clock::time_point last_incomplete_event_report_time_;
00308 int broadcast_timeout_ms_;
00309 int broadcast_count_;
00310 int subrun_event_count_;
00311
00312 std::set<pid_t> art_processes_;
00313 std::atomic<bool> restart_art_;
00314 fhicl::ParameterSet current_art_pset_;
00315 std::shared_ptr<art_config_file> current_art_config_file_;
00316
00317 RequestSender requests_;
00318
00319 FragmentPtr init_fragment_;
00320 FragmentPtr dropped_data_;
00321
00322 bool broadcastFragment_(FragmentPtr frag, FragmentPtr& outFrag);
00323
00324 detail::RawEventHeader* getEventHeader_(int buffer);
00325
00326 int getBufferForSequenceID_(Fragment::sequence_id_t seqID, bool create_new, Fragment::timestamp_t timestamp = Fragment::InvalidTimestamp);
00327 bool hasFragments_(int buffer);
00328 void complete_buffer_(int buffer);
00329 bool bufferComparator(int bufA, int bufB);
00330 void check_pending_buffers_(std::unique_lock<std::mutex> const& lock = std::unique_lock<std::mutex>(sequence_id_mutex_));
00331
00332 void send_init_frag_();
00333 SharedMemoryManager broadcasts_;
00334 };
00335 }
00336
00337 #endif //ARTDAQ_DAQRATE_SHAREDMEMORYEVENTMANAGER_HH