00001
00002
00003
00004
00005
00006
00007
00009
00010 #include "art/Framework/Core/EDFilter.h"
00011 #include "art/Framework/Core/ModuleMacros.h"
00012 #include "art/Framework/Principal/Event.h"
00013 #include "art/Framework/Principal/Handle.h"
00014 #include "art/Framework/Principal/Run.h"
00015 #include "art/Framework/Principal/SubRun.h"
00016 #include "canvas/Utilities/InputTag.h"
00017 #include "fhiclcpp/ParameterSet.h"
00018
00019 #include "artdaq/DAQdata/Globals.hh"
00020
00021 #include <memory>
00022 #include <random>
00023 #include <chrono>
00024
00025 namespace artdaq
00026 {
00027 class RandomDelayFilter;
00028 }
00029
00037 class artdaq::RandomDelayFilter : public art::EDFilter
00038 {
00039 public:
00054 explicit RandomDelayFilter(fhicl::ParameterSet const& p);
00055
00059 RandomDelayFilter(RandomDelayFilter const&) = delete;
00060
00064 RandomDelayFilter(RandomDelayFilter&&) = delete;
00065
00070 RandomDelayFilter& operator=(RandomDelayFilter const&) = delete;
00071
00076 RandomDelayFilter& operator=(RandomDelayFilter&&) = delete;
00077
00087 bool filter(art::Event& e) override;
00088
00089 private:
00090
00091 double min_ms_;
00092 double max_ms_;
00093 double mean_ms_;
00094 double sigma_ms_;
00095
00096 int pass_factor_;
00097 double load_factor_;
00098
00099
00100 bool isNormal_;
00101 std::mt19937 engine_;
00102 std::unique_ptr<std::uniform_real_distribution<double>> uniform_distn_;
00103 std::unique_ptr<std::normal_distribution<double>> normal_distn_;
00104 std::unique_ptr<std::uniform_int_distribution<int>> pass_distn_;
00105 };
00106
00107
00108 artdaq::RandomDelayFilter::RandomDelayFilter(fhicl::ParameterSet const& p)
00109 : min_ms_(p.get<double>("minimum_delay_ms", 0))
00110 , max_ms_(p.get<double>("maximum_delay_ms", 1000))
00111 , mean_ms_(p.get<double>("mean_delay_ms", 500))
00112 , sigma_ms_(p.get<double>("sigma_delay_ms", 100))
00113 , pass_factor_(p.get<int>("pass_filter_percentage", 100))
00114 , load_factor_(p.get<double>("cpu_load_ratio", 1.0))
00115 , isNormal_(p.get<bool>("use_normal_distribution", false))
00116 , engine_(p.get<int64_t>("random_seed", 271828))
00117 , pass_distn_(new std::uniform_int_distribution<int>(0, 100))
00118 {
00119
00120 if (pass_factor_ > 100) pass_factor_ = 100;
00121 if (pass_factor_ < 0) pass_factor_ = 0;
00122 if (load_factor_ < 0.0) load_factor_ = 0.0;
00123 if (load_factor_ > 1.0) load_factor_ = 1.0;
00124
00125 if (min_ms_ < 0) min_ms_ = 0;
00126 if (min_ms_ > max_ms_) max_ms_ = min_ms_;
00127 if (mean_ms_ < 0) mean_ms_ = 0;
00128 if (sigma_ms_ < 0) sigma_ms_ = 0;
00129
00130 uniform_distn_.reset(new std::uniform_real_distribution<double>(min_ms_, max_ms_));
00131 normal_distn_.reset(new std::normal_distribution<double>(mean_ms_, sigma_ms_));
00132 }
00133
00134 bool artdaq::RandomDelayFilter::filter(art::Event& e)
00135 {
00136 double delay = isNormal_ ? (*normal_distn_)(engine_) : (*uniform_distn_)(engine_);
00137 TLOG_DEBUG("RandomDelayFilter") << "Simulating processing of event " << e.event() << " by delaying " << std::to_string(delay) << "ms." << TLOG_ENDL;
00138
00139 usleep(1000 * (1 - load_factor_) * delay);
00140
00141 auto i = 0;
00142 auto now = std::chrono::steady_clock::now();
00143 while (TimeUtils::GetElapsedTimeMilliseconds(now) < static_cast<size_t>(delay * load_factor_))
00144 {
00145 i = i + 1 % std::numeric_limits<int>::max();
00146 }
00147
00148 return (*pass_distn_)(engine_) < pass_factor_;
00149 }
00150
00151 DEFINE_ART_MODULE(artdaq::RandomDelayFilter)