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 <boost/algorithm/string.hpp>
7 #include "svc_user_rados.h"
9 #include "svc_sys_obj.h"
10 #include "svc_sys_obj_cache.h"
12 #include "svc_meta_be_sobj.h"
13 #include "svc_sync_modules.h"
15 #include "rgw/rgw_user.h"
16 #include "rgw/rgw_bucket.h"
17 #include "rgw/rgw_tools.h"
18 #include "rgw/rgw_zone.h"
19 #include "rgw/rgw_rados.h"
21 #include "cls/user/cls_user_client.h"
23 #define dout_subsys ceph_subsys_rgw
25 #define RGW_BUCKETS_OBJ_SUFFIX ".buckets"
29 class RGWSI_User_Module
: public RGWSI_MBSObj_Handler_Module
{
30 RGWSI_User_RADOS::Svc
& svc
;
34 RGWSI_User_Module(RGWSI_User_RADOS::Svc
& _svc
) : RGWSI_MBSObj_Handler_Module("user"),
37 void get_pool_and_oid(const string
& key
, rgw_pool
*pool
, string
*oid
) override
{
39 *pool
= svc
.zone
->get_zone_params().user_uid_pool
;
46 const string
& get_oid_prefix() override
{
50 bool is_valid_oid(const string
& oid
) override
{
51 // filter out the user.buckets objects
52 return !boost::algorithm::ends_with(oid
, RGW_BUCKETS_OBJ_SUFFIX
);
55 string
key_to_oid(const string
& key
) override
{
59 string
oid_to_key(const string
& oid
) override
{
64 RGWSI_User_RADOS::RGWSI_User_RADOS(CephContext
*cct
): RGWSI_User(cct
) {
67 RGWSI_User_RADOS::~RGWSI_User_RADOS() {
70 void RGWSI_User_RADOS::init(RGWSI_RADOS
*_rados_svc
,
71 RGWSI_Zone
*_zone_svc
, RGWSI_SysObj
*_sysobj_svc
,
72 RGWSI_SysObj_Cache
*_cache_svc
, RGWSI_Meta
*_meta_svc
,
73 RGWSI_MetaBackend
*_meta_be_svc
,
74 RGWSI_SyncModules
*_sync_modules_svc
)
77 svc
.rados
= _rados_svc
;
79 svc
.sysobj
= _sysobj_svc
;
80 svc
.cache
= _cache_svc
;
82 svc
.meta_be
= _meta_be_svc
;
83 svc
.sync_modules
= _sync_modules_svc
;
86 int RGWSI_User_RADOS::do_start(optional_yield
, const DoutPrefixProvider
*dpp
)
88 uinfo_cache
.reset(new RGWChainedCacheImpl
<user_info_cache_entry
>);
89 uinfo_cache
->init(svc
.cache
);
91 int r
= svc
.meta
->create_be_handler(RGWSI_MetaBackend::Type::MDBE_SOBJ
, &be_handler
);
93 ldpp_dout(dpp
, 0) << "ERROR: failed to create be handler: r=" << r
<< dendl
;
97 RGWSI_MetaBackend_Handler_SObj
*bh
= static_cast<RGWSI_MetaBackend_Handler_SObj
*>(be_handler
);
99 auto module
= new RGWSI_User_Module(svc
);
100 be_module
.reset(module
);
101 bh
->set_module(module
);
105 rgw_raw_obj
RGWSI_User_RADOS::get_buckets_obj(const rgw_user
& user
) const
107 string oid
= user
.to_str() + RGW_BUCKETS_OBJ_SUFFIX
;
108 return rgw_raw_obj(svc
.zone
->get_zone_params().user_uid_pool
, oid
);
111 int RGWSI_User_RADOS::read_user_info(RGWSI_MetaBackend::Context
*ctx
,
112 const rgw_user
& user
,
114 RGWObjVersionTracker
* const objv_tracker
,
115 real_time
* const pmtime
,
116 rgw_cache_entry_info
* const cache_info
,
117 map
<string
, bufferlist
> * const pattrs
,
119 const DoutPrefixProvider
*dpp
)
121 if(user
.id
== RGW_USER_ANON_ID
) {
122 ldpp_dout(dpp
, 20) << "RGWSI_User_RADOS::read_user_info(): anonymous user" << dendl
;
128 RGWSI_MBSObj_GetParams
params(&bl
, pattrs
, pmtime
);
129 params
.set_cache_info(cache_info
);
131 int ret
= svc
.meta_be
->get_entry(ctx
, get_meta_key(user
), params
, objv_tracker
, y
, dpp
);
136 auto iter
= bl
.cbegin();
138 decode(user_id
, iter
);
139 if (user_id
.user_id
!= user
) {
140 ldpp_dout(dpp
, -1) << "ERROR: rgw_get_user_info_by_uid(): user id mismatch: " << user_id
.user_id
<< " != " << user
<< dendl
;
146 } catch (buffer::error
& err
) {
147 ldpp_dout(dpp
, 0) << "ERROR: failed to decode user info, caught buffer::error" << dendl
;
156 RGWSI_User_RADOS::Svc
& svc
;
157 RGWSI_MetaBackend_SObj::Context_SObj
*ctx
;
159 const RGWUserInfo
& info
;
160 RGWUserInfo
*old_info
;
161 RGWObjVersionTracker
*objv_tracker
;
162 const real_time
& mtime
;
164 map
<string
, bufferlist
> *pattrs
;
165 RGWObjVersionTracker ot
;
169 void set_err_msg(string msg
) {
170 if (!err_msg
.empty()) {
171 err_msg
= std::move(msg
);
176 PutOperation(RGWSI_User_RADOS::Svc
& svc
,
177 RGWSI_MetaBackend::Context
*_ctx
,
178 const RGWUserInfo
& info
,
179 RGWUserInfo
*old_info
,
180 RGWObjVersionTracker
*objv_tracker
,
181 const real_time
& mtime
,
183 map
<string
, bufferlist
> *pattrs
,
185 svc(svc
), info(info
), old_info(old_info
),
186 objv_tracker(objv_tracker
), mtime(mtime
),
187 exclusive(exclusive
), pattrs(pattrs
), y(y
) {
188 ctx
= static_cast<RGWSI_MetaBackend_SObj::Context_SObj
*>(_ctx
);
189 ui
.user_id
= info
.user_id
;
192 int prepare(const DoutPrefixProvider
*dpp
) {
197 if (ot
.write_version
.tag
.empty()) {
198 if (ot
.read_version
.tag
.empty()) {
199 ot
.generate_new_write_ver(svc
.meta_be
->ctx());
201 ot
.write_version
= ot
.read_version
;
202 ot
.write_version
.ver
++;
206 for (auto iter
= info
.swift_keys
.begin(); iter
!= info
.swift_keys
.end(); ++iter
) {
207 if (old_info
&& old_info
->swift_keys
.count(iter
->first
) != 0)
209 auto& k
= iter
->second
;
210 /* check if swift mapping exists */
212 int r
= svc
.user
->get_user_info_by_swift(ctx
, k
.id
, &inf
, nullptr, nullptr, y
, dpp
);
213 if (r
>= 0 && inf
.user_id
!= info
.user_id
&&
214 (!old_info
|| inf
.user_id
!= old_info
->user_id
)) {
215 ldpp_dout(dpp
, 0) << "WARNING: can't store user info, swift id (" << k
.id
216 << ") already mapped to another user (" << info
.user_id
<< ")" << dendl
;
221 /* check if access keys already exist */
222 for (auto iter
= info
.access_keys
.begin(); iter
!= info
.access_keys
.end(); ++iter
) {
223 if (old_info
&& old_info
->access_keys
.count(iter
->first
) != 0)
225 auto& k
= iter
->second
;
227 int r
= svc
.user
->get_user_info_by_access_key(ctx
, k
.id
, &inf
, nullptr, nullptr, y
, dpp
);
228 if (r
>= 0 && inf
.user_id
!= info
.user_id
&&
229 (!old_info
|| inf
.user_id
!= old_info
->user_id
)) {
230 ldpp_dout(dpp
, 0) << "WARNING: can't store user info, access key already mapped to another user" << dendl
;
238 int put(const DoutPrefixProvider
*dpp
) {
241 encode(info
, data_bl
);
243 RGWSI_MBSObj_PutParams
params(data_bl
, pattrs
, mtime
, exclusive
);
245 int ret
= svc
.meta_be
->put(ctx
, RGWSI_User::get_meta_key(info
.user_id
), params
, &ot
, y
, dpp
);
252 int complete(const DoutPrefixProvider
*dpp
) {
258 auto& obj_ctx
= *ctx
->obj_ctx
;
260 if (!info
.user_email
.empty()) {
262 old_info
->user_email
.compare(info
.user_email
) != 0) { /* only if new index changed */
263 ret
= rgw_put_system_obj(dpp
, obj_ctx
, svc
.zone
->get_zone_params().user_email_pool
, info
.user_email
,
264 link_bl
, exclusive
, NULL
, real_time(), y
);
270 const bool renamed
= old_info
&& old_info
->user_id
!= info
.user_id
;
271 for (auto iter
= info
.access_keys
.begin(); iter
!= info
.access_keys
.end(); ++iter
) {
272 auto& k
= iter
->second
;
273 if (old_info
&& old_info
->access_keys
.count(iter
->first
) != 0 && !renamed
)
276 ret
= rgw_put_system_obj(dpp
, obj_ctx
, svc
.zone
->get_zone_params().user_keys_pool
, k
.id
,
277 link_bl
, exclusive
, NULL
, real_time(), y
);
282 for (auto siter
= info
.swift_keys
.begin(); siter
!= info
.swift_keys
.end(); ++siter
) {
283 auto& k
= siter
->second
;
284 if (old_info
&& old_info
->swift_keys
.count(siter
->first
) != 0 && !renamed
)
287 ret
= rgw_put_system_obj(dpp
, obj_ctx
, svc
.zone
->get_zone_params().user_swift_pool
, k
.id
,
288 link_bl
, exclusive
, NULL
, real_time(), y
);
294 ret
= remove_old_indexes(*old_info
, info
, y
, dpp
);
303 int remove_old_indexes(const RGWUserInfo
& old_info
, const RGWUserInfo
& new_info
, optional_yield y
, const DoutPrefixProvider
*dpp
) {
306 if (!old_info
.user_id
.empty() &&
307 old_info
.user_id
!= new_info
.user_id
) {
308 if (old_info
.user_id
.tenant
!= new_info
.user_id
.tenant
) {
309 ldpp_dout(dpp
, 0) << "ERROR: tenant mismatch: " << old_info
.user_id
.tenant
<< " != " << new_info
.user_id
.tenant
<< dendl
;
312 ret
= svc
.user
->remove_uid_index(ctx
, old_info
, nullptr, y
, dpp
);
313 if (ret
< 0 && ret
!= -ENOENT
) {
314 set_err_msg("ERROR: could not remove index for uid " + old_info
.user_id
.to_str());
319 if (!old_info
.user_email
.empty() &&
320 old_info
.user_email
!= new_info
.user_email
) {
321 ret
= svc
.user
->remove_email_index(dpp
, ctx
, old_info
.user_email
, y
);
322 if (ret
< 0 && ret
!= -ENOENT
) {
323 set_err_msg("ERROR: could not remove index for email " + old_info
.user_email
);
328 for ([[maybe_unused
]] const auto& [name
, access_key
] : old_info
.access_keys
) {
329 if (!new_info
.access_keys
.count(access_key
.id
)) {
330 ret
= svc
.user
->remove_key_index(dpp
, ctx
, access_key
, y
);
331 if (ret
< 0 && ret
!= -ENOENT
) {
332 set_err_msg("ERROR: could not remove index for key " + access_key
.id
);
338 for (auto old_iter
= old_info
.swift_keys
.begin(); old_iter
!= old_info
.swift_keys
.end(); ++old_iter
) {
339 const auto& swift_key
= old_iter
->second
;
340 auto new_iter
= new_info
.swift_keys
.find(swift_key
.id
);
341 if (new_iter
== new_info
.swift_keys
.end()) {
342 ret
= svc
.user
->remove_swift_name_index(dpp
, ctx
, swift_key
.id
, y
);
343 if (ret
< 0 && ret
!= -ENOENT
) {
344 set_err_msg("ERROR: could not remove index for swift_name " + swift_key
.id
);
353 const string
& get_err_msg() {
358 int RGWSI_User_RADOS::store_user_info(RGWSI_MetaBackend::Context
*ctx
,
359 const RGWUserInfo
& info
,
360 RGWUserInfo
*old_info
,
361 RGWObjVersionTracker
*objv_tracker
,
362 const real_time
& mtime
,
364 map
<string
, bufferlist
> *attrs
,
366 const DoutPrefixProvider
*dpp
)
368 PutOperation
op(svc
, ctx
,
375 int r
= op
.prepare(dpp
);
385 r
= op
.complete(dpp
);
393 int RGWSI_User_RADOS::remove_key_index(const DoutPrefixProvider
*dpp
,
394 RGWSI_MetaBackend::Context
*_ctx
,
395 const RGWAccessKey
& access_key
,
398 RGWSI_MetaBackend_SObj::Context_SObj
*ctx
= static_cast<RGWSI_MetaBackend_SObj::Context_SObj
*>(_ctx
);
399 rgw_raw_obj
obj(svc
.zone
->get_zone_params().user_keys_pool
, access_key
.id
);
400 auto sysobj
= ctx
->obj_ctx
->get_obj(obj
);
401 return sysobj
.wop().remove(dpp
, y
);
404 int RGWSI_User_RADOS::remove_email_index(const DoutPrefixProvider
*dpp
,
405 RGWSI_MetaBackend::Context
*_ctx
,
412 RGWSI_MetaBackend_SObj::Context_SObj
*ctx
= static_cast<RGWSI_MetaBackend_SObj::Context_SObj
*>(_ctx
);
413 rgw_raw_obj
obj(svc
.zone
->get_zone_params().user_email_pool
, email
);
414 auto sysobj
= ctx
->obj_ctx
->get_obj(obj
);
415 return sysobj
.wop().remove(dpp
, y
);
418 int RGWSI_User_RADOS::remove_swift_name_index(const DoutPrefixProvider
*dpp
, RGWSI_MetaBackend::Context
*_ctx
, const string
& swift_name
,
421 RGWSI_MetaBackend_SObj::Context_SObj
*ctx
= static_cast<RGWSI_MetaBackend_SObj::Context_SObj
*>(_ctx
);
422 rgw_raw_obj
obj(svc
.zone
->get_zone_params().user_swift_pool
, swift_name
);
423 auto sysobj
= ctx
->obj_ctx
->get_obj(obj
);
424 return sysobj
.wop().remove(dpp
, y
);
428 * delete a user's presence from the RGW system.
429 * First remove their bucket ACLs, then delete them
430 * from the user and user email pools. This leaves the pools
431 * themselves alone, as well as any ACLs embedded in object xattrs.
433 int RGWSI_User_RADOS::remove_user_info(RGWSI_MetaBackend::Context
*_ctx
,
434 const RGWUserInfo
& info
,
435 RGWObjVersionTracker
*objv_tracker
,
437 const DoutPrefixProvider
*dpp
)
441 auto kiter
= info
.access_keys
.begin();
442 for (; kiter
!= info
.access_keys
.end(); ++kiter
) {
443 ldpp_dout(dpp
, 10) << "removing key index: " << kiter
->first
<< dendl
;
444 ret
= remove_key_index(dpp
, _ctx
, kiter
->second
, y
);
445 if (ret
< 0 && ret
!= -ENOENT
) {
446 ldpp_dout(dpp
, 0) << "ERROR: could not remove " << kiter
->first
<< " (access key object), should be fixed (err=" << ret
<< ")" << dendl
;
451 auto siter
= info
.swift_keys
.begin();
452 for (; siter
!= info
.swift_keys
.end(); ++siter
) {
453 auto& k
= siter
->second
;
454 ldpp_dout(dpp
, 10) << "removing swift subuser index: " << k
.id
<< dendl
;
455 /* check if swift mapping exists */
456 ret
= remove_swift_name_index(dpp
, _ctx
, k
.id
, y
);
457 if (ret
< 0 && ret
!= -ENOENT
) {
458 ldpp_dout(dpp
, 0) << "ERROR: could not remove " << k
.id
<< " (swift name object), should be fixed (err=" << ret
<< ")" << dendl
;
463 ldpp_dout(dpp
, 10) << "removing email index: " << info
.user_email
<< dendl
;
464 ret
= remove_email_index(dpp
, _ctx
, info
.user_email
, y
);
465 if (ret
< 0 && ret
!= -ENOENT
) {
466 ldpp_dout(dpp
, 0) << "ERROR: could not remove email index object for "
467 << info
.user_email
<< ", should be fixed (err=" << ret
<< ")" << dendl
;
471 rgw_raw_obj uid_bucks
= get_buckets_obj(info
.user_id
);
472 ldpp_dout(dpp
, 10) << "removing user buckets index" << dendl
;
473 RGWSI_MetaBackend_SObj::Context_SObj
*ctx
= static_cast<RGWSI_MetaBackend_SObj::Context_SObj
*>(_ctx
);
474 auto sysobj
= ctx
->obj_ctx
->get_obj(uid_bucks
);
475 ret
= sysobj
.wop().remove(dpp
, y
);
476 if (ret
< 0 && ret
!= -ENOENT
) {
477 ldpp_dout(dpp
, 0) << "ERROR: could not remove " << info
.user_id
<< ":" << uid_bucks
<< ", should be fixed (err=" << ret
<< ")" << dendl
;
481 ret
= remove_uid_index(ctx
, info
, objv_tracker
, y
, dpp
);
482 if (ret
< 0 && ret
!= -ENOENT
) {
489 int RGWSI_User_RADOS::remove_uid_index(RGWSI_MetaBackend::Context
*ctx
, const RGWUserInfo
& user_info
, RGWObjVersionTracker
*objv_tracker
,
490 optional_yield y
, const DoutPrefixProvider
*dpp
)
492 ldpp_dout(dpp
, 10) << "removing user index: " << user_info
.user_id
<< dendl
;
494 RGWSI_MBSObj_RemoveParams params
;
495 int ret
= svc
.meta_be
->remove(ctx
, get_meta_key(user_info
.user_id
), params
, objv_tracker
, y
, dpp
);
496 if (ret
< 0 && ret
!= -ENOENT
&& ret
!= -ECANCELED
) {
498 user_info
.user_id
.to_str(key
);
499 rgw_raw_obj
uid_obj(svc
.zone
->get_zone_params().user_uid_pool
, key
);
500 ldpp_dout(dpp
, 0) << "ERROR: could not remove " << user_info
.user_id
<< ":" << uid_obj
<< ", should be fixed (err=" << ret
<< ")" << dendl
;
507 int RGWSI_User_RADOS::get_user_info_from_index(RGWSI_MetaBackend::Context
*_ctx
,
509 const rgw_pool
& pool
,
511 RGWObjVersionTracker
* const objv_tracker
,
512 real_time
* const pmtime
, optional_yield y
, const DoutPrefixProvider
*dpp
)
514 RGWSI_MetaBackend_SObj::Context_SObj
*ctx
= static_cast<RGWSI_MetaBackend_SObj::Context_SObj
*>(_ctx
);
516 string cache_key
= pool
.to_str() + "/" + key
;
518 if (auto e
= uinfo_cache
->find(cache_key
)) {
521 *objv_tracker
= e
->objv_tracker
;
527 user_info_cache_entry e
;
531 int ret
= rgw_get_system_obj(*ctx
->obj_ctx
, pool
, key
, bl
, nullptr, &e
.mtime
, y
, dpp
);
535 rgw_cache_entry_info cache_info
;
537 auto iter
= bl
.cbegin();
541 int ret
= read_user_info(ctx
, uid
.user_id
,
542 &e
.info
, &e
.objv_tracker
, nullptr, &cache_info
, nullptr,
547 } catch (buffer::error
& err
) {
548 ldpp_dout(dpp
, 0) << "ERROR: failed to decode user info, caught buffer::error" << dendl
;
552 uinfo_cache
->put(dpp
, svc
.cache
, cache_key
, &e
, { &cache_info
});
556 *objv_tracker
= e
.objv_tracker
;
564 * Given an email, finds the user info associated with it.
565 * returns: 0 on success, -ERR# on failure (including nonexistence)
567 int RGWSI_User_RADOS::get_user_info_by_email(RGWSI_MetaBackend::Context
*ctx
,
568 const string
& email
, RGWUserInfo
*info
,
569 RGWObjVersionTracker
*objv_tracker
,
570 real_time
*pmtime
, optional_yield y
,
571 const DoutPrefixProvider
*dpp
)
573 return get_user_info_from_index(ctx
, email
, svc
.zone
->get_zone_params().user_email_pool
,
574 info
, objv_tracker
, pmtime
, y
, dpp
);
578 * Given an swift username, finds the user_info associated with it.
579 * returns: 0 on success, -ERR# on failure (including nonexistence)
581 int RGWSI_User_RADOS::get_user_info_by_swift(RGWSI_MetaBackend::Context
*ctx
,
582 const string
& swift_name
,
583 RGWUserInfo
*info
, /* out */
584 RGWObjVersionTracker
* const objv_tracker
,
585 real_time
* const pmtime
, optional_yield y
,
586 const DoutPrefixProvider
*dpp
)
588 return get_user_info_from_index(ctx
,
590 svc
.zone
->get_zone_params().user_swift_pool
,
591 info
, objv_tracker
, pmtime
, y
, dpp
);
595 * Given an access key, finds the user info associated with it.
596 * returns: 0 on success, -ERR# on failure (including nonexistence)
598 int RGWSI_User_RADOS::get_user_info_by_access_key(RGWSI_MetaBackend::Context
*ctx
,
599 const std::string
& access_key
,
601 RGWObjVersionTracker
* objv_tracker
,
602 real_time
*pmtime
, optional_yield y
,
603 const DoutPrefixProvider
*dpp
)
605 return get_user_info_from_index(ctx
,
607 svc
.zone
->get_zone_params().user_keys_pool
,
608 info
, objv_tracker
, pmtime
, y
, dpp
);
611 int RGWSI_User_RADOS::cls_user_update_buckets(const DoutPrefixProvider
*dpp
, rgw_raw_obj
& obj
, list
<cls_user_bucket_entry
>& entries
, bool add
, optional_yield y
)
613 auto rados_obj
= svc
.rados
->obj(obj
);
614 int r
= rados_obj
.open(dpp
);
619 librados::ObjectWriteOperation op
;
620 cls_user_set_buckets(op
, entries
, add
);
621 r
= rados_obj
.operate(dpp
, &op
, y
);
629 int RGWSI_User_RADOS::cls_user_add_bucket(const DoutPrefixProvider
*dpp
, rgw_raw_obj
& obj
, const cls_user_bucket_entry
& entry
, optional_yield y
)
631 list
<cls_user_bucket_entry
> l
;
634 return cls_user_update_buckets(dpp
, obj
, l
, true, y
);
637 int RGWSI_User_RADOS::cls_user_remove_bucket(const DoutPrefixProvider
*dpp
, rgw_raw_obj
& obj
, const cls_user_bucket
& bucket
, optional_yield y
)
639 auto rados_obj
= svc
.rados
->obj(obj
);
640 int r
= rados_obj
.open(dpp
);
645 librados::ObjectWriteOperation op
;
646 ::cls_user_remove_bucket(op
, bucket
);
647 r
= rados_obj
.operate(dpp
, &op
, y
);
654 int RGWSI_User_RADOS::add_bucket(const DoutPrefixProvider
*dpp
,
655 RGWSI_MetaBackend::Context
*ctx
,
656 const rgw_user
& user
,
657 const rgw_bucket
& bucket
,
658 ceph::real_time creation_time
,
663 cls_user_bucket_entry new_bucket
;
665 bucket
.convert(&new_bucket
.bucket
);
667 if (real_clock::is_zero(creation_time
))
668 new_bucket
.creation_time
= real_clock::now();
670 new_bucket
.creation_time
= creation_time
;
672 rgw_raw_obj obj
= get_buckets_obj(user
);
673 ret
= cls_user_add_bucket(dpp
, obj
, new_bucket
, y
);
675 ldpp_dout(dpp
, 0) << "ERROR: error adding bucket to user: ret=" << ret
<< dendl
;
683 int RGWSI_User_RADOS::remove_bucket(const DoutPrefixProvider
*dpp
,
684 RGWSI_MetaBackend::Context
*ctx
,
685 const rgw_user
& user
,
686 const rgw_bucket
& _bucket
,
689 cls_user_bucket bucket
;
690 bucket
.name
= _bucket
.name
;
691 rgw_raw_obj obj
= get_buckets_obj(user
);
692 int ret
= cls_user_remove_bucket(dpp
, obj
, bucket
, y
);
694 ldpp_dout(dpp
, 0) << "ERROR: error removing bucket from user: ret=" << ret
<< dendl
;
700 int RGWSI_User_RADOS::cls_user_flush_bucket_stats(const DoutPrefixProvider
*dpp
,
701 rgw_raw_obj
& user_obj
,
702 const RGWBucketEnt
& ent
, optional_yield y
)
704 cls_user_bucket_entry entry
;
707 list
<cls_user_bucket_entry
> entries
;
708 entries
.push_back(entry
);
710 int r
= cls_user_update_buckets(dpp
, user_obj
, entries
, false, y
);
712 ldpp_dout(dpp
, 20) << "cls_user_update_buckets() returned " << r
<< dendl
;
719 int RGWSI_User_RADOS::cls_user_list_buckets(const DoutPrefixProvider
*dpp
,
721 const string
& in_marker
,
722 const string
& end_marker
,
723 const int max_entries
,
724 list
<cls_user_bucket_entry
>& entries
,
725 string
* const out_marker
,
726 bool * const truncated
,
729 auto rados_obj
= svc
.rados
->obj(obj
);
730 int r
= rados_obj
.open(dpp
);
735 librados::ObjectReadOperation op
;
738 cls_user_bucket_list(op
, in_marker
, end_marker
, max_entries
, entries
, out_marker
, truncated
, &rc
);
740 r
= rados_obj
.operate(dpp
, &op
, &ibl
, y
);
749 int RGWSI_User_RADOS::list_buckets(const DoutPrefixProvider
*dpp
,
750 RGWSI_MetaBackend::Context
*ctx
,
751 const rgw_user
& user
,
752 const string
& marker
,
753 const string
& end_marker
,
755 RGWUserBuckets
*buckets
,
756 bool *is_truncated
, optional_yield y
)
761 if (user
.id
== RGW_USER_ANON_ID
) {
762 ldpp_dout(dpp
, 20) << "RGWSI_User_RADOS::list_buckets(): anonymous user" << dendl
;
763 *is_truncated
= false;
766 rgw_raw_obj obj
= get_buckets_obj(user
);
768 bool truncated
= false;
774 std::list
<cls_user_bucket_entry
> entries
;
775 ret
= cls_user_list_buckets(dpp
, obj
, m
, end_marker
, max
- total
, entries
, &m
, &truncated
, y
);
776 if (ret
== -ENOENT
) {
784 for (auto& entry
: entries
) {
785 buckets
->add(RGWBucketEnt(user
, std::move(entry
)));
789 } while (truncated
&& total
< max
);
792 *is_truncated
= truncated
;
798 int RGWSI_User_RADOS::flush_bucket_stats(const DoutPrefixProvider
*dpp
,
799 RGWSI_MetaBackend::Context
*ctx
,
800 const rgw_user
& user
,
801 const RGWBucketEnt
& ent
,
804 rgw_raw_obj obj
= get_buckets_obj(user
);
806 return cls_user_flush_bucket_stats(dpp
, obj
, ent
, y
);
809 int RGWSI_User_RADOS::reset_bucket_stats(const DoutPrefixProvider
*dpp
,
810 RGWSI_MetaBackend::Context
*ctx
,
811 const rgw_user
& user
,
814 return cls_user_reset_stats(dpp
, user
, y
);
817 int RGWSI_User_RADOS::cls_user_reset_stats(const DoutPrefixProvider
*dpp
, const rgw_user
& user
, optional_yield y
)
819 rgw_raw_obj obj
= get_buckets_obj(user
);
820 auto rados_obj
= svc
.rados
->obj(obj
);
821 int rval
, r
= rados_obj
.open(dpp
);
826 cls_user_reset_stats2_op call
;
827 cls_user_reset_stats2_ret ret
;
830 buffer::list in
, out
;
831 librados::ObjectWriteOperation op
;
833 call
.time
= real_clock::now();
834 ret
.update_call(call
);
837 op
.exec("user", "reset_user_stats2", in
, &out
, &rval
);
838 r
= rados_obj
.operate(dpp
, &op
, y
, librados::OPERATION_RETURNVEC
);
843 auto bliter
= out
.cbegin();
845 } catch (ceph::buffer::error
& err
) {
848 } while (ret
.truncated
);
853 int RGWSI_User_RADOS::complete_flush_stats(const DoutPrefixProvider
*dpp
,
854 RGWSI_MetaBackend::Context
*ctx
,
855 const rgw_user
& user
, optional_yield y
)
857 rgw_raw_obj obj
= get_buckets_obj(user
);
858 auto rados_obj
= svc
.rados
->obj(obj
);
859 int r
= rados_obj
.open(dpp
);
863 librados::ObjectWriteOperation op
;
864 ::cls_user_complete_stats_sync(op
);
865 return rados_obj
.operate(dpp
, &op
, y
);
868 int RGWSI_User_RADOS::cls_user_get_header(const DoutPrefixProvider
*dpp
,
869 const rgw_user
& user
, cls_user_header
*header
,
872 rgw_raw_obj obj
= get_buckets_obj(user
);
873 auto rados_obj
= svc
.rados
->obj(obj
);
874 int r
= rados_obj
.open(dpp
);
880 librados::ObjectReadOperation op
;
881 ::cls_user_get_header(op
, header
, &rc
);
882 return rados_obj
.operate(dpp
, &op
, &ibl
, y
);
885 int RGWSI_User_RADOS::cls_user_get_header_async(const DoutPrefixProvider
*dpp
, const string
& user_str
, RGWGetUserHeader_CB
*cb
)
887 rgw_raw_obj obj
= get_buckets_obj(rgw_user(user_str
));
888 auto rados_obj
= svc
.rados
->obj(obj
);
889 int r
= rados_obj
.open(dpp
);
894 auto& ref
= rados_obj
.get_ref();
896 r
= ::cls_user_get_header_async(ref
.pool
.ioctx(), ref
.obj
.oid
, cb
);
904 int RGWSI_User_RADOS::read_stats(const DoutPrefixProvider
*dpp
,
905 RGWSI_MetaBackend::Context
*ctx
,
906 const rgw_user
& user
, RGWStorageStats
*stats
,
907 ceph::real_time
*last_stats_sync
,
908 ceph::real_time
*last_stats_update
,
911 string user_str
= user
.to_str();
915 int ret
= read_user_info(ctx
, user
, &info
, nullptr, &mtime
, nullptr, nullptr, null_yield
, dpp
);
921 cls_user_header header
;
922 int r
= cls_user_get_header(dpp
, rgw_user(user_str
), &header
, y
);
923 if (r
< 0 && r
!= -ENOENT
)
926 const cls_user_stats
& hs
= header
.stats
;
928 stats
->size
= hs
.total_bytes
;
929 stats
->size_rounded
= hs
.total_bytes_rounded
;
930 stats
->num_objects
= hs
.total_entries
;
932 if (last_stats_sync
) {
933 *last_stats_sync
= header
.last_stats_sync
;
936 if (last_stats_update
) {
937 *last_stats_update
= header
.last_stats_update
;
943 class RGWGetUserStatsContext
: public RGWGetUserHeader_CB
{
944 RGWGetUserStats_CB
*cb
;
947 explicit RGWGetUserStatsContext(RGWGetUserStats_CB
* const cb
)
950 void handle_response(int r
, cls_user_header
& header
) override
{
951 const cls_user_stats
& hs
= header
.stats
;
953 RGWStorageStats stats
;
955 stats
.size
= hs
.total_bytes
;
956 stats
.size_rounded
= hs
.total_bytes_rounded
;
957 stats
.num_objects
= hs
.total_entries
;
959 cb
->set_response(stats
);
962 cb
->handle_response(r
);
968 int RGWSI_User_RADOS::read_stats_async(const DoutPrefixProvider
*dpp
, RGWSI_MetaBackend::Context
*ctx
,
969 const rgw_user
& user
, RGWGetUserStats_CB
*_cb
)
971 string user_str
= user
.to_str();
973 RGWGetUserStatsContext
*cb
= new RGWGetUserStatsContext(_cb
);
974 int r
= cls_user_get_header_async(dpp
, user_str
, cb
);