Skip to content

Commit ea2b27b

Browse files
authored
Merge pull request ceph#63189 from cbodley/wip-rgw-config-store-realm-watcher
rgw: move rados-specific parts of RGWRealmWatcher into ConfigStore Reviewed-by: Adam C. Emerson <[email protected]> Reviewed-by: Daniel Gryniewicz <[email protected]>
2 parents 3a75e1a + e70d932 commit ea2b27b

File tree

13 files changed

+268
-175
lines changed

13 files changed

+268
-175
lines changed

src/rgw/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ set(librgw_common_srcs
160160
rgw_tracer.cc
161161
rgw_lua_background.cc
162162
rgw_data_access.cc
163+
rgw_realm_watcher.cc
163164
driver/rados/account.cc
164165
driver/rados/buckets.cc
165166
rgw_bucket_logging.cc
@@ -225,6 +226,7 @@ list(APPEND librgw_common_srcs
225226
driver/rados/config/period.cc
226227
driver/rados/config/period_config.cc
227228
driver/rados/config/realm.cc
229+
driver/rados/config/realm_watcher.cc
228230
driver/rados/config/store.cc
229231
driver/rados/config/zone.cc
230232
driver/rados/config/zonegroup.cc)
@@ -395,7 +397,6 @@ set(rgw_a_srcs
395397
rgw_period_pusher.cc
396398
rgw_process.cc
397399
rgw_realm_reloader.cc
398-
rgw_realm_watcher.cc
399400
rgw_rest_config.cc
400401
rgw_rest_info.cc
401402
rgw_rest_metadata.cc

src/rgw/driver/dbstore/config/sqlite.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "include/encoding.h"
2626
#include "common/dout.h"
2727
#include "common/random_string.h"
28+
#include "rgw_realm_watcher.h"
2829

2930
#include "driver/rados/rgw_zone.h" // FIXME: subclass dependency
3031

@@ -676,6 +677,14 @@ int SQLiteConfigStore::realm_notify_new_period(const DoutPrefixProvider* dpp,
676677
return -ENOTSUP;
677678
}
678679

680+
auto SQLiteConfigStore::create_realm_watcher(const DoutPrefixProvider* dpp,
681+
optional_yield y,
682+
const RGWRealm& realm)
683+
-> std::unique_ptr<RGWRealmWatcher>
684+
{
685+
return nullptr;
686+
}
687+
679688
int SQLiteConfigStore::list_realm_names(const DoutPrefixProvider* dpp,
680689
optional_yield y, const std::string& marker,
681690
std::span<std::string> entries,

src/rgw/driver/dbstore/config/sqlite.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ class SQLiteConfigStore : public sal::ConfigStore {
6161
int realm_notify_new_period(const DoutPrefixProvider* dpp,
6262
optional_yield y,
6363
const RGWPeriod& period) override;
64+
auto create_realm_watcher(const DoutPrefixProvider* dpp,
65+
optional_yield y,
66+
const RGWRealm& realm)
67+
-> std::unique_ptr<RGWRealmWatcher> override;
6468
int list_realm_names(const DoutPrefixProvider* dpp,
6569
optional_yield y, const std::string& marker,
6670
std::span<std::string> entries,

src/rgw/driver/immutable_config/store.cc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
*
1313
*/
1414

15-
#include "rgw_zone.h"
1615
#include "store.h"
16+
#include "rgw_realm_watcher.h"
1717

1818
namespace rgw::sal {
1919

@@ -94,6 +94,14 @@ int ImmutableConfigStore::realm_notify_new_period(const DoutPrefixProvider* dpp,
9494
return -ENOTSUP;
9595
}
9696

97+
auto ImmutableConfigStore::create_realm_watcher(const DoutPrefixProvider* dpp,
98+
optional_yield y,
99+
const RGWRealm& realm)
100+
-> std::unique_ptr<RGWRealmWatcher>
101+
{
102+
return nullptr;
103+
}
104+
97105
int ImmutableConfigStore::list_realm_names(const DoutPrefixProvider* dpp,
98106
optional_yield y, const std::string& marker,
99107
std::span<std::string> entries,

src/rgw/driver/immutable_config/store.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#pragma once
1616

1717
#include "rgw_sal_config.h"
18+
#include "rgw_zone.h"
1819

1920
namespace rgw::sal {
2021

@@ -59,6 +60,10 @@ class ImmutableConfigStore : public ConfigStore {
5960
virtual int realm_notify_new_period(const DoutPrefixProvider* dpp,
6061
optional_yield y,
6162
const RGWPeriod& period) override;
63+
virtual auto create_realm_watcher(const DoutPrefixProvider* dpp,
64+
optional_yield y,
65+
const RGWRealm& realm)
66+
-> std::unique_ptr<RGWRealmWatcher> override;
6267
virtual int list_realm_names(const DoutPrefixProvider* dpp,
6368
optional_yield y, const std::string& marker,
6469
std::span<std::string> entries,
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
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 "realm_watcher.h"
5+
6+
#include "common/errno.h"
7+
#include "include/ceph_assert.h"
8+
9+
#include "rgw_tools.h"
10+
#include "rgw_zone.h"
11+
12+
#include "impl.h"
13+
#include "store.h"
14+
15+
#define dout_subsys ceph_subsys_rgw
16+
17+
#undef dout_prefix
18+
#define dout_prefix (*_dout << "rgw realm watcher: ")
19+
20+
21+
namespace rgw::rados {
22+
23+
RadosRealmWatcher::RadosRealmWatcher(const DoutPrefixProvider* dpp, CephContext* cct,
24+
librados::Rados& rados, const RGWRealm& realm)
25+
: cct(cct)
26+
{
27+
// no default realm, nothing to watch
28+
if (realm.get_id().empty()) {
29+
ldpp_dout(dpp, 4) << "No realm, disabling dynamic reconfiguration." << dendl;
30+
return;
31+
}
32+
33+
// establish the watch on RGWRealm
34+
int r = watch_start(dpp, rados, realm);
35+
if (r < 0) {
36+
ldpp_dout(dpp, -1) << "Failed to establish a watch on RGWRealm, "
37+
"disabling dynamic reconfiguration." << dendl;
38+
return;
39+
}
40+
}
41+
42+
RadosRealmWatcher::~RadosRealmWatcher()
43+
{
44+
watch_stop();
45+
}
46+
47+
void RadosRealmWatcher::handle_notify(uint64_t notify_id, uint64_t cookie,
48+
uint64_t notifier_id, bufferlist& bl)
49+
{
50+
if (cookie != watch_handle)
51+
return;
52+
53+
// send an empty notify ack
54+
bufferlist reply;
55+
pool_ctx.notify_ack(watch_oid, notify_id, cookie, reply);
56+
57+
try {
58+
auto p = bl.cbegin();
59+
while (!p.end()) {
60+
RGWRealmNotify notify;
61+
decode(notify, p);
62+
auto watcher = watchers.find(notify);
63+
if (watcher == watchers.end()) {
64+
lderr(cct) << "Failed to find a watcher for notify type "
65+
<< static_cast<int>(notify) << dendl;
66+
break;
67+
}
68+
watcher->second.handle_notify(notify, p);
69+
}
70+
} catch (const buffer::error &e) {
71+
lderr(cct) << "Failed to decode realm notifications." << dendl;
72+
}
73+
}
74+
75+
void RadosRealmWatcher::handle_error(uint64_t cookie, int err)
76+
{
77+
lderr(cct) << "RadosRealmWatcher::handle_error oid=" << watch_oid << " err=" << err << dendl;
78+
if (cookie != watch_handle)
79+
return;
80+
81+
watch_restart();
82+
}
83+
84+
int RadosRealmWatcher::watch_start(const DoutPrefixProvider* dpp,
85+
librados::Rados& rados,
86+
const RGWRealm& realm)
87+
{
88+
// initialize a Rados client
89+
int r = rados.init_with_context(cct);
90+
if (r < 0) {
91+
ldpp_dout(dpp, -1) << "Rados client initialization failed with "
92+
<< cpp_strerror(-r) << dendl;
93+
return r;
94+
}
95+
r = rados.connect();
96+
if (r < 0) {
97+
ldpp_dout(dpp, -1) << "Rados client connection failed with "
98+
<< cpp_strerror(-r) << dendl;
99+
return r;
100+
}
101+
102+
// open an IoCtx for the realm's pool
103+
rgw_pool pool(realm.get_pool(cct));
104+
r = rgw_init_ioctx(dpp, &rados, pool, pool_ctx);
105+
if (r < 0) {
106+
ldpp_dout(dpp, -1) << "Failed to open pool " << pool
107+
<< " with " << cpp_strerror(-r) << dendl;
108+
rados.shutdown();
109+
return r;
110+
}
111+
112+
// register a watch on the realm's control object
113+
auto oid = realm.get_control_oid();
114+
r = pool_ctx.watch2(oid, &watch_handle, this);
115+
if (r < 0) {
116+
ldpp_dout(dpp, -1) << "Failed to watch " << oid
117+
<< " with " << cpp_strerror(-r) << dendl;
118+
pool_ctx.close();
119+
rados.shutdown();
120+
return r;
121+
}
122+
123+
ldpp_dout(dpp, 10) << "Watching " << oid << dendl;
124+
std::swap(watch_oid, oid);
125+
return 0;
126+
}
127+
128+
int RadosRealmWatcher::watch_restart()
129+
{
130+
ceph_assert(!watch_oid.empty());
131+
int r = pool_ctx.unwatch2(watch_handle);
132+
if (r < 0) {
133+
lderr(cct) << "Failed to unwatch on " << watch_oid
134+
<< " with " << cpp_strerror(-r) << dendl;
135+
}
136+
r = pool_ctx.watch2(watch_oid, &watch_handle, this);
137+
if (r < 0) {
138+
lderr(cct) << "Failed to restart watch on " << watch_oid
139+
<< " with " << cpp_strerror(-r) << dendl;
140+
pool_ctx.close();
141+
watch_oid.clear();
142+
}
143+
return r;
144+
}
145+
146+
void RadosRealmWatcher::watch_stop()
147+
{
148+
if (!watch_oid.empty()) {
149+
pool_ctx.unwatch2(watch_handle);
150+
pool_ctx.close();
151+
watch_oid.clear();
152+
}
153+
}
154+
155+
auto RadosConfigStore::create_realm_watcher(const DoutPrefixProvider* dpp,
156+
optional_yield y,
157+
const RGWRealm& realm)
158+
-> std::unique_ptr<RGWRealmWatcher>
159+
{
160+
return std::make_unique<RadosRealmWatcher>(dpp, dpp->get_cct(), impl->rados, realm);
161+
}
162+
163+
} // namespace rgw::rados
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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+
#pragma once
5+
6+
#include "rgw_realm_watcher.h"
7+
#include "include/rados/librados.hpp"
8+
9+
class DoutPrefixProvider;
10+
class RGWRealm;
11+
12+
namespace rgw::rados {
13+
14+
class RadosRealmWatcher : public RGWRealmWatcher,
15+
public librados::WatchCtx2 {
16+
public:
17+
RadosRealmWatcher(const DoutPrefixProvider* dpp, CephContext* cct,
18+
librados::Rados& rados, const RGWRealm& realm);
19+
~RadosRealmWatcher() override;
20+
21+
/// respond to realm notifications by calling the appropriate watcher
22+
void handle_notify(uint64_t notify_id, uint64_t cookie,
23+
uint64_t notifier_id, bufferlist& bl) override;
24+
25+
/// reestablish the watch if it gets disconnected
26+
void handle_error(uint64_t cookie, int err) override;
27+
28+
private:
29+
CephContext *const cct;
30+
31+
librados::IoCtx pool_ctx;
32+
uint64_t watch_handle = 0;
33+
std::string watch_oid;
34+
35+
int watch_start(const DoutPrefixProvider* dpp,
36+
librados::Rados& rados,
37+
const RGWRealm& realm);
38+
int watch_restart();
39+
void watch_stop();
40+
};
41+
42+
} // namespace rgw::rados

src/rgw/driver/rados/config/store.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ class RadosConfigStore : public sal::ConfigStore {
6666
virtual int realm_notify_new_period(const DoutPrefixProvider* dpp,
6767
optional_yield y,
6868
const RGWPeriod& period) override;
69+
virtual auto create_realm_watcher(const DoutPrefixProvider* dpp,
70+
optional_yield y,
71+
const RGWRealm& realm)
72+
-> std::unique_ptr<RGWRealmWatcher> override;
6973
virtual int list_realm_names(const DoutPrefixProvider* dpp,
7074
optional_yield y, const std::string& marker,
7175
std::span<std::string> entries,

src/rgw/rgw_appmain.cc

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -520,22 +520,25 @@ int rgw::AppMain::init_frontends2(RGWLib* rgwlib)
520520
/* ignore error */
521521
}
522522

523-
if (env.driver->get_name() == "rados") {
524-
// add a watcher to respond to realm configuration changes
523+
// if we're part of a realm, add a watcher to respond to configuration changes
524+
if (const auto& realm = env.site->get_realm(); realm) {
525+
realm_watcher = env.cfgstore->create_realm_watcher(dpp, null_yield, *realm);
526+
}
527+
if (realm_watcher) {
525528
pusher = std::make_unique<RGWPeriodPusher>(dpp, env.driver, env.cfgstore, null_yield);
529+
realm_watcher->add_watcher(RGWRealmNotify::ZonesNeedPeriod, *pusher);
530+
526531
fe_pauser = std::make_unique<RGWFrontendPauser>(fes, pusher.get());
527532
rgw_pauser = std::make_unique<RGWPauser>();
528533
rgw_pauser->add_pauser(fe_pauser.get());
529534
if (env.lua.background) {
530535
rgw_pauser->add_pauser(env.lua.background);
531536
}
537+
532538
need_context_pool();
533539
reloader = std::make_unique<RGWRealmReloader>(
534-
env, *implicit_tenant_context, service_map_meta, rgw_pauser.get(), *context_pool);
535-
realm_watcher = std::make_unique<RGWRealmWatcher>(dpp, g_ceph_context,
536-
static_cast<rgw::sal::RadosStore*>(env.driver)->svc()->zone->get_realm());
540+
env, *implicit_tenant_context, service_map_meta, rgw_pauser.get(), *context_pool);
537541
realm_watcher->add_watcher(RGWRealmNotify::Reload, *reloader);
538-
realm_watcher->add_watcher(RGWRealmNotify::ZonesNeedPeriod, *pusher.get());
539542
}
540543

541544
return r;
@@ -582,8 +585,14 @@ void rgw::AppMain::init_lua()
582585

583586
void rgw::AppMain::shutdown(std::function<void(void)> finalize_async_signals)
584587
{
588+
// stop the realm reloader
589+
rgw_pauser.reset();
590+
fe_pauser.reset();
591+
realm_watcher.reset();
592+
pusher.reset();
593+
reloader.reset();
594+
585595
if (env.driver->get_name() == "rados") {
586-
reloader.reset(); // stop the realm reloader
587596
if (g_conf().get_val<bool>("rgw_lua_enable"))
588597
static_cast<rgw::sal::RadosLuaManager*>(env.lua.manager.get())->
589598
unwatch_reload(dpp);

src/rgw/rgw_realm_reloader.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "rgw_realm_watcher.h"
99
#include "common/Cond.h"
10+
#include "common/Timer.h"
1011
#include "rgw_sal_fwd.h"
1112

1213
struct RGWProcessEnv;

0 commit comments

Comments
 (0)