1 #include "TRACE/tracemf.h"
2 #define TRACE_NAME "ArtdaqSharedMemoryService"
4 #include "artdaq/ArtModules/ArtdaqSharedMemoryServiceInterface.h"
5 #include "artdaq/DAQdata/Globals.hh"
7 #include "artdaq-core/Core/SharedMemoryEventReceiver.hh"
8 #include "artdaq-core/Utilities/ExceptionHandler.hh"
10 #include "art/Framework/Services/Registry/ServiceDefinitionMacros.h"
11 #include "art/Framework/Services/Registry/ServiceHandle.h"
12 #include "fhiclcpp/types/Atom.h"
13 #include "fhiclcpp/types/Comment.h"
14 #include "fhiclcpp/types/ConfigurationTable.h"
15 #include "fhiclcpp/types/Name.h"
36 fhicl::Atom<uint32_t>
shared_memory_key{fhicl::Name{
"shared_memory_key"}, fhicl::Comment{
"Key to use when connecting to shared memory. Will default to 0xBEE70000 + getppid()."}, 0xBEE70000};
38 fhicl::Atom<uint32_t>
broadcast_shared_memory_key{fhicl::Name{
"broadcast_shared_memory_key"}, fhicl::Comment{
"Key to use when connecting to broadcast shared memory. Will default to 0xCEE70000 + getppid()."}, 0xCEE70000};
40 fhicl::Atom<int>
rank{fhicl::Name{
"rank"}, fhicl::Comment{
"Rank of this artdaq application. Used for data transfers"}};
61 std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>>
ReceiveEvent(
bool broadcast)
override;
67 size_t GetQueueSize()
override {
return incoming_events_->ReadReadyCount(); }
77 std::shared_ptr<artdaq::detail::RawEventHeader>
GetEventHeader()
override {
return evtHeader_; }
83 size_t GetMyId()
override {
return incoming_events_->GetMyId(); }
92 std::unique_ptr<artdaq::SharedMemoryEventReceiver> incoming_events_;
93 std::shared_ptr<artdaq::detail::RawEventHeader> evtHeader_;
95 bool resume_after_timeout_;
96 bool printed_exit_message_{
false};
101 #define build_key(seed) ((seed) + ((GetPartitionNumber() + 1) << 16) + (getppid() & 0xFFFF))
103 static fhicl::ParameterSet empty_pset;
106 : incoming_events_(nullptr)
107 , evtHeader_(nullptr)
108 , read_timeout_(pset.get<size_t>(
"read_timeout_us", static_cast<size_t>(pset.get<double>(
"waiting_time", 600.0) * 1000000)))
109 , resume_after_timeout_(pset.get<bool>(
"resume_after_timeout", true))
111 TLOG(TLVL_DEBUG + 33) <<
"ArtdaqSharedMemoryService CONSTRUCTOR";
113 incoming_events_ = std::make_unique<artdaq::SharedMemoryEventReceiver>(
114 pset.get<
int>(
"shared_memory_key", build_key(0xEE000000)),
115 pset.get<
int>(
"broadcast_shared_memory_key", build_key(0xBB000000)));
117 char const* artapp_env = getenv(
"ARTDAQ_APPLICATION_NAME");
118 std::string artapp_str;
119 if (artapp_env !=
nullptr)
121 artapp_str = std::string(artapp_env) +
"_";
124 TLOG(TLVL_DEBUG + 33) <<
"Setting app_name";
125 app_name = artapp_str +
"art" + std::to_string(incoming_events_->GetMyId());
128 artapp_env = getenv(
"ARTDAQ_RANK");
129 if (artapp_env !=
nullptr && my_rank < 0)
131 TLOG(TLVL_DEBUG + 33) <<
"Setting rank from envrionment";
132 my_rank = strtol(artapp_env,
nullptr, 10);
136 TLOG(TLVL_DEBUG + 33) <<
"Setting my_rank from shared memory";
137 my_rank = incoming_events_->GetRank();
144 metricMan->initialize(pset.get<fhicl::ParameterSet>(
"metrics", fhicl::ParameterSet()), app_name);
145 metricMan->do_start();
150 artdaq::ExceptionHandler(artdaq::ExceptionHandlerRethrow::no,
"Error loading metrics in ArtdaqSharedMemoryService()");
153 TLOG(TLVL_INFO) <<
"app_name is " << app_name <<
", rank " << my_rank;
163 TLOG(TLVL_DEBUG + 33) <<
"ReceiveEvent BEGIN";
164 std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> recvd_fragments;
166 if (printed_exit_message_)
168 return recvd_fragments;
171 while (recvd_fragments.empty())
173 TLOG(TLVL_DEBUG + 33) <<
"ReceiveEvent: Waiting for available buffer";
174 bool got_event =
false;
175 auto start_time = std::chrono::steady_clock::now();
176 auto read_timeout_to_use = read_timeout_ > 100000 ? 100000 : read_timeout_;
177 if (!resume_after_timeout_ || broadcast) read_timeout_to_use = read_timeout_;
178 while (!incoming_events_->IsEndOfData() && !got_event)
180 got_event = incoming_events_->ReadyForRead(broadcast, read_timeout_to_use);
181 if (!got_event && (!resume_after_timeout_ || broadcast))
183 TLOG(TLVL_ERROR) <<
"Timeout occurred! No data received after " << read_timeout_to_use <<
" us. Returning empty Fragment list!";
184 return recvd_fragments;
186 if (!got_event && artdaq::TimeUtils::GetElapsedTimeMicroseconds(start_time) > read_timeout_)
188 TLOG(TLVL_WARNING) <<
"Timeout occurred! No data received after " << artdaq::TimeUtils::GetElapsedTimeMicroseconds(start_time) <<
" us. Retrying.";
191 if (incoming_events_->IsEndOfData())
193 if (!printed_exit_message_)
195 TLOG(TLVL_INFO) <<
"End of Data signal received, exiting";
196 printed_exit_message_ =
true;
198 return recvd_fragments;
201 TLOG(TLVL_DEBUG + 33) <<
"ReceiveEvent: Reading buffer header";
202 auto errflag =
false;
203 auto hdrPtr = incoming_events_->ReadHeader(errflag);
204 if (errflag || hdrPtr ==
nullptr)
206 incoming_events_->ReleaseBuffer();
210 evtHeader_ = std::make_shared<artdaq::detail::RawEventHeader>(*hdrPtr);
211 TLOG(TLVL_DEBUG + 33) <<
"ReceiveEvent: Getting Fragment types";
212 auto fragmentTypes = incoming_events_->GetFragmentTypes(errflag);
215 incoming_events_->ReleaseBuffer();
219 if (fragmentTypes.empty())
221 TLOG(TLVL_ERROR) <<
"Event has no Fragments! Aborting!";
222 incoming_events_->ReleaseBuffer();
223 return recvd_fragments;
226 for (
auto const& type : fragmentTypes)
228 TLOG(TLVL_DEBUG + 33) <<
"ReceiveEvent: Getting all Fragments of type " <<
static_cast<int>(type);
229 recvd_fragments[type] = incoming_events_->GetFragmentsByType(errflag, type);
230 if (!recvd_fragments[type])
232 TLOG(TLVL_WARNING) <<
"Error retrieving Fragments from shared memory! (Most likely due to a buffer overwrite) Retrying...";
233 incoming_events_->ReleaseBuffer();
234 recvd_fragments.clear();
240 std::sort(recvd_fragments[type]->begin(), recvd_fragments[type]->end(), artdaq::fragmentSequenceIDCompare);
242 TLOG(TLVL_DEBUG + 33) <<
"ReceiveEvent: Releasing buffer";
243 incoming_events_->ReleaseBuffer();
246 TLOG(TLVL_DEBUG + 33) <<
"ReceiveEvent END";
247 return recvd_fragments;
fhicl::WrappedTable< Config > Parameters
Used for ParameterSet validation (if desired)
Interface for ArtdaqSharedMemoryService. This interface is declared to art as part of the required re...
static void CleanUpGlobals()
Clean up statically-allocated Manager class instances.
size_t GetQueueSize() override
Get the number of events which are ready to be read.
virtual ~ArtdaqSharedMemoryService()
NetMonTransportService Destructor. Calls disconnect().
fhicl::Atom< int > rank
"rank" (OPTIONAL) : The rank of this applicaiton, for use by non - artdaq applications running NetMon...
ArtdaqSharedMemoryService(fhicl::ParameterSet const &pset, art::ActivityRegistry &)
NetMonTransportService Constructor.
fhicl::Atom< uint32_t > broadcast_shared_memory_key
"shared_memory_key" (Default: 0xCEE70000 + pid): Key to use when connecting to broadcast shared memor...
size_t GetQueueCapacity() override
Get the maximum number of events which can be stored in the shared memory.
Allowed Configuration parameters of NetMonTransportService. May be used for configuration validation ...
size_t GetMyId() override
Get the ID of this art process.
ArtdaqSharedMemoryService extends ArtdaqSharedMemoryServiceInterface. It receives events from shared ...
fhicl::Atom< uint32_t > shared_memory_key
"shared_memory_key" (Default: 0xBEE70000 + pid): Key to use when connecting to shared memory...
std::shared_ptr< artdaq::detail::RawEventHeader > GetEventHeader() override
Get a shared_ptr to the current event header, if any.
std::unordered_map< artdaq::Fragment::type_t, std::unique_ptr< artdaq::Fragments > > ReceiveEvent(bool broadcast) override
Receive an event from the shared memory.