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
|