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"
27 class RGWSI_User_Module
: public RGWSI_MBSObj_Handler_Module
{
28 RGWSI_User_RADOS::Svc
& svc
;
32 RGWSI_User_Module(RGWSI_User_RADOS::Svc
& _svc
) : RGWSI_MBSObj_Handler_Module("user"),
35 void get_pool_and_oid(const string
& key
, rgw_pool
*pool
, string
*oid
) override
{
37 *pool
= svc
.zone
->get_zone_params().user_uid_pool
;
44 const string
& get_oid_prefix() override
{
48 bool is_valid_oid(const string
& oid
) override
{
49 // filter out the user.buckets objects
50 return !boost::algorithm::ends_with(oid
, RGW_BUCKETS_OBJ_SUFFIX
);
53 string
key_to_oid(const string
& key
) override
{
57 string
oid_to_key(const string
& oid
) override
{
62 RGWSI_User_RADOS::RGWSI_User_RADOS(CephContext
*cct
): RGWSI_User(cct
) {
65 RGWSI_User_RADOS::~RGWSI_User_RADOS() {
68 void RGWSI_User_RADOS::init(RGWSI_RADOS
*_rados_svc
,
69 RGWSI_Zone
*_zone_svc
, RGWSI_SysObj
*_sysobj_svc
,
70 RGWSI_SysObj_Cache
*_cache_svc
, RGWSI_Meta
*_meta_svc
,
71 RGWSI_MetaBackend
*_meta_be_svc
,
72 RGWSI_SyncModules
*_sync_modules_svc
)
75 svc
.rados
= _rados_svc
;
77 svc
.sysobj
= _sysobj_svc
;
78 svc
.cache
= _cache_svc
;
80 svc
.meta_be
= _meta_be_svc
;
81 svc
.sync_modules
= _sync_modules_svc
;
84 int RGWSI_User_RADOS::do_start()
86 uinfo_cache
.reset(new RGWChainedCacheImpl
<user_info_cache_entry
>);
87 uinfo_cache
->init(svc
.cache
);
89 int r
= svc
.meta
->create_be_handler(RGWSI_MetaBackend::Type::MDBE_SOBJ
, &be_handler
);
91 ldout(ctx(), 0) << "ERROR: failed to create be handler: r=" << r
<< dendl
;
95 RGWSI_MetaBackend_Handler_SObj
*bh
= static_cast<RGWSI_MetaBackend_Handler_SObj
*>(be_handler
);
97 auto module
= new RGWSI_User_Module(svc
);
98 be_module
.reset(module
);
99 bh
->set_module(module
);
103 rgw_raw_obj
RGWSI_User_RADOS::get_buckets_obj(const rgw_user
& user
) const
105 string oid
= user
.to_str() + RGW_BUCKETS_OBJ_SUFFIX
;
106 return rgw_raw_obj(svc
.zone
->get_zone_params().user_uid_pool
, oid
);
109 int RGWSI_User_RADOS::read_user_info(RGWSI_MetaBackend::Context
*ctx
,
110 const rgw_user
& user
,
112 RGWObjVersionTracker
* const objv_tracker
,
113 real_time
* const pmtime
,
114 rgw_cache_entry_info
* const cache_info
,
115 map
<string
, bufferlist
> * const pattrs
,
118 if(user
.id
== RGW_USER_ANON_ID
) {
119 ldout(svc
.meta_be
->ctx(), 20) << "RGWSI_User_RADOS::read_user_info(): anonymous user" << dendl
;
125 RGWSI_MBSObj_GetParams
params(&bl
, pattrs
, pmtime
);
126 params
.set_cache_info(cache_info
);
128 int ret
= svc
.meta_be
->get_entry(ctx
, get_meta_key(user
), params
, objv_tracker
, y
);
133 auto iter
= bl
.cbegin();
135 decode(user_id
, iter
);
136 if (user_id
.user_id
!= user
) {
137 lderr(svc
.meta_be
->ctx()) << "ERROR: rgw_get_user_info_by_uid(): user id mismatch: " << user_id
.user_id
<< " != " << user
<< dendl
;
143 } catch (buffer::error
& err
) {
144 ldout(svc
.meta_be
->ctx(), 0) << "ERROR: failed to decode user info, caught buffer::error" << dendl
;
153 RGWSI_User_RADOS::Svc
& svc
;
154 RGWSI_MetaBackend_SObj::Context_SObj
*ctx
;
156 const RGWUserInfo
& info
;
157 RGWUserInfo
*old_info
;
158 RGWObjVersionTracker
*objv_tracker
;
159 const real_time
& mtime
;
161 map
<string
, bufferlist
> *pattrs
;
162 RGWObjVersionTracker ot
;
166 void set_err_msg(string msg
) {
167 if (!err_msg
.empty()) {
168 err_msg
= std::move(msg
);
173 PutOperation(RGWSI_User_RADOS::Svc
& svc
,
174 RGWSI_MetaBackend::Context
*_ctx
,
175 const RGWUserInfo
& info
,
176 RGWUserInfo
*old_info
,
177 RGWObjVersionTracker
*objv_tracker
,
178 const real_time
& mtime
,
180 map
<string
, bufferlist
> *pattrs
,
182 svc(svc
), info(info
), old_info(old_info
),
183 objv_tracker(objv_tracker
), mtime(mtime
),
184 exclusive(exclusive
), pattrs(pattrs
), y(y
) {
185 ctx
= static_cast<RGWSI_MetaBackend_SObj::Context_SObj
*>(_ctx
);
186 ui
.user_id
= info
.user_id
;
194 if (ot
.write_version
.tag
.empty()) {
195 if (ot
.read_version
.tag
.empty()) {
196 ot
.generate_new_write_ver(svc
.meta_be
->ctx());
198 ot
.write_version
= ot
.read_version
;
199 ot
.write_version
.ver
++;
203 for (auto iter
= info
.swift_keys
.begin(); iter
!= info
.swift_keys
.end(); ++iter
) {
204 if (old_info
&& old_info
->swift_keys
.count(iter
->first
) != 0)
206 auto& k
= iter
->second
;
207 /* check if swift mapping exists */
209 int r
= svc
.user
->get_user_info_by_swift(ctx
, k
.id
, &inf
, nullptr, nullptr, y
);
210 if (r
>= 0 && inf
.user_id
!= info
.user_id
&&
211 (!old_info
|| inf
.user_id
!= old_info
->user_id
)) {
212 ldout(svc
.meta_be
->ctx(), 0) << "WARNING: can't store user info, swift id (" << k
.id
213 << ") already mapped to another user (" << info
.user_id
<< ")" << dendl
;
218 /* check if access keys already exist */
219 for (auto iter
= info
.access_keys
.begin(); iter
!= info
.access_keys
.end(); ++iter
) {
220 if (old_info
&& old_info
->access_keys
.count(iter
->first
) != 0)
222 auto& k
= iter
->second
;
224 int r
= svc
.user
->get_user_info_by_access_key(ctx
, k
.id
, &inf
, nullptr, nullptr, y
);
225 if (r
>= 0 && inf
.user_id
!= info
.user_id
&&
226 (!old_info
|| inf
.user_id
!= old_info
->user_id
)) {
227 ldout(svc
.meta_be
->ctx(), 0) << "WARNING: can't store user info, access key already mapped to another user" << dendl
;
238 encode(info
, data_bl
);
240 RGWSI_MBSObj_PutParams
params(data_bl
, pattrs
, mtime
, exclusive
);
242 int ret
= svc
.meta_be
->put(ctx
, RGWSI_User::get_meta_key(info
.user_id
), params
, &ot
, y
);
255 auto& obj_ctx
= *ctx
->obj_ctx
;
257 if (!info
.user_email
.empty()) {
259 old_info
->user_email
.compare(info
.user_email
) != 0) { /* only if new index changed */
260 ret
= rgw_put_system_obj(obj_ctx
, svc
.zone
->get_zone_params().user_email_pool
, info
.user_email
,
261 link_bl
, exclusive
, NULL
, real_time(), y
);
267 const bool renamed
= old_info
&& old_info
->user_id
!= info
.user_id
;
268 for (auto iter
= info
.access_keys
.begin(); iter
!= info
.access_keys
.end(); ++iter
) {
269 auto& k
= iter
->second
;
270 if (old_info
&& old_info
->access_keys
.count(iter
->first
) != 0 && !renamed
)
273 ret
= rgw_put_system_obj(obj_ctx
, svc
.zone
->get_zone_params().user_keys_pool
, k
.id
,
274 link_bl
, exclusive
, NULL
, real_time(), y
);
279 for (auto siter
= info
.swift_keys
.begin(); siter
!= info
.swift_keys
.end(); ++siter
) {
280 auto& k
= siter
->second
;
281 if (old_info
&& old_info
->swift_keys
.count(siter
->first
) != 0 && !renamed
)
284 ret
= rgw_put_system_obj(obj_ctx
, svc
.zone
->get_zone_params().user_swift_pool
, k
.id
,
285 link_bl
, exclusive
, NULL
, real_time(), y
);
291 ret
= remove_old_indexes(*old_info
, info
, y
);
300 int remove_old_indexes(const RGWUserInfo
& old_info
, const RGWUserInfo
& new_info
, optional_yield y
) {
303 if (!old_info
.user_id
.empty() &&
304 old_info
.user_id
!= new_info
.user_id
) {
305 if (old_info
.user_id
.tenant
!= new_info
.user_id
.tenant
) {
306 ldout(svc
.user
->ctx(), 0) << "ERROR: tenant mismatch: " << old_info
.user_id
.tenant
<< " != " << new_info
.user_id
.tenant
<< dendl
;
309 ret
= svc
.user
->remove_uid_index(ctx
, old_info
, nullptr, y
);
310 if (ret
< 0 && ret
!= -ENOENT
) {
311 set_err_msg("ERROR: could not remove index for uid " + old_info
.user_id
.to_str());
316 if (!old_info
.user_email
.empty() &&
317 old_info
.user_email
!= new_info
.user_email
) {
318 ret
= svc
.user
->remove_email_index(ctx
, old_info
.user_email
, y
);
319 if (ret
< 0 && ret
!= -ENOENT
) {
320 set_err_msg("ERROR: could not remove index for email " + old_info
.user_email
);
325 for ([[maybe_unused
]] const auto& [name
, access_key
] : old_info
.access_keys
) {
326 if (!new_info
.access_keys
.count(access_key
.id
)) {
327 ret
= svc
.user
->remove_key_index(ctx
, access_key
, y
);
328 if (ret
< 0 && ret
!= -ENOENT
) {
329 set_err_msg("ERROR: could not remove index for key " + access_key
.id
);
335 for (auto old_iter
= old_info
.swift_keys
.begin(); old_iter
!= old_info
.swift_keys
.end(); ++old_iter
) {
336 const auto& swift_key
= old_iter
->second
;
337 auto new_iter
= new_info
.swift_keys
.find(swift_key
.id
);
338 if (new_iter
== new_info
.swift_keys
.end()) {
339 ret
= svc
.user
->remove_swift_name_index(ctx
, swift_key
.id
, y
);
340 if (ret
< 0 && ret
!= -ENOENT
) {
341 set_err_msg("ERROR: could not remove index for swift_name " + swift_key
.id
);
350 const string
& get_err_msg() {
355 int RGWSI_User_RADOS::store_user_info(RGWSI_MetaBackend::Context
*ctx
,
356 const RGWUserInfo
& info
,
357 RGWUserInfo
*old_info
,
358 RGWObjVersionTracker
*objv_tracker
,
359 const real_time
& mtime
,
361 map
<string
, bufferlist
> *attrs
,
364 PutOperation
op(svc
, ctx
,
371 int r
= op
.prepare();
389 int RGWSI_User_RADOS::remove_key_index(RGWSI_MetaBackend::Context
*_ctx
,
390 const RGWAccessKey
& access_key
,
393 RGWSI_MetaBackend_SObj::Context_SObj
*ctx
= static_cast<RGWSI_MetaBackend_SObj::Context_SObj
*>(_ctx
);
394 rgw_raw_obj
obj(svc
.zone
->get_zone_params().user_keys_pool
, access_key
.id
);
395 auto sysobj
= ctx
->obj_ctx
->get_obj(obj
);
396 return sysobj
.wop().remove(y
);
399 int RGWSI_User_RADOS::remove_email_index(RGWSI_MetaBackend::Context
*_ctx
,
406 RGWSI_MetaBackend_SObj::Context_SObj
*ctx
= static_cast<RGWSI_MetaBackend_SObj::Context_SObj
*>(_ctx
);
407 rgw_raw_obj
obj(svc
.zone
->get_zone_params().user_email_pool
, email
);
408 auto sysobj
= ctx
->obj_ctx
->get_obj(obj
);
409 return sysobj
.wop().remove(y
);
412 int RGWSI_User_RADOS::remove_swift_name_index(RGWSI_MetaBackend::Context
*_ctx
, const string
& swift_name
,
415 RGWSI_MetaBackend_SObj::Context_SObj
*ctx
= static_cast<RGWSI_MetaBackend_SObj::Context_SObj
*>(_ctx
);
416 rgw_raw_obj
obj(svc
.zone
->get_zone_params().user_swift_pool
, swift_name
);
417 auto sysobj
= ctx
->obj_ctx
->get_obj(obj
);
418 return sysobj
.wop().remove(y
);
422 * delete a user's presence from the RGW system.
423 * First remove their bucket ACLs, then delete them
424 * from the user and user email pools. This leaves the pools
425 * themselves alone, as well as any ACLs embedded in object xattrs.
427 int RGWSI_User_RADOS::remove_user_info(RGWSI_MetaBackend::Context
*_ctx
,
428 const RGWUserInfo
& info
,
429 RGWObjVersionTracker
*objv_tracker
,
434 auto cct
= svc
.meta_be
->ctx();
436 auto kiter
= info
.access_keys
.begin();
437 for (; kiter
!= info
.access_keys
.end(); ++kiter
) {
438 ldout(cct
, 10) << "removing key index: " << kiter
->first
<< dendl
;
439 ret
= remove_key_index(_ctx
, kiter
->second
, y
);
440 if (ret
< 0 && ret
!= -ENOENT
) {
441 ldout(cct
, 0) << "ERROR: could not remove " << kiter
->first
<< " (access key object), should be fixed (err=" << ret
<< ")" << dendl
;
446 auto siter
= info
.swift_keys
.begin();
447 for (; siter
!= info
.swift_keys
.end(); ++siter
) {
448 auto& k
= siter
->second
;
449 ldout(cct
, 10) << "removing swift subuser index: " << k
.id
<< dendl
;
450 /* check if swift mapping exists */
451 ret
= remove_swift_name_index(_ctx
, k
.id
, y
);
452 if (ret
< 0 && ret
!= -ENOENT
) {
453 ldout(cct
, 0) << "ERROR: could not remove " << k
.id
<< " (swift name object), should be fixed (err=" << ret
<< ")" << dendl
;
458 ldout(cct
, 10) << "removing email index: " << info
.user_email
<< dendl
;
459 ret
= remove_email_index(_ctx
, info
.user_email
, y
);
460 if (ret
< 0 && ret
!= -ENOENT
) {
461 ldout(cct
, 0) << "ERROR: could not remove email index object for "
462 << info
.user_email
<< ", should be fixed (err=" << ret
<< ")" << dendl
;
466 rgw_raw_obj uid_bucks
= get_buckets_obj(info
.user_id
);
467 ldout(cct
, 10) << "removing user buckets index" << dendl
;
468 RGWSI_MetaBackend_SObj::Context_SObj
*ctx
= static_cast<RGWSI_MetaBackend_SObj::Context_SObj
*>(_ctx
);
469 auto sysobj
= ctx
->obj_ctx
->get_obj(uid_bucks
);
470 ret
= sysobj
.wop().remove(y
);
471 if (ret
< 0 && ret
!= -ENOENT
) {
472 ldout(cct
, 0) << "ERROR: could not remove " << info
.user_id
<< ":" << uid_bucks
<< ", should be fixed (err=" << ret
<< ")" << dendl
;
476 ret
= remove_uid_index(ctx
, info
, objv_tracker
, y
);
477 if (ret
< 0 && ret
!= -ENOENT
) {
484 int RGWSI_User_RADOS::remove_uid_index(RGWSI_MetaBackend::Context
*ctx
, const RGWUserInfo
& user_info
, RGWObjVersionTracker
*objv_tracker
,
487 ldout(cct
, 10) << "removing user index: " << user_info
.user_id
<< dendl
;
489 RGWSI_MBSObj_RemoveParams params
;
490 int ret
= svc
.meta_be
->remove(ctx
, get_meta_key(user_info
.user_id
), params
, objv_tracker
, y
);
491 if (ret
< 0 && ret
!= -ENOENT
&& ret
!= -ECANCELED
) {
493 user_info
.user_id
.to_str(key
);
494 rgw_raw_obj
uid_obj(svc
.zone
->get_zone_params().user_uid_pool
, key
);
495 ldout(cct
, 0) << "ERROR: could not remove " << user_info
.user_id
<< ":" << uid_obj
<< ", should be fixed (err=" << ret
<< ")" << dendl
;
502 int RGWSI_User_RADOS::get_user_info_from_index(RGWSI_MetaBackend::Context
*_ctx
,
504 const rgw_pool
& pool
,
506 RGWObjVersionTracker
* const objv_tracker
,
507 real_time
* const pmtime
, optional_yield y
)
509 RGWSI_MetaBackend_SObj::Context_SObj
*ctx
= static_cast<RGWSI_MetaBackend_SObj::Context_SObj
*>(_ctx
);
511 string cache_key
= pool
.to_str() + "/" + key
;
513 if (auto e
= uinfo_cache
->find(cache_key
)) {
516 *objv_tracker
= e
->objv_tracker
;
522 user_info_cache_entry e
;
526 int ret
= rgw_get_system_obj(*ctx
->obj_ctx
, pool
, key
, bl
, nullptr, &e
.mtime
, y
);
530 rgw_cache_entry_info cache_info
;
532 auto iter
= bl
.cbegin();
536 int ret
= read_user_info(ctx
, uid
.user_id
,
537 &e
.info
, &e
.objv_tracker
, nullptr, &cache_info
, nullptr,
542 } catch (buffer::error
& err
) {
543 ldout(svc
.meta_be
->ctx(), 0) << "ERROR: failed to decode user info, caught buffer::error" << dendl
;
547 uinfo_cache
->put(svc
.cache
, cache_key
, &e
, { &cache_info
});
551 *objv_tracker
= e
.objv_tracker
;
559 * Given an email, finds the user info associated with it.
560 * returns: 0 on success, -ERR# on failure (including nonexistence)
562 int RGWSI_User_RADOS::get_user_info_by_email(RGWSI_MetaBackend::Context
*ctx
,
563 const string
& email
, RGWUserInfo
*info
,
564 RGWObjVersionTracker
*objv_tracker
,
565 real_time
*pmtime
, optional_yield y
)
567 return get_user_info_from_index(ctx
, email
, svc
.zone
->get_zone_params().user_email_pool
,
568 info
, objv_tracker
, pmtime
, y
);
572 * Given an swift username, finds the user_info associated with it.
573 * returns: 0 on success, -ERR# on failure (including nonexistence)
575 int RGWSI_User_RADOS::get_user_info_by_swift(RGWSI_MetaBackend::Context
*ctx
,
576 const string
& swift_name
,
577 RGWUserInfo
*info
, /* out */
578 RGWObjVersionTracker
* const objv_tracker
,
579 real_time
* const pmtime
, optional_yield y
)
581 return get_user_info_from_index(ctx
,
583 svc
.zone
->get_zone_params().user_swift_pool
,
584 info
, objv_tracker
, pmtime
, y
);
588 * Given an access key, finds the user info associated with it.
589 * returns: 0 on success, -ERR# on failure (including nonexistence)
591 int RGWSI_User_RADOS::get_user_info_by_access_key(RGWSI_MetaBackend::Context
*ctx
,
592 const std::string
& access_key
,
594 RGWObjVersionTracker
* objv_tracker
,
595 real_time
*pmtime
, optional_yield y
)
597 return get_user_info_from_index(ctx
,
599 svc
.zone
->get_zone_params().user_keys_pool
,
600 info
, objv_tracker
, pmtime
, y
);
603 int RGWSI_User_RADOS::cls_user_update_buckets(rgw_raw_obj
& obj
, list
<cls_user_bucket_entry
>& entries
, bool add
)
605 auto rados_obj
= svc
.rados
->obj(obj
);
606 int r
= rados_obj
.open();
611 librados::ObjectWriteOperation op
;
612 cls_user_set_buckets(op
, entries
, add
);
613 r
= rados_obj
.operate(&op
, null_yield
);
621 int RGWSI_User_RADOS::cls_user_add_bucket(rgw_raw_obj
& obj
, const cls_user_bucket_entry
& entry
)
623 list
<cls_user_bucket_entry
> l
;
626 return cls_user_update_buckets(obj
, l
, true);
629 int RGWSI_User_RADOS::cls_user_remove_bucket(rgw_raw_obj
& obj
, const cls_user_bucket
& bucket
)
631 auto rados_obj
= svc
.rados
->obj(obj
);
632 int r
= rados_obj
.open();
637 librados::ObjectWriteOperation op
;
638 ::cls_user_remove_bucket(op
, bucket
);
639 r
= rados_obj
.operate(&op
, null_yield
);
646 int RGWSI_User_RADOS::add_bucket(RGWSI_MetaBackend::Context
*ctx
,
647 const rgw_user
& user
,
648 const rgw_bucket
& bucket
,
649 ceph::real_time creation_time
)
653 cls_user_bucket_entry new_bucket
;
655 bucket
.convert(&new_bucket
.bucket
);
657 if (real_clock::is_zero(creation_time
))
658 new_bucket
.creation_time
= real_clock::now();
660 new_bucket
.creation_time
= creation_time
;
662 rgw_raw_obj obj
= get_buckets_obj(user
);
663 ret
= cls_user_add_bucket(obj
, new_bucket
);
665 ldout(cct
, 0) << "ERROR: error adding bucket to user: ret=" << ret
<< dendl
;
673 int RGWSI_User_RADOS::remove_bucket(RGWSI_MetaBackend::Context
*ctx
,
674 const rgw_user
& user
,
675 const rgw_bucket
& _bucket
)
677 cls_user_bucket bucket
;
678 bucket
.name
= _bucket
.name
;
679 rgw_raw_obj obj
= get_buckets_obj(user
);
680 int ret
= cls_user_remove_bucket(obj
, bucket
);
682 ldout(cct
, 0) << "ERROR: error removing bucket from user: ret=" << ret
<< dendl
;
688 int RGWSI_User_RADOS::cls_user_flush_bucket_stats(rgw_raw_obj
& user_obj
,
689 const RGWBucketEnt
& ent
)
691 cls_user_bucket_entry entry
;
694 list
<cls_user_bucket_entry
> entries
;
695 entries
.push_back(entry
);
697 int r
= cls_user_update_buckets(user_obj
, entries
, false);
699 ldout(cct
, 20) << "cls_user_update_buckets() returned " << r
<< dendl
;
706 int RGWSI_User_RADOS::cls_user_list_buckets(rgw_raw_obj
& obj
,
707 const string
& in_marker
,
708 const string
& end_marker
,
709 const int max_entries
,
710 list
<cls_user_bucket_entry
>& entries
,
711 string
* const out_marker
,
712 bool * const truncated
)
714 auto rados_obj
= svc
.rados
->obj(obj
);
715 int r
= rados_obj
.open();
720 librados::ObjectReadOperation op
;
723 cls_user_bucket_list(op
, in_marker
, end_marker
, max_entries
, entries
, out_marker
, truncated
, &rc
);
725 r
= rados_obj
.operate(&op
, &ibl
, null_yield
);
734 int RGWSI_User_RADOS::list_buckets(RGWSI_MetaBackend::Context
*ctx
,
735 const rgw_user
& user
,
736 const string
& marker
,
737 const string
& end_marker
,
739 RGWUserBuckets
*buckets
,
745 if (user
.id
== RGW_USER_ANON_ID
) {
746 ldout(cct
, 20) << "RGWSI_User_RADOS::list_buckets(): anonymous user" << dendl
;
747 *is_truncated
= false;
750 rgw_raw_obj obj
= get_buckets_obj(user
);
752 bool truncated
= false;
758 std::list
<cls_user_bucket_entry
> entries
;
759 ret
= cls_user_list_buckets(obj
, m
, end_marker
, max
- total
, entries
, &m
, &truncated
);
760 if (ret
== -ENOENT
) {
768 for (auto& entry
: entries
) {
769 buckets
->add(RGWBucketEnt(user
, std::move(entry
)));
773 } while (truncated
&& total
< max
);
776 *is_truncated
= truncated
;
782 int RGWSI_User_RADOS::flush_bucket_stats(RGWSI_MetaBackend::Context
*ctx
,
783 const rgw_user
& user
,
784 const RGWBucketEnt
& ent
)
786 rgw_raw_obj obj
= get_buckets_obj(user
);
788 return cls_user_flush_bucket_stats(obj
, ent
);
791 int RGWSI_User_RADOS::reset_bucket_stats(RGWSI_MetaBackend::Context
*ctx
,
792 const rgw_user
& user
)
794 return cls_user_reset_stats(user
);
797 int RGWSI_User_RADOS::cls_user_reset_stats(const rgw_user
& user
)
799 rgw_raw_obj obj
= get_buckets_obj(user
);
800 auto rados_obj
= svc
.rados
->obj(obj
);
801 int rval
, r
= rados_obj
.open();
806 cls_user_reset_stats2_op call
;
807 cls_user_reset_stats2_ret ret
;
810 buffer::list in
, out
;
811 librados::ObjectWriteOperation op
;
813 call
.time
= real_clock::now();
814 ret
.update_call(call
);
817 op
.exec("user", "reset_user_stats2", in
, &out
, &rval
);
818 r
= rados_obj
.operate(&op
, null_yield
, librados::OPERATION_RETURNVEC
);
823 auto bliter
= out
.cbegin();
825 } catch (ceph::buffer::error
& err
) {
828 } while (ret
.truncated
);
833 int RGWSI_User_RADOS::complete_flush_stats(RGWSI_MetaBackend::Context
*ctx
,
834 const rgw_user
& user
)
836 rgw_raw_obj obj
= get_buckets_obj(user
);
837 auto rados_obj
= svc
.rados
->obj(obj
);
838 int r
= rados_obj
.open();
842 librados::ObjectWriteOperation op
;
843 ::cls_user_complete_stats_sync(op
);
844 return rados_obj
.operate(&op
, null_yield
);
847 int RGWSI_User_RADOS::cls_user_get_header(const rgw_user
& user
, cls_user_header
*header
)
849 rgw_raw_obj obj
= get_buckets_obj(user
);
850 auto rados_obj
= svc
.rados
->obj(obj
);
851 int r
= rados_obj
.open();
857 librados::ObjectReadOperation op
;
858 ::cls_user_get_header(op
, header
, &rc
);
859 return rados_obj
.operate(&op
, &ibl
, null_yield
);
862 int RGWSI_User_RADOS::cls_user_get_header_async(const string
& user_str
, RGWGetUserHeader_CB
*cb
)
864 rgw_raw_obj obj
= get_buckets_obj(rgw_user(user_str
));
865 auto rados_obj
= svc
.rados
->obj(obj
);
866 int r
= rados_obj
.open();
871 auto& ref
= rados_obj
.get_ref();
873 r
= ::cls_user_get_header_async(ref
.pool
.ioctx(), ref
.obj
.oid
, cb
);
881 int RGWSI_User_RADOS::read_stats(RGWSI_MetaBackend::Context
*ctx
,
882 const rgw_user
& user
, RGWStorageStats
*stats
,
883 ceph::real_time
*last_stats_sync
,
884 ceph::real_time
*last_stats_update
)
886 string user_str
= user
.to_str();
888 cls_user_header header
;
889 int r
= cls_user_get_header(rgw_user(user_str
), &header
);
893 const cls_user_stats
& hs
= header
.stats
;
895 stats
->size
= hs
.total_bytes
;
896 stats
->size_rounded
= hs
.total_bytes_rounded
;
897 stats
->num_objects
= hs
.total_entries
;
899 if (last_stats_sync
) {
900 *last_stats_sync
= header
.last_stats_sync
;
903 if (last_stats_update
) {
904 *last_stats_update
= header
.last_stats_update
;
910 class RGWGetUserStatsContext
: public RGWGetUserHeader_CB
{
911 RGWGetUserStats_CB
*cb
;
914 explicit RGWGetUserStatsContext(RGWGetUserStats_CB
* const cb
)
917 void handle_response(int r
, cls_user_header
& header
) override
{
918 const cls_user_stats
& hs
= header
.stats
;
920 RGWStorageStats stats
;
922 stats
.size
= hs
.total_bytes
;
923 stats
.size_rounded
= hs
.total_bytes_rounded
;
924 stats
.num_objects
= hs
.total_entries
;
926 cb
->set_response(stats
);
929 cb
->handle_response(r
);
935 int RGWSI_User_RADOS::read_stats_async(RGWSI_MetaBackend::Context
*ctx
,
936 const rgw_user
& user
, RGWGetUserStats_CB
*_cb
)
938 string user_str
= user
.to_str();
940 RGWGetUserStatsContext
*cb
= new RGWGetUserStatsContext(_cb
);
941 int r
= cls_user_get_header_async(user_str
, cb
);