]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
RGW - Zipper - Filter base implementation
authorDaniel Gryniewicz <dang@redhat.com>
Fri, 1 Jul 2022 15:54:06 +0000 (11:54 -0400)
committerDaniel Gryniewicz <dang@redhat.com>
Wed, 27 Jul 2022 17:32:53 +0000 (13:32 -0400)
This is the base implementation for filters.  It passes each call on
each object through to the next layer down.  This allows filters to
subclass these, and only implement the bits they care about, leaving the
rest as pass-through.

Signed-off-by: Daniel Gryniewicz <dang@redhat.com>
src/rgw/CMakeLists.txt
src/rgw/rgw_sal.h
src/rgw/rgw_sal_dbstore.h
src/rgw/rgw_sal_filter.cc [new file with mode: 0644]
src/rgw/rgw_sal_filter.h
src/rgw/rgw_sal_motr.h
src/rgw/rgw_sal_rados.cc
src/rgw/rgw_sal_rados.h

index a127b54a622395ea1b8b46a721d4de7c61853a63..91169e2ff3dc09f3b0e271a8e431c07bd4adc1ff 100644 (file)
@@ -133,6 +133,7 @@ set(librgw_common_srcs
   rgw_s3select.cc
   rgw_role.cc
   rgw_sal.cc
+  rgw_sal_filter.cc
   rgw_sal_rados.cc
   rgw_string.cc
   rgw_tag.cc
index 09a15d3607a7abd2143372616d3ffb4ce4fa4d55..1b9869e2966130a5917259cd1a0d06cc2244c641 100644 (file)
@@ -1464,6 +1464,8 @@ public:
   virtual int get_zone_count() const = 0;
   /** Get the placement tier associated with the rule */
   virtual int get_placement_tier(const rgw_placement_rule& rule, std::unique_ptr<PlacementTier>* tier) = 0;
+  /** Clone a copy of this zonegroup. */
+  virtual std::unique_ptr<ZoneGroup> clone() = 0;
 };
 
 /**
@@ -1476,6 +1478,8 @@ class Zone {
   public:
     virtual ~Zone() = default;
 
+    /** Clone a copy of this zone. */
+    virtual std::unique_ptr<Zone> clone() = 0;
     /** Get info about the zonegroup containing this zone */
     virtual ZoneGroup& get_zonegroup() = 0;
     /** Get info about a zonegroup by ID */
index 88f9ef750a0f88651c2d3a34927229be2dce91f9..038d188dc9fbc6579f9f39ff59967c66919ddb68 100644 (file)
@@ -289,6 +289,10 @@ protected:
                                   std::unique_ptr<PlacementTier>* tier) {
       return -1;
     }
+    virtual std::unique_ptr<ZoneGroup> clone() override {
+      std::unique_ptr<RGWZoneGroup>zg = std::make_unique<RGWZoneGroup>(*group.get());
+      return std::make_unique<DBZoneGroup>(store, std::move(zg));
+    }
   };
 
   class DBZone : public StoreZone {
@@ -325,6 +329,9 @@ protected:
        delete current_period;
       }
 
+      virtual std::unique_ptr<Zone> clone() override {
+       return std::make_unique<DBZone>(store);
+      }
       virtual ZoneGroup& get_zonegroup() override;
       virtual int get_zonegroup(const std::string& id, std::unique_ptr<ZoneGroup>* zonegroup) override;
       const RGWZoneParams& get_rgw_params();
diff --git a/src/rgw/rgw_sal_filter.cc b/src/rgw/rgw_sal_filter.cc
new file mode 100644 (file)
index 0000000..711a0f6
--- /dev/null
@@ -0,0 +1,1324 @@
+// -*- 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 (C) 2022 Red Hat, Inc.
+ *
+ * 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 "rgw_sal_filter.h"
+
+namespace rgw { namespace sal {
+
+/* These are helpers for getting 'next' out of an object, handling nullptr */
+static inline PlacementTier* nextPlacementTier(PlacementTier* t)
+{
+  if (!t)
+    return nullptr;
+
+  return dynamic_cast<FilterPlacementTier*>(t)->get_next();
+}
+
+static inline User* nextUser(User* t)
+{
+  if (!t)
+    return nullptr;
+
+  return dynamic_cast<FilterUser*>(t)->get_next();
+}
+
+static inline Bucket* nextBucket(Bucket* t)
+{
+  if (!t)
+    return nullptr;
+
+  return dynamic_cast<FilterBucket*>(t)->get_next();
+}
+
+static inline Object* nextObject(Object* t)
+{
+  if (!t)
+    return nullptr;
+
+  return dynamic_cast<FilterObject*>(t)->get_next();
+}
+
+int FilterZoneGroup::get_placement_tier(const rgw_placement_rule& rule,
+                                       std::unique_ptr<PlacementTier>* tier)
+{
+  std::unique_ptr<PlacementTier> nt;
+  int ret;
+
+  ret = next->get_placement_tier(rule, &nt);
+  if (ret != 0)
+    return ret;
+
+  PlacementTier* t = new FilterPlacementTier(std::move(nt));
+  tier->reset(t);
+  return 0;
+}
+
+int FilterZone::get_zonegroup(const std::string& id,
+                             std::unique_ptr<ZoneGroup>* zonegroup)
+{
+  std::unique_ptr<ZoneGroup> ngz;
+  int ret;
+
+  ret = next->get_zonegroup(id, &ngz);
+  if (ret != 0)
+    return ret;
+
+  ZoneGroup* zg = new FilterZoneGroup(std::move(ngz));
+  zonegroup->reset(zg);
+  return 0;
+}
+
+int FilterStore::initialize(CephContext *cct, const DoutPrefixProvider *dpp)
+{
+  zone = std::make_unique<FilterZone>(next->get_zone()->clone());
+
+  return 0;
+}
+
+const std::string FilterStore::get_name() const
+{
+  std::string name = "filter<" + next->get_name() + ">";
+  return name;
+}
+
+std::string FilterStore::get_cluster_id(const DoutPrefixProvider* dpp,  optional_yield y)
+{
+  return next->get_cluster_id(dpp, y);
+}
+
+std::unique_ptr<User> FilterStore::get_user(const rgw_user &u)
+{
+  std::unique_ptr<User> user = next->get_user(u);
+  return std::make_unique<FilterUser>(std::move(user));
+}
+
+int FilterStore::get_user_by_access_key(const DoutPrefixProvider* dpp, const std::string& key, optional_yield y, std::unique_ptr<User>* user)
+{
+  std::unique_ptr<User> nu;
+  int ret;
+
+  ret = next->get_user_by_access_key(dpp, key, y, &nu);
+  if (ret != 0)
+    return ret;
+
+  User* u = new FilterUser(std::move(nu));
+  user->reset(u);
+  return 0;
+}
+
+int FilterStore::get_user_by_email(const DoutPrefixProvider* dpp, const std::string& email, optional_yield y, std::unique_ptr<User>* user)
+{
+  std::unique_ptr<User> nu;
+  int ret;
+
+  ret = next->get_user_by_email(dpp, email, y, &nu);
+  if (ret != 0)
+    return ret;
+
+  User* u = new FilterUser(std::move(nu));
+  user->reset(u);
+  return 0;
+}
+
+int FilterStore::get_user_by_swift(const DoutPrefixProvider* dpp, const std::string& user_str, optional_yield y, std::unique_ptr<User>* user)
+{
+  std::unique_ptr<User> nu;
+  int ret;
+
+  ret = next->get_user_by_swift(dpp, user_str, y, &nu);
+  if (ret != 0)
+    return ret;
+
+  User* u = new FilterUser(std::move(nu));
+  user->reset(u);
+  return 0;
+}
+
+std::unique_ptr<Object> FilterStore::get_object(const rgw_obj_key& k)
+{
+  std::unique_ptr<Object> o = next->get_object(k);
+  return std::make_unique<FilterObject>(std::move(o));
+}
+
+int FilterStore::get_bucket(const DoutPrefixProvider* dpp, User* u, const rgw_bucket& b, std::unique_ptr<Bucket>* bucket, optional_yield y)
+{
+  std::unique_ptr<Bucket> nb;
+  int ret;
+  User* nu = nextUser(u);
+
+  ret = next->get_bucket(dpp, nu, b, &nb, y);
+  if (ret != 0)
+    return ret;
+
+  Bucket* fb = new FilterBucket(std::move(nb), u);
+  bucket->reset(fb);
+  return 0;
+}
+
+int FilterStore::get_bucket(User* u, const RGWBucketInfo& i, std::unique_ptr<Bucket>* bucket)
+{
+  std::unique_ptr<Bucket> nb;
+  int ret;
+  User* nu = nextUser(u);
+
+  ret = next->get_bucket(nu, i, &nb);
+  if (ret != 0)
+    return ret;
+
+  Bucket* fb = new FilterBucket(std::move(nb), u);
+  bucket->reset(fb);
+  return 0;
+}
+
+int FilterStore::get_bucket(const DoutPrefixProvider* dpp, User* u, const std::string& tenant, const std::string& name, std::unique_ptr<Bucket>* bucket, optional_yield y)
+{
+  std::unique_ptr<Bucket> nb;
+  int ret;
+  User* nu = nextUser(u);
+
+  ret = next->get_bucket(dpp, nu, tenant, name, &nb, y);
+  if (ret != 0)
+    return ret;
+
+  Bucket* fb = new FilterBucket(std::move(nb), u);
+  bucket->reset(fb);
+  return 0;
+}
+
+bool FilterStore::is_meta_master()
+{
+  return next->is_meta_master();
+}
+
+int FilterStore::forward_request_to_master(const DoutPrefixProvider *dpp,
+                                          User* user, obj_version* objv,
+                                          bufferlist& in_data,
+                                          JSONParser* jp, req_info& info,
+                                          optional_yield y)
+{
+  return next->forward_request_to_master(dpp, user, objv, in_data, jp, info, y);
+}
+
+int FilterStore::forward_iam_request_to_master(const DoutPrefixProvider *dpp,
+                                              const RGWAccessKey& key,
+                                              obj_version* objv,
+                                              bufferlist& in_data,
+                                              RGWXMLDecoder::XMLParser* parser,
+                                              req_info& info,
+                                              optional_yield y)
+{
+  return next->forward_iam_request_to_master(dpp, key, objv, in_data, parser, info, y);
+}
+
+std::string FilterStore::zone_unique_id(uint64_t unique_num)
+{
+  return next->zone_unique_id(unique_num);
+}
+
+std::string FilterStore::zone_unique_trans_id(uint64_t unique_num)
+{
+  return next->zone_unique_trans_id(unique_num);
+}
+
+int FilterStore::cluster_stat(RGWClusterStat& stats)
+{
+  return next->cluster_stat(stats);
+}
+
+std::unique_ptr<Lifecycle> FilterStore::get_lifecycle(void)
+{
+  std::unique_ptr<Lifecycle> lc = next->get_lifecycle();
+  return std::make_unique<FilterLifecycle>(std::move(lc));
+}
+
+std::unique_ptr<Completions> FilterStore::get_completions(void)
+{
+  std::unique_ptr<Completions> c = next->get_completions();
+  return std::make_unique<FilterCompletions>(std::move(c));
+}
+
+std::unique_ptr<Notification> FilterStore::get_notification(rgw::sal::Object* obj,
+                               rgw::sal::Object* src_obj, req_state* s,
+                               rgw::notify::EventType event_type,
+                               const std::string* object_name)
+{
+  std::unique_ptr<Notification> n = next->get_notification(nextObject(obj),
+                                                          nextObject(src_obj),
+                                                          s, event_type,
+                                                          object_name);
+  return std::make_unique<FilterNotification>(std::move(n));
+}
+
+std::unique_ptr<Notification> FilterStore::get_notification(const DoutPrefixProvider* dpp,
+                               rgw::sal::Object* obj, rgw::sal::Object* src_obj,
+                               rgw::notify::EventType event_type,
+                               rgw::sal::Bucket* _bucket, std::string& _user_id,
+                               std::string& _user_tenant, std::string& _req_id,
+                               optional_yield y)
+{
+  std::unique_ptr<Notification> n = next->get_notification(dpp, nextObject(obj),
+                                                          nextObject(src_obj),
+                                                          event_type,
+                                                          nextBucket(_bucket),
+                                                          _user_id,
+                                                          _user_tenant,
+                                                          _req_id, y);
+  return std::make_unique<FilterNotification>(std::move(n));
+}
+
+RGWLC* FilterStore::get_rgwlc()
+{
+  return next->get_rgwlc();
+}
+
+RGWCoroutinesManagerRegistry* FilterStore::get_cr_registry()
+{
+  return next->get_cr_registry();
+}
+
+int FilterStore::log_usage(const DoutPrefixProvider *dpp, std::map<rgw_user_bucket, RGWUsageBatch>& usage_info)
+{
+    return next->log_usage(dpp, usage_info);
+}
+
+int FilterStore::log_op(const DoutPrefixProvider *dpp, std::string& oid, bufferlist& bl)
+{
+    return next->log_op(dpp, oid, bl);
+}
+
+int FilterStore::register_to_service_map(const DoutPrefixProvider *dpp,
+                                        const std::string& daemon_type,
+                                        const std::map<std::string, std::string>& meta)
+{
+  return next->register_to_service_map(dpp, daemon_type, meta);
+}
+
+void FilterStore::get_quota(RGWQuota& quota)
+{
+  return next->get_quota(quota);
+}
+
+void FilterStore::get_ratelimit(RGWRateLimitInfo& bucket_ratelimit,
+                               RGWRateLimitInfo& user_ratelimit,
+                               RGWRateLimitInfo& anon_ratelimit)
+{
+  return next->get_ratelimit(bucket_ratelimit, user_ratelimit, anon_ratelimit);
+}
+
+int FilterStore::set_buckets_enabled(const DoutPrefixProvider* dpp,
+                                    std::vector<rgw_bucket>& buckets, bool enabled)
+{
+    return next->set_buckets_enabled(dpp, buckets, enabled);
+}
+
+uint64_t FilterStore::get_new_req_id()
+{
+    return next->get_new_req_id();
+}
+
+int FilterStore::get_sync_policy_handler(const DoutPrefixProvider* dpp,
+                                        std::optional<rgw_zone_id> zone,
+                                        std::optional<rgw_bucket> bucket,
+                                        RGWBucketSyncPolicyHandlerRef* phandler,
+                                        optional_yield y)
+{
+  return next->get_sync_policy_handler(dpp, zone, bucket, phandler, y);
+}
+
+RGWDataSyncStatusManager* FilterStore::get_data_sync_manager(const rgw_zone_id& source_zone)
+{
+  return next->get_data_sync_manager(source_zone);
+}
+
+void FilterStore::wakeup_meta_sync_shards(std::set<int>& shard_ids)
+{
+  return next->wakeup_meta_sync_shards(shard_ids);
+}
+
+void FilterStore::wakeup_data_sync_shards(const DoutPrefixProvider *dpp,
+                                         const rgw_zone_id& source_zone,
+                                         boost::container::flat_map<int, boost::container::flat_set<rgw_data_notify_entry>>& shard_ids)
+{
+  return next->wakeup_data_sync_shards(dpp, source_zone, shard_ids);
+}
+
+int FilterStore::clear_usage(const DoutPrefixProvider *dpp)
+{
+  return next->clear_usage(dpp);
+}
+
+int FilterStore::read_all_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch,
+                               uint64_t end_epoch, uint32_t max_entries,
+                               bool* is_truncated, RGWUsageIter& usage_iter,
+                               std::map<rgw_user_bucket, rgw_usage_log_entry>& usage)
+{
+  return next->read_all_usage(dpp, start_epoch, end_epoch, max_entries,
+                             is_truncated, usage_iter, usage);
+}
+
+int FilterStore::trim_all_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch,
+                               uint64_t end_epoch)
+{
+  return next->trim_all_usage(dpp, start_epoch, end_epoch);
+}
+
+int FilterStore::get_config_key_val(std::string name, bufferlist* bl)
+{
+  return next->get_config_key_val(name, bl);
+}
+
+int FilterStore::meta_list_keys_init(const DoutPrefixProvider *dpp,
+                                    const std::string& section,
+                                    const std::string& marker, void** phandle)
+{
+  return next->meta_list_keys_init(dpp, section, marker, phandle);
+}
+
+int FilterStore::meta_list_keys_next(const DoutPrefixProvider *dpp, void* handle,
+                                    int max, std::list<std::string>& keys,
+                                    bool* truncated)
+{
+  return next->meta_list_keys_next(dpp, handle, max, keys, truncated);
+}
+
+void FilterStore::meta_list_keys_complete(void* handle)
+{
+  next->meta_list_keys_complete(handle);
+}
+
+std::string FilterStore::meta_get_marker(void* handle)
+{
+  return next->meta_get_marker(handle);
+}
+
+int FilterStore::meta_remove(const DoutPrefixProvider* dpp, std::string& metadata_key,
+                            optional_yield y)
+{
+  return next->meta_remove(dpp, metadata_key, y);
+}
+
+const RGWSyncModuleInstanceRef& FilterStore::get_sync_module()
+{
+  return next->get_sync_module();
+}
+
+std::unique_ptr<LuaScriptManager> FilterStore::get_lua_script_manager()
+{
+  std::unique_ptr<LuaScriptManager> nm = next->get_lua_script_manager();
+
+  return std::make_unique<FilterLuaScriptManager>(std::move(nm));
+}
+
+std::unique_ptr<RGWRole> FilterStore::get_role(std::string name,
+                                             std::string tenant,
+                                             std::string path,
+                                             std::string trust_policy,
+                                             std::string max_session_duration_str,
+                std::multimap<std::string,std::string> tags)
+{
+  return next->get_role(name, tenant, path, trust_policy, max_session_duration_str, tags);
+}
+
+std::unique_ptr<RGWRole> FilterStore::get_role(std::string id)
+{
+  return next->get_role(id);
+}
+
+std::unique_ptr<RGWRole> FilterStore::get_role(const RGWRoleInfo& info)
+{
+  return next->get_role(info);
+}
+
+int FilterStore::get_roles(const DoutPrefixProvider *dpp,
+                          optional_yield y,
+                          const std::string& path_prefix,
+                          const std::string& tenant,
+                          std::vector<std::unique_ptr<RGWRole>>& roles)
+{
+  return next->get_roles(dpp, y, path_prefix, tenant, roles);
+}
+
+std::unique_ptr<RGWOIDCProvider> FilterStore::get_oidc_provider()
+{
+  return next->get_oidc_provider();
+}
+
+int FilterStore::get_oidc_providers(const DoutPrefixProvider *dpp,
+                                   const std::string& tenant,
+                                   std::vector<std::unique_ptr<RGWOIDCProvider>>& providers)
+{
+  return next->get_oidc_providers(dpp, tenant, providers);
+}
+
+std::unique_ptr<Writer> FilterStore::get_append_writer(const DoutPrefixProvider *dpp,
+                                 optional_yield y,
+                                 std::unique_ptr<rgw::sal::Object> _head_obj,
+                                 const rgw_user& owner,
+                                 const rgw_placement_rule *ptail_placement_rule,
+                                 const std::string& unique_tag,
+                                 uint64_t position,
+                                 uint64_t *cur_accounted_size)
+{
+  std::unique_ptr<Object> no = nextObject(_head_obj.get())->clone();
+
+  std::unique_ptr<Writer> writer = next->get_append_writer(dpp, y, std::move(no),
+                                                          owner, ptail_placement_rule,
+                                                          unique_tag, position,
+                                                          cur_accounted_size);
+
+  return std::make_unique<FilterWriter>(std::move(writer), std::move(_head_obj));
+}
+
+std::unique_ptr<Writer> FilterStore::get_atomic_writer(const DoutPrefixProvider *dpp,
+                                 optional_yield y,
+                                 std::unique_ptr<rgw::sal::Object> _head_obj,
+                                 const rgw_user& owner,
+                                 const rgw_placement_rule *ptail_placement_rule,
+                                 uint64_t olh_epoch,
+                                 const std::string& unique_tag)
+{
+  std::unique_ptr<Object> no = nextObject(_head_obj.get())->clone();
+
+  std::unique_ptr<Writer> writer = next->get_atomic_writer(dpp, y, std::move(no),
+                                                          owner, ptail_placement_rule,
+                                                          olh_epoch, unique_tag);
+
+  return std::make_unique<FilterWriter>(std::move(writer), std::move(_head_obj));
+}
+
+const std::string& FilterStore::get_compression_type(const rgw_placement_rule& rule)
+{
+  return next->get_compression_type(rule);
+}
+
+bool FilterStore::valid_placement(const rgw_placement_rule& rule)
+{
+  return next->valid_placement(rule);
+}
+
+void FilterStore::finalize(void)
+{
+  next->finalize();
+}
+
+CephContext* FilterStore::ctx(void)
+{
+  return next->ctx();
+}
+
+const std::string& FilterStore::get_luarocks_path() const
+{
+  return next->get_luarocks_path();
+}
+
+void FilterStore::set_luarocks_path(const std::string& path)
+{
+  next->set_luarocks_path(path);
+}
+
+int FilterUser::list_buckets(const DoutPrefixProvider* dpp, const std::string& marker,
+                            const std::string& end_marker, uint64_t max,
+                            bool need_stats, BucketList &buckets, optional_yield y)
+{
+  BucketList bl;
+  int ret;
+
+  buckets.clear();
+  ret = next->list_buckets(dpp, marker, end_marker, max, need_stats, bl, y);
+  if (ret < 0)
+    return ret;
+
+  buckets.set_truncated(bl.is_truncated());
+  for (auto& ent : bl.get_buckets()) {
+    buckets.add(std::make_unique<FilterBucket>(std::move(ent.second), this));
+  }
+
+  return 0;
+}
+
+int FilterUser::create_bucket(const DoutPrefixProvider* dpp,
+                             const rgw_bucket& b,
+                             const std::string& zonegroup_id,
+                             rgw_placement_rule& placement_rule,
+                             std::string& swift_ver_location,
+                             const RGWQuotaInfo * pquota_info,
+                             const RGWAccessControlPolicy& policy,
+                             Attrs& attrs,
+                             RGWBucketInfo& info,
+                             obj_version& ep_objv,
+                             bool exclusive,
+                             bool obj_lock_enabled,
+                             bool* existed,
+                             req_info& req_info,
+                             std::unique_ptr<Bucket>* bucket_out,
+                             optional_yield y)
+{
+  std::unique_ptr<Bucket> nb;
+  int ret;
+
+  ret = next->create_bucket(dpp, b, zonegroup_id, placement_rule, swift_ver_location, pquota_info, policy, attrs, info, ep_objv, exclusive, obj_lock_enabled, existed, req_info, &nb, y);
+  if (ret < 0)
+    return ret;
+
+  Bucket* fb = new FilterBucket(std::move(nb), this);
+  bucket_out->reset(fb);
+  return 0;
+}
+
+int FilterUser::read_attrs(const DoutPrefixProvider* dpp, optional_yield y)
+{
+  return next->read_attrs(dpp, y);
+}
+
+int FilterUser::merge_and_store_attrs(const DoutPrefixProvider* dpp,
+                                     Attrs& new_attrs, optional_yield y)
+{
+  return next->merge_and_store_attrs(dpp, new_attrs, y);
+}
+
+int FilterUser::read_stats(const DoutPrefixProvider *dpp,
+                          optional_yield y, RGWStorageStats* stats,
+                          ceph::real_time* last_stats_sync,
+                          ceph::real_time* last_stats_update)
+{
+  return next->read_stats(dpp, y, stats, last_stats_sync, last_stats_update);
+}
+
+int FilterUser::read_stats_async(const DoutPrefixProvider *dpp, RGWGetUserStats_CB* cb)
+{
+  return next->read_stats_async(dpp, cb);
+}
+
+int FilterUser::complete_flush_stats(const DoutPrefixProvider *dpp, optional_yield y)
+{
+  return next->complete_flush_stats(dpp, y);
+}
+
+int FilterUser::read_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch,
+                          uint64_t end_epoch, uint32_t max_entries,
+                          bool* is_truncated, RGWUsageIter& usage_iter,
+                          std::map<rgw_user_bucket, rgw_usage_log_entry>& usage)
+{
+  return next->read_usage(dpp, start_epoch, end_epoch, max_entries,
+                         is_truncated, usage_iter, usage);
+}
+
+int FilterUser::trim_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch,
+                          uint64_t end_epoch)
+{
+  return next->trim_usage(dpp, start_epoch, end_epoch);
+}
+
+int FilterUser::load_user(const DoutPrefixProvider* dpp, optional_yield y)
+{
+  return next->load_user(dpp, y);
+}
+
+int FilterUser::store_user(const DoutPrefixProvider* dpp, optional_yield y, bool exclusive, RGWUserInfo* old_info)
+{
+  return next->store_user(dpp, y, exclusive, old_info);
+}
+
+int FilterUser::remove_user(const DoutPrefixProvider* dpp, optional_yield y)
+{
+  return next->remove_user(dpp, y);
+}
+
+std::unique_ptr<Object> FilterBucket::get_object(const rgw_obj_key& k)
+{
+  std::unique_ptr<Object> o = next->get_object(k);
+
+  return std::make_unique<FilterObject>(std::move(o), this);
+}
+
+int FilterBucket::list(const DoutPrefixProvider* dpp, ListParams& params, int max,
+                      ListResults& results, optional_yield y)
+{
+  return next->list(dpp, params, max, results, y);
+}
+
+int FilterBucket::remove_bucket(const DoutPrefixProvider* dpp,
+                               bool delete_children,
+                               bool forward_to_master,
+                               req_info* req_info,
+                               optional_yield y)
+{
+  return next->remove_bucket(dpp, delete_children, forward_to_master, req_info, y);
+}
+
+int FilterBucket::remove_bucket_bypass_gc(int concurrent_max,
+                                         bool keep_index_consistent,
+                                         optional_yield y,
+                                         const DoutPrefixProvider *dpp)
+{
+  return next->remove_bucket_bypass_gc(concurrent_max, keep_index_consistent, y, dpp);
+}
+
+int FilterBucket::set_acl(const DoutPrefixProvider* dpp,
+                         RGWAccessControlPolicy &acl, optional_yield y)
+{
+  return next->set_acl(dpp, acl, y);
+}
+
+int FilterBucket::load_bucket(const DoutPrefixProvider* dpp, optional_yield y,
+                             bool get_stats)
+{
+  return next->load_bucket(dpp, y, get_stats);
+}
+
+int FilterBucket::read_stats(const DoutPrefixProvider *dpp,
+                            const bucket_index_layout_generation& idx_layout,
+                            int shard_id, std::string* bucket_ver,
+                            std::string* master_ver,
+                            std::map<RGWObjCategory, RGWStorageStats>& stats,
+                            std::string* max_marker, bool* syncstopped)
+{
+  return next->read_stats(dpp, idx_layout, shard_id, bucket_ver, master_ver,
+                         stats, max_marker, syncstopped);
+}
+
+int FilterBucket::read_stats_async(const DoutPrefixProvider *dpp,
+                                  const bucket_index_layout_generation& idx_layout,
+                                  int shard_id, RGWGetBucketStats_CB* ctx)
+{
+  return next->read_stats_async(dpp, idx_layout, shard_id, ctx);
+}
+
+int FilterBucket::sync_user_stats(const DoutPrefixProvider *dpp, optional_yield y)
+{
+  return next->sync_user_stats(dpp, y);
+}
+
+int FilterBucket::update_container_stats(const DoutPrefixProvider* dpp)
+{
+  return next->update_container_stats(dpp);
+}
+
+int FilterBucket::check_bucket_shards(const DoutPrefixProvider* dpp)
+{
+  return next->check_bucket_shards(dpp);
+}
+
+int FilterBucket::chown(const DoutPrefixProvider* dpp, User* new_user,
+                       User* old_user, optional_yield y,
+                       const std::string* marker)
+{
+  return next->chown(dpp, new_user, old_user, y, marker);
+}
+
+int FilterBucket::put_info(const DoutPrefixProvider* dpp, bool exclusive,
+                          ceph::real_time _mtime)
+{
+  return next->put_info(dpp, exclusive, _mtime);
+}
+
+bool FilterBucket::is_owner(User* user)
+{
+  return next->is_owner(nextUser(user));
+}
+
+int FilterBucket::check_empty(const DoutPrefixProvider* dpp, optional_yield y)
+{
+  return next->check_empty(dpp, y);
+}
+
+int FilterBucket::check_quota(const DoutPrefixProvider *dpp, RGWQuota& quota,
+                             uint64_t obj_size, optional_yield y,
+                             bool check_size_only)
+{
+  return next->check_quota(dpp, quota, obj_size, y, check_size_only);
+}
+
+int FilterBucket::merge_and_store_attrs(const DoutPrefixProvider* dpp,
+                                       Attrs& new_attrs, optional_yield y)
+{
+  return next->merge_and_store_attrs(dpp, new_attrs, y);
+}
+
+int FilterBucket::try_refresh_info(const DoutPrefixProvider* dpp,
+                                  ceph::real_time* pmtime)
+{
+  return next->try_refresh_info(dpp, pmtime);
+}
+
+int FilterBucket::read_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch,
+                            uint64_t end_epoch, uint32_t max_entries,
+                            bool* is_truncated, RGWUsageIter& usage_iter,
+                            std::map<rgw_user_bucket, rgw_usage_log_entry>& usage)
+{
+  return next->read_usage(dpp, start_epoch, end_epoch, max_entries,
+                         is_truncated, usage_iter, usage);
+}
+
+int FilterBucket::trim_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch,
+                            uint64_t end_epoch)
+{
+  return next->trim_usage(dpp, start_epoch, end_epoch);
+}
+
+int FilterBucket::remove_objs_from_index(const DoutPrefixProvider *dpp,
+                                        std::list<rgw_obj_index_key>& objs_to_unlink)
+{
+  return next->remove_objs_from_index(dpp, objs_to_unlink);
+}
+
+int FilterBucket::check_index(const DoutPrefixProvider *dpp,
+                             std::map<RGWObjCategory, RGWStorageStats>& existing_stats,
+                             std::map<RGWObjCategory, RGWStorageStats>& calculated_stats)
+{
+  return next->check_index(dpp, existing_stats, calculated_stats);
+}
+
+int FilterBucket::rebuild_index(const DoutPrefixProvider *dpp)
+{
+  return next->rebuild_index(dpp);
+}
+
+int FilterBucket::set_tag_timeout(const DoutPrefixProvider *dpp, uint64_t timeout)
+{
+  return next->set_tag_timeout(dpp, timeout);
+}
+
+int FilterBucket::purge_instance(const DoutPrefixProvider* dpp)
+{
+  return next->purge_instance(dpp);
+}
+
+std::unique_ptr<MultipartUpload> FilterBucket::get_multipart_upload(
+                                 const std::string& oid,
+                                 std::optional<std::string> upload_id,
+                                 ACLOwner owner, ceph::real_time mtime)
+{
+  std::unique_ptr<MultipartUpload> nmu =
+    next->get_multipart_upload(oid, upload_id, owner, mtime);
+
+  return std::make_unique<FilterMultipartUpload>(std::move(nmu), this);
+}
+
+int FilterBucket::list_multiparts(const DoutPrefixProvider *dpp,
+                                 const std::string& prefix,
+                                 std::string& marker,
+                                 const std::string& delim,
+                                 const int& max_uploads,
+                                 std::vector<std::unique_ptr<MultipartUpload>>& uploads,
+                                 std::map<std::string, bool> *common_prefixes,
+                                 bool *is_truncated)
+{
+  std::vector<std::unique_ptr<MultipartUpload>> nup;
+  int ret;
+
+  ret = next->list_multiparts(dpp, prefix, marker, delim, max_uploads, nup,
+                             common_prefixes, is_truncated);
+  if (ret < 0)
+    return ret;
+
+  for (auto& ent : nup) {
+    uploads.emplace_back(std::make_unique<FilterMultipartUpload>(std::move(ent), this));
+  }
+
+  return 0;
+}
+
+int FilterBucket::abort_multiparts(const DoutPrefixProvider* dpp, CephContext* cct)
+{
+  return next->abort_multiparts(dpp, cct);
+}
+
+int FilterObject::delete_object(const DoutPrefixProvider* dpp,
+                               optional_yield y,
+                               bool prevent_versioning)
+{
+  return next->delete_object(dpp, y, prevent_versioning);
+}
+
+int FilterObject::delete_obj_aio(const DoutPrefixProvider* dpp, RGWObjState* astate,
+                                Completions* aio, bool keep_index_consistent,
+                                optional_yield y)
+{
+  return next->delete_obj_aio(dpp, astate, aio, keep_index_consistent, y);
+}
+
+int FilterObject::copy_object(User* user,
+                             req_info* info,
+                             const rgw_zone_id& source_zone,
+                             rgw::sal::Object* dest_object,
+                             rgw::sal::Bucket* dest_bucket,
+                             rgw::sal::Bucket* src_bucket,
+                             const rgw_placement_rule& dest_placement,
+                             ceph::real_time* src_mtime,
+                             ceph::real_time* mtime,
+                             const ceph::real_time* mod_ptr,
+                             const ceph::real_time* unmod_ptr,
+                             bool high_precision_time,
+                             const char* if_match,
+                             const char* if_nomatch,
+                             AttrsMod attrs_mod,
+                             bool copy_if_newer,
+                             Attrs& attrs,
+                             RGWObjCategory category,
+                             uint64_t olh_epoch,
+                             boost::optional<ceph::real_time> delete_at,
+                             std::string* version_id,
+                             std::string* tag,
+                             std::string* etag,
+                             void (*progress_cb)(off_t, void *),
+                             void* progress_data,
+                             const DoutPrefixProvider* dpp,
+                             optional_yield y)
+{
+  return next->copy_object(user, info, source_zone,
+                          nextObject(dest_object),
+                          nextBucket(dest_bucket),
+                          nextBucket(src_bucket),
+                          dest_placement, src_mtime, mtime,
+                          mod_ptr, unmod_ptr, high_precision_time, if_match,
+                          if_nomatch, attrs_mod, copy_if_newer, attrs,
+                          category, olh_epoch, delete_at, version_id, tag,
+                          etag, progress_cb, progress_data, dpp, y);
+}
+
+RGWAccessControlPolicy& FilterObject::get_acl()
+{
+  return next->get_acl();
+}
+
+int FilterObject::get_obj_state(const DoutPrefixProvider* dpp, RGWObjState **pstate,
+                               optional_yield y, bool follow_olh)
+{
+  return next->get_obj_state(dpp, pstate, y, follow_olh);
+}
+
+int FilterObject::set_obj_attrs(const DoutPrefixProvider* dpp, Attrs* setattrs,
+                               Attrs* delattrs, optional_yield y)
+{
+  return next->set_obj_attrs(dpp, setattrs, delattrs, y);
+}
+
+int FilterObject::get_obj_attrs(optional_yield y, const DoutPrefixProvider* dpp,
+                               rgw_obj* target_obj)
+{
+  return next->get_obj_attrs(y, dpp, target_obj);
+}
+
+int FilterObject::modify_obj_attrs(const char* attr_name, bufferlist& attr_val,
+                                  optional_yield y, const DoutPrefixProvider* dpp)
+{
+  return next->modify_obj_attrs(attr_name, attr_val, y, dpp);
+}
+
+int FilterObject::delete_obj_attrs(const DoutPrefixProvider* dpp,
+                                  const char* attr_name, optional_yield y)
+{
+  return next->delete_obj_attrs(dpp, attr_name, y);
+}
+
+bool FilterObject::is_expired()
+{
+  return next->is_expired();
+}
+
+void FilterObject::gen_rand_obj_instance_name()
+{
+  return next->gen_rand_obj_instance_name();
+}
+
+std::unique_ptr<MPSerializer> FilterObject::get_serializer(const DoutPrefixProvider *dpp,
+                                                          const std::string& lock_name)
+{
+  std::unique_ptr<MPSerializer> s = next->get_serializer(dpp, lock_name);
+  return std::make_unique<FilterMPSerializer>(std::move(s));
+}
+
+int FilterObject::transition(Bucket* bucket,
+                            const rgw_placement_rule& placement_rule,
+                            const real_time& mtime,
+                            uint64_t olh_epoch,
+                            const DoutPrefixProvider* dpp,
+                            optional_yield y)
+{
+  return next->transition(nextBucket(bucket), placement_rule, mtime, olh_epoch,
+                         dpp, y);
+}
+
+int FilterObject::transition_to_cloud(Bucket* bucket,
+                                     rgw::sal::PlacementTier* tier,
+                                     rgw_bucket_dir_entry& o,
+                                     std::set<std::string>& cloud_targets,
+                                     CephContext* cct,
+                                     bool update_object,
+                                     const DoutPrefixProvider* dpp,
+                                     optional_yield y)
+{
+  return next->transition_to_cloud(nextBucket(bucket), nextPlacementTier(tier),
+                                  o, cloud_targets, cct, update_object, dpp, y);
+}
+
+bool FilterObject::placement_rules_match(rgw_placement_rule& r1, rgw_placement_rule& r2)
+{
+  return next->placement_rules_match(r1, r2);
+}
+
+int FilterObject::dump_obj_layout(const DoutPrefixProvider *dpp, optional_yield y,
+                                 Formatter* f)
+{
+  return next->dump_obj_layout(dpp, y, f);
+}
+
+void FilterObject::set_bucket(Bucket* b)
+{
+  bucket = b;
+  next->set_bucket(nextBucket(b));
+};
+
+int FilterObject::swift_versioning_restore(bool& restored,
+                                          const DoutPrefixProvider* dpp)
+{
+  return next->swift_versioning_restore(restored, dpp);
+}
+
+int FilterObject::swift_versioning_copy(const DoutPrefixProvider* dpp,
+                                       optional_yield y)
+{
+  return next->swift_versioning_copy(dpp, y);
+}
+
+std::unique_ptr<Object::ReadOp> FilterObject::get_read_op()
+{
+  std::unique_ptr<ReadOp> r = next->get_read_op();
+  return std::make_unique<FilterReadOp>(std::move(r));
+}
+
+std::unique_ptr<Object::DeleteOp> FilterObject::get_delete_op()
+{
+  std::unique_ptr<DeleteOp> d = next->get_delete_op();
+  return std::make_unique<FilterDeleteOp>(std::move(d));
+}
+
+int FilterObject::omap_get_vals(const DoutPrefixProvider *dpp, const std::string& marker,
+                               uint64_t count, std::map<std::string, bufferlist> *m,
+                               bool* pmore, optional_yield y)
+{
+  return next->omap_get_vals(dpp, marker, count, m, pmore, y);
+}
+
+int FilterObject::omap_get_all(const DoutPrefixProvider *dpp,
+                              std::map<std::string, bufferlist> *m,
+                              optional_yield y)
+{
+  return next->omap_get_all(dpp, m, y);
+}
+
+int FilterObject::omap_get_vals_by_keys(const DoutPrefixProvider *dpp,
+                                       const std::string& oid,
+                                       const std::set<std::string>& keys,
+                                       Attrs* vals)
+{
+  return next->omap_get_vals_by_keys(dpp, oid, keys, vals);
+}
+
+int FilterObject::omap_set_val_by_key(const DoutPrefixProvider *dpp,
+                                     const std::string& key, bufferlist& val,
+                                     bool must_exist, optional_yield y)
+{
+  return next->omap_set_val_by_key(dpp, key, val, must_exist, y);
+}
+
+int FilterObject::FilterReadOp::prepare(optional_yield y, const DoutPrefixProvider* dpp)
+{
+  /* Copy params into next */
+  next->params = params;
+  return next->prepare(y, dpp);
+}
+
+int FilterObject::FilterReadOp::read(int64_t ofs, int64_t end, bufferlist& bl,
+                                    optional_yield y, const DoutPrefixProvider* dpp)
+{
+  int ret = next->read(ofs, end, bl, y, dpp);
+  if (ret < 0)
+    return ret;
+
+  /* Copy params out of next */
+  params = next->params;
+  return ret;
+}
+
+int FilterObject::FilterReadOp::get_attr(const DoutPrefixProvider* dpp, const char* name, bufferlist& dest, optional_yield y)
+{
+  return next->get_attr(dpp, name, dest, y);
+}
+
+int FilterObject::FilterReadOp::iterate(const DoutPrefixProvider* dpp, int64_t ofs,
+                                       int64_t end, RGWGetDataCB* cb, optional_yield y)
+{
+  int ret = next->iterate(dpp, ofs, end, cb, y);
+  if (ret < 0)
+    return ret;
+
+  /* Copy params out of next */
+  params = next->params;
+  return ret;
+}
+
+int FilterObject::FilterDeleteOp::delete_obj(const DoutPrefixProvider* dpp,
+                                          optional_yield y)
+{
+  /* Copy params into next */
+  next->params = params;
+  int ret = next->delete_obj(dpp, y);
+  /* Copy result back */
+  result = next->result;
+  return ret;
+}
+
+std::unique_ptr<rgw::sal::Object> FilterMultipartUpload::get_meta_obj()
+{
+  std::unique_ptr<Object> no = next->get_meta_obj();
+
+  return std::make_unique<FilterObject>(std::move(no), bucket);
+}
+
+int FilterMultipartUpload::init(const DoutPrefixProvider *dpp, optional_yield y,
+                               ACLOwner& owner, rgw_placement_rule& dest_placement,
+                               rgw::sal::Attrs& attrs)
+{
+  return next->init(dpp, y, owner, dest_placement, attrs);
+}
+
+int FilterMultipartUpload::list_parts(const DoutPrefixProvider *dpp, CephContext *cct,
+                                     int num_parts, int marker,
+                                     int *next_marker, bool *truncated,
+                                     bool assume_unsorted)
+{
+  int ret;
+
+  ret = next->list_parts(dpp, cct, num_parts, marker, next_marker, truncated,
+                        assume_unsorted);
+  if (ret < 0)
+    return ret;
+
+  parts.clear();
+
+  for (auto& ent : next->get_parts()) {
+    parts.emplace(ent.first, std::make_unique<FilterMultipartPart>(std::move(ent.second)));
+  }
+
+  return 0;
+}
+
+int FilterMultipartUpload::abort(const DoutPrefixProvider *dpp, CephContext *cct)
+{
+  return next->abort(dpp, cct);
+}
+
+int FilterMultipartUpload::complete(const DoutPrefixProvider *dpp,
+                                   optional_yield y, CephContext* cct,
+                                   std::map<int, std::string>& part_etags,
+                                   std::list<rgw_obj_index_key>& remove_objs,
+                                   uint64_t& accounted_size, bool& compressed,
+                                   RGWCompressionInfo& cs_info, off_t& ofs,
+                                   std::string& tag, ACLOwner& owner,
+                                   uint64_t olh_epoch,
+                                   rgw::sal::Object* target_obj)
+{
+  return next->complete(dpp, y, cct, part_etags, remove_objs, accounted_size,
+                       compressed, cs_info, ofs, tag, owner, olh_epoch,
+                       nextObject(target_obj));
+}
+
+int FilterMultipartUpload::get_info(const DoutPrefixProvider *dpp,
+                                   optional_yield y, rgw_placement_rule** rule,
+                                   rgw::sal::Attrs* attrs)
+{
+  return next->get_info(dpp, y, rule, attrs);
+}
+
+std::unique_ptr<Writer> FilterMultipartUpload::get_writer(
+                                 const DoutPrefixProvider *dpp,
+                                 optional_yield y,
+                                 std::unique_ptr<rgw::sal::Object> _head_obj,
+                                 const rgw_user& owner,
+                                 const rgw_placement_rule *ptail_placement_rule,
+                                 uint64_t part_num,
+                                 const std::string& part_num_str)
+{
+  std::unique_ptr<Object> no = nextObject(_head_obj.get())->clone();
+
+  std::unique_ptr<Writer> writer;
+  writer = next->get_writer(dpp, y, std::move(no), owner,
+                           ptail_placement_rule, part_num, part_num_str);
+
+  return std::make_unique<FilterWriter>(std::move(writer), std::move(_head_obj));
+}
+
+int FilterMPSerializer::try_lock(const DoutPrefixProvider *dpp, utime_t dur,
+                                optional_yield y)
+{
+  return next->try_lock(dpp, dur, y);
+}
+
+int FilterLCSerializer::try_lock(const DoutPrefixProvider *dpp, utime_t dur,
+                                optional_yield y)
+{
+  return next->try_lock(dpp, dur, y);
+}
+
+std::unique_ptr<Lifecycle::LCEntry> FilterLifecycle::get_entry()
+{
+  std::unique_ptr<Lifecycle::LCEntry> e = next->get_entry();
+  return std::make_unique<FilterLCEntry>(std::move(e));
+}
+
+int FilterLifecycle::get_entry(const std::string& oid, const std::string& marker,
+                              std::unique_ptr<LCEntry>* entry)
+{
+  std::unique_ptr<LCEntry> ne;
+  int ret;
+
+  ret = next->get_entry(oid, marker, &ne);
+  if (ret < 0)
+    return ret;
+
+  LCEntry* e = new FilterLCEntry(std::move(ne));
+  entry->reset(e);
+
+  return 0;
+}
+
+int FilterLifecycle::get_next_entry(const std::string& oid, const std::string& marker,
+                                   std::unique_ptr<LCEntry>* entry)
+{
+  std::unique_ptr<LCEntry> ne;
+  int ret;
+
+  ret = next->get_next_entry(oid, marker, &ne);
+  if (ret < 0)
+    return ret;
+
+  LCEntry* e = new FilterLCEntry(std::move(ne));
+  entry->reset(e);
+
+  return 0;
+}
+
+int FilterLifecycle::set_entry(const std::string& oid, LCEntry& entry)
+{
+  return next->set_entry(oid, entry);
+}
+
+int FilterLifecycle::list_entries(const std::string& oid, const std::string& marker,
+                                 uint32_t max_entries,
+                                 std::vector<std::unique_ptr<LCEntry>>& entries)
+{
+  std::vector<std::unique_ptr<LCEntry>> ne;
+  int ret;
+
+  ret = next->list_entries(oid, marker, max_entries, ne);
+  if (ret < 0)
+    return ret;
+
+  for (auto& ent : ne) {
+    entries.emplace_back(std::make_unique<FilterLCEntry>(std::move(ent)));
+  }
+
+  return 0;
+}
+
+int FilterLifecycle::rm_entry(const std::string& oid, LCEntry& entry)
+{
+  return next->rm_entry(oid, entry);
+}
+
+int FilterLifecycle::get_head(const std::string& oid, std::unique_ptr<LCHead>* head)
+{
+  std::unique_ptr<LCHead> nh;
+  int ret;
+
+  ret = next->get_head(oid, &nh);
+  if (ret < 0)
+    return ret;
+
+  LCHead* h = new FilterLCHead(std::move(nh));
+  head->reset(h);
+
+  return 0;
+}
+
+int FilterLifecycle::put_head(const std::string& oid, LCHead& head)
+{
+  return next->put_head(oid, *(dynamic_cast<FilterLCHead&>(head).next.get()));
+}
+
+std::unique_ptr<LCSerializer> FilterLifecycle::get_serializer(
+                                             const std::string& lock_name,
+                                             const std::string& oid,
+                                             const std::string& cookie)
+{
+  std::unique_ptr<LCSerializer> ns;
+  ns = next->get_serializer(lock_name, oid, cookie);
+
+  return std::make_unique<FilterLCSerializer>(std::move(ns));
+}
+
+int FilterNotification::publish_reserve(const DoutPrefixProvider *dpp,
+                                       RGWObjTags* obj_tags)
+{
+  return next->publish_reserve(dpp, obj_tags);
+}
+
+int FilterNotification::publish_commit(const DoutPrefixProvider* dpp, uint64_t size,
+                                      const ceph::real_time& mtime, const
+                                      std::string& etag, const std::string& version)
+{
+  return next->publish_commit(dpp, size, mtime, etag, version);
+}
+
+int FilterWriter::process(bufferlist&& data, uint64_t offset)
+{
+  return next->process(std::move(data), offset);
+}
+
+int FilterWriter::complete(size_t accounted_size, const std::string& etag,
+                       ceph::real_time *mtime, ceph::real_time set_mtime,
+                       std::map<std::string, bufferlist>& attrs,
+                       ceph::real_time delete_at,
+                       const char *if_match, const char *if_nomatch,
+                       const std::string *user_data,
+                       rgw_zone_set *zones_trace, bool *canceled,
+                       optional_yield y)
+{
+  return next->complete(accounted_size, etag, mtime, set_mtime, attrs,
+                       delete_at, if_match, if_nomatch, user_data, zones_trace,
+                       canceled, y);
+}
+
+int FilterLuaScriptManager::get(const DoutPrefixProvider* dpp, optional_yield y,
+                               const std::string& key, std::string& script)
+{
+  return next->get(dpp, y, key, script);
+}
+
+int FilterLuaScriptManager::put(const DoutPrefixProvider* dpp, optional_yield y,
+                               const std::string& key, const std::string& script)
+{
+  return next->put(dpp, y, key, script);
+}
+
+int FilterLuaScriptManager::del(const DoutPrefixProvider* dpp, optional_yield y,
+                               const std::string& key)
+{
+  return next->del(dpp, y, key);
+}
+
+} } // namespace rgw::sal
index 53d333b0c3f5e693ed1d7faf4f0ca03557ebf9e8..69d1ce9b98256919f824316818126dc6ec72c04f 100644 (file)
 #pragma once
 
 #include "rgw_sal.h"
+#include "rgw_oidc_provider.h"
+#include "rgw_role.h"
 
 namespace rgw { namespace sal {
 
+class FilterCompletions : public Completions {
+protected:
+  std::unique_ptr<Completions> next;
+
+public:
+  FilterCompletions(std::unique_ptr<Completions> _next) : next(std::move(_next)) {}
+  virtual ~FilterCompletions() = default;
+  virtual int drain() override { return next->drain(); }
+};
+
+class FilterPlacementTier : public PlacementTier {
+protected:
+  std::unique_ptr<PlacementTier> next;
+
+public:
+  FilterPlacementTier(std::unique_ptr<PlacementTier> _next) : next(std::move(_next)) {}
+  virtual ~FilterPlacementTier() = default;
+
+  virtual const std::string& get_tier_type() override { return next->get_tier_type(); }
+  virtual const std::string& get_storage_class() override { return next->get_storage_class(); }
+  virtual bool retain_head_object() override { return next->retain_head_object(); }
+
+  /* Internal to Filters */
+  PlacementTier* get_next() { return next.get(); }
+};
+
+class FilterZoneGroup : public ZoneGroup {
+protected:
+  std::unique_ptr<ZoneGroup> next;
+
+public:
+  FilterZoneGroup(std::unique_ptr<ZoneGroup> _next) : next(std::move(_next)) {}
+  virtual ~FilterZoneGroup() = default;
+  virtual const std::string& get_id() const override
+    { return next->get_id(); }
+  virtual const std::string& get_name() const override
+    { return next->get_name(); }
+  virtual int equals(const std::string& other_zonegroup) const override
+    { return next->equals(other_zonegroup); }
+  virtual const std::string& get_endpoint() const override
+    { return next->get_endpoint(); }
+  virtual bool placement_target_exists(std::string& target) const override
+    { return next->placement_target_exists(target); }
+  virtual bool is_master_zonegroup() const override
+    { return next->is_master_zonegroup(); }
+  virtual const std::string& get_api_name() const override
+    { return next->get_api_name(); }
+  virtual int get_placement_target_names(std::set<std::string>& names) const override
+    { return next->get_placement_target_names(names); }
+  virtual const std::string& get_default_placement_name() const override
+    { return next->get_default_placement_name(); }
+  virtual int get_hostnames(std::list<std::string>& names) const override
+    { return next->get_hostnames(names); }
+  virtual int get_s3website_hostnames(std::list<std::string>& names) const override
+    { return next->get_s3website_hostnames(names); }
+  virtual int get_zone_count() const override
+    { return next->get_zone_count(); }
+  virtual int get_placement_tier(const rgw_placement_rule& rule, std::unique_ptr<PlacementTier>* tier) override;
+  virtual std::unique_ptr<ZoneGroup> clone() override {
+    std::unique_ptr<ZoneGroup> nzg = next->clone();
+    return std::make_unique<FilterZoneGroup>(std::move(nzg));
+  }
+};
+
+class FilterZone : public Zone {
+protected:
+  std::unique_ptr<Zone> next;
+private:
+  std::unique_ptr<ZoneGroup> group;
+
+public:
+  FilterZone(std::unique_ptr<Zone> _next) : next(std::move(_next))
+  {
+    group = std::make_unique<FilterZoneGroup>(next->get_zonegroup().clone());
+  }
+  virtual ~FilterZone() = default;
+
+  virtual std::unique_ptr<Zone> clone() override {
+    std::unique_ptr<Zone> nz = next->clone();
+    return std::make_unique<FilterZone>(std::move(nz));
+  }
+  virtual ZoneGroup& get_zonegroup() override {
+      return *group.get();
+  }
+  virtual int get_zonegroup(const std::string& id, std::unique_ptr<ZoneGroup>* zonegroup) override;
+  virtual const rgw_zone_id& get_id() override {
+      return next->get_id();
+  }
+  virtual const std::string& get_name() const override {
+      return next->get_name();
+  }
+  virtual bool is_writeable() override {
+      return next->is_writeable();
+  }
+  virtual bool get_redirect_endpoint(std::string* endpoint) override {
+      return next->get_redirect_endpoint(endpoint);
+  }
+  virtual bool has_zonegroup_api(const std::string& api) const override {
+      return next->has_zonegroup_api(api);
+  }
+  virtual const std::string& get_current_period_id() override {
+      return next->get_current_period_id();
+  }
+  virtual const RGWAccessKey& get_system_key() override {
+      return next->get_system_key();
+  }
+  virtual const std::string& get_realm_name() override {
+      return next->get_realm_name();
+  }
+  virtual const std::string& get_realm_id() override {
+      return next->get_realm_id();
+  }
+  virtual const std::string_view get_tier_type() override {
+      return next->get_tier_type();
+  }
+};
+
 class FilterStore : public Store {
-  public:
-    FilterStore() {}
-    virtual ~FilterStore() = default;
-
-    virtual int initialize(CephContext *cct, const DoutPrefixProvider *dpp) = 0;
-    virtual const std::string get_name() const = 0;
-    virtual std::string get_cluster_id(const DoutPrefixProvider* dpp,  optional_yield y) = 0;
-    virtual std::unique_ptr<User> get_user(const rgw_user& u) = 0;
-    virtual int get_user_by_access_key(const DoutPrefixProvider* dpp, const std::string& key, optional_yield y, std::unique_ptr<User>* user) = 0;
-    virtual int get_user_by_email(const DoutPrefixProvider* dpp, const std::string& email, optional_yield y, std::unique_ptr<User>* user) = 0;
-    virtual int get_user_by_swift(const DoutPrefixProvider* dpp, const std::string& user_str, optional_yield y, std::unique_ptr<User>* user) = 0;
-    virtual std::unique_ptr<Object> get_object(const rgw_obj_key& k) = 0;
-    virtual int get_bucket(User* u, const RGWBucketInfo& i, std::unique_ptr<Bucket>* bucket) = 0;
-    virtual int get_bucket(const DoutPrefixProvider* dpp, User* u, const rgw_bucket& b, std::unique_ptr<Bucket>* bucket, optional_yield y) = 0;
-    virtual int get_bucket(const DoutPrefixProvider* dpp, User* u, const std::string& tenant, const std::string& name, std::unique_ptr<Bucket>* bucket, optional_yield y) = 0;
-    virtual bool is_meta_master() = 0;
-    virtual int forward_request_to_master(const DoutPrefixProvider *dpp, User* user, obj_version* objv,
-                                         bufferlist& in_data, JSONParser* jp, req_info& info,
-                                         optional_yield y) = 0;
-    virtual Zone* get_zone() = 0;
-    virtual std::string zone_unique_id(uint64_t unique_num) = 0;
-    virtual std::string zone_unique_trans_id(const uint64_t unique_num) = 0;
-    virtual int cluster_stat(RGWClusterStat& stats) = 0;
-    virtual std::unique_ptr<Lifecycle> get_lifecycle(void) = 0;
-    virtual std::unique_ptr<Completions> get_completions(void) = 0;
-
-    virtual std::unique_ptr<Notification> get_notification(rgw::sal::Object* obj, rgw::sal::Object* src_obj, struct req_state* s,
-        rgw::notify::EventType event_type, const std::string* object_name=nullptr) = 0;
-    virtual std::unique_ptr<Notification> get_notification(
+protected:
+  Store* next;
+private:
+  std::unique_ptr<FilterZone> zone;
+
+public:
+  FilterStore(Store* _next) : next(_next) {}
+  virtual ~FilterStore() = default;
+
+  virtual int initialize(CephContext *cct, const DoutPrefixProvider *dpp) override;
+  virtual const std::string get_name() const override;
+  virtual std::string get_cluster_id(const DoutPrefixProvider* dpp,
+                                    optional_yield y) override;
+  virtual std::unique_ptr<User> get_user(const rgw_user& u) override;
+  virtual int get_user_by_access_key(const DoutPrefixProvider* dpp, const
+                                    std::string& key, optional_yield y,
+                                    std::unique_ptr<User>* user) override;
+  virtual int get_user_by_email(const DoutPrefixProvider* dpp, const
+                               std::string& email, optional_yield y,
+                               std::unique_ptr<User>* user) override;
+  virtual int get_user_by_swift(const DoutPrefixProvider* dpp, const
+                               std::string& user_str, optional_yield y,
+                               std::unique_ptr<User>* user) override;
+  virtual std::unique_ptr<Object> get_object(const rgw_obj_key& k) override;
+  virtual int get_bucket(User* u, const RGWBucketInfo& i,
+                        std::unique_ptr<Bucket>* bucket) override;
+  virtual int get_bucket(const DoutPrefixProvider* dpp, User* u, const
+                        rgw_bucket& b, std::unique_ptr<Bucket>* bucket,
+                        optional_yield y) override;
+  virtual int get_bucket(const DoutPrefixProvider* dpp, User* u, const
+                        std::string& tenant, const std::string& name,
+                        std::unique_ptr<Bucket>* bucket, optional_yield y) override;
+  virtual bool is_meta_master() override;
+  virtual int forward_request_to_master(const DoutPrefixProvider *dpp, User* user,
+                                       obj_version* objv, bufferlist& in_data,
+                                       JSONParser* jp, req_info& info,
+                                       optional_yield y) override;
+  virtual int forward_iam_request_to_master(const DoutPrefixProvider *dpp,
+                                           const RGWAccessKey& key,
+                                           obj_version* objv,
+                                           bufferlist& in_data,
+                                           RGWXMLDecoder::XMLParser* parser,
+                                           req_info& info,
+                                           optional_yield y) override;
+  virtual Zone* get_zone() override { return zone.get(); }
+  virtual std::string zone_unique_id(uint64_t unique_num) override;
+  virtual std::string zone_unique_trans_id(const uint64_t unique_num) override;
+  virtual int cluster_stat(RGWClusterStat& stats) override;
+  virtual std::unique_ptr<Lifecycle> get_lifecycle(void) override;
+  virtual std::unique_ptr<Completions> get_completions(void) override;
+
+  virtual std::unique_ptr<Notification> get_notification(rgw::sal::Object* obj,
+                                rgw::sal::Object* src_obj, struct req_state* s,
+                                rgw::notify::EventType event_type,
+                                const std::string* object_name=nullptr) override;
+  virtual std::unique_ptr<Notification> get_notification(
     const DoutPrefixProvider* dpp, rgw::sal::Object* obj, rgw::sal::Object* src_obj, 
-    rgw::notify::EventType event_type, rgw::sal::Bucket* _bucket, std::string& _user_id, std::string& _user_tenant,
-    std::string& _req_id, optional_yield y) = 0;
-
-    virtual RGWLC* get_rgwlc(void) = 0;
-    virtual RGWCoroutinesManagerRegistry* get_cr_registry() = 0;
-
-    virtual int log_usage(const DoutPrefixProvider *dpp, std::map<rgw_user_bucket, RGWUsageBatch>& usage_info) = 0;
-    virtual int log_op(const DoutPrefixProvider *dpp, std::string& oid, bufferlist& bl) = 0;
-    virtual int register_to_service_map(const DoutPrefixProvider *dpp, const std::string& daemon_type,
-                                       const std::map<std::string, std::string>& meta) = 0;
-    virtual void get_quota(RGWQuota& quota) = 0;
-    virtual void get_ratelimit(RGWRateLimitInfo& bucket_ratelimit, RGWRateLimitInfo& user_ratelimit, RGWRateLimitInfo& anon_ratelimit) = 0;
-    virtual int set_buckets_enabled(const DoutPrefixProvider* dpp, std::vector<rgw_bucket>& buckets, bool enabled) = 0;
-    virtual uint64_t get_new_req_id() = 0;
-    virtual int get_sync_policy_handler(const DoutPrefixProvider* dpp,
-                                       std::optional<rgw_zone_id> zone,
-                                       std::optional<rgw_bucket> bucket,
-                                       RGWBucketSyncPolicyHandlerRef* phandler,
-                                       optional_yield y) = 0;
-    virtual RGWDataSyncStatusManager* get_data_sync_manager(const rgw_zone_id& source_zone) = 0;
-    virtual void wakeup_meta_sync_shards(std::set<int>& shard_ids) = 0;
-    virtual void wakeup_data_sync_shards(const DoutPrefixProvider *dpp, const rgw_zone_id& source_zone, boost::container::flat_map<int, boost::container::flat_set<rgw_data_notify_entry>>& shard_ids) = 0;
-    virtual int clear_usage(const DoutPrefixProvider *dpp) = 0;
-    virtual int read_all_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch,
-                              uint32_t max_entries, bool* is_truncated,
-                              RGWUsageIter& usage_iter,
-                              std::map<rgw_user_bucket, rgw_usage_log_entry>& usage) = 0;
-    virtual int trim_all_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch) = 0;
-    virtual int get_config_key_val(std::string name, bufferlist* bl) = 0;
-    virtual int meta_list_keys_init(const DoutPrefixProvider *dpp, const std::string& section, const std::string& marker, void** phandle) = 0;
-    virtual int meta_list_keys_next(const DoutPrefixProvider *dpp, void* handle, int max, std::list<std::string>& keys, bool* truncated) = 0;
-    virtual void meta_list_keys_complete(void* handle) = 0;
-    virtual std::string meta_get_marker(void* handle) = 0;
-    virtual int meta_remove(const DoutPrefixProvider* dpp, std::string& metadata_key, optional_yield y) = 0;
-    virtual const RGWSyncModuleInstanceRef& get_sync_module() = 0;
-    virtual std::string get_host_id() = 0;
-    virtual std::unique_ptr<LuaScriptManager> get_lua_script_manager() = 0;
-    virtual std::unique_ptr<RGWRole> get_role(std::string name,
-                                             std::string tenant,
-                                             std::string path="",
-                                             std::string trust_policy="",
-                                             std::string max_session_duration_str="",
-                std::multimap<std::string,std::string> tags={}) = 0;
-    virtual std::unique_ptr<RGWRole> get_role(std::string id) = 0;
-    virtual std::unique_ptr<RGWRole> get_role(const RGWRoleInfo& info) = 0;
-    virtual int get_roles(const DoutPrefixProvider *dpp,
-                         optional_yield y,
-                         const std::string& path_prefix,
-                         const std::string& tenant,
-                         std::vector<std::unique_ptr<RGWRole>>& roles) = 0;
-    virtual std::unique_ptr<RGWOIDCProvider> get_oidc_provider() = 0;
-    virtual int get_oidc_providers(const DoutPrefixProvider *dpp,
-                                  const std::string& tenant,
-                                  std::vector<std::unique_ptr<RGWOIDCProvider>>& providers) = 0;
-    virtual std::unique_ptr<Writer> get_append_writer(const DoutPrefixProvider *dpp,
+    rgw::notify::EventType event_type, rgw::sal::Bucket* _bucket,
+    std::string& _user_id, std::string& _user_tenant,
+    std::string& _req_id, optional_yield y) override;
+
+  virtual RGWLC* get_rgwlc(void) override;
+  virtual RGWCoroutinesManagerRegistry* get_cr_registry() override;
+
+  virtual int log_usage(const DoutPrefixProvider *dpp, std::map<rgw_user_bucket,
+                       RGWUsageBatch>& usage_info) override;
+  virtual int log_op(const DoutPrefixProvider *dpp, std::string& oid,
+                    bufferlist& bl) override;
+  virtual int register_to_service_map(const DoutPrefixProvider *dpp, const
+                                     std::string& daemon_type,
+                                     const std::map<std::string,
+                                     std::string>& meta) override;
+  virtual void get_quota(RGWQuota& quota) override;
+  virtual void get_ratelimit(RGWRateLimitInfo& bucket_ratelimit,
+                            RGWRateLimitInfo& user_ratelimit,
+                            RGWRateLimitInfo& anon_ratelimit) override;
+  virtual int set_buckets_enabled(const DoutPrefixProvider* dpp,
+                                 std::vector<rgw_bucket>& buckets,
+                                 bool enabled) override;
+  virtual uint64_t get_new_req_id() override;
+  virtual int get_sync_policy_handler(const DoutPrefixProvider* dpp,
+                                     std::optional<rgw_zone_id> zone,
+                                     std::optional<rgw_bucket> bucket,
+                                     RGWBucketSyncPolicyHandlerRef* phandler,
+                                     optional_yield y) override;
+  virtual RGWDataSyncStatusManager* get_data_sync_manager(const rgw_zone_id& source_zone) override;
+  virtual void wakeup_meta_sync_shards(std::set<int>& shard_ids) override;
+  virtual void wakeup_data_sync_shards(const DoutPrefixProvider *dpp,
+                                      const rgw_zone_id& source_zone,
+                                      boost::container::flat_map<int, boost::container::flat_set<rgw_data_notify_entry>>& shard_ids) override;
+  virtual int clear_usage(const DoutPrefixProvider *dpp) override;
+  virtual int read_all_usage(const DoutPrefixProvider *dpp,
+                            uint64_t start_epoch, uint64_t end_epoch,
+                            uint32_t max_entries, bool* is_truncated,
+                            RGWUsageIter& usage_iter,
+                            std::map<rgw_user_bucket, rgw_usage_log_entry>& usage) override;
+  virtual int trim_all_usage(const DoutPrefixProvider *dpp,
+                            uint64_t start_epoch, uint64_t end_epoch) override;
+  virtual int get_config_key_val(std::string name, bufferlist* bl) override;
+  virtual int meta_list_keys_init(const DoutPrefixProvider *dpp,
+                                 const std::string& section,
+                                 const std::string& marker,
+                                 void** phandle) override;
+  virtual int meta_list_keys_next(const DoutPrefixProvider *dpp, void* handle,
+                                 int max, std::list<std::string>& keys,
+                                 bool* truncated) override;
+  virtual void meta_list_keys_complete(void* handle) override;
+  virtual std::string meta_get_marker(void* handle) override;
+  virtual int meta_remove(const DoutPrefixProvider* dpp,
+                         std::string& metadata_key, optional_yield y) override;
+  virtual const RGWSyncModuleInstanceRef& get_sync_module() override;
+  virtual std::string get_host_id() override { return next->get_host_id(); }
+  virtual std::unique_ptr<LuaScriptManager> get_lua_script_manager() override;
+  virtual std::unique_ptr<RGWRole> get_role(std::string name,
+                                           std::string tenant,
+                                           std::string path="",
+                                           std::string trust_policy="",
+                                           std::string
+                                           max_session_duration_str="",
+                std::multimap<std::string,std::string> tags={}) override;
+  virtual std::unique_ptr<RGWRole> get_role(std::string id) override;
+  virtual std::unique_ptr<RGWRole> get_role(const RGWRoleInfo& info) override;
+  virtual int get_roles(const DoutPrefixProvider *dpp,
+                       optional_yield y,
+                       const std::string& path_prefix,
+                       const std::string& tenant,
+                       std::vector<std::unique_ptr<RGWRole>>& roles) override;
+  virtual std::unique_ptr<RGWOIDCProvider> get_oidc_provider() override;
+  virtual int get_oidc_providers(const DoutPrefixProvider *dpp,
+                                const std::string& tenant,
+                                std::vector<std::unique_ptr<RGWOIDCProvider>>&
+                                providers) override;
+  virtual std::unique_ptr<Writer> get_append_writer(const DoutPrefixProvider *dpp,
                                  optional_yield y,
                                  std::unique_ptr<rgw::sal::Object> _head_obj,
                                  const rgw_user& owner,
-                                 const rgw_placement_rule *ptail_placement_rule,
+                                 const rgw_placement_rule
+                                 *ptail_placement_rule,
                                  const std::string& unique_tag,
                                  uint64_t position,
-                                 uint64_t *cur_accounted_size) = 0;
-    virtual std::unique_ptr<Writer> get_atomic_writer(const DoutPrefixProvider *dpp,
+                                 uint64_t *cur_accounted_size) override;
+  virtual std::unique_ptr<Writer> get_atomic_writer(const DoutPrefixProvider *dpp,
                                  optional_yield y,
                                  std::unique_ptr<rgw::sal::Object> _head_obj,
                                  const rgw_user& owner,
                                  const rgw_placement_rule *ptail_placement_rule,
                                  uint64_t olh_epoch,
-                                 const std::string& unique_tag) = 0;
+                                 const std::string& unique_tag) override;
 
-    virtual const std::string& get_compression_type(const rgw_placement_rule& rule) = 0;
-    virtual bool valid_placement(const rgw_placement_rule& rule) = 0;
+  virtual const std::string& get_compression_type(const rgw_placement_rule& rule) override;
+  virtual bool valid_placement(const rgw_placement_rule& rule) override;
 
-    virtual void finalize(void) = 0;
+  virtual void finalize(void) override;
 
-    virtual CephContext* ctx(void) = 0;
+  virtual CephContext* ctx(void) override;
 
-    virtual const std::string& get_luarocks_path() const = 0;
-    virtual void set_luarocks_path(const std::string& path) = 0;
+  virtual const std::string& get_luarocks_path() const override;
+  virtual void set_luarocks_path(const std::string& path) override;
 };
 
 class FilterUser : public User {
-  public:
-    FilterUser() {}
-    virtual ~FilterUser() = default;
-
-    virtual std::unique_ptr<User> clone() = 0;
-    virtual int list_buckets(const DoutPrefixProvider* dpp,
-                            const std::string& marker, const std::string& end_marker,
-                            uint64_t max, bool need_stats, BucketList& buckets,
-                            optional_yield y) = 0;
-    virtual int create_bucket(const DoutPrefixProvider* dpp,
-                            const rgw_bucket& b,
-                            const std::string& zonegroup_id,
-                            rgw_placement_rule& placement_rule,
-                            std::string& swift_ver_location,
-                            const RGWQuotaInfo* pquota_info,
-                            const RGWAccessControlPolicy& policy,
+protected:
+  std::unique_ptr<User> next;
+
+public:
+  FilterUser(std::unique_ptr<User> _next) : next(std::move(_next)) {}
+  FilterUser(FilterUser& u) : next(u.next->clone()) {};
+  virtual ~FilterUser() = default;
+
+  virtual std::unique_ptr<User> clone() override {
+    return std::make_unique<FilterUser>(*this);
+  }
+  virtual int list_buckets(const DoutPrefixProvider* dpp,
+                          const std::string& marker, const std::string& end_marker,
+                          uint64_t max, bool need_stats, BucketList& buckets,
+                          optional_yield y) override;
+  virtual int create_bucket(const DoutPrefixProvider* dpp,
+                           const rgw_bucket& b,
+                           const std::string& zonegroup_id,
+                           rgw_placement_rule& placement_rule,
+                           std::string& swift_ver_location,
+                           const RGWQuotaInfo* pquota_info,
+                           const RGWAccessControlPolicy& policy,
                            Attrs& attrs,
-                            RGWBucketInfo& info,
-                            obj_version& ep_objv,
+                           RGWBucketInfo& info,
+                           obj_version& ep_objv,
                            bool exclusive,
                            bool obj_lock_enabled,
                            bool* existed,
                            req_info& req_info,
                            std::unique_ptr<Bucket>* bucket,
-                           optional_yield y) = 0;
-
-    virtual std::string& get_display_name() = 0;
-    virtual const std::string& get_tenant() = 0;
-    virtual void set_tenant(std::string& _t) = 0;
-    virtual const std::string& get_ns() = 0;
-    virtual void set_ns(std::string& _ns) = 0;
-    virtual void clear_ns() = 0;
-    virtual const rgw_user& get_id() const = 0;
-    virtual uint32_t get_type() const = 0;
-    virtual int32_t get_max_buckets() const = 0;
-    virtual const RGWUserCaps& get_caps() const = 0;
-    virtual RGWObjVersionTracker& get_version_tracker() = 0;
-    virtual Attrs& get_attrs() = 0;
-    virtual void set_attrs(Attrs& _attrs) = 0;
-    virtual bool empty() = 0;
-    virtual int read_attrs(const DoutPrefixProvider* dpp, optional_yield y) = 0;
-    virtual int merge_and_store_attrs(const DoutPrefixProvider* dpp, Attrs& new_attrs, optional_yield y) = 0;
-    virtual int read_stats(const DoutPrefixProvider *dpp,
-                          const bucket_index_layout_generation& idx_layout,
-                          int shard_id, std::string* bucket_ver, std::string* master_ver,
-                          std::map<RGWObjCategory, RGWStorageStats>& stats,
-                          std::string* max_marker = nullptr,
-                          bool* syncstopped = nullptr) = 0;
-    virtual int read_stats_async(const DoutPrefixProvider *dpp,
-                                const bucket_index_layout_generation& idx_layout,
-                                int shard_id, RGWGetBucketStats_CB* ctx) = 0;
-    virtual int complete_flush_stats(const DoutPrefixProvider *dpp, optional_yield y) = 0;
-    virtual int read_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch,
-                          uint64_t end_epoch, uint32_t max_entries,
-                          bool* is_truncated, RGWUsageIter& usage_iter,
-                          std::map<rgw_user_bucket, rgw_usage_log_entry>& usage) = 0;
-    virtual int trim_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch) = 0;
-
-    virtual int load_user(const DoutPrefixProvider* dpp, optional_yield y) = 0;
-    virtual int store_user(const DoutPrefixProvider* dpp, optional_yield y, bool exclusive, RGWUserInfo* old_info = nullptr) = 0;
-    virtual int remove_user(const DoutPrefixProvider* dpp, optional_yield y) = 0;
-
-    RGWUserInfo& get_info() = 0;
-    virtual void print(std::ostream& out) const = 0;
+                           optional_yield y) override;
+
+  virtual std::string& get_display_name() override { return next->get_display_name(); }
+  virtual const std::string& get_tenant() override { return next->get_tenant(); }
+  virtual void set_tenant(std::string& _t) override { next->set_tenant(_t); }
+  virtual const std::string& get_ns() override { return next->get_ns(); }
+  virtual void set_ns(std::string& _ns) override { next->set_ns(_ns); }
+  virtual void clear_ns() override { next->clear_ns(); }
+  virtual const rgw_user& get_id() const override { return next->get_id(); }
+  virtual uint32_t get_type() const override { return next->get_type(); }
+  virtual int32_t get_max_buckets() const override { return next->get_max_buckets(); }
+  virtual const RGWUserCaps& get_caps() const override { return next->get_caps(); }
+  virtual RGWObjVersionTracker& get_version_tracker() override {
+    return next->get_version_tracker();
+  }
+  virtual Attrs& get_attrs() override { return next->get_attrs(); }
+  virtual void set_attrs(Attrs& _attrs) override { next->set_attrs(_attrs); }
+  virtual bool empty() override { return next->empty(); }
+  virtual int read_attrs(const DoutPrefixProvider* dpp, optional_yield y) override;
+  virtual int merge_and_store_attrs(const DoutPrefixProvider* dpp, Attrs&
+                                   new_attrs, optional_yield y) override;
+  virtual int read_stats(const DoutPrefixProvider *dpp,
+                        optional_yield y, RGWStorageStats* stats,
+                        ceph::real_time* last_stats_sync = nullptr,
+                        ceph::real_time* last_stats_update = nullptr) override;
+  virtual int read_stats_async(const DoutPrefixProvider *dpp,
+                              RGWGetUserStats_CB* cb) override;
+  virtual int complete_flush_stats(const DoutPrefixProvider *dpp, optional_yield y) override;
+  virtual int read_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch,
+                        uint64_t end_epoch, uint32_t max_entries,
+                        bool* is_truncated, RGWUsageIter& usage_iter,
+                        std::map<rgw_user_bucket, rgw_usage_log_entry>& usage) override;
+  virtual int trim_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch,
+                        uint64_t end_epoch) override;
+
+  virtual int load_user(const DoutPrefixProvider* dpp, optional_yield y) override;
+  virtual int store_user(const DoutPrefixProvider* dpp, optional_yield y, bool
+                        exclusive, RGWUserInfo* old_info = nullptr) override;
+  virtual int remove_user(const DoutPrefixProvider* dpp, optional_yield y) override;
+
+  RGWUserInfo& get_info() override { return next->get_info(); }
+  virtual void print(std::ostream& out) const override { return next->print(out); }
+
+  /* Internal to Filters */
+  User* get_next() { return next.get(); }
 };
 
 class FilterBucket : public Bucket {
-  public:
-
-    Bucket() = default;
-    virtual ~Bucket() = default;
-
-    virtual std::unique_ptr<Object> get_object(const rgw_obj_key& key) = 0;
-    virtual int list(const DoutPrefixProvider* dpp, ListParams&, int, ListResults&, optional_yield y) = 0;
-    virtual Attrs& get_attrs(void) = 0;
-    virtual int set_attrs(Attrs a) = 0;
-    virtual int remove_bucket(const DoutPrefixProvider* dpp, bool delete_children, bool forward_to_master, req_info* req_info, optional_yield y) = 0;
-    virtual int remove_bucket_bypass_gc(int concurrent_max, bool
-                                       keep_index_consistent,
-                                       optional_yield y, const
-                                       DoutPrefixProvider *dpp) = 0;
-    virtual RGWAccessControlPolicy& get_acl(void) = 0;
-    virtual int set_acl(const DoutPrefixProvider* dpp, RGWAccessControlPolicy& acl, optional_yield y) = 0;
-
-    virtual void set_owner(rgw::sal::User* _owner) = 0;
-    virtual int load_bucket(const DoutPrefixProvider* dpp, optional_yield y, bool get_stats = false) = 0;
-    virtual int read_stats(const DoutPrefixProvider *dpp, int shard_id,
-                                std::string* bucket_ver, std::string* master_ver,
-                                std::map<RGWObjCategory, RGWStorageStats>& stats,
-                                std::string* max_marker = nullptr,
-                                bool* syncstopped = nullptr) = 0;
-    virtual int read_stats_async(const DoutPrefixProvider *dpp, int shard_id, RGWGetBucketStats_CB* ctx) = 0;
-    virtual int sync_user_stats(const DoutPrefixProvider *dpp, optional_yield y) = 0;
-    virtual int update_container_stats(const DoutPrefixProvider* dpp) = 0;
-    virtual int check_bucket_shards(const DoutPrefixProvider* dpp) = 0;
-    virtual int chown(const DoutPrefixProvider* dpp, User* new_user, User* old_user, optional_yield y, const std::string* marker = nullptr) = 0;
-    virtual int put_info(const DoutPrefixProvider* dpp, bool exclusive, ceph::real_time mtime) = 0;
-    virtual bool is_owner(User* user) = 0;
-    virtual User* get_owner(void) = 0;
-    virtual ACLOwner get_acl_owner(void) = 0;
-    virtual int check_empty(const DoutPrefixProvider* dpp, optional_yield y) = 0;
-    virtual int check_quota(const DoutPrefixProvider *dpp, RGWQuota& quota, uint64_t obj_size, optional_yield y, bool check_size_only = false) = 0;
-    virtual int merge_and_store_attrs(const DoutPrefixProvider* dpp, Attrs& new_attrs, optional_yield y) = 0;
-    virtual int try_refresh_info(const DoutPrefixProvider* dpp, ceph::real_time* pmtime) = 0;
-    virtual int read_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch, uint32_t max_entries,
-                          bool* is_truncated, RGWUsageIter& usage_iter,
-                          std::map<rgw_user_bucket, rgw_usage_log_entry>& usage) = 0;
-    virtual int trim_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch) = 0;
-    virtual int remove_objs_from_index(const DoutPrefixProvider *dpp, std::list<rgw_obj_index_key>& objs_to_unlink) = 0;
-    virtual int check_index(const DoutPrefixProvider *dpp, std::map<RGWObjCategory, RGWStorageStats>& existing_stats, std::map<RGWObjCategory, RGWStorageStats>& calculated_stats) = 0;
-    virtual int rebuild_index(const DoutPrefixProvider *dpp) = 0;
-    virtual int set_tag_timeout(const DoutPrefixProvider *dpp, uint64_t timeout) = 0;
-    virtual int purge_instance(const DoutPrefixProvider* dpp) = 0;
-    virtual bool empty() const = 0;
-    virtual const std::string& get_name() const = 0;
-    virtual const std::string& get_tenant() const = 0;
-    virtual const std::string& get_marker() const = 0;
-    virtual const std::string& get_bucket_id() const = 0;
-    virtual size_t get_size() const = 0;
-    virtual size_t get_size_rounded() const = 0;
-    virtual uint64_t get_count() const = 0;
-    virtual rgw_placement_rule& get_placement_rule() = 0;
-    virtual ceph::real_time& get_creation_time() = 0;
-    virtual ceph::real_time& get_modification_time() = 0;
-    virtual obj_version& get_version() = 0;
-    virtual void set_version(obj_version &ver) = 0;
-    virtual bool versioned() = 0;
-    virtual bool versioning_enabled() = 0;
-
-    virtual std::unique_ptr<Bucket> clone() = 0;
-
-    virtual std::unique_ptr<MultipartUpload> get_multipart_upload(
+protected:
+  std::unique_ptr<Bucket> next;
+private:
+  User* user;
+
+public:
+
+  FilterBucket(std::unique_ptr<Bucket> _next, User* _user) :
+    next(std::move(_next)), user(_user) {}
+  virtual ~FilterBucket() = default;
+
+  virtual std::unique_ptr<Object> get_object(const rgw_obj_key& key) override;
+  virtual int list(const DoutPrefixProvider* dpp, ListParams&, int,
+                  ListResults&, optional_yield y) override;
+  virtual Attrs& get_attrs(void) override { return next->get_attrs(); }
+  virtual int set_attrs(Attrs a) override { return next->set_attrs(a); }
+  virtual int remove_bucket(const DoutPrefixProvider* dpp, bool delete_children,
+                           bool forward_to_master, req_info* req_info,
+                           optional_yield y) override;
+  virtual int remove_bucket_bypass_gc(int concurrent_max, bool
+                                     keep_index_consistent,
+                                     optional_yield y, const
+                                     DoutPrefixProvider *dpp) override;
+  virtual RGWAccessControlPolicy& get_acl(void) override { return next->get_acl(); }
+  virtual int set_acl(const DoutPrefixProvider* dpp, RGWAccessControlPolicy& acl,
+                     optional_yield y) override;
+
+  virtual void set_owner(rgw::sal::User* _owner) override { next->set_owner(_owner); }
+  virtual int load_bucket(const DoutPrefixProvider* dpp, optional_yield y,
+                         bool get_stats = false) override;
+  virtual int read_stats(const DoutPrefixProvider *dpp,
+                        const bucket_index_layout_generation& idx_layout,
+                        int shard_id, std::string* bucket_ver, std::string* master_ver,
+                        std::map<RGWObjCategory, RGWStorageStats>& stats,
+                        std::string* max_marker = nullptr,
+                        bool* syncstopped = nullptr) override;
+  virtual int read_stats_async(const DoutPrefixProvider *dpp,
+                              const bucket_index_layout_generation& idx_layout,
+                              int shard_id, RGWGetBucketStats_CB* ctx) override;
+  virtual int sync_user_stats(const DoutPrefixProvider *dpp, optional_yield y) override;
+  virtual int update_container_stats(const DoutPrefixProvider* dpp) override;
+  virtual int check_bucket_shards(const DoutPrefixProvider* dpp) override;
+  virtual int chown(const DoutPrefixProvider* dpp, User* new_user,
+                   User* old_user, optional_yield y,
+                   const std::string* marker = nullptr) override;
+  virtual int put_info(const DoutPrefixProvider* dpp, bool exclusive,
+                      ceph::real_time mtime) override;
+  virtual bool is_owner(User* user) override;
+  virtual User* get_owner(void) override { return user; }
+  virtual ACLOwner get_acl_owner(void) override { return next->get_acl_owner(); }
+  virtual int check_empty(const DoutPrefixProvider* dpp, optional_yield y) override;
+  virtual int check_quota(const DoutPrefixProvider *dpp, RGWQuota& quota,
+                         uint64_t obj_size, optional_yield y,
+                         bool check_size_only = false) override;
+  virtual int merge_and_store_attrs(const DoutPrefixProvider* dpp,
+                                   Attrs& new_attrs, optional_yield y) override;
+  virtual int try_refresh_info(const DoutPrefixProvider* dpp,
+                              ceph::real_time* pmtime) override;
+  virtual int read_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch,
+                        uint64_t end_epoch, uint32_t max_entries,
+                        bool* is_truncated, RGWUsageIter& usage_iter,
+                        std::map<rgw_user_bucket,
+                        rgw_usage_log_entry>& usage) override;
+  virtual int trim_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch,
+                        uint64_t end_epoch) override;
+  virtual int remove_objs_from_index(const DoutPrefixProvider *dpp,
+                                    std::list<rgw_obj_index_key>&
+                                    objs_to_unlink) override;
+  virtual int check_index(const DoutPrefixProvider *dpp,
+                         std::map<RGWObjCategory, RGWStorageStats>&
+                         existing_stats,
+                         std::map<RGWObjCategory, RGWStorageStats>&
+                         calculated_stats) override;
+  virtual int rebuild_index(const DoutPrefixProvider *dpp) override;
+  virtual int set_tag_timeout(const DoutPrefixProvider *dpp, uint64_t timeout) override;
+  virtual int purge_instance(const DoutPrefixProvider* dpp) override;
+  virtual bool empty() const override { return next->empty(); }
+  virtual const std::string& get_name() const override { return next->get_name(); }
+  virtual const std::string& get_tenant() const override { return next->get_tenant(); }
+  virtual const std::string& get_marker() const override { return next->get_marker(); }
+  virtual const std::string& get_bucket_id() const override { return next->get_bucket_id(); }
+  virtual size_t get_size() const override { return next->get_size(); }
+  virtual size_t get_size_rounded() const override { return next->get_size_rounded(); }
+  virtual uint64_t get_count() const override { return next->get_count(); }
+  virtual rgw_placement_rule& get_placement_rule() override { return next->get_placement_rule(); }
+  virtual ceph::real_time& get_creation_time() override { return next->get_creation_time(); }
+  virtual ceph::real_time& get_modification_time() override { return next->get_modification_time(); }
+  virtual obj_version& get_version() override { return next->get_version(); }
+  virtual void set_version(obj_version &ver) override { next->set_version(ver); }
+  virtual bool versioned() override { return next->versioned(); }
+  virtual bool versioning_enabled() override { return next->versioning_enabled(); }
+
+  virtual std::unique_ptr<Bucket> clone() override {
+    std::unique_ptr<Bucket> nb = next->clone();
+    return std::make_unique<FilterBucket>(std::move(nb), user);
+  }
+
+  virtual std::unique_ptr<MultipartUpload> get_multipart_upload(
                                const std::string& oid,
                                std::optional<std::string> upload_id=std::nullopt,
-                               ACLOwner owner={}, ceph::real_time mtime=real_clock::now()) = 0;
-    virtual int list_multiparts(const DoutPrefixProvider *dpp,
-                               const std::string& prefix,
-                               std::string& marker,
-                               const std::string& delim,
-                               const int& max_uploads,
-                               std::vector<std::unique_ptr<MultipartUpload>>& uploads,
-                               std::map<std::string, bool> *common_prefixes,
-                               bool *is_truncated) = 0;
-    virtual int abort_multiparts(const DoutPrefixProvider* dpp,
-                                CephContext* cct) = 0;
-
-    virtual rgw_bucket& get_key() = 0;
-    virtual RGWBucketInfo& get_info() = 0;
-
-    virtual void print(std::ostream& out) const = 0;
-
-    virtual bool operator==(const Bucket& b) const = 0;
-    virtual bool operator!=(const Bucket& b) const = 0;
-
-    friend class BucketList;
+                               ACLOwner owner={}, ceph::real_time mtime=real_clock::now()) override;
+  virtual int list_multiparts(const DoutPrefixProvider *dpp,
+                             const std::string& prefix,
+                             std::string& marker,
+                             const std::string& delim,
+                             const int& max_uploads,
+                             std::vector<std::unique_ptr<MultipartUpload>>& uploads,
+                             std::map<std::string, bool> *common_prefixes,
+                             bool *is_truncated) override;
+  virtual int abort_multiparts(const DoutPrefixProvider* dpp,
+                              CephContext* cct) override;
+
+  virtual rgw_bucket& get_key() override { return next->get_key(); }
+  virtual RGWBucketInfo& get_info() override { return next->get_info(); }
+
+  virtual void print(std::ostream& out) const override { return next->print(out); }
+
+  virtual bool operator==(const Bucket& b) const override { return next->operator==(b); }
+  virtual bool operator!=(const Bucket& b) const override { return next->operator!=(b); }
+
+  friend class BucketList;
+
+  /* Internal to Filters */
+  Bucket* get_next() { return next.get(); }
 };
 
 class FilterObject : public Object {
-  public:
+protected:
+  std::unique_ptr<Object> next;
+private:
+  Bucket* bucket{nullptr};
+
+public:
 
-    struct FilterOp : ReadOp {
-      virtual ~FilterOp() = default;
+  struct FilterReadOp : ReadOp {
+    std::unique_ptr<ReadOp> next;
 
-      virtual int prepare(optional_yield y, const DoutPrefixProvider* dpp) = 0;
-      virtual int read(int64_t ofs, int64_t end, bufferlist& bl, optional_yield y, const DoutPrefixProvider* dpp) = 0;
-      virtual int iterate(const DoutPrefixProvider* dpp, int64_t ofs, int64_t end, RGWGetDataCB* cb, optional_yield y) = 0;
-      virtual int get_attr(const DoutPrefixProvider* dpp, const char* name, bufferlist& dest, optional_yield y) = 0;
-    };
+    FilterReadOp(std::unique_ptr<ReadOp> _next) : next(std::move(_next)) {}
+    virtual ~FilterReadOp() = default;
+
+    virtual int prepare(optional_yield y, const DoutPrefixProvider* dpp) override;
+    virtual int read(int64_t ofs, int64_t end, bufferlist& bl, optional_yield y,
+                    const DoutPrefixProvider* dpp) override;
+    virtual int iterate(const DoutPrefixProvider* dpp, int64_t ofs, int64_t end,
+                       RGWGetDataCB* cb, optional_yield y) override;
+    virtual int get_attr(const DoutPrefixProvider* dpp, const char* name,
+                        bufferlist& dest, optional_yield y) override;
+  };
 
-    struct FilterOp : DeleteOp {
-      virtual ~FilterOp() = default;
+  struct FilterDeleteOp : DeleteOp {
+    std::unique_ptr<DeleteOp> next;
 
-      virtual int delete_obj(const DoutPrefixProvider* dpp, optional_yield y) = 0;
-    };
+    FilterDeleteOp(std::unique_ptr<DeleteOp> _next) : next(std::move(_next)) {}
+    virtual ~FilterDeleteOp() = default;
 
-    FilterObject() {}
-    virtual ~FilterObject() = default;
+    virtual int delete_obj(const DoutPrefixProvider* dpp, optional_yield y) override;
+  };
 
-    virtual int delete_object(const DoutPrefixProvider* dpp,
-                             optional_yield y,
-                             bool prevent_versioning = false) = 0;
-    virtual int delete_obj_aio(const DoutPrefixProvider* dpp, RGWObjState* astate, Completions* aio,
-                              bool keep_index_consistent, optional_yield y) = 0;
-    virtual int copy_object(User* user,
+  FilterObject(std::unique_ptr<Object> _next) : next(std::move(_next)) {}
+  FilterObject(std::unique_ptr<Object> _next, Bucket* _bucket) :
+                       next(std::move(_next)), bucket(_bucket) {}
+  FilterObject(FilterObject& _o) {
+    next = _o.next->clone();
+    bucket = _o.bucket;
+  }
+  virtual ~FilterObject() = default;
+
+  virtual int delete_object(const DoutPrefixProvider* dpp,
+                           optional_yield y,
+                           bool prevent_versioning = false) override;
+  virtual int delete_obj_aio(const DoutPrefixProvider* dpp, RGWObjState* astate,
+                            Completions* aio,
+                            bool keep_index_consistent, optional_yield y) override;
+  virtual int copy_object(User* user,
                req_info* info, const rgw_zone_id& source_zone,
-               rgw::sal::Object* dest_object, rgw::sal::Bucket* dest_bucket,
+              rgw::sal::Object* dest_object, rgw::sal::Bucket* dest_bucket,
                rgw::sal::Bucket* src_bucket,
                const rgw_placement_rule& dest_placement,
                ceph::real_time* src_mtime, ceph::real_time* mtime,
@@ -329,128 +565,153 @@ class FilterObject : public Object {
               boost::optional<ceph::real_time> delete_at,
                std::string* version_id, std::string* tag, std::string* etag,
                void (*progress_cb)(off_t, void *), void* progress_data,
-               const DoutPrefixProvider* dpp, optional_yield y) = 0;
-    virtual RGWAccessControlPolicy& get_acl(void) = 0;
-    virtual int set_acl(const RGWAccessControlPolicy& acl) = 0;
-    virtual void set_atomic() = 0;
-    virtual bool is_atomic() = 0;
-    virtual void set_prefetch_data() = 0;
-    virtual bool is_prefetch_data() = 0;
-    virtual void set_compressed() = 0;
-    virtual bool is_compressed() = 0;
-    virtual void invalidate() = 0;
-    virtual bool empty() const = 0;
-    virtual const std::string &get_name() const = 0;
-
-    virtual int get_obj_state(const DoutPrefixProvider* dpp, RGWObjState **state, optional_yield y, bool follow_olh = true) = 0;
-    virtual int set_obj_attrs(const DoutPrefixProvider* dpp, Attrs* setattrs, Attrs* delattrs, optional_yield y) = 0;
-    virtual int get_obj_attrs(optional_yield y, const DoutPrefixProvider* dpp, rgw_obj* target_obj = NULL) = 0;
-    virtual int modify_obj_attrs(const char* attr_name, bufferlist& attr_val, optional_yield y, const DoutPrefixProvider* dpp) = 0;
-    virtual int delete_obj_attrs(const DoutPrefixProvider* dpp, const char* attr_name, optional_yield y) = 0;
-    virtual bool is_expired() = 0;
-    virtual void gen_rand_obj_instance_name() = 0;
-    virtual MPSerializer* get_serializer(const DoutPrefixProvider *dpp, const std::string& lock_name) = 0;
-    virtual int transition(Bucket* bucket,
-                          const rgw_placement_rule& placement_rule,
-                          const real_time& mtime,
-                          uint64_t olh_epoch,
-                          const DoutPrefixProvider* dpp,
-                          optional_yield y) = 0;
-    virtual int transition_to_cloud(Bucket* bucket,
-                          rgw::sal::PlacementTier* tier,
-                          rgw_bucket_dir_entry& o,
-                          std::set<std::string>& cloud_targets,
-                          CephContext* cct,
-                          bool update_object,
-                          const DoutPrefixProvider* dpp,
-                          optional_yield y) = 0;
-    virtual bool placement_rules_match(rgw_placement_rule& r1, rgw_placement_rule& r2) = 0;
-    virtual int dump_obj_layout(const DoutPrefixProvider *dpp, optional_yield y, Formatter* f) = 0;
-
-    virtual Attrs& get_attrs(void) = 0;
-    virtual const Attrs& get_attrs(void) const = 0;
-    virtual int set_attrs(Attrs a) = 0;
-    virtual bool has_attrs(void) = 0;
-    virtual ceph::real_time get_mtime(void) const = 0;
-    virtual uint64_t get_obj_size(void) const = 0;
-    virtual Bucket* get_bucket(void) const = 0;
-    virtual void set_bucket(Bucket* b) = 0;
-    virtual std::string get_hash_source(void) = 0;
-    virtual void set_hash_source(std::string s) = 0;
-    virtual std::string get_oid(void) const = 0;
-    virtual bool get_delete_marker(void) = 0;
-    virtual bool get_in_extra_data(void) = 0;
-    virtual void set_in_extra_data(bool i) = 0;
-    int range_to_ofs(uint64_t obj_size, int64_t &ofs, int64_t &end);
-    virtual void set_obj_size(uint64_t s) = 0;
-    virtual void set_name(const std::string& n) = 0;
-    virtual void set_key(const rgw_obj_key& k) = 0;
-    virtual rgw_obj get_obj(void) const = 0;
-
-    virtual int swift_versioning_restore(bool& restored,   /* out */
-                                        const DoutPrefixProvider* dpp) = 0;
-    virtual int swift_versioning_copy(const DoutPrefixProvider* dpp,
-                                     optional_yield y) = 0;
-
-    virtual std::unique_ptr<ReadOp> get_read_op() = 0;
-    virtual std::unique_ptr<DeleteOp> get_delete_op() = 0;
-
-    virtual int omap_get_vals(const DoutPrefixProvider *dpp, const std::string& marker, uint64_t count,
-                             std::map<std::string, bufferlist>* m,
-                             bool* pmore, optional_yield y) = 0;
-    virtual int omap_get_all(const DoutPrefixProvider *dpp, std::map<std::string, bufferlist>* m,
-                            optional_yield y) = 0;
-    virtual int omap_get_vals_by_keys(const DoutPrefixProvider *dpp, const std::string& oid,
-                             const std::set<std::string>& keys,
-                             Attrs* vals) = 0;
-    virtual int omap_set_val_by_key(const DoutPrefixProvider *dpp, const std::string& key, bufferlist& val,
-                                   bool must_exist, optional_yield y) = 0;
-
-    virtual std::unique_ptr<Object> clone() = 0;
-
-    virtual rgw_obj_key& get_key() = 0;
-    virtual void set_instance(const std::string &i) = 0;
-    virtual const std::string &get_instance() const = 0;
-    virtual bool have_instance(void) = 0;
-    virtual void clear_instance() = 0;
-
-    virtual void print(std::ostream& out) const = 0;
+               const DoutPrefixProvider* dpp, optional_yield y) override;
+  virtual RGWAccessControlPolicy& get_acl(void) override;
+  virtual int set_acl(const RGWAccessControlPolicy& acl) override { return next->set_acl(acl); }
+  virtual void set_atomic() override { return next->set_atomic(); }
+  virtual bool is_atomic() override { return next->is_atomic(); }
+  virtual void set_prefetch_data() override { return next->set_prefetch_data(); }
+  virtual bool is_prefetch_data() override { return next->is_prefetch_data(); }
+  virtual void set_compressed() override { return next->set_compressed(); }
+  virtual bool is_compressed() override { return next->is_compressed(); }
+  virtual void invalidate() override { return next->invalidate(); }
+  virtual bool empty() const override { return next->empty(); }
+  virtual const std::string &get_name() const override { return next->get_name(); }
+
+  virtual int get_obj_state(const DoutPrefixProvider* dpp, RGWObjState **state,
+                           optional_yield y, bool follow_olh = true) override;
+  virtual int set_obj_attrs(const DoutPrefixProvider* dpp, Attrs* setattrs,
+                           Attrs* delattrs, optional_yield y) override;
+  virtual int get_obj_attrs(optional_yield y, const DoutPrefixProvider* dpp,
+                           rgw_obj* target_obj = NULL) override;
+  virtual int modify_obj_attrs(const char* attr_name, bufferlist& attr_val,
+                              optional_yield y, const DoutPrefixProvider* dpp) override;
+  virtual int delete_obj_attrs(const DoutPrefixProvider* dpp, const char* attr_name,
+                              optional_yield y) override;
+  virtual bool is_expired() override;
+  virtual void gen_rand_obj_instance_name() override;
+  virtual std::unique_ptr<MPSerializer> get_serializer(const DoutPrefixProvider *dpp,
+                                                      const std::string& lock_name) override;
+  virtual int transition(Bucket* bucket,
+                        const rgw_placement_rule& placement_rule,
+                        const real_time& mtime,
+                        uint64_t olh_epoch,
+                        const DoutPrefixProvider* dpp,
+                        optional_yield y) override;
+  virtual int transition_to_cloud(Bucket* bucket,
+                                 rgw::sal::PlacementTier* tier,
+                                 rgw_bucket_dir_entry& o,
+                                 std::set<std::string>& cloud_targets,
+                                 CephContext* cct,
+                                 bool update_object,
+                                 const DoutPrefixProvider* dpp,
+                                 optional_yield y) override;
+  virtual bool placement_rules_match(rgw_placement_rule& r1, rgw_placement_rule& r2) override;
+  virtual int dump_obj_layout(const DoutPrefixProvider *dpp, optional_yield y,
+                             Formatter* f) override;
+
+  virtual Attrs& get_attrs(void) override { return next->get_attrs(); };
+  virtual const Attrs& get_attrs(void) const override { return next->get_attrs(); };
+  virtual int set_attrs(Attrs a) override { return next->set_attrs(a); };
+  virtual bool has_attrs(void) override { return next->has_attrs(); };
+  virtual ceph::real_time get_mtime(void) const override { return next->get_mtime(); };
+  virtual uint64_t get_obj_size(void) const override { return next->get_obj_size(); };
+  virtual Bucket* get_bucket(void) const override { return bucket; };
+  virtual void set_bucket(Bucket* b) override;
+  virtual std::string get_hash_source(void) override { return next->get_hash_source(); };
+  virtual void set_hash_source(std::string s) override { return next->set_hash_source(s); };
+  virtual std::string get_oid(void) const override { return next->get_oid(); };
+  virtual bool get_delete_marker(void) override { return next->get_delete_marker(); };
+  virtual bool get_in_extra_data(void) override { return next->get_in_extra_data(); };
+  virtual void set_in_extra_data(bool i) override { return next->set_in_extra_data(i); };
+  int range_to_ofs(uint64_t obj_size, int64_t &ofs, int64_t &end) {
+    return next->range_to_ofs(obj_size, ofs, end);
+  };
+  virtual void set_obj_size(uint64_t s) override { return next->set_obj_size(s); };
+  virtual void set_name(const std::string& n) override { return next->set_name(n); };
+  virtual void set_key(const rgw_obj_key& k) override { return next->set_key(k); };
+  virtual rgw_obj get_obj(void) const override { return next->get_obj(); };
+  virtual rgw_obj_key& get_key() override { return next->get_key(); }
+  virtual void set_instance(const std::string &i) override { return next->set_instance(i); }
+  virtual const std::string &get_instance() const override { return next->get_instance(); }
+  virtual bool have_instance(void) override { return next->have_instance(); }
+  virtual void clear_instance() override { return next->clear_instance(); }
+
+  virtual int swift_versioning_restore(bool& restored,   /* out */
+                                      const DoutPrefixProvider* dpp) override;
+  virtual int swift_versioning_copy(const DoutPrefixProvider* dpp,
+                                   optional_yield y) override;
+
+  virtual std::unique_ptr<ReadOp> get_read_op() override;
+  virtual std::unique_ptr<DeleteOp> get_delete_op() override;
+
+  virtual int omap_get_vals(const DoutPrefixProvider *dpp, const std::string& marker,
+                           uint64_t count, std::map<std::string, bufferlist>* m,
+                           bool* pmore, optional_yield y) override;
+  virtual int omap_get_all(const DoutPrefixProvider *dpp,
+                          std::map<std::string, bufferlist>* m,
+                          optional_yield y) override;
+  virtual int omap_get_vals_by_keys(const DoutPrefixProvider *dpp,
+                                   const std::string& oid,
+                                   const std::set<std::string>& keys,
+                                   Attrs* vals) override;
+  virtual int omap_set_val_by_key(const DoutPrefixProvider *dpp,
+                                 const std::string& key, bufferlist& val,
+                                 bool must_exist, optional_yield y) override;
+
+  virtual std::unique_ptr<Object> clone() override {
+    return std::make_unique<FilterObject>(*this);
+  }
+
+  virtual void print(std::ostream& out) const override { return next->print(out); }
+
+  /* Internal to Filters */
+  Object* get_next() { return next.get(); }
 };
 
 class FilterMultipartPart : public MultipartPart {
+protected:
+  std::unique_ptr<MultipartPart> next;
+
 public:
-  FilterMultipartPart() = default;
+  FilterMultipartPart(std::unique_ptr<MultipartPart> _next) : next(std::move(_next)) {}
   virtual ~FilterMultipartPart() = default;
 
-  virtual uint32_t get_num() = 0;
-  virtual uint64_t get_size() = 0;
-  virtual const std::string& get_etag() = 0;
-  virtual ceph::real_time& get_mtime() = 0;
+  virtual uint32_t get_num() override { return next->get_num(); }
+  virtual uint64_t get_size() override { return next->get_size(); }
+  virtual const std::string& get_etag() override { return next->get_etag(); }
+  virtual ceph::real_time& get_mtime() override { return next->get_mtime(); }
 };
 
 class FilterMultipartUpload : public MultipartUpload {
+protected:
+  std::unique_ptr<MultipartUpload> next;
+  Bucket* bucket;
+  std::map<uint32_t, std::unique_ptr<MultipartPart>> parts;
+
 public:
-  FilterMultipartUpload() = default;
+  FilterMultipartUpload(std::unique_ptr<MultipartUpload> _next, Bucket* _b) :
+    next(std::move(_next)), bucket(_b) {}
   virtual ~FilterMultipartUpload() = default;
 
-  virtual const std::string& get_meta() const = 0;
-  virtual const std::string& get_key() const = 0;
-  virtual const std::string& get_upload_id() const = 0;
-  virtual const ACLOwner& get_owner() const = 0;
-  virtual ceph::real_time& get_mtime() = 0;
+  virtual const std::string& get_meta() const override { return next->get_meta(); }
+  virtual const std::string& get_key() const override { return next->get_key(); }
+  virtual const std::string& get_upload_id() const override { return next->get_upload_id(); }
+  virtual const ACLOwner& get_owner() const override { return next->get_owner(); }
+  virtual ceph::real_time& get_mtime() override { return next->get_mtime(); }
 
-  virtual std::map<uint32_t, std::unique_ptr<MultipartPart>>& get_parts() = 0;
+  virtual std::map<uint32_t, std::unique_ptr<MultipartPart>>& get_parts() override { return parts; }
 
-  virtual const jspan_context& get_trace() = 0;
+  virtual const jspan_context& get_trace() override { return next->get_trace(); }
 
-  virtual std::unique_ptr<rgw::sal::Object> get_meta_obj() = 0;
+  virtual std::unique_ptr<rgw::sal::Object> get_meta_obj() override;
 
-  virtual int init(const DoutPrefixProvider* dpp, optional_yield y, ACLOwner& owner, rgw_placement_rule& dest_placement, rgw::sal::Attrs& attrs) = 0;
+  virtual int init(const DoutPrefixProvider* dpp, optional_yield y, ACLOwner& owner, rgw_placement_rule& dest_placement, rgw::sal::Attrs& attrs) override;
   virtual int list_parts(const DoutPrefixProvider* dpp, CephContext* cct,
                         int num_parts, int marker,
                         int* next_marker, bool* truncated,
-                        bool assume_unsorted = false) = 0;
-  virtual int abort(const DoutPrefixProvider* dpp, CephContext* cct) = 0;
+                        bool assume_unsorted = false) override;
+  virtual int abort(const DoutPrefixProvider* dpp, CephContext* cct) override;
   virtual int complete(const DoutPrefixProvider* dpp,
                       optional_yield y, CephContext* cct,
                       std::map<int, std::string>& part_etags,
@@ -459,9 +720,11 @@ public:
                       RGWCompressionInfo& cs_info, off_t& ofs,
                       std::string& tag, ACLOwner& owner,
                       uint64_t olh_epoch,
-                      rgw::sal::Object* target_obj) = 0;
+                      rgw::sal::Object* target_obj) override;
 
-  virtual int get_info(const DoutPrefixProvider *dpp, optional_yield y, rgw_placement_rule** rule, rgw::sal::Attrs* attrs = nullptr) = 0;
+  virtual int get_info(const DoutPrefixProvider *dpp, optional_yield y,
+                      rgw_placement_rule** rule,
+                      rgw::sal::Attrs* attrs = nullptr) override;
 
   virtual std::unique_ptr<Writer> get_writer(const DoutPrefixProvider *dpp,
                          optional_yield y,
@@ -469,93 +732,122 @@ public:
                          const rgw_user& owner,
                          const rgw_placement_rule *ptail_placement_rule,
                          uint64_t part_num,
-                         const std::string& part_num_str) = 0;
-  virtual void print(std::ostream& out) const = 0;
+                         const std::string& part_num_str) override;
+  virtual void print(std::ostream& out) const override { return next->print(out); }
 };
 
 class FilterMPSerializer : public MPSerializer {
+protected:
+  std::unique_ptr<MPSerializer> next;
+
 public:
-  FilterMPSerializer() = default;
+  FilterMPSerializer(std::unique_ptr<MPSerializer> _next) : next(std::move(_next)) {}
   virtual ~FilterMPSerializer() = default;
 
-  virtual void clear_locked() = 0;
+  virtual int try_lock(const DoutPrefixProvider *dpp, utime_t dur, optional_yield y) override;
+  virtual int unlock() override { return next->unlock(); }
+  virtual void clear_locked() override { next->clear_locked(); }
+  virtual bool is_locked() override { return next->is_locked(); }
+  virtual void print(std::ostream& out) const override { return next->print(out); }
 };
 
 class FilterLCSerializer : public LCSerializer {
+protected:
+  std::unique_ptr<LCSerializer> next;
+
 public:
-  FilterLCSerializer() {}
+  FilterLCSerializer(std::unique_ptr<LCSerializer> _next) : next(std::move(_next)) {}
   virtual ~FilterLCSerializer() = default;
+
+  virtual int try_lock(const DoutPrefixProvider *dpp, utime_t dur, optional_yield y) override;
+  virtual int unlock() override { return next->unlock(); }
+  virtual void print(std::ostream& out) const override { return next->print(out); }
 };
 
 class FilterLifecycle : public Lifecycle {
+protected:
+  std::unique_ptr<Lifecycle> next;
+
 public:
   struct FilterLCHead : LCHead {
-    FilterLCHead() = default;
+    std::unique_ptr<LCHead> next;
+
+    FilterLCHead(std::unique_ptr<LCHead> _next) : next(std::move(_next)) {}
     virtual ~FilterLCHead() = default;
 
-    virtual time_t& get_start_date() = 0;
-    virtual void set_start_date(time_t) = 0;
-    virtual std::string& get_marker() = 0;
-    virtual void set_marker(const std::string&) = 0;
-    virtual time_t& get_shard_rollover_date() = 0;
-    virtual void set_shard_rollover_date(time_t) = 0;
+    virtual time_t& get_start_date() override { return next->get_start_date(); }
+    virtual void set_start_date(time_t t) override { next->set_start_date(t); }
+    virtual std::string& get_marker() override { return next->get_marker(); }
+    virtual void set_marker(const std::string& m) override { next->set_marker(m); }
+    virtual time_t& get_shard_rollover_date() override { return next->get_shard_rollover_date(); }
+    virtual void set_shard_rollover_date(time_t t) override { next->set_shard_rollover_date(t); }
   };
 
   struct FilterLCEntry : LCEntry {
-    FilterLCEntry() = default;
+    std::unique_ptr<LCEntry> next;
+
+    FilterLCEntry(std::unique_ptr<LCEntry> _next) : next(std::move(_next)) {}
     virtual ~FilterLCEntry() = default;
 
-    virtual std::string& get_bucket() = 0;
-    virtual void set_bucket(const std::string&) = 0;
-    virtual std::string& get_oid() = 0;
-    virtual void set_oid(const std::string&) = 0;
-    virtual uint64_t get_start_time() = 0;
-    virtual void set_start_time(uint64_t) = 0;
-    virtual uint32_t get_status() = 0;
-    virtual void set_status(uint32_t) = 0;
+    virtual std::string& get_bucket() override { return next->get_bucket(); }
+    virtual void set_bucket(const std::string& b) override { next->set_bucket(b); }
+    virtual std::string& get_oid() override { return next->get_oid(); }
+    virtual void set_oid(const std::string& o) override { next->set_oid(o); }
+    virtual uint64_t get_start_time() override { return next->get_start_time(); }
+    virtual void set_start_time(uint64_t t) override { next->set_start_time(t); }
+    virtual uint32_t get_status() override { return next->get_status(); }
+    virtual void set_status(uint32_t s) override { next->set_status(s); }
+    virtual void print(std::ostream& out) const override { return next->print(out); }
   };
 
-  FilterLifecycle() = default;
+  FilterLifecycle(std::unique_ptr<Lifecycle> _next) : next(std::move(_next)) {}
   virtual ~FilterLifecycle() = default;
 
-  virtual std::unique_ptr<LCEntry> get_entry() = 0;
-  virtual int get_entry(const std::string& oid, const std::string& marker, std::unique_ptr<LCEntry>* entry) = 0;
-  virtual int get_next_entry(const std::string& oid, const std::string& marker, std::unique_ptr<LCEntry>* entry) = 0;
-  virtual int set_entry(const std::string& oid, LCEntry& entry) = 0;
+  virtual std::unique_ptr<LCEntry> get_entry() override;
+  virtual int get_entry(const std::string& oid, const std::string& marker,
+                       std::unique_ptr<LCEntry>* entry) override;
+  virtual int get_next_entry(const std::string& oid, const std::string& marker,
+                            std::unique_ptr<LCEntry>* entry) override;
+  virtual int set_entry(const std::string& oid, LCEntry& entry) override;
   virtual int list_entries(const std::string& oid, const std::string& marker,
                           uint32_t max_entries,
-                          std::vector<std::unique_ptr<LCEntry>>& entries) = 0;
-  virtual int rm_entry(const std::string& oid, LCEntry& entry) = 0;
-  virtual int get_head(const std::string& oid, std::unique_ptr<LCHead>* head) = 0;
-  virtual int put_head(const std::string& oid, LCHead& head) = 0;
-  virtual LCSerializer* get_serializer(const std::string& lock_name, const std::string& oid, const std::string& cookie) = 0;
+                          std::vector<std::unique_ptr<LCEntry>>& entries) override;
+  virtual int rm_entry(const std::string& oid, LCEntry& entry) override;
+  virtual int get_head(const std::string& oid, std::unique_ptr<LCHead>* head) override;
+  virtual int put_head(const std::string& oid, LCHead& head) override;
+  virtual std::unique_ptr<LCSerializer> get_serializer(const std::string& lock_name,
+                                                      const std::string& oid,
+                                                      const std::string& cookie) override;
 };
 
 class FilterNotification : public Notification {
 protected:
-  Object* obj;
-  Object* src_obj;
-  rgw::notify::EventType event_type;
+  std::unique_ptr<Notification> next;
 
-  public:
-    FilterNotification(Object* _obj, Object* _src_obj, rgw::notify::EventType _type)
-      : obj(_obj), src_obj(_src_obj), event_type(_type)
-    {}
+public:
+  FilterNotification(std::unique_ptr<Notification> _next) : next(std::move(_next)) {}
 
-    virtual ~FilterNotification() = default;
+  virtual ~FilterNotification() = default;
 
-    virtual int publish_reserve(const DoutPrefixProvider *dpp, RGWObjTags* obj_tags = nullptr) = 0;
-    virtual int publish_commit(const DoutPrefixProvider* dpp, uint64_t size,
-                              const ceph::real_time& mtime, const std::string& etag, const std::string& version) = 0;
+  virtual int publish_reserve(const DoutPrefixProvider *dpp,
+                             RGWObjTags* obj_tags = nullptr) override;
+  virtual int publish_commit(const DoutPrefixProvider* dpp, uint64_t size,
+                            const ceph::real_time& mtime,
+                            const std::string& etag,
+                            const std::string& version) override;
 };
 
 class FilterWriter : public Writer {
+protected:
+  std::unique_ptr<Writer> next;
+  std::unique_ptr<Object> head_obj;
 public:
-  FilterWriter() {}
+  FilterWriter(std::unique_ptr<Writer> _next, std::unique_ptr<Object> _head_obj) :
+    next(std::move(_next)), head_obj(std::move(_head_obj)) {}
   virtual ~FilterWriter() = default;
 
-  virtual int prepare(optional_yield y) = 0;
-  virtual int process(bufferlist&& data, uint64_t offset) = 0;
+  virtual int prepare(optional_yield y) { return next->prepare(y); }
+  virtual int process(bufferlist&& data, uint64_t offset) override;
   virtual int complete(size_t accounted_size, const std::string& etag,
                        ceph::real_time *mtime, ceph::real_time set_mtime,
                        std::map<std::string, bufferlist>& attrs,
@@ -563,60 +855,21 @@ public:
                        const char *if_match, const char *if_nomatch,
                        const std::string *user_data,
                        rgw_zone_set *zones_trace, bool *canceled,
-                       optional_yield y) = 0;
-};
-
-class FilterPlacementTier : public PlacementTier {
-public:
-  virtual ~FilterPlacementTier() = default;
-
-  virtual const std::string& get_tier_type() = 0;
-  virtual const std::string& get_storage_class() = 0;
-  virtual bool retain_head_object() = 0;
-};
-
-class FilterZoneGroup : public ZoneGroup {
-public:
-  virtual ~FilterZoneGroup() = default;
-  virtual const std::string& get_id() const = 0;
-  virtual const std::string& get_name() const = 0;
-  virtual int equals(const std::string& other_zonegroup) const = 0;
-  virtual const std::string& get_endpoint() const = 0;
-  virtual bool placement_target_exists(std::string& target) const = 0;
-  virtual bool is_master_zonegroup() const = 0;
-  virtual const std::string& get_api_name() const = 0;
-  virtual int get_placement_target_names(std::set<std::string>& names) const = 0;
-  virtual const std::string& get_default_placement_name() const = 0;
-  virtual int get_hostnames(std::list<std::string>& names) const = 0;
-  virtual int get_s3website_hostnames(std::list<std::string>& names) const = 0;
-  virtual int get_zone_count() const = 0;
-  virtual int get_placement_tier(const rgw_placement_rule& rule, std::unique_ptr<PlacementTier>* tier) = 0;
-};
-
-class FilterZone : public Zone {
-  public:
-    virtual ~FilterZone() = default;
-
-    virtual ZoneGroup& get_zonegroup() = 0;
-    virtual int get_zonegroup(const std::string& id, std::unique_ptr<ZoneGroup>* zonegroup) = 0;
-    virtual const rgw_zone_id& get_id() = 0;
-    virtual const std::string& get_name() const = 0;
-    virtual bool is_writeable() = 0;
-    virtual bool get_redirect_endpoint(std::string* endpoint) = 0;
-    virtual bool has_zonegroup_api(const std::string& api) const = 0;
-    virtual const std::string& get_current_period_id() = 0;
-    virtual const RGWAccessKey& get_system_key() = 0;
-    virtual const std::string& get_realm_name() = 0;
-    virtual const std::string& get_realm_id() = 0;
+                       optional_yield y) override;
 };
 
 class FilterLuaScriptManager : public LuaScriptManager {
+protected:
+  std::unique_ptr<LuaScriptManager> next;
+
 public:
+  FilterLuaScriptManager(std::unique_ptr<LuaScriptManager> _next) : next(std::move(_next)) {}
   virtual ~FilterLuaScriptManager() = default;
 
-  virtual int get(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key, std::string& script) = 0;
-  virtual int put(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key, const std::string& script) = 0;
-  virtual int del(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key) = 0;
+  virtual int get(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key, std::string& script) override;
+  virtual int put(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key, const std::string& script) override;
+  virtual int del(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key) override;
 };
 
+
 } } // namespace rgw::sal
index c3784d2324f76e5047a60af055b0cb0de39cac04..fae89d8cd48d1fea2bbbce11bec0cfaaf63488c0 100644 (file)
@@ -403,6 +403,9 @@ public:
   }
   virtual int get_placement_tier(const rgw_placement_rule& rule, std::unique_ptr<PlacementTier>* tier);
   const RGWZoneGroup& get_group() { return group; }
+  virtual std::unique_ptr<ZoneGroup> clone() override {
+    return std::make_unique<MotrZoneGroup>(store, group);
+  }
 };
 
 class MotrZone : public StoreZone {
@@ -446,6 +449,9 @@ class MotrZone : public StoreZone {
     }
     ~MotrZone() = default;
 
+    virtual std::unique_ptr<Zone> clone() override {
+      return std::make_unique<MotrZone>(store);
+    }
     virtual ZoneGroup& get_zonegroup() override;
     virtual int get_zonegroup(const std::string& id, std::unique_ptr<ZoneGroup>* zonegroup) override;
     virtual const rgw_zone_id& get_id() override;
index 6d7c93c9ce14f554e86a5e5f69268b4fd1dc3e77..d3b53ecc7293a79629e151b381e04014b197cac2 100644 (file)
@@ -1243,8 +1243,9 @@ int RadosStore::get_raw_chunk_size(const DoutPrefixProvider* dpp, const rgw_raw_
 
 int RadosStore::initialize(CephContext *cct, const DoutPrefixProvider *dpp)
 {
-  RadosZoneGroup zg(this, svc()->zone->get_zonegroup());
-  zone = make_unique<RadosZone>(this, zg);
+  std::unique_ptr<ZoneGroup> zg =
+    std::make_unique<RadosZoneGroup>(this, svc()->zone->get_zonegroup());
+  zone = make_unique<RadosZone>(this, std::move(zg));
   return 0;
 }
 
@@ -2940,11 +2941,6 @@ int RadosZoneGroup::get_placement_tier(const rgw_placement_rule& rule,
   return 0;
 }
 
-ZoneGroup& RadosZone::get_zonegroup()
-{
-  return group;
-}
-
 int RadosZone::get_zonegroup(const std::string& id, std::unique_ptr<ZoneGroup>* zonegroup)
 {
   ZoneGroup* zg;
index edf2321aac9372f0ff1ff4ca688fe66e76e0c9af..8f72c70429c7c035ae4216b900da63a54b9ba716 100644 (file)
@@ -86,17 +86,23 @@ public:
   }
   virtual int get_placement_tier(const rgw_placement_rule& rule, std::unique_ptr<PlacementTier>* tier);
   const RGWZoneGroup& get_group() const { return group; }
+  virtual std::unique_ptr<ZoneGroup> clone() override {
+    return std::make_unique<RadosZoneGroup>(store, group);
+  }
 };
 
 class RadosZone : public StoreZone {
   protected:
     RadosStore* store;
-    RadosZoneGroup group;
+    std::unique_ptr<ZoneGroup> group;
   public:
-    RadosZone(RadosStore* _store, RadosZoneGroup _zg) : store(_store), group(_zg) {}
+    RadosZone(RadosStore* _store, std::unique_ptr<ZoneGroup> _zg) : store(_store), group(std::move(_zg)) {}
     ~RadosZone() = default;
 
-    virtual ZoneGroup& get_zonegroup() override;
+    virtual std::unique_ptr<Zone> clone() override {
+      return std::make_unique<RadosZone>(store, group->clone());
+    }
+    virtual ZoneGroup& get_zonegroup() override { return *(group.get()); }
     virtual int get_zonegroup(const std::string& id, std::unique_ptr<ZoneGroup>* zonegroup) override;
     virtual const rgw_zone_id& get_id() override;
     virtual const std::string& get_name() const override;