From: Casey Bodley Date: Fri, 1 Dec 2023 03:06:27 +0000 (-0500) Subject: rgw/rados: add rgwrados::buckets namespace abstraction for cls_user X-Git-Tag: v19.1.0~99^2~144 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=fbdd11fc3f8441c2ce56341f1bdec6daaa81c08f;p=ceph.git rgw/rados: add rgwrados::buckets namespace abstraction for cls_user move cls_user stuff out of RGWSI_User_RADOS into namespace rgwrados::buckets that doesn't depend on rgw_user, so it can also be used for account bucket owners Signed-off-by: Casey Bodley (cherry picked from commit 92f04d8637f78d916a3bcf955fe7cff56f053283) --- diff --git a/src/rgw/CMakeLists.txt b/src/rgw/CMakeLists.txt index ebe113984dd..dc6be92af87 100644 --- a/src/rgw/CMakeLists.txt +++ b/src/rgw/CMakeLists.txt @@ -151,6 +151,7 @@ set(librgw_common_srcs rgw_lua_background.cc rgw_data_access.cc driver/rados/account.cc + driver/rados/buckets.cc driver/rados/cls_fifo_legacy.cc driver/rados/rgw_bucket.cc driver/rados/rgw_bucket_sync.cc diff --git a/src/rgw/driver/rados/buckets.cc b/src/rgw/driver/rados/buckets.cc new file mode 100644 index 00000000000..8c35028d093 --- /dev/null +++ b/src/rgw/driver/rados/buckets.cc @@ -0,0 +1,275 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +/* + * Ceph - scalable distributed file system + * + * Copyright contributors to the Ceph project + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#include "buckets.h" +#include "include/rados/librados.hpp" +#include "common/async/yield_context.h" +#include "common/dout.h" +#include "cls/user/cls_user_client.h" +#include "rgw_common.h" +#include "rgw_sal.h" +#include "rgw_tools.h" + +namespace rgwrados::buckets { + +static int set(const DoutPrefixProvider* dpp, optional_yield y, + librados::Rados& rados, const rgw_raw_obj& obj, + cls_user_bucket_entry&& entry, bool add) +{ + std::list entries; + entries.push_back(std::move(entry)); + + rgw_rados_ref ref; + int r = rgw_get_rados_ref(dpp, &rados, obj, &ref); + if (r < 0) { + return r; + } + + librados::ObjectWriteOperation op; + ::cls_user_set_buckets(op, entries, add); + return ref.operate(dpp, &op, y); +} + +int add(const DoutPrefixProvider* dpp, optional_yield y, + librados::Rados& rados, const rgw_raw_obj& obj, + const rgw_bucket& bucket, ceph::real_time creation_time) +{ + cls_user_bucket_entry entry; + bucket.convert(&entry.bucket); + + if (ceph::real_clock::is_zero(creation_time)) { + entry.creation_time = ceph::real_clock::now(); + } else { + entry.creation_time = creation_time; + } + + constexpr bool add = true; // create/update entry + return set(dpp, y, rados, obj, std::move(entry), add); +} + +int remove(const DoutPrefixProvider* dpp, optional_yield y, + librados::Rados& rados, const rgw_raw_obj& obj, + const rgw_bucket& bucket) +{ + cls_user_bucket clsbucket; + bucket.convert(&clsbucket); + + rgw_rados_ref ref; + int r = rgw_get_rados_ref(dpp, &rados, obj, &ref); + if (r < 0) { + return r; + } + + librados::ObjectWriteOperation op; + ::cls_user_remove_bucket(op, clsbucket); + return ref.operate(dpp, &op, y); +} + +int list(const DoutPrefixProvider* dpp, optional_yield y, + librados::Rados& rados, const rgw_raw_obj& obj, + const std::string& tenant, const std::string& start_marker, + const std::string& end_marker, uint64_t max, + rgw::sal::BucketList& listing) +{ + listing.buckets.clear(); + + rgw_rados_ref ref; + int r = rgw_get_rados_ref(dpp, &rados, obj, &ref); + if (r < 0) { + return r; + } + + std::string marker = start_marker; + bool truncated = false; + + do { + const uint64_t count = max - listing.buckets.size(); + std::list entries; + + librados::ObjectReadOperation op; + int rc = 0; + ::cls_user_bucket_list(op, marker, end_marker, count, + entries, &marker, &truncated, &rc); + + bufferlist bl; + int r = ref.operate(dpp, &op, &bl, y); + if (r == -ENOENT) { + listing.next_marker.clear(); + return 0; + } + if (r < 0) { + return r; + } + if (rc < 0) { + return rc; + } + + for (auto& entry : entries) { + RGWBucketEnt ent; + ent.bucket.tenant = tenant; + ent.bucket.name = std::move(entry.bucket.name); + ent.bucket.marker = std::move(entry.bucket.marker); + ent.bucket.bucket_id = std::move(entry.bucket.bucket_id); + ent.size = entry.size; + ent.size_rounded = entry.size_rounded; + ent.creation_time = entry.creation_time; + ent.count = entry.count; + + listing.buckets.push_back(std::move(ent)); + } + } while (truncated && listing.buckets.size() < max); + + if (truncated) { + listing.next_marker = std::move(marker); + } else { + listing.next_marker.clear(); + } + return 0; +} + +int write_stats(const DoutPrefixProvider* dpp, optional_yield y, + librados::Rados& rados, const rgw_raw_obj& obj, + const RGWBucketEnt& ent) +{ + cls_user_bucket_entry entry; + ent.convert(&entry); + + constexpr bool add = false; // bucket entry must exist + return set(dpp, y, rados, obj, std::move(entry), add); +} + +int read_stats(const DoutPrefixProvider* dpp, optional_yield y, + librados::Rados& rados, const rgw_raw_obj& obj, + RGWStorageStats& stats, ceph::real_time* last_synced, + ceph::real_time* last_updated) +{ + rgw_rados_ref ref; + int r = rgw_get_rados_ref(dpp, &rados, obj, &ref); + if (r < 0) { + return r; + } + + librados::ObjectReadOperation op; + cls_user_header header; + ::cls_user_get_header(op, &header, nullptr); + + bufferlist bl; + r = ref.operate(dpp, &op, &bl, y); + if (r < 0 && r != -ENOENT) { + return r; + } + + stats.size = header.stats.total_bytes; + stats.size_rounded = header.stats.total_bytes_rounded; + stats.num_objects = header.stats.total_entries; + if (last_synced) { + *last_synced = header.last_stats_sync; + } + if (last_updated) { + *last_updated = header.last_stats_update; + } + return 0; +} + +// callback wrapper for cls_user_get_header_async() +class AsyncHeaderCB : public RGWGetUserHeader_CB { + boost::intrusive_ptr cb; + public: + explicit AsyncHeaderCB(boost::intrusive_ptr cb) + : cb(std::move(cb)) {} + + void handle_response(int r, cls_user_header& header) override { + const cls_user_stats& hs = header.stats; + RGWStorageStats stats; + stats.size = hs.total_bytes; + stats.size_rounded = hs.total_bytes_rounded; + stats.num_objects = hs.total_entries; + cb->handle_response(r, stats); + cb.reset(); + } +}; + +int read_stats_async(const DoutPrefixProvider* dpp, + librados::Rados& rados, + const rgw_raw_obj& obj, + boost::intrusive_ptr cb) +{ + rgw_rados_ref ref; + int r = rgw_get_rados_ref(dpp, &rados, obj, &ref); + if (r < 0) { + return r; + } + + auto headercb = std::make_unique(std::move(cb)); + r = ::cls_user_get_header_async(ref.ioctx, ref.obj.oid, headercb.get()); + if (r >= 0) { + headercb.release(); // release ownership, handle_response() will free + } + return r; +} + +int reset_stats(const DoutPrefixProvider* dpp, optional_yield y, + librados::Rados& rados, const rgw_raw_obj& obj) +{ + rgw_rados_ref ref; + int r = rgw_get_rados_ref(dpp, &rados, obj, &ref); + if (r < 0) { + return r; + } + + int rval; + + cls_user_reset_stats2_op call; + cls_user_reset_stats2_ret ret; + + do { + buffer::list in, out; + librados::ObjectWriteOperation op; + + call.time = ceph::real_clock::now(); + ret.update_call(call); + + encode(call, in); + op.exec("user", "reset_user_stats2", in, &out, &rval); + r = ref.operate(dpp, &op, y, librados::OPERATION_RETURNVEC); + if (r < 0) { + return r; + } + try { + auto bliter = out.cbegin(); + decode(ret, bliter); + } catch (ceph::buffer::error& err) { + return -EINVAL; + } + } while (ret.truncated); + + return rval; +} + +int complete_flush_stats(const DoutPrefixProvider* dpp, optional_yield y, + librados::Rados& rados, const rgw_raw_obj& obj) +{ + rgw_rados_ref ref; + int r = rgw_get_rados_ref(dpp, &rados, obj, &ref); + if (r < 0) { + return r; + } + + librados::ObjectWriteOperation op; + ::cls_user_complete_stats_sync(op); + return ref.operate(dpp, &op, y); +} + +} // namespace rgwrados::buckets diff --git a/src/rgw/driver/rados/buckets.h b/src/rgw/driver/rados/buckets.h new file mode 100644 index 00000000000..3ac29f8de39 --- /dev/null +++ b/src/rgw/driver/rados/buckets.h @@ -0,0 +1,96 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +/* + * Ceph - scalable distributed file system + * + * Copyright contributors to the Ceph project + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#pragma once + +#include +#include +#include +#include "include/rados/librados_fwd.hpp" +#include "common/ceph_time.h" +#include "rgw_sal_fwd.h" + +class DoutPrefixProvider; +class optional_yield; +struct rgw_bucket; +struct rgw_raw_obj; +struct RGWBucketEnt; +struct RGWStorageStats; + +/// Interface for bucket owners (users or accounts) to manage +/// their list of buckets and storage stats with cls_user. +namespace rgwrados::buckets { + +/// Add the given bucket to the list. +int add(const DoutPrefixProvider* dpp, + optional_yield y, + librados::Rados& rados, + const rgw_raw_obj& obj, + const rgw_bucket& bucket, + ceph::real_time creation_time); + +/// Remove the given bucket from the list. +int remove(const DoutPrefixProvider* dpp, + optional_yield y, + librados::Rados& rados, + const rgw_raw_obj& obj, + const rgw_bucket& bucket); + +/// Return a paginated list of buckets. +int list(const DoutPrefixProvider* dpp, + optional_yield y, + librados::Rados& rados, + const rgw_raw_obj& obj, + const std::string& tenant, + const std::string& marker, + const std::string& end_marker, + uint64_t max, + rgw::sal::BucketList& buckets); + +/// Update usage stats for the given bucket. +int write_stats(const DoutPrefixProvider* dpp, + optional_yield y, + librados::Rados& rados, + const rgw_raw_obj& obj, + const RGWBucketEnt& bucket); + +/// Read the total usage stats of all buckets. +int read_stats(const DoutPrefixProvider* dpp, + optional_yield y, + librados::Rados& rados, + const rgw_raw_obj& obj, + RGWStorageStats& stats, + ceph::real_time* last_synced, + ceph::real_time* last_updated); + +/// Read the total usage stats of all buckets asynchronously. +int read_stats_async(const DoutPrefixProvider* dpp, + librados::Rados& rados, + const rgw_raw_obj& obj, + boost::intrusive_ptr cb); + +/// Recalculate the sum of bucket usage. +int reset_stats(const DoutPrefixProvider* dpp, + optional_yield y, + librados::Rados& rados, + const rgw_raw_obj& obj); + +/// Update the last_synced timestamp. +int complete_flush_stats(const DoutPrefixProvider* dpp, + optional_yield y, + librados::Rados& rados, + const rgw_raw_obj& obj); + +} // namespace rgwrados::buckets diff --git a/src/rgw/driver/rados/cls_fifo_legacy.h b/src/rgw/driver/rados/cls_fifo_legacy.h index c345c728512..ed23129eb30 100644 --- a/src/rgw/driver/rados/cls_fifo_legacy.h +++ b/src/rgw/driver/rados/cls_fifo_legacy.h @@ -41,7 +41,7 @@ namespace rgw::cls::fifo { namespace cb = ceph::buffer; -namespace fifo = rados::cls::fifo; +namespace fifo = ::rados::cls::fifo; namespace lr = librados; inline constexpr std::uint64_t default_max_part_size = 4 * 1024 * 1024; diff --git a/src/rgw/driver/rados/rgw_bucket.cc b/src/rgw/driver/rados/rgw_bucket.cc index ce869f399d6..d5304fec499 100644 --- a/src/rgw/driver/rados/rgw_bucket.cc +++ b/src/rgw/driver/rados/rgw_bucket.cc @@ -3233,11 +3233,11 @@ int RGWBucketCtl::read_bucket_stats(const rgw_bucket& bucket, }); } -int RGWBucketCtl::read_buckets_stats(map& m, +int RGWBucketCtl::read_buckets_stats(std::vector& buckets, optional_yield y, const DoutPrefixProvider *dpp) { return call([&](RGWSI_Bucket_X_Ctx& ctx) { - return svc.bucket->read_buckets_stats(ctx, m, y, dpp); + return svc.bucket->read_buckets_stats(ctx, buckets, y, dpp); }); } diff --git a/src/rgw/driver/rados/rgw_bucket.h b/src/rgw/driver/rados/rgw_bucket.h index 5af10b524de..a1a59dc321e 100644 --- a/src/rgw/driver/rados/rgw_bucket.h +++ b/src/rgw/driver/rados/rgw_bucket.h @@ -692,7 +692,7 @@ public: const DoutPrefixProvider *dpp, bool update_entrypoint = true); - int read_buckets_stats(std::map& m, + int read_buckets_stats(std::vector& buckets, optional_yield y, const DoutPrefixProvider *dpp); diff --git a/src/rgw/driver/rados/rgw_sal_rados.cc b/src/rgw/driver/rados/rgw_sal_rados.cc index b6aab98aae2..8b6d4992c3d 100644 --- a/src/rgw/driver/rados/rgw_sal_rados.cc +++ b/src/rgw/driver/rados/rgw_sal_rados.cc @@ -105,27 +105,8 @@ int RadosUser::list_buckets(const DoutPrefixProvider* dpp, const std::string& ma const std::string& end_marker, uint64_t max, bool need_stats, BucketList &result, optional_yield y) { - RGWUserBuckets ulist; - bool is_truncated = false; - - int ret = store->ctl()->user->list_buckets(dpp, get_id(), marker, end_marker, - max, need_stats, &ulist, - &is_truncated, y); - if (ret < 0) - return ret; - - result.buckets.clear(); - - for (auto& ent : ulist.get_buckets()) { - result.buckets.push_back(std::move(ent.second)); - } - - if (is_truncated && !result.buckets.empty()) { - result.next_marker = result.buckets.back().bucket.name; - } else { - result.next_marker.clear(); - } - return 0; + return store->ctl()->user->list_buckets(dpp, get_id(), marker, end_marker, + max, need_stats, result, y); } int RadosBucket::create(const DoutPrefixProvider* dpp, diff --git a/src/rgw/driver/rados/rgw_user.cc b/src/rgw/driver/rados/rgw_user.cc index a4b00a9b5e9..c894349664c 100644 --- a/src/rgw/driver/rados/rgw_user.cc +++ b/src/rgw/driver/rados/rgw_user.cc @@ -2789,8 +2789,7 @@ int RGWUserCtl::list_buckets(const DoutPrefixProvider *dpp, const string& end_marker, uint64_t max, bool need_stats, - RGWUserBuckets *buckets, - bool *is_truncated, + rgw::sal::BucketList& listing, optional_yield y, uint64_t default_max) { @@ -2799,13 +2798,12 @@ int RGWUserCtl::list_buckets(const DoutPrefixProvider *dpp, } int ret = svc.user->list_buckets(dpp, user, marker, end_marker, - max, buckets, is_truncated, y); + max, listing, y); if (ret < 0) { return ret; } if (need_stats) { - map& m = buckets->get_buckets(); - ret = ctl.bucket->read_buckets_stats(m, y, dpp); + ret = ctl.bucket->read_buckets_stats(listing.buckets, y, dpp); if (ret < 0 && ret != -ENOENT) { ldpp_dout(dpp, 0) << "ERROR: could not get stats for buckets" << dendl; return ret; diff --git a/src/rgw/driver/rados/rgw_user.h b/src/rgw/driver/rados/rgw_user.h index 373b672e6eb..7947b3094bd 100644 --- a/src/rgw/driver/rados/rgw_user.h +++ b/src/rgw/driver/rados/rgw_user.h @@ -880,8 +880,7 @@ public: const std::string& end_marker, uint64_t max, bool need_stats, - RGWUserBuckets *buckets, - bool *is_truncated, + rgw::sal::BucketList& listing, optional_yield y, uint64_t default_max = 1000); diff --git a/src/rgw/services/svc_bucket.h b/src/rgw/services/svc_bucket.h index caf6e029452..5963c54171f 100644 --- a/src/rgw/services/svc_bucket.h +++ b/src/rgw/services/svc_bucket.h @@ -104,7 +104,7 @@ public: const DoutPrefixProvider *dpp) = 0; virtual int read_buckets_stats(RGWSI_Bucket_X_Ctx& ctx, - std::map& m, + std::vector& buckets, optional_yield y, const DoutPrefixProvider *dpp) = 0; }; diff --git a/src/rgw/services/svc_bucket_sobj.cc b/src/rgw/services/svc_bucket_sobj.cc index 9927cc2d3a9..41e7b02e175 100644 --- a/src/rgw/services/svc_bucket_sobj.cc +++ b/src/rgw/services/svc_bucket_sobj.cc @@ -626,13 +626,11 @@ int RGWSI_Bucket_SObj::read_bucket_stats(RGWSI_Bucket_X_Ctx& ctx, } int RGWSI_Bucket_SObj::read_buckets_stats(RGWSI_Bucket_X_Ctx& ctx, - map& m, + std::vector& buckets, optional_yield y, const DoutPrefixProvider *dpp) { - map::iterator iter; - for (iter = m.begin(); iter != m.end(); ++iter) { - RGWBucketEnt& ent = iter->second; + for (auto& ent : buckets) { int r = read_bucket_stats(ctx, ent.bucket, &ent, y, dpp); if (r < 0) { ldpp_dout(dpp, 0) << "ERROR: " << __func__ << "(): read_bucket_stats returned r=" << r << dendl; @@ -640,5 +638,5 @@ int RGWSI_Bucket_SObj::read_buckets_stats(RGWSI_Bucket_X_Ctx& ctx, } } - return m.size(); + return buckets.size(); } diff --git a/src/rgw/services/svc_bucket_sobj.h b/src/rgw/services/svc_bucket_sobj.h index 7a466ca37dd..9b95ca18fa4 100644 --- a/src/rgw/services/svc_bucket_sobj.h +++ b/src/rgw/services/svc_bucket_sobj.h @@ -173,7 +173,7 @@ public: const DoutPrefixProvider *dpp) override; int read_buckets_stats(RGWSI_Bucket_X_Ctx& ctx, - std::map& m, + std::vector& buckets, optional_yield y, const DoutPrefixProvider *dpp) override; }; diff --git a/src/rgw/services/svc_user.h b/src/rgw/services/svc_user.h index f53ec49f259..cf46df6e3d1 100644 --- a/src/rgw/services/svc_user.h +++ b/src/rgw/services/svc_user.h @@ -102,8 +102,7 @@ public: const std::string& marker, const std::string& end_marker, uint64_t max, - RGWUserBuckets *buckets, - bool *is_truncated, + rgw::sal::BucketList& listing, optional_yield y) = 0; virtual int flush_bucket_stats(const DoutPrefixProvider *dpp, diff --git a/src/rgw/services/svc_user_rados.cc b/src/rgw/services/svc_user_rados.cc index 9d06d5f13af..b8fdd3212fd 100644 --- a/src/rgw/services/svc_user_rados.cc +++ b/src/rgw/services/svc_user_rados.cc @@ -19,7 +19,7 @@ #include "rgw_zone.h" #include "rgw_rados.h" -#include "cls/user/cls_user_client.h" +#include "driver/rados/buckets.h" #define dout_subsys ceph_subsys_rgw @@ -624,68 +624,15 @@ int RGWSI_User_RADOS::get_user_info_by_access_key(RGWSI_MetaBackend::Context *ct info, objv_tracker, pmtime, y, dpp); } -int RGWSI_User_RADOS::cls_user_update_buckets(const DoutPrefixProvider *dpp, rgw_raw_obj& obj, list& entries, bool add, optional_yield y) -{ - rgw_rados_ref rados_obj; - int r = rgw_get_rados_ref(dpp, rados, obj, &rados_obj); - if (r < 0) { - return r; - } - - librados::ObjectWriteOperation op; - cls_user_set_buckets(op, entries, add); - r = rados_obj.operate(dpp, &op, y); - if (r < 0) { - return r; - } - - return 0; -} - -int RGWSI_User_RADOS::cls_user_add_bucket(const DoutPrefixProvider *dpp, rgw_raw_obj& obj, const cls_user_bucket_entry& entry, optional_yield y) -{ - list l; - l.push_back(entry); - - return cls_user_update_buckets(dpp, obj, l, true, y); -} - -int RGWSI_User_RADOS::cls_user_remove_bucket(const DoutPrefixProvider *dpp, rgw_raw_obj& obj, const cls_user_bucket& bucket, optional_yield y) -{ - rgw_rados_ref rados_obj; - int r = rgw_get_rados_ref(dpp, rados, obj, &rados_obj); - if (r < 0) { - return r; - } - - librados::ObjectWriteOperation op; - ::cls_user_remove_bucket(op, bucket); - r = rados_obj.operate(dpp, &op, y); - if (r < 0) - return r; - - return 0; -} - int RGWSI_User_RADOS::add_bucket(const DoutPrefixProvider *dpp, const rgw_user& user, const rgw_bucket& bucket, ceph::real_time creation_time, optional_yield y) { - int ret; - - cls_user_bucket_entry new_bucket; - - bucket.convert(&new_bucket.bucket); - new_bucket.size = 0; - if (real_clock::is_zero(creation_time)) - new_bucket.creation_time = real_clock::now(); - else - new_bucket.creation_time = creation_time; - rgw_raw_obj obj = get_buckets_obj(user); - ret = cls_user_add_bucket(dpp, obj, new_bucket, y); + int ret = rgwrados::buckets::add(dpp, y, *rados, obj, + bucket, creation_time); if (ret < 0) { ldpp_dout(dpp, 0) << "ERROR: error adding bucket to user: ret=" << ret << dendl; return ret; @@ -697,13 +644,11 @@ int RGWSI_User_RADOS::add_bucket(const DoutPrefixProvider *dpp, int RGWSI_User_RADOS::remove_bucket(const DoutPrefixProvider *dpp, const rgw_user& user, - const rgw_bucket& _bucket, + const rgw_bucket& bucket, optional_yield y) { - cls_user_bucket bucket; - bucket.name = _bucket.name; rgw_raw_obj obj = get_buckets_obj(user); - int ret = cls_user_remove_bucket(dpp, obj, bucket, y); + int ret = rgwrados::buckets::remove(dpp, y, *rados, obj, bucket); if (ret < 0) { ldpp_dout(dpp, 0) << "ERROR: error removing bucket from user: ret=" << ret << dendl; } @@ -711,101 +656,23 @@ int RGWSI_User_RADOS::remove_bucket(const DoutPrefixProvider *dpp, return 0; } -int RGWSI_User_RADOS::cls_user_flush_bucket_stats(const DoutPrefixProvider *dpp, - rgw_raw_obj& user_obj, - const RGWBucketEnt& ent, optional_yield y) -{ - cls_user_bucket_entry entry; - ent.convert(&entry); - - list entries; - entries.push_back(entry); - - int r = cls_user_update_buckets(dpp, user_obj, entries, false, y); - if (r < 0) { - ldpp_dout(dpp, 20) << "cls_user_update_buckets() returned " << r << dendl; - return r; - } - - return 0; -} - -int RGWSI_User_RADOS::cls_user_list_buckets(const DoutPrefixProvider *dpp, - rgw_raw_obj& obj, - const string& in_marker, - const string& end_marker, - const int max_entries, - list& entries, - string * const out_marker, - bool * const truncated, - optional_yield y) -{ - rgw_rados_ref rados_obj; - int r = rgw_get_rados_ref(dpp, rados, obj, &rados_obj); - if (r < 0) { - return r; - } - - librados::ObjectReadOperation op; - int rc; - - cls_user_bucket_list(op, in_marker, end_marker, max_entries, entries, out_marker, truncated, &rc); - bufferlist ibl; - r = rados_obj.operate(dpp, &op, &ibl, y); - if (r < 0) - return r; - if (rc < 0) - return rc; - - return 0; -} - int RGWSI_User_RADOS::list_buckets(const DoutPrefixProvider *dpp, const rgw_user& user, const string& marker, const string& end_marker, uint64_t max, - RGWUserBuckets *buckets, - bool *is_truncated, optional_yield y) + rgw::sal::BucketList& listing, + optional_yield y) { - int ret; - - buckets->clear(); - if (user.id == RGW_USER_ANON_ID) { + if (user.id == RGW_USER_ANON_ID) { ldpp_dout(dpp, 20) << "RGWSI_User_RADOS::list_buckets(): anonymous user" << dendl; - *is_truncated = false; + listing.next_marker.clear(); return 0; } - rgw_raw_obj obj = get_buckets_obj(user); - - bool truncated = false; - string m = marker; - - uint64_t total = 0; - do { - std::list entries; - ret = cls_user_list_buckets(dpp, obj, m, end_marker, max - total, entries, &m, &truncated, y); - if (ret == -ENOENT) { - ret = 0; - } - - if (ret < 0) { - return ret; - } - - for (auto& entry : entries) { - buckets->add(RGWBucketEnt(user, std::move(entry))); - total++; - } - - } while (truncated && total < max); - - if (is_truncated) { - *is_truncated = truncated; - } - - return 0; + rgw_raw_obj obj = get_buckets_obj(user); + return rgwrados::buckets::list(dpp, y, *rados, obj, user.tenant, + marker, end_marker, max, listing); } int RGWSI_User_RADOS::flush_bucket_stats(const DoutPrefixProvider *dpp, @@ -814,102 +681,22 @@ int RGWSI_User_RADOS::flush_bucket_stats(const DoutPrefixProvider *dpp, optional_yield y) { rgw_raw_obj obj = get_buckets_obj(user); - - return cls_user_flush_bucket_stats(dpp, obj, ent, y); + return rgwrados::buckets::write_stats(dpp, y, *rados, obj, ent); } int RGWSI_User_RADOS::reset_bucket_stats(const DoutPrefixProvider *dpp, const rgw_user& user, optional_yield y) -{ - return cls_user_reset_stats(dpp, user, y); -} - -int RGWSI_User_RADOS::cls_user_reset_stats(const DoutPrefixProvider *dpp, const rgw_user& user, optional_yield y) { rgw_raw_obj obj = get_buckets_obj(user); - rgw_rados_ref rados_obj; - int r = rgw_get_rados_ref(dpp, rados, obj, &rados_obj); - if (r < 0) { - return r; - } - - int rval; - - cls_user_reset_stats2_op call; - cls_user_reset_stats2_ret ret; - - do { - buffer::list in, out; - librados::ObjectWriteOperation op; - - call.time = real_clock::now(); - ret.update_call(call); - - encode(call, in); - op.exec("user", "reset_user_stats2", in, &out, &rval); - r = rados_obj.operate(dpp, &op, y, librados::OPERATION_RETURNVEC); - if (r < 0) { - return r; - } - try { - auto bliter = out.cbegin(); - decode(ret, bliter); - } catch (ceph::buffer::error& err) { - return -EINVAL; - } - } while (ret.truncated); - - return rval; + return rgwrados::buckets::reset_stats(dpp, y, *rados, obj); } int RGWSI_User_RADOS::complete_flush_stats(const DoutPrefixProvider *dpp, const rgw_user& user, optional_yield y) { rgw_raw_obj obj = get_buckets_obj(user); - rgw_rados_ref rados_obj; - int r = rgw_get_rados_ref(dpp, rados, obj, &rados_obj); - if (r < 0) { - return r; - } - - librados::ObjectWriteOperation op; - ::cls_user_complete_stats_sync(op); - return rados_obj.operate(dpp, &op, y); -} - -int RGWSI_User_RADOS::cls_user_get_header(const DoutPrefixProvider *dpp, - const rgw_user& user, cls_user_header *header, - optional_yield y) -{ - rgw_raw_obj obj = get_buckets_obj(user); - rgw_rados_ref rados_obj; - int r = rgw_get_rados_ref(dpp, rados, obj, &rados_obj); - if (r < 0) { - return r; - } - int rc; - bufferlist ibl; - librados::ObjectReadOperation op; - ::cls_user_get_header(op, header, &rc); - return rados_obj.operate(dpp, &op, &ibl, y); -} - -int RGWSI_User_RADOS::cls_user_get_header_async(const DoutPrefixProvider *dpp, const string& user_str, RGWGetUserHeader_CB *cb) -{ - rgw_raw_obj obj = get_buckets_obj(rgw_user(user_str)); - rgw_rados_ref ref; - int r = rgw_get_rados_ref(dpp, rados, obj, &ref); - if (r < 0) { - return r; - } - - r = ::cls_user_get_header_async(ref.ioctx, ref.obj.oid, cb); - if (r < 0) { - return r; - } - - return 0; + return rgwrados::buckets::complete_flush_stats(dpp, y, *rados, obj); } int RGWSI_User_RADOS::read_stats(const DoutPrefixProvider *dpp, @@ -919,71 +706,17 @@ int RGWSI_User_RADOS::read_stats(const DoutPrefixProvider *dpp, ceph::real_time *last_stats_update, optional_yield y) { - string user_str = user.to_str(); - - RGWUserInfo info; - real_time mtime; - int ret = read_user_info(ctx, user, &info, nullptr, &mtime, nullptr, nullptr, y, dpp); - if (ret < 0) - { - return ret; - } - - cls_user_header header; - int r = cls_user_get_header(dpp, rgw_user(user_str), &header, y); - if (r < 0 && r != -ENOENT) - return r; - - const cls_user_stats& hs = header.stats; - - stats->size = hs.total_bytes; - stats->size_rounded = hs.total_bytes_rounded; - stats->num_objects = hs.total_entries; - - if (last_stats_sync) { - *last_stats_sync = header.last_stats_sync; - } - - if (last_stats_update) { - *last_stats_update = header.last_stats_update; - } - - return 0; + rgw_raw_obj obj = get_buckets_obj(user); + return rgwrados::buckets::read_stats( + dpp, y, *rados, obj, *stats, + last_stats_sync, last_stats_update); } -class RGWGetUserStatsContext : public RGWGetUserHeader_CB { - boost::intrusive_ptr cb; - -public: - explicit RGWGetUserStatsContext(boost::intrusive_ptr cb) - : cb(std::move(cb)) {} - - void handle_response(int r, cls_user_header& header) override { - const cls_user_stats& hs = header.stats; - RGWStorageStats stats; - - stats.size = hs.total_bytes; - stats.size_rounded = hs.total_bytes_rounded; - stats.num_objects = hs.total_entries; - - cb->handle_response(r, stats); - cb.reset(); - } -}; - int RGWSI_User_RADOS::read_stats_async(const DoutPrefixProvider *dpp, const rgw_user& user, - boost::intrusive_ptr _cb) + boost::intrusive_ptr cb) { - string user_str = user.to_str(); - - RGWGetUserStatsContext *cb = new RGWGetUserStatsContext(std::move(_cb)); - int r = cls_user_get_header_async(dpp, user_str, cb); - if (r < 0) { - delete cb; - return r; - } - - return 0; + rgw_raw_obj obj = get_buckets_obj(user); + return rgwrados::buckets::read_stats_async(dpp, *rados, obj, std::move(cb)); } diff --git a/src/rgw/services/svc_user_rados.h b/src/rgw/services/svc_user_rados.h index 6912327f0b1..1ac0212fa9a 100644 --- a/src/rgw/services/svc_user_rados.h +++ b/src/rgw/services/svc_user_rados.h @@ -71,28 +71,6 @@ class RGWSI_User_RADOS : public RGWSI_User int remove_email_index(const DoutPrefixProvider *dpp, const std::string& email, optional_yield y); int remove_swift_name_index(const DoutPrefixProvider *dpp, const std::string& swift_name, optional_yield y); - /* admin management */ - int cls_user_update_buckets(const DoutPrefixProvider *dpp, rgw_raw_obj& obj, std::list& entries, bool add, optional_yield y); - int cls_user_add_bucket(const DoutPrefixProvider *dpp, rgw_raw_obj& obj, const cls_user_bucket_entry& entry, optional_yield y); - int cls_user_remove_bucket(const DoutPrefixProvider *dpp, rgw_raw_obj& obj, const cls_user_bucket& bucket, optional_yield y); - - /* quota stats */ - int cls_user_flush_bucket_stats(const DoutPrefixProvider *dpp, rgw_raw_obj& user_obj, - const RGWBucketEnt& ent, optional_yield y); - int cls_user_list_buckets(const DoutPrefixProvider *dpp, - rgw_raw_obj& obj, - const std::string& in_marker, - const std::string& end_marker, - const int max_entries, - std::list& entries, - std::string * const out_marker, - bool * const truncated, - optional_yield y); - - int cls_user_reset_stats(const DoutPrefixProvider *dpp, const rgw_user& user, optional_yield y); - int cls_user_get_header(const DoutPrefixProvider *dpp, const rgw_user& user, cls_user_header *header, optional_yield y); - int cls_user_get_header_async(const DoutPrefixProvider *dpp, const std::string& user, RGWGetUserHeader_CB *cb); - int do_start(optional_yield, const DoutPrefixProvider *dpp) override; public: librados::Rados* rados{nullptr}; @@ -183,8 +161,7 @@ public: const std::string& marker, const std::string& end_marker, uint64_t max, - RGWUserBuckets *buckets, - bool *is_truncated, + rgw::sal::BucketList& listing, optional_yield y) override; /* quota related */