]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/ConfigWatcher.cc
import ceph 15.2.10
[ceph.git] / ceph / src / librbd / ConfigWatcher.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "librbd/ConfigWatcher.h"
5 #include "common/config_obs.h"
6 #include "common/dout.h"
7 #include "common/errno.h"
8 #include "librbd/ImageCtx.h"
9 #include "librbd/ImageState.h"
10 #include "librbd/api/Config.h"
11 #include <deque>
12 #include <string>
13 #include <vector>
14 #include <boost/algorithm/string/predicate.hpp>
15
16 #define dout_subsys ceph_subsys_rbd
17 #undef dout_prefix
18 #define dout_prefix *_dout << "librbd::ConfigWatcher: " \
19 << __func__ << ": "
20
21 namespace librbd {
22
23 template <typename I>
24 struct ConfigWatcher<I>::Observer : public md_config_obs_t {
25 ConfigWatcher<I>* m_config_watcher;
26
27 std::deque<std::string> m_config_key_strs;
28 mutable std::vector<const char*> m_config_keys;
29
30 Observer(CephContext* cct, ConfigWatcher<I>* config_watcher)
31 : m_config_watcher(config_watcher) {
32 const std::string rbd_key_prefix("rbd_");
33 auto& schema = cct->_conf.get_schema();
34 for (auto& pair : schema) {
35 // watch all "rbd_" keys for simplicity
36 if (!boost::starts_with(pair.first, rbd_key_prefix)) {
37 continue;
38 }
39
40 m_config_key_strs.emplace_back(pair.first);
41 }
42
43 m_config_keys.reserve(m_config_key_strs.size());
44 for (auto& key : m_config_key_strs) {
45 m_config_keys.emplace_back(key.c_str());
46 }
47 m_config_keys.emplace_back(nullptr);
48 }
49
50 const char** get_tracked_conf_keys() const override {
51 ceph_assert(!m_config_keys.empty());
52 return &m_config_keys[0];
53 }
54
55 void handle_conf_change(const ConfigProxy& conf,
56 const std::set <std::string> &changed) override {
57 m_config_watcher->handle_global_config_change(changed);
58 }
59 };
60
61 template <typename I>
62 ConfigWatcher<I>::ConfigWatcher(I& image_ctx)
63 : m_image_ctx(image_ctx) {
64 }
65
66 template <typename I>
67 ConfigWatcher<I>::~ConfigWatcher() {
68 ceph_assert(m_observer == nullptr);
69 }
70
71 template <typename I>
72 void ConfigWatcher<I>::init() {
73 auto cct = m_image_ctx.cct;
74 ldout(cct, 10) << dendl;
75
76 m_observer = new Observer(cct, this);
77 cct->_conf.add_observer(m_observer);
78 }
79
80 template <typename I>
81 void ConfigWatcher<I>::shut_down() {
82 auto cct = m_image_ctx.cct;
83 ldout(cct, 10) << dendl;
84
85 ceph_assert(m_observer != nullptr);
86 cct->_conf.remove_observer(m_observer);
87
88 delete m_observer;
89 m_observer = nullptr;
90 }
91
92 template <typename I>
93 void ConfigWatcher<I>::handle_global_config_change(
94 std::set<std::string> changed_keys) {
95
96 {
97 // ignore any global changes that are being overridden
98 std::shared_lock image_locker{m_image_ctx.image_lock};
99 for (auto& key : m_image_ctx.config_overrides) {
100 changed_keys.erase(key);
101 }
102 }
103 if (changed_keys.empty()) {
104 return;
105 }
106
107 auto cct = m_image_ctx.cct;
108 ldout(cct, 10) << "changed_keys=" << changed_keys << dendl;
109
110 // refresh the image to pick up any global config overrides
111 m_image_ctx.state->handle_update_notification();
112 }
113
114 } // namespace librbd
115
116 template class librbd::ConfigWatcher<librbd::ImageCtx>;