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