1 #ifndef ARTDAQ_DAQRATE_SHAREDMEMORYEVENTMANAGER_HH
2 #define ARTDAQ_DAQRATE_SHAREDMEMORYEVENTMANAGER_HH
4 #include "artdaq/DAQdata/Globals.hh"
11 #include "artdaq-core/Core/SharedMemoryManager.hh"
12 #include "artdaq-core/Data/RawEvent.hh"
13 #include "artdaq/DAQrate/RequestSender.hh"
14 #include "artdaq/DAQrate/StatisticsHelper.hh"
15 #include "fhiclcpp/fwd.h"
16 #define ART_SUPPORTS_DUPLICATE_EVENTS 0
31 : dir_name_(
"/tmp/partition_" + std::to_string(GetPartitionNumber()))
32 , file_name_(dir_name_ +
"/artConfig_" + std::to_string(my_rank) +
"_" + std::to_string(artdaq::TimeUtils::gettimeofday_us()) +
".fcl")
34 mkdir(dir_name_.c_str(), 0777);
36 std::ofstream of(file_name_, std::ofstream::trunc);
40 dir_name_ =
"/tmp/partition_" + std::to_string(GetPartitionNumber()) +
"_" + std::to_string(getuid());
41 mkdir(dir_name_.c_str(), 0777);
42 file_name_ = dir_name_ +
"/artConfig_" + std::to_string(my_rank) +
"_" + std::to_string(artdaq::TimeUtils::gettimeofday_us()) +
".fcl";
44 of.open(file_name_, std::ofstream::trunc);
47 TLOG(TLVL_ERROR) <<
"Failed to open configuration file after two attemps! ABORTING!";
59 if (!ps.has_key(
"services.message"))
61 of <<
" services.message: { " << generateMessageFacilityConfiguration(
"art") <<
"} ";
70 remove(file_name_.c_str());
71 rmdir(dir_name_.c_str());
80 std::string dir_name_;
81 std::string file_name_;
96 typedef std::map<sequence_id_t, RawEvent_ptr>
EventMap;
105 fhicl::Atom<size_t>
max_event_size_bytes{fhicl::Name{
"max_event_size_bytes"}, fhicl::Comment{
"Maximum event size (all Fragments), in bytes"}};
107 fhicl::Atom<size_t>
stale_buffer_timeout_usec{fhicl::Name{
"stale_buffer_timeout_usec"}, fhicl::Comment{
"Maximum amount of time elapsed before a buffer is marked as abandoned. Time is reset each time an operation is performed on the buffer."}, 5000000};
109 fhicl::Atom<bool>
overwrite_mode{fhicl::Name{
"overwrite_mode"}, fhicl::Comment{
"Whether buffers are allowed to be overwritten when safe (state == Full or Reading)"},
false};
111 fhicl::Atom<bool>
restart_crashed_art_processes{fhicl::Name{
"restart_crashed_art_processes"}, fhicl::Comment{
"Whether to automatically restart art processes that fail for any reason"},
true};
113 fhicl::Atom<uint32_t>
shared_memory_key{fhicl::Name{
"shared_memory_key"}, fhicl::Comment{
"Key to use for shared memory access"}, 0xBEE70000 + getpid()};
115 fhicl::Atom<size_t>
buffer_count{fhicl::Name{
"buffer_count"}, fhicl::Comment{
"Number of events in the Shared Memory (incomplete + pending art)"}};
118 fhicl::Atom<size_t>
max_fragment_size_bytes{fhicl::Name{
"max_fragment_size_bytes"}, fhicl::Comment{
" Maximum Fragment size, in bytes"}};
120 fhicl::Atom<size_t>
event_queue_wait_time{fhicl::Name{
"event_queue_wait_time"}, fhicl::Comment{
"Amount of time (in seconds) an event can exist in shared memory before being released to art. Used as input to default parameter of \"stale_buffer_timeout_usec\"."}, 5};
122 fhicl::Atom<bool>
broadcast_mode{fhicl::Name{
"broadcast_mode"}, fhicl::Comment{
"When true, buffers are not marked Empty when read, but return to Full state. Buffers are overwritten in order received."},
false};
124 fhicl::Atom<size_t>
art_analyzer_count{fhicl::Name{
"art_analyzer_count"}, fhicl::Comment{
"Number of art procceses to start"}, 1};
126 fhicl::Atom<size_t>
expected_fragments_per_event{fhicl::Name{
"expected_fragments_per_event"}, fhicl::Comment{
"Number of Fragments to expect per event"}};
128 fhicl::Atom<int>
maximum_oversize_fragment_count{fhicl::Name{
"maximum_oversize_fragment_count"}, fhicl::Comment{
"Maximum number of over-size Fragments to drop before throwing an exception. Default is 1, which means to throw an exception if any over-size Fragments are dropped. Set to 0 to disable."}, 1};
130 fhicl::Atom<bool>
update_run_ids_on_new_fragment{fhicl::Name{
"update_run_ids_on_new_fragment"}, fhicl::Comment{
"Whether the run and subrun ID of an event should be updated whenever a Fragment is added."},
true};
132 fhicl::Atom<bool>
use_sequence_id_for_event_number{fhicl::Name{
"use_sequence_id_for_event_number"}, fhicl::Comment{
"Whether to use the artdaq Sequence ID (true) or the Timestamp (false) for art Event numbers"},
true};
134 fhicl::Atom<size_t>
max_subrun_lookup_table_size{fhicl::Name{
"max_subrun_lookup_table_size"}, fhicl::Comment{
"The maximum number of entries to store in the sequence ID-SubRun ID lookup table"}, 100};
136 fhicl::Atom<size_t>
max_event_list_length{fhicl::Name{
"max_event_list_length"}, fhicl::Comment{
" The maximum number of entries to store in the released events list"}, 100};
138 fhicl::Atom<bool>
send_init_fragments{fhicl::Name{
"send_init_fragments"}, fhicl::Comment{
"Whether Init Fragments are expected to be sent to art. If true, a Warning message is printed when an Init Fragment is requested but none are available."},
true};
140 fhicl::Atom<int>
incomplete_event_report_interval_ms{fhicl::Name{
"incomplete_event_report_interval_ms"}, fhicl::Comment{
"Interval at which an incomplete event report should be written"}, -1};
143 fhicl::Atom<int>
fragment_broadcast_timeout_ms{fhicl::Name{
"fragment_broadcast_timeout_ms"}, fhicl::Comment{
"Amount of time broadcast fragments should live in the broadcast shared memory segment"}, 3000};
145 fhicl::Atom<double>
minimum_art_lifetime_s{fhicl::Name{
"minimum_art_lifetime_s"}, fhicl::Comment{
"Amount of time that an art process should run to not be considered \"DOA\""}, 2.0};
148 fhicl::Atom<size_t>
expected_art_event_processing_time_us{fhicl::Name{
"expected_art_event_processing_time_us"}, fhicl::Comment{
"During shutdown, SMEM will wait for this amount of time while it is checking that the art threads are done reading buffers."}, 100000};
152 fhicl::Atom<size_t>
broadcast_buffer_count{fhicl::Name{
"broadcast_buffer_count"}, fhicl::Comment{
"Buffers in the broadcast shared memory segment"}, 10};
154 fhicl::Atom<size_t>
broadcast_buffer_size{fhicl::Name{
"broadcast_buffer_size"}, fhicl::Comment{
"Size of the buffers in the broadcast shared memory segment"}, 0x100000};
156 fhicl::Atom<bool>
use_art{fhicl::Name{
"use_art"}, fhicl::Comment{
"Whether to start and manage art threads (Sets art_analyzer count to 0 and overwrite_mode to true when false)"},
true};
158 fhicl::Atom<bool>
manual_art{fhicl::Name{
"manual_art"}, fhicl::Comment{
"Prints the startup command line for the art process so that the user may (for example) run it in GDB or valgrind"},
false};
183 bool AddFragment(detail::RawFragmentHeader frag,
void* dataPtr);
193 bool AddFragment(FragmentPtr frag,
size_t timeout_usec, FragmentPtr& outfrag);
201 RawDataType*
WriteFragmentHeader(detail::RawFragmentHeader frag,
bool dropIfNoBuffersAvailable =
false);
239 size_t GetFragmentCount(Fragment::sequence_id_t seqID, Fragment::type_t type = Fragment::InvalidFragmentType);
252 void RunArt(std::shared_ptr<art_config_file> config_file, std::shared_ptr<std::atomic<pid_t>> pid_out);
331 if (requests_) requests_->SetRequestMode(mode);
358 if (dropped_data_.count(frag) && dropped_data_[frag] !=
nullptr)
360 return dropped_data_[frag]->dataBegin();
395 size_t get_art_process_count_()
397 std::unique_lock<std::mutex> lk(art_process_mutex_);
398 return art_processes_.size();
401 std::string buildStatisticsString_()
const;
404 size_t num_art_processes_;
405 size_t const num_fragments_per_event_;
406 size_t const queue_size_;
409 std::map<sequence_id_t, subrun_id_t> subrun_event_map_;
410 size_t max_subrun_event_map_length_;
411 static std::mutex subrun_event_map_mutex_;
413 std::set<int> active_buffers_;
414 std::set<int> pending_buffers_;
415 std::unordered_map<Fragment::sequence_id_t, size_t> released_incomplete_events_;
416 std::set<Fragment::sequence_id_t> released_events_;
417 size_t max_event_list_length_;
419 bool update_run_ids_;
420 bool use_sequence_id_for_event_number_;
421 bool overwrite_mode_;
422 size_t init_fragment_count_;
425 std::unordered_map<int, std::atomic<int>> buffer_writes_pending_;
426 std::unordered_map<int, std::mutex> buffer_mutexes_;
427 static std::mutex sequence_id_mutex_;
429 int incomplete_event_report_interval_ms_;
430 std::chrono::steady_clock::time_point last_incomplete_event_report_time_;
431 std::chrono::steady_clock::time_point last_backpressure_report_time_;
432 std::chrono::steady_clock::time_point last_fragment_header_write_time_;
434 StatisticsHelper statsHelper_;
436 int broadcast_timeout_ms_;
438 std::atomic<int> run_event_count_;
439 std::atomic<int> run_incomplete_event_count_;
440 std::atomic<int> subrun_event_count_;
441 std::atomic<int> subrun_incomplete_event_count_;
442 std::atomic<int> oversize_fragment_count_;
443 int maximum_oversize_fragment_count_;
445 mutable std::mutex art_process_mutex_;
446 std::set<pid_t> art_processes_;
447 std::atomic<bool> restart_art_;
448 bool always_restart_art_;
449 std::atomic<bool> manual_art_;
450 fhicl::ParameterSet current_art_pset_;
451 std::shared_ptr<art_config_file> current_art_config_file_;
452 double minimum_art_lifetime_s_;
453 size_t art_event_processing_time_us_;
455 std::unique_ptr<RequestSender> requests_;
456 fhicl::ParameterSet data_pset_;
458 FragmentPtrs init_fragments_;
459 std::unordered_map<Fragment::fragment_id_t, FragmentPtr> dropped_data_;
461 bool broadcastFragments_(FragmentPtrs& frags);
463 detail::RawEventHeader* getEventHeader_(
int buffer);
465 int getBufferForSequenceID_(Fragment::sequence_id_t seqID,
bool create_new, Fragment::timestamp_t timestamp = Fragment::InvalidTimestamp);
466 bool hasFragments_(
int buffer);
467 void complete_buffer_(
int buffer);
468 bool bufferComparator(
int bufA,
int bufB);
469 void check_pending_buffers_(std::unique_lock<std::mutex>
const& lock);
471 void send_init_frags_();
472 SharedMemoryManager broadcasts_;
476 #endif //ARTDAQ_DAQRATE_SHAREDMEMORYEVENTMANAGER_HH
void RunArt(std::shared_ptr< art_config_file > config_file, std::shared_ptr< std::atomic< pid_t >> pid_out)
Run an art instance, recording the return codes and restarting it until the end flag is raised...
fhicl::Atom< size_t > event_queue_wait_time
"event_queue_wait_time" (Default: 5) : Amount of time(in seconds) an event can exist in shared memory...
fhicl::Atom< bool > overwrite_mode
"overwite_mode" (Default: false): Whether new data is allowed to overwrite buffers in the "Full" stat...
art_config_file wraps a temporary file used to configure art
void AddInitFragment(FragmentPtr &frag)
Set the stored Init fragment, if one has not yet been set already.
void ShutdownArtProcesses(std::set< pid_t > &pids)
Shutdown a set of art processes.
size_t GetLockedBufferCount()
Returns the number of buffers currently owned by this manager.
virtual ~SharedMemoryEventManager()
SharedMemoryEventManager Destructor.
The SharedMemoryEventManager is a SharedMemoryManger which tracks events as they are built...
Fragment::sequence_id_t sequence_id_t
Copy Fragment::sequence_id_t into local scope.
fhicl::Atom< size_t > broadcast_buffer_size
"broadcast_buffer_size" (Default: 0x100000): Size of the buffers in the broadcast shared memory segme...
subrun_id_t GetCurrentSubrun()
Get the current subrun number (Gets the last defined subrun)
fhicl::Atom< bool > restart_crashed_art_processes
"restart_crashed_art_processes" (Default: true) : Whether to automatically restart art processes that...
void ReconfigureArt(fhicl::ParameterSet art_pset, run_id_t newRun=0, int n_art_processes=-1)
Restart all art processes, using the given fhicl code to configure the new art processes.
pid_t StartArtProcess(fhicl::ParameterSet pset)
Start one art process.
fhicl::Atom< double > minimum_art_lifetime_s
"minimum_art_lifetime_s" (Default: 2 seconds): Amount of time that an art process should run to not b...
fhicl::Atom< int > maximum_oversize_fragment_count
"maximum_oversize_fragment_count" (Default: 1): Maximum number of over-size Fragments to drop before ...
fhicl::Atom< bool > update_run_ids_on_new_fragment
"update_run_ids_on_new_fragment" (Default: true) : Whether the run and subrun ID of an event should b...
RawDataType * WriteFragmentHeader(detail::RawFragmentHeader frag, bool dropIfNoBuffersAvailable=false)
Get a pointer to a reserved memory area for the given Fragment header.
void setRequestMode(detail::RequestMessageMode mode)
Set the RequestMessageMode for all outgoing data requests.
size_t GetArtEventCount()
Returns the number of events sent to art this run.
fhicl::Atom< size_t > art_analyzer_count
"art_analyzer_count" (Default: 1) : Number of art procceses to start
Configuration of the SharedMemoryEventManager. May be used for parameter validation ...
fhicl::Atom< bool > use_sequence_id_for_event_number
"use_sequence_id_for_event_number" (Default: true): Whether to use the artdaq Sequence ID (true) or t...
fhicl::Atom< uint32_t > broadcast_shared_memory_key
"broadcast_shared_memory_key" (Default: 0xCEE7000 + PID): Key to use for broadcast shared memory acce...
RawEvent::run_id_t run_id_t
Copy RawEvent::run_id_t into local scope.
fhicl::WrappedTable< Config > Parameters
Used for ParameterSet validation (if desired)
size_t GetFragmentCount(Fragment::sequence_id_t seqID, Fragment::type_t type=Fragment::InvalidFragmentType)
Get the count of Fragments of a given type in an event.
void UpdateArtConfiguration(fhicl::ParameterSet art_pset)
Updates the internally-stored copy of the art configuration.
RawDataType * GetDroppedDataAddress(Fragment::fragment_id_t frag)
Gets the address of the "dropped data" fragment. Used for testing.
fhicl::Atom< size_t > max_subrun_lookup_table_size
"max_subrun_lookup_table_size" (Default: 100): The maximum number of entries to store in the sequence...
size_t GetPendingEventCount()
Returns the number of events which are complete but waiting on lower sequenced events to finish...
void StartArt()
Start all the art processes.
run_id_t runID() const
Get the current Run number.
fhicl::Atom< size_t > max_fragment_size_bytes
fhicl::Atom< size_t > buffer_count
"buffer_count" REQUIRED: Number of events in the Shared Memory(incomplete + pending art) ...
subrun_id_t GetSubrunForSequenceID(Fragment::sequence_id_t seqID)
Get the subrun number that the given Sequence ID would be assigned to.
fhicl::TableFragment< artdaq::RequestSender::Config > requestSenderConfig
Configuration of the RequestSender. See artdaq::RequestSender::Config.
fhicl::Atom< size_t > expected_art_event_processing_time_us
fhicl::Atom< uint32_t > shared_memory_key
"shared_memory_key" (Default 0xBEE70000 + PID) : Key to use for shared memory access ...
std::map< sequence_id_t, RawEvent_ptr > EventMap
An EventMap is a map of RawEvent_ptr objects, keyed by sequence ID.
RequestMessageMode
Mode used to indicate current run conditions to the request receiver.
fhicl::Atom< size_t > max_event_list_length
"max_event_list_length" (Default: 100): The maximum number of entries to store in the released events...
void rolloverSubrun()
Add a subrun transition immediately after the highest currently define sequence ID.
void sendMetrics()
Send metrics to the MetricManager, if one has been instantiated in the application.
fhicl::Atom< size_t > stale_buffer_timeout_usec
"stale_buffer_timeout_usec" (Default: event_queue_wait_time * 1, 000, 000) : Maximum amount of time e...
fhicl::Atom< size_t > expected_fragments_per_event
"expected_fragments_per_event" (REQUIRED) : Number of Fragments to expect per event ...
size_t GetIncompleteEventCount()
Returns the number of buffers which contain data but are not yet complete.
fhicl::Atom< bool > send_init_fragments
"send_init_fragments" (Default: true): Whether Init Fragments are expected to be sent to art...
static const std::string FRAGMENTS_RECEIVED_STAT_KEY
Key for Fragments Received MonitoredQuantity.
SharedMemoryEventManager(fhicl::ParameterSet pset, fhicl::ParameterSet art_pset)
SharedMemoryEventManager Constructor.
bool endRun()
Send an EndOfRunFragment to the art thread.
fhicl::Atom< size_t > max_event_size_bytes
void setOverwrite(bool overwrite)
Set the overwrite flag (non-reliable data transfer) for the Shared Memory.
fhicl::Atom< int > incomplete_event_report_interval_ms
"incomplete_event_report_interval_ms" (Default: -1): Interval at which an incomplete event report sho...
std::string getFileName() const
Get the path of the temporary file.
fhicl::Atom< bool > manual_art
"manual_art" (Default: false): Prints the startup command line for the art process so that the user m...
fhicl::Atom< bool > broadcast_mode
"broadcast_mode" (Default: false) : When true, buffers are not marked Empty when read, but return to Full state.Buffers are overwritten in order received.
fhicl::Atom< size_t > broadcast_buffer_count
"broadcast_buffer_count" (Default: 10): Buffers in the broadcast shared memory segment ...
void DoneWritingFragment(detail::RawFragmentHeader frag)
Used to indicate that the given Fragment is now completely in the buffer. Will check for buffer compl...
static const std::string EVENTS_RELEASED_STAT_KEY
Key for the Events Released MonitoredQuantity.
uint32_t GetBroadcastKey()
Gets the shared memory key of the broadcast SharedMemoryManager.
bool endOfData()
Indicate that the end of input has been reached to the art processes.
fhicl::Atom< bool > use_art
"use_art" (Default: true): Whether to start and manage art threads (Sets art_analyzer count to 0 and ...
RawEvent::subrun_id_t subrun_id_t
Copy RawEvent::subrun_id_t into local scope.
fhicl::Atom< int > fragment_broadcast_timeout_ms
art_config_file(fhicl::ParameterSet ps)
art_config_file Constructor
void startRun(run_id_t runID)
Start a Run.
size_t GetFragmentCountInBuffer(int buffer, Fragment::type_t type=Fragment::InvalidFragmentType)
Get the count of Fragments of a given type in a buffer.
void CheckPendingBuffers()
Check for buffers which are ready to be marked incomplete and released to art and issue tokens for an...