]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_realm_watcher.cc
import 14.2.4 nautilus point release
[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
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 if (cookie != watch_handle)
75 return;
76
77 if (err == -ENOTCONN) {
78 ldout(cct, 4) << "Disconnected watch on " << watch_oid << dendl;
79 watch_restart();
80 }
81 }
82
83 int RGWRealmWatcher::watch_start(const RGWRealm& realm)
84 {
85 // initialize a Rados client
86 int r = rados.init_with_context(cct);
87 if (r < 0) {
88 lderr(cct) << "Rados client initialization failed with "
89 << cpp_strerror(-r) << dendl;
90 return r;
91 }
92 r = rados.connect();
93 if (r < 0) {
94 lderr(cct) << "Rados client connection failed with "
95 << cpp_strerror(-r) << dendl;
96 return r;
97 }
98
99 // open an IoCtx for the realm's pool
100 rgw_pool pool(realm.get_pool(cct));
101 r = rgw_init_ioctx(&rados, pool, pool_ctx);
102 if (r < 0) {
103 lderr(cct) << "Failed to open pool " << pool
104 << " with " << cpp_strerror(-r) << dendl;
105 rados.shutdown();
106 return r;
107 }
108
109 // register a watch on the realm's control object
110 auto oid = realm.get_control_oid();
111 r = pool_ctx.watch2(oid, &watch_handle, this);
112 if (r < 0) {
113 lderr(cct) << "Failed to watch " << oid
114 << " with " << cpp_strerror(-r) << dendl;
115 pool_ctx.close();
116 rados.shutdown();
117 return r;
118 }
119
120 ldout(cct, 10) << "Watching " << oid << dendl;
121 std::swap(watch_oid, oid);
122 return 0;
123 }
124
125 int RGWRealmWatcher::watch_restart()
126 {
127 ceph_assert(!watch_oid.empty());
128 int r = pool_ctx.unwatch2(watch_handle);
129 if (r < 0) {
130 lderr(cct) << "Failed to unwatch on " << watch_oid
131 << " with " << cpp_strerror(-r) << dendl;
132 }
133 r = pool_ctx.watch2(watch_oid, &watch_handle, this);
134 if (r < 0) {
135 lderr(cct) << "Failed to restart watch on " << watch_oid
136 << " with " << cpp_strerror(-r) << dendl;
137 pool_ctx.close();
138 watch_oid.clear();
139 }
140 return r;
141 }
142
143 void RGWRealmWatcher::watch_stop()
144 {
145 if (!watch_oid.empty()) {
146 pool_ctx.unwatch2(watch_handle);
147 pool_ctx.close();
148 watch_oid.clear();
149 }
150 }