00001 #include <errno.h>
00002 #include <sstream>
00003 #include <iomanip>
00004 #include <bitset>
00005
00006 #include <signal.h>
00007
00008 #include <boost/tokenizer.hpp>
00009 #include <boost/filesystem.hpp>
00010 #include <boost/algorithm/string.hpp>
00011 #include <boost/exception/all.hpp>
00012 #include <boost/throw_exception.hpp>
00013
00014 #include "fhiclcpp/ParameterSet.h"
00015
00016 #define TRACE_NAME (app_name + "_DispatcherCore").c_str() // include these 2 first -
00017 #include "artdaq/DAQdata/Globals.hh"
00018
00019 #include "artdaq-core/Core/SimpleMemoryReader.hh"
00020 #include "artdaq-core/Data/RawEvent.hh"
00021
00022 #include "artdaq/Application/DispatcherCore.hh"
00023 #include "artdaq/TransferPlugins/MakeTransferPlugin.hh"
00024
00025
00026
00027 artdaq::DispatcherCore::DispatcherCore()
00028 : DataReceiverCore()
00029 {}
00030
00031 artdaq::DispatcherCore::~DispatcherCore()
00032 {
00033 TLOG(TLVL_DEBUG) << "Destructor" ;
00034 }
00035
00036 bool artdaq::DispatcherCore::initialize(fhicl::ParameterSet const& pset)
00037 {
00038 TLOG(TLVL_DEBUG) << "initialize method called with DAQ " << "ParameterSet = \"" << pset.to_string() << "\"." ;
00039
00040 pset_ = pset;
00041 pset_.erase("outputs");
00042 pset_.erase("physics");
00043 pset_.erase("daq");
00044
00045
00046 fhicl::ParameterSet daq_pset;
00047 try
00048 {
00049 daq_pset = pset.get<fhicl::ParameterSet>("daq");
00050 }
00051 catch (...)
00052 {
00053 TLOG(TLVL_ERROR)
00054 << "Unable to find the DAQ parameters in the initialization "
00055 << "ParameterSet: \"" + pset.to_string() + "\"." ;
00056 return false;
00057 }
00058 fhicl::ParameterSet agg_pset;
00059 try
00060 {
00061 agg_pset = daq_pset.get<fhicl::ParameterSet>("dispatcher", daq_pset.get<fhicl::ParameterSet>("aggregator"));
00062 }
00063 catch (...)
00064 {
00065 TLOG(TLVL_ERROR)
00066 << "Unable to find the Dispatcher parameters in the DAQ "
00067 << "initialization ParameterSet: \"" + daq_pset.to_string() + "\"." ;
00068 return false;
00069 }
00070
00071 broadcast_mode_ = agg_pset.get<bool>("broadcast_mode", true);
00072 if (broadcast_mode_ && !agg_pset.has_key("broadcast_mode"))
00073 {
00074 agg_pset.put<bool>("broadcast_mode", true);
00075 }
00076
00077 agg_pset.erase("art_analyzer_count");
00078 agg_pset.put<int>("art_analyzer_count", 0);
00079
00080
00081 fhicl::ParameterSet metric_pset;
00082
00083 try
00084 {
00085 metric_pset = daq_pset.get<fhicl::ParameterSet>("metrics");
00086 }
00087 catch (...) {}
00088
00089 return initializeDataReceiver(pset, agg_pset, metric_pset);
00090 }
00091
00092 std::string artdaq::DispatcherCore::register_monitor(fhicl::ParameterSet const& pset)
00093 {
00094 TLOG(TLVL_DEBUG) << "DispatcherCore::register_monitor called with argument \"" << pset.to_string() << "\"" ;
00095 std::lock_guard<std::mutex> lock(dispatcher_transfers_mutex_);
00096 check_filters_();
00097
00098 try
00099 {
00100 TLOG(TLVL_DEBUG) << "Getting unique_label from input ParameterSet" ;
00101 auto label = pset.get<std::string>("unique_label");
00102 TLOG(TLVL_DEBUG) << "Unique label is " << label ;
00103 if (registered_monitors_.count(label))
00104 {
00105 throw cet::exception("DispatcherCore") << "Unique label already exists!";
00106 }
00107
00108 registered_monitors_[label] = pset;
00109 if (event_store_ptr_ != nullptr)
00110 {
00111 if (broadcast_mode_) {
00112 fhicl::ParameterSet ps = merge_parameter_sets_(pset_, label, pset);
00113 TLOG(TLVL_DEBUG) << "Starting art process with received fhicl" ;
00114 registered_monitor_pids_[label] = event_store_ptr_->StartArtProcess(ps);
00115 }
00116 else
00117 {
00118 TLOG(TLVL_DEBUG) << "Generating new fhicl and reconfiguring art" ;
00119 event_store_ptr_->ReconfigureArt(generate_filter_fhicl_());
00120 }
00121 }
00122 else
00123 {
00124 TLOG(TLVL_ERROR) << "Unable to add monitor as there is no SharedMemoryEventManager instance!" ;
00125 }
00126 }
00127 catch (const cet::exception& e)
00128 {
00129 std::stringstream errmsg;
00130 errmsg << "Unable to create a Transfer plugin with the FHiCL code \"" << pset.to_string() << "\", a new monitor has not been registered" << std::endl;
00131 errmsg << "Exception: " << e.what();
00132 TLOG(TLVL_ERROR) << errmsg.str() ;
00133 return errmsg.str();
00134 }
00135 catch (const boost::exception& e)
00136 {
00137 std::stringstream errmsg;
00138 errmsg << "Unable to create a Transfer plugin with the FHiCL code \"" << pset.to_string() << "\", a new monitor has not been registered" << std::endl;
00139 errmsg << "Exception: " << boost::diagnostic_information(e);
00140 TLOG(TLVL_ERROR) << errmsg.str() ;
00141 return errmsg.str();
00142 }
00143 catch (const std::exception& e)
00144 {
00145 std::stringstream errmsg;
00146 errmsg << "Unable to create a Transfer plugin with the FHiCL code \"" << pset.to_string() << "\", a new monitor has not been registered" << std::endl;
00147 errmsg << "Exception: " << e.what();
00148 TLOG(TLVL_ERROR) << errmsg.str() ;
00149 return errmsg.str();
00150 }
00151 catch (...)
00152 {
00153 std::stringstream errmsg;
00154 errmsg << "Unable to create a Transfer plugin with the FHiCL code \"" << pset.to_string() << "\", a new monitor has not been registered";
00155 TLOG(TLVL_ERROR) << errmsg.str() ;
00156 return errmsg.str();
00157 }
00158
00159 return "Success";
00160 }
00161
00162 std::string artdaq::DispatcherCore::unregister_monitor(std::string const& label)
00163 {
00164 TLOG(TLVL_DEBUG) << "DispatcherCore::unregister_monitor called with argument \"" << label << "\"" ;
00165 std::lock_guard<std::mutex> lock(dispatcher_transfers_mutex_);
00166 check_filters_();
00167
00168 try
00169 {
00170 if (registered_monitors_.count(label) == 0)
00171 {
00172 std::stringstream errmsg;
00173 errmsg << "Warning in DispatcherCore::unregister_monitor: unable to find requested transfer plugin with "
00174 << "label \"" << label << "\"";
00175 TLOG(TLVL_WARNING) << errmsg.str() ;
00176 return errmsg.str();
00177 }
00178
00179 registered_monitors_.erase(label);
00180 if (event_store_ptr_ != nullptr)
00181 {
00182 if(broadcast_mode_) {
00183 std::set<pid_t> pids;
00184 pids.insert(registered_monitor_pids_[label]);
00185 event_store_ptr_->ShutdownArtProcesses(pids);
00186 registered_monitor_pids_.erase(label);
00187 }
00188 else
00189 {
00190 event_store_ptr_->ReconfigureArt(generate_filter_fhicl_());
00191 }
00192 }
00193 }
00194 catch (...)
00195 {
00196 std::stringstream errmsg;
00197 errmsg << "Unable to unregister transfer plugin with label \"" << label << "\"";
00198 return errmsg.str();
00199 }
00200
00201 return "Success";
00202 }
00203
00204 fhicl::ParameterSet artdaq::DispatcherCore::merge_parameter_sets_(fhicl::ParameterSet skel,std::string label, fhicl::ParameterSet pset)
00205 {
00206 fhicl::ParameterSet generated_pset = skel;
00207 fhicl::ParameterSet generated_outputs;
00208 fhicl::ParameterSet generated_physics;
00209 fhicl::ParameterSet generated_physics_analyzers;
00210 fhicl::ParameterSet generated_physics_producers;
00211 fhicl::ParameterSet generated_physics_filters;
00212 std::unordered_map<std::string, std::vector<std::string>> generated_physics_filter_paths;
00213
00214 TLOG(TLVL_DEBUG) << "merge_parameter_sets_: Generating fhicl for monitor " << label ;
00215
00216 try
00217 {
00218 auto path = pset.get<std::vector<std::string>>("path");
00219
00220 auto filters = pset.get<std::vector<fhicl::ParameterSet>>("filter_paths", std::vector<fhicl::ParameterSet>());
00221 for (auto& filter : filters)
00222 {
00223 try {
00224 auto name = filter.get<std::string>("name");
00225 auto path = filter.get<std::vector<std::string>>("path");
00226 if (generated_physics_filter_paths.count(name))
00227 {
00228 bool matched = generated_physics_filter_paths[name].size() == path.size();
00229 for (size_t ii = 0; matched && ii < generated_physics_filter_paths[name].size(); ++ii)
00230 {
00231 matched = matched && path[ii] == generated_physics_filter_paths[name][ii];
00232 }
00233
00234 if (matched)
00235 {
00236
00237 continue;
00238 }
00239 else
00240 {
00241 auto newname = label + name;
00242 generated_physics_filter_paths[newname] = path;
00243 }
00244 }
00245 else
00246 {
00247 generated_physics_filter_paths[name] = path;
00248 }
00249 }
00250 catch (...)
00251 {
00252 }
00253 }
00254
00255
00256 auto outputs = pset.get<fhicl::ParameterSet>("outputs");
00257 if (outputs.get_pset_names().size() > 1 || outputs.get_pset_names().size() == 0)
00258 {
00259
00260 }
00261 auto output_name = outputs.get_pset_names()[0];
00262 auto output_pset = outputs.get<fhicl::ParameterSet>(output_name);
00263 generated_outputs.put(label + output_name, output_pset);
00264 bool outputInPath = false;
00265 for (size_t ii = 0; ii < path.size(); ++ii)
00266 {
00267 if (path[ii] == output_name)
00268 {
00269 path[ii] = label + output_name;
00270 outputInPath = true;
00271 }
00272 }
00273 if (!outputInPath)
00274 {
00275 path.push_back(label + output_name);
00276 }
00277
00278
00279 auto physics_pset = pset.get<fhicl::ParameterSet>("physics");
00280
00281 if (physics_pset.has_key("analyzers"))
00282 {
00283 auto analyzers = physics_pset.get<fhicl::ParameterSet>("analyzers");
00284 for (auto key : analyzers.get_pset_names())
00285 {
00286 if (generated_physics_analyzers.has_key(key) && analyzers.get<fhicl::ParameterSet>(key) == generated_physics_analyzers.get<fhicl::ParameterSet>(key))
00287 {
00288
00289 continue;
00290 }
00291 else if (generated_physics_analyzers.has_key(key))
00292 {
00293
00294 auto newkey = label + key;
00295 generated_physics_analyzers.put<fhicl::ParameterSet>(newkey, analyzers.get<fhicl::ParameterSet>(key));
00296 for (size_t ii = 0; ii < path.size(); ++ii)
00297 {
00298 if (path[ii] == key)
00299 {
00300 path[ii] = newkey;
00301 }
00302 }
00303 }
00304 else
00305 {
00306 generated_physics_analyzers.put<fhicl::ParameterSet>(key, analyzers.get<fhicl::ParameterSet>(key));
00307 }
00308 }
00309 }
00310 if (physics_pset.has_key("producers"))
00311 {
00312 auto producers = physics_pset.get<fhicl::ParameterSet>("producers");
00313 for (auto key : producers.get_pset_names())
00314 {
00315 if (generated_physics_producers.has_key(key) && producers.get<fhicl::ParameterSet>(key) == generated_physics_producers.get<fhicl::ParameterSet>(key))
00316 {
00317
00318 continue;
00319 }
00320 else if (generated_physics_producers.has_key(key))
00321 {
00322
00323 auto newkey = label + key;
00324 generated_physics_producers.put<fhicl::ParameterSet>(newkey, producers.get<fhicl::ParameterSet>(key));
00325 for (size_t ii = 0; ii < path.size(); ++ii)
00326 {
00327 if (path[ii] == key)
00328 {
00329 path[ii] = newkey;
00330 }
00331 }
00332 }
00333 else
00334 {
00335 generated_physics_producers.put<fhicl::ParameterSet>(key, producers.get<fhicl::ParameterSet>(key));
00336 }
00337 }
00338 }
00339 if (physics_pset.has_key("filters"))
00340 {
00341 auto filters = physics_pset.get<fhicl::ParameterSet>("filters");
00342 for (auto key : filters.get_pset_names())
00343 {
00344 if (generated_physics_filters.has_key(key) && filters.get<fhicl::ParameterSet>(key) == generated_physics_filters.get<fhicl::ParameterSet>(key))
00345 {
00346
00347 continue;
00348 }
00349 else if (generated_physics_filters.has_key(key))
00350 {
00351
00352 auto newkey = label + key;
00353 generated_physics_filters.put<fhicl::ParameterSet>(newkey, filters.get<fhicl::ParameterSet>(key));
00354 for (size_t ii = 0; ii < path.size(); ++ii)
00355 {
00356 if (path[ii] == key)
00357 {
00358 path[ii] = newkey;
00359 }
00360 }
00361 }
00362 else
00363 {
00364 generated_physics_filters.put<fhicl::ParameterSet>(key, filters.get<fhicl::ParameterSet>(key));
00365 }
00366 }
00367 }
00368 generated_physics.put<std::vector<std::string>>(label, path);
00369 }
00370 catch (cet::exception& e)
00371 {
00372
00373 TLOG(TLVL_ERROR) << "merge_parameter_sets_: Error processing input fhicl: " << e.what() ;
00374 }
00375
00376 TLOG(TLVL_DEBUG) << "merge_parameter_sets_: Building final ParameterSet" ;
00377 generated_pset.put("outputs", generated_outputs);
00378
00379 generated_physics.put("analyzers", generated_physics_analyzers);
00380 generated_physics.put("producers", generated_physics_producers);
00381 generated_physics.put("filters", generated_physics_filters);
00382
00383 for (auto& path : generated_physics_filter_paths)
00384 {
00385 generated_physics.put(path.first, path.second);
00386 }
00387
00388 generated_pset.put("physics", generated_physics);
00389
00390 return generated_pset;
00391 }
00392
00393 fhicl::ParameterSet artdaq::DispatcherCore::generate_filter_fhicl_()
00394 {
00395 TLOG(TLVL_DEBUG) << "generate_filter_fhicl_ BEGIN" ;
00396 fhicl::ParameterSet generated_pset = pset_;
00397
00398 for (auto& monitor : registered_monitors_)
00399 {
00400 auto label = monitor.first;
00401 auto pset = monitor.second;
00402 generated_pset = merge_parameter_sets_(generated_pset, label, pset);
00403 }
00404
00405
00406 TLOG(TLVL_DEBUG) << "generate_filter_fhicl_ returning ParameterSet: " << generated_pset.to_string() ;
00407 return generated_pset;
00408 }
00409
00410 void artdaq::DispatcherCore::check_filters_()
00411 {
00412 auto it = registered_monitors_.begin();
00413 while (it != registered_monitors_.end())
00414 {
00415 if (!event_store_ptr_)
00416 {
00417 registered_monitor_pids_.erase(it->first);
00418 it = registered_monitors_.erase(it);
00419 }
00420 else
00421 {
00422 auto pid = registered_monitor_pids_[it->first];
00423 auto sts = kill(pid, 0);
00424 if (sts < 0) {
00425 registered_monitor_pids_.erase(it->first);
00426 it = registered_monitors_.erase(it);
00427 continue;
00428 }
00429 }
00430 ++it;
00431 }
00432 }