]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: initial work to separate bucket name and instance
authorYehuda Sadeh <yehuda@inktank.com>
Sun, 23 Jun 2013 05:47:48 +0000 (22:47 -0700)
committerYehuda Sadeh <yehuda@inktank.com>
Sun, 23 Jun 2013 08:15:56 +0000 (01:15 -0700)
Bucket info now resides in an instance specific object. The
old bucket info object now contains a pointer to the new
instance.

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_rados.cc
src/rgw/rgw_rados.h

index 0325a60840c1b98b658bdae68f258be01516a747..d3f673f7488df64e3ec1c5ca37d3f9a743c5ef75 100644 (file)
@@ -177,12 +177,15 @@ done:
 }
 #endif
 
-int rgw_bucket_set_attrs(RGWRados *store, rgw_obj& obj,
+int rgw_bucket_set_attrs(RGWRados *store, rgw_bucket& bucket,
                          map<string, bufferlist>& attrs,
                          map<string, bufferlist>* rmattrs,
                          RGWObjVersionTracker *objv_tracker)
 {
-  return store->meta_mgr->set_attrs(bucket_meta_handler, obj.bucket.name,
+  string oid;
+  store->get_bucket_meta_oid(bucket, oid);
+  rgw_obj obj(store->zone.domain_root, oid);
+  return store->meta_mgr->set_attrs(bucket_meta_handler, oid,
                                     obj, attrs, rmattrs, objv_tracker);
 }
 
@@ -1363,7 +1366,8 @@ public:
       bci.info.bucket.index_pool = old_bci.info.bucket.index_pool;
     }
 
-    ret = store->put_bucket_info(entry, bci.info, false, &objv_tracker, mtime, &bci.attrs);
+#warning need to take care of different routes here
+    ret = store->put_bucket_info(entry, bci.info, false, &objv_tracker, mtime, &bci.attrs, false);
     if (ret < 0)
       return ret;
 
index a4c2fded5de2b48ee4ffdf31d73b6ded435d7bbb..09ddc653f73fad27973071be19ac201a606bf589 100644 (file)
@@ -100,7 +100,7 @@ extern int rgw_remove_user_bucket_info(RGWRados *store, string user_id, rgw_buck
 extern int rgw_remove_object(RGWRados *store, rgw_bucket& bucket, std::string& object);
 extern int rgw_remove_bucket(RGWRados *store, rgw_bucket& bucket, bool delete_children);
 
-extern int rgw_bucket_set_attrs(RGWRados *store, rgw_obj& obj,
+extern int rgw_bucket_set_attrs(RGWRados *store, rgw_bucket& obj,
                                 map<string, bufferlist>& attrs,
                                 map<string, bufferlist>* rmattrs,
                                 RGWObjVersionTracker *objv_tracker);
index bafe10d46db7384d3cf9567829128a7236d896fa..a3e3cf5472d867a168657a2aed1c047d8c8acc77 100644 (file)
@@ -607,15 +607,17 @@ struct RGWBucketInfo
   string region;
   time_t creation_time;
   string placement_rule;
+  bool has_instance_obj;
 
   void encode(bufferlist& bl) const {
-     ENCODE_START(7, 4, bl);
+     ENCODE_START(8, 4, bl);
      ::encode(bucket, bl);
      ::encode(owner, bl);
      ::encode(flags, bl);
      ::encode(region, bl);
      ::encode(creation_time, bl);
      ::encode(placement_rule, bl);
+     ::encode(has_instance_obj, bl);
      ENCODE_FINISH(bl);
   }
   void decode(bufferlist::iterator& bl) {
@@ -631,6 +633,8 @@ struct RGWBucketInfo
        ::decode(creation_time, bl);
      if (struct_v >= 7)
        ::decode(placement_rule, bl);
+     if (struct_v >= 8)
+       ::decode(has_instance_obj, bl);
      DECODE_FINISH(bl);
   }
   void dump(Formatter *f) const;
@@ -638,10 +642,38 @@ struct RGWBucketInfo
 
   void decode_json(JSONObj *obj);
 
-  RGWBucketInfo() : flags(0), creation_time(0) {}
+  RGWBucketInfo() : flags(0), creation_time(0), has_instance_obj(false) {}
 };
 WRITE_CLASS_ENCODER(RGWBucketInfo)
 
+struct RGWBucketEntryPoint
+{
+  rgw_bucket bucket;
+
+  bool has_bucket_info;
+  RGWBucketInfo old_bucket_info;
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(8, 8, bl);
+    ::encode(bucket, bl);
+    ENCODE_FINISH(bl);
+  }
+  void decode(bufferlist::iterator& bl) {
+    bufferlist::iterator orig_iter = bl;
+    DECODE_START_LEGACY_COMPAT_LEN_32(8, 4, 4, bl);
+    if (struct_v < 8) {
+      /* ouch, old entry, contains the bucket info itself */
+      old_bucket_info.decode(orig_iter);
+      has_bucket_info = true;
+      return;
+    }
+    has_bucket_info = false;
+    ::decode(bucket, bl);
+    DECODE_FINISH(bl);
+  }
+};
+WRITE_CLASS_ENCODER(RGWBucketEntryPoint)
+
 struct RGWBucketStats
 {
   RGWObjCategory category;
index 8555d825df5434307f6c9335235821c3fe037f88..bfc09bd6bd6ece11d9fcedd30a83208aa973e419 100644 (file)
@@ -444,6 +444,7 @@ void RGWBucketInfo::dump(Formatter *f) const
   encode_json("flags", flags, f);
   encode_json("region", region, f);
   encode_json("placement_rule", region, f);
+  encode_json("has_instance_obj", has_instance_obj, f);
 }
 
 void RGWBucketInfo::decode_json(JSONObj *obj) {
@@ -453,6 +454,7 @@ void RGWBucketInfo::decode_json(JSONObj *obj) {
   JSONDecoder::decode_json("flags", flags, obj);
   JSONDecoder::decode_json("region", region, obj);
   JSONDecoder::decode_json("placement_rule", region, obj);
+  JSONDecoder::decode_json("has_instance_obj", has_instance_obj, obj);
 }
 
 void RGWObjEnt::dump(Formatter *f) const
index 0ded08a94f4000a26e6bb3b13c288262381e2f88..0f009d2e19073f8d419ffe0328f9b64fc47b85fb 100644 (file)
@@ -1407,7 +1407,7 @@ void RGWPutMetadata::execute()
   if (s->object) {
     ret = store->set_attrs(s->obj_ctx, obj, attrs, &rmattrs, ptracker);
   } else {
-    ret = rgw_bucket_set_attrs(store, obj, attrs, &rmattrs, ptracker);
+    ret = rgw_bucket_set_attrs(store, obj.bucket, attrs, &rmattrs, ptracker);
   }
 }
 
@@ -1704,7 +1704,7 @@ void RGWPutACLs::execute()
   if (s->object) {
     ret = store->set_attrs(s->obj_ctx, obj, attrs, NULL, ptracker);
   } else {
-    ret = rgw_bucket_set_attrs(store, obj, attrs, NULL, ptracker);
+    ret = rgw_bucket_set_attrs(store, obj.bucket, attrs, NULL, ptracker);
   }
 }
 
index 3ccb083e71bea50f79c53ec37430db464e0626bd..2562a3afeb38a5fddd8eacc42c83cc72015358bd 100644 (file)
@@ -1805,7 +1805,7 @@ int RGWRados::create_bucket(RGWUserInfo& owner, rgw_bucket& bucket,
       time(&info.creation_time);
     else
       info.creation_time = creation_time;
-    ret = put_bucket_info(bucket.name, info, exclusive, &objv_tracker, 0, &attrs);
+    ret = put_bucket_info(bucket.name, info, exclusive, &objv_tracker, 0, &attrs, true);
     if (ret == -EEXIST) {
       librados::IoCtx index_ctx; // context for new bucket
       int r = open_bucket_index_ctx(bucket, index_ctx);
@@ -1813,7 +1813,8 @@ int RGWRados::create_bucket(RGWUserInfo& owner, rgw_bucket& bucket,
         return r;
 
       index_ctx.remove(dir_oid);
-      /* we need this for this objv_tracker */
+      /* we need to updated objv_tracker, but we don't want the old cruft there */
+      objv_tracker = RGWObjVersionTracker();
       r = get_bucket_info(NULL, bucket.name, info, &objv_tracker, NULL);
       if (r < 0) {
         if (r == -ENOENT) {
@@ -2838,7 +2839,7 @@ int RGWRados::set_bucket_owner(rgw_bucket& bucket, ACLOwner& owner)
 
   info.owner = owner.get_id();
 
-  r = put_bucket_info(bucket.name, info, false, &objv_tracker, 0, &attrs);
+  r = put_bucket_info(bucket.name, info, false, &objv_tracker, 0, &attrs, false);
   if (r < 0) {
     ldout(cct, 0) << "NOTICE: put_bucket_info on bucket=" << bucket.name << " returned err=" << r << dendl;
     return r;
@@ -2876,7 +2877,7 @@ int RGWRados::set_buckets_enabled(vector<rgw_bucket>& buckets, bool enabled)
       info.flags |= BUCKET_SUSPENDED;
     }
 
-    r = put_bucket_info(bucket.name, info, false, &objv_tracker, 0, &attrs);
+    r = put_bucket_info(bucket.name, info, false, &objv_tracker, 0, &attrs, false);
     if (r < 0) {
       ldout(cct, 0) << "NOTICE: put_bucket_info on bucket=" << bucket.name << " returned err=" << r << ", skipping bucket" << dendl;
       ret = r;
@@ -4463,38 +4464,103 @@ int RGWRados::get_bucket_stats(rgw_bucket& bucket, uint64_t *bucket_ver, uint64_
   return 0;
 }
 
+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, RGWObjVersionTracker *objv_tracker,
                               time_t *pmtime, map<string, bufferlist> *pattrs)
 {
   bufferlist bl;
 
-  int ret = rgw_get_system_obj(this, ctx, zone.domain_root, bucket_name, bl, objv_tracker, pmtime, pattrs);
+  RGWObjVersionTracker ot;
+  int ret = rgw_get_system_obj(this, ctx, zone.domain_root, bucket_name, bl, &ot, pmtime, pattrs);
   if (ret < 0) {
     info.bucket.name = bucket_name; /* only init this field */
     return ret;
   }
 
+  RGWBucketEntryPoint entry_point;
   bufferlist::iterator iter = bl.begin();
   try {
-    ::decode(info, iter);
+    ::decode(entry_point, iter);
   } catch (buffer::error& err) {
     ldout(cct, 0) << "ERROR: could not decode buffer info, caught buffer::error" << dendl;
     return -EIO;
   }
 
-  ldout(cct, 20) << "rgw_get_bucket_info: bucket=" << info.bucket << " owner " << info.owner << dendl;
+  if (entry_point.has_bucket_info) {
+    info = entry_point.old_bucket_info;
+    ldout(cct, 20) << "rgw_get_bucket_info: old bucket info, bucket=" << info.bucket << " owner " << info.owner << dendl;
+    return 0;
+  }
+
+  ldout(cct, 20) << "rgw_get_bucket_info: bucket instance: " << entry_point.bucket << dendl;
+
+  if (pattrs)
+    pattrs->clear();
+
+  /* read bucket instance info */
+
+  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, objv_tracker, pmtime, pattrs);
+  if (ret < 0) {
+    info.bucket.name = bucket_name; /* only init this field */
+    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, RGWObjVersionTracker *objv_tracker,
-                              time_t mtime, map<string, bufferlist> *pattrs)
+                              time_t mtime, map<string, bufferlist> *pattrs, bool create_entry_point)
 {
   bufferlist bl;
 
   ::encode(info, bl);
 
-  int ret = rgw_bucket_store_info(this, info.bucket.name, bl, exclusive, pattrs, objv_tracker, mtime);
+  bool create_head = !info.has_instance_obj || create_entry_point;
+
+  info.has_instance_obj = true;
+
+  string oid;
+  get_bucket_meta_oid(info.bucket, oid);
+  int ret = rgw_bucket_store_info(this, oid, bl, exclusive, pattrs, objv_tracker, mtime);
+  if (ret < 0) {
+    return ret;
+  }
+
+  if (!create_head)
+    return 0; /* done! */
+
+  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);
+
+  if (exclusive && ret == -EEXIST) {
+    rgw_obj obj(zone.domain_root, oid);
+    int r = delete_obj(NULL, obj);
+    if (r < 0) {
+      ldout(cct, 0) << "ERROR: failed removing object " << obj << " when trying to clean up" << dendl;
+    }
+  }
 
   return ret;
 }
index 4a21ad00e023db75141e0344a47d4ba2759bd436..ca15aa1c14a65b88d19af3b426a8afd9c0e1efbd 100644 (file)
@@ -1268,10 +1268,11 @@ 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);
   virtual int get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& info, RGWObjVersionTracker *objv_tracker,
                               time_t *pmtime, map<string, bufferlist> *pattrs = NULL);
   virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info, bool exclusive, RGWObjVersionTracker *objv_tracker,
-                              time_t mtime, map<string, bufferlist> *pattrs);
+                              time_t mtime, map<string, bufferlist> *pattrs, bool create_entry_point);
 
   int cls_rgw_init_index(librados::IoCtx& io_ctx, librados::ObjectWriteOperation& op, string& oid);
   int cls_obj_prepare_op(rgw_bucket& bucket, RGWModifyOp op, string& tag,