diff options
author | Yehuda Sadeh <yehuda@inktank.com> | 2013-06-23 21:00:00 -0700 |
---|---|---|
committer | Yehuda Sadeh <yehuda@inktank.com> | 2013-06-23 21:00:00 -0700 |
commit | 71869c4b9edc13bac3333ae86fd6280fded113db (patch) | |
tree | 66c9727b861298989896932196c2b1e13300ce9b | |
parent | 00973dfdcab54e51a7cfcf09990f31849239e2a7 (diff) | |
download | ceph-71869c4b9edc13bac3333ae86fd6280fded113db.tar.gz |
rgw: create meta handler for bucket instance
Create utility functions for reading writing bucket entry
point and bucket instance. Add a separate meta handler for
bucket instance.
Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
-rw-r--r-- | src/rgw/rgw_bucket.cc | 158 | ||||
-rw-r--r-- | src/rgw/rgw_common.h | 3 | ||||
-rw-r--r-- | src/rgw/rgw_json_enc.cc | 17 | ||||
-rw-r--r-- | src/rgw/rgw_rados.cc | 113 | ||||
-rw-r--r-- | src/rgw/rgw_rados.h | 7 |
5 files changed, 256 insertions, 42 deletions
diff --git a/src/rgw/rgw_bucket.cc b/src/rgw/rgw_bucket.cc index fb92aa311d8..3bce4cd4c0b 100644 --- a/src/rgw/rgw_bucket.cc +++ b/src/rgw/rgw_bucket.cc @@ -24,6 +24,7 @@ using namespace std; static RGWMetadataHandler *bucket_meta_handler = NULL; +static RGWMetadataHandler *bucket_instance_meta_handler = NULL; // define as static when RGWBucket implementation compete void rgw_get_buckets_obj(string& user_id, string& buckets_obj_id) @@ -1290,10 +1291,23 @@ struct RGWBucketCompleteInfo { } }; -class RGWBucketMetadataObject : public RGWMetadataObject { +class RGWBucketEntryMetadataObject : public RGWMetadataObject { + RGWBucketEntryPoint ep; +public: + RGWBucketEntryMetadataObject(RGWBucketEntryPoint& _ep, obj_version& v, time_t m) : ep(_ep) { + objv = v; + mtime = m; + } + + void dump(Formatter *f) const { + ep.dump(f); + } +}; + +class RGWBucketInstanceMetadataObject : public RGWMetadataObject { RGWBucketCompleteInfo info; public: - RGWBucketMetadataObject(RGWBucketCompleteInfo& i, obj_version& v, time_t m) : info(i) { + RGWBucketInstanceMetadataObject(RGWBucketCompleteInfo& i, obj_version& v, time_t m) : info(i) { objv = v; mtime = m; } @@ -1321,15 +1335,140 @@ public: string get_type() { return "bucket"; } int get(RGWRados *store, string& entry, RGWMetadataObject **obj) { + RGWObjVersionTracker ot; + RGWBucketEntryPoint be; + + time_t mtime; + + int ret = store->get_bucket_entrypoint_info(NULL, entry, be, &ot, &mtime); + if (ret < 0) + return ret; + + RGWBucketEntryMetadataObject *mdo = new RGWBucketEntryMetadataObject(be, ot.read_version, mtime); + + *obj = mdo; + + return 0; + } + + int put(RGWRados *store, string& entry, RGWObjVersionTracker& objv_tracker, time_t mtime, JSONObj *obj) { + RGWBucketEntryPoint be, old_be; + decode_json_obj(be, obj); + + time_t orig_mtime; + + int ret = store->get_bucket_entrypoint_info(NULL, entry, be, &objv_tracker, &orig_mtime); + if (ret < 0 && ret != -ENOENT) + return ret; + + ret = store->put_bucket_entrypoint_info(entry, old_be, false, mtime); + if (ret < 0) + return ret; + +#warning need to link bucket here +#if 0 + ret = rgw_add_bucket(store, bci.info.owner, bci.info.bucket, bci.info.creation_time); + if (ret < 0) + return ret; +#endif + + return 0; + } + + struct list_keys_info { + RGWRados *store; + RGWListRawObjsCtx ctx; + }; + + int remove(RGWRados *store, string& entry, RGWObjVersionTracker& objv_tracker) { + rgw_bucket bucket; + int r = init_bucket(store, entry, bucket, &objv_tracker); + if (r < 0) { + cerr << "could not init bucket=" << entry << std::endl; + return r; + } + + return store->delete_bucket(bucket, objv_tracker); + } + + void get_pool_and_oid(RGWRados *store, string& key, rgw_bucket& bucket, string& oid) { + oid = key; + bucket = store->zone.domain_root; + } + + int list_keys_init(RGWRados *store, void **phandle) + { + list_keys_info *info = new list_keys_info; + + info->store = store; + + *phandle = (void *)info; + + return 0; + } + + int list_keys_next(void *handle, int max, list<string>& keys, bool *truncated) { + list_keys_info *info = (list_keys_info *)handle; + + string no_filter; + + keys.clear(); + + RGWRados *store = info->store; + + list<string> unfiltered_keys; + + int ret = store->list_raw_objects(store->zone.domain_root, no_filter, + max, info->ctx, unfiltered_keys, truncated); + if (ret < 0) + return ret; + + // now filter out the system entries + list<string>::iterator iter; + for (iter = unfiltered_keys.begin(); iter != unfiltered_keys.end(); ++iter) { + string& k = *iter; + + if (k[0] != '.') { + keys.push_back(k); + } + } + + return 0; + } + + void list_keys_complete(void *handle) { + list_keys_info *info = (list_keys_info *)handle; + delete info; + } +}; + +class RGWBucketInstanceMetadataHandler : public RGWMetadataHandler { + + int init_bucket(RGWRados *store, string& bucket_name, rgw_bucket& bucket, RGWObjVersionTracker *objv_tracker) { + RGWBucketInfo bucket_info; + int r = store->get_bucket_info(NULL, bucket_name, bucket_info, NULL); + if (r < 0) { + cerr << "could not get bucket info for bucket=" << bucket_name << std::endl; + return r; + } + bucket = bucket_info.bucket; + + return 0; + } + +public: + string get_type() { return "bucket.instance"; } + + int get(RGWRados *store, string& entry, RGWMetadataObject **obj) { RGWBucketCompleteInfo bci; time_t mtime; - int ret = store->get_bucket_info(NULL, entry, bci.info, &mtime, &bci.attrs); + int ret = store->get_bucket_instance_info(NULL, entry, bci.info, &mtime, &bci.attrs); if (ret < 0) return ret; - RGWBucketMetadataObject *mdo = new RGWBucketMetadataObject(bci, bci.info.objv_tracker.read_version, mtime); + RGWBucketInstanceMetadataObject *mdo = new RGWBucketInstanceMetadataObject(bci, bci.info.objv_tracker.read_version, mtime); *obj = mdo; @@ -1344,7 +1483,7 @@ public: old_bci.info.objv_tracker = objv_tracker; - int ret = store->get_bucket_info(NULL, entry, old_bci.info, &orig_mtime, &old_bci.attrs); + int ret = store->get_bucket_instance_info(NULL, entry, old_bci.info, &orig_mtime, &old_bci.attrs); if (ret < 0 && ret != -ENOENT) return ret; @@ -1365,8 +1504,7 @@ public: bci.info.objv_tracker = old_bci.info.objv_tracker; } -#warning need to take care of different routes here - ret = store->put_bucket_info(entry, bci.info, false, mtime, &bci.attrs, false); + ret = store->put_bucket_instance_info(entry, bci.info, false, mtime, &bci.attrs); if (ret < 0) return ret; @@ -1376,10 +1514,6 @@ public: if (ret < 0) return ret; - ret = rgw_add_bucket(store, bci.info.owner, bci.info.bucket, bci.info.creation_time); - if (ret < 0) - return ret; - return 0; } @@ -1454,4 +1588,6 @@ void rgw_bucket_init(RGWMetadataManager *mm) { bucket_meta_handler = new RGWBucketMetadataHandler; mm->register_handler(bucket_meta_handler); + bucket_instance_meta_handler = new RGWBucketInstanceMetadataHandler; + mm->register_handler(bucket_instance_meta_handler); } diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 42aeecfbe4b..af70846f87c 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -707,6 +707,9 @@ struct RGWBucketEntryPoint ::decode(bucket, bl); DECODE_FINISH(bl); } + + void dump(Formatter *f) const; + void decode_json(JSONObj *obj); }; WRITE_CLASS_ENCODER(RGWBucketEntryPoint) diff --git a/src/rgw/rgw_json_enc.cc b/src/rgw/rgw_json_enc.cc index bfc09bd6bd6..8ab6ff530e6 100644 --- a/src/rgw/rgw_json_enc.cc +++ b/src/rgw/rgw_json_enc.cc @@ -436,6 +436,23 @@ void rgw_bucket::decode_json(JSONObj *obj) { JSONDecoder::decode_json("bucket_id", bucket_id, obj); } +void RGWBucketEntryPoint::dump(Formatter *f) const +{ + encode_json("bucket", bucket, f); + encode_json("has_bucket_info", has_bucket_info, f); + if (has_bucket_info) { + encode_json("old_bucket_info", old_bucket_info, f); + } +} + +void RGWBucketEntryPoint::decode_json(JSONObj *obj) { + JSONDecoder::decode_json("bucket", bucket, obj); + JSONDecoder::decode_json("has_bucket_info", has_bucket_info, obj); + if (has_bucket_info) { + JSONDecoder::decode_json("old_bucket_info", old_bucket_info, obj); + } +} + void RGWBucketInfo::dump(Formatter *f) const { encode_json("bucket", bucket, f); diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index bf1e16d32c7..2e490dea13c 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -4464,19 +4464,53 @@ void RGWRados::get_bucket_meta_oid(rgw_bucket& bucket, string& oid) oid = ".bucket.meta." + bucket.bucket_id; } -int RGWRados::get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& info, - time_t *pmtime, map<string, bufferlist> *pattrs) +int RGWRados::get_bucket_instance_info(void *ctx, string& name, RGWBucketInfo& info, + time_t *pmtime, map<string, bufferlist> *pattrs) +{ + /* entry in the format <bucket>/<bucket_id> */ + int pos = name.find('/'); + if (pos < 0) { + return -EINVAL; + } + string oid = ".bucket.meta." + name.substr(pos + 1); + + return get_bucket_instance_from_oid(ctx, oid, info, pmtime, pattrs); +} + +int RGWRados::get_bucket_instance_from_oid(void *ctx, string& oid, RGWBucketInfo& info, + time_t *pmtime, map<string, bufferlist> *pattrs) +{ + ldout(cct, 20) << "reading from " << zone.domain_root << ":" << oid << dendl; + + bufferlist epbl; + + int ret = rgw_get_system_obj(this, ctx, zone.domain_root, oid, epbl, &info.objv_tracker, pmtime, pattrs); + if (ret < 0) { + return ret; + } + + bufferlist::iterator iter = epbl.begin(); + try { + ::decode(info, iter); + } catch (buffer::error& err) { + ldout(cct, 0) << "ERROR: could not decode buffer info, caught buffer::error" << dendl; + return -EIO; + } + return 0; +} + +int RGWRados::get_bucket_entrypoint_info(void *ctx, string& bucket_name, + RGWBucketEntryPoint& entry_point, + RGWObjVersionTracker *objv_tracker, + time_t *pmtime) { bufferlist bl; - RGWObjVersionTracker ot; - int ret = rgw_get_system_obj(this, ctx, zone.domain_root, bucket_name, bl, &ot, pmtime, pattrs); + int ret = rgw_get_system_obj(this, ctx, zone.domain_root, bucket_name, bl, objv_tracker, pmtime, NULL); if (ret < 0) { - info.bucket.name = bucket_name; /* only init this field */ return ret; } - RGWBucketEntryPoint entry_point; bufferlist::iterator iter = bl.begin(); try { ::decode(entry_point, iter); @@ -4484,6 +4518,21 @@ int RGWRados::get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& inf ldout(cct, 0) << "ERROR: could not decode buffer info, caught buffer::error" << dendl; return -EIO; } + return 0; +} + +int RGWRados::get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& info, + time_t *pmtime, map<string, bufferlist> *pattrs) +{ + bufferlist bl; + + RGWBucketEntryPoint entry_point; + time_t ep_mtime; + int ret = get_bucket_entrypoint_info(ctx, bucket_name, entry_point, NULL, &ep_mtime); + if (ret < 0) { + info.bucket.name = bucket_name; /* only init this field */ + return ret; + } if (entry_point.has_bucket_info) { info = entry_point.old_bucket_info; @@ -4501,40 +4550,44 @@ int RGWRados::get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& inf string oid; get_bucket_meta_oid(entry_point.bucket, oid); - ldout(cct, 20) << "reading from " << zone.domain_root << ":" << oid << dendl; - - bufferlist epbl; - - ret = rgw_get_system_obj(this, ctx, zone.domain_root, oid, epbl, &info.objv_tracker, pmtime, pattrs); + ret = get_bucket_instance_from_oid(ctx, oid, info, pmtime, pattrs); if (ret < 0) { - info.bucket.name = bucket_name; /* only init this field */ + info.bucket.name = bucket_name; return ret; } - - iter = epbl.begin(); - try { - ::decode(info, iter); - } catch (buffer::error& err) { - ldout(cct, 0) << "ERROR: could not decode buffer info, caught buffer::error" << dendl; - return -EIO; - } return 0; } -int RGWRados::put_bucket_info(string& bucket_name, RGWBucketInfo& info, bool exclusive, - time_t mtime, map<string, bufferlist> *pattrs, bool create_entry_point) +int RGWRados::put_bucket_entrypoint_info(string& bucket_name, RGWBucketEntryPoint& entry_point, + bool exclusive, time_t mtime) { - bufferlist bl; - - bool create_head = !info.has_instance_obj || create_entry_point; + bufferlist epbl; + ::encode(entry_point, epbl); + RGWObjVersionTracker ot; + return rgw_bucket_store_info(this, bucket_name, epbl, exclusive, NULL, &ot, mtime); +} +int RGWRados::put_bucket_instance_info(string& bucket_name, RGWBucketInfo& info, bool exclusive, + time_t mtime, map<string, bufferlist> *pattrs) +{ info.has_instance_obj = true; + bufferlist bl; ::encode(info, bl); string oid; get_bucket_meta_oid(info.bucket, oid); - int ret = rgw_bucket_store_info(this, oid, bl, exclusive, pattrs, &info.objv_tracker, mtime); + return rgw_bucket_store_info(this, oid, bl, exclusive, pattrs, &info.objv_tracker, mtime); +} + +int RGWRados::put_bucket_info(string& bucket_name, RGWBucketInfo& info, bool exclusive, + time_t mtime, map<string, bufferlist> *pattrs, bool create_entry_point) +{ + bufferlist bl; + + bool create_head = !info.has_instance_obj || create_entry_point; + + int ret = put_bucket_instance_info(bucket_name, info, exclusive, mtime, pattrs); if (ret < 0) { return ret; } @@ -4544,12 +4597,10 @@ int RGWRados::put_bucket_info(string& bucket_name, RGWBucketInfo& info, bool exc RGWBucketEntryPoint entry_point; entry_point.bucket = info.bucket; - bufferlist epbl; - ::encode(entry_point, epbl); - RGWObjVersionTracker ot; - ret = rgw_bucket_store_info(this, info.bucket.name, epbl, exclusive, pattrs, &ot, mtime); - + ret = put_bucket_entrypoint_info(info.bucket.name, entry_point, exclusive, mtime); if (exclusive && ret == -EEXIST) { + string oid; + get_bucket_meta_oid(info.bucket, oid); rgw_obj obj(zone.domain_root, oid); int r = delete_obj(NULL, obj); if (r < 0) { diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index 72583008587..990bb1372ce 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -1268,6 +1268,13 @@ public: int decode_policy(bufferlist& bl, ACLOwner *owner); int get_bucket_stats(rgw_bucket& bucket, uint64_t *bucket_ver, uint64_t *master_ver, map<RGWObjCategory, RGWBucketStats>& stats); void get_bucket_meta_oid(rgw_bucket& bucket, string& oid); + + int put_bucket_entrypoint_info(string& bucket_name, RGWBucketEntryPoint& entry_point, bool exclusive, time_t mtime); + int put_bucket_instance_info(string& bucket_name, RGWBucketInfo& info, bool exclusive, time_t mtime, map<string, bufferlist> *pattrs); + int get_bucket_entrypoint_info(void *ctx, string& bucket_name, RGWBucketEntryPoint& entry_point, RGWObjVersionTracker *objv_tracker, time_t *pmtime); + int get_bucket_instance_info(void *ctx, string& name, RGWBucketInfo& info, time_t *pmtime, map<string, bufferlist> *pattrs); + int get_bucket_instance_from_oid(void *ctx, string& oid, RGWBucketInfo& info, time_t *pmtime, map<string, bufferlist> *pattrs); + virtual int get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& info, time_t *pmtime, map<string, bufferlist> *pattrs = NULL); virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info, bool exclusive, |