From 802e9e5a3c3e2666386138aff17f734f3922848a Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Thu, 9 Jun 2011 13:25:46 -0700 Subject: [PATCH] rgw: implement namespace, use it in complete multipart --- src/rgw/rgw_access.h | 2 +- src/rgw/rgw_common.h | 90 ++++++++++++++++++++++++++++++++++++++++++-- src/rgw/rgw_fs.cc | 10 ++++- src/rgw/rgw_fs.h | 2 +- src/rgw/rgw_op.cc | 33 ++++++++++------ src/rgw/rgw_rados.cc | 11 ++++-- src/rgw/rgw_rados.h | 2 +- 7 files changed, 126 insertions(+), 24 deletions(-) diff --git a/src/rgw/rgw_access.h b/src/rgw/rgw_access.h index 3b597d847df5f..b10120c1dcf14 100644 --- a/src/rgw/rgw_access.h +++ b/src/rgw/rgw_access.h @@ -40,7 +40,7 @@ public: */ virtual int list_objects(std::string& id, std::string& bucket, int max, std::string& prefix, std::string& delim, std::string& marker, std::vector& result, map& common_prefixes, - bool get_content_type) = 0; + bool get_content_type, std::string& ns) = 0; /** Create a new bucket*/ virtual int create_bucket(std::string& id, std::string& bucket, map& attrs, uint64_t auid=0) = 0; diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 28934fa6deca0..87508efe43fad 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -449,10 +449,13 @@ struct RGWUploadPartInfo { WRITE_CLASS_ENCODER(RGWUploadPartInfo) class rgw_obj { + std::string orig_obj; + std::string orig_key; public: std::string bucket; - std::string object; std::string key; + std::string ns; + std::string object; rgw_obj() {} rgw_obj(std::string& b, std::string& o) { @@ -461,14 +464,93 @@ public: rgw_obj(std::string& b, std::string& o, std::string& k) { init(b, o, k); } + rgw_obj(std::string& b, std::string& o, std::string& k, std::string& n) { + init(b, o, k, n); + } + void init(std::string& b, std::string& o, std::string& k, std::string& n) { + bucket = b; + set_ns(n); + set_obj(o); + set_key(k); + } void init(std::string& b, std::string& o, std::string& k) { bucket = b; - object = o; + set_obj(o); + set_key(k); } void init(std::string& b, std::string& o) { bucket = b; - object = o; - key = o; + set_obj(o); + orig_key = key = ""; + } + int set_ns(const char *n) { + if (!n) + return -EINVAL; + string ns_str(n); + return set_ns(ns_str); + } + int set_ns(string& n) { + if (n[0] == '_') + return -EINVAL; + ns = n; + set_obj(orig_obj); + return 0; + } + + void set_key(string& k) { + orig_key = k; + if (k.compare(object) == 0) + key = ""; + else + key = k; + } + + void set_obj(string& o) { + orig_obj = o; + if (ns.empty()) { + if (o.empty()) + return; + if (o.size() < 1 || o[0] != '_') { + object = o; + return; + } + object = "__"; + object.append(o); + } else { + object = "_"; + object.append(ns); + object.append("_"); + object.append(o); + } + set_key(orig_key); + } + + static bool translate_raw_obj(string& obj, string& ns) { + if (ns.empty()) { + if (obj[0] != '_') + return true; + + if (obj.size() >= 2 && obj[1] == '_') { + obj = obj.substr(1); + return true; + } + + return false; + } + + if (obj[0] != '_' || obj.size() < 3) // for namespace, min size would be 3: _x_ + return false; + + int pos = obj.find('_', 1); + if (pos <= 1) // if it starts with __, it's not in our namespace + return false; + + string obj_ns = obj.substr(1, pos - 1); + if (obj_ns.compare(ns) != 0) + return false; + + obj = obj.substr(pos + 1); + return true; } }; diff --git a/src/rgw/rgw_fs.cc b/src/rgw/rgw_fs.cc index b4e8442ad069d..f1eb79f3b33d7 100644 --- a/src/rgw/rgw_fs.cc +++ b/src/rgw/rgw_fs.cc @@ -96,7 +96,7 @@ int RGWFS::obj_stat(rgw_obj& obj, uint64_t *psize, time_t *pmtime) int RGWFS::list_objects(string& id, string& bucket, int max, string& prefix, string& delim, string& marker, vector& result, map& common_prefixes, - bool get_content_type) + bool get_content_type, string& ns) { map dir_map; char path[BUF_SIZE]; @@ -117,7 +117,13 @@ int RGWFS::list_objects(string& id, string& bucket, int max, string& prefix, str if (prefix.empty() || (prefix.compare(0, prefix.size(), prefix) == 0)) { - dir_map[dirent->d_name] = true; + + string obj = dirent->d_name; + + if (!rgw_obj::translate_raw_obj(obj, ns)) + continue; + + dir_map[obj] = true; } } diff --git a/src/rgw/rgw_fs.h b/src/rgw/rgw_fs.h index 00a5c670cb8a0..14000bb001c15 100644 --- a/src/rgw/rgw_fs.h +++ b/src/rgw/rgw_fs.h @@ -16,7 +16,7 @@ public: int list_objects(std::string& id, std::string& bucket, int max, std::string& prefix, std::string& delim, std::string& marker, std::vector& result, map& common_prefixes, - bool get_content_type); + bool get_content_type, string& ns); int create_bucket(std::string& id, std::string& bucket, map& attrs, uint64_t auid=0); int put_obj_meta(std::string& id, rgw_obj& obj, time_t *mtime, diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index e91a1a01854fe..0693e5138a4a6 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -18,6 +18,8 @@ using namespace std; using ceph::crypto::MD5; +static string mp_ns = "multipart"; + static int parse_range(const char *range, off_t& ofs, off_t& end) { int r = -ERANGE; @@ -110,12 +112,14 @@ int read_acls(struct req_state *s, RGWAccessControlPolicy *policy, string& bucke { string upload_id = s->args.get("uploadId"); string oid = object; + rgw_obj obj; if (!oid.empty() && !upload_id.empty()) { oid.append("."); oid.append(upload_id); + obj.set_ns(mp_ns); } - rgw_obj obj(bucket, oid, object); + obj.init(bucket, oid, object); int ret = get_policy_from_attr(policy, obj); if (ret == -ENOENT && object.size()) { @@ -281,6 +285,8 @@ void RGWStatBucket::execute() void RGWListBucket::execute() { + string no_ns; + if (!verify_permission(s, RGW_PERM_READ)) { ret = -EACCES; goto done; @@ -309,7 +315,7 @@ void RGWListBucket::execute() } ret = rgwstore->list_objects(s->user.user_id, s->bucket_str, max, prefix, delimiter, marker, objs, common_prefixes, - !!(s->prot_flags & RGW_REST_OPENSTACK)); + !!(s->prot_flags & RGW_REST_OPENSTACK), no_ns); done: send_response(); } @@ -430,6 +436,7 @@ void RGWPutObj::execute() MD5 hash; string oid; multipart = s->args.exists("uploadId"); + rgw_obj obj; if (!multipart) { oid = s->object_str; } else { @@ -444,8 +451,10 @@ void RGWPutObj::execute() } oid.append("."); oid.append(part_num); + + obj.set_ns(mp_ns); } - rgw_obj obj(s->bucket_str, oid, s->object_str); + obj.init(s->bucket_str, oid, s->object_str); do { get_data(); if (len > 0) { @@ -508,7 +517,7 @@ void RGWPutObj::execute() RGW_LOG(0) << "JJJ name=" << p << "bl.length()=" << bl.length() << dendl; meta_attrs[p] = bl; - rgw_obj meta_obj(s->bucket_str, multipart_meta_obj, s->object_str); + rgw_obj meta_obj(s->bucket_str, multipart_meta_obj, s->object_str, mp_ns); ret = rgwstore->put_obj_meta(s->user.user_id, meta_obj, NULL, meta_attrs, false); } @@ -881,7 +890,7 @@ void RGWInitMultipart::execute() tmp_obj_name.append("."); tmp_obj_name.append(upload_id); - obj.init(s->bucket_str, tmp_obj_name, s->object_str); + obj.init(s->bucket_str, tmp_obj_name, s->object_str, mp_ns); ret = rgwstore->put_obj_meta(s->user.user_id, obj, NULL, attrs, true); } while (ret == -EEXIST); done: @@ -895,7 +904,7 @@ static int get_multiparts_info(struct req_state *s, string& oid, map attrs; map::iterator iter; - rgw_obj obj(s->bucket_str, oid, s->object_str); + rgw_obj obj(s->bucket_str, oid, s->object_str, mp_ns); int ret = rgwstore->prepare_get_obj(obj, 0, NULL, &attrs, NULL, NULL, NULL, NULL, NULL, NULL, &handle, &s->err); @@ -1026,9 +1035,10 @@ void RGWCompleteMultipart::execute() char buf[16]; snprintf(buf, sizeof(buf), "%d", obj_iter->second.num); oid.append(buf); - rgw_obj src_obj(s->bucket_str, oid, s->object_str); - rgw_obj dst_obj(s->bucket_str, s->object_str); - rgwstore->clone_range(dst_obj, ofs, src_obj, 0, obj_iter->second.size); + rgw_obj src_obj(s->bucket_str, oid, s->object_str, mp_ns); + ret = rgwstore->clone_range(target_obj, ofs, src_obj, 0, obj_iter->second.size); + if (ret < 0) + goto done; ofs += obj_iter->second.size; } @@ -1038,14 +1048,13 @@ void RGWCompleteMultipart::execute() char buf[16]; snprintf(buf, sizeof(buf), "%d", obj_iter->second.num); oid.append(buf); - rgw_obj obj(s->bucket_str, oid, s->object_str); + rgw_obj obj(s->bucket_str, oid, s->object_str, mp_ns); rgwstore->delete_obj(s->user.user_id, obj); } // and also remove the metadata obj - meta_obj.init(s->bucket_str, meta_oid, s->object_str); + meta_obj.init(s->bucket_str, meta_oid, s->object_str, mp_ns); rgwstore->delete_obj(s->user.user_id, meta_obj); - done: send_response(); } diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index d89eed45816e3..45f03031447cc 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -151,7 +151,7 @@ int RGWRados::list_buckets_next(std::string& id, RGWObjEnt& obj, RGWAccessHandle */ int RGWRados::list_objects(string& id, string& bucket, int max, string& prefix, string& delim, string& marker, vector& result, map& common_prefixes, - bool get_content_type) + bool get_content_type, string& ns) { librados::IoCtx io_ctx; int r = open_bucket_ctx(bucket, io_ctx); @@ -162,9 +162,14 @@ int RGWRados::list_objects(string& id, string& bucket, int max, string& prefix, { librados::ObjectIterator i_end = io_ctx.objects_end(); for (librados::ObjectIterator i = io_ctx.objects_begin(); i != i_end; ++i) { + string obj = *i; + + if (!rgw_obj::translate_raw_obj(obj, ns)) + continue; + if (prefix.empty() || - ((*i).compare(0, prefix.size(), prefix) == 0)) { - dir_set.insert(*i); + ((obj).compare(0, prefix.size(), prefix) == 0)) { + dir_set.insert(obj); } } } diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index 4b3fa2b4ce4ba..aea5be318b314 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -33,7 +33,7 @@ public: /** get listing of the objects in a bucket */ virtual int list_objects(std::string& id, std::string& bucket, int max, std::string& prefix, std::string& delim, std::string& marker, std::vector& result, map& common_prefixes, - bool get_content_type); + bool get_content_type, string& ns); /** * create a bucket with name bucket and the given list of attrs -- 2.39.5