1
#include "source/common/config/config_provider_impl.h"
2

            
3
namespace Envoy {
4
namespace Config {
5

            
6
ConfigSubscriptionCommonBase::ConfigSubscriptionCommonBase(
7
    const std::string& name, const uint64_t manager_identifier,
8
    ConfigProviderManagerImplBase& config_provider_manager,
9
    Server::Configuration::ServerFactoryContext& factory_context)
10
112
    : name_(name), tls_(factory_context.threadLocal()),
11
112
      local_init_target_(fmt::format("ConfigSubscriptionCommonBase local init target '{}'", name_),
12
112
                         [this]() { start(); }),
13
112
      parent_init_target_(fmt::format("ConfigSubscriptionCommonBase init target '{}'", name_),
14
112
                          [this]() { local_init_manager_.initialize(local_init_watcher_); }),
15
112
      local_init_watcher_(fmt::format("ConfigSubscriptionCommonBase local watcher '{}'", name_),
16
112
                          [this]() { parent_init_target_.ready(); }),
17
112
      local_init_manager_(
18
112
          fmt::format("ConfigSubscriptionCommonBase local init manager '{}'", name_)),
19
112
      manager_identifier_(manager_identifier), config_provider_manager_(config_provider_manager),
20
112
      time_source_(factory_context.timeSource()),
21
112
      last_updated_(factory_context.timeSource().systemTime()) {
22
112
  THROW_IF_NOT_OK(Envoy::Config::Utility::checkLocalInfo(name, factory_context.localInfo()));
23
111
  local_init_manager_.add(local_init_target_);
24
111
}
25

            
26
ImmutableConfigProviderBase::ImmutableConfigProviderBase(
27
    Server::Configuration::ServerFactoryContext& factory_context,
28
    ConfigProviderManagerImplBase& config_provider_manager,
29
    ConfigProviderInstanceType instance_type, ApiType api_type)
30
13
    : last_updated_(factory_context.timeSource().systemTime()),
31
13
      config_provider_manager_(config_provider_manager), instance_type_(instance_type),
32
13
      api_type_(api_type) {
33
13
  ASSERT(instance_type_ == ConfigProviderInstanceType::Static ||
34
13
         instance_type_ == ConfigProviderInstanceType::Inline);
35
13
  config_provider_manager_.bindImmutableConfigProvider(this);
36
13
}
37

            
38
13
ImmutableConfigProviderBase::~ImmutableConfigProviderBase() {
39
13
  config_provider_manager_.unbindImmutableConfigProvider(this);
40
13
}
41

            
42
111
ConfigSubscriptionCommonBase::~ConfigSubscriptionCommonBase() {
43
111
  local_init_target_.ready();
44
111
  config_provider_manager_.unbindSubscription(manager_identifier_);
45
111
}
46

            
47
280
void ConfigSubscriptionCommonBase::applyConfigUpdate(const ConfigUpdateCb& update_fn) {
48
492
  tls_.runOnAllThreads([update_fn](OptRef<ThreadLocalConfig> thread_local_config) {
49
492
    thread_local_config->config_ = update_fn(thread_local_config->config_);
50
492
  });
51
280
}
52

            
53
bool ConfigSubscriptionInstance::checkAndApplyConfigUpdate(const Protobuf::Message& config_proto,
54
                                                           const std::string& config_name,
55
5
                                                           const std::string& version_info) {
56
5
  const uint64_t new_hash = MessageUtil::hash(config_proto);
57
5
  if (config_info_) {
58
1
    ASSERT(config_info_.value().last_config_hash_.has_value());
59
1
    if (config_info_.value().last_config_hash_.value() == new_hash) {
60
1
      return false;
61
1
    }
62
1
  }
63

            
64
4
  config_info_ = {new_hash, version_info};
65
4
  ENVOY_LOG(debug, "{}: loading new configuration: config_name={} hash={}", name_, config_name,
66
4
            new_hash);
67
4
  ConfigProvider::ConfigConstSharedPtr new_config_impl = onConfigProtoUpdate(config_proto);
68
4
  applyConfigUpdate([new_config_impl](ConfigProvider::ConfigConstSharedPtr)
69
4
                        -> ConfigProvider::ConfigConstSharedPtr { return new_config_impl; });
70
4
  return true;
71
5
}
72

            
73
ConfigProviderManagerImplBase::ConfigProviderManagerImplBase(OptRef<Server::Admin> admin,
74
9573
                                                             const std::string& config_name) {
75
9573
  if (!admin.has_value()) {
76
    return;
77
  }
78
9573
  config_tracker_entry_ = admin->getConfigTracker().add(
79
9573
      config_name,
80
9573
      [this](const Matchers::StringMatcher& name_matcher) { return dumpConfigs(name_matcher); });
81
  // ConfigTracker keys must be unique. We are asserting that no one has stolen the key
82
  // from us, since the returned entry will be nullptr if the key already exists.
83
9573
  RELEASE_ASSERT(config_tracker_entry_, "");
84
9573
}
85

            
86
const ConfigProviderManagerImplBase::ConfigProviderSet&
87
35
ConfigProviderManagerImplBase::immutableConfigProviders(ConfigProviderInstanceType type) const {
88
35
  static ConfigProviderSet empty_set;
89
35
  ConfigProviderMap::const_iterator it;
90
35
  if ((it = immutable_config_providers_map_.find(type)) == immutable_config_providers_map_.end()) {
91
30
    return empty_set;
92
30
  }
93

            
94
5
  return *it->second;
95
35
}
96

            
97
void ConfigProviderManagerImplBase::bindImmutableConfigProvider(
98
13
    ImmutableConfigProviderBase* provider) {
99
13
  ConfigProviderMap::iterator it;
100
13
  if ((it = immutable_config_providers_map_.find(provider->instanceType())) ==
101
13
      immutable_config_providers_map_.end()) {
102
12
    immutable_config_providers_map_.insert(std::make_pair(
103
12
        provider->instanceType(),
104
12
        std::make_unique<ConfigProviderSet>(std::initializer_list<ConfigProvider*>({provider}))));
105
12
  } else {
106
1
    it->second->insert(provider);
107
1
  }
108
13
}
109

            
110
void ConfigProviderManagerImplBase::unbindImmutableConfigProvider(
111
13
    ImmutableConfigProviderBase* provider) {
112
13
  auto it = immutable_config_providers_map_.find(provider->instanceType());
113
13
  ASSERT(it != immutable_config_providers_map_.end());
114
13
  it->second->erase(provider);
115
13
}
116

            
117
} // namespace Config
118
} // namespace Envoy