1 #define TRACE_NAME "TransferWrapper"
3 #include "artdaq/ArtModules/detail/TransferWrapper.hh"
4 #include "artdaq/TransferPlugins/MakeTransferPlugin.hh"
5 #include "artdaq/ExternalComms/MakeCommanderPlugin.hh"
6 #include "artdaq/DAQdata/NetMonHeader.hh"
7 #include "artdaq/DAQdata/Globals.hh"
8 #include "artdaq-core/Utilities/ExceptionHandler.hh"
9 #include "artdaq-core/Data/Fragment.hh"
11 #include "cetlib/BasicPluginFactory.h"
12 #include "cetlib_except/exception.h"
13 #include "fhiclcpp/ParameterSet.h"
15 #include <TBufferFile.h>
32 void signal_handler(
int signal)
34 gSignalStatus = signal;
38 timeoutInUsecs_(pset.get<std::size_t>(
"timeoutInUsecs", 100000))
39 , dispatcherHost_(pset.get<std::string>(
"dispatcherHost",
"localhost"))
40 , dispatcherPort_(pset.get<std::string>(
"dispatcherPort",
"5266"))
41 , serverUrl_(pset.get<std::string>(
"server_url",
"http://" + dispatcherHost_ +
":" + dispatcherPort_ +
"/RPC2"))
42 , maxEventsBeforeInit_(pset.get<std::size_t>(
"maxEventsBeforeInit", 5))
43 , allowedFragmentTypes_(pset.get<std::vector<int>>(
"allowedFragmentTypes", { 226, 227, 229 }))
44 , quitOnFragmentIntegrityProblem_(pset.get<
bool>(
"quitOnFragmentIntegrityProblem",
true))
45 , monitorRegistered_(
false)
47 std::signal(SIGINT, signal_handler);
55 ExceptionHandler(ExceptionHandlerRethrow::yes,
56 "TransferWrapper: failure in call to MakeTransferPlugin");
59 fhicl::ParameterSet new_pset(pset);
60 if (!new_pset.has_key(
"server_url")) {
61 new_pset.put<std::string>(
"server_url", serverUrl_);
64 auto dispatcherConfig = pset.get<fhicl::ParameterSet>(
"dispatcher_config");
71 TLOG(TLVL_INFO) <<
"Attempting to register this monitor (\"" << transfer_->uniqueLabel()
72 <<
"\") with the dispatcher aggregator" ;
74 auto status = commander_->send_register_monitor(dispatcherConfig.to_string());
76 TLOG(TLVL_INFO) <<
"Response from dispatcher is \"" << status <<
"\"" ;
78 if (status ==
"Success")
80 monitorRegistered_ =
true;
85 TLOG(TLVL_WARNING) <<
"Error in TransferWrapper: attempt to register with dispatcher did not result in the \"Success\" response" ;
94 std::unique_ptr<artdaq::Fragment> fragmentPtr;
95 bool receivedFragment =
false;
96 static bool initialized =
false;
97 static size_t fragments_received = 0;
99 while (
true && !gSignalStatus)
101 fragmentPtr = std::make_unique<artdaq::Fragment>();
103 while (!receivedFragment)
107 TLOG(TLVL_INFO) <<
"Ctrl-C appears to have been hit" ;
114 auto result = transfer_->receiveFragment(*fragmentPtr, timeoutInUsecs_);
118 receivedFragment =
true;
119 fragments_received++;
121 static size_t cntr = 1;
122 auto mod = ++cntr % 10;
124 if (mod == 1) suffix =
"-st";
125 if (mod == 2) suffix =
"-nd";
126 if (mod == 3) suffix =
"-rd";
127 TLOG(TLVL_INFO) <<
"Received " << cntr << suffix <<
" event, "
128 <<
"seqID == " << fragmentPtr->sequenceID()
129 <<
", type == " << fragmentPtr->typeString() ;
134 TLOG(TLVL_ERROR) <<
"Transfer Plugin disconnected or other unrecoverable error. Shutting down.";
140 TLOG(TLVL_WARNING) <<
"Timeout occurred in call to transfer_->receiveFragmentFrom; will try again" ;
146 ExceptionHandler(ExceptionHandlerRethrow::yes,
147 "Problem receiving data in TransferWrapper::receiveMessage");
151 if (fragmentPtr->type() == artdaq::Fragment::EndOfDataFragmentType)
162 extractTBufferFile(*fragmentPtr, msg);
166 ExceptionHandler(ExceptionHandlerRethrow::yes,
167 "Problem extracting TBufferFile from artdaq::Fragment in TransferWrapper::receiveMessage");
170 checkIntegrity(*fragmentPtr);
172 if (initialized || fragmentPtr->type() == artdaq::Fragment::InitFragmentType)
179 receivedFragment =
false;
181 if (fragments_received > maxEventsBeforeInit_)
183 throw cet::exception(
"TransferWrapper") <<
"First " << maxEventsBeforeInit_ <<
184 " events received did not include the \"Init\" event containing necessary info for art; exiting...";
192 artdaq::TransferWrapper::extractTBufferFile(
const artdaq::Fragment& fragment,
193 std::unique_ptr<TBufferFile>& tbuffer)
196 char* buffer = (
char *)malloc(header->
data_length);
197 memcpy(buffer, fragment.dataBeginBytes(), header->
data_length);
200 tbuffer.reset(
new TBufferFile(TBuffer::kRead, header->
data_length, buffer, kTRUE, 0));
204 artdaq::TransferWrapper::checkIntegrity(
const artdaq::Fragment& fragment)
const
206 const size_t artdaqheader = artdaq::detail::RawFragmentHeader::num_words() *
207 sizeof(artdaq::detail::RawFragmentHeader::RawDataType);
208 const size_t payload =
static_cast<size_t>(fragment.dataEndBytes() - fragment.dataBeginBytes());
210 const size_t totalsize = fragment.sizeBytes();
212 const size_t type =
static_cast<size_t>(fragment.type());
214 if (totalsize != artdaqheader + metadata + payload)
216 std::stringstream errmsg;
217 errmsg <<
"Error: artdaq fragment of type " <<
218 fragment.typeString() <<
", sequence ID " <<
219 fragment.sequenceID() <<
220 " has internally inconsistent measures of its size, signalling data corruption: in bytes," <<
221 " total size = " << totalsize <<
", artdaq fragment header = " << artdaqheader <<
222 ", metadata = " << metadata <<
", payload = " << payload;
224 TLOG(TLVL_ERROR) << errmsg.str() ;
226 if (quitOnFragmentIntegrityProblem_)
228 throw cet::exception(
"TransferWrapper") << errmsg.str();
236 auto findloc = std::find(allowedFragmentTypes_.begin(), allowedFragmentTypes_.end(),
static_cast<int>(type));
238 if (findloc == allowedFragmentTypes_.end())
240 std::stringstream errmsg;
241 errmsg <<
"Error: artdaq fragment appears to have type "
242 << type <<
", not found in the allowed fragment types list";
244 TLOG(TLVL_ERROR) << errmsg.str() ;
245 if (quitOnFragmentIntegrityProblem_)
247 throw cet::exception(
"TransferWrapper") << errmsg.str();
257 artdaq::TransferWrapper::unregisterMonitor()
259 if (!monitorRegistered_)
261 throw cet::exception(
"TransferWrapper") <<
262 "The function to unregister the monitor was called, but the monitor doesn't appear to be registered";
268 TLOG(TLVL_INFO) <<
"Requesting that this monitor (" << transfer_->uniqueLabel()
269 <<
") be unregistered from the dispatcher aggregator";
271 auto status = commander_->send_unregister_monitor(transfer_->uniqueLabel());
274 TLOG(TLVL_INFO) <<
"Response from dispatcher is \""
277 if (status ==
"Success")
279 monitorRegistered_ =
false;
282 else if (status ==
"busy")
286 throw cet::exception(
"TransferWrapper") <<
"Error in TransferWrapper: attempt to unregister with dispatcher did not result in the \"Success\" response";
295 if (monitorRegistered_)
303 ExceptionHandler(ExceptionHandlerRethrow::no,
304 "An exception occurred when trying to unregister monitor during TransferWrapper's destruction");
Commandable is the base class for all artdaq components which implement the artdaq state machine...
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.
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.
std::unique_ptr< artdaq::CommanderInterface > MakeCommanderPlugin(const fhicl::ParameterSet &commander_pset, artdaq::Commandable &commandable)
Load a CommanderInterface plugin.
Value that is to be returned when a Transfer plugin determines that no more data will be arriving...
For code clarity, things checking for successful receive should check retval >= RECV_SUCCESS.