]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: write bucket info in one operation
authorYehuda Sadeh <yehuda@hq.newdream.net>
Fri, 23 Dec 2011 20:46:05 +0000 (12:46 -0800)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Fri, 23 Dec 2011 20:47:16 +0000 (12:47 -0800)
src/rgw/rgw_access.h
src/rgw/rgw_admin.cc
src/rgw/rgw_fs.cc
src/rgw/rgw_fs.h
src/rgw/rgw_op.cc
src/rgw/rgw_rados.cc
src/rgw/rgw_rados.h
src/rgw/rgw_tools.cc
src/rgw/rgw_tools.h
src/rgw/rgw_user.cc
src/rgw/rgw_user.h

index 071fba65a1b3472d12979b529329bd6a37aaade5..e0928c1f58b194ba6312370a79abdab6036757cf 100644 (file)
@@ -74,15 +74,15 @@ public:
                       map<std::string, bufferlist>& attrs, RGWObjCategory category, bool exclusive,
                       map<std::string, bufferlist>* rmattrs) = 0;
   virtual int put_obj_data(void *ctx, rgw_obj& obj, const char *data,
-                      off_t ofs, size_t len) = 0;
+                      off_t ofs, size_t len, bool exclusive) = 0;
   virtual int aio_put_obj_data(void *ctx, rgw_obj& obj, const char *data,
-                      off_t ofs, size_t len, void **handle) { return -ENOTSUP; }
+                      off_t ofs, size_t len, bool exclusive, void **handle) { return -ENOTSUP; }
 
   /* note that put_obj doesn't set category on an object, only use it for none user objects */
-  int put_obj(void *ctx, rgw_obj& obj, const char *data, size_t len,
+  int put_obj(void *ctx, rgw_obj& obj, const char *data, size_t len, bool exclusive,
               time_t *mtime, map<std::string, bufferlist>& attrs) {
-    int ret = put_obj_data(ctx, obj, data, -1, len);
-    if (ret >= 0) {
+    int ret = put_obj_data(ctx, obj, data, -1, len, exclusive);
+    if (ret >= 0 && (attrs.size() || mtime)) {
       ret = put_obj_meta(ctx, obj, len, mtime, attrs, RGW_OBJ_CATEGORY_NONE, false, NULL);
     }
     return ret;
@@ -265,7 +265,7 @@ public:
   /* The bucket here can either be the bucket name identifier, or the ID
    * in period format: ".123" */
   virtual int get_bucket_info(void *ctx, string& bucket, RGWBucketInfo& info) = 0;
-  virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info) = 0;
+  virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info, bool exclusive) = 0;
 
 
   virtual int remove_temp_objects(string date, string time) {
index c0377dc70375a16fb191d62946df43be48787afa..8582e0ab56fbc1118b87880f27500def98a8b4cf 100644 (file)
@@ -835,7 +835,7 @@ int main(int argc, char **argv)
 
       info.subusers[subuser] = u;
     }
-    if ((err = rgw_store_user_info(info)) < 0) {
+    if ((err = rgw_store_user_info(info, false)) < 0) {
       cerr << "error storing user info: " << cpp_strerror(-err) << std::endl;
       break;
     }
@@ -861,7 +861,7 @@ int main(int argc, char **argv)
         keys_map->erase(kiter);
       }
     }
-    if ((err = rgw_store_user_info(info)) < 0) {
+    if ((err = rgw_store_user_info(info, false)) < 0) {
       cerr << "error storing user info: " << cpp_strerror(-err) << std::endl;
       break;
     }
@@ -885,7 +885,7 @@ int main(int argc, char **argv)
       } else {
         rgw_remove_key_index(kiter->second);
         keys_map->erase(kiter);
-        if ((err = rgw_store_user_info(info)) < 0) {
+        if ((err = rgw_store_user_info(info, false)) < 0) {
           cerr << "error storing user info: " << cpp_strerror(-err) << std::endl;
           break;
         }
@@ -1261,7 +1261,7 @@ next:
 
     int ret;
     info.suspended = disable;
-    ret = rgw_store_user_info(info);
+    ret = rgw_store_user_info(info, false);
     if (ret < 0) {
       cerr << "ERROR: failed to store user info user=" << user_id << " ret=" << ret << std::endl;
       return 1;
index 21b82f656803919df35ebc4f2a71c0fb6ac2da35..3fbed040338adf5f4e6bf71d5d6d1087789a51ee 100644 (file)
@@ -254,7 +254,7 @@ done_err:
 }
 
 int RGWFS::put_obj_data(void *ctx, rgw_obj& obj, const char *data,
-                  off_t ofs, size_t size)
+                  off_t ofs, size_t size, bool exclusive)
 {
   rgw_bucket& bucket = obj.bucket;
   std::string& oid = obj.object;
@@ -331,7 +331,7 @@ int RGWFS::copy_obj(void *ctx, rgw_obj& dest_obj,
   }
   attrs = attrset;
 
-  ret = put_obj(ctx, dest_obj, data, ret, mtime, attrs);
+  ret = put_obj(ctx, dest_obj, data, ret, false, mtime, attrs);
 
   return ret;
 }
@@ -694,7 +694,7 @@ int RGWFS::get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& info)
   return -ENOTSUP;
 }
 
-int RGWFS::put_bucket_info(string& bucket_name, RGWBucketInfo& info)
+int RGWFS::put_bucket_info(string& bucket_name, RGWBucketInfo& info, bool exclusive)
 {
   return -ENOTSUP;
 }
index 96ea95c3d35d3187808777e7dafdacbff6d3a4b4..c78d53035e02a65865aba2d1815383f2730b8c41 100644 (file)
@@ -23,7 +23,7 @@ public:
              map<std::string, bufferlist>& attrs, RGWObjCategory category, bool exclusive,
              map<std::string, bufferlist> *rmattrs);
   int put_obj_data(void *ctx, rgw_obj& obj, const char *data,
-              off_t ofs, size_t size);
+              off_t ofs, size_t size, bool exclusive);
   int copy_obj(void *ctx, rgw_obj& dest_obj,
                rgw_obj& src_obj,
                time_t *mtime,
@@ -63,7 +63,7 @@ public:
   int obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime, map<string, bufferlist> *attrs);
 
   virtual int get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& info);
-  virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info);
+  virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info, bool exclusive);
 };
 
 #endif
index 12fd5aa0478ac5d3ac82579812c2604c552b7576..fd18d0933305c6438bb77c7921bb7f43934f1a52 100644 (file)
@@ -738,7 +738,7 @@ void RGWPutObj::execute()
         void *handle;
         ret = rgwstore->aio_put_obj_data(s->obj_ctx, obj,
                                     data,
-                                    ((ofs == 0) ? -1 : ofs), len, &handle);
+                                    ((ofs == 0) ? -1 : ofs), len, false, &handle);
         if (ret < 0)
           goto done_err;
 
index c960af5fc069008ad65ac22aa8d411303871a43e..69057456cf4ffe1fac46cf52547a8c23f245c877 100644 (file)
@@ -474,7 +474,7 @@ int RGWRados::create_bucket(string& owner, rgw_bucket& bucket,
       RGWBucketInfo info;
       info.bucket = bucket;
       info.owner = owner;
-      ret = store_bucket_info(info);
+      ret = store_bucket_info(info, exclusive);
       if (ret < 0) {
         dout(0) << "failed to store bucket info, removing bucket" << dendl;
         delete_bucket(bucket);
@@ -486,19 +486,23 @@ int RGWRados::create_bucket(string& owner, rgw_bucket& bucket,
   return ret;
 }
 
-int RGWRados::store_bucket_info(RGWBucketInfo& info)
+int RGWRados::store_bucket_info(RGWBucketInfo& info, bool exclusive)
 {
   bufferlist bl;
   ::encode(info, bl);
 
-  int ret = rgw_put_obj(info.owner, pi_buckets_rados, info.bucket.name, bl.c_str(), bl.length());
+  int ret = rgw_put_obj(info.owner, pi_buckets_rados, info.bucket.name, bl.c_str(), bl.length(), exclusive);
   if (ret < 0)
     return ret;
 
   char bucket_char[16];
   snprintf(bucket_char, sizeof(bucket_char), ".%lld", (long long unsigned)info.bucket.bucket_id);
   string bucket_id_string(bucket_char);
-  ret = rgw_put_obj(info.owner, pi_buckets_rados, bucket_id_string, bl.c_str(), bl.length());
+  ret = rgw_put_obj(info.owner, pi_buckets_rados, bucket_id_string, bl.c_str(), bl.length(), false);
+  if (ret < 0) {
+    dout(0) << "ERROR: failed to store " << pi_buckets_rados << ":" << bucket_id_string << " ret=" << ret << dendl;
+    return ret;
+  }
 
   dout(0) << "store_bucket_info: bucket=" << info.bucket << " owner " << info.owner << dendl;
   return 0;
@@ -692,17 +696,17 @@ int RGWRados::put_obj_meta(void *ctx, rgw_obj& obj,  uint64_t size,
  * Returns: 0 on success, -ERR# otherwise.
  */
 int RGWRados::put_obj_data(void *ctx, rgw_obj& obj,
-                          const char *data, off_t ofs, size_t len)
+                          const char *data, off_t ofs, size_t len, bool exclusive)
 {
   void *handle;
-  int r = aio_put_obj_data(ctx, obj, data, ofs, len, &handle);
+  int r = aio_put_obj_data(ctx, obj, data, ofs, len, exclusive, &handle);
   if (r < 0)
     return r;
   return aio_wait(handle);
 }
 
 int RGWRados::aio_put_obj_data(void *ctx, rgw_obj& obj,
-                              const char *data, off_t ofs, size_t len,
+                              const char *data, off_t ofs, size_t len, bool exclusive,
                                void **handle)
 {
   rgw_bucket bucket;
@@ -722,16 +726,17 @@ int RGWRados::aio_put_obj_data(void *ctx, rgw_obj& obj,
   AioCompletion *c = librados::Rados::aio_create_completion(NULL, NULL, NULL);
   *handle = c;
   
+  ObjectWriteOperation op;
 
-  if (ofs == -1) {
-    // write_full wants to write the complete bufferlist, not part of it
-    assert(bl.length() == len);
+  if (exclusive)
+    op.create(true);
 
-    r = io_ctx.aio_write_full(oid, c, bl);
-  }
-  else {
-    r = io_ctx.aio_write(oid, c, bl, len, ofs);
+  if (ofs == -1) {
+    op.write_full(bl);
+  else {
+    op.write(ofs, bl);
   }
+  r = io_ctx.aio_operate(oid, c, &op);
   if (r < 0)
     return r;
 
@@ -810,7 +815,7 @@ int RGWRados::copy_obj(void *ctx,
 
     // In the first call to put_obj_data, we pass ofs == -1 so that it will do
     // a write_full, wiping out whatever was in the object before this
-    r = put_obj_data(ctx, tmp_obj, data, ((ofs == 0) ? -1 : ofs), ret);
+    r = put_obj_data(ctx, tmp_obj, data, ((ofs == 0) ? -1 : ofs), ret, false);
     free(data);
     if (r < 0)
       goto done_err;
@@ -908,7 +913,7 @@ int RGWRados::set_buckets_enabled(vector<rgw_bucket>& buckets, bool enabled)
       info.flags |= BUCKET_SUSPENDED;
     }
 
-    r = put_bucket_info(bucket.name, info);
+    r = put_bucket_info(bucket.name, info, false);
     if (r < 0) {
       dout(0) << "put_bucket_info on bucket=" << bucket.name << " returned err=" << r << ", skipping bucket" << dendl;
       ret = r;
@@ -1816,7 +1821,7 @@ int RGWRados::get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& inf
   return 0;
 }
 
-int RGWRados::put_bucket_info(string& bucket_name, RGWBucketInfo& info)
+int RGWRados::put_bucket_info(string& bucket_name, RGWBucketInfo& info, bool exclusive)
 {
   bufferlist bl;
 
@@ -1824,7 +1829,7 @@ int RGWRados::put_bucket_info(string& bucket_name, RGWBucketInfo& info)
 
   string unused;
 
-  int ret = rgw_put_obj(unused, pi_buckets_rados, bucket_name, bl.c_str(), bl.length());
+  int ret = rgw_put_obj(unused, pi_buckets_rados, bucket_name, bl.c_str(), bl.length(), exclusive);
 
   return ret;
 }
index a77d3fc099c4d086eec7ab59a7898421cbb15cd4..e33dcdf3e517cf090ee462dfcfc983c95a6748d5 100644 (file)
@@ -134,7 +134,7 @@ class RGWRados  : public RGWAccess
   int delete_obj_impl(void *ctx, rgw_obj& src_obj, bool sync);
 
   int select_bucket_placement(std::string& bucket_name, rgw_bucket& bucket);
-  int store_bucket_info(RGWBucketInfo& info);
+  int store_bucket_info(RGWBucketInfo& info, bool exclusive);
 
 public:
   RGWRados() : lock("rados_timer_lock"), timer(NULL), watcher(NULL), watch_handle(0) {}
@@ -184,9 +184,9 @@ public:
               map<std::string, bufferlist>& attrs, RGWObjCategory category, bool exclusive,
               map<std::string, bufferlist>* rmattrs);
   virtual int put_obj_data(void *ctx, rgw_obj& obj, const char *data,
-              off_t ofs, size_t len);
+              off_t ofs, size_t len, bool exclusive);
   virtual int aio_put_obj_data(void *ctx, rgw_obj& obj, const char *data,
-                               off_t ofs, size_t len, void **handle);
+                               off_t ofs, size_t len, bool exclusive, void **handle);
   virtual int aio_wait(void *handle);
   virtual bool aio_completed(void *handle);
   virtual int clone_objs(void *ctx, rgw_obj& dst_obj, 
@@ -307,7 +307,7 @@ public:
   int decode_policy(bufferlist& bl, ACLOwner *owner);
   int get_bucket_stats(rgw_bucket& bucket, map<RGWObjCategory, RGWBucketStats>& stats);
   virtual int get_bucket_info(void *ctx, string& bucket_name, RGWBucketInfo& info);
-  virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info);
+  virtual int put_bucket_info(string& bucket_name, RGWBucketInfo& info, bool exclusive);
 
   int cls_rgw_init_index(rgw_bucket& bucket, string& oid);
   int cls_obj_prepare_op(rgw_bucket& bucket, uint8_t op, string& tag,
index eca5ce1f699f06a9d38f1c6dcfff5dd60b0f0ffc..81f89eb2eec5952e9a4058be4d2bd6563230745e 100644 (file)
 
 static map<string, string> ext_mime_map;
 
-int rgw_put_obj(string& uid, rgw_bucket& bucket, string& oid, const char *data, size_t size)
+int rgw_put_obj(string& uid, rgw_bucket& bucket, string& oid, const char *data, size_t size, bool exclusive)
 {
   map<string,bufferlist> attrs;
 
   rgw_obj obj(bucket, oid);
 
-  int ret = rgwstore->put_obj(NULL, obj, data, size, NULL, attrs);
+  int ret = rgwstore->put_obj(NULL, obj, data, size, exclusive, NULL, attrs);
 
   if (ret == -ENOENT) {
     ret = rgwstore->create_bucket(uid, bucket, attrs, true); //all callers are using system buckets
     if (ret >= 0)
-      ret = rgwstore->put_obj(NULL, obj, data, size, NULL, attrs);
+      ret = rgwstore->put_obj(NULL, obj, data, size, exclusive, NULL, attrs);
   }
 
   return ret;
index 5174d419c7a635e0871fdb2adebf24451e528495..c3230f859faf55220ec951904421cb5446d821af 100644 (file)
@@ -7,7 +7,7 @@
 #include "rgw_common.h"
 
 
-int rgw_put_obj(string& uid, rgw_bucket& bucket, string& oid, const char *data, size_t size);
+int rgw_put_obj(string& uid, rgw_bucket& bucket, string& oid, const char *data, size_t size, bool exclusive);
 int rgw_get_obj(void *ctx, rgw_bucket& bucket, string& key, bufferlist& bl);
 
 int rgw_tools_init(CephContext *cct);
index 6430092b1ad867246ca3e1c0fedb7ba9f00626ad..6088834f0aac31c808884e537bce808ff6ebf684 100644 (file)
@@ -40,7 +40,7 @@ bool rgw_user_is_authenticated(RGWUserInfo& info)
  * Save the given user information to storage.
  * Returns: 0 on success, -ERR# on failure.
  */
-int rgw_store_user_info(RGWUserInfo& info)
+int rgw_store_user_info(RGWUserInfo& info, bool exclusive)
 {
   bufferlist bl;
   info.encode(bl);
@@ -80,12 +80,12 @@ int rgw_store_user_info(RGWUserInfo& info)
   ::encode(ui, uid_bl);
   ::encode(info, uid_bl);
 
-  ret = rgw_put_obj(info.user_id, ui_uid_bucket, info.user_id, uid_bl.c_str(), uid_bl.length());
+  ret = rgw_put_obj(info.user_id, ui_uid_bucket, info.user_id, uid_bl.c_str(), uid_bl.length(), exclusive);
   if (ret < 0)
     return ret;
 
   if (info.user_email.size()) {
-    ret = rgw_put_obj(info.user_id, ui_email_bucket, info.user_email, uid_bl.c_str(), uid_bl.length());
+    ret = rgw_put_obj(info.user_id, ui_email_bucket, info.user_email, uid_bl.c_str(), uid_bl.length(), exclusive);
     if (ret < 0)
       return ret;
   }
@@ -94,7 +94,7 @@ int rgw_store_user_info(RGWUserInfo& info)
     map<string, RGWAccessKey>::iterator iter = info.access_keys.begin();
     for (; iter != info.access_keys.end(); ++iter) {
       RGWAccessKey& k = iter->second;
-      ret = rgw_put_obj(k.id, ui_key_bucket, k.id, uid_bl.c_str(), uid_bl.length());
+      ret = rgw_put_obj(k.id, ui_key_bucket, k.id, uid_bl.c_str(), uid_bl.length(), exclusive);
       if (ret < 0)
         return ret;
     }
@@ -103,7 +103,7 @@ int rgw_store_user_info(RGWUserInfo& info)
   map<string, RGWAccessKey>::iterator siter;
   for (siter = info.swift_keys.begin(); siter != info.swift_keys.end(); ++siter) {
     RGWAccessKey& k = siter->second;
-    ret = rgw_put_obj(info.user_id, ui_swift_bucket, k.id, uid_bl.c_str(), uid_bl.length());
+    ret = rgw_put_obj(info.user_id, ui_swift_bucket, k.id, uid_bl.c_str(), uid_bl.length(), exclusive);
     if (ret < 0)
       return ret;
   }
index 51294d05970915a151f6956e53cc10206a69249f..6c2cb807cd2196f182a9cc224825b464cd57de6b 100644 (file)
@@ -44,7 +44,7 @@ extern bool rgw_user_is_authenticated(RGWUserInfo& info);
  * Save the given user information to storage.
  * Returns: 0 on success, -ERR# on failure.
  */
-extern int rgw_store_user_info(RGWUserInfo& info);
+extern int rgw_store_user_info(RGWUserInfo& info, bool exclusive);
 /**
  * Given an email, finds the user info associated with it.
  * returns: 0 on success, -ERR# on failure (including nonexistence)