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 */