1 #include "artdaq/TransferPlugins/TransferWrapper.hh"
2 #include "artdaq/TransferPlugins/MakeTransferPlugin.hh"
3 #include "artdaq/DAQdata/NetMonHeader.hh"
4 #include "artdaq/DAQdata/Globals.hh"
5 #include "artdaq-core/Utilities/ExceptionHandler.hh"
6 #include "artdaq-core/Data/Fragment.hh"
8 #include "cetlib/BasicPluginFactory.h"
9 #include "fhiclcpp/ParameterSet.h"
10 #pragma GCC diagnostic push
11 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
12 #include <xmlrpc-c/girerr.hpp>
13 #include <xmlrpc-c/base.hpp>
14 #include <xmlrpc-c/client_simple.hpp>
15 #pragma GCC diagnostic pop
17 #include "TBufferFile.h"
34 void signal_handler(
int signal)
36 gSignalStatus = signal;
40 timeoutInUsecs_(pset.get<std::size_t>(
"timeoutInUsecs", 100000))
41 , dispatcherHost_(pset.get<std::string>(
"dispatcherHost"))
42 , dispatcherPort_(pset.get<std::string>(
"dispatcherPort"))
43 , serverUrl_(
"http://" + dispatcherHost_ +
":" + dispatcherPort_ +
"/RPC2")
44 , maxEventsBeforeInit_(pset.get<std::size_t>(
"maxEventsBeforeInit", 5))
45 , allowedFragmentTypes_(pset.get<std::vector<int>>(
"allowedFragmentTypes", {226, 227, 229}))
46 , quitOnFragmentIntegrityProblem_(pset.get<
bool>(
"quitOnFragmentIntegrityProblem",
true))
47 , debugLevel_(pset.get<std::size_t>(
"debugLevel", 0))
48 , monitorRegistered_(
false)
50 std::signal(SIGINT, signal_handler);
58 ExceptionHandler(ExceptionHandlerRethrow::yes,
59 "TransferWrapper: failure in call to MakeTransferPlugin");
62 xmlrpc_c::clientSimple myClient;
63 xmlrpc_c::value result;
65 TLOG_INFO(
"TransferWrapper") <<
"Attempting to register this monitor (\"" << transfer_->uniqueLabel()
66 <<
"\") with the dispatcher aggregator" << TLOG_ENDL;
70 myClient.call(serverUrl_,
"daq.register_monitor",
"s", &result, pset.to_string().c_str());
74 std::stringstream errmsg;
75 errmsg <<
"Problem attempting XML-RPC call on host " << dispatcherHost_
76 <<
", port " << dispatcherPort_ <<
"; possible causes are malformed FHiCL or nonexistent process at requested port";
77 ExceptionHandler(ExceptionHandlerRethrow::yes,
81 const std::string status = xmlrpc_c::value_string(result);
83 TLOG_INFO(
"TransferWrapper") <<
"Response from dispatcher is \""
84 << status <<
"\"" << TLOG_ENDL;
86 if (status ==
"Success")
88 monitorRegistered_ =
true;
92 throw cet::exception(
"TransferWrapper") <<
"Error in TransferWrapper: attempt to register with dispatcher did not result in the \"Success\" response";
98 std::unique_ptr<artdaq::Fragment> fragmentPtr;
99 bool receivedFragment =
false;
100 static bool initialized =
false;
101 static size_t fragments_received = 0;
103 while (
true && !gSignalStatus)
105 fragmentPtr = std::make_unique<artdaq::Fragment>();
107 while (!receivedFragment)
111 TLOG_INFO(
"TransferWrapper") <<
"Ctrl-C appears to have been hit" << TLOG_ENDL;
118 auto result = transfer_->receiveFragment(*fragmentPtr, timeoutInUsecs_);
122 receivedFragment =
true;
123 fragments_received++;
125 static size_t cntr = 1;
129 TLOG_INFO(
"TransferWrapper") <<
"Received " << cntr++ <<
"-th event, "
130 <<
"seqID == " << fragmentPtr->sequenceID()
131 <<
", type == " <<
static_cast<int>(fragmentPtr->type()) << TLOG_ENDL;
139 TLOG_WARNING(
"TransferWrapper") <<
"Timeout occurred in call to transfer_->receiveFragmentFrom; will try again" << TLOG_ENDL;
145 ExceptionHandler(ExceptionHandlerRethrow::yes,
146 "Problem receiving data in TransferWrapper::receiveMessage");
152 extractTBufferFile(*fragmentPtr, msg);
156 ExceptionHandler(ExceptionHandlerRethrow::yes,
157 "Problem extracting TBufferFile from artdaq::Fragment in TransferWrapper::receiveMessage");
160 checkIntegrity(*fragmentPtr);
162 if (initialized || fragmentPtr->type() == artdaq::Fragment::InitFragmentType)
169 receivedFragment =
false;
171 if (fragments_received > maxEventsBeforeInit_)
173 throw cet::exception(
"TransferWrapper") <<
"First " << maxEventsBeforeInit_ <<
174 " events received did not include the \"Init\" event containing necessary info for art; exiting...";
182 artdaq::TransferWrapper::extractTBufferFile(
const artdaq::Fragment& fragment,
183 std::unique_ptr<TBufferFile>& tbuffer)
186 char* buffer = (
char *)malloc(header->
data_length);
187 memcpy(buffer, fragment.dataBeginBytes(), header->
data_length);
190 tbuffer.reset(
new TBufferFile(TBuffer::kRead, header->
data_length, buffer, kTRUE, 0));
194 artdaq::TransferWrapper::checkIntegrity(
const artdaq::Fragment& fragment)
const
196 const size_t artdaqheader = artdaq::detail::RawFragmentHeader::num_words() *
197 sizeof(artdaq::detail::RawFragmentHeader::RawDataType);
198 const size_t payload =
static_cast<size_t>(fragment.dataEndBytes() - fragment.dataBeginBytes());
200 const size_t totalsize = fragment.sizeBytes();
202 const size_t type =
static_cast<size_t>(fragment.type());
204 if (totalsize != artdaqheader + metadata + payload)
206 std::stringstream errmsg;
207 errmsg <<
"Error: artdaq fragment of type " <<
208 type <<
", sequence ID " <<
209 fragment.sequenceID() <<
210 " has internally inconsistent measures of its size, signalling data corruption: in bytes," <<
211 " total size = " << totalsize <<
", artdaq fragment header = " << artdaqheader <<
212 ", metadata = " << metadata <<
", payload = " << payload;
214 TLOG_ERROR(
"TransferWrapper") << errmsg.str() << TLOG_ENDL;
216 if (quitOnFragmentIntegrityProblem_)
218 throw cet::exception(
"TransferWrapper") << errmsg.str();
226 auto findloc = std::find(allowedFragmentTypes_.begin(), allowedFragmentTypes_.end(),
static_cast<int>(type));
228 if (findloc == allowedFragmentTypes_.end())
230 std::stringstream errmsg;
231 errmsg <<
"Error: artdaq fragment appears to have type "
232 << type <<
", not found in the allowed fragment types list";
234 TLOG_ERROR(
"TransferWrapper") << errmsg.str() << TLOG_ENDL;
235 if (quitOnFragmentIntegrityProblem_)
237 throw cet::exception(
"TransferWrapper") << errmsg.str();
247 artdaq::TransferWrapper::unregisterMonitor()
249 if (!monitorRegistered_)
251 throw cet::exception(
"TransferWrapper") <<
252 "The function to unregister the monitor was called, but the monitor doesn't appear to be registered";
255 TLOG_INFO(
"TransferWrapper") <<
"Requesting that this monitor (" << transfer_->uniqueLabel()
256 <<
") be unregistered from the dispatcher aggregator" << TLOG_ENDL;
258 xmlrpc_c::clientSimple myClient;
259 xmlrpc_c::value result;
263 myClient.call(serverUrl_,
"daq.unregister_monitor",
"s", &result, (transfer_->uniqueLabel()).c_str());
267 std::stringstream errmsg;
268 errmsg <<
"Problem attempting to unregister monitor via XML-RPC call on host " << dispatcherHost_
269 <<
", port " << dispatcherPort_ <<
"; possible causes are that the monitor label \""
270 << transfer_->uniqueLabel()
271 <<
"\" is unrecognized by contacted process or process at requested port doesn't exist";
272 ExceptionHandler(ExceptionHandlerRethrow::no,
276 const std::string status = xmlrpc_c::value_string(result);
278 TLOG_INFO(
"TransferWrapper") <<
"Response from dispatcher is \""
279 << status <<
"\"" << TLOG_ENDL;
281 if (status ==
"Success")
283 monitorRegistered_ =
false;
287 throw cet::exception(
"TransferWrapper") <<
"Error in TransferWrapper: attempt to unregister with dispatcher did not result in the \"Success\" response";
294 if (monitorRegistered_)
302 ExceptionHandler(ExceptionHandlerRethrow::no,
303 "An exception occurred when trying to unregister monitor during TransferWrapper's destruction");
void receiveMessage(std::unique_ptr< TBufferFile > &msg)
Receive a Fragment from the TransferInterface, and send it to art.
TransferWrapper(const fhicl::ParameterSet &pset)
TransferWrapper Constructor.
virtual ~TransferWrapper()
TransferWrapper Destructor.
static const int RECV_TIMEOUT
Value to be returned upon receive timeout. Because receivers otherwise return rank, this is also the limit on the number of ranks that artdaq currently supports.
This TransferInterface is a Receiver.
std::unique_ptr< artdaq::TransferInterface > MakeTransferPlugin(const fhicl::ParameterSet &pset, std::string plugin_label, TransferInterface::Role role)
Load a TransferInterface plugin.
volatile std::sig_atomic_t gSignalStatus
Stores singal from signal handler.