artdaq  v3_09_01
RandomDelayFilter_module.cc
1 // Class: RandomDelayFilter
3 // Module Type: filter
4 // File: RandomDelayFilter_module.cc
5 //
6 // Generated at Fri Mar 4 10:45:30 2016 by Eric Flumerfelt using artmod
7 // from cetpkgsupport v1_09_00.
9 
10 #define TRACE_NAME "RandomDelayFilter"
11 
12 #include "art/Framework/Core/EDFilter.h"
13 #include "art/Framework/Core/ModuleMacros.h"
14 #include "art/Framework/Principal/Event.h"
15 #include "art/Framework/Principal/Handle.h"
16 #include "art/Framework/Principal/Run.h"
17 #include "art/Framework/Principal/SubRun.h"
18 #include "canvas/Utilities/InputTag.h"
19 #include "fhiclcpp/ParameterSet.h"
20 
21 #include "artdaq/DAQdata/Globals.hh"
22 
23 #include <chrono>
24 #include <memory>
25 #include <random>
26 
27 namespace artdaq {
28 class RandomDelayFilter;
29 }
30 
38 class artdaq::RandomDelayFilter : public art::EDFilter
39 {
40 public:
55  explicit RandomDelayFilter(fhicl::ParameterSet const& p);
56 
57  ~RandomDelayFilter() override = default;
58 
62  RandomDelayFilter(RandomDelayFilter const&) = delete;
63 
68 
74 
80 
90  bool filter(art::Event& e) override;
91 
92 private:
93  // Random Delay Parameters (min/max for uniform, mean/sigma for normal)
94  double min_ms_;
95  double max_ms_;
96  double mean_ms_;
97  double sigma_ms_;
98 
99  int pass_factor_;
100  double load_factor_;
101 
102  // Random Engine Setup
103  std::mt19937 engine_;
104  std::unique_ptr<std::uniform_real_distribution<double>> uniform_distn_;
105  std::unique_ptr<std::normal_distribution<double>> normal_distn_;
106  std::unique_ptr<std::exponential_distribution<double>> exponential_distn_;
107  std::unique_ptr<std::uniform_int_distribution<int>> pass_distn_;
108 
109  enum class DistType
110  {
111  Fixed,
112  Uniform,
113  Normal,
114  Exponential
115  };
116  DistType distribution_type_;
117 };
118 
119 artdaq::RandomDelayFilter::RandomDelayFilter(fhicl::ParameterSet const& p)
120  :
121 #if ART_HEX_VERSION >= 0x30200
122  art::EDFilter(p)
123  ,
124 #endif
125  min_ms_(p.get<double>("minimum_delay_ms", 0))
126  , max_ms_(p.get<double>("maximum_delay_ms", 1000))
127  , mean_ms_(p.get<double>("mean_delay_ms", 500))
128  , sigma_ms_(p.get<double>("sigma_delay_ms", 100))
129  , pass_factor_(p.get<int>("pass_filter_percentage", 100))
130  , load_factor_(p.get<double>("cpu_load_ratio", 0.5))
131  , engine_(p.get<int64_t>("random_seed", time(nullptr)))
132  , pass_distn_(new std::uniform_int_distribution<int>(0, 100))
133 {
134  // Set limits on parameters
135  if (pass_factor_ > 100)
136  {
137  pass_factor_ = 100;
138  }
139  if (pass_factor_ < 0)
140  {
141  pass_factor_ = 0;
142  }
143  if (load_factor_ < 0.0)
144  {
145  load_factor_ = 0.0;
146  }
147  if (load_factor_ > 1.0)
148  {
149  load_factor_ = 1.0;
150  }
151 
152  if (min_ms_ < 0)
153  {
154  min_ms_ = 0;
155  }
156  if (min_ms_ > max_ms_)
157  {
158  max_ms_ = min_ms_;
159  }
160  if (mean_ms_ < 0)
161  {
162  mean_ms_ = 0;
163  }
164  if (sigma_ms_ < 0)
165  {
166  sigma_ms_ = 0;
167  }
168 
169  auto type = p.get<std::string>("distribution_type", "Uniform");
170  assert(!type.empty());
171  switch (type[0])
172  {
173  case 'n':
174  case 'N':
175  TLOG(TLVL_INFO) << "Generating delay times using Normal distribution with mean " << mean_ms_ << " ms, std. dev. " << sigma_ms_ << " ms, min " << min_ms_ << " ms and max " << max_ms_ << "ms.";
176  distribution_type_ = DistType::Normal;
177  if (mean_ms_ < min_ms_)
178  {
179  TLOG(TLVL_WARNING) << "Mean is smaller than min, setting to min";
180  mean_ms_ = min_ms_;
181  }
182  mean_ms_ -= min_ms_; // When we sample the distribution, we offset by min_ms_
183  normal_distn_ = std::make_unique<std::normal_distribution<double>>(mean_ms_, sigma_ms_);
184  break;
185  case 'e':
186  case 'E':
187  TLOG(TLVL_INFO) << "Generating delay times using Exponential distribution with mean " << mean_ms_ << " ms, min " << min_ms_ << " ms and max " << max_ms_ << " ms.";
188  distribution_type_ = DistType::Exponential;
189  if (mean_ms_ < min_ms_)
190  {
191  TLOG(TLVL_WARNING) << "Mean is smaller than min, setting to min";
192  mean_ms_ = min_ms_;
193  }
194  mean_ms_ -= min_ms_; // When we sample the distribution, we offset by min_ms_
195  if (mean_ms_ == 0)
196  {
197  mean_ms_ = 1;
198  }
199  exponential_distn_ = std::make_unique<std::exponential_distribution<double>>(1 / mean_ms_);
200  break;
201  case 'U':
202  case 'u':
203  TLOG(TLVL_INFO) << "Generating delay times using Uniform distribution with min " << min_ms_ << " ms and max " << max_ms_ << " ms.";
204  distribution_type_ = DistType::Uniform;
205  uniform_distn_ = std::make_unique<std::uniform_real_distribution<double>>(min_ms_, max_ms_);
206  break;
207  case 'f':
208  case 'F':
209  default:
210  TLOG(TLVL_INFO) << "Delay time set to " << min_ms_ << " ms.";
211  distribution_type_ = DistType::Fixed;
212  break;
213  }
214 }
215 
217 {
218  double delay = min_ms_;
219  do
220  {
221  switch (distribution_type_)
222  {
223  case DistType::Normal:
224  delay += (*normal_distn_)(engine_);
225  break;
226  case DistType::Exponential:
227  delay += (*exponential_distn_)(engine_);
228  break;
229  case DistType::Uniform:
230  delay = (*uniform_distn_)(engine_);
231  break;
232  case DistType::Fixed:
233  break;
234  }
235  } while (delay > max_ms_ && delay < min_ms_);
236  TLOG(TLVL_DEBUG) << "Simulating processing of event " << e.event() << " by delaying " << delay << "ms.";
237 
238  usleep(static_cast<unsigned>(1000 * (1 - load_factor_) * delay));
239 
240  auto i = 0;
241  auto now = std::chrono::steady_clock::now();
242  while (TimeUtils::GetElapsedTimeMilliseconds(now) < static_cast<size_t>(delay * load_factor_))
243  {
244  i = i + 1 % std::numeric_limits<int>::max();
245  }
246 
247  return (*pass_distn_)(engine_) < pass_factor_;
248 }
249 
250 DEFINE_ART_MODULE(artdaq::RandomDelayFilter)// NOLINT(performance-unnecessary-value-param)
RandomDelayFilter(fhicl::ParameterSet const &p)
RandomDelayFilter Constructor.
bool filter(art::Event &e) override
Filter is a required override of art::EDFilter, and is called for each event.
A filter which delays for a random amount of time, then drops a random fraction of events...
RandomDelayFilter & operator=(RandomDelayFilter const &)=delete
Copy Assignment operator is deleted.