From eb86cd410df93fa9edb959e9d2db9a56410dd0f3 Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Thu, 30 Nov 2023 23:44:06 -0500 Subject: [PATCH] rgw/rados: add account metadata handler Signed-off-by: Casey Bodley --- src/rgw/driver/rados/account.cc | 192 +++++++++++++++++++++++++++ src/rgw/driver/rados/account.h | 6 + src/rgw/driver/rados/rgw_sal_rados.h | 4 +- src/rgw/driver/rados/rgw_service.cc | 11 +- src/rgw/driver/rados/rgw_service.h | 1 + 5 files changed, 211 insertions(+), 3 deletions(-) diff --git a/src/rgw/driver/rados/account.cc b/src/rgw/driver/rados/account.cc index acc4dee0c2360..f7c86099eee88 100644 --- a/src/rgw/driver/rados/account.cc +++ b/src/rgw/driver/rados/account.cc @@ -19,6 +19,8 @@ #include "common/errno.h" #include "rgw_account.h" #include "rgw_common.h" +#include "rgw_metadata.h" +#include "rgw_metadata_lister.h" #include "rgw_obj_types.h" #include "rgw_string.h" #include "rgw_tools.h" @@ -388,4 +390,194 @@ int remove(const DoutPrefixProvider* dpp, return 0; } + +// metadata abstraction + +struct CompleteInfo { + RGWAccountInfo info; + std::map attrs; + bool has_attrs = false; + + void dump(Formatter* f) const { + info.dump(f); + encode_json("attrs", attrs, f); + } + + void decode_json(JSONObj* obj) { + decode_json_obj(info, obj); + has_attrs = JSONDecoder::decode_json("attrs", attrs, obj); + } +}; + +class MetadataObject : public RGWMetadataObject { + CompleteInfo aci; + public: + MetadataObject(const CompleteInfo& aci, const obj_version& v, + ceph::real_time m) + : RGWMetadataObject(v, m), aci(aci) {} + + void dump(Formatter *f) const override { + aci.dump(f); + } + + CompleteInfo& get() { return aci; } +}; + + +class MetadataLister : public RGWMetadataLister { + public: + using RGWMetadataLister::RGWMetadataLister; + + void filter_transform(std::vector& oids, + std::list& keys) override + { + // remove the oid prefix from keys + constexpr auto trim = [] (const std::string& oid) { + return oid.substr(account_oid_prefix.size()); + }; + std::transform(oids.begin(), oids.end(), + std::back_inserter(keys), + trim); + } +}; + +class MetadataHandler : public RGWMetadataHandler { + RGWSI_SysObj& sysobj; + const RGWZoneParams& zone; + public: + MetadataHandler(RGWSI_SysObj& sysobj, const RGWZoneParams& zone) + : sysobj(sysobj), zone(zone) {} + + std::string get_type() override { return "account"; } + + RGWMetadataObject* get_meta_obj(JSONObj* obj, + const obj_version& objv, + const ceph::real_time& mtime) override + { + CompleteInfo aci; + try { + decode_json_obj(aci, obj); + } catch (const JSONDecoder::err&) { + return nullptr; + } + return new MetadataObject(aci, objv, mtime); + } + + int get(std::string& entry, RGWMetadataObject** obj, + optional_yield y, const DoutPrefixProvider* dpp) override + { + const std::string& account_id = entry; + CompleteInfo aci; + RGWObjVersionTracker objv; + ceph::real_time mtime; + + int r = read(dpp, y, sysobj, zone, account_id, + aci.info, aci.attrs, mtime, objv); + if (r < 0) { + return r; + } + + *obj = new MetadataObject(aci, objv.read_version, mtime); + return 0; + } + + int put(std::string& entry, RGWMetadataObject* obj, + RGWObjVersionTracker& objv, optional_yield y, + const DoutPrefixProvider* dpp, + RGWMDLogSyncType type, bool from_remote_zone) override + { + const std::string& account_id = entry; + auto account_obj = static_cast(obj); + const auto& new_info = account_obj->get().info; + + // account id must match metadata key + if (new_info.id != account_id) { + return -EINVAL; + } + + // read existing metadata + RGWAccountInfo old_info; + std::map old_attrs; + ceph::real_time old_mtime; + int r = read(dpp, y, sysobj, zone, account_id, + old_info, old_attrs, old_mtime, objv); + if (r < 0 && r != -ENOENT) { + return r; + } + const RGWAccountInfo* pold_info = (r == -ENOENT ? nullptr : &old_info); + + // write/overwrite metadata + constexpr bool exclusive = false; + return write(dpp, y, sysobj, zone, new_info, pold_info, + account_obj->get().attrs, obj->get_mtime(), + exclusive, objv); + } + + int remove(std::string& entry, RGWObjVersionTracker& objv, + optional_yield y, const DoutPrefixProvider* dpp) override + { + const std::string& account_id = entry; + + // read existing metadata + RGWAccountInfo info; + std::map attrs; + ceph::real_time mtime; + int r = read(dpp, y, sysobj, zone, account_id, + info, attrs, mtime, objv); + if (r < 0) { + return r; + } + + return account::remove(dpp, y, sysobj, zone, info, objv); + } + + int mutate(const std::string& entry, + const ceph::real_time& mtime, + RGWObjVersionTracker* objv, + optional_yield y, + const DoutPrefixProvider* dpp, + RGWMDLogStatus op_type, + std::function f) override + { + return -ENOTSUP; // unused + } + + int list_keys_init(const DoutPrefixProvider* dpp, + const std::string& marker, void** phandle) override + { + auto lister = std::make_unique( + sysobj.get_pool(zone.account_pool)); + int r = lister->init(dpp, marker, account_oid_prefix); + if (r < 0) { + return r; + } + *phandle = lister.release(); + return 0; + } + + int list_keys_next(const DoutPrefixProvider* dpp, void* handle, int max, + std::list& keys, bool* truncated) override + { + auto lister = static_cast(handle); + return lister->get_next(dpp, max, keys, truncated); + } + + void list_keys_complete(void* handle) override + { + delete static_cast(handle); + } + + std::string get_marker(void* handle) override + { + auto lister = static_cast(handle); + return lister->get_marker(); + } +}; + +auto create_metadata_handler(RGWSI_SysObj& sysobj, const RGWZoneParams& zone) + -> std::unique_ptr +{ + return std::make_unique(sysobj, zone); +} + } // namespace rgwrados::account diff --git a/src/rgw/driver/rados/account.h b/src/rgw/driver/rados/account.h index 4bae82271f084..c73d68bc626d3 100644 --- a/src/rgw/driver/rados/account.h +++ b/src/rgw/driver/rados/account.h @@ -17,6 +17,7 @@ #include #include +#include #include #include "include/encoding.h" #include "common/async/yield_context.h" @@ -27,6 +28,7 @@ class JSONObj; struct rgw_raw_obj; class RGWAccountInfo; struct RGWBucketInfo; +class RGWMetadataHandler; class RGWObjVersionTracker; class RGWSI_SysObj; class RGWStorageStats; @@ -34,6 +36,10 @@ class RGWZoneParams; namespace rgwrados::account { +/// Account metadata handler factory +auto create_metadata_handler(RGWSI_SysObj& sysobj, const RGWZoneParams& zone) + -> std::unique_ptr; + /// Return the rados object that tracks the given account's buckets. This /// can be used with the cls_user interface in namespace rgwrados::buckets. rgw_raw_obj get_buckets_obj(const RGWZoneParams& zone, diff --git a/src/rgw/driver/rados/rgw_sal_rados.h b/src/rgw/driver/rados/rgw_sal_rados.h index 9529799882805..83ba68832b3a6 100644 --- a/src/rgw/driver/rados/rgw_sal_rados.h +++ b/src/rgw/driver/rados/rgw_sal_rados.h @@ -725,7 +725,7 @@ protected: class MPRadosSerializer : public StoreMPSerializer { librados::IoCtx ioctx; - rados::cls::lock::Lock lock; + ::rados::cls::lock::Lock lock; librados::ObjectWriteOperation op; public: @@ -739,7 +739,7 @@ public: class LCRadosSerializer : public StoreLCSerializer { librados::IoCtx* ioctx; - rados::cls::lock::Lock lock; + ::rados::cls::lock::Lock lock; public: LCRadosSerializer(RadosStore* store, const std::string& oid, const std::string& lock_name, const std::string& cookie); diff --git a/src/rgw/driver/rados/rgw_service.cc b/src/rgw/driver/rados/rgw_service.cc index e0d885b86a6e9..8d726431fba7f 100644 --- a/src/rgw/driver/rados/rgw_service.cc +++ b/src/rgw/driver/rados/rgw_service.cc @@ -29,6 +29,7 @@ #include "common/errno.h" +#include "account.h" #include "rgw_bucket.h" #include "rgw_cr_rados.h" #include "rgw_datalog.h" @@ -391,6 +392,8 @@ int RGWCtlDef::init(RGWServices& svc, rgw::sal::Driver* driver, const DoutPrefix meta.otp.reset(RGWOTPMetaHandlerAllocator::alloc()); meta.role = std::make_unique(driver, svc.role); + meta.account = rgwrados::account::create_metadata_handler( + *svc.sysobj, svc.zone->get_zone_params()); user.reset(new RGWUserCtl(svc.zone, svc.user, (RGWUserMetadataHandler *)meta.user.get())); bucket.reset(new RGWBucketCtl(svc.zone, @@ -477,7 +480,13 @@ int RGWCtl::init(RGWServices *_svc, rgw::sal::Driver* driver, const DoutPrefixPr r = meta.role->attach(meta.mgr); if (r < 0) { - ldout(cct, 0) << "ERROR: failed to start init otp ctl (" << cpp_strerror(-r) << dendl; + ldout(cct, 0) << "ERROR: failed to start init meta.role ctl (" << cpp_strerror(-r) << dendl; + return r; + } + + r = _ctl.meta.account->attach(meta.mgr); + if (r < 0) { + ldout(cct, 0) << "ERROR: failed to start init meta.account ctl (" << cpp_strerror(-r) << dendl; return r; } r = meta.topic->attach(meta.mgr); diff --git a/src/rgw/driver/rados/rgw_service.h b/src/rgw/driver/rados/rgw_service.h index ebab083f27ec7..c2da007b0fee6 100644 --- a/src/rgw/driver/rados/rgw_service.h +++ b/src/rgw/driver/rados/rgw_service.h @@ -197,6 +197,7 @@ struct RGWCtlDef { std::unique_ptr otp; std::unique_ptr role; std::unique_ptr topic; + std::unique_ptr account; std::unique_ptr> topic_cache; -- 2.39.5