$treeview $search $mathjax $extrastylesheet
artdaq
v3_04_00
$projectbrief
|
$projectbrief
|
$searchbox |
00001 00002 // genToArt 00003 // 00004 // This application is intended to invoke a configurable set of fragment 00005 // generators, and funnel the result to an invocation of art. This is 00006 // not an MPI application (see caveat below), so is not intended for 00007 // high performance production DAQ scenarios -- for that, see the pmt 00008 // application driver and its associated applcations boardreader and 00009 // eventbuilder. 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 { // Something stored. 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 { // Need fresh fragments. 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 // artdaq::FragmentGenerator & 00201 // ThrottledGenerator:: 00202 // generator() const 00203 // { 00204 // return *generator_; 00205 // } 00206 00224 int process_data(fhicl::ParameterSet const& pset) 00225 { 00226 auto const gta_pset = pset.get<fhicl::ParameterSet>("genToArt"); 00227 00228 // Make the generators based on the configuration. 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 " << frags.size() << " Fragments in event " << 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 " << 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 " << 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 // Command line handling. 00334 bpo::variables_map vm; 00335 auto result = process_cmd_line(argc, argv, vm); 00336 if (result != 0) 00337 { 00338 return (result); 00339 } 00340 // Read FHiCL configuration file. 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 }