LCOV - code coverage report
Current view: top level - artdaq/Application - BoardReaderApp.cc (source / functions) Coverage Total Hit
Test: artdaq.info.cleaned Lines: 0.0 % 194 0
Test Date: 2026-10-29 00:35:58 Functions: 0.0 % 23 0

            Line data    Source code
       1              : #include "artdaq/DAQdata/Globals.hh"
       2              : #define TRACE_NAME (app_name + "_BoardReaderApp").c_str()  // NOLINT
       3              : 
       4              : #include "artdaq-core/Utilities/ExceptionHandler.hh"
       5              : #include "artdaq/Application/BoardReaderApp.hh"
       6              : 
       7              : #include <boost/lexical_cast.hpp>
       8              : 
       9              : #include <memory>
      10              : #include <string>
      11              : 
      12            0 : artdaq::BoardReaderApp::BoardReaderApp()
      13            0 :     : fragment_receiver_ptr_(nullptr)
      14              : {
      15            0 : }
      16              : 
      17              : // *******************************************************************
      18              : // *** The following methods implement the state machine operations.
      19              : // *******************************************************************
      20              : 
      21            0 : bool artdaq::BoardReaderApp::do_initialize(fhicl::ParameterSet const& pset, uint64_t timeout, uint64_t timestamp)
      22              : {
      23            0 :         report_string_ = "";
      24            0 :         external_request_status_ = true;
      25              : 
      26              :         // in the following block, we first destroy the existing BoardReader
      27              :         // instance, then create a new one.  Doing it in one step does not
      28              :         // produce the desired result since that creates a new instance and
      29              :         // then deletes the old one, and we need the opposite order.
      30            0 :         TLOG(TLVL_DEBUG + 32) << "Initializing first deleting old instance " << static_cast<void*>(fragment_receiver_ptr_.get());
      31            0 :         fragment_receiver_ptr_.reset(nullptr);
      32            0 :         fragment_receiver_ptr_ = std::make_unique<BoardReaderCore>(*this);
      33            0 :         TLOG(TLVL_DEBUG + 32) << "Initializing new BoardReaderCore at " << static_cast<void*>(fragment_receiver_ptr_.get()) << " with pset " << pset.to_string();
      34              :         try
      35              :         {
      36            0 :                 external_request_status_ = fragment_receiver_ptr_->initialize(pset, timeout, timestamp);
      37              :         }
      38            0 :         catch (const std::exception& ex)
      39              :         {
      40            0 :                 external_request_status_ = false;
      41            0 :                 report_string_ = "Error initializing " + app_name + ": " + ex.what();
      42            0 :                 return false;
      43            0 :         }
      44            0 :         catch (...)
      45              :         {
      46            0 :                 external_request_status_ = false;
      47            0 :                 report_string_ = "Error initializing " + app_name + " (unknown exception)";
      48            0 :                 return false;
      49            0 :         }
      50            0 :         if (!external_request_status_)
      51              :         {
      52            0 :                 auto core_error = fragment_receiver_ptr_->GetLastInitError();
      53            0 :                 if (!core_error.empty())
      54              :                 {
      55            0 :                         report_string_ = "Error initializing " + app_name + ": " + core_error;
      56              :                 }
      57              :                 else
      58              :                 {
      59            0 :                         report_string_ = "Error initializing ";
      60            0 :                         report_string_.append(app_name + " ");
      61            0 :                         report_string_.append("with ParameterSet = \"" + pset.to_string() + "\".");
      62              :                 }
      63            0 :         }
      64              : 
      65            0 :         TLOG(TLVL_DEBUG + 32) << "do_initialize(fhicl::ParameterSet, uint64_t, uint64_t): "
      66            0 :                               << "Done initializing.";
      67            0 :         return external_request_status_;
      68              : }
      69              : 
      70            0 : bool artdaq::BoardReaderApp::do_start(art::RunID id, uint64_t timeout, uint64_t timestamp)
      71              : {
      72            0 :         report_string_ = "";
      73            0 :         if (timeout == 0)
      74              :         {
      75            0 :                 timeout = 3600;  // seconds
      76              :         }
      77            0 :         fragment_receiver_ptr_->SetStartTransitionTimeout(timeout);
      78            0 :         external_request_status_ = true;
      79              : 
      80            0 :         boost::thread::attributes attrs;
      81            0 :         attrs.set_stack_size(4096 * 2000);  // 8 MB
      82              :         try
      83              :         {
      84            0 :                 fragment_output_thread_ = boost::thread(attrs, boost::bind(&BoardReaderCore::send_fragments, fragment_receiver_ptr_.get()));
      85              :                 char tname[16];                                                // Size 16 - see man page pthread_setname_np(3) and/or prctl(2)
      86            0 :                 snprintf(tname, sizeof(tname) - 1, "%d-FragOutput", my_rank);  // NOLINT
      87            0 :                 tname[sizeof(tname) - 1] = '\0';                               // assure term. snprintf is not too evil :)
      88            0 :                 auto handle = fragment_output_thread_.native_handle();
      89            0 :                 pthread_setname_np(handle, tname);
      90            0 :                 fragment_input_thread_ = boost::thread(attrs, boost::bind(&BoardReaderCore::receive_fragments, fragment_receiver_ptr_.get()));
      91            0 :                 snprintf(tname, sizeof(tname) - 1, "%d-FragInput", my_rank);  // NOLINT
      92            0 :                 tname[sizeof(tname) - 1] = '\0';                              // assure term. snprintf is not too evil :)
      93            0 :                 handle = fragment_input_thread_.native_handle();
      94            0 :                 pthread_setname_np(handle, tname);
      95              :         }
      96            0 :         catch (const boost::exception& e)
      97              :         {
      98            0 :                 std::stringstream exception_string;
      99            0 :                 exception_string << "Caught boost::exception starting Fragment Processing threads: " << boost::diagnostic_information(e) << ", errno=" << errno;
     100              : 
     101            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, exception_string.str());
     102            0 :         }
     103              : 
     104            0 :         auto start_wait = std::chrono::steady_clock::now();
     105            0 :         while (!fragment_receiver_ptr_->GetSenderThreadActive() || !fragment_receiver_ptr_->GetReceiverThreadActive())
     106              :         {
     107            0 :                 if (TimeUtils::GetElapsedTime(start_wait) > timeout)
     108              :                 {
     109            0 :                         TLOG(TLVL_ERROR) << "Timeout occurred waiting for BoardReaderCore threads to start. Timeout = " << timeout << " s, Time waited = " << TimeUtils::GetElapsedTime(start_wait) << " s,"
     110            0 :                                          << " Receiver ready: " << std::boolalpha << fragment_receiver_ptr_->GetReceiverThreadActive() << ", Sender ready: " << fragment_receiver_ptr_->GetSenderThreadActive();
     111            0 :                         external_request_status_ = false;
     112            0 :                         break;
     113              :                 }
     114            0 :                 usleep(10000);
     115              :         }
     116              : 
     117              :         // Only if starting threads successful
     118            0 :         if (external_request_status_)
     119              :         {
     120            0 :                 external_request_status_ = fragment_receiver_ptr_->start(id, timeout, timestamp);
     121              :         }
     122              : 
     123            0 :         if (!external_request_status_)
     124              :         {
     125            0 :                 report_string_ = "Error starting ";
     126            0 :                 report_string_.append(app_name + " ");
     127            0 :                 report_string_.append("for run number ");
     128            0 :                 report_string_.append(boost::lexical_cast<std::string>(id.run()));
     129            0 :                 report_string_.append(", timeout ");
     130            0 :                 report_string_.append(boost::lexical_cast<std::string>(timeout));
     131            0 :                 report_string_.append(", timestamp ");
     132            0 :                 report_string_.append(boost::lexical_cast<std::string>(timestamp));
     133            0 :                 report_string_.append(".");
     134              :         }
     135              : 
     136            0 :         return external_request_status_;
     137            0 : }
     138              : 
     139            0 : bool artdaq::BoardReaderApp::do_stop(uint64_t timeout, uint64_t timestamp)
     140              : {
     141            0 :         report_string_ = "";
     142            0 :         external_request_status_ = fragment_receiver_ptr_->stop(timeout, timestamp);
     143            0 :         if (!external_request_status_)
     144              :         {
     145            0 :                 report_string_ = "Error stopping ";
     146            0 :                 report_string_.append(app_name + ".");
     147            0 :                 return false;
     148              :         }
     149            0 :         if (fragment_input_thread_.joinable())
     150              :         {
     151            0 :                 TLOG(TLVL_DEBUG + 32) << "Joining fragment input (Generator) thread";
     152            0 :                 fragment_input_thread_.join();
     153              :         }
     154            0 :         if (fragment_output_thread_.joinable())
     155              :         {
     156            0 :                 TLOG(TLVL_DEBUG + 32) << "Joining fragment output (Sender) thread";
     157            0 :                 fragment_output_thread_.join();
     158              :         }
     159              : 
     160            0 :         TLOG(TLVL_DEBUG + 32) << "BoardReader Stopped. Getting run statistics";
     161            0 :         int number_of_fragments_sent = -1;
     162            0 :         if (fragment_receiver_ptr_)
     163              :         {
     164            0 :                 number_of_fragments_sent = fragment_receiver_ptr_->GetFragmentsProcessed();
     165              :         }
     166            0 :         TLOG(TLVL_DEBUG + 32) << "do_stop(uint64_t, uint64_t): "
     167            0 :                               << "Number of fragments sent = " << number_of_fragments_sent
     168            0 :                               << ".";
     169              : 
     170            0 :         return external_request_status_;
     171              : }
     172              : 
     173            0 : bool artdaq::BoardReaderApp::do_pause(uint64_t timeout, uint64_t timestamp)
     174              : {
     175            0 :         report_string_ = "";
     176            0 :         external_request_status_ = fragment_receiver_ptr_->pause(timeout, timestamp);
     177            0 :         if (!external_request_status_)
     178              :         {
     179            0 :                 report_string_ = "Error pausing ";
     180            0 :                 report_string_.append(app_name + ".");
     181              :         }
     182              : 
     183            0 :         if (fragment_input_thread_.joinable()) fragment_input_thread_.join();
     184            0 :         if (fragment_output_thread_.joinable()) fragment_output_thread_.join();
     185            0 :         int number_of_fragments_sent = fragment_receiver_ptr_->GetFragmentsProcessed();
     186            0 :         TLOG(TLVL_DEBUG + 32) << "do_pause(uint64_t, uint64_t): "
     187            0 :                               << "Number of fragments sent = " << number_of_fragments_sent
     188            0 :                               << ".";
     189              : 
     190            0 :         return external_request_status_;
     191              : }
     192              : 
     193            0 : bool artdaq::BoardReaderApp::do_resume(uint64_t timeout, uint64_t timestamp)
     194              : {
     195            0 :         report_string_ = "";
     196            0 :         if (timeout == 0)
     197              :         {
     198            0 :                 timeout = 3600;  // seconds
     199              :         }
     200            0 :         external_request_status_ = true;
     201              : 
     202            0 :         boost::thread::attributes attrs;
     203            0 :         attrs.set_stack_size(4096 * 2000);  // 8 MB
     204              :         try
     205              :         {
     206            0 :                 fragment_output_thread_ = boost::thread(attrs, boost::bind(&BoardReaderCore::send_fragments, fragment_receiver_ptr_.get()));
     207              :                 char tname[16];                                                // Size 16 - see man page pthread_setname_np(3) and/or prctl(2)
     208            0 :                 snprintf(tname, sizeof(tname) - 1, "%d-FragOutput", my_rank);  // NOLINT
     209            0 :                 tname[sizeof(tname) - 1] = '\0';                               // assure term. snprintf is not too evil :)
     210            0 :                 auto handle = fragment_output_thread_.native_handle();
     211            0 :                 pthread_setname_np(handle, tname);
     212            0 :                 fragment_input_thread_ = boost::thread(attrs, boost::bind(&BoardReaderCore::receive_fragments, fragment_receiver_ptr_.get()));
     213              : 
     214            0 :                 snprintf(tname, sizeof(tname) - 1, "%d-FragInput", my_rank);  // NOLINT
     215            0 :                 tname[sizeof(tname) - 1] = '\0';                              // assure term. snprintf is not too evil :)
     216            0 :                 handle = fragment_input_thread_.native_handle();
     217            0 :                 pthread_setname_np(handle, tname);
     218              :         }
     219            0 :         catch (const boost::exception& e)
     220              :         {
     221            0 :                 std::stringstream exception_string;
     222            0 :                 exception_string << "Caught boost::exception starting Fragment Processing threads: " << boost::diagnostic_information(e) << ", errno=" << errno;
     223              : 
     224            0 :                 ExceptionHandler(ExceptionHandlerRethrow::yes, exception_string.str());
     225            0 :         }
     226              : 
     227            0 :         auto start_wait = std::chrono::steady_clock::now();
     228            0 :         while (!fragment_receiver_ptr_->GetSenderThreadActive() || !fragment_receiver_ptr_->GetReceiverThreadActive())
     229              :         {
     230            0 :                 if (TimeUtils::GetElapsedTimeMicroseconds(start_wait) > timeout * 1000000)
     231              :                 {
     232            0 :                         TLOG(TLVL_ERROR) << "Timeout occurred waiting for BoardReaderCore threads to start. Timeout = " << timeout << " s, Time waited = " << TimeUtils::GetElapsedTime(start_wait) << " s,"
     233            0 :                                          << " Receiver ready: " << std::boolalpha << fragment_receiver_ptr_->GetReceiverThreadActive() << ", Sender ready: " << fragment_receiver_ptr_->GetSenderThreadActive();
     234            0 :                         external_request_status_ = false;
     235            0 :                         break;
     236              :                 }
     237            0 :                 usleep(10000);
     238              :         }
     239              : 
     240              :         // Only if starting threads successful
     241            0 :         if (external_request_status_)
     242              :         {
     243            0 :                 external_request_status_ = fragment_receiver_ptr_->resume(timeout, timestamp);
     244              :         }
     245            0 :         if (!external_request_status_)
     246              :         {
     247            0 :                 report_string_ = "Error resuming ";
     248            0 :                 report_string_.append(app_name + ".");
     249              :         }
     250            0 :         return external_request_status_;
     251            0 : }
     252              : 
     253            0 : bool artdaq::BoardReaderApp::do_shutdown(uint64_t timeout)
     254              : {
     255            0 :         report_string_ = "";
     256            0 :         external_request_status_ = fragment_receiver_ptr_->shutdown(timeout);
     257              :         // 02-Jun-2018, ELF & KAB: it's very, very unlikely that the following call is needed,
     258              :         // but just in case...
     259            0 :         if (fragment_input_thread_.joinable()) fragment_input_thread_.join();
     260            0 :         if (fragment_output_thread_.joinable()) fragment_output_thread_.join();
     261            0 :         if (!external_request_status_)
     262              :         {
     263            0 :                 report_string_ = "Error shutting down ";
     264            0 :                 report_string_.append(app_name + ".");
     265              :         }
     266            0 :         return external_request_status_;
     267              : }
     268              : 
     269            0 : bool artdaq::BoardReaderApp::do_soft_initialize(fhicl::ParameterSet const& pset, uint64_t timeout, uint64_t timestamp)
     270              : {
     271            0 :         report_string_ = "";
     272            0 :         external_request_status_ = fragment_receiver_ptr_->soft_initialize(pset, timeout, timestamp);
     273            0 :         if (!external_request_status_)
     274              :         {
     275            0 :                 report_string_ = "Error soft-initializing ";
     276            0 :                 report_string_.append(app_name + " ");
     277            0 :                 report_string_.append("with ParameterSet = \"" + pset.to_string() + "\".");
     278              :         }
     279            0 :         return external_request_status_;
     280              : }
     281              : 
     282            0 : bool artdaq::BoardReaderApp::do_reinitialize(fhicl::ParameterSet const& pset, uint64_t timeout, uint64_t timestamp)
     283              : {
     284            0 :         external_request_status_ = fragment_receiver_ptr_->reinitialize(pset, timeout, timestamp);
     285            0 :         if (!external_request_status_)
     286              :         {
     287            0 :                 report_string_ = "Error reinitializing ";
     288            0 :                 report_string_.append(app_name + " ");
     289            0 :                 report_string_.append("with ParameterSet = \"" + pset.to_string() + "\".");
     290              :         }
     291            0 :         return external_request_status_;
     292              : }
     293              : 
     294            0 : void artdaq::BoardReaderApp::BootedEnter()
     295              : {
     296            0 :         TLOG(TLVL_DEBUG + 32) << "Booted state entry action called.";
     297              : 
     298              :         // the destruction of any existing BoardReaderCore has to happen in the
     299              :         // Booted Entry action rather than the Initialized Exit action because the
     300              :         // Initialized Exit action is only called after the "init" transition guard
     301              :         // condition is executed.
     302            0 :         fragment_receiver_ptr_.reset(nullptr);
     303            0 : }
     304              : 
     305            0 : bool artdaq::BoardReaderApp::do_meta_command(std::string const& command, std::string const& arg)
     306              : {
     307            0 :         external_request_status_ = fragment_receiver_ptr_->metaCommand(command, arg);
     308            0 :         if (!external_request_status_)
     309              :         {
     310            0 :                 report_string_ = "Error running meta-command on ";
     311            0 :                 report_string_.append(app_name + " ");
     312            0 :                 report_string_.append("with command = \"" + command + "\", arg = \"" + arg + "\".");
     313              :         }
     314            0 :         return external_request_status_;
     315              : }
     316              : 
     317            0 : std::string artdaq::BoardReaderApp::report(std::string const& which) const
     318              : {
     319            0 :         std::string resultString;
     320              : 
     321              :         // if all that is requested is the latest state change result, return it
     322            0 :         if (which == "transition_status")
     323              :         {
     324            0 :                 if (report_string_.length() > 0) { return report_string_; }
     325              : 
     326            0 :                 return "Success";
     327              :         }
     328              : 
     329              :         //// if there is an outstanding report/message at the Commandable/Application
     330              :         //// level, prepend that
     331              :         // if (report_string_.length() > 0) {
     332              :         //   resultString.append("*** Overall status message:\r\n");
     333              :         //   resultString.append(report_string_ + "\r\n");
     334              :         //   resultString.append("*** Requested report response:\r\n");
     335              :         // }
     336              : 
     337              :         // pass the request to the BoardReaderCore instance, if it's available
     338            0 :         if (fragment_receiver_ptr_ != nullptr)
     339              :         {
     340            0 :                 resultString.append(fragment_receiver_ptr_->report(which));
     341              :         }
     342              :         else
     343              :         {
     344            0 :                 resultString.append("This BoardReader has not yet been initialized and ");
     345            0 :                 resultString.append("therefore can not provide reporting.");
     346              :         }
     347              : 
     348            0 :         return resultString;
     349            0 : }
        

Generated by: LCOV version 2.0-1