]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_realm_watcher.cc
import ceph 15.2.10
[ceph.git] / ceph / src / rgw / rgw_realm_watcher.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
3
4 #include "common/errno.h"
5
6 #include "rgw_realm_watcher.h"
7 #include "rgw_tools.h"
8 #include "rgw_zone.h"
9
10 #define dout_subsys ceph_subsys_rgw
11
12 #undef dout_prefix
13 #define dout_prefix (*_dout << "rgw realm watcher: ")
14
15
16 RGWRealmWatcher::RGWRealmWatcher(CephContext* cct, const RGWRealm& realm)
17 : cct(cct)
18 {
19 // no default realm, nothing to watch
20 if (realm.get_id().empty()) {
21 ldout(cct, 4) << "No realm, disabling dynamic reconfiguration." << dendl;
22 return;
23 }
24
25 // establish the watch on RGWRealm
26 int r = watch_start(realm);
27 if (r < 0) {
28 lderr(cct) << "Failed to establish a watch on RGWRealm, "
29 "disabling dynamic reconfiguration." << dendl;
30 return;
31 }
32 }
33
34 RGWRealmWatcher::~RGWRealmWatcher()
35 {
36 watch_stop();
37 }
38
39 void RGWRealmWatcher::add_watcher(RGWRealmNotify type, Watcher& watcher)
40 {
41 watchers.emplace(type, watcher);
42 }
43
44 void RGWRealmWatcher::handle_notify(uint64_t notify_id, uint64_t cookie,
45 uint64_t notifier_id, bufferlist& bl)
46 {
47 if (cookie != watch_handle)
48 return;
49
50 // send an empty notify ack
51 bufferlist reply;
52 pool_ctx.notify_ack(watch_oid, notify_id, cookie, reply);
53
54 try {
55 auto p = bl.cbegin();
56 while (!p.end()) {
57 RGWRealmNotify notify;
58 decode(notify, p);
59 auto watcher = watchers.find(notify);
60 if (watcher == watchers.end()) {
61 lderr(cct) << "Failed to find a watcher for notify type "
62 << static_cast<int>(notify) << dendl;
63 break;
64 }
65 watcher->second.handle_notify(notify, p);
66 }
67 } catch (const buffer::error &e) {
68 lderr(cct) << "Failed to decode realm notifications." << dendl;
69 }
70 }
71
72 void RGWRealmWatcher::handle_error(uint64_t cookie, int err)
73 {
74 lderr(cct) << "RGWRealmWatcher::handle_error oid=" << watch_oid << " err=" << err << dendl;
75 if (cookie != watch_handle)
76 return;
77
78 watch_restart();
79 }
80
81 int RGWRealmWatcher::watch_start(const RGWRealm& realm)
82 {
83 // initialize a Rados client
84 int r = rados.init_with_context(cct);
85 if (r < 0) {
86 lderr(cct) << "Rados client initialization failed with "
87 << cpp_strerror(-r) << dendl;
88 return r;
89 }
90 r = rados.connect();
91 if (r < 0) {
92 lderr(cct) << "Rados client connection failed with "
93 << cpp_strerror(-r) << dendl;
94 return r;
95 }
96
97 // open an IoCtx for the realm's pool
98 rgw_pool pool(realm.get_pool(cct));
99 r = rgw_init_ioctx(&rados, pool, pool_ctx);
100 if (r < 0) {
101 lderr(cct) << "Failed to open pool " << pool
102 << " with " << cpp_strerror(-r) << dendl;
103 rados.shutdown();
104 return r;
105 }
106
107 // register a watch on the realm's control object
108 auto oid = realm.get_control_oid();
109 r = pool_ctx.watch2(oid, &watch_handle, this);
110 if (r < 0) {
111 lderr(cct) << "Failed to watch " << oid
112 << " with " << cpp_strerror(-r) << dendl;
113 pool_ctx.close();
114 rados.shutdown();
115 return r;
116 }
117
118 ldout(cct, 10) << "Watching " << oid << dendl;
119 std::swap(watch_oid, oid);
120 return 0;
121 }
122
123 int RGWRealmWatcher::watch_restart()
124 {
125 ceph_assert(!watch_oid.empty());
126 int r = pool_ctx.unwatch2(watch_handle);
127 if (r < 0) {
128 lderr(cct) << "Failed to unwatch on " << watch_oid
129 << " with " << cpp_strerror(-r) << dendl;
130 }
131 r = pool_ctx.watch2(watch_oid, &watch_handle, this);
132 if (r < 0) {
133 lderr(cct) << "Failed to restart watch on " << watch_oid
134 << " with " << cpp_strerror(-r) << dendl;
135 pool_ctx.close();
136 watch_oid.clear();
137 }
138 return r;
139 }
140
141 void RGWRealmWatcher::watch_stop()
142 {
143 if (!watch_oid.empty()) {
144 pool_ctx.unwatch2(watch_handle);
145 pool_ctx.close();
146 watch_oid.clear();
147 }
148 }