1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
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"
17 #include "rgw_auth_registry.h"
19 #define dout_context g_ceph_context
20 #define dout_subsys ceph_subsys_rgw
22 namespace rgw::dmclock
{
28 class RGWFrontendConfig
{
30 std::multimap
<std::string
, std::string
> config_map
;
31 std::string framework
;
33 int parse_config(const std::string
& config
,
34 std::multimap
<std::string
, std::string
>& config_map
);
37 explicit RGWFrontendConfig(const std::string
& config
)
42 const int ret
= parse_config(config
, config_map
);
43 return ret
< 0 ? ret
: 0;
46 void set_default_config(RGWFrontendConfig
& def_conf
);
48 std::optional
<string
> get_val(const std::string
& key
);
50 bool get_val(const std::string
& key
,
51 const std::string
& def_val
,
53 bool get_val(const std::string
& key
, int def_val
, int *out
);
55 std::string
get_val(const std::string
& key
,
56 const std::string
& def_val
) {
58 get_val(key
, def_val
, &out
);
62 const std::string
& get_config() {
66 std::multimap
<std::string
, std::string
>& get_config_map() {
70 std::string
get_framework() const {
77 virtual ~RGWFrontend() {}
79 virtual int init() = 0;
81 virtual int run() = 0;
82 virtual void stop() = 0;
83 virtual void join() = 0;
85 virtual void pause_for_new_config() = 0;
86 virtual void unpause_with_new_config(rgw::sal::RGWRadosStore
* store
,
87 rgw_auth_registry_ptr_t auth_registry
) = 0;
91 struct RGWMongooseEnv
: public RGWProcessEnv
{
92 // every request holds a read lock, so we need to prioritize write locks to
93 // avoid starving pause_for_new_config()
94 static constexpr bool prioritize_write
= true;
97 explicit RGWMongooseEnv(const RGWProcessEnv
&env
)
99 mutex("RGWCivetWebFrontend", false, true, prioritize_write
) {
104 class RGWCivetWebFrontend
: public RGWFrontend
{
105 RGWFrontendConfig
* conf
;
106 struct mg_context
* ctx
;
109 std::unique_ptr
<rgw::dmclock::SyncScheduler
> scheduler
;
110 std::unique_ptr
<rgw::dmclock::ClientConfig
> client_config
;
112 void set_conf_default(std::multimap
<std::string
, std::string
>& m
,
113 const std::string
& key
,
114 const std::string
& def_val
) {
115 if (m
.find(key
) == std::end(m
)) {
116 m
.emplace(key
, def_val
);
120 CephContext
* cct() const { return env
.store
->ctx(); }
122 RGWCivetWebFrontend(RGWProcessEnv
& env
,
123 RGWFrontendConfig
*conf
,
124 rgw::dmclock::SchedulerCtx
& sched_ctx
);
126 int init() override
{
132 int process(struct mg_connection
* conn
);
134 void stop() override
{
140 void join() override
{
144 void pause_for_new_config() override
{
145 // block callbacks until unpause
146 env
.mutex
.get_write();
149 void unpause_with_new_config(rgw::sal::RGWRadosStore
* const store
,
150 rgw_auth_registry_ptr_t auth_registry
) override
{
152 env
.auth_registry
= std::move(auth_registry
);
154 env
.mutex
.put_write();
156 }; /* RGWCivetWebFrontend */
158 class RGWProcessFrontend
: public RGWFrontend
{
160 RGWFrontendConfig
* conf
;
161 RGWProcess
* pprocess
;
163 RGWProcessControlThread
* thread
;
166 RGWProcessFrontend(RGWProcessEnv
& pe
, RGWFrontendConfig
* _conf
)
167 : conf(_conf
), pprocess(nullptr), env(pe
), thread(nullptr) {
170 ~RGWProcessFrontend() override
{
176 ceph_assert(pprocess
); /* should have initialized by init() */
177 thread
= new RGWProcessControlThread(pprocess
);
178 thread
->create("rgw_frontend");
182 void stop() override
;
184 void join() override
{
188 void pause_for_new_config() override
{
192 void unpause_with_new_config(rgw::sal::RGWRadosStore
* const store
,
193 rgw_auth_registry_ptr_t auth_registry
) override
{
195 env
.auth_registry
= auth_registry
;
196 pprocess
->unpause_with_new_config(store
, std::move(auth_registry
));
198 }; /* RGWProcessFrontend */
200 class RGWFCGXFrontend
: public RGWProcessFrontend
{
202 RGWFCGXFrontend(RGWProcessEnv
& pe
, RGWFrontendConfig
* _conf
)
203 : RGWProcessFrontend(pe
, _conf
) {}
205 int init() override
{
206 pprocess
= new RGWFCGXProcess(g_ceph_context
, &env
,
207 g_conf()->rgw_thread_pool_size
, conf
);
210 }; /* RGWFCGXFrontend */
212 class RGWLoadGenFrontend
: public RGWProcessFrontend
{
214 RGWLoadGenFrontend(RGWProcessEnv
& pe
, RGWFrontendConfig
*_conf
)
215 : RGWProcessFrontend(pe
, _conf
) {}
217 int init() override
{
219 conf
->get_val("num_threads", g_conf()->rgw_thread_pool_size
, &num_threads
);
220 RGWLoadGenProcess
*pp
= new RGWLoadGenProcess(g_ceph_context
, &env
,
226 conf
->get_val("uid", "", &uid_str
);
227 if (uid_str
.empty()) {
228 derr
<< "ERROR: uid param must be specified for loadgen frontend"
233 rgw_user
uid(uid_str
);
235 RGWUserInfo user_info
;
236 int ret
= env
.store
->ctl()->user
->get_info_by_uid(uid
, &user_info
, null_yield
);
238 derr
<< "ERROR: failed reading user info: uid=" << uid
<< " ret="
243 map
<string
, RGWAccessKey
>::iterator aiter
= user_info
.access_keys
.begin();
244 if (aiter
== user_info
.access_keys
.end()) {
245 derr
<< "ERROR: user has no S3 access keys set" << dendl
;
249 pp
->set_access_key(aiter
->second
);
253 }; /* RGWLoadGenFrontend */
255 // FrontendPauser implementation for RGWRealmReloader
256 class RGWFrontendPauser
: public RGWRealmReloader::Pauser
{
257 std::list
<RGWFrontend
*> &frontends
;
258 RGWRealmReloader::Pauser
* pauser
;
259 rgw::auth::ImplicitTenants
& implicit_tenants
;
262 RGWFrontendPauser(std::list
<RGWFrontend
*> &frontends
,
263 rgw::auth::ImplicitTenants
& implicit_tenants
,
264 RGWRealmReloader::Pauser
* pauser
= nullptr)
265 : frontends(frontends
),
267 implicit_tenants(implicit_tenants
) {
270 void pause() override
{
271 for (auto frontend
: frontends
)
272 frontend
->pause_for_new_config();
276 void resume(rgw::sal::RGWRadosStore
*store
) override
{
277 /* Initialize the registry of auth strategies which will coordinate
278 * the dynamic reconfiguration. */
279 auto auth_registry
= \
280 rgw::auth::StrategyRegistry::create(g_ceph_context
, implicit_tenants
, store
->getRados()->pctl
);
282 for (auto frontend
: frontends
)
283 frontend
->unpause_with_new_config(store
, auth_registry
);
285 pauser
->resume(store
);
289 #endif /* RGW_FRONTEND_H */