From 19fcec84d8d7d21e796c7624e521b60d28ee21ed Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:45:59 +0200 Subject: Adding upstream version 16.2.11+ds. Signed-off-by: Daniel Baumann --- src/common/config_obs_mgr.h | 118 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 src/common/config_obs_mgr.h (limited to 'src/common/config_obs_mgr.h') diff --git a/src/common/config_obs_mgr.h b/src/common/config_obs_mgr.h new file mode 100644 index 000000000..06b3cf934 --- /dev/null +++ b/src/common/config_obs_mgr.h @@ -0,0 +1,118 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- + +#pragma once + +#include +#include +#include + +#include "common/config_tracker.h" + +class ConfigValues; + +// @c ObserverMgr manages a set of config observers which are interested in +// the changes of settings at runtime. +template +class ObserverMgr : public ConfigTracker { + // Maps configuration options to the observer listening for them. + using obs_map_t = std::multimap; + obs_map_t observers; + +public: + typedef std::map> rev_obs_map; + typedef std::function config_gather_cb; + + // Adds a new observer to this configuration. You can do this at any time, + // but it will only receive notifications for the changes that happen after + // you attach it, obviously. + // + // Most developers will probably attach their observers after global_init, + // but before anyone can call injectargs. + // + // The caller is responsible for allocating observers. + void add_observer(ConfigObs* observer); + + // Remove an observer from this configuration. + // This doesn't delete the observer! If you allocated it with new(), + // you need to delete it yourself. + // This function will assert if you try to delete an observer that isn't + // there. + void remove_observer(ConfigObs* observer); + // invoke callback for every observers tracking keys + void for_each_observer(config_gather_cb callback); + // invoke callback for observers keys tracking the provided change set + template + void for_each_change(const std::set& changes, + ConfigProxyT& proxy, + config_gather_cb callback, std::ostream *oss); + bool is_tracking(const std::string& name) const override; +}; + +// we could put the implementations in a .cc file, and only instantiate the +// used template specializations explicitly, but that forces us to involve +// unused headers and libraries at compile-time. for instance, for instantiate, +// to instantiate ObserverMgr for seastar, we will need to include seastar +// headers to get the necessary types in place, but that would force us to link +// the non-seastar binaries against seastar libraries. so, to avoid pulling +// in unused dependencies at the expense of increasing compiling time, we put +// the implementation in the header file. +template +void ObserverMgr::add_observer(ConfigObs* observer) +{ + const char **keys = observer->get_tracked_conf_keys(); + for (const char ** k = keys; *k; ++k) { + observers.emplace(*k, observer); + } +} + +template +void ObserverMgr::remove_observer(ConfigObs* observer) +{ + [[maybe_unused]] bool found_obs = false; + for (auto o = observers.begin(); o != observers.end(); ) { + if (o->second == observer) { + observers.erase(o++); + found_obs = true; + } else { + ++o; + } + } + ceph_assert(found_obs); +} + +template +void ObserverMgr::for_each_observer(config_gather_cb callback) +{ + for (const auto& [key, obs] : observers) { + callback(obs, key); + } +} + +template +template +void ObserverMgr::for_each_change(const std::set& changes, + ConfigProxyT& proxy, + config_gather_cb callback, std::ostream *oss) +{ + // create the reverse observer mapping, mapping observers to the set of + // changed keys that they'll get. + std::string val; + for (auto& key : changes) { + auto [first, last] = observers.equal_range(key); + if ((oss) && !proxy.get_val(key, &val)) { + (*oss) << key << " = '" << val << "' "; + if (first == last) { + (*oss) << "(not observed, change may require restart) "; + } + } + for (auto r = first; r != last; ++r) { + callback(r->second, key); + } + } +} + +template +bool ObserverMgr::is_tracking(const std::string& name) const +{ + return observers.count(name) > 0; +} -- cgit v1.2.3