00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #define TRACE_NAME "artdaqDriver"
00012
00013 #include "art/Framework/Art/artapp.h"
00014 #include "artdaq-core/Generators/FragmentGenerator.hh"
00015 #include "artdaq-core/Data/Fragment.hh"
00016 #include "artdaq-core/Utilities/ExceptionHandler.hh"
00017 #include "artdaq/DAQdata/GenericFragmentSimulator.hh"
00018
00019 #include "artdaq/DAQdata/Globals.hh"
00020 #include "artdaq-core/Generators/makeFragmentGenerator.hh"
00021 #include "artdaq/Application/makeCommandableFragmentGenerator.hh"
00022 #include "artdaq-utilities/Plugins/MetricManager.hh"
00023 #include "artdaq-core/Core/SimpleMemoryReader.hh"
00024 #include "cetlib/filepath_maker.h"
00025 #include "fhiclcpp/ParameterSet.h"
00026 #include "fhiclcpp/make_ParameterSet.h"
00027 #include <boost/program_options.hpp>
00028
00029 #include <signal.h>
00030 #include <iostream>
00031 #include <memory>
00032 #include <utility>
00033 #include "artdaq/DAQrate/SharedMemoryEventManager.hh"
00034 #include "artdaq/Application/LoadParameterSet.hh"
00035
00036 namespace bpo = boost::program_options;
00037
00038 volatile int events_to_generate;
00039 void sig_handler(int) { events_to_generate = -1; }
00040
00041 template<typename B, typename D>
00042 std::unique_ptr<D>
00043 dynamic_unique_ptr_cast(std::unique_ptr<B>& p);
00044
00045 int main(int argc, char * argv[]) try
00046 {
00047 auto pset = LoadParameterSet(argc, argv);
00048
00049 int run = pset.get<int>("run_number", 1);
00050 bool debug = pset.get<bool>("debug_cout", false);
00051 uint64_t timeout = pset.get<uint64_t>("transition_timeout", 30);
00052 uint64_t timestamp = 0;
00053
00054 artdaq::configureMessageFacility("artdaqDriver", true, debug);
00055
00056 fhicl::ParameterSet fragment_receiver_pset = pset.get<fhicl::ParameterSet>("fragment_receiver");
00057
00058 std::unique_ptr<artdaq::FragmentGenerator>
00059 gen(artdaq::makeFragmentGenerator(fragment_receiver_pset.get<std::string>("generator"),
00060 fragment_receiver_pset));
00061
00062 std::unique_ptr<artdaq::CommandableFragmentGenerator> commandable_gen =
00063 dynamic_unique_ptr_cast<artdaq::FragmentGenerator, artdaq::CommandableFragmentGenerator>(gen);
00064
00065 artdaq::MetricManager metricMan_;
00066 metricMan = &metricMan_;
00067 my_rank = 0;
00068
00069 fhicl::ParameterSet metric_pset;
00070 try {
00071 metric_pset = pset.get<fhicl::ParameterSet>("metrics");
00072 }
00073 catch (...) {}
00074
00075 if (metric_pset.is_empty()) {
00076 TLOG(TLVL_INFO) << "No metric plugins appear to be defined";
00077 }
00078 try {
00079 metricMan_.initialize(metric_pset, "artdaqDriver");
00080 metricMan_.do_start();
00081 }
00082 catch (...) {
00083 }
00084 artdaq::FragmentPtrs frags;
00086
00087
00088
00089 fhicl::ParameterSet event_builder_pset = pset.get<fhicl::ParameterSet>("event_builder");
00090
00091 artdaq::SharedMemoryEventManager event_manager(event_builder_pset, pset);
00093
00094 int events_to_generate = pset.get<int>("events_to_generate", 0);
00095 int event_count = 0;
00096 artdaq::Fragment::sequence_id_t previous_sequence_id = -1;
00097
00098 if (commandable_gen) {
00099 commandable_gen->StartCmd(run, timeout, timestamp);
00100 }
00101
00102 TLOG(50) << "driver main before event_manager.startRun";
00103 event_manager.startRun(run);
00104
00105
00106
00107
00108
00109 while ((commandable_gen && commandable_gen->getNext(frags)) ||
00110 (gen && gen->getNext(frags))) {
00111 TLOG(50) << "driver main: getNext returned frags.size()=" << std::to_string(frags.size()) << " current event_count=" << event_count;
00112 for (auto & val : frags) {
00113 if (val->sequenceID() != previous_sequence_id) {
00114 ++event_count;
00115 previous_sequence_id = val->sequenceID();
00116 }
00117 if (events_to_generate != 0 && event_count > events_to_generate) {
00118 if (commandable_gen) {
00119 commandable_gen->StopCmd(timeout, timestamp);
00120 }
00121 break;
00122 }
00123 artdaq::FragmentPtr tempFrag;
00124 auto sts = event_manager.AddFragment(std::move(val), 1000000, tempFrag);
00125 if (!sts)
00126 {
00127 TLOG(TLVL_ERROR) << "Fragment was not added after 1s. Check art process status!";
00128 exit(1);
00129 }
00130 }
00131 frags.clear();
00132
00133 if (events_to_generate != 0 && event_count >= events_to_generate) {
00134 if (commandable_gen) {
00135 commandable_gen->StopCmd(timeout, timestamp);
00136 }
00137 break;
00138 }
00139 }
00140
00141 if (commandable_gen) {
00142 commandable_gen->joinThreads();
00143 }
00144
00145 TLOG(TLVL_INFO) << "Fragments generated, waiting for art to process them.";
00146 auto art_wait_start_time = std::chrono::steady_clock::now();
00147 auto last_delta_time = std::chrono::steady_clock::now();
00148 auto last_count = event_manager.size() - event_manager.WriteReadyCount(false);
00149
00150 while (last_count > 0 && artdaq::TimeUtils::GetElapsedTime(last_delta_time) < 1.0)
00151 {
00152 auto this_count = event_manager.size() - event_manager.WriteReadyCount(false);
00153 if (this_count != last_count) {
00154 last_delta_time = std::chrono::steady_clock::now();
00155 last_count = this_count;
00156 }
00157 usleep(1000);
00158 }
00159
00160 TLOG(TLVL_INFO) << "Ending Run, waited " << std::setprecision(2) << artdaq::TimeUtils::GetElapsedTime(art_wait_start_time) << " seconds for art to process events. (" << last_count << " buffers remain).";
00161 event_manager.endRun();
00162 usleep(artdaq::TimeUtils::GetElapsedTimeMicroseconds(art_wait_start_time));
00163
00164 TLOG(TLVL_INFO) << "Shutting down art";
00165 bool endSucceeded = false;
00166 int attemptsToEnd = 1;
00167 endSucceeded = event_manager.endOfData();
00168 while (!endSucceeded && attemptsToEnd < 3) {
00169 ++attemptsToEnd;
00170 endSucceeded = event_manager.endOfData();
00171 }
00172 if (!endSucceeded) {
00173 TLOG(TLVL_ERROR) << "Failed to shut down the reader and the SharedMemoryEventManager "
00174 << "because the endOfData marker could not be pushed "
00175 << "onto the queue.";
00176 }
00177
00178 metricMan_.do_stop();
00179 return 0;
00180 }
00181 catch (std::string & x)
00182 {
00183 std::cerr << "Exception (type string) caught in artdaqDriver: " << x << '\n';
00184 return 1;
00185 }
00186 catch (char const * m)
00187 {
00188 std::cerr << "Exception (type char const*) caught in artdaqDriver: ";
00189 if (m)
00190 {
00191 std::cerr << m;
00192 }
00193 else
00194 {
00195 std::cerr << "[the value was a null pointer, so no message is available]";
00196 }
00197 std::cerr << '\n';
00198 }
00199 catch (...) {
00200 artdaq::ExceptionHandler(artdaq::ExceptionHandlerRethrow::no,
00201 "Exception caught in artdaqDriver");
00202 }
00203
00204
00205 template<typename B, typename D>
00206 std::unique_ptr<D>
00207 dynamic_unique_ptr_cast(std::unique_ptr<B>& p)
00208 {
00209 D* result = dynamic_cast<D*>(p.get());
00210
00211 if (result) {
00212 p.release();
00213 return std::unique_ptr<D>(result);
00214 }
00215 return nullptr;
00216 }