1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
10 #include "rgw_request.h"
11 #include "rgw_process.h"
12 #include "rgw_realm_reloader.h"
14 #include "rgw_civetweb.h"
15 #include "rgw_civetweb_log.h"
16 #include "civetweb/civetweb.h"
18 #include "rgw_auth_registry.h"
20 #define dout_context g_ceph_context
21 #define dout_subsys ceph_subsys_rgw
23 class RGWFrontendConfig {
25 std::map<std::string, std::string> config_map;
26 std::string framework;
28 int parse_config(const std::string& config,
29 std::map<std::string, std::string>& config_map);
32 RGWFrontendConfig(const std::string& config)
37 const int ret = parse_config(config, config_map);
38 return ret < 0 ? ret : 0;
41 bool get_val(const std::string& key,
42 const std::string& def_val,
44 bool get_val(const std::string& key, int def_val, int *out);
46 std::string get_val(const std::string& key,
47 const std::string& def_val) {
49 get_val(key, def_val, &out);
53 const std::string& get_config() {
57 std::map<std::string, std::string>& get_config_map() {
61 std::string get_framework() const {
68 virtual ~RGWFrontend() {}
70 virtual int init() = 0;
72 virtual int run() = 0;
73 virtual void stop() = 0;
74 virtual void join() = 0;
76 virtual void pause_for_new_config() = 0;
77 virtual void unpause_with_new_config(RGWRados* store,
78 rgw_auth_registry_ptr_t auth_registry) = 0;
82 struct RGWMongooseEnv : public RGWProcessEnv {
83 // every request holds a read lock, so we need to prioritize write locks to
84 // avoid starving pause_for_new_config()
85 static constexpr bool prioritize_write = true;
88 RGWMongooseEnv(const RGWProcessEnv &env)
90 mutex("RGWCivetWebFrontend", false, true, prioritize_write) {
95 class RGWCivetWebFrontend : public RGWFrontend {
96 RGWFrontendConfig* conf;
97 struct mg_context* ctx;
100 void set_conf_default(std::map<std::string, std::string>& m,
101 const std::string& key,
102 const std::string& def_val) {
103 if (m.find(key) == std::end(m)) {
109 RGWCivetWebFrontend(RGWProcessEnv& env,
110 RGWFrontendConfig* conf)
116 int init() override {
122 int process(struct mg_connection* conn);
124 void stop() override {
130 void join() override {
134 void pause_for_new_config() override {
135 // block callbacks until unpause
136 env.mutex.get_write();
139 void unpause_with_new_config(RGWRados* const store,
140 rgw_auth_registry_ptr_t auth_registry) override {
142 env.auth_registry = std::move(auth_registry);
144 env.mutex.put_write();
146 }; /* RGWCivetWebFrontend */
148 class RGWProcessFrontend : public RGWFrontend {
150 RGWFrontendConfig* conf;
151 RGWProcess* pprocess;
153 RGWProcessControlThread* thread;
156 RGWProcessFrontend(RGWProcessEnv& pe, RGWFrontendConfig* _conf)
157 : conf(_conf), pprocess(nullptr), env(pe), thread(nullptr) {
160 ~RGWProcessFrontend() override {
166 assert(pprocess); /* should have initialized by init() */
167 thread = new RGWProcessControlThread(pprocess);
168 thread->create("rgw_frontend");
172 void stop() override;
174 void join() override {
178 void pause_for_new_config() override {
182 void unpause_with_new_config(RGWRados* const store,
183 rgw_auth_registry_ptr_t auth_registry) override {
185 env.auth_registry = auth_registry;
186 pprocess->unpause_with_new_config(store, std::move(auth_registry));
188 }; /* RGWProcessFrontend */
190 class RGWFCGXFrontend : public RGWProcessFrontend {
192 RGWFCGXFrontend(RGWProcessEnv& pe, RGWFrontendConfig* _conf)
193 : RGWProcessFrontend(pe, _conf) {}
195 int init() override {
196 pprocess = new RGWFCGXProcess(g_ceph_context, &env,
197 g_conf->rgw_thread_pool_size, conf);
200 }; /* RGWFCGXFrontend */
202 class RGWLoadGenFrontend : public RGWProcessFrontend {
204 RGWLoadGenFrontend(RGWProcessEnv& pe, RGWFrontendConfig *_conf)
205 : RGWProcessFrontend(pe, _conf) {}
207 int init() override {
209 conf->get_val("num_threads", g_conf->rgw_thread_pool_size, &num_threads);
210 RGWLoadGenProcess *pp = new RGWLoadGenProcess(g_ceph_context, &env,
216 conf->get_val("uid", "", &uid_str);
217 if (uid_str.empty()) {
218 derr << "ERROR: uid param must be specified for loadgen frontend"
223 rgw_user uid(uid_str);
225 RGWUserInfo user_info;
226 int ret = rgw_get_user_info_by_uid(env.store, uid, user_info, NULL);
228 derr << "ERROR: failed reading user info: uid=" << uid << " ret="
233 map<string, RGWAccessKey>::iterator aiter = user_info.access_keys.begin();
234 if (aiter == user_info.access_keys.end()) {
235 derr << "ERROR: user has no S3 access keys set" << dendl;
239 pp->set_access_key(aiter->second);
243 }; /* RGWLoadGenFrontend */
245 // FrontendPauser implementation for RGWRealmReloader
246 class RGWFrontendPauser : public RGWRealmReloader::Pauser {
247 std::list<RGWFrontend*> &frontends;
248 RGWRealmReloader::Pauser* pauser;
251 RGWFrontendPauser(std::list<RGWFrontend*> &frontends,
252 RGWRealmReloader::Pauser* pauser = nullptr)
253 : frontends(frontends), pauser(pauser) {}
255 void pause() override {
256 for (auto frontend : frontends)
257 frontend->pause_for_new_config();
261 void resume(RGWRados *store) override {
262 /* Initialize the registry of auth strategies which will coordinate
263 * the dynamic reconfiguration. */
264 auto auth_registry = \
265 rgw::auth::StrategyRegistry::create(g_ceph_context, store);
267 for (auto frontend : frontends)
268 frontend->unpause_with_new_config(store, auth_registry);
270 pauser->resume(store);
274 #endif /* RGW_FRONTEND_H */