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

            Line data    Source code
       1              : #define TRACE_NAME "CompositeDriver"
       2              : 
       3              : #include "artdaq/Generators/CommandableFragmentGenerator.hh"
       4              : #include "artdaq/Generators/GeneratorMacros.hh"
       5              : #include "artdaq/Generators/makeCommandableFragmentGenerator.hh"
       6              : #include "canvas/Utilities/Exception.h"
       7              : #include "cetlib_except/exception.h"
       8              : 
       9              : #include <boost/algorithm/string.hpp>
      10              : 
      11              : namespace artdaq {
      12              : /**
      13              :  * \brief CompositeDriver handles a set of lower-level generators
      14              :  *
      15              :  * When multiple CommandableFragmentGenerators are needed by a single BoardReader, CompositeDriver may be used to provide
      16              :  * a single interface to all of them.
      17              :  */
      18              : class CompositeDriver : public CommandableFragmentGenerator
      19              : {
      20              : public:
      21              :         /**
      22              :          * \brief CompositeDriver Constructor
      23              :          * \param ps ParameterSet used to configure CompositeDriver
      24              :          *
      25              :          * \verbatim
      26              :          * CompositeDriver accepts the following Parameters:
      27              :          * "generator_config_list" (REQUIRED): A FHiCL sequence of FHiCL tables, each one configuring
      28              :          * a CommandableFragmentGenerator instance.
      29              :          * \endverbatim
      30              :          */
      31              :         explicit CompositeDriver(fhicl::ParameterSet const& ps);
      32              : 
      33              :         /**
      34              :          * \brief Destructor. Calls the destructors for each configured CommandableFragmentGenerator
      35              :          */
      36              :         virtual ~CompositeDriver() noexcept;
      37              : 
      38              :         /**
      39              :          * \brief Start all configured CommandableFragmentGenerators
      40              :          */
      41              :         void start() override;
      42              : 
      43              :         /**
      44              :          * \brief Call non-locked stop methods for all configured CommandableFragmentGenerators
      45              :          */
      46              :         void stopNoMutex() override;
      47              : 
      48              :         /**
      49              :          * \brief Call stop methods for all configured CommandableFragmentGenerators. Currently handled by stopNoMutex
      50              :          */
      51              :         void stop() override;
      52              : 
      53              :         /**
      54              :          * \brief Pause all configured CommandableFragmentGenerators
      55              :          */
      56              :         void pause() override;
      57              : 
      58              :         /**
      59              :          * \brief Resume all configured CommandableFragmentGenerators
      60              :          */
      61              :         void resume() override;
      62              : 
      63              : private:
      64              :         CompositeDriver(CompositeDriver const&) = delete;
      65              :         CompositeDriver(CompositeDriver&&) = delete;
      66              :         CompositeDriver& operator=(CompositeDriver const&) = delete;
      67              :         CompositeDriver& operator=(CompositeDriver&&) = delete;
      68              : 
      69              :         std::vector<artdaq::Fragment::fragment_id_t> fragmentIDs() override;
      70              : 
      71              :         bool getNext_(artdaq::FragmentPtrs& frags) override;
      72              : 
      73              :         bool makeChildGenerator_(fhicl::ParameterSet const&);
      74              : 
      75              :         std::vector<std::unique_ptr<CommandableFragmentGenerator>> generator_list_;
      76              :         std::vector<bool> generator_active_list_;
      77              : };
      78              : }  // namespace artdaq
      79            0 : artdaq::CompositeDriver::CompositeDriver(const fhicl::ParameterSet& ps)
      80            0 :     : CommandableFragmentGenerator(ps)
      81              : {
      82              :         auto psetList =
      83            0 :             ps.get<std::vector<fhicl::ParameterSet>>("generator_config_list");
      84            0 :         for (const auto& pset : psetList)
      85              :         {
      86            0 :                 if (!makeChildGenerator_(pset))
      87              :                 {
      88            0 :                         TLOG(TLVL_ERROR) << "Unable to create child generator for PSet= \"" << pset.to_string() << "\"";
      89            0 :                         throw cet::exception("CompositeDriver")  // NOLINT(cert-err60-cpp)
      90              :                             << "Unable to create child generator for PSet= \""
      91            0 :                             << pset.to_string() << "\"";
      92              :                 }
      93              :         }
      94              : 
      95            0 :         std::string compositeMetricName;
      96            0 :         for (auto& generator : generator_list_)
      97              :         {
      98            0 :                 if (compositeMetricName.length() > 0) { compositeMetricName.append(", "); }
      99            0 :                 compositeMetricName.append(generator->metricsReportingInstanceName());
     100              :         }
     101            0 :         this->metricsReportingInstanceName(compositeMetricName);
     102            0 : }
     103              : 
     104            0 : artdaq::CompositeDriver::~CompositeDriver() noexcept
     105              : {
     106              :         // 15-Feb-2014, KAB - explicitly destruct the generators so that
     107              :         // we can control the order in which they are destructed
     108            0 :         size_t listSize = generator_list_.size();
     109            0 :         while (listSize > 0)
     110              :         {
     111            0 :                 --listSize;
     112              :                 try
     113              :                 {
     114            0 :                         generator_list_.resize(listSize);
     115              :                 }
     116            0 :                 catch (...)
     117              :                 {
     118            0 :                         TLOG(TLVL_ERROR)
     119            0 :                             << "Unknown exception when destructing the generator at index "
     120            0 :                             << (listSize + 1);
     121            0 :                 }
     122              :         }
     123            0 : }
     124              : 
     125            0 : void artdaq::CompositeDriver::start()
     126              : {
     127            0 :         for (auto&& idx : generator_active_list_)
     128              :         {
     129            0 :                 idx = true;
     130              :         }
     131            0 :         for (auto& generator : generator_list_)
     132              :         {
     133            0 :                 generator->StartCmd(run_number(), timeout(), timestamp());
     134              :         }
     135            0 : }
     136              : 
     137            0 : void artdaq::CompositeDriver::stopNoMutex()
     138              : {
     139            0 :         std::vector<std::unique_ptr<CommandableFragmentGenerator>>::reverse_iterator riter;
     140            0 :         for (riter = generator_list_.rbegin(); riter != generator_list_.rend(); ++riter)
     141              :         {
     142            0 :                 (*riter)->StopCmd(timeout(), timestamp());
     143              :         }
     144            0 : }
     145              : 
     146            0 : void artdaq::CompositeDriver::stop()
     147              : {
     148              :         // 02/17/16 ELF: This logic is now handled in stopNoMutex
     149              :         /*
     150              :         std::vector<std::unique_ptr<CommandableFragmentGenerator>>::reverse_iterator riter;
     151              :         for (riter = generator_list_.rbegin(); riter != generator_list_.rend(); ++riter) {
     152              :           (*riter)->StopCmd( timeout(), timestamp() );
     153              :         }
     154              :         */
     155            0 : }
     156              : 
     157            0 : void artdaq::CompositeDriver::pause()
     158              : {
     159            0 :         std::vector<std::unique_ptr<CommandableFragmentGenerator>>::reverse_iterator riter;
     160            0 :         for (riter = generator_list_.rbegin(); riter != generator_list_.rend(); ++riter)
     161              :         {
     162            0 :                 (*riter)->PauseCmd(timeout(), timestamp());
     163              :         }
     164            0 : }
     165              : 
     166            0 : void artdaq::CompositeDriver::resume()
     167              : {
     168            0 :         for (auto&& idx : generator_active_list_)
     169              :         {
     170            0 :                 idx = true;
     171              :         }
     172            0 :         for (auto& generator : generator_list_)
     173              :         {
     174            0 :                 generator->ResumeCmd(timeout(), timestamp());
     175              :         }
     176            0 : }
     177              : 
     178            0 : std::vector<artdaq::Fragment::fragment_id_t> artdaq::CompositeDriver::fragmentIDs()
     179              : {
     180            0 :         std::vector<artdaq::Fragment::fragment_id_t> workList;
     181            0 :         for (auto& idx : generator_list_)
     182              :         {
     183              :                 std::vector<artdaq::Fragment::fragment_id_t> tempList =
     184            0 :                     idx->fragmentIDs();
     185            0 :                 workList.insert(workList.end(), tempList.begin(), tempList.end());
     186            0 :         }
     187            0 :         return workList;
     188            0 : }
     189              : 
     190            0 : bool artdaq::CompositeDriver::getNext_(artdaq::FragmentPtrs& frags)
     191              : {
     192            0 :         bool anyGeneratorIsActive = false;
     193            0 :         for (size_t idx = 0; idx < generator_list_.size(); ++idx)
     194              :         {
     195            0 :                 if (generator_active_list_[idx])
     196              :                 {
     197            0 :                         bool status = generator_list_[idx]->getNext(frags);
     198              : 
     199              :                         // 08-May-2015, KAB & JCF: if the generator getNext() method returns
     200              :                         // false (which indicates that the data flow has stopped) *and* the
     201              :                         // reason that it has stopped is because there was an exception that
     202              :                         // wasn't handled by the experiment-specific FragmentGenerator class,
     203              :                         // we throw an exception so that the process will move to the
     204              :                         // InRunError state. We do our best to try to reproduce the original
     205              :                         // exception message.
     206            0 :                         if (!status && generator_list_[idx]->exception())
     207              :                         {
     208              :                                 std::string reportString =
     209            0 :                                     generator_list_[idx]->ReportCmd("latest_exception");
     210            0 :                                 if (std::string::npos !=
     211            0 :                                     boost::algorithm::to_lower_copy(reportString).find("exception"))
     212              :                                 {
     213            0 :                                         TLOG(TLVL_ERROR) << "The FragmentGenerator for " << generator_list_[idx]->metricsReportingInstanceName() << " threw an exception: " << reportString;
     214            0 :                                         throw cet::exception("CompositeDriver_generator")  // NOLINT(cert-err60-cpp)
     215              :                                             << "The FragmentGenerator for "
     216            0 :                                             << generator_list_[idx]->metricsReportingInstanceName()
     217            0 :                                             << " threw an exception: " << reportString;
     218              :                                 }
     219              : 
     220            0 :                                 TLOG(TLVL_ERROR) << "The FragmentGenerator for " << generator_list_[idx]->metricsReportingInstanceName() << " threw an exception.";
     221            0 :                                 throw cet::exception("CompositeDriver_generator")  // NOLINT(cert-err60-cpp)
     222              :                                     << "The FragmentGenerator for "
     223            0 :                                     << generator_list_[idx]->metricsReportingInstanceName()
     224            0 :                                     << " threw an exception.";
     225            0 :                         }
     226            0 :                         generator_active_list_[idx] = status;
     227            0 :                         if (status) { anyGeneratorIsActive = true; }
     228              :                 }
     229              :         }
     230            0 :         return anyGeneratorIsActive;
     231              : }
     232              : 
     233            0 : bool artdaq::CompositeDriver::makeChildGenerator_(fhicl::ParameterSet const& pset)
     234              : {
     235              :         // pull out the relevant parts of the ParameterSet, if needed
     236            0 :         auto daq_pset = pset.get<fhicl::ParameterSet>("daq", pset);
     237            0 :         auto fr_pset = daq_pset.get<fhicl::ParameterSet>("fragment_receiver", daq_pset);
     238              : 
     239              :         // create the requested FragmentGenerator
     240            0 :         auto frag_gen_name = fr_pset.get<std::string>("generator", "");
     241            0 :         if (frag_gen_name.length() == 0)
     242              :         {
     243            0 :                 TLOG(TLVL_ERROR)
     244            0 :                     << "No fragment generator (parameter name = \"generator\") was "
     245            0 :                     << "specified in the fragment_receiver ParameterSet.  The "
     246            0 :                     << "DAQ initialization PSet was \"" << daq_pset.to_string() << "\".";
     247            0 :                 return false;
     248              :         }
     249              : 
     250            0 :         std::unique_ptr<artdaq::CommandableFragmentGenerator> tmp_gen_ptr;
     251              :         try
     252              :         {
     253            0 :                 tmp_gen_ptr = artdaq::makeCommandableFragmentGenerator(frag_gen_name, fr_pset);
     254              :         }
     255            0 :         catch (art::Exception& excpt)
     256              :         {
     257            0 :                 TLOG(TLVL_ERROR)
     258            0 :                     << "Exception creating a FragmentGenerator of type \""
     259            0 :                     << frag_gen_name << "\" with parameter set \"" << fr_pset.to_string()
     260            0 :                     << "\", exception = " << excpt;
     261            0 :                 return false;
     262            0 :         }
     263            0 :         catch (cet::exception& excpt)
     264              :         {
     265            0 :                 TLOG(TLVL_ERROR)
     266            0 :                     << "Exception creating a FragmentGenerator of type \""
     267            0 :                     << frag_gen_name << "\" with parameter set \"" << fr_pset.to_string()
     268            0 :                     << "\", exception = " << excpt;
     269            0 :                 return false;
     270            0 :         }
     271            0 :         catch (...)
     272              :         {
     273            0 :                 TLOG(TLVL_ERROR)
     274            0 :                     << "Unknown exception creating a FragmentGenerator of type \""
     275            0 :                     << frag_gen_name << "\" with parameter set \"" << fr_pset.to_string()
     276            0 :                     << "\".";
     277            0 :                 return false;
     278            0 :         }
     279              : 
     280            0 :         std::unique_ptr<CommandableFragmentGenerator> generator_ptr;
     281            0 :         generator_ptr.reset(nullptr);
     282              :         try
     283              :         {
     284            0 :                 auto tmp_cmdablegen_bareptr = tmp_gen_ptr.release();
     285            0 :                 if (tmp_cmdablegen_bareptr != nullptr)
     286              :                 {
     287            0 :                         generator_ptr.reset(tmp_cmdablegen_bareptr);
     288              :                 }
     289              :         }
     290              :         catch (...)
     291              :         {}
     292            0 :         if (!generator_ptr)
     293              :         {
     294            0 :                 TLOG(TLVL_ERROR)
     295            0 :                     << "Error: The requested fragment generator type (" << frag_gen_name
     296            0 :                     << ") is not a CommandableFragmentGenerator, and only "
     297            0 :                     << "CommandableFragmentGenerators are currently supported.";
     298            0 :                 return false;
     299              :         }
     300              : 
     301            0 :         generator_list_.push_back(std::move(generator_ptr));
     302            0 :         generator_active_list_.push_back(true);
     303            0 :         return true;
     304            0 : }
     305              : 
     306            0 : DEFINE_ARTDAQ_COMMANDABLE_GENERATOR(artdaq::CompositeDriver)
        

Generated by: LCOV version 2.0-1