summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYehuda Sadeh <yehuda@inktank.com>2013-06-15 18:41:21 -0700
committerYehuda Sadeh <yehuda@inktank.com>2013-06-15 18:41:21 -0700
commita2cf14fe27a2da54e44b12a373b15b29c89d31b9 (patch)
tree97ad66b0af7fd48c8b7fbe9688b6337207128337
parent8eae1b8ba2ded15438ae1d0b689058a690e4411f (diff)
downloadceph-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.cc20
-rw-r--r--src/rgw/rgw_bucket.h2
-rw-r--r--src/rgw/rgw_common.h25
-rw-r--r--src/rgw/rgw_json_enc.cc4
-rw-r--r--src/rgw/rgw_op.cc25
-rw-r--r--src/rgw/rgw_op.h2
-rw-r--r--src/rgw/rgw_rados.cc8
-rw-r--r--src/rgw/rgw_rados.h2
-rw-r--r--src/rgw/rgw_rest_s3.cc4
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);
}