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