artdaq  v3_07_01
RoundRobin_policy.cc
1 #include "artdaq/DAQdata/Globals.hh"
2 #define TRACE_NAME (app_name + "_RoundRobin_policy").c_str()
3 
4 #include "artdaq/RoutingPolicies/PolicyMacros.hh"
5 #include "artdaq/RoutingPolicies/RoutingMasterPolicy.hh"
6 
7 #include "fhiclcpp/ParameterSet.h"
8 #include "tracemf.h"
9 
10 namespace artdaq {
16 {
17 public:
25  explicit RoundRobinPolicy(fhicl::ParameterSet ps)
27  , minimum_participants_(ps.get<int>("minimum_participants", 0))
28  {
29  }
30 
34  virtual ~RoundRobinPolicy() = default;
35 
45 
46 private:
47  int minimum_participants_;
48 };
49 
51 {
52  TLOG(12) << "RoundRobinPolicy::GetCurrentTable start";
53  auto tokens = getTokensSnapshot();
54  TLOG(13) << "RoundRobinPolicy::GetCurrentTable token list size is " << tokens->size();
55  std::map<int, int> table;
56  for (auto token : *tokens.get())
57  {
58  TLOG(14) << "RoundRobinPolicy::GetCurrentTable adding token for rank " << token << " to table";
59  table[token]++;
60  }
61  tokens->clear();
62  TLOG(13) << "RoundRobinPolicy::GetCurrentTable table size is " << table.size() << ", token list size is " << tokens->size();
63 
64  detail::RoutingPacket output;
65 
66  // If 0 or negative, add minimum_participants_ to GetRecevierCount to ensure that it's correct
67  // 02-Apr-2019, KAB: changed the declared type of "minimum" from 'auto' to 'int' to avoid the
68  // situation in which the compiler chooses a type of 'unsigned int', the minimum_participants_ is
69  // a negative number that is larger (in absolute value) to the receiver count, and "minimum"
70  // ends up with a large positive value.
71  int minimum = minimum_participants_ > 0 ? minimum_participants_ : GetReceiverCount() + minimum_participants_;
72  if (minimum < 1) minimum = 1; // Can't go below 1
73  if (minimum > static_cast<int>(GetReceiverCount())) minimum = GetReceiverCount(); // Can't go above receiver count
74 
75  bool endCondition = table.size() < static_cast<size_t>(minimum);
76  TLOG(15) << "RoundRobinPolicy::GetCurrentTable initial endCondition is " << endCondition << ", minimum is " << minimum;
77 
78  while (!endCondition)
79  {
80  for (auto it = table.begin(); it != table.end();)
81  {
82  TLOG(16) << "RoundRobinPolicy::GetCurrentTable assigning sequenceID " << next_sequence_id_ << " to rank " << it->first;
83  output.emplace_back(detail::RoutingPacketEntry(next_sequence_id_++, it->first));
84  table[it->first]--;
85 
86  if (table[it->first] <= 0)
87  it = table.erase(it);
88  else
89  ++it;
90  }
91  endCondition = table.size() < static_cast<size_t>(minimum);
92  }
93 
94  for (auto r : table)
95  {
96  for (auto i = 0; i < r.second; ++i)
97  {
98  tokens->push_back(r.first);
99  }
100  }
101  TLOG(13) << "RoundRobinPolicy::GetCurrentTable unused tokens for " << tokens->size() << " ranks will be saved for later";
102  addUnusedTokens(std::move(tokens));
103 
104  TLOG(12) << "RoundRobinPolicy::GetCurrentTable return with table size " << output.size();
105  return output;
106 }
107 } // namespace artdaq
108 
109 DEFINE_ARTDAQ_ROUTING_POLICY(artdaq::RoundRobinPolicy)
A row of the Routing Table.
A RoutingMasterPolicy which evenly distributes Sequence IDs to all receivers. If an uneven number of ...
virtual ~RoundRobinPolicy()=default
Default virtual Destructor.
The interface through which RoutingMasterCore obtains Routing Tables using received Routing Tokens...
detail::RoutingPacket GetCurrentTable() override
Create a Routing Table using the tokens that have been received.
std::vector< RoutingPacketEntry > RoutingPacket
A RoutingPacket is simply a vector of RoutingPacketEntry objects. It is not suitable for network tran...
Fragment::sequence_id_t next_sequence_id_
The next sequence ID to be assigned.
std::unique_ptr< std::deque< int > > getTokensSnapshot()
Gets the current token list, used for building Routing Tables.
void addUnusedTokens(std::unique_ptr< std::deque< int >> tokens)
If necessary, return unused tokens to the token list, for subsequent updates.
RoundRobinPolicy(fhicl::ParameterSet ps)
RoundRobinPolicy Constructor.
size_t GetReceiverCount() const
Get the number of configured receivers.