// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab ft=cpp
+#include "rgw_user.h"
#include "common/errno.h"
-#include "rgw_user.h"
#include "rgw_account.h"
#include "rgw_bucket.h"
+#include "rgw_metadata.h"
+#include "rgw_metadata_lister.h"
#include "rgw_quota.h"
#include "rgw_rest_iam.h" // validate_iam_user_name()
return 0;
}
-class RGWUserMetadataHandler : public RGWMetadataHandler_GenericMetaBE {
-public:
- struct Svc {
- RGWSI_User *user{nullptr};
- } svc;
+struct RGWUserCompleteInfo {
+ RGWUserInfo info;
+ std::map<std::string, bufferlist> attrs;
+ bool has_attrs{false};
- RGWUserMetadataHandler(RGWSI_User *user_svc) {
- base_init(user_svc->ctx(), user_svc->get_be_handler());
- svc.user = user_svc;
+ void dump(Formatter * const f) const {
+ info.dump(f);
+ encode_json("attrs", attrs, f);
}
- ~RGWUserMetadataHandler() {}
-
- string get_type() override { return "user"; }
+ void decode_json(JSONObj *obj) {
+ decode_json_obj(info, obj);
+ has_attrs = JSONDecoder::decode_json("attrs", attrs, obj);
+ }
+};
- int do_get(RGWSI_MetaBackend_Handler::Op *op, string& entry, RGWMetadataObject **obj, optional_yield y, const DoutPrefixProvider *dpp) override {
- RGWUserCompleteInfo uci;
- RGWObjVersionTracker objv_tracker;
- real_time mtime;
+class RGWUserMetadataObject : public RGWMetadataObject {
+ RGWUserCompleteInfo uci;
+public:
+ RGWUserMetadataObject(const RGWUserCompleteInfo& uci,
+ const obj_version& v, ceph::real_time m)
+ : RGWMetadataObject(v, m), uci(uci) {}
- rgw_user user = RGWSI_User::user_from_meta_key(entry);
+ void dump(Formatter *f) const override {
+ uci.dump(f);
+ }
- int ret = svc.user->read_user_info(user, &uci.info, &objv_tracker,
- &mtime, nullptr, &uci.attrs,
- y, dpp);
- if (ret < 0) {
- return ret;
- }
+ RGWUserCompleteInfo& get_uci() {
+ return uci;
+ }
+};
- RGWUserMetadataObject *mdo = new RGWUserMetadataObject(uci, objv_tracker.read_version, mtime);
- *obj = mdo;
+class RGWUserMetadataHandler : public RGWMetadataHandler {
+ RGWSI_User *svc_user{nullptr};
+ public:
+ explicit RGWUserMetadataHandler(RGWSI_User* svc_user)
+ : svc_user(svc_user) {}
- return 0;
- }
+ string get_type() override { return "user"; }
- RGWMetadataObject *get_meta_obj(JSONObj *jo, const obj_version& objv, const ceph::real_time& mtime) override {
+ RGWMetadataObject *get_meta_obj(JSONObj *jo, const obj_version& objv,
+ const ceph::real_time& mtime) override {
RGWUserCompleteInfo uci;
try {
return new RGWUserMetadataObject(uci, objv, mtime);
}
- int do_put(RGWSI_MetaBackend_Handler::Op *op, string& entry,
- RGWMetadataObject *obj,
- RGWObjVersionTracker& objv_tracker,
- optional_yield y, const DoutPrefixProvider *dpp,
- RGWMDLogSyncType type, bool from_remote_zone) override;
-
- int do_remove(RGWSI_MetaBackend_Handler::Op *op, string& entry, RGWObjVersionTracker& objv_tracker,
- optional_yield y, const DoutPrefixProvider *dpp) override {
- RGWUserInfo info;
+ int get(std::string& entry, RGWMetadataObject** obj, optional_yield y,
+ const DoutPrefixProvider *dpp) override;
+ int put(std::string& entry, RGWMetadataObject* obj,
+ RGWObjVersionTracker& objv_tracker,
+ optional_yield y, const DoutPrefixProvider* dpp,
+ RGWMDLogSyncType type, bool from_remote_zone) override;
+ int remove(std::string& entry, RGWObjVersionTracker& objv_tracker,
+ optional_yield y, const DoutPrefixProvider *dpp) override;
+
+ int mutate(const std::string& entry, const ceph::real_time& mtime,
+ RGWObjVersionTracker* objv_tracker, optional_yield y,
+ const DoutPrefixProvider* dpp, RGWMDLogStatus op_type,
+ std::function<int()> f) override;
+
+ int list_keys_init(const DoutPrefixProvider* dpp, const std::string& marker,
+ void** phandle) override;
+ int list_keys_next(const DoutPrefixProvider* dpp, void* handle, int max,
+ std::list<std::string>& keys, bool* truncated) override;
+ void list_keys_complete(void *handle) override;
+ std::string get_marker(void *handle) override;
+};
- rgw_user user = RGWSI_User::user_from_meta_key(entry);
+int RGWUserMetadataHandler::get(std::string& entry, RGWMetadataObject **obj,
+ optional_yield y, const DoutPrefixProvider *dpp)
+{
+ RGWUserCompleteInfo uci;
+ RGWObjVersionTracker objv_tracker;
+ real_time mtime;
- int ret = svc.user->read_user_info(user, &info, nullptr,
- nullptr, nullptr, nullptr,
- y, dpp);
- if (ret < 0) {
- return ret;
- }
+ rgw_user user = RGWSI_User::user_from_meta_key(entry);
- return svc.user->remove_user_info(info, &objv_tracker, y, dpp);
+ int ret = svc_user->read_user_info(user, &uci.info, &objv_tracker,
+ &mtime, nullptr, &uci.attrs,
+ y, dpp);
+ if (ret < 0) {
+ return ret;
}
-};
-class RGWMetadataHandlerPut_User : public RGWMetadataHandlerPut_SObj
+ *obj = new RGWUserMetadataObject(uci, objv_tracker.read_version, mtime);
+ return 0;
+}
+
+int RGWUserMetadataHandler::put(std::string& entry, RGWMetadataObject *obj,
+ RGWObjVersionTracker& objv_tracker,
+ optional_yield y, const DoutPrefixProvider *dpp,
+ RGWMDLogSyncType type, bool from_remote_zone)
{
- RGWUserMetadataHandler *uhandler;
- RGWUserMetadataObject *uobj;
-public:
- RGWMetadataHandlerPut_User(RGWUserMetadataHandler *_handler,
- RGWSI_MetaBackend_Handler::Op *op, string& entry,
- RGWMetadataObject *obj, RGWObjVersionTracker& objv_tracker,
- optional_yield y,
- RGWMDLogSyncType type, bool from_remote_zone) : RGWMetadataHandlerPut_SObj(_handler, op, entry, obj, objv_tracker, y, type, from_remote_zone),
- uhandler(_handler) {
- uobj = static_cast<RGWUserMetadataObject *>(obj);
+ const rgw_user user = RGWSI_User::user_from_meta_key(entry);
+
+ // read existing user info
+ std::optional old = RGWUserCompleteInfo{};
+ int ret = svc_user->read_user_info(user, &old->info, &objv_tracker,
+ nullptr, nullptr, &old->attrs, y, dpp);
+ if (ret == -ENOENT) {
+ old = std::nullopt;
+ } else if (ret < 0) {
+ return ret;
}
+ RGWUserInfo* pold_info = (old ? &old->info : nullptr);
- int put_checked(const DoutPrefixProvider *dpp) override;
-};
+ // store the updated user info
+ auto newobj = static_cast<RGWUserMetadataObject*>(obj);
+ RGWUserCompleteInfo& uci = newobj->get_uci();
+ auto pattrs = (uci.has_attrs ? &uci.attrs : nullptr);
+ auto mtime = obj->get_mtime();
-int RGWUserMetadataHandler::do_put(RGWSI_MetaBackend_Handler::Op *op, string& entry,
- RGWMetadataObject *obj,
- RGWObjVersionTracker& objv_tracker,
- optional_yield y, const DoutPrefixProvider *dpp,
- RGWMDLogSyncType type, bool from_remote_zone)
-{
- RGWMetadataHandlerPut_User put_op(this, op, entry, obj, objv_tracker, y, type, from_remote_zone);
- return do_put_operate(&put_op, dpp);
+ ret = svc_user->store_user_info(uci.info, pold_info, &objv_tracker,
+ mtime, false, pattrs, y, dpp);
+ if (ret < 0) {
+ return ret;
+ }
+
+ return STATUS_APPLIED;
}
-int RGWMetadataHandlerPut_User::put_checked(const DoutPrefixProvider *dpp)
+int RGWUserMetadataHandler::remove(std::string& entry, RGWObjVersionTracker& objv_tracker,
+ optional_yield y, const DoutPrefixProvider *dpp)
{
- RGWUserMetadataObject *orig_obj = static_cast<RGWUserMetadataObject *>(old_obj);
- RGWUserCompleteInfo& uci = uobj->get_uci();
+ RGWUserInfo info;
- map<string, bufferlist> *pattrs{nullptr};
- if (uci.has_attrs) {
- pattrs = &uci.attrs;
+ rgw_user user = RGWSI_User::user_from_meta_key(entry);
+
+ int ret = svc_user->read_user_info(user, &info, nullptr,
+ nullptr, nullptr, nullptr,
+ y, dpp);
+ if (ret < 0) {
+ return ret;
}
- RGWUserInfo *pold_info = (orig_obj ? &orig_obj->get_uci().info : nullptr);
+ return svc_user->remove_user_info(info, &objv_tracker, y, dpp);
+};
- auto mtime = obj->get_mtime();
+int RGWUserMetadataHandler::mutate(const std::string& entry, const ceph::real_time& mtime,
+ RGWObjVersionTracker* objv_tracker, optional_yield y,
+ const DoutPrefixProvider* dpp, RGWMDLogStatus op_type,
+ std::function<int()> f)
+{
+ return -ENOTSUP; // unused
+}
- int ret = uhandler->svc.user->store_user_info(uci.info, pold_info,
- &objv_tracker, mtime,
- false, pattrs, y, dpp);
+int RGWUserMetadataHandler::list_keys_init(const DoutPrefixProvider* dpp,
+ const std::string& marker,
+ void** phandle)
+{
+ std::unique_ptr<RGWMetadataLister> lister;
+ int ret = svc_user->create_lister(dpp, marker, lister);
if (ret < 0) {
return ret;
}
+ *phandle = lister.release(); // release ownership
+ return 0;
+}
- return STATUS_APPLIED;
+int RGWUserMetadataHandler::list_keys_next(const DoutPrefixProvider* dpp,
+ void* handle, int max,
+ std::list<std::string>& keys,
+ bool* truncated)
+{
+ auto lister = static_cast<RGWMetadataLister*>(handle);
+ return lister->get_next(dpp, max, keys, truncated);
+}
+
+void RGWUserMetadataHandler::list_keys_complete(void *handle)
+{
+ delete static_cast<RGWMetadataLister*>(handle);
+}
+
+std::string RGWUserMetadataHandler::get_marker(void *handle)
+{
+ auto lister = static_cast<RGWMetadataLister*>(handle);
+ return lister->get_marker();
}
-RGWUserCtl::RGWUserCtl(RGWSI_Zone *zone_svc,
- RGWSI_User *user_svc,
- RGWUserMetadataHandler *_umhandler) : umhandler(_umhandler) {
+RGWUserCtl::RGWUserCtl(RGWSI_Zone *zone_svc, RGWSI_User *user_svc)
+{
svc.zone = zone_svc;
svc.user = user_svc;
- be_handler = umhandler->get_be_handler();
}
template <class T>
return svc.user->remove_user_info(info, params.objv_tracker, y, dpp);
}
-RGWMetadataHandler *RGWUserMetaHandlerAllocator::alloc(RGWSI_User *user_svc) {
- return new RGWUserMetadataHandler(user_svc);
+auto create_user_metadata_handler(RGWSI_User *user_svc)
+ -> std::unique_ptr<RGWMetadataHandler>
+{
+ return std::make_unique<RGWUserMetadataHandler>(user_svc);
}
void rgw_user::dump(Formatter *f) const
#include "svc_user.h"
#include "svc_user_rados.h"
+#include "svc_mdlog.h"
#include "svc_zone.h"
#include "svc_sys_obj.h"
#include "svc_sys_obj_cache.h"
#include "svc_meta.h"
-#include "svc_meta_be_sobj.h"
-#include "svc_sync_modules.h"
#include "rgw_user.h"
#include "rgw_account.h"
#include "rgw_bucket.h"
+#include "rgw_metadata_lister.h"
#include "rgw_tools.h"
#include "rgw_zone.h"
#include "rgw_rados.h"
using namespace std;
-class RGWSI_User_Module : public RGWSI_MBSObj_Handler_Module {
- RGWSI_User_RADOS::Svc& svc;
-
- const string prefix;
-public:
- RGWSI_User_Module(RGWSI_User_RADOS::Svc& _svc) : RGWSI_MBSObj_Handler_Module("user"),
- svc(_svc) {}
-
- void get_pool_and_oid(const string& key, rgw_pool *pool, string *oid) override {
- if (pool) {
- *pool = svc.zone->get_zone_params().user_uid_pool;
- }
- if (oid) {
- *oid = key;
- }
- }
-
- const string& get_oid_prefix() override {
- return prefix;
- }
-
- bool is_valid_oid(const string& oid) override {
- // filter out the user.buckets objects
- return !boost::algorithm::ends_with(oid, RGW_BUCKETS_OBJ_SUFFIX);
- }
-
- string key_to_oid(const string& key) override {
- return key;
- }
-
- string oid_to_key(const string& oid) override {
- return oid;
- }
-};
-
RGWSI_User_RADOS::RGWSI_User_RADOS(CephContext *cct): RGWSI_User(cct) {
}
}
void RGWSI_User_RADOS::init(librados::Rados* rados_,
- RGWSI_Zone *_zone_svc, RGWSI_SysObj *_sysobj_svc,
- RGWSI_SysObj_Cache *_cache_svc, RGWSI_Meta *_meta_svc,
- RGWSI_MetaBackend *_meta_be_svc,
- RGWSI_SyncModules *_sync_modules_svc)
+ RGWSI_Zone *_zone_svc,
+ RGWSI_MDLog *mdlog_svc,
+ RGWSI_SysObj *_sysobj_svc,
+ RGWSI_SysObj_Cache *_cache_svc,
+ RGWSI_Meta *_meta_svc)
{
svc.user = this;
rados = rados_;
svc.zone = _zone_svc;
+ svc.mdlog = mdlog_svc;
svc.sysobj = _sysobj_svc;
svc.cache = _cache_svc;
svc.meta = _meta_svc;
- svc.meta_be = _meta_be_svc;
- svc.sync_modules = _sync_modules_svc;
}
int RGWSI_User_RADOS::do_start(optional_yield, const DoutPrefixProvider *dpp)
{
uinfo_cache.reset(new RGWChainedCacheImpl<user_info_cache_entry>);
uinfo_cache->init(svc.cache);
-
- int r = svc.meta->create_be_handler(RGWSI_MetaBackend::Type::MDBE_SOBJ, &be_handler);
- if (r < 0) {
- ldpp_dout(dpp, 0) << "ERROR: failed to create be handler: r=" << r << dendl;
- return r;
- }
-
- RGWSI_MetaBackend_Handler_SObj *bh = static_cast<RGWSI_MetaBackend_Handler_SObj *>(be_handler);
-
- auto module = new RGWSI_User_Module(svc);
- be_module.reset(module);
- bh->set_module(module);
return 0;
}
return rgw_raw_obj(svc.zone->get_zone_params().user_uid_pool, oid);
}
+class UserLister : public RGWMetadataLister {
+ public:
+ using RGWMetadataLister::RGWMetadataLister;
+
+ void filter_transform(std::vector<std::string>& oids,
+ std::list<std::string>& keys) override
+ {
+ // filter out the user.buckets objects
+ constexpr auto filter = [] (const std::string& oid) {
+ return oid.ends_with(RGW_BUCKETS_OBJ_SUFFIX);
+ };
+ // 'oids' is mutable so we can move its elements instead of copying
+ std::remove_copy_if(std::make_move_iterator(oids.begin()),
+ std::make_move_iterator(oids.end()),
+ std::back_inserter(keys), filter);
+ }
+};
+
+int RGWSI_User_RADOS::create_lister(const DoutPrefixProvider* dpp,
+ const std::string& marker,
+ std::unique_ptr<RGWMetadataLister>& lister)
+{
+ const rgw_pool& pool = svc.zone->get_zone_params().user_uid_pool;
+ auto p = std::make_unique<UserLister>(svc.sysobj->get_pool(pool));
+ int r = p->init(dpp, marker, ""); // empty prefix
+ if (r < 0) {
+ return r;
+ }
+ lister = std::move(p);
+ return 0;
+}
+
int RGWSI_User_RADOS::read_user_info(const rgw_user& user,
RGWUserInfo *info,
RGWObjVersionTracker * const objv_tracker,
if (ot.write_version.tag.empty()) {
if (ot.read_version.tag.empty()) {
- ot.generate_new_write_ver(svc.meta_be->ctx());
+ ot.generate_new_write_ver(dpp->get_cct());
} else {
ot.write_version = ot.read_version;
ot.write_version.ver++;
const rgw_pool& pool = svc.zone->get_zone_params().user_uid_pool;
const std::string key = RGWSI_User::get_meta_key(info.user_id);
- return rgw_put_system_obj(dpp, svc.sysobj, pool, key, data_bl,
- exclusive, &ot, mtime, y, pattrs);
+ int r = rgw_put_system_obj(dpp, svc.sysobj, pool, key, data_bl,
+ exclusive, &ot, mtime, y, pattrs);
+ if (r < 0) {
+ return r;
+ }
+ return svc.mdlog->complete_entry(dpp, y, "user", key, &ot);
}
int complete(const DoutPrefixProvider *dpp) {
const rgw_pool& pool = svc.zone->get_zone_params().user_uid_pool;
const std::string key = get_meta_key(user_info.user_id);
int ret = rgw_delete_system_obj(dpp, svc.sysobj, pool, key, objv_tracker, y);
- if (ret < 0 && ret != -ENOENT && ret != -ECANCELED) {
+ if (ret == -ENOENT || ret == -ECANCELED) {
+ return 0; // success but no mdlog entry
+ }
+ if (ret < 0) {
ldpp_dout(dpp, 0) << "ERROR: could not remove " << user_info.user_id
<< ": " << cpp_strerror(ret) << dendl;
return ret;
}
- return 0;
+ return svc.mdlog->complete_entry(dpp, y, "user", key, objv_tracker);
}
static int read_index(const DoutPrefixProvider* dpp, optional_yield y,