]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/rados: add rgwrados::buckets namespace abstraction for cls_user
authorCasey Bodley <cbodley@redhat.com>
Fri, 1 Dec 2023 03:06:27 +0000 (22:06 -0500)
committerCasey Bodley <cbodley@redhat.com>
Wed, 10 Apr 2024 16:53:05 +0000 (12:53 -0400)
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 <cbodley@redhat.com>
15 files changed:
src/rgw/CMakeLists.txt
src/rgw/driver/rados/buckets.cc [new file with mode: 0644]
src/rgw/driver/rados/buckets.h [new file with mode: 0644]
src/rgw/driver/rados/cls_fifo_legacy.h
src/rgw/driver/rados/rgw_bucket.cc
src/rgw/driver/rados/rgw_bucket.h
src/rgw/driver/rados/rgw_sal_rados.cc
src/rgw/driver/rados/rgw_user.cc
src/rgw/driver/rados/rgw_user.h
src/rgw/services/svc_bucket.h
src/rgw/services/svc_bucket_sobj.cc
src/rgw/services/svc_bucket_sobj.h
src/rgw/services/svc_user.h
src/rgw/services/svc_user_rados.cc
src/rgw/services/svc_user_rados.h

index ef4d24b0c3bc741a309acce84f5080e37fa7233d..1ddddb00c238530891b0704c0f0e1631015cea52 100644 (file)
@@ -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 (file)
index 0000000..8c35028
--- /dev/null
@@ -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<cls_user_bucket_entry> 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<cls_user_bucket_entry> 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<rgw::sal::ReadStatsCB> cb;
+ public:
+  explicit AsyncHeaderCB(boost::intrusive_ptr<rgw::sal::ReadStatsCB> 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<rgw::sal::ReadStatsCB> 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<AsyncHeaderCB>(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 (file)
index 0000000..3ac29f8
--- /dev/null
@@ -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 <cstdint>
+#include <string>
+#include <boost/intrusive_ptr.hpp>
+#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<rgw::sal::ReadStatsCB> 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
index c345c728512aaf9282853350ae39c352ba0c1fec..ed23129eb304520cc6a2e6d79ab7b81174ffe37c 100644 (file)
@@ -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;
index ce869f399d6e2a656468b63db105ccd8a04cef0b..d5304fec4993bd2bf87a698d36e241a55eca44cb 100644 (file)
@@ -3233,11 +3233,11 @@ int RGWBucketCtl::read_bucket_stats(const rgw_bucket& bucket,
   });
 }
 
-int RGWBucketCtl::read_buckets_stats(map<string, RGWBucketEnt>& m,
+int RGWBucketCtl::read_buckets_stats(std::vector<RGWBucketEnt>& 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);
   });
 }
 
index 5af10b524de6a6d0595abb036cb4283949bf531a..a1a59dc321e51da77faf7292145e4733996a4ad0 100644 (file)
@@ -692,7 +692,7 @@ public:
                     const DoutPrefixProvider *dpp,
                     bool update_entrypoint = true);
 
-  int read_buckets_stats(std::map<std::string, RGWBucketEnt>& m,
+  int read_buckets_stats(std::vector<RGWBucketEnt>& buckets,
                          optional_yield y,
                          const DoutPrefixProvider *dpp);
 
index b6aab98aae2e37264517f4d2508e97a510cc92a8..8b6d4992c3df2ea05611ba812d231586dbc42119 100644 (file)
@@ -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,
index a6881502210152ffdaa87c2f3a8724a10851d2a6..712e6bdffd644cbc98d105523314df964547afe0 100644 (file)
@@ -2793,8 +2793,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)
 {
@@ -2803,13 +2802,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<string, RGWBucketEnt>& 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;
index 373b672e6eb47f26478045308ae1c29b10568c03..7947b3094bd853e8a8b8ddbe8b2ac09178e52f13 100644 (file)
@@ -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);
 
index caf6e029452b08769fb2c0096c3025d9302bd04b..5963c54171fbca683806154c086aa8560bea9acb 100644 (file)
@@ -104,7 +104,7 @@ public:
                         const DoutPrefixProvider *dpp) = 0;
 
   virtual int read_buckets_stats(RGWSI_Bucket_X_Ctx& ctx,
-                                 std::map<std::string, RGWBucketEnt>& m,
+                                 std::vector<RGWBucketEnt>& buckets,
                                  optional_yield y,
                                  const DoutPrefixProvider *dpp) = 0;
 };
index 9927cc2d3a979a24c6f9370350272b488e752bcd..41e7b02e17596610351157bb69b71d1aec3b8d5b 100644 (file)
@@ -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<string, RGWBucketEnt>& m,
+                                          std::vector<RGWBucketEnt>& buckets,
                                           optional_yield y,
                                           const DoutPrefixProvider *dpp)
 {
-  map<string, RGWBucketEnt>::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();
 }
index 7a466ca37dd8fd39effc43ba23108e243b268328..9b95ca18fa4bd38d347d8c59b0870ad423b2a532 100644 (file)
@@ -173,7 +173,7 @@ public:
                         const DoutPrefixProvider *dpp) override;
 
   int read_buckets_stats(RGWSI_Bucket_X_Ctx& ctx,
-                         std::map<std::string, RGWBucketEnt>& m,
+                         std::vector<RGWBucketEnt>& buckets,
                          optional_yield y,
                          const DoutPrefixProvider *dpp) override;
 };
index f53ec49f2595a421219d5c46eedfb8adf4a2bd6b..cf46df6e3d11bfbcd2822be0ac1a6f1c648d42d7 100644 (file)
@@ -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, 
index 9d06d5f13af9960a31ee192fa08975bd666bd4f4..b8fdd3212fd80b5e77de48911e96cfca623e5472 100644 (file)
@@ -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<cls_user_bucket_entry>& 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<cls_user_bucket_entry> 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<cls_user_bucket_entry> 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<cls_user_bucket_entry>& 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<cls_user_bucket_entry> 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<rgw::sal::ReadStatsCB> cb;
-
-public:
-  explicit RGWGetUserStatsContext(boost::intrusive_ptr<rgw::sal::ReadStatsCB> 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<rgw::sal::ReadStatsCB> _cb)
+                                       boost::intrusive_ptr<rgw::sal::ReadStatsCB> 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));
 }
 
index 6912327f0b1b4a9a5b20f322ffd8d1c04fe0b0c4..1ac0212fa9aa48b218c455d0ca10e926073a56e4 100644 (file)
@@ -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<cls_user_bucket_entry>& 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<cls_user_bucket_entry>& 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 */