1 #include "artdaq/DAQdata/Globals.hh"
2 #define TRACE_NAME "ListenTransferWrapper"
4 #include "artdaq-core/Data/Fragment.hh"
5 #include "artdaq-core/Utilities/ExceptionHandler.hh"
6 #include "artdaq-core/Utilities/TimeUtils.hh"
7 #include "artdaq/ArtModules/detail/ListenTransferWrapper.hh"
8 #include "artdaq/DAQdata/NetMonHeader.hh"
9 #include "artdaq/TransferPlugins/MakeTransferPlugin.hh"
11 #include "cetlib/BasicPluginFactory.h"
12 #include "cetlib_except/exception.h"
13 #include "fhiclcpp/ParameterSet.h"
30 void listen_signal_handler(
int signal)
32 gListenSignalStatus = signal;
36 : timeoutInUsecs_(pset.get<std::size_t>(
"timeoutInUsecs", 100000))
37 , last_received_data_()
38 , last_report_(std::chrono::steady_clock::now())
41 , maxEventsBeforeInit_(pset.get<std::size_t>(
"maxEventsBeforeInit", 5))
42 , allowedFragmentTypes_(pset.get<std::vector<int>>(
"allowedFragmentTypes", {226, 227, 229}))
43 , runningStateTimeout_(pset.get<
double>(
"dispatcherConnectTimeout", 0))
44 , runningStateInterval_us_(pset.get<
size_t>(
"dispatcherConnectRetryInterval_us", 1000000))
45 , quitOnFragmentIntegrityProblem_(pset.get<
bool>(
"quitOnFragmentIntegrityProblem",
true))
46 , multi_run_mode_(pset.get<
bool>(
"allowMultipleRuns",
true))
48 std::signal(SIGINT, listen_signal_handler);
54 metricMan->initialize(pset.get<fhicl::ParameterSet>(
"metrics", fhicl::ParameterSet()),
"Online Monitor");
55 metricMan->do_start();
60 artdaq::ExceptionHandler(
61 artdaq::ExceptionHandlerRethrow::no,
62 "ListenTransferWrapper: could not configure metrics");
71 artdaq::ExceptionHandler(artdaq::ExceptionHandlerRethrow::no,
"ListenTransferWrapper: failure in call to MakeTransferPlugin");
75 if (runningStateInterval_us_ < 1000)
77 TLOG(TLVL_WARNING) <<
"Invalid value " << runningStateInterval_us_ <<
" us detected for dispatcherConnectRetryInterval_us. Setting to 1000 us";
78 runningStateInterval_us_ = 1000;
80 if (runningStateInterval_us_ > 30000000)
82 TLOG(TLVL_WARNING) <<
"Invalid value " << runningStateInterval_us_ <<
" us detected for dispatcherConnectRetryInterval_us. Setting to 30,000,000 us";
83 runningStateInterval_us_ = 30000000;
89 artdaq::FragmentPtrs fragmentPtrs;
90 bool receivedFragment =
false;
91 static bool initialized =
false;
92 static size_t fragments_received = 0;
94 while (gListenSignalStatus == 0)
96 receivedFragment =
false;
97 auto fragmentPtr = std::make_unique<artdaq::Fragment>();
99 while (!receivedFragment)
101 if (gListenSignalStatus != 0)
103 TLOG(TLVL_INFO) <<
"Ctrl-C appears to have been hit";
109 auto result = transfer_->receiveFragment(*fragmentPtr, timeoutInUsecs_);
113 receivedFragment =
true;
114 fragments_received++;
116 static size_t cntr = 0;
117 auto mod = ++cntr % 10;
131 TLOG(TLVL_INFO) <<
"Received " << cntr << suffix <<
" event, "
132 <<
"seqID == " << fragmentPtr->sequenceID()
133 <<
", type == " << fragmentPtr->typeString();
134 last_received_data_ = std::chrono::steady_clock::now();
139 TLOG(TLVL_ERROR) <<
"Transfer Plugin disconnected or other unrecoverable error. Shutting down.";
149 auto tlvl = TLVL_DEBUG + 33;
150 if (artdaq::TimeUtils::GetElapsedTime(last_report_) > 1.0 && artdaq::TimeUtils::GetElapsedTime(last_received_data_) > 1.0)
153 last_report_ = std::chrono::steady_clock::now();
156 auto last_received_milliseconds = artdaq::TimeUtils::GetElapsedTimeMilliseconds(last_received_data_);
160 TLOG(tlvl) <<
"Timeout occurred in call to transfer_->receiveFragmentFrom; will try again"
161 <<
", status = " << result <<
", last received data " << last_received_milliseconds <<
" ms ago.";
166 artdaq::ExceptionHandler(
167 artdaq::ExceptionHandlerRethrow::yes,
168 "Problem receiving data in ListenTransferWrapper::receiveMessage");
172 if (fragmentPtr->type() == artdaq::Fragment::EndOfSubrunFragmentType || fragmentPtr->type() == artdaq::Fragment::EndOfRunFragmentType)
178 if (fragmentPtr->type() == artdaq::Fragment::EndOfDataFragmentType)
193 checkIntegrity(*fragmentPtr);
195 if (initialized || fragmentPtr->type() == artdaq::Fragment::InitFragmentType)
197 if (initialized && fragmentPtr->type() == artdaq::Fragment::InitFragmentType)
203 fragmentPtrs.push_back(std::move(fragmentPtr));
207 if (fragments_received > maxEventsBeforeInit_)
209 throw cet::exception(
"ListenTransferWrapper") <<
"First " << maxEventsBeforeInit_ <<
" events received did not include the \"Init\" event containing necessary info for art; exiting...";
216 std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>>
219 std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> output;
221 auto ptrs = receiveMessage();
222 for (
auto& ptr : ptrs)
224 auto fragType = ptr->type();
225 auto fragPtr = ptr.release();
228 if (output.count(fragType) == 0u)
230 output[fragType] = std::make_unique<artdaq::Fragments>();
233 output[fragType]->emplace_back(std::move(*fragPtr));
239 void artdaq::ListenTransferWrapper::checkIntegrity(
240 const artdaq::Fragment& fragment)
const
242 const size_t artdaqheader = artdaq::detail::RawFragmentHeader::num_words() *
243 sizeof(artdaq::detail::RawFragmentHeader::RawDataType);
244 const auto payload =
static_cast<size_t>(fragment.dataEndBytes() - fragment.dataBeginBytes());
246 const size_t totalsize = fragment.sizeBytes();
248 const auto type =
static_cast<size_t>(fragment.type());
250 if (totalsize != artdaqheader + metadata + payload)
252 std::stringstream errmsg;
253 errmsg <<
"Error: artdaq fragment of type " << fragment.typeString() <<
", sequence ID " << fragment.sequenceID() <<
" has internally inconsistent measures of its size, signalling data corruption: in bytes,"
254 <<
" total size = " << totalsize <<
", artdaq fragment header = " << artdaqheader <<
", metadata = " << metadata <<
", payload = " << payload;
256 TLOG(TLVL_ERROR) << errmsg.str();
258 if (quitOnFragmentIntegrityProblem_)
260 throw cet::exception(
"ListenTransferWrapper") << errmsg.str();
266 auto findloc = std::find(allowedFragmentTypes_.begin(), allowedFragmentTypes_.end(),
static_cast<int>(type));
268 if (findloc == allowedFragmentTypes_.end())
270 std::stringstream errmsg;
271 errmsg <<
"Error: artdaq fragment appears to have type "
272 << type <<
", not found in the allowed fragment types list";
274 TLOG(TLVL_ERROR) << errmsg.str();
275 if (quitOnFragmentIntegrityProblem_)
277 throw cet::exception(
"ListenTransferWrapper") << errmsg.str();
static void CleanUpGlobals()
Clean up statically-allocated Manager class instances.
virtual ~ListenTransferWrapper()
ListenTransferWrapper Destructor.
std::unordered_map< artdaq::Fragment::type_t, std::unique_ptr< artdaq::Fragments > > receiveMessages()
Receive all messsages for an event from ArtdaqSharedMemoryService.
std::unique_ptr< artdaq::TransferInterface > MakeTransferPlugin(const fhicl::ParameterSet &pset, const std::string &plugin_label, TransferInterface::Role role)
Load a TransferInterface plugin.
This TransferInterface is a Receiver.
Value that is to be returned when a Transfer plugin determines that no more data will be arriving...
artdaq::FragmentPtrs receiveMessage()
Receive a Fragment from the TransferInterface, and send it to art.
volatile std::sig_atomic_t gListenSignalStatus
Stores singal from signal handler.
For code clarity, things checking for successful receive should check retval >= NO_RANK_INFO.
ListenTransferWrapper(const fhicl::ParameterSet &pset)
ListenTransferWrapper Constructor.