]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_realm_reloader.cc
add subtree-ish sources for 12.0.3
[ceph.git] / 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
3
4 #include "rgw_realm_reloader.h"
5 #include "rgw_rados.h"
6
7 #include "rgw_bucket.h"
8 #include "rgw_log.h"
9 #include "rgw_rest.h"
10 #include "rgw_user.h"
11
12 #define dout_subsys ceph_subsys_rgw
13
14 #undef dout_prefix
15 #define dout_prefix (*_dout << "rgw realm reloader: ")
16
17
18 // safe callbacks from SafeTimer are unneccessary. reload() can take a long
19 // time, so we don't want to hold the mutex and block handle_notify() for the
20 // duration
21 static constexpr bool USE_SAFE_TIMER_CALLBACKS = false;
22
23
24 RGWRealmReloader::RGWRealmReloader(RGWRados*& store, Pauser* frontends)
25 : store(store),
26 frontends(frontends),
27 timer(store->ctx(), mutex, USE_SAFE_TIMER_CALLBACKS),
28 mutex("RGWRealmReloader"),
29 reload_scheduled(nullptr)
30 {
31 timer.init();
32 }
33
34 RGWRealmReloader::~RGWRealmReloader()
35 {
36 Mutex::Locker lock(mutex);
37 timer.shutdown();
38 }
39
40 class RGWRealmReloader::C_Reload : public Context {
41 RGWRealmReloader* reloader;
42 public:
43 C_Reload(RGWRealmReloader* reloader) : reloader(reloader) {}
44 void finish(int r) override { reloader->reload(); }
45 };
46
47 void RGWRealmReloader::handle_notify(RGWRealmNotify type,
48 bufferlist::iterator& p)
49 {
50 if (!store) {
51 /* we're in the middle of reload */
52 return;
53 }
54
55 CephContext *const cct = store->ctx();
56
57 Mutex::Locker lock(mutex);
58 if (reload_scheduled) {
59 ldout(cct, 4) << "Notification on realm, reconfiguration "
60 "already scheduled" << dendl;
61 return;
62 }
63
64 reload_scheduled = new C_Reload(this);
65 cond.SignalOne(); // wake reload() if it blocked on a bad configuration
66
67 // schedule reload() without delay
68 timer.add_event_after(0, reload_scheduled);
69
70 ldout(cct, 4) << "Notification on realm, reconfiguration scheduled" << dendl;
71 }
72
73 void RGWRealmReloader::reload()
74 {
75 CephContext *const cct = store->ctx();
76 ldout(cct, 1) << "Pausing frontends for realm update..." << dendl;
77
78 frontends->pause();
79
80 ldout(cct, 1) << "Frontends paused" << dendl;
81
82 // TODO: make RGWRados responsible for rgw_log_usage lifetime
83 rgw_log_usage_finalize();
84
85 // destroy the existing store
86 RGWStoreManager::close_storage(store);
87 store = nullptr;
88
89 ldout(cct, 1) << "Store closed" << dendl;
90 {
91 // allow a new notify to reschedule us. it's important that we do this
92 // before we start loading the new realm, or we could miss some updates
93 Mutex::Locker lock(mutex);
94 reload_scheduled = nullptr;
95 }
96
97 while (!store) {
98 // recreate and initialize a new store
99 store = RGWStoreManager::get_storage(cct,
100 cct->_conf->rgw_enable_gc_threads,
101 cct->_conf->rgw_enable_lc_threads,
102 cct->_conf->rgw_enable_quota_threads,
103 cct->_conf->rgw_run_sync_thread);
104
105 ldout(cct, 1) << "Creating new store" << dendl;
106
107 RGWRados* store_cleanup = nullptr;
108 {
109 Mutex::Locker lock(mutex);
110
111 // failure to recreate RGWRados is not a recoverable error, but we
112 // don't want to assert or abort the entire cluster. instead, just
113 // sleep until we get another notification, and retry until we get
114 // a working configuration
115 if (store == nullptr) {
116 lderr(cct) << "Failed to reinitialize RGWRados after a realm "
117 "configuration update. Waiting for a new update." << dendl;
118
119 // sleep until another event is scheduled
120 while (!reload_scheduled)
121 cond.Wait(mutex);
122
123 ldout(cct, 1) << "Woke up with a new configuration, retrying "
124 "RGWRados initialization." << dendl;
125 }
126
127 if (reload_scheduled) {
128 // cancel the event; we'll handle it now
129 timer.cancel_event(reload_scheduled);
130 reload_scheduled = nullptr;
131
132 // if we successfully created a store, clean it up outside of the lock,
133 // then continue to loop and recreate another
134 std::swap(store, store_cleanup);
135 }
136 }
137
138 if (store_cleanup) {
139 ldout(cct, 4) << "Got another notification, restarting RGWRados "
140 "initialization." << dendl;
141
142 RGWStoreManager::close_storage(store_cleanup);
143 }
144 }
145
146 ldout(cct, 1) << "Finishing initialization of new store" << dendl;
147 // finish initializing the new store
148 ldout(cct, 1) << " - REST subsystem init" << dendl;
149 rgw_rest_init(cct, store, store->get_zonegroup());
150 ldout(cct, 1) << " - user subsystem init" << dendl;
151 rgw_user_init(store);
152 ldout(cct, 1) << " - user subsystem init" << dendl;
153 rgw_bucket_init(store->meta_mgr);
154 ldout(cct, 1) << " - usage subsystem init" << dendl;
155 rgw_log_usage_init(cct, store);
156
157 ldout(cct, 1) << "Resuming frontends with new realm configuration." << dendl;
158
159 frontends->resume(store);
160 }