Line data Source code
1 : #include "source/common/rds/route_config_provider_manager.h" 2 : 3 : #include "source/common/rds/util.h" 4 : 5 : namespace Envoy { 6 : namespace Rds { 7 : 8 : RouteConfigProviderManager::RouteConfigProviderManager(OptRef<Server::Admin> admin, 9 : const std::string& config_tracker_key, 10 : ProtoTraits& proto_traits) 11 96 : : proto_traits_(proto_traits) { 12 96 : if (!admin.has_value()) { 13 0 : return; 14 0 : } 15 96 : config_tracker_entry_ = admin->getConfigTracker().add( 16 96 : config_tracker_key, 17 96 : [this](const Matchers::StringMatcher& matcher) { return dumpRouteConfigs(matcher); }); 18 : // ConfigTracker keys must be unique. We are asserting that no one has stolen the "routes" key 19 : // from us, since the returned entry will be nullptr if the key already exists. 20 96 : RELEASE_ASSERT(config_tracker_entry_, ""); 21 96 : } 22 : 23 148 : void RouteConfigProviderManager::eraseStaticProvider(RouteConfigProvider* provider) { 24 148 : static_route_config_providers_.erase(provider); 25 148 : } 26 : 27 50 : void RouteConfigProviderManager::eraseDynamicProvider(uint64_t manager_identifier) { 28 50 : dynamic_route_config_providers_.erase(manager_identifier); 29 50 : } 30 : 31 : std::unique_ptr<envoy::admin::v3::RoutesConfigDump> 32 94 : RouteConfigProviderManager::dumpRouteConfigs(const Matchers::StringMatcher& name_matcher) const { 33 94 : auto config_dump = std::make_unique<envoy::admin::v3::RoutesConfigDump>(); 34 : 35 116 : for (const auto& element : dynamic_route_config_providers_) { 36 46 : const auto provider = element.second.first.lock(); 37 : // Because the RouteConfigProviderManager's weak_ptrs only get cleaned up 38 : // in the RdsRouteConfigSubscription destructor, and the single threaded nature 39 : // of this code, locking the weak_ptr will not fail. 40 46 : ASSERT(provider); 41 : 42 46 : if (provider->configInfo()) { 43 36 : if (!name_matcher.match( 44 36 : resourceName(proto_traits_, provider->configInfo().value().config_))) { 45 0 : continue; 46 0 : } 47 36 : auto* dynamic_config = config_dump->mutable_dynamic_route_configs()->Add(); 48 36 : dynamic_config->set_version_info(provider->configInfo().value().version_); 49 36 : MessageUtil::packFrom(*dynamic_config->mutable_route_config(), 50 36 : provider->configInfo().value().config_); 51 36 : TimestampUtil::systemClockToTimestamp(provider->lastUpdated(), 52 36 : *dynamic_config->mutable_last_updated()); 53 36 : } 54 46 : } 55 : 56 94 : for (const auto& provider : static_route_config_providers_) { 57 70 : ASSERT(provider->configInfo()); 58 70 : if (!name_matcher.match(resourceName(proto_traits_, provider->configInfo().value().config_))) { 59 0 : continue; 60 0 : } 61 70 : auto* static_config = config_dump->mutable_static_route_configs()->Add(); 62 70 : MessageUtil::packFrom(*static_config->mutable_route_config(), 63 70 : provider->configInfo().value().config_); 64 70 : TimestampUtil::systemClockToTimestamp(provider->lastUpdated(), 65 70 : *static_config->mutable_last_updated()); 66 70 : } 67 : 68 94 : return config_dump; 69 94 : } 70 : 71 : RouteConfigProviderPtr RouteConfigProviderManager::addStaticProvider( 72 74 : std::function<RouteConfigProviderPtr()> create_static_provider) { 73 74 : auto provider = create_static_provider(); 74 74 : static_route_config_providers_.insert(provider.get()); 75 74 : return provider; 76 74 : } 77 : 78 : RouteConfigProviderSharedPtr RouteConfigProviderManager::addDynamicProvider( 79 : const Protobuf::Message& rds, const std::string& route_config_name, Init::Manager& init_manager, 80 : std::function< 81 : std::pair<RouteConfigProviderSharedPtr, const Init::Target*>(uint64_t manager_identifier)> 82 66 : create_dynamic_provider) { 83 : // RdsRouteConfigSubscriptions are unique based on their serialized RDS config. 84 66 : const uint64_t manager_identifier = MessageUtil::hash(rds); 85 66 : auto existing_provider = 86 66 : reuseDynamicProvider(manager_identifier, init_manager, route_config_name); 87 : 88 66 : if (existing_provider) { 89 16 : return existing_provider; 90 16 : } 91 50 : auto new_provider = create_dynamic_provider(manager_identifier); 92 50 : init_manager.add(*new_provider.second); 93 50 : dynamic_route_config_providers_.insert({manager_identifier, new_provider}); 94 50 : return new_provider.first; 95 66 : } 96 : 97 : RouteConfigProviderSharedPtr 98 : RouteConfigProviderManager::reuseDynamicProvider(uint64_t manager_identifier, 99 : Init::Manager& init_manager, 100 66 : const std::string& route_config_name) { 101 66 : auto it = dynamic_route_config_providers_.find(manager_identifier); 102 66 : if (it == dynamic_route_config_providers_.end()) { 103 50 : return nullptr; 104 50 : } 105 : // Because the RouteConfigProviderManager's weak_ptrs only get cleaned up 106 : // in the RdsRouteConfigSubscription destructor, and the single threaded nature 107 : // of this code, locking the weak_ptr will not fail. 108 16 : auto existing_provider = it->second.first.lock(); 109 16 : RELEASE_ASSERT(existing_provider != nullptr, 110 16 : absl::StrCat("cannot find subscribed rds resource ", route_config_name)); 111 16 : init_manager.add(*it->second.second); 112 16 : return existing_provider; 113 16 : } 114 : 115 : } // namespace Rds 116 : } // namespace Envoy