From 7f5f1ec12d23288e571643ceca4fde2315bad185 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Wed, 19 Oct 2011 14:58:22 -0700 Subject: [PATCH] rgw: implement swift metadata POST --- src/rgw/rgw_access.h | 5 ++-- src/rgw/rgw_fs.cc | 3 +- src/rgw/rgw_fs.h | 3 +- src/rgw/rgw_op.cc | 62 ++++++++++++++++++++++++++++++++++----- src/rgw/rgw_op.h | 17 +++++++++++ src/rgw/rgw_rados.cc | 10 ++++++- src/rgw/rgw_rados.h | 3 +- src/rgw/rgw_rest.h | 7 +++++ src/rgw/rgw_rest_swift.cc | 18 ++++++++++++ src/rgw/rgw_rest_swift.h | 10 ++++++- 10 files changed, 123 insertions(+), 15 deletions(-) diff --git a/src/rgw/rgw_access.h b/src/rgw/rgw_access.h index 7020302db3839..2b6d08136dbfc 100644 --- a/src/rgw/rgw_access.h +++ b/src/rgw/rgw_access.h @@ -72,7 +72,8 @@ public: /** write an object to the storage device in the appropriate pool with the given stats */ virtual int put_obj_meta(void *ctx, std::string& id, rgw_obj& obj, uint64_t size, time_t *mtime, - map& attrs, RGWObjCategory category, bool exclusive) = 0; + map& attrs, RGWObjCategory category, bool exclusive, + map* rmattrs) = 0; virtual int put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data, off_t ofs, size_t len) = 0; virtual int aio_put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data, @@ -83,7 +84,7 @@ public: time_t *mtime, map& attrs) { int ret = put_obj_data(ctx, id, obj, data, -1, len); if (ret >= 0) { - ret = put_obj_meta(ctx, id, obj, len, mtime, attrs, RGW_OBJ_CATEGORY_NONE, false); + ret = put_obj_meta(ctx, id, obj, len, mtime, attrs, RGW_OBJ_CATEGORY_NONE, false, NULL); } return ret; } diff --git a/src/rgw/rgw_fs.cc b/src/rgw/rgw_fs.cc index 21b714e3edd74..06e624dd580ff 100644 --- a/src/rgw/rgw_fs.cc +++ b/src/rgw/rgw_fs.cc @@ -206,7 +206,8 @@ int RGWFS::create_bucket(std::string& id, rgw_bucket& bucket, map& attrs, - RGWObjCategory category, bool exclusive) + RGWObjCategory category, bool exclusive, + map *rmattrs) { rgw_bucket& bucket = obj.bucket; std::string& oid = obj.object; diff --git a/src/rgw/rgw_fs.h b/src/rgw/rgw_fs.h index ce91624afb16e..664951ca54156 100644 --- a/src/rgw/rgw_fs.h +++ b/src/rgw/rgw_fs.h @@ -20,7 +20,8 @@ public: int create_bucket(std::string& id, rgw_bucket& bucket, map& attrs, bool system_bucket, bool exclusive, uint64_t auid=0); int put_obj_meta(void *ctx, std::string& id, rgw_obj& obj, uint64_t size, time_t *mtime, - map& attrs, RGWObjCategory category, bool exclusive); + map& attrs, RGWObjCategory category, bool exclusive, + map *rmattrs); int put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data, off_t ofs, size_t size); int copy_obj(void *ctx, std::string& id, rgw_obj& dest_obj, diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index b3b3e93134175..0164e3c62b24a 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -163,6 +163,15 @@ static int get_policy_from_attr(void *ctx, RGWAccessControlPolicy *policy, rgw_o return ret; } +static int get_obj_attrs(struct req_state *s, rgw_obj& obj, map& attrs) +{ + void *handle; + int ret = rgwstore->prepare_get_obj(s->obj_ctx, obj, 0, NULL, &attrs, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, &handle, &s->err); + rgwstore->finish_get_obj(&handle); + return ret; +} + int read_acls(struct req_state *s, RGWAccessControlPolicy *policy, rgw_bucket& bucket, string& object) { string upload_id; @@ -771,7 +780,7 @@ void RGWPutObj::execute() goto done; } } else { - ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, obj, s->obj_size, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false); + ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, obj, s->obj_size, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false, NULL); if (ret < 0) goto done_err; @@ -802,6 +811,47 @@ done_err: send_response(); } +int RGWPutObjMetadata::verify_permission() +{ + if (!::verify_permission(s, RGW_PERM_WRITE)) + return -EACCES; + + return 0; +} + +void RGWPutObjMetadata::execute() +{ + ret = -EINVAL; + + const char *meta_prefix = RGW_ATTR_META_PREFIX; + int meta_prefix_len = sizeof(RGW_ATTR_META_PREFIX) - 1; + map attrs, orig_attrs, rmattrs; + map::iterator iter; + get_request_metadata(s, attrs); + + rgw_obj obj(s->bucket, s->object_str); + + rgwstore->set_atomic(s->obj_ctx, obj); + + /* check if obj exists, read orig attrs */ + ret = get_obj_attrs(s, obj, orig_attrs); + if (ret < 0) + goto done; + + /* only remove meta attrs */ + for (iter = orig_attrs.begin(); iter != orig_attrs.end(); ++iter) { + const string& name = iter->first; + if (name.compare(0, meta_prefix_len, meta_prefix) == 0) { + rmattrs[name] = iter->second; + } + } + + ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, obj, s->obj_size, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false, &rmattrs); + +done: + send_response(); +} + int RGWDeleteObj::verify_permission() { if (!::verify_permission(s, RGW_PERM_WRITE)) @@ -1208,7 +1258,7 @@ void RGWInitMultipart::execute() obj.init(s->bucket, tmp_obj_name, s->object_str, mp_ns); // the meta object will be indexed with 0 size, we c - ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MULTIMETA, true); + ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MULTIMETA, true, NULL); } while (ret == -EEXIST); done: send_response(); @@ -1217,17 +1267,13 @@ done: static int get_multiparts_info(struct req_state *s, string& meta_oid, map& parts, RGWAccessControlPolicy& policy, map& attrs) { - void *handle; map parts_map; map::iterator iter; bufferlist header; rgw_obj obj(s->bucket, meta_oid, s->object_str, mp_ns); - int ret = rgwstore->prepare_get_obj(s->obj_ctx, obj, 0, NULL, &attrs, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, &handle, &s->err); - rgwstore->finish_get_obj(&handle); - + int ret = get_obj_attrs(s, obj, attrs); if (ret < 0) return ret; @@ -1361,7 +1407,7 @@ void RGWCompleteMultipart::execute() target_obj.init(s->bucket, s->object_str); rgwstore->set_atomic(s->obj_ctx, target_obj); - ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, target_obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false); + ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, target_obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false, NULL); if (ret < 0) goto done; diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index e6bc5e2517b16..e54d2a98849ed 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -266,6 +266,23 @@ public: virtual void send_response() = 0; }; +class RGWPutObjMetadata : public RGWOp { +protected: + int ret; + +public: + RGWPutObjMetadata() {} + + virtual void init(struct req_state *s) { + RGWOp::init(s); + ret = 0; + } + int verify_permission(); + void execute(); + + virtual void send_response() = 0; +}; + class RGWDeleteObj : public RGWOp { protected: int ret; diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 73bfb75f8c751..e2ad4d5cde295 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -605,7 +605,8 @@ int RGWRados::create_pools(std::string& id, vector& names, vector& * Returns: 0 on success, -ERR# otherwise. */ int RGWRados::put_obj_meta(void *ctx, std::string& id, rgw_obj& obj, uint64_t size, - time_t *mtime, map& attrs, RGWObjCategory category, bool exclusive) + time_t *mtime, map& attrs, RGWObjCategory category, bool exclusive, + map* rmattrs) { rgw_bucket bucket; std::string oid, key; @@ -627,6 +628,13 @@ int RGWRados::put_obj_meta(void *ctx, std::string& id, rgw_obj& obj, uint64_t s bufferlist acl_bl; map::iterator iter; + if (rmattrs) { + for (iter = rmattrs->begin(); iter != rmattrs->end(); ++iter) { + const string& name = iter->first; + op.rmxattr(name.c_str()); + } + } + for (iter = attrs.begin(); iter != attrs.end(); ++iter) { const string& name = iter->first; bufferlist& bl = iter->second; diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index a2413c8309e7e..331d0eb83ca39 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -171,7 +171,8 @@ public: /** Write/overwrite an object to the bucket storage. */ virtual int put_obj_meta(void *ctx, std::string& id, rgw_obj& obj, uint64_t size, time_t *mtime, - map& attrs, RGWObjCategory category, bool exclusive); + map& attrs, RGWObjCategory category, bool exclusive, + map* rmattrs); virtual int put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data, off_t ofs, size_t len); virtual int aio_put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data, diff --git a/src/rgw/rgw_rest.h b/src/rgw/rgw_rest.h index 178e767d45de2..7aeb0d5c19577 100644 --- a/src/rgw/rgw_rest.h +++ b/src/rgw/rgw_rest.h @@ -66,6 +66,13 @@ public: int get_data(); }; +class RGWPutObjMetadata_REST : public RGWPutObjMetadata +{ +public: + RGWPutObjMetadata_REST() {} + ~RGWPutObjMetadata_REST() {} +}; + class RGWDeleteObj_REST : public RGWDeleteObj { public: RGWDeleteObj_REST() {} diff --git a/src/rgw/rgw_rest_swift.cc b/src/rgw/rgw_rest_swift.cc index 45155e1abd333..5706ea2edeb17 100644 --- a/src/rgw/rgw_rest_swift.cc +++ b/src/rgw/rgw_rest_swift.cc @@ -247,6 +247,16 @@ void RGWPutObj_REST_SWIFT::send_response() flush_formatter_to_req_state(s, s->formatter); } +void RGWPutObjMetadata_REST_SWIFT::send_response() +{ + if (!ret) + ret = STATUS_ACCEPTED; + set_req_state_err(s, ret); + dump_errno(s); + end_header(s); + flush_formatter_to_req_state(s, s->formatter); +} + void RGWDeleteObj_REST_SWIFT::send_response() { int r = ret; @@ -376,6 +386,14 @@ RGWOp *RGWHandler_REST_SWIFT::get_delete_op() return NULL; } +RGWOp *RGWHandler_REST_SWIFT::get_post_op() +{ + if (s->object) + return new RGWPutObjMetadata_REST_SWIFT; + + return NULL; +} + int RGWHandler_REST_SWIFT::authorize() { bool authorized = rgw_verify_os_token(s); diff --git a/src/rgw/rgw_rest_swift.h b/src/rgw/rgw_rest_swift.h index 3f78c8a3a0f3c..fde210100c196 100644 --- a/src/rgw/rgw_rest_swift.h +++ b/src/rgw/rgw_rest_swift.h @@ -80,6 +80,14 @@ public: void send_response(); }; +class RGWPutObjMetadata_REST_SWIFT : public RGWPutObjMetadata_REST { +public: + RGWPutObjMetadata_REST_SWIFT() {} + ~RGWPutObjMetadata_REST_SWIFT() {} + + void send_response(); +}; + class RGWDeleteObj_REST_SWIFT : public RGWDeleteObj_REST { public: RGWDeleteObj_REST_SWIFT() {} @@ -120,7 +128,7 @@ protected: RGWOp *get_retrieve_op(bool get_data); RGWOp *get_create_op(); RGWOp *get_delete_op(); - RGWOp *get_post_op() { return NULL; } + RGWOp *get_post_op(); public: RGWHandler_REST_SWIFT() : RGWHandler_REST() {} -- 2.39.5