From dbee69927803ccf7aa592ca8718335dde16bb2f3 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Fri, 24 Jun 2011 14:09:30 -0700 Subject: [PATCH] rgw: atomic put --- src/include/rados/librados.hpp | 3 +++ src/librados.cc | 7 +++++++ src/rgw/rgw_access.h | 5 +++++ src/rgw/rgw_op.cc | 23 +++++++++++++++++++---- src/rgw/rgw_rados.cc | 28 ++++++++++++++++++++++++++++ src/rgw/rgw_rados.h | 4 ++++ 6 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/include/rados/librados.hpp b/src/include/rados/librados.hpp index 77ac98e42da22..f0ee082d18e0d 100644 --- a/src/include/rados/librados.hpp +++ b/src/include/rados/librados.hpp @@ -122,6 +122,9 @@ namespace librados void rmxattr(const char *name); void setxattr(const char *name, const bufferlist& bl); void tmap_update(const bufferlist& cmdbl); + void clone_range(uint64_t dst_off, + const std::string& src_oid, uint64_t src_off, + size_t len); void exec(const char *cls, const char *method, bufferlist& bl); diff --git a/src/librados.cc b/src/librados.cc index 98aa9116be1ec..c121307e01c10 100644 --- a/src/librados.cc +++ b/src/librados.cc @@ -195,6 +195,13 @@ void librados::ObjectOperation::tmap_update(const bufferlist& cmdbl) o->tmap_update(c); } +void librados::ObjectOperation::clone_range(uint64_t dst_off, + const std::string& src_oid, uint64_t src_off, + size_t len) +{ + ::ObjectOperation *o = (::ObjectOperation *)impl; + o->clone_range(src_oid, src_off, len, dst_off); +} librados::WatchCtx:: diff --git a/src/rgw/rgw_access.h b/src/rgw/rgw_access.h index 1c563e12d292b..751c324684cbb 100644 --- a/src/rgw/rgw_access.h +++ b/src/rgw/rgw_access.h @@ -160,6 +160,11 @@ public: virtual int clone_range(rgw_obj& dst_obj, off_t dst_ofs, rgw_obj& src_obj, off_t src_ofs, size_t size) = 0; + + virtual int clone_obj(rgw_obj& dst_obj, off_t dst_ofs, + rgw_obj& src_obj, off_t src_ofs, + size_t size, + map attrs) { return -ENOTSUP; } /** * a simple object read without keeping state */ diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 5b192a3f403a7..08a2e49885a85 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -19,6 +19,7 @@ using namespace std; using ceph::crypto::MD5; static string mp_ns = "multipart"; +static string tmp_ns = "tmp"; class MultipartMetaFilter : public RGWAccessListFilter { public: @@ -560,6 +561,12 @@ void RGWPutObj::execute() rgw_obj obj; if (!multipart) { oid = s->object_str; + obj.set_ns(tmp_ns); + + char buf[33]; + gen_rand_alphanumeric(buf, sizeof(buf) - 1); + oid.append("_"); + oid.append(buf); } else { oid = s->object_str; string upload_id = s->args.get("uploadId"); @@ -644,11 +651,19 @@ void RGWPutObj::execute() get_request_metadata(s, attrs); - ret = rgwstore->put_obj_meta(s->user.user_id, obj, NULL, attrs, false); - if (ret < 0) - goto done; + if (!multipart) { + rgw_obj dst_obj(s->bucket_str, s->object_str); + ret = rgwstore->clone_obj(dst_obj, 0, obj, 0, s->obj_size, attrs); + if (ret < 0) + goto done; + ret = rgwstore->delete_obj(s->user.user_id, obj); + if (ret < 0) + goto done; + } else { + ret = rgwstore->put_obj_meta(s->user.user_id, obj, NULL, attrs, false); + if (ret < 0) + goto done; - if (multipart) { bl.clear(); map meta_attrs; RGWUploadPartInfo info; diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index de6b80c494e65..7b5f0537306b6 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -865,6 +865,34 @@ int RGWRados::clone_range(rgw_obj& dst_obj, off_t dst_ofs, return io_ctx.clone_range(dst_oid, dst_ofs, src_oid, src_ofs, size); } +int RGWRados::clone_obj(rgw_obj& dst_obj, off_t dst_ofs, + rgw_obj& src_obj, off_t src_ofs, size_t size, + map attrs) +{ + std::string& bucket = dst_obj.bucket; + std::string& dst_oid = dst_obj.object; + std::string& src_oid = src_obj.object; + librados::IoCtx io_ctx; + + int r = open_bucket_ctx(bucket, io_ctx); + if (r < 0) + return r; + + io_ctx.locator_set_key(dst_obj.key); + ObjectOperation op; + op.create(false); + map::iterator iter; + for (iter = attrs.begin(); iter != attrs.end(); ++iter) { + const string& name = iter->first; + bufferlist& bl = iter->second; + op.setxattr(name.c_str(), bl); + } + op.clone_range(dst_ofs, src_oid, src_ofs, size); + + bufferlist outbl; + int ret = io_ctx.operate(dst_oid, &op, &outbl); + return ret; +} int RGWRados::get_obj(void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end) diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index 9e31160e125a7..8948a95cf7069 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -54,6 +54,10 @@ public: virtual bool aio_completed(void *handle); virtual int clone_range(rgw_obj& dst_obj, off_t dst_ofs, rgw_obj& src_obj, off_t src_ofs, size_t size); + virtual int clone_obj(rgw_obj& dst_obj, off_t dst_ofs, + rgw_obj& src_obj, off_t src_ofs, size_t size, + map attrs); + /** Copy an object, with many extra options */ virtual int copy_obj(std::string& id, rgw_obj& dest_obj, rgw_obj& src_obj, -- 2.39.5