LCOV - code coverage report
Current view: top level - envoy/registry - registry.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 163 262 62.2 %
Date: 2024-01-05 06:35:25 Functions: 1451 2675 54.2 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <algorithm>
       4             : #include <functional>
       5             : #include <map>
       6             : #include <string>
       7             : #include <vector>
       8             : 
       9             : #include "envoy/common/exception.h"
      10             : #include "envoy/config/core/v3/base.pb.h"
      11             : 
      12             : #include "source/common/common/assert.h"
      13             : #include "source/common/common/fmt.h"
      14             : #include "source/common/common/logger.h"
      15             : #include "source/common/common/utility.h"
      16             : #include "source/common/protobuf/utility.h"
      17             : 
      18             : #include "absl/base/attributes.h"
      19             : #include "absl/container/flat_hash_map.h"
      20             : #include "absl/strings/str_join.h"
      21             : #include "absl/strings/string_view.h"
      22             : #include "fmt/ranges.h"
      23             : 
      24             : namespace Envoy {
      25             : namespace Registry {
      26             : 
      27             : template <class Base> class FactoryRegistry;
      28             : template <class T, class Base> class RegisterFactory;
      29             : 
      30             : /**
      31             :  * FactoryRegistryProxy is a proxy object that provides access to the
      32             :  * static methods of a strongly-typed factory registry.
      33             :  */
      34             : class FactoryRegistryProxy {
      35             : public:
      36           0 :   virtual ~FactoryRegistryProxy() = default;
      37             :   virtual std::vector<absl::string_view> registeredNames() const PURE;
      38             :   // Return all registered factory names, including disabled factories.
      39             :   virtual std::vector<absl::string_view> allRegisteredNames() const PURE;
      40             :   virtual absl::optional<envoy::config::core::v3::BuildVersion>
      41             :   getFactoryVersion(absl::string_view name) const PURE;
      42             :   virtual bool disableFactory(absl::string_view) PURE;
      43             :   virtual bool isFactoryDisabled(absl::string_view) const PURE;
      44             :   virtual absl::flat_hash_map<std::string, std::vector<std::string>> registeredTypes() const PURE;
      45             :   virtual absl::string_view canonicalFactoryName(absl::string_view) const PURE;
      46             : };
      47             : 
      48             : template <class Base> class FactoryRegistryProxyImpl : public FactoryRegistryProxy {
      49             : public:
      50             :   using FactoryRegistry = Envoy::Registry::FactoryRegistry<Base>;
      51             : 
      52           0 :   std::vector<absl::string_view> registeredNames() const override {
      53           0 :     return FactoryRegistry::registeredNames();
      54           0 :   }
      55             : 
      56        6532 :   std::vector<absl::string_view> allRegisteredNames() const override {
      57        6532 :     return FactoryRegistry::registeredNames(true);
      58        6532 :   }
      59             : 
      60             :   absl::optional<envoy::config::core::v3::BuildVersion>
      61       22410 :   getFactoryVersion(absl::string_view name) const override {
      62       22410 :     return FactoryRegistry::getFactoryVersion(name);
      63       22410 :   }
      64             : 
      65           0 :   bool disableFactory(absl::string_view name) override {
      66           0 :     return FactoryRegistry::disableFactory(name);
      67           0 :   }
      68             : 
      69       22410 :   bool isFactoryDisabled(absl::string_view name) const override {
      70       22410 :     return FactoryRegistry::isFactoryDisabled(name);
      71       22410 :   }
      72             : 
      73        6532 :   absl::flat_hash_map<std::string, std::vector<std::string>> registeredTypes() const override {
      74        6532 :     return FactoryRegistry::registeredTypes();
      75        6532 :   }
      76             : 
      77           0 :   absl::string_view canonicalFactoryName(absl::string_view name) const override {
      78           0 :     return FactoryRegistry::canonicalFactoryName(name);
      79           0 :   }
      80             : };
      81             : 
      82             : /**
      83             :  * BaseFactoryCategoryRegistry holds the static factory map for
      84             :  * FactoryCategoryRegistry, ensuring that friends of that class
      85             :  * cannot get non-const access to it.
      86             :  */
      87             : class BaseFactoryCategoryRegistry {
      88             : protected:
      89             :   using MapType = absl::flat_hash_map<std::string, FactoryRegistryProxy*>;
      90             : 
      91        7863 :   static MapType& factories() {
      92        7863 :     static auto* factories = new MapType();
      93        7863 :     return *factories;
      94        7863 :   }
      95             : };
      96             : 
      97             : /**
      98             :  * FactoryCategoryRegistry registers factory registries by their
      99             :  * declared category. The category is exposed by a static category()
     100             :  * method on the factory base type.
     101             :  *
     102             :  * Only RegisterFactory instances are able to register factory registries.
     103             :  */
     104             : class FactoryCategoryRegistry : public BaseFactoryCategoryRegistry {
     105             : public:
     106             :   /**
     107             :    * @return a read-only reference to the map of registered factory
     108             :    * registries.
     109             :    */
     110         269 :   static const MapType& registeredFactories() { return factories(); }
     111             : 
     112             :   /**
     113             :    * @return whether the given category name is already registered.
     114             :    */
     115        3049 :   static bool isRegistered(absl::string_view category) {
     116        3049 :     return factories().find(category) != factories().end();
     117        3049 :   }
     118             : 
     119           0 :   static bool disableFactory(absl::string_view category, absl::string_view name) {
     120           0 :     auto registry = factories().find(category);
     121             : 
     122           0 :     if (registry != factories().end()) {
     123           0 :       return registry->second->disableFactory(name);
     124           0 :     }
     125             : 
     126           0 :     return false;
     127           0 :   }
     128             : 
     129             : private:
     130             :   // Allow RegisterFactory and the test helper InjectFactoryCategory to register a category, but
     131             :   // no-one else. This enforces correct use of the registration machinery.
     132             :   template <class T, class Base> friend class RegisterFactory;
     133             :   template <class Base> friend class InjectFactoryCategory;
     134             : 
     135        1496 :   static void registerCategory(const std::string& category, FactoryRegistryProxy* factory_names) {
     136        1496 :     auto result = factories().emplace(std::make_pair(category, factory_names));
     137        1496 :     RELEASE_ASSERT(result.second == true,
     138        1496 :                    fmt::format("Double registration for category: '{}'", category));
     139        1496 :   }
     140             : 
     141           0 :   static void deregisterCategoryForTest(const std::string& category) {
     142           0 :     factories().erase(category);
     143           0 :     RELEASE_ASSERT(factories().find(category) == factories().end(),
     144           0 :                    fmt::format("Deregistration for category '{}' failed", category));
     145           0 :   }
     146             : };
     147             : 
     148             : // Forward declaration of test class for friend declaration below.
     149             : template <typename T> class InjectFactory;
     150             : 
     151             : /**
     152             :  * General registry for implementation factories. The registry is templated by the Base class that a
     153             :  * set of factories conforms to.
     154             :  *
     155             :  * Classes are found by name, so a single name cannot be registered twice for the same Base class.
     156             :  * Factories are registered by reference and this reference is expected to be valid through the life
     157             :  * of the program. Factories cannot be deregistered.
     158             :  * Factories should generally be registered by statically instantiating the RegisterFactory class.
     159             :  *
     160             :  * Note: This class is not thread safe, so registration should only occur in a single threaded
     161             :  * environment, which is guaranteed by the static instantiation mentioned above.
     162             :  *
     163             :  * Example lookup: BaseFactoryType *factory =
     164             :  * FactoryRegistry<BaseFactoryType>::getFactory("example_factory_name");
     165             :  */
     166             : template <class Base> class FactoryRegistry : public Logger::Loggable<Logger::Id::config> {
     167             : public:
     168             :   /**
     169             :    * Return a sorted vector of registered factory names.
     170             :    */
     171        6535 :   static std::vector<absl::string_view> registeredNames(bool include_disabled = false) {
     172        6535 :     std::vector<absl::string_view> ret;
     173             : 
     174        6535 :     ret.reserve(factories().size());
     175             : 
     176       22491 :     for (const auto& [factory_name, factory] : factories()) {
     177       22491 :       if (factory || include_disabled) {
     178       22491 :         ret.push_back(factory_name);
     179       22491 :       }
     180       22491 :     }
     181             : 
     182        6535 :     std::sort(ret.begin(), ret.end());
     183             : 
     184        6535 :     return ret;
     185        6535 :   }
     186             : 
     187             :   /**
     188             :    * Gets the current map of factory implementations.
     189             :    */
     190       53099 :   static absl::flat_hash_map<std::string, Base*>& factories() {
     191       53099 :     static auto* factories = new absl::flat_hash_map<std::string, Base*>;
     192       53099 :     return *factories;
     193       53099 :   }
     194             : 
     195             :   /**
     196             :    * Gets the current map of vendor specific factory versions.
     197             :    */
     198             :   static absl::flat_hash_map<std::string, envoy::config::core::v3::BuildVersion>&
     199       44820 :   versionedFactories() {
     200       44820 :     using VersionedFactoryMap =
     201       44820 :         absl::flat_hash_map<std::string, envoy::config::core::v3::BuildVersion>;
     202       44820 :     MUTABLE_CONSTRUCT_ON_FIRST_USE(VersionedFactoryMap);
     203       44820 :   }
     204             : 
     205         384 :   static absl::flat_hash_map<std::string, std::string>& deprecatedFactoryNames() {
     206         384 :     static auto* deprecated_factory_names = new absl::flat_hash_map<std::string, std::string>;
     207         384 :     return *deprecated_factory_names;
     208         384 :   }
     209             : 
     210             :   /**
     211             :    * Lazily constructs a mapping from the configuration message type to a factory,
     212             :    * including the deprecated configuration message types.
     213             :    * Must be invoked after factory registration is completed.
     214             :    */
     215        9594 :   static absl::flat_hash_map<std::string, Base*>& factoriesByType() {
     216        9594 :     static absl::flat_hash_map<std::string, Base*>* factories_by_type =
     217        9594 :         buildFactoriesByType().release();
     218             : 
     219        9594 :     return *factories_by_type;
     220        9594 :   }
     221             : 
     222             :   /**
     223             :    * instead_value are used when passed name was deprecated.
     224             :    */
     225             :   static void registerFactory(Base& factory, absl::string_view name,
     226        3963 :                               absl::string_view instead_value = "") {
     227        3963 :     auto result = factories().emplace(std::make_pair(name, &factory));
     228        3963 :     if (!result.second) {
     229           0 :       ExceptionUtil::throwEnvoyException(
     230           0 :           fmt::format("Double registration for name: '{}'", factory.name()));
     231           0 :     }
     232             : 
     233        3963 :     if (!instead_value.empty()) {
     234         384 :       deprecatedFactoryNames().emplace(std::make_pair(name, instead_value));
     235         384 :     }
     236        3963 :   }
     237             : 
     238             :   /**
     239             :    * version is used for registering vendor specific factories that are versioned
     240             :    * independently of Envoy.
     241             :    */
     242             :   static void registerFactory(Base& factory, absl::string_view name,
     243             :                               const envoy::config::core::v3::BuildVersion& version,
     244             :                               absl::string_view instead_value = "") {
     245             :     auto result = factories().emplace(std::make_pair(name, &factory));
     246             :     if (!result.second) {
     247             :       ExceptionUtil::throwEnvoyException(
     248             :           fmt::format("Double registration for name: '{}'", factory.name()));
     249             :     }
     250             :     versionedFactories().emplace(std::make_pair(name, version));
     251             :     if (!instead_value.empty()) {
     252             :       deprecatedFactoryNames().emplace(std::make_pair(name, instead_value));
     253             :     }
     254             :   }
     255             : 
     256             :   /**
     257             :    * Permanently disables the named factory by setting the corresponding
     258             :    * factory pointer to null. If the factory is registered under multiple
     259             :    * (deprecated) names, all the possible names are disabled.
     260             :    */
     261           0 :   static bool disableFactory(absl::string_view name) {
     262           0 :     const auto disable = [](absl::string_view name) -> bool {
     263           0 :       auto it = factories().find(name);
     264           0 :       if (it != factories().end()) {
     265           0 :         it->second = nullptr;
     266           0 :         return true;
     267           0 :       }
     268           0 :       return false;
     269           0 :     };
     270             : 
     271             :     // First, find the canonical name for this factory.
     272           0 :     absl::string_view canonicalName = canonicalFactoryName(name);
     273             : 
     274             :     // Next, disable the factory by all its deprecated names.
     275           0 :     for (const auto& [deprecated_name, mapped_canonical_name] : deprecatedFactoryNames()) {
     276           0 :       if (mapped_canonical_name == canonicalName) {
     277           0 :         disable(deprecated_name);
     278           0 :       }
     279           0 :     }
     280             : 
     281             :     // Finally, disable the factory by its canonical name.
     282           0 :     return disable(canonicalName);
     283           0 :   }
     284             : 
     285             :   /**
     286             :    * Gets a factory by name. If the name isn't found in the registry, returns nullptr.
     287             :    */
     288        6289 :   static Base* getFactory(absl::string_view name) {
     289        6289 :     auto it = factories().find(name);
     290        6289 :     if (it == factories().end()) {
     291         380 :       return nullptr;
     292         380 :     }
     293             : 
     294        5909 :     return it->second;
     295        6289 :   }
     296             : 
     297        1530 :   static Base* getFactoryByType(absl::string_view type) {
     298        1530 :     auto it = factoriesByType().find(type);
     299        1530 :     if (it == factoriesByType().end()) {
     300          73 :       return nullptr;
     301          73 :     }
     302        1457 :     return it->second;
     303        1530 :   }
     304             : 
     305             :   /**
     306             :    * @return the canonical name of the factory. If the given name is a
     307             :    * deprecated factory name, the canonical name is returned instead.
     308             :    */
     309           0 :   static absl::string_view canonicalFactoryName(absl::string_view name) {
     310           0 :     const auto it = deprecatedFactoryNames().find(name);
     311           0 :     return (it == deprecatedFactoryNames().end()) ? name : it->second;
     312           0 :   }
     313             : 
     314             :   /**
     315             :    * @return true if the named factory was disabled.
     316             :    */
     317       22410 :   static bool isFactoryDisabled(absl::string_view name) {
     318       22410 :     auto it = factories().find(name);
     319       22410 :     ASSERT(it != factories().end());
     320       22410 :     return it->second == nullptr;
     321       22410 :   }
     322             : 
     323             :   /**
     324             :    * @return vendor specific version of a factory.
     325             :    */
     326             :   static absl::optional<envoy::config::core::v3::BuildVersion>
     327       22410 :   getFactoryVersion(absl::string_view name) {
     328       22410 :     auto it = versionedFactories().find(name);
     329       22410 :     if (it == versionedFactories().end()) {
     330       22410 :       return absl::nullopt;
     331       22410 :     }
     332           0 :     return it->second;
     333       22410 :   }
     334             : 
     335             :   /**
     336             :    * @return set of config type names indexed by the factory name.
     337             :    */
     338        6532 :   static absl::flat_hash_map<std::string, std::vector<std::string>> registeredTypes() {
     339        6532 :     absl::flat_hash_map<std::string, std::vector<std::string>> mapping;
     340       14672 :     for (const auto& [config_type, factory] : factoriesByType()) {
     341       14672 :       mapping[factory->name()].push_back(config_type);
     342       14672 :     }
     343        6532 :     return mapping;
     344        6532 :   }
     345             : 
     346             : private:
     347             :   // Allow factory injection only in tests.
     348             :   friend class InjectFactory<Base>;
     349             : 
     350         508 :   static std::unique_ptr<absl::flat_hash_map<std::string, Base*>> buildFactoriesByType() {
     351         508 :     auto mapping = std::make_unique<absl::flat_hash_map<std::string, Base*>>();
     352             : 
     353        1533 :     for (const auto& [factory_name, factory] : factories()) {
     354        1532 :       UNREFERENCED_PARAMETER(factory_name);
     355        1532 :       if (factory == nullptr) {
     356           0 :         continue;
     357           0 :       }
     358             : 
     359        1557 :       for (const auto& config_type : factory->configTypes()) {
     360        1139 :         ASSERT(!config_type.empty(), "Extension config types can never be empty string");
     361             : 
     362             :         // Register config types in the mapping.
     363        1139 :         auto it = mapping->find(config_type);
     364        1139 :         if (it != mapping->end() && it->second != factory) {
     365             :           // Mark double-registered types with a nullptr for tests only.
     366             :           // See issue https://github.com/envoyproxy/envoy/issues/9643.
     367           0 :           RELEASE_ASSERT(false, fmt::format("Double registration for type: '{}' by '{}' and '{}'",
     368           0 :                                             config_type, factory->name(),
     369           0 :                                             it->second ? it->second->name() : ""));
     370           0 :           it->second = nullptr;
     371        1139 :         } else {
     372        1139 :           mapping->emplace(std::make_pair(config_type, factory));
     373        1139 :         }
     374        1139 :       }
     375        1532 :     }
     376             : 
     377         508 :     return mapping;
     378         508 :   }
     379             : 
     380             :   // Rebuild the factories-by-type map based on the current factories.
     381           2 :   static void rebuildFactoriesByTypeForTest() {
     382           2 :     auto& mapping = factoriesByType();
     383           2 :     auto updated_mapping = buildFactoriesByType();
     384             : 
     385             :     // Copy the updated mapping over the old one.
     386           2 :     mapping = *updated_mapping;
     387           2 :   }
     388             : 
     389             :   /**
     390             :    * Replaces a factory by name. This method should only be used for testing purposes.
     391             :    * @param factory is the factory to inject.
     392             :    * @param deprecated_names install the given deprecated names for this factory.
     393             :    * @return std::function<void()> a function that will restore the previously registered factories
     394             :    *         (by name or type).
     395             :    */
     396             :   static std::function<void()>
     397             :   replaceFactoryForTest(Base& factory,
     398           1 :                         std::initializer_list<absl::string_view> deprecated_names = {}) {
     399           1 :     using DeprecatedNamesVector = std::vector<std::pair<std::string, std::string>>;
     400             : 
     401             :     // If an existing factory is registered with this name, track it for later restoration.
     402           1 :     Base* prev_by_name = nullptr;
     403           1 :     auto it = factories().find(factory.name());
     404           1 :     if (it != factories().end()) {
     405           0 :       prev_by_name = it->second;
     406           0 :       factories().erase(it);
     407             : 
     408           0 :       ENVOY_LOG(
     409           0 :           info, "Factory '{}' (type '{}') displaced-by-name with test factory '{}' (type '{}')",
     410           0 :           prev_by_name->name(), prev_by_name->configTypes(), factory.name(), factory.configTypes());
     411           1 :     } else {
     412           1 :       ENVOY_LOG(info, "Factory '{}' (type '{}') registered for tests", factory.name(),
     413           1 :                 factory.configTypes());
     414           1 :     }
     415             : 
     416           1 :     factories().emplace(factory.name(), &factory);
     417           1 :     RELEASE_ASSERT(getFactory(factory.name()) == &factory,
     418           1 :                    "test factory by-name registration failed");
     419             : 
     420           1 :     DeprecatedNamesVector prev_deprecated_names;
     421           1 :     if (deprecated_names.size() > 0) {
     422           0 :       for (auto deprecated_name : deprecated_names) {
     423           0 :         auto it = deprecatedFactoryNames().find(deprecated_name);
     424           0 :         if (it != deprecatedFactoryNames().end()) {
     425           0 :           prev_deprecated_names.emplace_back(std::make_pair(it->first, it->second));
     426           0 :           deprecatedFactoryNames().erase(it);
     427             : 
     428           0 :           ENVOY_LOG(
     429           0 :               info,
     430           0 :               "Deprecated name '{}' (mapped to '{}') displaced with test factory '{}' (type '{}')",
     431           0 :               it->first, it->second, factory.name(), factory.configTypes());
     432           0 :         } else {
     433             :           // Name not previously mapped, remember to remove it.
     434           0 :           prev_deprecated_names.emplace_back(std::make_pair(deprecated_name, ""));
     435             : 
     436           0 :           ENVOY_LOG(info, "Deprecated name '{}' (mapped to '{}')", deprecated_name, factory.name());
     437           0 :         }
     438             : 
     439             :         // Register the replacement factory with a deprecated name.
     440           0 :         factories().emplace(deprecated_name, &factory);
     441           0 :         RELEASE_ASSERT(getFactory(deprecated_name) == &factory,
     442           0 :                        "test factory registration by deprecated name failed");
     443             : 
     444             :         // Register the replacement factory's deprecated name.
     445           0 :         deprecatedFactoryNames().emplace(std::make_pair(deprecated_name, factory.name()));
     446           0 :       }
     447           0 :     }
     448             : 
     449           1 :     rebuildFactoriesByTypeForTest();
     450             : 
     451           1 :     return [replacement = &factory, prev_by_name, prev_deprecated_names]() {
     452             :       // Unregister the replacement factory by name.
     453           1 :       factories().erase(replacement->name());
     454             : 
     455           1 :       ENVOY_LOG(info, "Removed test factory '{}' (type '{}')", replacement->name(),
     456           1 :                 replacement->configTypes());
     457             : 
     458           1 :       if (prev_by_name) {
     459             :         // Restore any factory displaced by name, but only register the type if it's non-empty.
     460           0 :         factories().emplace(prev_by_name->name(), prev_by_name);
     461             : 
     462           0 :         ENVOY_LOG(info, "Restored factory '{}' (type '{}'), formerly displaced-by-name",
     463           0 :                   prev_by_name->name(), prev_by_name->configTypes());
     464           0 :       }
     465             : 
     466           1 :       for (auto [prev_deprecated_name, mapped_canonical_name] : prev_deprecated_names) {
     467           0 :         deprecatedFactoryNames().erase(prev_deprecated_name);
     468             : 
     469           0 :         ENVOY_LOG(info, "Removed deprecated name '{}'", prev_deprecated_name);
     470             : 
     471           0 :         if (!mapped_canonical_name.empty()) {
     472           0 :           deprecatedFactoryNames().emplace(
     473           0 :               std::make_pair(prev_deprecated_name, mapped_canonical_name));
     474             : 
     475           0 :           auto* deprecated_factory = getFactory(mapped_canonical_name);
     476           0 :           RELEASE_ASSERT(deprecated_factory != nullptr,
     477           0 :                          "failed to restore deprecated factory name");
     478           0 :           factories().emplace(mapped_canonical_name, deprecated_factory);
     479             : 
     480           0 :           ENVOY_LOG(info, "Restored deprecated name '{}' (mapped to '{}'", prev_deprecated_name,
     481           0 :                     mapped_canonical_name);
     482           0 :         }
     483           0 :       }
     484             : 
     485           1 :       rebuildFactoriesByTypeForTest();
     486           1 :     };
     487           1 :   }
     488             : };
     489             : 
     490             : /**
     491             :  * Factory registration template. Enables users to register a particular implementation factory with
     492             :  * the FactoryRegistry by instantiating this templated class with the specific factory class and the
     493             :  * general Base class to which that factory conforms.
     494             :  *
     495             :  * Because factories are generally registered once and live for the length of the program, the
     496             :  * standard use of this class is static instantiation within a linked implementation's translation
     497             :  * unit. For an example of a typical use case, @see NamedNetworkFilterConfigFactory.
     498             :  *
     499             :  * Example registration: REGISTER_FACTORY(SpecificFactory, BaseFactory);
     500             :  *                       LEGACY_REGISTER_FACTORY(SpecificFactory, BaseFactory, "deprecated_name");
     501             :  */
     502             : template <class T, class Base> class RegisterFactory {
     503             : public:
     504             :   /**
     505             :    * Constructor that registers an instance of the factory with the FactoryRegistry.
     506             :    */
     507        2665 :   RegisterFactory() {
     508        2665 :     ASSERT(!instance_.name().empty());
     509        2665 :     FactoryRegistry<Base>::registerFactory(instance_, instance_.name());
     510             : 
     511             :     // Also register this factory with its category.
     512             :     //
     513             :     // Each time a factory registers, the registry will attempt to
     514             :     // register its category here. This means that we have to ignore
     515             :     // multiple attempts to register the same category and can't detect
     516             :     // duplicate categories.
     517        2665 :     if (!FactoryCategoryRegistry::isRegistered(instance_.category())) {
     518        1365 :       FactoryCategoryRegistry::registerCategory(instance_.category(),
     519        1365 :                                                 new FactoryRegistryProxyImpl<Base>());
     520        1365 :     }
     521        2665 :   }
     522             : 
     523             :   /**
     524             :    * Constructor that registers an instance of the factory with the FactoryRegistry along with
     525             :    * deprecated names.
     526             :    */
     527         384 :   explicit RegisterFactory(std::initializer_list<absl::string_view> deprecated_names) {
     528         384 :     if (!instance_.name().empty()) {
     529         384 :       FactoryRegistry<Base>::registerFactory(instance_, instance_.name());
     530         384 :     } else {
     531           0 :       ASSERT(deprecated_names.size() != 0,
     532           0 :              "Attempted to register a factory without a name or deprecated name");
     533           0 :     }
     534             : 
     535         384 :     for (auto deprecated_name : deprecated_names) {
     536         384 :       ASSERT(!deprecated_name.empty());
     537         384 :       FactoryRegistry<Base>::registerFactory(instance_, deprecated_name, instance_.name());
     538         384 :     }
     539             : 
     540         384 :     if (!FactoryCategoryRegistry::isRegistered(instance_.category())) {
     541         131 :       FactoryCategoryRegistry::registerCategory(instance_.category(),
     542         131 :                                                 new FactoryRegistryProxyImpl<Base>());
     543         131 :     }
     544         384 :   }
     545             : 
     546             :   /**
     547             :    * Constructor that registers an instance of the factory with the FactoryRegistry along with
     548             :    * vendor specific version.
     549             :    */
     550             :   RegisterFactory(uint32_t major, uint32_t minor, uint32_t patch,
     551             :                   const std::map<std::string, std::string>& version_metadata)
     552             :       : RegisterFactory(major, minor, patch, version_metadata, {}) {}
     553             : 
     554             :   /**
     555             :    * Constructor that registers an instance of the factory with the FactoryRegistry along with
     556             :    * vendor specific version and deprecated names.
     557             :    */
     558             :   RegisterFactory(uint32_t major, uint32_t minor, uint32_t patch,
     559             :                   const std::map<std::string, std::string>& version_metadata,
     560             :                   std::initializer_list<absl::string_view> deprecated_names) {
     561             :     auto version = makeBuildVersion(major, minor, patch, version_metadata);
     562             :     if (instance_.name().empty()) {
     563             :       ASSERT(deprecated_names.size() != 0);
     564             :     } else {
     565             :       FactoryRegistry<Base>::registerFactory(instance_, instance_.name(), version);
     566             :     }
     567             : 
     568             :     for (auto deprecated_name : deprecated_names) {
     569             :       ASSERT(!deprecated_name.empty());
     570             :       FactoryRegistry<Base>::registerFactory(instance_, deprecated_name, version, instance_.name());
     571             :     }
     572             : 
     573             :     if (!FactoryCategoryRegistry::isRegistered(instance_.category())) {
     574             :       FactoryCategoryRegistry::registerCategory(instance_.category(),
     575             :                                                 new FactoryRegistryProxyImpl<Base>());
     576             :     }
     577             :   }
     578             : 
     579             : private:
     580             :   static envoy::config::core::v3::BuildVersion
     581             :   makeBuildVersion(uint32_t major, uint32_t minor, uint32_t patch,
     582             :                    const std::map<std::string, std::string>& metadata) {
     583             :     envoy::config::core::v3::BuildVersion version;
     584             :     version.mutable_version()->set_major_number(major);
     585             :     version.mutable_version()->set_minor_number(minor);
     586             :     version.mutable_version()->set_patch(patch);
     587             :     *version.mutable_metadata() = MessageUtil::keyValueStruct(metadata);
     588             :     return version;
     589             :   }
     590             : 
     591             :   T instance_{};
     592             : };
     593             : 
     594             : /**
     595             :  * RegisterInternalFactory is a special case for registering factories
     596             :  * that are considered internal implementation details that should
     597             :  * not be exposed to operators via the factory categories.
     598             :  *
     599             :  * There is no corresponding REGISTER_INTERNAL_FACTORY because
     600             :  * this should be used sparingly and only in special cases.
     601             :  */
     602             : template <class T, class Base> class RegisterInternalFactory {
     603             : public:
     604         530 :   RegisterInternalFactory() {
     605         530 :     ASSERT(!instance_.name().empty());
     606         530 :     FactoryRegistry<Base>::registerFactory(instance_, instance_.name());
     607         530 :   }
     608             : 
     609             : private:
     610             :   T instance_{};
     611             : };
     612             : 
     613             : #ifdef ENVOY_STATIC_EXTENSION_REGISTRATION
     614             : /**
     615             :  * Macro used for static registration.
     616             :  */
     617             : #define REGISTER_FACTORY(FACTORY, BASE)                                                            \
     618           0 :   ABSL_ATTRIBUTE_UNUSED void forceRegister##FACTORY() {}                                           \
     619             :   static Envoy::Registry::RegisterFactory</* NOLINT(fuchsia-statically-constructed-objects) */     \
     620             :                                           FACTORY, BASE>                                           \
     621             :       FACTORY##_registered
     622             : /**
     623             :  * Macro used for static registration with deprecated name.
     624             :  */
     625             : #define LEGACY_REGISTER_FACTORY(FACTORY, BASE, DEPRECATED_NAME)                                    \
     626           0 :   ABSL_ATTRIBUTE_UNUSED void forceRegister##FACTORY() {}                                           \
     627             :   static Envoy::Registry::RegisterFactory</* NOLINT(fuchsia-statically-constructed-objects) */     \
     628             :                                           FACTORY, BASE>                                           \
     629             :       FACTORY##_registered {                                                                       \
     630             :     DEPRECATED_NAME                                                                                \
     631             :   }
     632             : #else
     633             : /**
     634             :  * Macro used to define a registration function.
     635             :  */
     636             : #define REGISTER_FACTORY(FACTORY, BASE)                                                            \
     637             :   ABSL_ATTRIBUTE_UNUSED void forceRegister##FACTORY() {                                            \
     638             :     ABSL_ATTRIBUTE_UNUSED static auto registered =                                                 \
     639             :         new Envoy::Registry::RegisterFactory<FACTORY, BASE>();                                     \
     640             :   }
     641             : /**
     642             :  * Macro used to define a registration function with deprecated name.
     643             :  */
     644             : #define LEGACY_REGISTER_FACTORY(FACTORY, BASE, DEPRECATED_NAME)                                    \
     645             :   ABSL_ATTRIBUTE_UNUSED void forceRegister##FACTORY() {                                            \
     646             :     ABSL_ATTRIBUTE_UNUSED static auto registered =                                                 \
     647             :         new Envoy::Registry::RegisterFactory<FACTORY, BASE>({DEPRECATED_NAME});                    \
     648             :   }
     649             : #endif
     650             : 
     651             : #define FACTORY_VERSION(major, minor, patch, ...) major, minor, patch, __VA_ARGS__
     652             : 
     653             : /**
     654             :  * Macro used for static registration declaration.
     655             :  * Calling forceRegister...(); can be used to force the static factory initializer to run in a
     656             :  * setting in which Envoy is bundled as a static archive. In this case, the static initializer is
     657             :  * not run until a function in the compilation unit is invoked. The force function can be invoked
     658             :  * from a static library wrapper.
     659             :  */
     660             : #define DECLARE_FACTORY(FACTORY) ABSL_ATTRIBUTE_UNUSED void forceRegister##FACTORY()
     661             : 
     662             : } // namespace Registry
     663             : } // namespace Envoy

Generated by: LCOV version 1.15