1
#pragma once
2

            
3
#include <memory>
4

            
5
#include "envoy/server/factory_context.h"
6
#include "envoy/upstream/load_balancer.h"
7

            
8
#include "source/common/upstream/load_balancer_factory_base.h"
9

            
10
namespace Envoy {
11
namespace Extensions {
12
namespace LoadBalancingPolicies {
13
namespace Common {
14

            
15
template <class ProtoType, class Impl>
16
class FactoryBase : public Upstream::TypedLoadBalancerFactoryBase<ProtoType> {
17
public:
18
2777
  FactoryBase(const std::string& name) : Upstream::TypedLoadBalancerFactoryBase<ProtoType>(name) {}
19

            
20
  Upstream::ThreadAwareLoadBalancerPtr create(OptRef<const Upstream::LoadBalancerConfig> lb_config,
21
                                              const Upstream::ClusterInfo& cluster_info,
22
                                              const Upstream::PrioritySet& priority_set,
23
                                              Runtime::Loader& runtime,
24
                                              Envoy::Random::RandomGenerator& random,
25
17310
                                              TimeSource& time_source) override {
26

            
27
17310
    return std::make_unique<ThreadAwareLb>(std::make_shared<LbFactory>(
28
17310
        lb_config, cluster_info, priority_set, runtime, random, time_source));
29
17310
  }
30

            
31
private:
32
  class LbFactory : public Upstream::LoadBalancerFactory {
33
  public:
34
    LbFactory(OptRef<const Upstream::LoadBalancerConfig> lb_config,
35
              const Upstream::ClusterInfo& cluster_info, const Upstream::PrioritySet& priority_set,
36
              Runtime::Loader& runtime, Envoy::Random::RandomGenerator& random,
37
              TimeSource& time_source)
38
17310
        : lb_config_(lb_config), cluster_info_(cluster_info), priority_set_(priority_set),
39
17310
          runtime_(runtime), random_(random), time_source_(time_source) {}
40

            
41
33147
    Upstream::LoadBalancerPtr create(Upstream::LoadBalancerParams params) override {
42
33147
      return Impl()(params, lb_config_, cluster_info_, priority_set_, runtime_, random_,
43
33147
                    time_source_);
44
33147
    }
45

            
46
33449
    bool recreateOnHostChange() const override { return false; }
47

            
48
  public:
49
    OptRef<const Upstream::LoadBalancerConfig> lb_config_;
50

            
51
    const Upstream::ClusterInfo& cluster_info_;
52
    const Upstream::PrioritySet& priority_set_;
53
    Runtime::Loader& runtime_;
54
    Envoy::Random::RandomGenerator& random_;
55
    TimeSource& time_source_;
56
  };
57

            
58
  class ThreadAwareLb : public Upstream::ThreadAwareLoadBalancer {
59
  public:
60
17310
    ThreadAwareLb(Upstream::LoadBalancerFactorySharedPtr factory) : factory_(std::move(factory)) {}
61

            
62
17856
    Upstream::LoadBalancerFactorySharedPtr factory() override { return factory_; }
63
17100
    absl::Status initialize() override { return absl::OkStatus(); }
64

            
65
  private:
66
    Upstream::LoadBalancerFactorySharedPtr factory_;
67
  };
68

            
69
  const std::string name_;
70
};
71

            
72
/**
73
 * Helper class to hold either a legacy or production config.
74
 */
75
template <class ActiveType, class LegacyType> class ActiveOrLegacy {
76
public:
77
  template <class BaseType> static ActiveOrLegacy get(const BaseType* base) {
78
    auto* active_type = dynamic_cast<const ActiveType*>(base);
79
    if (active_type != nullptr) {
80
      return {active_type};
81
    }
82
    auto* legacy_type = dynamic_cast<const LegacyType*>(base);
83
    if (legacy_type != nullptr) {
84
      return {legacy_type};
85
    }
86

            
87
    return {};
88
  }
89

            
90
  bool hasActive() const { return active_ != nullptr; }
91
  bool hasLegacy() const { return legacy_ != nullptr; }
92

            
93
  const ActiveType* active() const {
94
    ASSERT(hasActive());
95
    return active_;
96
  }
97
  const LegacyType* legacy() const {
98
    ASSERT(hasLegacy());
99
    return legacy_;
100
  }
101

            
102
private:
103
  ActiveOrLegacy() = default;
104
  ActiveOrLegacy(const ActiveType* active) : active_(active) {}
105
  ActiveOrLegacy(const LegacyType* legacy) : legacy_(legacy) {}
106

            
107
  const ActiveType* active_{};
108
  const LegacyType* legacy_{};
109
};
110

            
111
} // namespace Common
112
} // namespace LoadBalancingPolicies
113
} // namespace Extensions
114
} // namespace Envoy