1
#pragma once
2

            
3
#include <cstdint>
4
#include <memory>
5
#include <vector>
6

            
7
#include "envoy/upstream/upstream.h"
8

            
9
#include "source/common/upstream/edf_scheduler.h"
10

            
11
#include "absl/types/optional.h"
12

            
13
namespace Envoy {
14
namespace Upstream {
15

            
16
class LocalityWrr {
17
public:
18
  explicit LocalityWrr(const HostSet& host_set, uint64_t seed);
19

            
20
  absl::optional<uint32_t> chooseHealthyLocality();
21
  absl::optional<uint32_t> chooseDegradedLocality();
22

            
23
private:
24
  struct LocalityEntry {
25
    LocalityEntry(uint32_t index, double effective_weight)
26
112
        : index_(index), effective_weight_(effective_weight) {}
27
    const uint32_t index_;
28
    const double effective_weight_;
29
  };
30

            
31
  // Rebuilds the provided locality scheduler with locality entries based on the locality weights
32
  // and eligible hosts.
33
  //
34
  // @param locality_scheduler the locality scheduler to rebuild. Will be set to nullptr if no
35
  // localities are eligible.
36
  // @param locality_entries the vector that holds locality entries. Will be reset and populated
37
  // with entries corresponding to the new scheduler.
38
  // @param eligible_hosts_per_locality eligible hosts for this scheduler grouped by locality.
39
  // @param eligible_hosts all eligible hosts for this scheduler.
40
  // @param all_hosts_per_locality all hosts for this HostSet grouped by locality.
41
  // @param locality_weights the weighting of each locality.
42
  // @param overprovisioning_factor the overprovisioning factor to use when computing the effective
43
  // weight of a locality.
44
  // @param seed a random number of initial picks to "invoke" on the locality scheduler. This
45
  // allows to distribute the load between different localities across worker threads and a fleet
46
  // of Envoys.
47
  static void
48
  rebuildLocalityScheduler(std::unique_ptr<EdfScheduler<LocalityEntry>>& locality_scheduler,
49
                           std::vector<std::shared_ptr<LocalityEntry>>& locality_entries,
50
                           const HostsPerLocality& eligible_hosts_per_locality,
51
                           const HostVector& eligible_hosts,
52
                           HostsPerLocalityConstSharedPtr all_hosts_per_locality,
53
                           HostsPerLocalityConstSharedPtr excluded_hosts_per_locality,
54
                           LocalityWeightsConstSharedPtr locality_weights,
55
                           uint32_t overprovisioning_factor, uint64_t seed);
56
  // Weight for a locality taking into account health status using the provided eligible hosts per
57
  // locality.
58
  static double effectiveLocalityWeight(uint32_t index,
59
                                        const HostsPerLocality& eligible_hosts_per_locality,
60
                                        const HostsPerLocality& excluded_hosts_per_locality,
61
                                        const HostsPerLocality& all_hosts_per_locality,
62
                                        const LocalityWeights& locality_weights,
63
                                        uint32_t overprovisioning_factor);
64

            
65
  static absl::optional<uint32_t> chooseLocality(EdfScheduler<LocalityEntry>* locality_scheduler);
66

            
67
  std::vector<std::shared_ptr<LocalityEntry>> healthy_locality_entries_;
68
  std::unique_ptr<EdfScheduler<LocalityEntry>> healthy_locality_scheduler_;
69
  std::vector<std::shared_ptr<LocalityEntry>> degraded_locality_entries_;
70
  std::unique_ptr<EdfScheduler<LocalityEntry>> degraded_locality_scheduler_;
71
};
72

            
73
} // namespace Upstream
74
} // namespace Envoy