artdaq  v3_12_02
CapacityTest_policy.cc
1 #include <cmath>
2 #include "artdaq/RoutingPolicies/PolicyMacros.hh"
3 #include "artdaq/RoutingPolicies/RoutingManagerPolicy.hh"
4 #include "fhiclcpp/ParameterSet.h"
5 
6 namespace artdaq {
11 {
12 public:
22  explicit CapacityTestPolicy(const fhicl::ParameterSet& ps);
23 
27  ~CapacityTestPolicy() override = default;
28 
39  virtual void CreateRoutingTable(detail::RoutingPacket& output) override;
46  virtual detail::RoutingPacketEntry CreateRouteForSequenceID(artdaq::Fragment::sequence_id_t seq, int requesting_rank) override;
47 
48 private:
49  std::pair<size_t, std::map<int, int>> sortTokens_();
50  void restoreUnusedTokens_(std::map<int, int> const& sorted_tokens);
51 
52  CapacityTestPolicy(CapacityTestPolicy const&) = delete;
54  CapacityTestPolicy& operator=(CapacityTestPolicy const&) = delete;
55  CapacityTestPolicy& operator=(CapacityTestPolicy&&) = delete;
56 
57  int tokenUsagePercent_;
58 };
59 
60 CapacityTestPolicy::CapacityTestPolicy(const fhicl::ParameterSet& ps)
62  , tokenUsagePercent_(ps.get<int>("tokens_used_per_table_percent", 50))
63 {}
64 
66 {
67  auto sorted_tokens = sortTokens_();
68  size_t tokenCount = sorted_tokens.first;
69  auto table = sorted_tokens.second;
70  size_t tokensToUse = ceil(tokenCount * tokenUsagePercent_ / 100.0);
71 
72  for (auto r : table)
73  {
74  bool breakCondition = false;
75  while (table[r.first] > 0)
76  {
77  output.emplace_back(detail::RoutingPacketEntry(next_sequence_id_++, r.first));
78  table[r.first]--;
80  if (tokens_used_since_last_update_ >= tokensToUse)
81  {
82  breakCondition = true;
83  break;
84  }
85  }
86  if (breakCondition)
87  {
88  break;
89  }
90  }
91 
92  restoreUnusedTokens_(table);
93 }
94 
96 {
97  // TODO, ELF 09/22/2020: Do we want to use the tokens_used_per_table_percent limitation here, too?
99  auto sorted_tokens = sortTokens_();
100  if (sorted_tokens.first == 0) return output; // Trivial case: no tokens
101  auto dest = sorted_tokens.second.begin()->first;
102  sorted_tokens.second[dest]--;
104  restoreUnusedTokens_(sorted_tokens.second);
105 
106  output = detail::RoutingPacketEntry(seq, dest);
107 
108  return output;
109 }
110 
111 std::pair<size_t, std::map<int, int>> CapacityTestPolicy::sortTokens_()
112 {
113  auto output = std::make_pair(0, std::map<int, int>());
114  for (auto token : tokens_)
115  {
116  output.second[token]++;
117  output.first++;
118  }
119  tokens_.clear();
120  return output;
121 }
122 
123 void CapacityTestPolicy::restoreUnusedTokens_(std::map<int, int> const& sorted_tokens)
124 {
125  for (auto r : sorted_tokens)
126  {
127  for (auto i = 0; i < r.second; ++i)
128  {
129  tokens_.push_back(r.first);
130  }
131  }
132 }
133 
134 } // namespace artdaq
135 
136 DEFINE_ARTDAQ_ROUTING_POLICY(artdaq::CapacityTestPolicy)
virtual void CreateRoutingTable(detail::RoutingPacket &output) override
Add entries to the given RoutingPacket using currently-held tokens.
A row of the Routing Table.
Fragment::sequence_id_t next_sequence_id_
The next sequence ID to be assigned.
The interface through which RoutingManagerCore obtains Routing Tables using received Routing Tokens...
virtual detail::RoutingPacketEntry CreateRouteForSequenceID(artdaq::Fragment::sequence_id_t seq, int requesting_rank) override
Get an artdaq::detail::RoutingPacketEntry for a given sequence ID and rank. Used by RequestBasedEvent...
~CapacityTestPolicy() override=default
Default virtual Destructor.
std::vector< RoutingPacketEntry > RoutingPacket
A RoutingPacket is simply a vector of RoutingPacketEntry objects. It is not suitable for network tran...
A RoutingManagerPolicy which tries to fully load the first receiver, then the second, and so on.
std::deque< int > tokens_
The list of tokens which are available for use.
CapacityTestPolicy(const fhicl::ParameterSet &ps)
CapacityTestPolicy Constructor.
std::atomic< size_t > tokens_used_since_last_update_
Number of tokens consumed since last metric update.