artdaq  v3_11_01
PreferSameHost_policy.cc
1 #include "artdaq/DAQdata/Globals.hh"
2 #define TRACE_NAME (app_name + "_PreferSameHost_policy").c_str()
3 
4 #include "artdaq/DAQdata/HostMap.hh"
5 #include "artdaq/RoutingPolicies/PolicyMacros.hh"
6 #include "artdaq/RoutingPolicies/RoutingManagerPolicy.hh"
7 
8 #include "fhiclcpp/ParameterSet.h"
9 #include "tracemf.h"
10 
11 namespace artdaq {
16 {
17 public:
25  explicit PreferSameHostPolicy(const fhicl::ParameterSet& ps)
27  , minimum_participants_(ps.get<int>("minimum_participants", 0))
28  , host_map_(MakeHostMap(ps))
29  {
30  }
31 
35  ~PreferSameHostPolicy() override = default;
36 
45  void CreateRoutingTable(detail::RoutingPacket& output) override;
52  detail::RoutingPacketEntry CreateRouteForSequenceID(artdaq::Fragment::sequence_id_t seq, int requesting_rank) override;
53 
54 private:
57  PreferSameHostPolicy& operator=(PreferSameHostPolicy const&) = delete;
58  PreferSameHostPolicy& operator=(PreferSameHostPolicy&&) = delete;
59 
60  std::map<int, int> sortTokens_();
61  void restoreUnusedTokens_(std::map<int, int> const& sorted_tokens_);
62  int calculateMinimum_();
63 
64  int minimum_participants_;
65  hostMap_t host_map_;
66 };
67 
69 {
70  TLOG(12) << "PreferSameHostPolicy::GetCurrentTable token list size is " << tokens_.size();
71  auto table = sortTokens_();
72  TLOG(13) << "PreferSameHostPolicy::GetCurrentTable table size is " << table.size();
73 
74  int minimum = calculateMinimum_();
75  bool endCondition = table.size() < static_cast<size_t>(minimum);
76  TLOG(15) << "PreferSameHostPolicy::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) << "PreferSameHostPolicy::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  {
88  it = table.erase(it);
89  }
90  else
91  {
92  ++it;
93  }
94  }
95  endCondition = table.size() < static_cast<size_t>(minimum);
96  }
97 
98  restoreUnusedTokens_(table);
99  TLOG(13) << "PreferSameHostPolicy::GetCurrentTable " << tokens_.size() << " unused tokens will be saved for later";
100 
101  TLOG(12) << "PreferSameHostPolicy::GetCurrentTable return with table size " << output.size();
102 }
103 detail::RoutingPacketEntry PreferSameHostPolicy::CreateRouteForSequenceID(artdaq::Fragment::sequence_id_t seq, int requesting_rank)
104 {
106  auto table = sortTokens_();
107 
108  // Trivial case: no tokens
109  if (table.empty()) return output;
110 
111  if (host_map_.count(requesting_rank) == 0)
112  {
113  TLOG(TLVL_WARNING) << "Received Routing Request from rank " << requesting_rank << ", which is not in my Host Map!";
114  }
115  auto host = host_map_[requesting_rank];
116 
117  // First try to find a match
118  std::set<int> matching_ranks_;
119  int max_rank = -1;
120  int max_rank_tokens = 0;
121  for (auto& entry : table)
122  {
123  if (entry.second == 0) continue;
124  if (host_map_.count(entry.first) == 0)
125  {
126  TLOG(TLVL_WARNING) << "Receiver rank " << entry.first << " is not in the host map! Is this policy configured correctly?!";
127  }
128  else
129  {
130  if (host_map_[entry.first] == host)
131  {
132  matching_ranks_.insert(entry.first);
133  }
134  }
135  if (entry.second > max_rank_tokens)
136  {
137  max_rank = entry.first;
138  max_rank_tokens = entry.second;
139  }
140  }
141 
142  if (matching_ranks_.size() == 0)
143  {
144  output = detail::RoutingPacketEntry(seq, max_rank);
145  table[max_rank]--;
146  }
147  else if (matching_ranks_.size() == 1)
148  {
149  output = detail::RoutingPacketEntry(seq, *matching_ranks_.begin());
150  table[*matching_ranks_.begin()]--;
151  }
152  else
153  {
154  // Find the most tokens in matching_ranks_
155  int max = 0;
156  int max_rank = -1;
157  for (auto& rank : matching_ranks_)
158  {
159  if (table[rank] > max)
160  {
161  max = table[rank];
162  max_rank = rank;
163  }
164  }
165  output = detail::RoutingPacketEntry(seq, max_rank);
166  table[max_rank]--;
167  }
168 
169  restoreUnusedTokens_(table);
170  return output;
171 }
172 std::map<int, int> PreferSameHostPolicy::sortTokens_()
173 {
174  auto output = std::map<int, int>();
175  for (auto token : tokens_)
176  {
177  output[token]++;
178  }
179  tokens_.clear();
180  return output;
181 }
182 
183 void PreferSameHostPolicy::restoreUnusedTokens_(std::map<int, int> const& sorted_tokens)
184 {
185  for (auto r : sorted_tokens)
186  {
187  for (auto i = 0; i < r.second; ++i)
188  {
189  tokens_.push_back(r.first);
190  }
191  }
192 }
193 
194 int PreferSameHostPolicy::calculateMinimum_()
195 {
196  // If 0 or negative, add minimum_participants_ to GetRecevierCount to ensure that it's correct
197  // 02-Apr-2019, KAB: changed the declared type of "minimum" from 'auto' to 'int' to avoid the
198  // situation in which the compiler chooses a type of 'unsigned int', the minimum_participants_ is
199  // a negative number that is larger (in absolute value) to the receiver count, and "minimum"
200  // ends up with a large positive value.
201  int minimum = minimum_participants_ > 0 ? minimum_participants_ : GetReceiverCount() + minimum_participants_;
202  if (minimum < 1)
203  {
204  minimum = 1; // Can't go below 1
205  }
206  return minimum;
207 }
208 
209 } // namespace artdaq
210 
211 DEFINE_ARTDAQ_ROUTING_POLICY(artdaq::PreferSameHostPolicy)
A row of the Routing Table.
PreferSameHostPolicy(const fhicl::ParameterSet &ps)
PreferSameHostPolicy Constructor.
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...
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...
void CreateRoutingTable(detail::RoutingPacket &output) override
Generate a set of Routing Tables using received tokens.
~PreferSameHostPolicy() 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 keep data on the same host. For EventBuilding mode...
size_t GetReceiverCount() const
Get the number of configured receivers.
std::deque< int > tokens_
The list of tokens which are available for use.
std::map< int, std::string > hostMap_t
The host_map is a map associating ranks with artdaq::DestinationInfo objects.
Definition: HostMap.hh:40
hostMap_t MakeHostMap(fhicl::ParameterSet const &pset, hostMap_t map=hostMap_t())
Make a hostMap_t from a HostMap::Config ParameterSet
Definition: HostMap.hh:66