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
00101 SharedMemoryEventManager(fhicl::ParameterSet pset, fhicl::ParameterSet art_pset);
00105 virtual ~SharedMemoryEventManager();
00106
00107 private:
00114 bool AddFragment(detail::RawFragmentHeader frag, void* dataPtr);
00115
00116 public:
00124 bool AddFragment(FragmentPtr frag, size_t timeout_usec, FragmentPtr& outfrag);
00125
00132 RawDataType* WriteFragmentHeader(detail::RawFragmentHeader frag, bool dropIfNoBuffersAvailable = false);
00133
00138 void DoneWritingFragment(detail::RawFragmentHeader frag);
00139
00144 size_t GetIncompleteEventCount() { return active_buffers_.size(); }
00145
00150 size_t GetPendingEventCount() { return pending_buffers_.size(); }
00151
00156 size_t GetLockedBufferCount() { return GetBuffersOwnedByManager().size(); }
00157
00162 size_t GetArtEventCount() { return subrun_event_count_; }
00163
00170 size_t GetFragmentCount(Fragment::sequence_id_t seqID, Fragment::type_t type = Fragment::InvalidFragmentType);
00171
00178 size_t GetFragmentCountInBuffer(int buffer, Fragment::type_t type = Fragment::InvalidFragmentType);
00179
00183 void RunArt(std::shared_ptr<art_config_file> config_file, pid_t& pid_out);
00187 void StartArt();
00188
00194 pid_t StartArtProcess(fhicl::ParameterSet pset);
00195
00200 void ShutdownArtProcesses(std::set<pid_t> pids);
00201
00208 void ReconfigureArt(fhicl::ParameterSet art_pset, run_id_t newRun = 0, int n_art_processes = -1);
00209
00219 bool endOfData();
00220
00225 void startRun(run_id_t runID);
00226
00230 void startSubrun();
00231
00236 run_id_t runID() const { return run_id_; }
00237
00242 subrun_id_t subrunID() const { return subrun_id_; }
00243
00248 bool endRun();
00249
00254 bool endSubrun();
00255
00259 void sendMetrics();
00260
00265 void setRequestMode(detail::RequestMessageMode mode) { if (requests_) requests_->SetRequestMode(mode); }
00266
00271 void setOverwrite(bool overwrite) { overwrite_mode_ = overwrite; }
00272
00276 void SetInitFragment(FragmentPtr frag);
00277
00282 uint32_t GetBroadcastKey() { return broadcasts_.GetKey(); }
00283
00288 RawDataType* GetDroppedDataAddress() { return dropped_data_->dataBegin(); }
00289
00290 private:
00291 size_t num_art_processes_;
00292 size_t const num_fragments_per_event_;
00293 size_t const queue_size_;
00294 run_id_t run_id_;
00295 subrun_id_t subrun_id_;
00296
00297 std::set<int> active_buffers_;
00298 std::set<int> pending_buffers_;
00299 std::unordered_map<Fragment::sequence_id_t, size_t> released_incomplete_events_;
00300
00301 bool update_run_ids_;
00302 bool overwrite_mode_;
00303 bool send_init_fragments_;
00304 bool running_;
00305
00306 std::unordered_map<int, std::atomic<int>> buffer_writes_pending_;
00307 std::unordered_map<int, std::mutex> buffer_mutexes_;
00308 static std::mutex sequence_id_mutex_;
00309
00310 int incomplete_event_report_interval_ms_;
00311 std::chrono::steady_clock::time_point last_incomplete_event_report_time_;
00312 int broadcast_timeout_ms_;
00313
00314 std::atomic<int> run_event_count_;
00315 std::atomic<int> run_incomplete_event_count_;
00316 std::atomic<int> subrun_event_count_;
00317 std::atomic<int> subrun_incomplete_event_count_;
00318
00319 std::set<pid_t> art_processes_;
00320 std::atomic<bool> restart_art_;
00321 fhicl::ParameterSet current_art_pset_;
00322 std::shared_ptr<art_config_file> current_art_config_file_;
00323 double minimum_art_lifetime_s_;
00324 size_t art_event_processing_time_us_;
00325
00326 std::unique_ptr<RequestSender> requests_;
00327 fhicl::ParameterSet data_pset_;
00328
00329 FragmentPtr init_fragment_;
00330 FragmentPtr dropped_data_;
00331
00332 bool broadcastFragment_(FragmentPtr frag, FragmentPtr& outFrag);
00333
00334 detail::RawEventHeader* getEventHeader_(int buffer);
00335
00336 int getBufferForSequenceID_(Fragment::sequence_id_t seqID, bool create_new, Fragment::timestamp_t timestamp = Fragment::InvalidTimestamp);
00337 bool hasFragments_(int buffer);
00338 void complete_buffer_(int buffer);
00339 bool bufferComparator(int bufA, int bufB);
00340 void check_pending_buffers_(std::unique_lock<std::mutex> const& lock = std::unique_lock<std::mutex>(sequence_id_mutex_));
00341
00342 void send_init_frag_();
00343 SharedMemoryManager broadcasts_;
00344 };
00345 }
00346
00347 #endif //ARTDAQ_DAQRATE_SHAREDMEMORYEVENTMANAGER_HH