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"
30 std::unique_ptr<artdaq::DataSenderManager> artdaq::BoardReaderCore::sender_ptr_ =
nullptr;
33 : parent_application_(parent_application)
35 , generator_ptr_(nullptr)
36 , run_id_(art::RunID::flushRun())
38 , stop_requested_(false)
39 , pause_requested_(false)
41 TLOG(TLVL_DEBUG) <<
"Constructor";
52 TLOG(TLVL_DEBUG) <<
"Destructor";
53 TLOG(TLVL_DEBUG) <<
"Stopping Request Receiver BEGIN";
54 request_receiver_ptr_.reset(
nullptr);
55 TLOG(TLVL_DEBUG) <<
"Stopping Request Receiver END";
60 TLOG(TLVL_DEBUG) <<
"initialize method called with "
61 <<
"ParameterSet = \"" << pset.to_string() <<
"\".";
64 fhicl::ParameterSet daq_pset;
67 daq_pset = pset.get<fhicl::ParameterSet>(
"daq");
72 <<
"Unable to find the DAQ parameters in the initialization "
73 <<
"ParameterSet: \"" + pset.to_string() +
"\".";
76 fhicl::ParameterSet fr_pset;
79 fr_pset = daq_pset.get<fhicl::ParameterSet>(
"fragment_receiver");
85 <<
"Unable to find the fragment_receiver parameters in the DAQ "
86 <<
"initialization ParameterSet: \"" + daq_pset.to_string() +
"\".";
91 fhicl::ParameterSet metric_pset;
94 metric_pset = daq_pset.get<fhicl::ParameterSet>(
"metrics");
99 if (metric_pset.is_empty())
101 TLOG(TLVL_INFO) <<
"No metric plugins appear to be defined";
105 metricMan->initialize(metric_pset, app_name);
109 ExceptionHandler(ExceptionHandlerRethrow::no,
110 "Error loading metrics in BoardReaderCore::initialize()");
113 if (daq_pset.has_key(
"rank"))
115 if (my_rank >= 0 && daq_pset.get<
int>(
"rank") != my_rank)
117 TLOG(TLVL_WARNING) <<
"BoardReader rank specified at startup is different than rank specified at configure! Using rank received at configure!";
119 my_rank = daq_pset.get<
int>(
"rank");
123 TLOG(TLVL_ERROR) <<
"BoardReader rank not specified at startup or in configuration! Aborting";
124 throw cet::exception(
"RankNotSpecifiedError") <<
"BoardReader rank not specified at startup or in configuration! Aborting";
128 auto frag_gen_name = fr_pset.get<std::string>(
"generator",
"");
129 if (frag_gen_name.length() == 0)
132 <<
"No fragment generator (parameter name = \"generator\") was "
133 <<
"specified in the fragment_receiver ParameterSet. The "
134 <<
"DAQ initialization PSet was \"" << daq_pset.to_string() <<
"\".";
144 std::stringstream exception_string;
145 exception_string <<
"Exception thrown during initialization of fragment generator of type \""
146 << frag_gen_name <<
"\"";
148 ExceptionHandler(ExceptionHandlerRethrow::no, exception_string.str());
150 TLOG(TLVL_DEBUG) <<
"FHiCL parameter set used to initialize the fragment generator which threw an exception: " << fr_pset.to_string();
161 std::stringstream exception_string;
162 exception_string <<
"Exception thrown during initialization of Fragment Buffer";
164 ExceptionHandler(ExceptionHandlerRethrow::no, exception_string.str());
166 TLOG(TLVL_DEBUG) <<
"FHiCL parameter set used to initialize the fragment buffer which threw an exception: " << fr_pset.to_string();
171 std::shared_ptr<RequestBuffer> request_buffer = std::make_shared<RequestBuffer>(fr_pset.get<artdaq::Fragment::sequence_id_t>(
"request_increment", 1));
175 request_receiver_ptr_.reset(
new RequestReceiver(fr_pset, request_buffer));
176 generator_ptr_->SetRequestBuffer(request_buffer);
177 fragment_buffer_ptr_->SetRequestBuffer(request_buffer);
181 ExceptionHandler(ExceptionHandlerRethrow::no,
"Exception thrown during initialization of request receiver");
183 TLOG(TLVL_DEBUG) <<
"FHiCL parameter set used to initialize the request receiver which threw an exception: " << fr_pset.to_string();
187 metricMan->setPrefix(generator_ptr_->metricsReportingInstanceName());
189 rt_priority_ = fr_pset.get<
int>(
"rt_priority", 0);
192 statsHelper_.createCollectors(fr_pset, 100, 30.0, 60.0, FRAGMENTS_PROCESSED_STAT_KEY);
195 skip_seqId_test_ = (fr_pset.get<
bool>(
"skip_seqID_test",
false) || generator_ptr_->fragmentIDs().size() > 1 || fragment_buffer_ptr_->request_mode() != RequestMode::Ignored);
197 verbose_ = fr_pset.get<
bool>(
"verbose",
true);
204 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Starting run " <<
id.run();
205 stop_requested_.store(
false);
206 pause_requested_.store(
false);
210 statsHelper_.resetStatistics();
212 fragment_buffer_ptr_->Reset(
false);
214 metricMan->do_start();
215 generator_ptr_->StartCmd(
id.run(), timeout, timestamp);
218 request_receiver_ptr_->SetRunNumber(static_cast<uint32_t>(
id.run()));
219 request_receiver_ptr_->startRequestReception();
222 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Completed the Start transition (Started run) for run " << run_id_.run()
223 <<
", timeout = " << timeout <<
", timestamp = " << timestamp;
229 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Stopping run " << run_id_.run() <<
" after " << fragment_count_ <<
" fragments.";
230 stop_requested_.store(
true);
232 TLOG(TLVL_DEBUG) <<
"Stopping Request reception BEGIN";
233 request_receiver_ptr_->stopRequestReception();
234 TLOG(TLVL_DEBUG) <<
"Stopping Request reception END";
236 TLOG(TLVL_DEBUG) <<
"Stopping CommandableFragmentGenerator BEGIN";
237 generator_ptr_->StopCmd(timeout, timestamp);
238 TLOG(TLVL_DEBUG) <<
"Stopping CommandableFragmentGenerator END";
240 TLOG(TLVL_DEBUG) <<
"Stopping FragmentBuffer";
241 fragment_buffer_ptr_->Stop();
243 TLOG(TLVL_DEBUG) <<
"Stopping DataSenderManager";
246 sender_ptr_->StopSender();
250 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Completed the Stop transition for run " << run_id_.run();
256 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Pausing run " << run_id_.run() <<
" after " << fragment_count_ <<
" fragments.";
257 pause_requested_.store(
true);
258 generator_ptr_->PauseCmd(timeout, timestamp);
259 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Completed the Pause transition for run " << run_id_.run();
265 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Resuming run " << run_id_.run();
266 pause_requested_.store(
false);
267 metricMan->do_start();
268 generator_ptr_->ResumeCmd(timeout, timestamp);
269 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Completed the Resume transition for run " << run_id_.run();
275 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Starting Shutdown transition";
276 generator_ptr_->joinThreads();
277 generator_ptr_.reset(
nullptr);
278 metricMan->shutdown();
279 TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) <<
"Completed Shutdown transition";
285 TLOG(TLVL_DEBUG) <<
"soft_initialize method called with "
286 <<
"ParameterSet = \"" << pset.to_string()
287 <<
"\". Forwarding to initialize.";
288 return initialize(pset, timeout, timestamp);
293 TLOG(TLVL_DEBUG) <<
"reinitialize method called with "
294 <<
"ParameterSet = \"" << pset.to_string()
295 <<
"\". Forwarding to initalize.";
296 return initialize(pset, timeout, timestamp);
301 if (rt_priority_ > 0)
303 #pragma GCC diagnostic push
304 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
305 sched_param s_param = {};
306 s_param.sched_priority = rt_priority_;
307 if (pthread_setschedparam(pthread_self(), SCHED_RR, &s_param))
308 TLOG(TLVL_WARNING) <<
"setting realtime priority failed";
309 #pragma GCC diagnostic pop
315 if (rt_priority_ > 0)
317 #pragma GCC diagnostic push
318 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
319 sched_param s_param = {};
320 s_param.sched_priority = rt_priority_;
321 int status = pthread_setschedparam(pthread_self(), SCHED_RR, &s_param);
325 <<
"Failed to set realtime priority to " << rt_priority_
326 <<
", return code = " << status;
328 #pragma GCC diagnostic pop
331 TLOG(TLVL_DEBUG) <<
"Waiting for first fragment.";
332 artdaq::MonitoredQuantityStats::TIME_POINT_T startTime, after_input, after_buffer;
333 artdaq::FragmentPtrs frags;
335 receiver_thread_active_ =
true;
337 auto wait_start = std::chrono::steady_clock::now();
338 while (!running_ && TimeUtils::GetElapsedTime(wait_start) < start_transition_timeout_)
344 TLOG(TLVL_ERROR) <<
"Timeout (" << start_transition_timeout_ <<
" s) while waiting for Start after receive_fragments thread started!";
345 receiver_thread_active_ =
false;
348 while (receiver_thread_active_)
350 startTime = artdaq::MonitoredQuantity::getCurrentTime();
352 TLOG(18) <<
"receive_fragments getNext start";
353 receiver_thread_active_ = generator_ptr_->getNext(frags);
354 TLOG(18) <<
"receive_fragments getNext done (receiver_thread_active_=" << receiver_thread_active_ <<
")";
362 if (!receiver_thread_active_ && generator_ptr_ && generator_ptr_->exception())
364 parent_application_.in_run_failure();
367 after_input = artdaq::MonitoredQuantity::getCurrentTime();
369 if (!receiver_thread_active_) {
break; }
370 statsHelper_.addSample(FRAGMENTS_PER_READ_STAT_KEY, frags.size());
372 if (frags.size() > 0)
374 TLOG(18) <<
"receive_fragments AddFragmentsToBuffer start";
375 fragment_buffer_ptr_->AddFragmentsToBuffer(std::move(frags));
376 TLOG(18) <<
"receive_fragments AddFragmentsToBuffer done";
379 after_buffer = artdaq::MonitoredQuantity::getCurrentTime();
380 TLOG(16) <<
"receive_fragments INPUT_WAIT=" << (after_input - startTime) <<
", BUFFER_WAIT=" << (after_buffer - after_input);
381 statsHelper_.addSample(INPUT_WAIT_STAT_KEY, after_input - startTime);
382 statsHelper_.addSample(BUFFER_WAIT_STAT_KEY, after_buffer - after_input);
383 if (statsHelper_.statsRollingWindowHasMoved()) { sendMetrics_(); }
390 metricMan->do_stop();
392 TLOG(TLVL_DEBUG) <<
"receive_fragments loop end";
396 if (rt_priority_ > 0)
398 #pragma GCC diagnostic push
399 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
400 sched_param s_param = {};
401 s_param.sched_priority = rt_priority_;
402 if (pthread_setschedparam(pthread_self(), SCHED_RR, &s_param) != 0)
404 TLOG(TLVL_WARNING) <<
"setting realtime priority failed";
406 #pragma GCC diagnostic pop
412 if (rt_priority_ > 0)
414 #pragma GCC diagnostic push
415 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
416 sched_param s_param = {};
417 s_param.sched_priority = rt_priority_;
418 int status = pthread_setschedparam(pthread_self(), SCHED_RR, &s_param);
422 <<
"Failed to set realtime priority to " << rt_priority_
423 <<
", return code = " << status;
425 #pragma GCC diagnostic pop
428 TLOG(TLVL_DEBUG) <<
"Initializing DataSenderManager. my_rank=" << my_rank;
429 sender_ptr_ = std::make_unique<artdaq::DataSenderManager>(data_pset_);
431 TLOG(TLVL_DEBUG) <<
"Waiting for first fragment.";
432 artdaq::MonitoredQuantityStats::TIME_POINT_T startTime;
434 artdaq::FragmentPtrs frags;
435 auto targetFragCount = generator_ptr_->fragmentIDs().size();
437 sender_thread_active_ =
true;
439 auto wait_start = std::chrono::steady_clock::now();
440 while (!running_ && TimeUtils::GetElapsedTime(wait_start) < start_transition_timeout_)
446 TLOG(TLVL_ERROR) <<
"Timeout (" << start_transition_timeout_ <<
" s) while waiting for Start after send_fragments thread started!";
447 sender_thread_active_ =
false;
450 while (sender_thread_active_)
452 startTime = artdaq::MonitoredQuantity::getCurrentTime();
454 TLOG(18) <<
"send_fragments applyRequests start";
455 sender_thread_active_ = fragment_buffer_ptr_->applyRequests(frags);
456 TLOG(18) <<
"send_fragments applyRequests done (sender_thread_active_=" << sender_thread_active_ <<
")";
463 if (!sender_thread_active_ && generator_ptr_ && generator_ptr_->exception())
465 parent_application_.in_run_failure();
468 delta_time = artdaq::MonitoredQuantity::getCurrentTime() - startTime;
470 TLOG(16) <<
"send_fragments REQUEST_WAIT=" << delta_time;
471 statsHelper_.addSample(REQUEST_WAIT_STAT_KEY, delta_time);
473 if (!sender_thread_active_) {
break; }
475 for (
auto& fragPtr : frags)
477 if (fragPtr ==
nullptr)
479 TLOG(TLVL_WARNING) <<
"Encountered a bad fragment pointer in fragment " << fragment_count_ <<
". "
480 <<
"This is most likely caused by a problem with the Fragment Generator!";
483 if (fragment_count_ == 0)
485 TLOG(TLVL_DEBUG) <<
"Received first Fragment from Fragment Generator, sequence ID " << fragPtr->sequenceID() <<
", size = " << fragPtr->sizeBytes() <<
" bytes.";
488 if (fragPtr->type() == Fragment::EndOfRunFragmentType || fragPtr->type() == Fragment::EndOfSubrunFragmentType || fragPtr->type() == Fragment::InitFragmentType)
491 artdaq::Fragment::sequence_id_t sequence_id = fragPtr->sequenceID();
492 statsHelper_.addSample(FRAGMENTS_PROCESSED_STAT_KEY, fragPtr->sizeBytes());
494 startTime = artdaq::MonitoredQuantity::getCurrentTime();
495 TLOG(17) <<
"send_fragments seq=" << sequence_id <<
" sendFragment start";
496 auto res = sender_ptr_->sendFragment(std::move(*fragPtr));
499 statsHelper_.addSample(OUTPUT_WAIT_STAT_KEY,
500 artdaq::MonitoredQuantity::getCurrentTime() - startTime);
504 artdaq::Fragment::sequence_id_t sequence_id = fragPtr->sequenceID();
505 SetMFIteration(
"Sequence ID " + std::to_string(sequence_id));
506 statsHelper_.addSample(FRAGMENTS_PROCESSED_STAT_KEY, fragPtr->sizeBytes());
516 if (!skip_seqId_test_ && abs(static_cast<int64_t>(sequence_id) - static_cast<int64_t>(prev_seq_id_)) > 1)
519 <<
"Missing sequence IDs: current sequence ID = "
520 << sequence_id <<
", previous sequence ID = "
521 << prev_seq_id_ <<
".";
523 prev_seq_id_ = sequence_id;
525 startTime = artdaq::MonitoredQuantity::getCurrentTime();
526 TLOG(17) <<
"send_fragments seq=" << sequence_id <<
" sendFragment start";
527 auto res = sender_ptr_->sendFragment(std::move(*fragPtr));
528 if (sender_ptr_->GetSentSequenceIDCount(sequence_id) == targetFragCount)
530 sender_ptr_->RemoveRoutingTableEntry(sequence_id);
534 statsHelper_.addSample(OUTPUT_WAIT_STAT_KEY,
535 artdaq::MonitoredQuantity::getCurrentTime() - startTime);
537 bool readyToReport = statsHelper_.readyToReport();
540 TLOG(TLVL_INFO) << buildStatisticsString_();
544 TLOG(((fragment_count_ == 1) ? TLVL_DEBUG
545 : (((fragment_count_ % 250) == 0 || readyToReport) ? 13 : 14)))
546 << ((fragment_count_ == 1)
547 ?
"Sent first Fragment"
548 :
"Sending fragment " + std::to_string(fragment_count_))
549 <<
" with SeqID " << sequence_id <<
".";
551 if (statsHelper_.statsRollingWindowHasMoved()) { sendMetrics_(); }
553 std::this_thread::yield();
556 sender_ptr_.reset(
nullptr);
561 metricMan->do_stop();
563 TLOG(TLVL_DEBUG) <<
"send_fragments loop end";
568 std::string resultString;
571 if (generator_ptr_ !=
nullptr && which !=
"core")
573 resultString = generator_ptr_->ReportCmd(which);
574 if (resultString.length() > 0) {
return resultString; }
581 std::string tmpString = app_name +
" run number = ";
582 tmpString.append(boost::lexical_cast<std::string>(run_id_.run()));
584 tmpString.append(
", Sent Fragment count = ");
585 tmpString.append(boost::lexical_cast<std::string>(fragment_count_));
587 if (!which.empty() && which !=
"core")
589 tmpString.append(
". Command=\"" + which +
"\" is not currently supported.");
596 TLOG(TLVL_DEBUG) <<
"metaCommand method called with "
597 <<
"command = \"" << command <<
"\""
598 <<
", arg = \"" << arg <<
"\""
603 return generator_ptr_->metaCommand(command, arg);
609 std::string artdaq::BoardReaderCore::buildStatisticsString_()
611 std::ostringstream oss;
612 double fragmentsGeneratedCount = 1.0;
613 double fragmentsOutputCount = 1.0;
614 oss << app_name <<
" statistics:" << std::endl;
616 oss <<
" Fragments read: ";
617 artdaq::MonitoredQuantityPtr mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(FRAGMENTS_PER_READ_STAT_KEY);
618 if (mqPtr.get() !=
nullptr)
620 artdaq::MonitoredQuantityStats stats;
621 mqPtr->getStats(stats);
622 oss << stats.recentSampleCount <<
" fragments generated at "
623 << stats.recentSampleRate <<
" reads/sec, fragment rate = "
624 << stats.recentValueRate <<
" fragments/sec, monitor window = "
625 << stats.recentDuration <<
" sec, min::max read size = "
626 << stats.recentValueMin
628 << stats.recentValueMax
630 fragmentsGeneratedCount = std::max(
double(stats.recentSampleCount), 1.0);
631 oss <<
" Average times per fragment: ";
632 if (stats.recentSampleRate > 0.0)
634 oss <<
" elapsed time = "
635 << (1.0 / stats.recentSampleRate) <<
" sec";
640 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(FRAGMENTS_PROCESSED_STAT_KEY);
641 if (mqPtr.get() !=
nullptr)
643 artdaq::MonitoredQuantityStats stats;
644 mqPtr->getStats(stats);
645 oss <<
" Fragment output statistics: "
646 << stats.recentSampleCount <<
" fragments sent at "
647 << stats.recentSampleRate <<
" fragments/sec, effective data rate = "
648 << (stats.recentValueRate *
sizeof(artdaq::RawDataType) / 1024.0 / 1024.0) <<
" MB/sec, monitor window = "
649 << stats.recentDuration <<
" sec, min::max event size = "
650 << (stats.recentValueMin *
sizeof(artdaq::RawDataType) / 1024.0 / 1024.0)
652 << (stats.recentValueMax *
sizeof(artdaq::RawDataType) / 1024.0 / 1024.0)
653 <<
" MB" << std::endl;
654 fragmentsOutputCount = std::max(
double(stats.recentSampleCount), 1.0);
665 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(INPUT_WAIT_STAT_KEY);
666 if (mqPtr.get() !=
nullptr)
668 oss <<
" Input wait time = "
669 << (mqPtr->getRecentValueSum() / fragmentsGeneratedCount) <<
" s/fragment";
671 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(BUFFER_WAIT_STAT_KEY);
672 if (mqPtr.get() != 0)
674 oss <<
", buffer wait time = "
675 << (mqPtr->getRecentValueSum() / fragmentsGeneratedCount) <<
" s/fragment";
677 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(REQUEST_WAIT_STAT_KEY);
678 if (mqPtr.get() != 0)
680 oss <<
", request wait time = "
681 << (mqPtr->getRecentValueSum() / fragmentsOutputCount) <<
" s/fragment";
684 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(OUTPUT_WAIT_STAT_KEY);
685 if (mqPtr.get() !=
nullptr)
687 oss <<
", output wait time = "
688 << (mqPtr->getRecentValueSum() / fragmentsOutputCount) <<
" s/fragment";
694 void artdaq::BoardReaderCore::sendMetrics_()
697 double fragmentCount = 1.0;
698 artdaq::MonitoredQuantityPtr mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(FRAGMENTS_PROCESSED_STAT_KEY);
699 if (mqPtr.get() !=
nullptr)
701 artdaq::MonitoredQuantityStats stats;
702 mqPtr->getStats(stats);
703 fragmentCount = std::max(
double(stats.recentSampleCount), 1.0);
704 metricMan->sendMetric(
"Fragment Count", stats.fullSampleCount,
"fragments", 1, MetricMode::LastPoint);
705 metricMan->sendMetric(
"Fragment Rate", stats.recentSampleRate,
"fragments/sec", 1, MetricMode::Average);
706 metricMan->sendMetric(
"Average Fragment Size", (stats.recentValueAverage *
sizeof(artdaq::RawDataType)),
"bytes/fragment", 2, MetricMode::Average);
707 metricMan->sendMetric(
"Data Rate", (stats.recentValueRate *
sizeof(artdaq::RawDataType)),
"bytes/sec", 2, MetricMode::Average);
718 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(INPUT_WAIT_STAT_KEY);
719 if (mqPtr.get() !=
nullptr)
721 metricMan->sendMetric(
"Avg Input Wait Time", (mqPtr->getRecentValueSum() / fragmentCount),
"seconds/fragment", 3, MetricMode::Average);
724 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(BUFFER_WAIT_STAT_KEY);
725 if (mqPtr.get() != 0)
727 metricMan->sendMetric(
"Avg Buffer Wait Time", (mqPtr->getRecentValueSum() / fragmentCount),
"seconds/fragment", 3, MetricMode::Average);
729 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(REQUEST_WAIT_STAT_KEY);
730 if (mqPtr.get() != 0)
732 metricMan->sendMetric(
"Avg Request Response Wait Time", (mqPtr->getRecentValueSum() / fragmentCount),
"seconds/fragment", 3, MetricMode::Average);
734 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(OUTPUT_WAIT_STAT_KEY);
735 if (mqPtr.get() !=
nullptr)
737 metricMan->sendMetric(
"Avg Output Wait Time", (mqPtr->getRecentValueSum() / fragmentCount),
"seconds/fragment", 3, MetricMode::Average);
740 mqPtr = artdaq::StatisticsCollection::getInstance().getMonitoredQuantity(FRAGMENTS_PER_READ_STAT_KEY);
741 if (mqPtr.get() !=
nullptr)
743 metricMan->sendMetric(
"Avg Frags Per Read", mqPtr->getRecentValueAverage(),
"fragments/read", 4, MetricMode::Average);
static const std::string BUFFER_WAIT_STAT_KEY
Key for the Fragment Buffer Wait MonitoredQuantity.
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 FRAGMENTS_PER_READ_STAT_KEY
Key for the Fragments Per Read MonitoredQuantity.
static const std::string REQUEST_WAIT_STAT_KEY
Key for the Request Buffer Wait 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.