2 #include "artdaq/DAQdata/Globals.hh"
3 #define TRACE_NAME (app_name + "_BoardReaderCore").c_str()
5 #include "artdaq-core/Data/Fragment.hh"
6 #include "artdaq-core/Utilities/ExceptionHandler.hh"
7 #include "artdaq/Application/BoardReaderCore.hh"
8 #include "artdaq/Application/TaskType.hh"
9 #include "artdaq/Generators/makeCommandableFragmentGenerator.hh"
16 #include "canvas/Utilities/Exception.h"
17 #include "cetlib_except/exception.h"
23 const std::string artdaq::BoardReaderCore::BUFFER_WAIT_STAT_KEY(
"BoardReaderCoreBufferWaitTime");
24 const std::string artdaq::BoardReaderCore::REQUEST_WAIT_STAT_KEY(
"BoardReaderCoreRequestWaitTime");
32 std::unique_ptr<artdaq::DataSenderManager> artdaq::BoardReaderCore::sender_ptr_ =
nullptr;
35 : parent_application_(parent_application)
37 , generator_ptr_(nullptr)
38 , run_id_(art::RunID::flushRun())
40 , stop_requested_(false)
41 , pause_requested_(false)
43 TLOG(TLVL_DEBUG) <<
"Constructor";
55 TLOG(TLVL_DEBUG) <<
"Destructor";
56 TLOG(TLVL_DEBUG) <<
"Stopping Request Receiver BEGIN";
57 request_receiver_ptr_.reset(
nullptr);
58 TLOG(TLVL_DEBUG) <<
"Stopping Request Receiver END";
63 TLOG(TLVL_DEBUG) <<
"initialize method called with "
64 <<
"ParameterSet = \"" << pset.to_string() <<
"\".";
67 fhicl::ParameterSet daq_pset;
70 daq_pset = pset.get<fhicl::ParameterSet>(
"daq");
75 <<
"Unable to find the DAQ parameters in the initialization "
76 <<
"ParameterSet: \"" + pset.to_string() +
"\".";
79 fhicl::ParameterSet fr_pset;
82 fr_pset = daq_pset.get<fhicl::ParameterSet>(
"fragment_receiver");
88 <<
"Unable to find the fragment_receiver parameters in the DAQ "
89 <<
"initialization ParameterSet: \"" + daq_pset.to_string() +
"\".";
94 fhicl::ParameterSet metric_pset;
97 metric_pset = daq_pset.get<fhicl::ParameterSet>(
"metrics");
102 if (metric_pset.is_empty())
104 TLOG(TLVL_INFO) <<
"No metric plugins appear to be defined";
108 metricMan->initialize(metric_pset, app_name);
112 ExceptionHandler(ExceptionHandlerRethrow::no,
113 "Error loading metrics in BoardReaderCore::initialize()");
116 if (daq_pset.has_key(
"rank"))
118 if (my_rank >= 0 && daq_pset.get<
int>(
"rank") != my_rank)
120 TLOG(TLVL_WARNING) <<
"BoardReader rank specified at startup is different than rank specified at configure! Using rank received at configure!";
122 my_rank = daq_pset.get<
int>(
"rank");
126 TLOG(TLVL_ERROR) <<
"BoardReader rank not specified at startup or in configuration! Aborting";
127 throw cet::exception(
"RankNotSpecifiedError") <<
"BoardReader rank not specified at startup or in configuration! Aborting";
131 auto frag_gen_name = fr_pset.get<std::string>(
"generator",
"");
132 if (frag_gen_name.length() == 0)
135 <<
"No fragment generator (parameter name = \"generator\") was "
136 <<
"specified in the fragment_receiver ParameterSet. The "
137 <<
"DAQ initialization PSet was \"" << daq_pset.to_string() <<
"\".";
147 std::stringstream exception_string;
148 exception_string <<
"Exception thrown during initialization of fragment generator of type \""
149 << frag_gen_name <<
"\"";
151 ExceptionHandler(ExceptionHandlerRethrow::no, exception_string.str());
153 TLOG(TLVL_DEBUG) <<
"FHiCL parameter set used to initialize the fragment generator which threw an exception: " << fr_pset.to_string();
164 std::stringstream exception_string;
165 exception_string <<
"Exception thrown during initialization of Fragment Buffer";
167 ExceptionHandler(ExceptionHandlerRethrow::no, exception_string.str());
169 TLOG(TLVL_DEBUG) <<
"FHiCL parameter set used to initialize the fragment buffer which threw an exception: " << fr_pset.to_string();
174 std::shared_ptr<RequestBuffer> request_buffer = std::make_shared<RequestBuffer>(fr_pset.get<artdaq::Fragment::sequence_id_t>(
"request_increment", 1));
178 request_receiver_ptr_.reset(
new RequestReceiver(fr_pset, request_buffer));
179 generator_ptr_->SetRequestBuffer(request_buffer);
180 fragment_buffer_ptr_->SetRequestBuffer(request_buffer);
184 ExceptionHandler(ExceptionHandlerRethrow::no,
"Exception thrown during initialization of request receiver");
186 TLOG(TLVL_DEBUG) <<
"FHiCL parameter set used to initialize the request receiver which threw an exception: " << fr_pset.to_string();
191 metricMan->setPrefix(generator_ptr_->metricsReportingInstanceName());
193 rt_priority_ = fr_pset.get<
int>(
"rt_priority", 0);
196 statsHelper_.createCollectors(fr_pset, 100, 30.0, 60.0, FRAGMENTS_PROCESSED_STAT_KEY);
199 skip_seqId_test_ = (generator_ptr_->fragmentIDs().size() > 1 || fragment_buffer_ptr_->request_mode() != RequestMode::Ignored);
201 verbose_ = fr_pset.get<
bool>(
"verbose",
true);
208 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Starting run " <<
id.run();
209 stop_requested_.store(
false);
210 pause_requested_.store(
false);
214 statsHelper_.resetStatistics();
216 fragment_buffer_ptr_->Reset(
false);
218 metricMan->do_start();
219 generator_ptr_->StartCmd(
id.run(), timeout, timestamp);
222 request_receiver_ptr_->SetRunNumber(static_cast<uint32_t>(
id.run()));
223 request_receiver_ptr_->startRequestReception();
225 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Completed the Start transition (Started run) for run " << run_id_.run()
226 <<
", timeout = " << timeout <<
", timestamp = " << timestamp;
232 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Stopping run " << run_id_.run() <<
" after " << fragment_count_ <<
" fragments.";
233 stop_requested_.store(
true);
235 TLOG(TLVL_DEBUG) <<
"Stopping Request reception BEGIN";
236 request_receiver_ptr_->stopRequestReception();
237 TLOG(TLVL_DEBUG) <<
"Stopping Request reception END";
239 TLOG(TLVL_DEBUG) <<
"Stopping CommandableFragmentGenerator BEGIN";
240 generator_ptr_->StopCmd(timeout, timestamp);
241 TLOG(TLVL_DEBUG) <<
"Stopping CommandableFragmentGenerator END";
243 TLOG(TLVL_DEBUG) <<
"Stopping FragmentBuffer";
244 fragment_buffer_ptr_->Stop();
246 TLOG(TLVL_DEBUG) <<
"Stopping DataSenderManager";
249 sender_ptr_->StopSender();
252 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Completed the Stop transition for run " << run_id_.run();
258 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Pausing run " << run_id_.run() <<
" after " << fragment_count_ <<
" fragments.";
259 pause_requested_.store(
true);
260 generator_ptr_->PauseCmd(timeout, timestamp);
261 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Completed the Pause transition for run " << run_id_.run();
267 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Resuming run " << run_id_.run();
268 pause_requested_.store(
false);
269 metricMan->do_start();
270 generator_ptr_->ResumeCmd(timeout, timestamp);
271 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Completed the Resume transition for run " << run_id_.run();
277 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Starting Shutdown transition";
278 generator_ptr_->joinThreads();
279 generator_ptr_.reset(
nullptr);
280 metricMan->shutdown();
281 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Completed Shutdown transition";
287 TLOG(TLVL_DEBUG) <<
"soft_initialize method called with "
288 <<
"ParameterSet = \"" << pset.to_string()
289 <<
"\". Forwarding to initialize.";
290 return initialize(pset, timeout, timestamp);
295 TLOG(TLVL_DEBUG) <<
"reinitialize method called with "
296 <<
"ParameterSet = \"" << pset.to_string()
297 <<
"\". Forwarding to initalize.";
298 return initialize(pset, timeout, timestamp);
303 if (rt_priority_ > 0)
305 #pragma GCC diagnostic push
306 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
307 sched_param s_param = {};
308 s_param.sched_priority = rt_priority_;
309 if (pthread_setschedparam(pthread_self(), SCHED_RR, &s_param))
310 TLOG(TLVL_WARNING) <<
"setting realtime priority failed";
311 #pragma GCC diagnostic pop
317 if (rt_priority_ > 0)
319 #pragma GCC diagnostic push
320 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
321 sched_param s_param = {};
322 s_param.sched_priority = rt_priority_;
323 int status = pthread_setschedparam(pthread_self(), SCHED_RR, &s_param);
327 <<
"Failed to set realtime priority to " << rt_priority_
328 <<
", return code = " << status;
330 #pragma GCC diagnostic pop
333 TLOG(TLVL_DEBUG) <<
"Waiting for first fragment.";
334 artdaq::MonitoredQuantityStats::TIME_POINT_T startTime, after_input, after_buffer;
335 artdaq::FragmentPtrs frags;
341 startTime = artdaq::MonitoredQuantity::getCurrentTime();
343 TLOG(18) <<
"receive_fragments getNext start";
344 active = generator_ptr_->getNext(frags);
345 TLOG(18) <<
"receive_fragments getNext done (active=" << active <<
")";
352 if (!active && generator_ptr_ && generator_ptr_->exception())
354 parent_application_.in_run_failure();
357 after_input = artdaq::MonitoredQuantity::getCurrentTime();
360 if (!active) {
break; }
361 statsHelper_.addSample(FRAGMENTS_PER_READ_STAT_KEY, frags.size());
363 if (frags.size() > 0)
365 TLOG(18) <<
"receive_fragments AddFragmentsToBuffer start";
366 fragment_buffer_ptr_->AddFragmentsToBuffer(std::move(frags));
367 TLOG(18) <<
"receive_fragments AddFragmentsToBuffer done";
370 after_buffer = artdaq::MonitoredQuantity::getCurrentTime();
371 TLOG(16) <<
"receive_fragments INPUT_WAIT=" << (after_input - startTime) <<
", BUFFER_WAIT=" << (after_buffer - after_input);
372 statsHelper_.addSample(INPUT_WAIT_STAT_KEY, after_input - startTime);
373 statsHelper_.addSample(BUFFER_WAIT_STAT_KEY, after_buffer - after_input);
374 if (statsHelper_.statsRollingWindowHasMoved()) { sendMetrics_(); }
381 metricMan->do_stop();
383 TLOG(TLVL_DEBUG) <<
"receive_fragments loop end";
387 if (rt_priority_ > 0)
389 #pragma GCC diagnostic push
390 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
391 sched_param s_param = {};
392 s_param.sched_priority = rt_priority_;
393 if (pthread_setschedparam(pthread_self(), SCHED_RR, &s_param) != 0)
395 TLOG(TLVL_WARNING) <<
"setting realtime priority failed";
397 #pragma GCC diagnostic pop
403 if (rt_priority_ > 0)
405 #pragma GCC diagnostic push
406 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
407 sched_param s_param = {};
408 s_param.sched_priority = rt_priority_;
409 int status = pthread_setschedparam(pthread_self(), SCHED_RR, &s_param);
413 <<
"Failed to set realtime priority to " << rt_priority_
414 <<
", return code = " << status;
416 #pragma GCC diagnostic pop
419 TLOG(TLVL_DEBUG) <<
"Initializing DataSenderManager. my_rank=" << my_rank;
420 sender_ptr_ = std::make_unique<artdaq::DataSenderManager>(data_pset_);
422 TLOG(TLVL_DEBUG) <<
"Waiting for first fragment.";
423 artdaq::MonitoredQuantityStats::TIME_POINT_T startTime;
425 artdaq::FragmentPtrs frags;
426 auto targetFragCount = generator_ptr_->fragmentIDs().size();
432 startTime = artdaq::MonitoredQuantity::getCurrentTime();
434 TLOG(18) <<
"send_fragments applyRequests start";
435 active = fragment_buffer_ptr_->applyRequests(frags);
436 TLOG(18) <<
"send_fragments applyRequests done (active=" << active <<
")";
443 if (!active && generator_ptr_ && generator_ptr_->exception())
445 parent_application_.in_run_failure();
448 delta_time = artdaq::MonitoredQuantity::getCurrentTime() - startTime;
450 TLOG(16) <<
"send_fragments REQUEST_WAIT=" << delta_time;
451 statsHelper_.addSample(REQUEST_WAIT_STAT_KEY, delta_time);
453 if (!active) {
break; }
455 for (
auto& fragPtr : frags)
457 if (fragPtr ==
nullptr)
459 TLOG(TLVL_WARNING) <<
"Encountered a bad fragment pointer in fragment " << fragment_count_ <<
". "
460 <<
"This is most likely caused by a problem with the Fragment Generator!";
463 if (fragment_count_ == 0)
465 TLOG(TLVL_DEBUG) <<
"Received first Fragment from Fragment Generator, sequence ID " << fragPtr->sequenceID() <<
", size = " << fragPtr->sizeBytes() <<
" bytes.";
468 if (fragPtr->type() == Fragment::EndOfRunFragmentType || fragPtr->type() == Fragment::EndOfSubrunFragmentType || fragPtr->type() == Fragment::InitFragmentType)
471 artdaq::Fragment::sequence_id_t sequence_id = fragPtr->sequenceID();
472 statsHelper_.addSample(FRAGMENTS_PROCESSED_STAT_KEY, fragPtr->sizeBytes());
474 startTime = artdaq::MonitoredQuantity::getCurrentTime();
475 TLOG(17) <<
"send_fragments seq=" << sequence_id <<
" sendFragment start";
476 auto res = sender_ptr_->sendFragment(std::move(*fragPtr));
479 statsHelper_.addSample(OUTPUT_WAIT_STAT_KEY,
480 artdaq::MonitoredQuantity::getCurrentTime() - startTime);
484 artdaq::Fragment::sequence_id_t sequence_id = fragPtr->sequenceID();
485 SetMFIteration(
"Sequence ID " + std::to_string(sequence_id));
486 statsHelper_.addSample(FRAGMENTS_PROCESSED_STAT_KEY, fragPtr->sizeBytes());
496 if (!skip_seqId_test_ && abs(static_cast<int64_t>(sequence_id) - static_cast<int64_t>(prev_seq_id_)) > 1)
499 <<
"Missing sequence IDs: current sequence ID = "
500 << sequence_id <<
", previous sequence ID = "
501 << prev_seq_id_ <<
".";
503 prev_seq_id_ = sequence_id;
505 startTime = artdaq::MonitoredQuantity::getCurrentTime();
506 TLOG(17) <<
"send_fragments seq=" << sequence_id <<
" sendFragment start";
507 auto res = sender_ptr_->sendFragment(std::move(*fragPtr));
508 if (sender_ptr_->GetSentSequenceIDCount(sequence_id) == targetFragCount)
510 sender_ptr_->RemoveRoutingTableEntry(sequence_id);
514 statsHelper_.addSample(OUTPUT_WAIT_STAT_KEY,
515 artdaq::MonitoredQuantity::getCurrentTime() - startTime);
517 bool readyToReport = statsHelper_.readyToReport();
520 TLOG(TLVL_INFO) << buildStatisticsString_();
524 TLOG(((fragment_count_ == 1) ? TLVL_DEBUG
525 : (((fragment_count_ % 250) == 0 || readyToReport) ? 13 : 14)))
526 << ((fragment_count_ == 1)
527 ?
"Sent first Fragment"
528 :
"Sending fragment " + std::to_string(fragment_count_))
529 <<
" with SeqID " << sequence_id <<
".";
531 if (statsHelper_.statsRollingWindowHasMoved()) { sendMetrics_(); }
533 std::this_thread::yield();
536 sender_ptr_.reset(
nullptr);
541 metricMan->do_stop();
543 TLOG(TLVL_DEBUG) <<
"send_fragments loop end";
548 std::string resultString;
551 if (generator_ptr_ !=
nullptr && which !=
"core")
553 resultString = generator_ptr_->ReportCmd(which);
554 if (resultString.length() > 0) {
return resultString; }
561 std::string tmpString = app_name +
" run number = ";
562 tmpString.append(boost::lexical_cast<std::string>(run_id_.run()));
564 tmpString.append(
", Sent Fragment count = ");
565 tmpString.append(boost::lexical_cast<std::string>(fragment_count_));
567 if (!which.empty() && which !=
"core")
569 tmpString.append(
". Command=\"" + which +
"\" is not currently supported.");
576 TLOG(TLVL_DEBUG) <<
"metaCommand method called with "
577 <<
"command = \"" << command <<
"\""
578 <<
", arg = \"" << arg <<
"\""
583 return generator_ptr_->metaCommand(command, arg);
589 std::string artdaq::BoardReaderCore::buildStatisticsString_()
591 std::ostringstream oss;
592 double fragmentsGeneratedCount = 1.0;
593 double fragmentsOutputCount = 1.0;
594 oss << app_name <<
" statistics:" << std::endl;
596 oss <<
" Fragments read: ";
597 artdaq::MonitoredQuantityPtr mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(FRAGMENTS_PER_READ_STAT_KEY);
598 if (mqPtr.get() !=
nullptr)
600 artdaq::MonitoredQuantityStats stats;
601 mqPtr->getStats(stats);
602 oss << stats.recentSampleCount <<
" fragments generated at "
603 << stats.recentSampleRate <<
" reads/sec, fragment rate = "
604 << stats.recentValueRate <<
" fragments/sec, monitor window = "
605 << stats.recentDuration <<
" sec, min::max read size = "
606 << stats.recentValueMin
608 << stats.recentValueMax
610 fragmentsGeneratedCount = std::max(
double(stats.recentSampleCount), 1.0);
611 oss <<
" Average times per fragment: ";
612 if (stats.recentSampleRate > 0.0)
614 oss <<
" elapsed time = "
615 << (1.0 / stats.recentSampleRate) <<
" sec";
620 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(FRAGMENTS_PROCESSED_STAT_KEY);
621 if (mqPtr.get() !=
nullptr)
623 artdaq::MonitoredQuantityStats stats;
624 mqPtr->getStats(stats);
625 oss <<
" Fragment output statistics: "
626 << stats.recentSampleCount <<
" fragments sent at "
627 << stats.recentSampleRate <<
" fragments/sec, effective data rate = "
628 << (stats.recentValueRate *
sizeof(artdaq::RawDataType) / 1024.0 / 1024.0) <<
" MB/sec, monitor window = "
629 << stats.recentDuration <<
" sec, min::max event size = "
630 << (stats.recentValueMin *
sizeof(artdaq::RawDataType) / 1024.0 / 1024.0)
632 << (stats.recentValueMax *
sizeof(artdaq::RawDataType) / 1024.0 / 1024.0)
633 <<
" MB" << std::endl;
634 fragmentsOutputCount = std::max(
double(stats.recentSampleCount), 1.0);
645 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(INPUT_WAIT_STAT_KEY);
646 if (mqPtr.get() !=
nullptr)
648 oss <<
" Input wait time = "
649 << (mqPtr->getRecentValueSum() / fragmentsGeneratedCount) <<
" s/fragment";
651 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(BUFFER_WAIT_STAT_KEY);
652 if (mqPtr.get() != 0)
654 oss <<
", buffer wait time = "
655 << (mqPtr->getRecentValueSum() / fragmentsGeneratedCount) <<
" s/fragment";
657 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(REQUEST_WAIT_STAT_KEY);
658 if (mqPtr.get() != 0)
660 oss <<
", request wait time = "
661 << (mqPtr->getRecentValueSum() / fragmentsOutputCount) <<
" s/fragment";
664 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(BRSYNC_WAIT_STAT_KEY);
665 if (mqPtr.get() !=
nullptr)
667 oss <<
", BRsync wait time = "
668 << (mqPtr->getRecentValueSum() / fragmentsOutputCount) <<
" s/fragment";
671 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(OUTPUT_WAIT_STAT_KEY);
672 if (mqPtr.get() !=
nullptr)
674 oss <<
", output wait time = "
675 << (mqPtr->getRecentValueSum() / fragmentsOutputCount) <<
" s/fragment";
682 void artdaq::BoardReaderCore::sendMetrics_()
685 double fragmentCount = 1.0;
686 artdaq::MonitoredQuantityPtr mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(FRAGMENTS_PROCESSED_STAT_KEY);
687 if (mqPtr.get() !=
nullptr)
689 artdaq::MonitoredQuantityStats stats;
690 mqPtr->getStats(stats);
691 fragmentCount = std::max(
double(stats.recentSampleCount), 1.0);
692 metricMan->sendMetric(
"Fragment Count", stats.fullSampleCount,
"fragments", 1, MetricMode::LastPoint);
693 metricMan->sendMetric(
"Fragment Rate", stats.recentSampleRate,
"fragments/sec", 1, MetricMode::Average);
694 metricMan->sendMetric(
"Average Fragment Size", (stats.recentValueAverage *
sizeof(artdaq::RawDataType)),
"bytes/fragment", 2, MetricMode::Average);
695 metricMan->sendMetric(
"Data Rate", (stats.recentValueRate *
sizeof(artdaq::RawDataType)),
"bytes/sec", 2, MetricMode::Average);
706 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(INPUT_WAIT_STAT_KEY);
707 if (mqPtr.get() !=
nullptr)
709 metricMan->sendMetric(
"Avg Input Wait Time", (mqPtr->getRecentValueSum() / fragmentCount),
"seconds/fragment", 3, MetricMode::Average);
712 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(BUFFER_WAIT_STAT_KEY);
713 if (mqPtr.get() != 0)
715 metricMan->sendMetric(
"Avg Buffer Wait Time", (mqPtr->getRecentValueSum() / fragmentCount),
"seconds/fragment", 3, MetricMode::Average);
717 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(REQUEST_WAIT_STAT_KEY);
718 if (mqPtr.get() != 0)
720 metricMan->sendMetric(
"Avg Request Response Wait Time", (mqPtr->getRecentValueSum() / fragmentCount),
"seconds/fragment", 3, MetricMode::Average);
722 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(BRSYNC_WAIT_STAT_KEY);
723 if (mqPtr.get() !=
nullptr)
725 metricMan->sendMetric(
"Avg BoardReader Sync Wait Time", (mqPtr->getRecentValueSum() / fragmentCount),
"seconds/fragment", 3, MetricMode::Average);
728 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(OUTPUT_WAIT_STAT_KEY);
729 if (mqPtr.get() !=
nullptr)
731 metricMan->sendMetric(
"Avg Output Wait Time", (mqPtr->getRecentValueSum() / fragmentCount),
"seconds/fragment", 3, MetricMode::Average);
734 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(FRAGMENTS_PER_READ_STAT_KEY);
735 if (mqPtr.get() !=
nullptr)
737 metricMan->sendMetric(
"Avg Frags Per Read", mqPtr->getRecentValueAverage(),
"fragments/read", 4, MetricMode::Average);
void addMonitoredQuantityName(std::string const &statKey)
Add a MonitoredQuantity name to the list.
Commandable is the base class for all artdaq components which implement the artdaq state machine...
bool initialize(fhicl::ParameterSet const &pset, uint64_t timeout, uint64_t timestamp)
Initialize the BoardReaderCore.
static const std::string FRAGMENTS_PROCESSED_STAT_KEY
Key for the Fragments Processed MonitoredQuantity.
bool reinitialize(fhicl::ParameterSet const &pset, uint64_t timeout, uint64_t timestamp)
Reinitialize the BoardReader. No-Op.
static const std::string INPUT_WAIT_STAT_KEY
Key for the Input Wait MonitoredQuantity.
bool stop(uint64_t timeout, uint64_t timestamp)
Stop the BoardReader, and the CommandableFragmentGenerator.
virtual ~BoardReaderCore()
BoardReaderCore Destructor.
static std::string CopyStatusToString(CopyStatus in)
Convert a CopyStatus variable to its string represenatation
BoardReaderCore(Commandable &parent_application)
BoardReaderCore Constructor.
std::unique_ptr< CommandableFragmentGenerator > makeCommandableFragmentGenerator(std::string const &generator_plugin_spec, fhicl::ParameterSet const &ps)
Load a CommandableFragmentGenerator plugin.
FragmentBuffer is a FragmentGenerator-derived abstract class that defines the interface for a Fragmen...
Receive data requests and make them available to CommandableFragmentGenerator or other interested par...
static const std::string BRSYNC_WAIT_STAT_KEY
Key for the Sync Wait MonitoredQuantity.
static const std::string FRAGMENTS_PER_READ_STAT_KEY
Key for the Fragments Per Read MonitoredQuantity.
static const std::string OUTPUT_WAIT_STAT_KEY
Key for the Output Wait MonitoredQuantity.
void send_fragments()
Main working loop of the BoardReaderCore, pt. 2.
bool soft_initialize(fhicl::ParameterSet const &pset, uint64_t timeout, uint64_t timestamp)
Soft-Initialize the BoardReader. No-Op.
std::string report(std::string const &which) const
Send a report on a given run-time quantity.
bool shutdown(uint64_t timeout)
Shutdown the BoardReader, and the CommandableFragmentGenerator.
bool start(art::RunID id, uint64_t timeout, uint64_t timestamp)
Start the BoardReader, and the CommandableFragmentGenerator.
bool resume(uint64_t timeout, uint64_t timestamp)
Resume the BoardReader, and the CommandableFragmentGenerator.
void receive_fragments()
Main working loop of the BoardReaderCore.
bool pause(uint64_t timeout, uint64_t timestamp)
Pause the BoardReader, and the CommandableFragmentGenerator.
bool metaCommand(std::string const &command, std::string const &arg)
Run a user-defined command on the CommandableFragmentGenerator.