1
#pragma once
2

            
3
#include "source/common/upstream/upstream_impl.h"
4
#include "source/extensions/load_balancing_policies/common/load_balancer_impl.h"
5

            
6
namespace Envoy {
7
namespace Extensions {
8
namespace Clusters {
9
namespace Aggregate {
10

            
11
// AggregateLoadBalancerContext wraps the load balancer context to re-assign priority load
12
// according the to host priority selected by the aggregate load balancer.
13
class AggregateLoadBalancerContext : public Upstream::LoadBalancerContextBase {
14
public:
15
  AggregateLoadBalancerContext(Upstream::LoadBalancerContext* context,
16
                               Upstream::LoadBalancerBase::HostAvailability host_availability,
17
                               uint32_t host_priority)
18
1282
      : host_availability_(host_availability), host_priority_(host_priority) {
19
1282
    if (context == nullptr) {
20
1245
      owned_context_ = std::make_unique<Upstream::LoadBalancerContextBase>();
21
1245
      context_ = owned_context_.get();
22
1281
    } else {
23
37
      context_ = context;
24
37
    }
25
1282
  }
26

            
27
  // Upstream::LoadBalancerContext
28
1
  absl::optional<uint64_t> computeHashKey() override { return context_->computeHashKey(); }
29
1
  const Network::Connection* downstreamConnection() const override {
30
1
    return context_->downstreamConnection();
31
1
  }
32
1
  const Router::MetadataMatchCriteria* metadataMatchCriteria() override {
33
1
    return context_->metadataMatchCriteria();
34
1
  }
35
1
  const Http::RequestHeaderMap* downstreamHeaders() const override {
36
1
    return context_->downstreamHeaders();
37
1
  }
38
  const Upstream::HealthyAndDegradedLoad&
39
  determinePriorityLoad(const Upstream::PrioritySet&,
40
                        const Upstream::HealthyAndDegradedLoad& original_priority_load,
41
781
                        const Upstream::RetryPriority::PriorityMappingFunc&) override {
42
    // Re-assign load. Set all traffic to the priority and availability selected in aggregate
43
    // cluster.
44
    //
45
    // Note: context_->determinePriorityLoad() was already called and its result handled in
46
    // AggregateClusterLoadBalancer::LoadBalancerImpl::chooseHost().
47
781
    const size_t priorities = original_priority_load.healthy_priority_load_.get().size();
48
781
    priority_load_.healthy_priority_load_.get().assign(priorities, 0);
49
781
    priority_load_.degraded_priority_load_.get().assign(priorities, 0);
50

            
51
781
    if (host_availability_ == Upstream::LoadBalancerBase::HostAvailability::Healthy) {
52
545
      priority_load_.healthy_priority_load_.get()[host_priority_] = 100;
53
545
    } else {
54
236
      priority_load_.degraded_priority_load_.get()[host_priority_] = 100;
55
236
    }
56
781
    return priority_load_;
57
781
  }
58
780
  bool shouldSelectAnotherHost(const Upstream::Host& host) override {
59
780
    return context_->shouldSelectAnotherHost(host);
60
780
  }
61
780
  uint32_t hostSelectionRetryCount() const override { return context_->hostSelectionRetryCount(); }
62
1
  Network::Socket::OptionsSharedPtr upstreamSocketOptions() const override {
63
1
    return context_->upstreamSocketOptions();
64
1
  }
65
1
  Network::TransportSocketOptionsConstSharedPtr upstreamTransportSocketOptions() const override {
66
1
    return context_->upstreamTransportSocketOptions();
67
1
  }
68
1
  void setHeadersModifier(std::function<void(Http::ResponseHeaderMap&)> modifier) override {
69
1
    context_->setHeadersModifier(std::move(modifier));
70
1
  }
71

            
72
private:
73
  Upstream::HealthyAndDegradedLoad priority_load_;
74
  std::unique_ptr<Upstream::LoadBalancerContext> owned_context_;
75
  Upstream::LoadBalancerContext* context_{nullptr};
76
  const Upstream::LoadBalancerBase::HostAvailability host_availability_;
77
  const uint32_t host_priority_;
78
};
79

            
80
} // namespace Aggregate
81
} // namespace Clusters
82
} // namespace Extensions
83
} // namespace Envoy