diff options
author | Yehuda Sadeh <yehuda@inktank.com> | 2013-06-15 18:41:21 -0700 |
---|---|---|
committer | Yehuda Sadeh <yehuda@inktank.com> | 2013-06-15 18:41:21 -0700 |
commit | a2cf14fe27a2da54e44b12a373b15b29c89d31b9 (patch) | |
tree | 97ad66b0af7fd48c8b7fbe9688b6337207128337 | |
parent | 8eae1b8ba2ded15438ae1d0b689058a690e4411f (diff) | |
download | ceph-a2cf14fe27a2da54e44b12a373b15b29c89d31b9.tar.gz |
rgw: preserve bucket creation time across different zones / regions
Keep bucket creation time in RGWBucketInfo, and make use
of it where necessary.
Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
-rw-r--r-- | src/rgw/rgw_bucket.cc | 20 | ||||
-rw-r--r-- | src/rgw/rgw_bucket.h | 2 | ||||
-rw-r--r-- | src/rgw/rgw_common.h | 25 | ||||
-rw-r--r-- | src/rgw/rgw_json_enc.cc | 4 | ||||
-rw-r--r-- | src/rgw/rgw_op.cc | 25 | ||||
-rw-r--r-- | src/rgw/rgw_op.h | 2 | ||||
-rw-r--r-- | src/rgw/rgw_rados.cc | 8 | ||||
-rw-r--r-- | src/rgw/rgw_rados.h | 2 | ||||
-rw-r--r-- | src/rgw/rgw_rest_s3.cc | 4 |
9 files changed, 51 insertions, 41 deletions
diff --git a/src/rgw/rgw_bucket.cc b/src/rgw/rgw_bucket.cc index 889859b5e32..ae0a23e9a85 100644 --- a/src/rgw/rgw_bucket.cc +++ b/src/rgw/rgw_bucket.cc @@ -72,7 +72,7 @@ int rgw_read_user_buckets(RGWRados *store, string user_id, RGWUserBuckets& bucke return 0; } -int rgw_add_bucket(RGWRados *store, string user_id, rgw_bucket& bucket) +int rgw_add_bucket(RGWRados *store, string user_id, rgw_bucket& bucket, time_t creation_time) { int ret; string& bucket_name = bucket.name; @@ -82,7 +82,10 @@ int rgw_add_bucket(RGWRados *store, string user_id, rgw_bucket& bucket) RGWBucketEnt new_bucket; new_bucket.bucket = bucket; new_bucket.size = 0; - time(&new_bucket.mtime); + if (!creation_time) + time(&new_bucket.creation_time); + else + new_bucket.creation_time = creation_time; ::encode(new_bucket, bl); string buckets_obj_id; @@ -147,7 +150,10 @@ int RGWBucket::create_bucket(string bucket_str, string& user_id, string& region_ rgw_bucket& bucket = bucket_info.bucket; - ret = store->create_bucket(user_id, bucket, region_name, attrs, objv_tracker, NULL, NULL); + RGWBucketInfo new_info; + + ret = store->create_bucket(user_id, bucket, region_name, attrs, objv_tracker, + NULL, bucket_info.creation_time, NULL, &new_info); if (ret && ret != -EEXIST) goto done; @@ -159,7 +165,7 @@ int RGWBucket::create_bucket(string bucket_str, string& user_id, string& region_ goto done; } - ret = rgw_add_bucket(store, user_id, bucket); + ret = rgw_add_bucket(store, user_id, bucket, new_info.creation_time); if (ret == -EEXIST) ret = 0; @@ -236,7 +242,7 @@ void check_bad_user_bucket_mapping(RGWRados *store, const string& user_id, bool cout << "bucket info mismatch: expected " << actual_bucket << " got " << bucket << std::endl; if (fix) { cout << "fixing" << std::endl; - r = rgw_add_bucket(store, user_id, actual_bucket); + r = rgw_add_bucket(store, user_id, actual_bucket, bucket_info.creation_time); if (r < 0) { cerr << "failed to fix bucket: " << cpp_strerror(-r) << std::endl; } @@ -443,7 +449,7 @@ int RGWBucket::link(RGWBucketAdminOpState& op_state, std::string *err_msg) if (r < 0) return r; - r = rgw_add_bucket(store, user_id, bucket); + r = rgw_add_bucket(store, user_id, bucket, 0); if (r < 0) return r; } else { @@ -1359,7 +1365,7 @@ public: if (ret < 0) return ret; - ret = rgw_add_bucket(store, bci.info.owner, bci.info.bucket); + ret = rgw_add_bucket(store, bci.info.owner, bci.info.bucket, bci.info.creation_time); if (ret < 0) return ret; diff --git a/src/rgw/rgw_bucket.h b/src/rgw/rgw_bucket.h index cec6192b75e..0278b872aa7 100644 --- a/src/rgw/rgw_bucket.h +++ b/src/rgw/rgw_bucket.h @@ -93,7 +93,7 @@ extern void rgw_bucket_init(RGWMetadataManager *mm); extern int rgw_read_user_buckets(RGWRados *store, string user_id, RGWUserBuckets& buckets, const string& marker, uint64_t max, bool need_stats); -extern int rgw_add_bucket(RGWRados *store, string user_id, rgw_bucket& bucket); +extern int rgw_add_bucket(RGWRados *store, string user_id, rgw_bucket& bucket, time_t creation_time); extern int rgw_remove_user_bucket_info(RGWRados *store, string user_id, rgw_bucket& bucket); extern int rgw_remove_object(RGWRados *store, rgw_bucket& bucket, std::string& object); diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 49f61d5a2b8..3a4b76a09b0 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -597,17 +597,19 @@ struct RGWBucketInfo string owner; uint32_t flags; string region; + time_t creation_time; void encode(bufferlist& bl) const { - ENCODE_START(5, 4, bl); + ENCODE_START(6, 4, bl); ::encode(bucket, bl); ::encode(owner, bl); ::encode(flags, bl); ::encode(region, bl); + ::encode(creation_time, bl); ENCODE_FINISH(bl); } void decode(bufferlist::iterator& bl) { - DECODE_START_LEGACY_COMPAT_LEN_32(5, 4, 4, bl); + DECODE_START_LEGACY_COMPAT_LEN_32(6, 4, 4, bl); ::decode(bucket, bl); if (struct_v >= 2) ::decode(owner, bl); @@ -615,6 +617,8 @@ struct RGWBucketInfo ::decode(flags, bl); if (struct_v >= 5) ::decode(region, bl); + if (struct_v >= 6) + ::decode(creation_time, bl); DECODE_FINISH(bl); } void dump(Formatter *f) const; @@ -622,7 +626,7 @@ struct RGWBucketInfo void decode_json(JSONObj *obj); - RGWBucketInfo() : flags(0) {} + RGWBucketInfo() : flags(0), creation_time(0) {} }; WRITE_CLASS_ENCODER(RGWBucketInfo) @@ -779,15 +783,15 @@ struct RGWBucketEnt { rgw_bucket bucket; size_t size; size_t size_rounded; - time_t mtime; + time_t creation_time; uint64_t count; - RGWBucketEnt() : size(0), size_rounded(0), mtime(0), count(0) {} + RGWBucketEnt() : size(0), size_rounded(0), creation_time(0), count(0) {} void encode(bufferlist& bl) const { ENCODE_START(5, 5, bl); uint64_t s = size; - __u32 mt = mtime; + __u32 mt = creation_time; string empty_str; // originally had the bucket name here, but we encode bucket later ::encode(empty_str, bl); ::encode(s, bl); @@ -807,7 +811,7 @@ struct RGWBucketEnt { ::decode(s, bl); ::decode(mt, bl); size = s; - mtime = mt; + creation_time = mt; if (struct_v >= 2) ::decode(count, bl); if (struct_v >= 3) @@ -819,13 +823,6 @@ struct RGWBucketEnt { } void dump(Formatter *f) const; static void generate_test_instances(list<RGWBucketEnt*>& o); - void clear() { - bucket.clear(); - size = 0; - size_rounded = 0; - mtime = 0; - count = 0; - } }; WRITE_CLASS_ENCODER(RGWBucketEnt) diff --git a/src/rgw/rgw_json_enc.cc b/src/rgw/rgw_json_enc.cc index 7b807a3e3bb..afdf1d6d8b3 100644 --- a/src/rgw/rgw_json_enc.cc +++ b/src/rgw/rgw_json_enc.cc @@ -435,6 +435,7 @@ void rgw_bucket::decode_json(JSONObj *obj) { void RGWBucketInfo::dump(Formatter *f) const { encode_json("bucket", bucket, f); + encode_json("creation_time", creation_time, f); encode_json("owner", owner, f); encode_json("flags", flags, f); encode_json("region", region, f); @@ -442,6 +443,7 @@ void RGWBucketInfo::dump(Formatter *f) const void RGWBucketInfo::decode_json(JSONObj *obj) { JSONDecoder::decode_json("bucket", bucket, obj); + JSONDecoder::decode_json("creation_time", creation_time, obj); JSONDecoder::decode_json("owner", owner, obj); JSONDecoder::decode_json("flags", flags, obj); JSONDecoder::decode_json("region", region, obj); @@ -465,7 +467,7 @@ void RGWBucketEnt::dump(Formatter *f) const encode_json("bucket", bucket, f); encode_json("size", size, f); encode_json("size_rounded", size_rounded, f); - encode_json("mtime", mtime, f); + encode_json("mtime", creation_time, f); /* mtime / creation time discrepency needed for backward compatibility */ encode_json("count", count, f); } diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 838f5fb4405..c5e29b06666 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -909,8 +909,9 @@ void RGWCreateBucket::execute() } } - rgw_bucket master_bucket; + RGWBucketInfo master_info; rgw_bucket *pmaster_bucket; + time_t creation_time; if (!store->region.is_master) { JSONParser jp; @@ -919,12 +920,15 @@ void RGWCreateBucket::execute() return; JSONDecoder::decode_json("object_ver", objv, &jp); - JSONDecoder::decode_json("bucket", master_bucket, &jp); + JSONDecoder::decode_json("bucket_info", master_info, &jp); ldout(s->cct, 20) << "parsed: objv.tag=" << objv.tag << " objv.ver=" << objv.ver << dendl; - pmaster_bucket = &master_bucket; + ldout(s->cct, 20) << "got creation time: << " << master_info.creation_time << dendl; + pmaster_bucket= &master_info.bucket; + creation_time = master_info.creation_time; pobjv = &objv; } else { pmaster_bucket = NULL; + creation_time = 0; } string region_name; @@ -943,7 +947,8 @@ void RGWCreateBucket::execute() attrs[RGW_ATTR_ACL] = aclbl; s->bucket.name = s->bucket_name_str; - ret = store->create_bucket(s->user.user_id, s->bucket, region_name, attrs, objv_tracker, pobjv, pmaster_bucket, true); + ret = store->create_bucket(s->user.user_id, s->bucket, region_name, attrs, objv_tracker, pobjv, + creation_time, pmaster_bucket, &info, true); /* continue if EEXIST and create_bucket will fail below. this way we can recover * from a partial create by retrying it. */ ldout(s->cct, 20) << "rgw_create_bucket returned ret=" << ret << " bucket=" << s->bucket << dendl; @@ -959,14 +964,6 @@ void RGWCreateBucket::execute() * info, verify that the reported bucket owner is the current user. * If all is ok then update the user's list of buckets */ - RGWBucketInfo info; - map<string, bufferlist> attrs; - int r = store->get_bucket_info(NULL, s->bucket.name, info, &s->objv_tracker, NULL, &attrs); - if (r < 0) { - ldout(s->cct, 0) << "ERROR: get_bucket_info on bucket=" << s->bucket.name << " returned err=" << r << " after create_bucket returned -EEXIST" << dendl; - ret = r; - return; - } if (info.owner.compare(s->user.user_id) != 0) { ret = -ERR_BUCKET_EXISTS; return; @@ -974,14 +971,12 @@ void RGWCreateBucket::execute() s->bucket = info.bucket; } - ret = rgw_add_bucket(store, s->user.user_id, s->bucket); + ret = rgw_add_bucket(store, s->user.user_id, s->bucket, info.creation_time); if (ret && !existed && ret != -EEXIST) /* if it exists (or previously existed), don't remove it! */ rgw_remove_user_bucket_info(store, s->user.user_id, s->bucket); if (ret == -EEXIST) ret = -ERR_BUCKET_EXISTS; - - bucket = s->bucket; } int RGWDeleteBucket::verify_permission() diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index 2431cb17222..0b8462148b8 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -234,7 +234,7 @@ protected: RGWAccessControlPolicy policy; string location_constraint; RGWObjVersionTracker objv_tracker; - rgw_bucket bucket; + RGWBucketInfo info; bufferlist in_data; diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 98b6dd1421d..6e91c8571d2 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -1680,7 +1680,9 @@ int RGWRados::create_bucket(string& owner, rgw_bucket& bucket, map<std::string, bufferlist>& attrs, RGWObjVersionTracker& objv_tracker, obj_version *pobjv, + time_t creation_time, rgw_bucket *pmaster_bucket, + RGWBucketInfo *pinfo, bool exclusive) { #define MAX_CREATE_RETRIES 20 /* need to bound retries */ @@ -1729,6 +1731,10 @@ int RGWRados::create_bucket(string& owner, rgw_bucket& bucket, info.bucket = bucket; info.owner = owner; info.region = region_name; + if (!creation_time) + time(&info.creation_time); + else + info.creation_time = creation_time; ret = put_bucket_info(bucket.name, info, exclusive, &objv_tracker, &attrs); if (ret == -EEXIST) { librados::IoCtx index_ctx; // context for new bucket @@ -1747,6 +1753,8 @@ int RGWRados::create_bucket(string& owner, rgw_bucket& bucket, return r; } } + if (pinfo) + *pinfo = info; return ret; } diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index 160069bdc7b..2a2ffe0437a 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -779,7 +779,9 @@ public: map<std::string,bufferlist>& attrs, RGWObjVersionTracker& objv_tracker, obj_version *pobjv, + time_t creation_time, rgw_bucket *master_bucket, + RGWBucketInfo *pinfo, bool exclusive = true); virtual int add_bucket_placement(std::string& new_pool); virtual int remove_bucket_placement(std::string& new_pool); diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 9496fe01d3e..8a67095bc27 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -35,7 +35,7 @@ void dump_bucket(struct req_state *s, RGWBucketEnt& obj) { s->formatter->open_object_section("Bucket"); s->formatter->dump_string("Name", obj.bucket.name); - dump_time(s, "CreationDate", &obj.mtime); + dump_time(s, "CreationDate", &obj.creation_time); s->formatter->close_section(); } @@ -430,7 +430,7 @@ void RGWCreateBucket_ObjStore_S3::send_response() f.open_object_section("info"); encode_json("object_ver", objv_tracker.read_version, &f); - encode_json("bucket", bucket, &f); + encode_json("bucket_info", info, &f); f.close_section(); rgw_flush_formatter_and_reset(s, &f); } |