]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: preserve bucket creation time across different zones / regions
authorYehuda Sadeh <yehuda@inktank.com>
Sun, 16 Jun 2013 01:41:21 +0000 (18:41 -0700)
committerYehuda Sadeh <yehuda@inktank.com>
Sun, 16 Jun 2013 01:41:21 +0000 (18:41 -0700)
Keep bucket creation time in RGWBucketInfo, and make use
of it where necessary.

Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
src/rgw/rgw_bucket.cc
src/rgw/rgw_bucket.h
src/rgw/rgw_common.h
src/rgw/rgw_json_enc.cc
src/rgw/rgw_op.cc
src/rgw/rgw_op.h
src/rgw/rgw_rados.cc
src/rgw/rgw_rados.h
src/rgw/rgw_rest_s3.cc

index 889859b5e320dba95e6ac0a331b29a45317d64d6..ae0a23e9a856a42aab794df86d86b1520b04e154 100644 (file)
@@ -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;
 
index cec6192b75e25a21d371eb104a185bf04eddd10f..0278b872aa7bb3076e7865c78b137233fd4144a8 100644 (file)
@@ -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);
index 49f61d5a2b88c6403fca649b9f4f2e0a0012620f..3a4b76a09b050375db1ecd41429b5db7b07be58f 100644 (file)
@@ -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)
 
index 7b807a3e3bb7907ad62e3651c2c4fa7a528df476..afdf1d6d8b34f8bacd8f9bb930492c0e988aa9c5 100644 (file)
@@ -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);
 }
 
index 838f5fb440560800ac63bcc72ba3b7c0fc77cde7..c5e29b0666673738fd7c3d811528ab4dcc85f8f5 100644 (file)
@@ -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()
index 2431cb172229eeab77d359ab4a42fc6506f8cec2..0b8462148b8411135deafb6f9ee8732ad7faeb5b 100644 (file)
@@ -234,7 +234,7 @@ protected:
   RGWAccessControlPolicy policy;
   string location_constraint;
   RGWObjVersionTracker objv_tracker;
-  rgw_bucket bucket;
+  RGWBucketInfo info;
 
   bufferlist in_data;
 
index 98b6dd1421d50c94f6a53b25a233e565580d57bf..6e91c8571d20254244d2307691786cd3bc3bb895 100644 (file)
@@ -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;
   }
 
index 160069bdc7b83fde2487480e48acc6849211edcb..2a2ffe0437a7196a367efdd4c24c6708f4a156d0 100644 (file)
@@ -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);
index 9496fe01d3e1008b3138244308e404a02f544b4f..8a67095bc278076afb4d10721f88e9d3fd0754ae 100644 (file)
@@ -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);
   }