00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012 #define TRACE_NAME "genToArt"
00013
00014 #include "art/Framework/Art/artapp.h"
00015 #include "canvas/Utilities/Exception.h"
00016 #include "artdaq-core/Generators/FragmentGenerator.hh"
00017 #include "artdaq-core/Data/Fragment.hh"
00018 #include "artdaq/DAQdata/GenericFragmentSimulator.hh"
00019 #include "artdaq/Application/CommandableFragmentGenerator.hh"
00020 #include "artdaq/DAQrate/SharedMemoryEventManager.hh"
00021 #include "artdaq-core/Generators/makeFragmentGenerator.hh"
00022 #include "artdaq-core/Core/SimpleMemoryReader.hh"
00023 #include "artdaq-core/Utilities/SimpleLookupPolicy.hh"
00024 #include "cetlib/container_algorithms.h"
00025 #include "fhiclcpp/ParameterSet.h"
00026 #include "fhiclcpp/make_ParameterSet.h"
00027
00028 #include <boost/program_options.hpp>
00029
00030 #include <deque>
00031 #include <iostream>
00032 #include <map>
00033 #include <memory>
00034 #include <string>
00035 #include <utility>
00036
00037 namespace bpo = boost::program_options;
00038
00039 namespace
00040 {
00048 int process_cmd_line(int argc, char** argv,
00049 bpo::variables_map& vm)
00050 {
00051 std::ostringstream descstr;
00052 descstr << argv[0]
00053 << " <-c <config-file>> <other-options> [<source-file>]+";
00054 bpo::options_description desc(descstr.str());
00055 desc.add_options()
00056 ("config,c", bpo::value<std::string>(), "Configuration file.")
00057 ("help,h", "produce help message");
00058 try
00059 {
00060 bpo::store(bpo::command_line_parser(argc, argv).options(desc).run(), vm);
00061 bpo::notify(vm);
00062 }
00063 catch (bpo::error const& e)
00064 {
00065 TLOG(TLVL_ERROR) << "Exception from command line processing in " << argv[0]
00066 << ": " << e.what();
00067 return -1;
00068 }
00069 if (vm.count("help"))
00070 {
00071 std::cout << desc << std::endl;
00072 return 1;
00073 }
00074 if (!vm.count("config"))
00075 {
00076 TLOG(TLVL_ERROR) << "Exception from command line processing in " << argv[0]
00077 << ": no configuration file given.\n"
00078 << "For usage and an options list, please do '"
00079 << argv[0] << " --help"
00080 << "'.";
00081 return 2;
00082 }
00083 return 0;
00084 }
00085
00090 class ThrottledGenerator
00091 {
00092 public:
00098 ThrottledGenerator(std::string const& generator,
00099 fhicl::ParameterSet const& ps);
00100
00106 bool getNext(artdaq::FragmentPtrs& newFrags);
00107
00112 size_t numFragIDs() const;
00113
00120 void start(int run, uint64_t timeout, uint64_t timestamp) const
00121 {
00122 auto gen_ptr = dynamic_cast<artdaq::CommandableFragmentGenerator*>(generator_.get());
00123 if (gen_ptr != nullptr) gen_ptr->StartCmd(run, timeout, timestamp);
00124 }
00130 void stop(uint64_t timeout, uint64_t timestamp) const
00131 {
00132 auto gen_ptr = dynamic_cast<artdaq::CommandableFragmentGenerator*>(generator_.get());
00133 if (gen_ptr != nullptr) gen_ptr->StopCmd(timeout, timestamp);
00134 }
00135
00136 private:
00137 bool generateFragments_();
00138
00139 std::unique_ptr<artdaq::FragmentGenerator> generator_;
00140 size_t const numFragIDs_;
00141 std::map<artdaq::Fragment::fragment_id_t,
00142 std::deque<artdaq::FragmentPtr>> frags_;
00143 };
00144
00145 ThrottledGenerator::
00146 ThrottledGenerator(std::string const& generator,
00147 fhicl::ParameterSet const& ps)
00148 :
00149 generator_(artdaq::makeFragmentGenerator(generator, ps))
00150 , numFragIDs_(generator_->fragmentIDs().size())
00151 , frags_()
00152 {
00153 assert(generator_);
00154 }
00155
00156 bool
00157 ThrottledGenerator::
00158 getNext(artdaq::FragmentPtrs& newFrags)
00159 {
00160 if (frags_.size() && frags_.begin()->second.size())
00161 {
00162 for (auto& fQp : frags_)
00163 {
00164 assert(fQp.second.size());
00165 newFrags.emplace_back(std::move(fQp.second.front()));
00166 fQp.second.pop_front();
00167 }
00168 }
00169 else
00170 {
00171 return generateFragments_() && getNext(newFrags);
00172 }
00173 return true;
00174 }
00175
00176 bool
00177 ThrottledGenerator::
00178 generateFragments_()
00179 {
00180 artdaq::FragmentPtrs incomingFrags;
00181 bool result{ false };
00182 while ((result = generator_->getNext(incomingFrags)) &&
00183 incomingFrags.empty())
00184 {
00185 }
00186 for (auto&& frag : incomingFrags)
00187 {
00188 frags_[frag->fragmentID()].emplace_back(std::move(frag));
00189 }
00190 return result;
00191 }
00192
00193 size_t
00194 ThrottledGenerator::
00195 numFragIDs() const
00196 {
00197 return numFragIDs_;
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00224 int process_data(fhicl::ParameterSet const& pset)
00225 {
00226 auto const gta_pset = pset.get<fhicl::ParameterSet>("genToArt");
00227
00228
00229 std::vector<ThrottledGenerator> generators;
00230
00231 auto const fr_pset = gta_pset.get<std::vector<fhicl::ParameterSet>>("fragment_receivers");
00232 for (auto const& gen_ps : fr_pset)
00233 {
00234 generators.emplace_back(gen_ps.get<std::string>("generator"),
00235 gen_ps);
00236 }
00237
00238 artdaq::FragmentPtrs frags;
00239 auto eb_pset = gta_pset.get<fhicl::ParameterSet>("event_builder", {});
00240 size_t expected_frags_per_event = 0;
00241 for (auto& gen : generators)
00242 {
00243 gen.start(1000, 0, 0);
00244 expected_frags_per_event += gen.numFragIDs();
00245 }
00246 eb_pset.put_or_replace<size_t>("expected_fragments_per_event", expected_frags_per_event);
00247
00248 artdaq::SharedMemoryEventManager store(eb_pset, pset);
00249 store.startRun(gta_pset.get<int>("run_number", 1000));
00250
00251 auto const events_to_generate =
00252 gta_pset.get<artdaq::Fragment::sequence_id_t>("events_to_generate", -1);
00253 auto const reset_sequenceID = pset.get<bool>("reset_sequenceID", true);
00254 bool done = false;
00255 for (artdaq::Fragment::sequence_id_t event_count = 1;
00256 (events_to_generate == static_cast<decltype(events_to_generate)>(-1)
00257 || event_count <= events_to_generate) && (!done);
00258 ++event_count)
00259 {
00260 for (auto& gen : generators)
00261 {
00262 done |= !gen.getNext(frags);
00263 }
00264 TLOG(TLVL_TRACE) << "There are " << std::to_string(frags.size()) << " Fragments in event " << std::to_string(event_count) << ".";
00265 artdaq::Fragment::sequence_id_t current_sequence_id = -1;
00266 for (auto& val : frags)
00267 {
00268 if (reset_sequenceID)
00269 {
00270 TLOG(TLVL_DEBUG) << "Setting fragment sequence id to " << std::to_string(event_count);
00271 val->setSequenceID(event_count);
00272 }
00273 if (current_sequence_id ==
00274 static_cast<artdaq::Fragment::sequence_id_t>(-1))
00275 {
00276 current_sequence_id = val->sequenceID();
00277 }
00278 else if (val->sequenceID() != current_sequence_id)
00279 {
00280 throw art::Exception(art::errors::DataCorruption)
00281 << "Data corruption: apparently related fragments have "
00282 << " different sequence IDs: "
00283 << val->sequenceID()
00284 << " and "
00285 << current_sequence_id
00286 << ".\n";
00287 }
00288
00289 auto start_time = std::chrono::steady_clock::now();
00290 bool sts = false;
00291 auto loop_count = 0;
00292 while (!sts)
00293 {
00294 artdaq::FragmentPtr tempFrag;
00295 sts = store.AddFragment(std::move(val), 1000000, tempFrag);
00296 if (!sts && event_count <= 10 && loop_count > 100)
00297 {
00298 TLOG(TLVL_ERROR) << "Fragment was not added after " << artdaq::TimeUtils::GetElapsedTime(start_time) << " s. Check art thread status!";
00299 store.endOfData();
00300 exit(1);
00301 }
00302 val = std::move(tempFrag);
00303 if (!sts)
00304 {
00305 loop_count++;
00306 usleep(10000);
00307 }
00308 }
00309 }
00310 frags.clear();
00311 TLOG(TLVL_TRACE) << "Event " << std::to_string(event_count) << " END";
00312 }
00313 for (auto& gen : generators)
00314 {
00315 gen.stop(0, 0);
00316 }
00317
00318 bool endSucceeded = store.endOfData();
00319 if (endSucceeded)
00320 {
00321 return 0;
00322 }
00323 else
00324 {
00325 return 15;
00326 }
00327 }
00328 }
00329
00330 int main(int argc, char* argv[]) try
00331 {
00332 artdaq::configureMessageFacility("genToArt");
00333
00334 bpo::variables_map vm;
00335 auto result = process_cmd_line(argc, argv, vm);
00336 if (result != 0)
00337 {
00338 return (result);
00339 }
00340
00341 fhicl::ParameterSet pset;
00342 if (getenv("FHICL_FILE_PATH") == nullptr)
00343 {
00344 TLOG(TLVL_ERROR)
00345 << "INFO: environment variable FHICL_FILE_PATH was not set. Using \".\"\n";
00346 setenv("FHICL_FILE_PATH", ".", 0);
00347 }
00348 artdaq::SimpleLookupPolicy lookup_policy("FHICL_FILE_PATH");
00349 make_ParameterSet(vm["config"].as<std::string>(), lookup_policy, pset);
00350 return process_data(pset);
00351 }
00352 catch (std::string& x)
00353 {
00354 TLOG(TLVL_ERROR) << "Exception (type string) caught in genToArt: " << x << '\n';
00355 return 1;
00356 }
00357 catch (char const* m)
00358 {
00359 TLOG(TLVL_ERROR) << "Exception (type char const*) caught in genToArt: ";
00360 if (m)
00361 {
00362 TLOG(TLVL_ERROR) << m;
00363 }
00364 else
00365 {
00366 TLOG(TLVL_ERROR) << "[the value was a null pointer, so no message is available]";
00367 }
00368 }