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_; }
86 std::unique_ptr<artdaq::SharedMemoryEventReceiver> incoming_events_;
87 std::shared_ptr<artdaq::detail::RawEventHeader> evtHeader_;
89 bool resume_after_timeout_;
94 #define build_key(seed) ((seed) + ((GetPartitionNumber() + 1) << 16) + (getppid() & 0xFFFF))
96 static fhicl::ParameterSet empty_pset;
99 : incoming_events_(nullptr)
100 , evtHeader_(nullptr)
101 , read_timeout_(pset.get<size_t>(
"read_timeout_us", static_cast<size_t>(pset.get<double>(
"waiting_time", 600.0) * 1000000)))
102 , resume_after_timeout_(pset.get<bool>(
"resume_after_timeout", true))
104 TLOG(TLVL_DEBUG + 33) <<
"ArtdaqSharedMemoryService CONSTRUCTOR";
106 incoming_events_ = std::make_unique<artdaq::SharedMemoryEventReceiver>(
107 pset.get<
int>(
"shared_memory_key", build_key(0xEE000000)),
108 pset.get<
int>(
"broadcast_shared_memory_key", build_key(0xBB000000)));
110 char const* artapp_env = getenv(
"ARTDAQ_APPLICATION_NAME");
111 std::string artapp_str;
112 if (artapp_env !=
nullptr)
114 artapp_str = std::string(artapp_env) +
"_";
117 TLOG(TLVL_DEBUG + 33) <<
"Setting app_name";
118 app_name = artapp_str +
"art" + std::to_string(incoming_events_->GetMyId());
121 artapp_env = getenv(
"ARTDAQ_RANK");
122 if (artapp_env !=
nullptr && my_rank < 0)
124 TLOG(TLVL_DEBUG + 33) <<
"Setting rank from envrionment";
125 my_rank = strtol(artapp_env,
nullptr, 10);
129 TLOG(TLVL_DEBUG + 33) <<
"Setting my_rank from shared memory";
130 my_rank = incoming_events_->GetRank();
137 metricMan->initialize(pset.get<fhicl::ParameterSet>(
"metrics", fhicl::ParameterSet()), app_name);
138 metricMan->do_start();
143 artdaq::ExceptionHandler(artdaq::ExceptionHandlerRethrow::no,
"Error loading metrics in ArtdaqSharedMemoryService()");
146 TLOG(TLVL_INFO) <<
"app_name is " << app_name <<
", rank " << my_rank;
156 TLOG(TLVL_DEBUG + 33) <<
"ReceiveEvent BEGIN";
157 std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> recvd_fragments;
159 while (recvd_fragments.empty())
161 TLOG(TLVL_DEBUG + 33) <<
"ReceiveEvent: Waiting for available buffer";
162 bool got_event =
false;
163 auto start_time = std::chrono::steady_clock::now();
164 auto read_timeout_to_use = read_timeout_ > 100000 ? 100000 : read_timeout_;
165 if (!resume_after_timeout_ || broadcast) read_timeout_to_use = read_timeout_;
166 while (!incoming_events_->IsEndOfData() && !got_event)
168 got_event = incoming_events_->ReadyForRead(broadcast, read_timeout_to_use);
169 if (!got_event && (!resume_after_timeout_ || broadcast))
171 TLOG(TLVL_ERROR) <<
"Timeout occurred! No data received after " << read_timeout_to_use <<
" us. Returning empty Fragment list!";
172 return recvd_fragments;
174 if (!got_event && artdaq::TimeUtils::GetElapsedTimeMicroseconds(start_time) > read_timeout_)
176 TLOG(TLVL_WARNING) <<
"Timeout occurred! No data received after " << artdaq::TimeUtils::GetElapsedTimeMicroseconds(start_time) <<
" us. Retrying.";
179 if (incoming_events_->IsEndOfData())
181 TLOG(TLVL_INFO) <<
"End of Data signal received, exiting";
182 return recvd_fragments;
185 TLOG(TLVL_DEBUG + 33) <<
"ReceiveEvent: Reading buffer header";
186 auto errflag =
false;
187 auto hdrPtr = incoming_events_->ReadHeader(errflag);
188 if (errflag || hdrPtr ==
nullptr)
190 incoming_events_->ReleaseBuffer();
194 evtHeader_ = std::make_shared<artdaq::detail::RawEventHeader>(*hdrPtr);
195 TLOG(TLVL_DEBUG + 33) <<
"ReceiveEvent: Getting Fragment types";
196 auto fragmentTypes = incoming_events_->GetFragmentTypes(errflag);
199 incoming_events_->ReleaseBuffer();
203 if (fragmentTypes.empty())
205 TLOG(TLVL_ERROR) <<
"Event has no Fragments! Aborting!";
206 incoming_events_->ReleaseBuffer();
207 return recvd_fragments;
210 for (
auto const& type : fragmentTypes)
212 TLOG(TLVL_DEBUG + 33) <<
"ReceiveEvent: Getting all Fragments of type " <<
static_cast<int>(type);
213 recvd_fragments[type] = incoming_events_->GetFragmentsByType(errflag, type);
214 if (!recvd_fragments[type])
216 TLOG(TLVL_WARNING) <<
"Error retrieving Fragments from shared memory! (Most likely due to a buffer overwrite) Retrying...";
217 incoming_events_->ReleaseBuffer();
218 recvd_fragments.clear();
224 std::sort(recvd_fragments[type]->begin(), recvd_fragments[type]->end(), artdaq::fragmentSequenceIDCompare);
226 TLOG(TLVL_DEBUG + 33) <<
"ReceiveEvent: Releasing buffer";
227 incoming_events_->ReleaseBuffer();
230 TLOG(TLVL_DEBUG + 33) <<
"ReceiveEvent END";
231 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 ...
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.