]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_realm_reloader.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
4 #include "rgw_realm_reloader.h"
7 #include "rgw_bucket.h"
13 #include "services/svc_zone.h"
15 #include "common/errno.h"
17 #define dout_subsys ceph_subsys_rgw
20 #define dout_prefix (*_dout << "rgw realm reloader: ")
23 // safe callbacks from SafeTimer are unneccessary. reload() can take a long
24 // time, so we don't want to hold the mutex and block handle_notify() for the
26 static constexpr bool USE_SAFE_TIMER_CALLBACKS
= false;
29 RGWRealmReloader::RGWRealmReloader(rgw::sal::RGWRadosStore
*& store
, std::map
<std::string
, std::string
>& service_map_meta
,
32 service_map_meta(service_map_meta
),
34 timer(store
->ctx(), mutex
, USE_SAFE_TIMER_CALLBACKS
),
35 mutex(ceph::make_mutex("RGWRealmReloader")),
36 reload_scheduled(nullptr)
41 RGWRealmReloader::~RGWRealmReloader()
43 std::lock_guard lock
{mutex
};
47 class RGWRealmReloader::C_Reload
: public Context
{
48 RGWRealmReloader
* reloader
;
50 explicit C_Reload(RGWRealmReloader
* reloader
) : reloader(reloader
) {}
51 void finish(int r
) override
{ reloader
->reload(); }
54 void RGWRealmReloader::handle_notify(RGWRealmNotify type
,
55 bufferlist::const_iterator
& p
)
58 /* we're in the middle of reload */
62 CephContext
*const cct
= store
->ctx();
64 std::lock_guard lock
{mutex
};
65 if (reload_scheduled
) {
66 ldout(cct
, 4) << "Notification on realm, reconfiguration "
67 "already scheduled" << dendl
;
71 reload_scheduled
= new C_Reload(this);
72 cond
.notify_one(); // wake reload() if it blocked on a bad configuration
74 // schedule reload() without delay
75 timer
.add_event_after(0, reload_scheduled
);
77 ldout(cct
, 4) << "Notification on realm, reconfiguration scheduled" << dendl
;
80 void RGWRealmReloader::reload()
82 CephContext
*const cct
= store
->ctx();
83 ldout(cct
, 1) << "Pausing frontends for realm update..." << dendl
;
87 ldout(cct
, 1) << "Frontends paused" << dendl
;
89 // TODO: make RGWRados responsible for rgw_log_usage lifetime
90 rgw_log_usage_finalize();
92 // destroy the existing store
93 RGWStoreManager::close_storage(store
);
96 ldout(cct
, 1) << "Store closed" << dendl
;
98 // allow a new notify to reschedule us. it's important that we do this
99 // before we start loading the new realm, or we could miss some updates
100 std::lock_guard lock
{mutex
};
101 reload_scheduled
= nullptr;
105 // recreate and initialize a new store
107 RGWStoreManager::get_storage(cct
,
108 cct
->_conf
->rgw_enable_gc_threads
,
109 cct
->_conf
->rgw_enable_lc_threads
,
110 cct
->_conf
->rgw_enable_quota_threads
,
111 cct
->_conf
->rgw_run_sync_thread
,
112 cct
->_conf
.get_val
<bool>("rgw_dynamic_resharding"),
113 cct
->_conf
->rgw_cache_enabled
);
115 ldout(cct
, 1) << "Creating new store" << dendl
;
117 rgw::sal::RGWRadosStore
* store_cleanup
= nullptr;
119 std::unique_lock lock
{mutex
};
121 // failure to recreate RGWRados is not a recoverable error, but we
122 // don't want to assert or abort the entire cluster. instead, just
123 // sleep until we get another notification, and retry until we get
124 // a working configuration
125 if (store
== nullptr) {
126 lderr(cct
) << "Failed to reinitialize RGWRados after a realm "
127 "configuration update. Waiting for a new update." << dendl
;
129 // sleep until another event is scheduled
130 cond
.wait(lock
, [this] { return reload_scheduled
; });
131 ldout(cct
, 1) << "Woke up with a new configuration, retrying "
132 "RGWRados initialization." << dendl
;
135 if (reload_scheduled
) {
136 // cancel the event; we'll handle it now
137 timer
.cancel_event(reload_scheduled
);
138 reload_scheduled
= nullptr;
140 // if we successfully created a store, clean it up outside of the lock,
141 // then continue to loop and recreate another
142 std::swap(store
, store_cleanup
);
147 ldout(cct
, 4) << "Got another notification, restarting RGWRados "
148 "initialization." << dendl
;
150 RGWStoreManager::close_storage(store_cleanup
);
154 int r
= store
->getRados()->register_to_service_map("rgw", service_map_meta
);
156 lderr(cct
) << "ERROR: failed to register to service map: " << cpp_strerror(-r
) << dendl
;
161 ldout(cct
, 1) << "Finishing initialization of new store" << dendl
;
162 // finish initializing the new store
163 ldout(cct
, 1) << " - REST subsystem init" << dendl
;
164 rgw_rest_init(cct
, store
->svc()->zone
->get_zonegroup());
165 ldout(cct
, 1) << " - usage subsystem init" << dendl
;
166 rgw_log_usage_init(cct
, store
->getRados());
168 ldout(cct
, 1) << "Resuming frontends with new realm configuration." << dendl
;
170 frontends
->resume(store
);