00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012 #include "art/Framework/Art/artapp.h"
00013 #include "canvas/Utilities/Exception.h"
00014 #include "artdaq/Application/MPI2/MPISentry.hh"
00015 #include "artdaq-core/Generators/FragmentGenerator.hh"
00016 #include "artdaq-core/Data/Fragment.hh"
00017 #include "artdaq/DAQdata/GenericFragmentSimulator.hh"
00018 #include "artdaq-core/Generators/makeFragmentGenerator.hh"
00019 #include "artdaq/DAQrate/EventStore.hh"
00020 #include "artdaq-core/Core/SimpleQueueReader.hh"
00021 #include "artdaq-core/Utilities/SimpleLookupPolicy.hh"
00022 #include "cetlib/container_algorithms.h"
00023 #include "fhiclcpp/ParameterSet.h"
00024 #include "fhiclcpp/make_ParameterSet.h"
00025
00026 #include "boost/program_options.hpp"
00027
00028 #include <deque>
00029 #include <iostream>
00030 #include <map>
00031 #include <memory>
00032 #include <string>
00033 #include <utility>
00034
00035 using namespace std;
00036 using namespace fhicl;
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 std::cerr << "Exception from command line processing in " << argv[0]
00066 << ": " << e.what() << "\n";
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 std::cerr << "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 << "'.\n";
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
00114 private:
00115 bool generateFragments_();
00116
00117 std::unique_ptr<artdaq::FragmentGenerator> generator_;
00118 size_t const numFragIDs_;
00119 std::map<artdaq::Fragment::fragment_id_t,
00120 std::deque<artdaq::FragmentPtr>> frags_;
00121 };
00122
00123 ThrottledGenerator::
00124 ThrottledGenerator(std::string const& generator,
00125 fhicl::ParameterSet const& ps)
00126 :
00127 generator_(artdaq::makeFragmentGenerator(generator, ps))
00128 , numFragIDs_(generator_->fragmentIDs().size())
00129 , frags_()
00130 {
00131 assert(generator_);
00132 }
00133
00134 bool
00135 ThrottledGenerator::
00136 getNext(artdaq::FragmentPtrs& newFrags)
00137 {
00138 if (frags_.size() && frags_.begin()->second.size())
00139 {
00140 for (auto& fQp : frags_)
00141 {
00142 assert(fQp.second.size());
00143 newFrags.emplace_back(std::move(fQp.second.front()));
00144 fQp.second.pop_front();
00145 }
00146 }
00147 else
00148 {
00149 return generateFragments_() && getNext(newFrags);
00150 }
00151 return true;
00152 }
00153
00154 bool
00155 ThrottledGenerator::
00156 generateFragments_()
00157 {
00158 artdaq::FragmentPtrs incomingFrags;
00159 bool result{false};
00160 while ((result = generator_->getNext(incomingFrags)) &&
00161 incomingFrags.empty()) { }
00162 for (auto&& frag : incomingFrags)
00163 {
00164 frags_[frag->fragmentID()].emplace_back(std::move(frag));
00165 }
00166 return result;
00167 }
00168
00169 size_t
00170 ThrottledGenerator::
00171 numFragIDs() const
00172 {
00173 return numFragIDs_;
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00202 int process_data(int argc, char** argv,
00203 fhicl::ParameterSet const& pset)
00204 {
00205 auto const gta_pset = pset.get<ParameterSet>("genToArt");
00206
00207
00208 std::vector<ThrottledGenerator> generators;
00209
00210 auto const fr_pset = gta_pset.get<std::vector<ParameterSet>>("fragment_receivers");
00211 for (auto const& gen_ps : fr_pset)
00212 {
00213 generators.emplace_back(gen_ps.get<std::string>("generator"),
00214 gen_ps);
00215 }
00216
00217 artdaq::FragmentPtrs frags;
00218 auto const eb_pset = gta_pset.get<ParameterSet>("event_builder", {});
00219 size_t expected_frags_per_event = 0;
00220 for (auto& gen : generators)
00221 {
00222 expected_frags_per_event += gen.numFragIDs();
00223 }
00224
00225 artdaq::EventStore store(eb_pset, expected_frags_per_event,
00226 gta_pset.get<artdaq::EventStore::run_id_t>("run_number"),
00227 argc,
00228 argv,
00229 &artapp);
00230
00231 auto const events_to_generate =
00232 gta_pset.get<artdaq::Fragment::sequence_id_t>("events_to_generate", -1);
00233 auto const reset_sequenceID = pset.get<bool>("reset_sequenceID", true);
00234 bool done = false;
00235 for (artdaq::Fragment::sequence_id_t event_count = 1;
00236 (events_to_generate == static_cast<decltype(events_to_generate)>(-1)
00237 || event_count <= events_to_generate) && (!done);
00238 ++event_count)
00239 {
00240 for (auto& gen : generators)
00241 {
00242 done |= !gen.getNext(frags);
00243 }
00244 artdaq::Fragment::sequence_id_t current_sequence_id = -1;
00245 for (auto& val : frags)
00246 {
00247 if (reset_sequenceID)
00248 {
00249 val->setSequenceID(event_count);
00250 }
00251 if (current_sequence_id ==
00252 static_cast<artdaq::Fragment::sequence_id_t>(-1))
00253 {
00254 current_sequence_id = val->sequenceID();
00255 }
00256 else if (val->sequenceID() != current_sequence_id)
00257 {
00258 throw art::Exception(art::errors::DataCorruption)
00259 << "Data corruption: apparently related fragments have "
00260 << " different sequence IDs: "
00261 << val->sequenceID()
00262 << " and "
00263 << current_sequence_id
00264 << ".\n";
00265 }
00266 store.insert(std::move(val));
00267 }
00268 frags.clear();
00269 }
00270
00271 int readerReturnValue;
00272 bool endSucceeded = store.endOfData(readerReturnValue);
00273 if (endSucceeded)
00274 {
00275 return readerReturnValue;
00276 }
00277 else
00278 {
00279 return 15;
00280 }
00281 }
00282 }
00283
00284 int main(int argc, char* argv[]) try
00285 {
00286
00287 artdaq::MPISentry sentry(&argc, &argv);
00288
00289 bpo::variables_map vm;
00290 auto result = process_cmd_line(argc, argv, vm);
00291 if (result != 0)
00292 {
00293 return (result);
00294 }
00295
00296 ParameterSet pset;
00297 if (getenv("FHICL_FILE_PATH") == nullptr)
00298 {
00299 std::cerr
00300 << "INFO: environment variable FHICL_FILE_PATH was not set. Using \".\"\n";
00301 setenv("FHICL_FILE_PATH", ".", 0);
00302 }
00303 artdaq::SimpleLookupPolicy lookup_policy("FHICL_FILE_PATH");
00304 make_ParameterSet(vm["config"].as<std::string>(), lookup_policy, pset);
00305 return process_data(argc, argv, pset);
00306 }
00307 catch (std::string& x)
00308 {
00309 cerr << "Exception (type string) caught in genToArt: " << x << '\n';
00310 return 1;
00311 }
00312 catch (char const* m)
00313 {
00314 cerr << "Exception (type char const*) caught in genToArt: ";
00315 if (m)
00316 {
00317 cerr << m;
00318 }
00319 else
00320 {
00321 cerr << "[the value was a null pointer, so no message is available]";
00322 }
00323 cerr << '\n';
00324 }