]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: introduce context to specific access calls
authorYehuda Sadeh <yehuda@hq.newdream.net>
Tue, 2 Aug 2011 23:29:16 +0000 (16:29 -0700)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Thu, 4 Aug 2011 22:58:33 +0000 (15:58 -0700)
15 files changed:
src/include/rados/librados.hpp
src/librados.cc
src/osdc/Objecter.h
src/rgw/rgw_access.h
src/rgw/rgw_admin.cc
src/rgw/rgw_cache.h
src/rgw/rgw_common.cc
src/rgw/rgw_common.h
src/rgw/rgw_fs.cc
src/rgw/rgw_fs.h
src/rgw/rgw_main.cc
src/rgw/rgw_op.cc
src/rgw/rgw_rados.cc
src/rgw/rgw_rados.h
src/rgw/rgw_user.cc

index d891fe8944fe50e8f4dc2e20eef2a3b2fde4fc18..6fd78ef68a6c7ae55cdbe2deacbd7d5bbee07de4 100644 (file)
@@ -121,7 +121,7 @@ namespace librados
     void zero(uint64_t off, uint64_t len);
     void rmxattr(const char *name);
     void setxattr(const char *name, const bufferlist& bl);
-    void cmpxattr(const char *name, const bufferlist& val, int op, int mode);
+    void cmpxattr(const char *name, const bufferlist& bl);
     void tmap_update(const bufferlist& cmdbl);
     void clone_range(uint64_t dst_off,
                      const std::string& src_oid, uint64_t src_off,
index 2c6acee08782ab65cb6607bf91121a733d40d51b..5986544f9eab1a8e20111ab07ea7e7ebf1055f1d 100644 (file)
@@ -190,10 +190,10 @@ void librados::ObjectOperation::setxattr(const char *name, const bufferlist& v)
   o->setxattr(name, v);
 }
 
-void librados::ObjectOperation::cmpxattr(const char *name, const bufferlist& v, int op, int mode)
+void librados::ObjectOperation::cmpxattr(const char *name, const bufferlist& v)
 {
   ::ObjectOperation *o = (::ObjectOperation *)impl;
-  o->cmpxattr(name, v, op, mode);
+  o->cmpxattr(name, v);
 }
 
 void librados::ObjectOperation::tmap_update(const bufferlist& cmdbl)
index dd45660fd1646facf1617b91f777527d6004f7d1..873ef68b74c4c5eee4d4063828b090b3877bbebc 100644 (file)
@@ -198,6 +198,9 @@ struct ObjectOperation {
     bl.append(s);
     add_xattr(CEPH_OSD_OP_SETXATTR, name, bl);
   }
+  void cmpxattr(const char *name, const bufferlist& bl) {
+    add_xattr(CEPH_OSD_OP_CMPXATTR, name, bl);
+  }
   void rmxattr(const char *name) {
     bufferlist bl;
     add_xattr(CEPH_OSD_OP_RMXATTR, name, bl);
index a232a5e8db65b0f3a6f5d408934aad4c70ce27b8..8b59ce6fcda1be9c36e7003727d714af5f201ed1 100644 (file)
@@ -60,18 +60,18 @@ public:
   virtual int create_bucket(std::string& id, std::string& bucket, map<std::string, bufferlist>& attrs, bool exclusive = true, uint64_t auid = 0) = 0;
   /** write an object to the storage device in the appropriate pool
     with the given stats */
-  virtual int put_obj_meta(std::string& id, rgw_obj& obj, time_t *mtime,
+  virtual int put_obj_meta(void *ctx, std::string& id, rgw_obj& obj, time_t *mtime,
                       map<std::string, bufferlist>& attrs, bool exclusive) = 0;
-  virtual int put_obj_data(std::string& id, rgw_obj& obj, const char *data,
+  virtual int put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
                       off_t ofs, size_t len) = 0;
-  virtual int aio_put_obj_data(std::string& id, rgw_obj& obj, const char *data,
+  virtual int aio_put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
                       off_t ofs, size_t len, void **handle) { return -ENOTSUP; }
 
-  int put_obj(std::string& id, rgw_obj& obj, const char *data, size_t len,
+  int put_obj(void *ctx, std::string& id, rgw_obj& obj, const char *data, size_t len,
               time_t *mtime, map<std::string, bufferlist>& attrs) {
-    int ret = put_obj_data(id, obj, data, -1, len);
+    int ret = put_obj_data(ctx, id, obj, data, -1, len);
     if (ret >= 0) {
-      ret = put_obj_meta(id, obj, mtime, attrs, false);
+      ret = put_obj_meta(ctx, id, obj, mtime, attrs, false);
     }
     return ret;
   }
@@ -96,7 +96,7 @@ public:
    * err: stores any errors resulting from the get of the original object
    * Returns: 0 on success, -ERR# otherwise.
    */
-  virtual int copy_obj(std::string& id, rgw_obj& dest_obj,
+  virtual int copy_obj(void *ctx, std::string& id, rgw_obj& dest_obj,
                       rgw_obj& src_obj,
                       time_t *mtime,
                       const time_t *mod_ptr,
@@ -128,7 +128,7 @@ public:
    * obj: name of the object to delete
    * Returns: 0 on success, -ERR# otherwise.
    */
-  virtual int delete_obj(std::string& id, rgw_obj& obj, bool sync = true) = 0;
+  virtual int delete_obj(void *ctx, std::string& id, rgw_obj& obj, bool sync = true) = 0;
 
 /**
  * Get data about an object out of RADOS and into memory.
@@ -152,7 +152,8 @@ public:
  *          (if get_data==true) length of read data,
  *          (if get_data==false) length of the object
  */
-  virtual int prepare_get_obj(rgw_obj& obj,
+  virtual int prepare_get_obj(void *ctx,
+            rgw_obj& obj,
             off_t ofs, off_t *end,
             map<string, bufferlist> *attrs,
             const time_t *mod_ptr,
@@ -165,16 +166,16 @@ public:
             void **handle,
             struct rgw_err *err) = 0;
 
-  virtual int get_obj(void **handle, rgw_obj& obj,
+  virtual int get_obj(void *ctx, void **handle, rgw_obj& obj,
             char **data, off_t ofs, off_t end) = 0;
 
   virtual void finish_get_obj(void **handle) = 0;
 
-  virtual int clone_range(rgw_obj& dst_obj, off_t dst_ofs,
+  virtual int clone_range(void *ctx, rgw_obj& dst_obj, off_t dst_ofs,
                           rgw_obj& src_obj, off_t src_ofs,
                           uint64_t size) = 0;
 
-  virtual int clone_obj(rgw_obj& dst_obj, off_t dst_ofs,
+  virtual int clone_obj(void *ctx, rgw_obj& dst_obj, off_t dst_ofs,
                           rgw_obj& src_obj, off_t src_ofs,
                           uint64_t size, map<string, bufferlist> attrs) {
     RGWCloneRangeInfo info;
@@ -184,16 +185,16 @@ public:
     info.dst_ofs = dst_ofs;
     info.len = size;
     v.push_back(info);
-    return clone_objs(dst_obj, v, attrs, true);
+    return clone_objs(ctx, dst_obj, v, attrs, true);
   }
 
-  virtual int clone_objs(rgw_obj& dst_obj,
+  virtual int clone_objs(void *ctx, rgw_obj& dst_obj,
                         vector<RGWCloneRangeInfo>& ranges,
                         map<string, bufferlist> attrs, bool truncate_dest) { return -ENOTSUP; }
  /**
    * a simple object read without keeping state
    */
-  virtual int read(rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl) = 0;
+  virtual int read(void *ctx, rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl) = 0;
 
   /**
    * Get the attributes for an object.
@@ -203,7 +204,7 @@ public:
    * dest: bufferlist to store the result in
    * Returns: 0 on success, -ERR# otherwise.
    */
-  virtual int get_attr(rgw_obj& obj, const char *name, bufferlist& dest) = 0;
+  virtual int get_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& dest) = 0;
 
   /**
    * Set an attr on an object.
@@ -213,14 +214,14 @@ public:
    * bl: the contents of the attr
    * Returns: 0 on success, -ERR# otherwise.
    */
-  virtual int set_attr(rgw_obj& obj, const char *name, bufferlist& bl) = 0;
+  virtual int set_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& bl) = 0;
 
   virtual int get_bucket_id(std::string& bucket) { return -ENOTSUP; }
 
  /**
   * stat an object
   */
-  virtual int obj_stat(rgw_obj& obj, uint64_t *psize, time_t *pmtime) = 0;
+  virtual int obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime) = 0;
 
   virtual bool supports_tmap() { return false; }
 
@@ -240,6 +241,9 @@ public:
   static RGWAccess *init_storage_provider(const char *type, CephContext *cct);
   static void close_storage();
   static RGWAccess *store;
+
+  virtual void *create_context() { return NULL; }
+  virtual void destroy_context(void *ctx) {}
 };
 
 class RGWStoreManager {
index 91ff18a693bf7f8fb162ddef93dadcb4e341adab..e796225a71ca24854ea8e3e8da01a6cee7249a5c 100644 (file)
@@ -300,7 +300,7 @@ static int create_bucket(string& bucket, string& user_id, string& display_name,
   if (ret && ret != -EEXIST)   
     goto done;
 
-  ret = rgwstore->set_attr(obj, RGW_ATTR_ACL, aclbl);
+  ret = rgwstore->set_attr(NULL, obj, RGW_ATTR_ACL, aclbl);
   if (ret < 0) {
     cerr << "couldn't set acl on bucket" << std::endl;
   }
@@ -702,7 +702,7 @@ int main(int argc, char **argv)
     string bucket_str(bucket);
     string object_str(object);
     rgw_obj obj(bucket_str, object_str);
-    int ret = store->get_attr(obj, RGW_ATTR_ACL, bl);
+    int ret = store->get_attr(NULL, obj, RGW_ATTR_ACL, bl);
 
     RGWAccessControlPolicy policy;
     if (ret >= 0) {
@@ -755,7 +755,7 @@ int main(int argc, char **argv)
     bufferlist aclbl;
     rgw_obj obj(bucket_str, no_oid);
 
-    int r = rgwstore->get_attr(obj, RGW_ATTR_ACL, aclbl);
+    int r = rgwstore->get_attr(NULL, obj, RGW_ATTR_ACL, aclbl);
     if (r >= 0) {
       RGWAccessControlPolicy policy;
       ACLOwner owner;
@@ -816,14 +816,14 @@ int main(int argc, char **argv)
 
     uint64_t size;
     rgw_obj obj(log_bucket, oid);
-    int r = store->obj_stat(obj, &size, NULL);
+    int r = store->obj_stat(NULL, obj, &size, NULL);
     if (r < 0) {
       cerr << "error while doing stat on " <<  log_bucket << ":" << oid
           << " " << cpp_strerror(-r) << std::endl;
       return -r;
     }
     bufferlist bl;
-    r = store->read(obj, 0, size, bl);
+    r = store->read(NULL, obj, 0, size, bl);
     if (r < 0) {
       cerr << "error while reading from " <<  log_bucket << ":" << oid
           << " " << cpp_strerror(-r) << std::endl;
@@ -923,7 +923,7 @@ int main(int argc, char **argv)
     bufferlist bl;
     rgw_obj obj(bucket_str, no_object);
 
-    ret = rgwstore->get_attr(obj, RGW_ATTR_ACL, bl);
+    ret = rgwstore->get_attr(NULL, obj, RGW_ATTR_ACL, bl);
     if (ret < 0) {
       RGW_LOG(0) << "can't read bucket acls: " << ret << dendl;
       return ret;
index 24860f80a09e381a701e9f8352ff3525daddf788..9bd8af9cfc96abb2e9294cf27ce9ced8c4db858b 100644 (file)
@@ -149,23 +149,23 @@ class RGWCache  : public T
 public:
   RGWCache() {}
 
-  int put_obj_data(std::string& id, rgw_obj& obj, const char *data,
+  int put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
               off_t ofs, size_t len);
 
-  int get_obj(void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end);
+  int get_obj(void *ctx, void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end);
 
-  int obj_stat(std::string& bucket, std::string& obj, uint64_t *psize, time_t *pmtime);
+  int obj_stat(void *ctx, std::string& bucket, std::string& obj, uint64_t *psize, time_t *pmtime);
 
-  int delete_obj(std::string& id, rgw_obj& obj, bool sync);
+  int delete_obj(void *ctx, std::string& id, rgw_obj& obj, bool sync);
 };
 
 
 template <class T>
-int RGWCache<T>::delete_obj(std::string& id, rgw_obj& obj, bool sync)
+int RGWCache<T>::delete_obj(void *ctx, std::string& id, rgw_obj& obj, bool sync)
 {
   string& bucket = obj.bucket;
   if (bucket[0] != '.')
-    return T::delete_obj(id, obj, sync);
+    return T::delete_obj(ctx, id, obj, sync);
 
   string name = normal_name(obj);
   cache.remove(name);
@@ -173,15 +173,15 @@ int RGWCache<T>::delete_obj(std::string& id, rgw_obj& obj, bool sync)
   ObjectCacheInfo info;
   distribute(obj, info, REMOVE_OBJ);
 
-  return T::delete_obj(id, obj, sync);
+  return T::delete_obj(ctx, id, obj, sync);
 }
 
 template <class T>
-int RGWCache<T>::get_obj(void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end)
+int RGWCache<T>::get_obj(void *ctx, void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end)
 {
   string& bucket = obj.bucket;
   if (bucket[0] != '.' || ofs != 0)
-    return T::get_obj(handle, obj, data, ofs, end);
+    return T::get_obj(ctx, handle, obj, data, ofs, end);
 
   string& oid = obj.object;
   string name = normal_name(bucket, oid);
@@ -197,7 +197,7 @@ int RGWCache<T>::get_obj(void **handle, rgw_obj& obj, char **data, off_t ofs, of
     memcpy(*data, bl.c_str(), bl.length());
     return bl.length();
   }
-  int r = T::get_obj(handle, obj, data, ofs, end);
+  int r = T::get_obj(ctx, handle, obj, data, ofs, end);
   if (r < 0) {
     if (r == -ENOENT) { // only update ENOENT, we'd rather retry other errors
       info.status = r;
@@ -218,7 +218,7 @@ int RGWCache<T>::get_obj(void **handle, rgw_obj& obj, char **data, off_t ofs, of
 }
 
 template <class T>
-int RGWCache<T>::put_obj_data(std::string& id, rgw_obj& obj, const char *data,
+int RGWCache<T>::put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
               off_t ofs, size_t len)
 {
   string& bucket = obj.bucket;
@@ -236,7 +236,7 @@ int RGWCache<T>::put_obj_data(std::string& id, rgw_obj& obj, const char *data,
     info.status = 0;
     info.flags = CACHE_FLAG_DATA;
   }
-  int ret = T::put_obj_data(id, obj, data, ofs, len);
+  int ret = T::put_obj_data(ctx, id, obj, data, ofs, len);
   if (cacheable) {
     if (ret >= 0) {
       cache.put(name, info);
@@ -252,10 +252,10 @@ int RGWCache<T>::put_obj_data(std::string& id, rgw_obj& obj, const char *data,
 }
 
 template <class T>
-int RGWCache<T>::obj_stat(std::string& bucket, std::string& obj, uint64_t *psize, time_t *pmtime)
+int RGWCache<T>::obj_stat(void *ctx, std::string& bucket, std::string& obj, uint64_t *psize, time_t *pmtime)
 {
   if (bucket[0] != '.')
-    return T::obj_stat(bucket, obj, psize, pmtime);
+    return T::obj_stat(ctx, bucket, obj, psize, pmtime);
 
   string name = normal_name(bucket, obj);
 
@@ -274,7 +274,7 @@ int RGWCache<T>::obj_stat(std::string& bucket, std::string& obj, uint64_t *psize
     mtime = info.meta.mtime;
     goto done;
   }
-  r = T::obj_stat(bucket, obj, &size, &mtime);
+  r = T::obj_stat(ctx, bucket, obj, &size, &mtime);
   if (r < 0) {
     if (r == -ENOENT) {
       info.status = r;
index 8b8c7e2113b7aa253e6222d971b987a87666c7aa..4574f4a7b734d1fdfffec442cb434e20e27600b4 100644 (file)
@@ -66,7 +66,6 @@ req_state::req_state(struct RGWEnv *e) : acl(NULL), os_auth_token(NULL), os_user
 }
 
 req_state::~req_state() {
-  delete acl;
   delete formatter;
   free(os_user);
   free(os_groups);
index 1cbe42801230a9f2926b6b600af79c26eacbdb25..677b25ef135392933ac2fec9d3740d398f9c496c 100644 (file)
@@ -47,6 +47,7 @@ extern string rgw_root_bucket;
 #define RGW_ATTR_BUCKETS       RGW_ATTR_PREFIX "buckets"
 #define RGW_ATTR_META_PREFIX   RGW_ATTR_PREFIX "x-amz-meta-"
 #define RGW_ATTR_CONTENT_TYPE  RGW_ATTR_PREFIX "content_type"
+#define RGW_ATTR_ID_TAG        RGW_ATTR_PREFIX "idtag"
 
 #define RGW_BUCKETS_OBJ_PREFIX ".buckets"
 
@@ -416,6 +417,8 @@ struct req_state {
 
    struct RGWEnv *env;
 
+   void *obj_ctx;
+
    req_state(struct RGWEnv *e);
    ~req_state();
 };
@@ -629,6 +632,12 @@ public:
     ::decode(ns, bl);
     ::decode(object, bl);
   }
+
+  bool operator<(const rgw_obj& o) const {
+    return  (bucket.compare(o.bucket) < 0) ||
+            (object.compare(o.object) < 0) ||
+            (ns.compare(o.ns) < 0);
+  }
 };
 WRITE_CLASS_ENCODER(rgw_obj)
 
index c8e9ad7619cdbba1b8878bbd7b725470a83a7bc2..d584f990b9afe825c6ab33edced2c8d8f10ef66d 100644 (file)
@@ -89,7 +89,7 @@ int RGWFS::list_buckets_next(string& id, RGWObjEnt& obj, RGWAccessHandle *handle
   }
 }
 
-int RGWFS::obj_stat(rgw_obj& obj, uint64_t *psize, time_t *pmtime)
+int RGWFS::obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime)
 {
   return -ENOTSUP;
 }
@@ -203,7 +203,7 @@ int RGWFS::create_bucket(std::string& id, std::string& bucket, map<std::string,
   return 0;
 }
 
-int RGWFS::put_obj_meta(std::string& id, rgw_obj& obj,
+int RGWFS::put_obj_meta(void *ctx, std::string& id, rgw_obj& obj,
                   time_t *mtime, map<string, bufferlist>& attrs, bool exclusive)
 {
   std::string& bucket = obj.bucket;
@@ -250,7 +250,7 @@ done_err:
   return -errno;
 }
 
-int RGWFS::put_obj_data(std::string& id, rgw_obj& obj, const char *data,
+int RGWFS::put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
                   off_t ofs, size_t size)
 {
   std::string& bucket = obj.bucket;
@@ -291,7 +291,7 @@ done_err:
   return r;
 }
 
-int RGWFS::copy_obj(std::string& id, rgw_obj& dest_obj,
+int RGWFS::copy_obj(void *ctx, std::string& id, rgw_obj& dest_obj,
                rgw_obj& src_obj,
                time_t *mtime,
                const time_t *mod_ptr,
@@ -309,13 +309,13 @@ int RGWFS::copy_obj(std::string& id, rgw_obj& dest_obj,
   time_t lastmod;
 
   map<string, bufferlist> attrset;
-  ret = prepare_get_obj(src_obj, 0, &end, &attrset, mod_ptr, unmod_ptr, &lastmod,
+  ret = prepare_get_obj(ctx, src_obj, 0, &end, &attrset, mod_ptr, unmod_ptr, &lastmod,
                         if_match, if_nomatch, &total_len, &obj_size, &handle, err);
   if (ret < 0)
     return ret;
  
   do { 
-    ret = get_obj(&handle, src_obj, &data, ofs, end);
+    ret = get_obj(ctx, &handle, src_obj, &data, ofs, end);
     if (ret < 0)
       return ret;
     ofs += ret;
@@ -327,7 +327,7 @@ int RGWFS::copy_obj(std::string& id, rgw_obj& dest_obj,
   }
   attrs = attrset;
 
-  ret = put_obj(id, dest_obj, data, ret, mtime, attrs);
+  ret = put_obj(ctx, id, dest_obj, data, ret, mtime, attrs);
 
   return ret;
 }
@@ -345,7 +345,7 @@ int RGWFS::delete_bucket(std::string& id, std::string& bucket)
 }
 
 
-int RGWFS::delete_obj(std::string& id, rgw_obj& obj, bool sync)
+int RGWFS::delete_obj(void *ctx, std::string& id, rgw_obj& obj, bool sync)
 {
   std::string& bucket = obj.bucket;
   std::string& oid = obj.object;
@@ -413,7 +413,7 @@ int RGWFS::get_attr(const char *name, const char *path, char **attr)
   return attr_len;
 }
 
-int RGWFS::get_attr(rgw_obj& obj, const char *name, bufferlist& dest)
+int RGWFS::get_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& dest)
 {
   std::string& bucket = obj.bucket;
   std::string& oid = obj.object;
@@ -434,7 +434,7 @@ done:
   return r;
 }
 
-int RGWFS::set_attr(rgw_obj& obj,
+int RGWFS::set_attr(void *ctx, rgw_obj& obj,
                        const char *name, bufferlist& bl)
 {
   std::string& bucket = obj.bucket;
@@ -453,7 +453,8 @@ int RGWFS::set_attr(rgw_obj& obj,
   return ret;
 }
 
-int RGWFS::prepare_get_obj(rgw_obj& obj,
+int RGWFS::prepare_get_obj(void *ctx,
+            rgw_obj& obj,
             off_t ofs, off_t *end,
             map<string, bufferlist> *attrs,
             const time_t *mod_ptr,
@@ -561,7 +562,7 @@ done_err:
   return r;
 }
 
-int RGWFS::get_obj(void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end)
+int RGWFS::get_obj(void *ctx, void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end)
 {
   uint64_t len;
   bufferlist bl;
@@ -616,7 +617,7 @@ void RGWFS::finish_get_obj(void **handle)
   }
 }
 
-int RGWFS::read(rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl)
+int RGWFS::read(void *ctx, rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl)
 {
   std::string& bucket = obj.bucket;
   std::string& oid = obj.object;
index a69456dea7dd17c1e1dbd92cd4e535ea7445b052..27ac43310f6023ce3acbeb5acbc2614864561b07 100644 (file)
@@ -19,13 +19,13 @@ public:
                    bool get_content_type, string& ns, bool *is_truncated, RGWAccessListFilter *filter);
 
   int create_bucket(std::string& id, std::string& bucket, map<std::string, bufferlist>& attrs, bool exclusive, uint64_t auid=0);
-  int put_obj_meta(std::string& id, rgw_obj& obj, time_t *mtime,
+  int put_obj_meta(void *ctx, std::string& id, rgw_obj& obj, time_t *mtime,
              map<std::string, bufferlist>& attrs, bool exclusive);
-  int put_obj_data(std::string& id, rgw_obj& obj, const char *data,
+  int put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
               off_t ofs, size_t size);
-  int clone_range(rgw_obj& dst_obj, off_t dst_ofs,
+  int clone_range(void *ctx, rgw_obj& dst_obj, off_t dst_ofs,
                   rgw_obj& src_obj, off_t src_ofs, uint64_t size) { return -ENOTSUP; }
-  int copy_obj(std::string& id, rgw_obj& dest_obj,
+  int copy_obj(void *ctx, std::string& id, rgw_obj& dest_obj,
                rgw_obj& src_obj,
                time_t *mtime,
                const time_t *mod_ptr,
@@ -35,14 +35,15 @@ public:
                map<std::string, bufferlist>& attrs,
                struct rgw_err *err);
   int delete_bucket(std::string& id, std::string& bucket);
-  int delete_obj(std::string& id, rgw_obj& obj, bool sync);
+  int delete_obj(void *ctx, std::string& id, rgw_obj& obj, bool sync);
 
   int get_attr(const char *name, int fd, char **attr);
   int get_attr(const char *name, const char *path, char **attr);
-  int get_attr(rgw_obj& obj, const char *name, bufferlist& dest);
-  int set_attr(rgw_obj& obj, const char *name, bufferlist& bl);
+  int get_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& dest);
+  int set_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& bl);
 
-  int prepare_get_obj(rgw_obj& obj,
+  int prepare_get_obj(void *ctx,
+            rgw_obj& obj,
             off_t ofs, off_t *end,
            map<std::string, bufferlist> *attrs,
             const time_t *mod_ptr,
@@ -55,11 +56,11 @@ public:
             void **handle,
             struct rgw_err *err);
 
-  int get_obj(void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end);
+  int get_obj(void *ctx, void **handle, rgw_obj& obj, char **data, off_t ofs, off_t end);
 
   void finish_get_obj(void **handle);
-  int read(rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl);
-  int obj_stat(rgw_obj& obj, uint64_t *psize, time_t *pmtime);
+  int read(void *ctx, rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl);
+  int obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime);
 };
 
 #endif
index 7313d9049ee3e2a6e1a178cbb0bf0dca908018bf..c8915b8fb98c22b97f710d552b41b843d4b1e3f1 100644 (file)
@@ -153,6 +153,7 @@ void RGWProcess::handle_request(FCGX_Request *fcgx)
   rgw_env.init(fcgx->envp);
 
   struct req_state *s = new req_state(&rgw_env);
+  s->obj_ctx = rgwstore->create_context();
 
   RGWOp *op = NULL;
   int init_error = 0;
@@ -201,6 +202,7 @@ done:
   int http_ret = s->err.http_ret;
 
   handler->put_op(op);
+  rgwstore->destroy_context(s->obj_ctx);
   delete s;
   FCGX_Finish_r(fcgx);
   delete fcgx;
index ead6b96c45bb59f6dd81e21eb893d84d202fbcab..c02d167de02d517131fbd33d7f00a8f5cea7722d 100644 (file)
@@ -137,13 +137,13 @@ void get_request_metadata(struct req_state *s, map<string, bufferlist>& attrs)
  * object: name of the object to get the ACL for.
  * Returns: 0 on success, -ERR# otherwise.
  */
-static int get_policy_from_attr(RGWAccessControlPolicy *policy, rgw_obj& obj)
+static int get_policy_from_attr(void *ctx, RGWAccessControlPolicy *policy, rgw_obj& obj)
 {
   bufferlist bl;
   int ret = 0;
 
   if (obj.bucket.size()) {
-    ret = rgwstore->get_attr(obj, RGW_ATTR_ACL, bl);
+    ret = rgwstore->get_attr(ctx, obj, RGW_ATTR_ACL, bl);
 
     if (ret >= 0) {
       bufferlist::iterator iter = bl.begin();
@@ -182,14 +182,14 @@ int read_acls(struct req_state *s, RGWAccessControlPolicy *policy, string& bucke
   }
   obj.init(bucket, oid, object);
 
-  int ret = get_policy_from_attr(policy, obj);
+  int ret = get_policy_from_attr(s->obj_ctx, policy, obj);
   if (ret == -ENOENT && object.size()) {
     /* object does not exist checking the bucket's ACL to make sure
        that we send a proper error code */
     RGWAccessControlPolicy bucket_policy;
     string no_object;
     rgw_obj no_obj(bucket, no_object);
-    ret = get_policy_from_attr(&bucket_policy, no_obj);
+    ret = get_policy_from_attr(s->obj_ctx, &bucket_policy, no_obj);
     if (ret < 0)
       return ret;
 
@@ -251,7 +251,7 @@ void RGWGetObj::execute()
   init_common();
 
   obj.init(s->bucket_str, s->object_str);
-  ret = rgwstore->prepare_get_obj(obj, ofs, &end, &attrs, mod_ptr,
+  ret = rgwstore->prepare_get_obj(s->obj_ctx, obj, ofs, &end, &attrs, mod_ptr,
                                   unmod_ptr, &lastmod, if_match, if_nomatch, &total_len, &s->obj_size, &handle, &s->err);
   if (ret < 0)
     goto done;
@@ -260,7 +260,7 @@ void RGWGetObj::execute()
     goto done;
 
   while (ofs <= end) {
-    ret = rgwstore->get_obj(&handle, obj, &data, ofs, end);
+    ret = rgwstore->get_obj(s->obj_ctx, &handle, obj, &data, ofs, end);
     if (ret < 0) {
       goto done;
     }
@@ -419,7 +419,7 @@ void RGWCreateBucket::execute()
 
   rgw_obj obj(rgw_root_bucket, s->bucket_str);
 
-  int r = get_policy_from_attr(&old_policy, obj);
+  int r = get_policy_from_attr(s->obj_ctx, &old_policy, obj);
   if (r >= 0)  {
     if (old_policy.get_owner().get_id().compare(s->user.user_id) != 0) {
       ret = -EEXIST;
@@ -621,7 +621,7 @@ void RGWPutObj::execute()
        // For the first call to put_obj_data, pass -1 as the offset to
        // do a write_full.
         void *handle;
-        ret = rgwstore->aio_put_obj_data(s->user.user_id, obj,
+        ret = rgwstore->aio_put_obj_data(s->obj_ctx, s->user.user_id, obj,
                                     data,
                                     ((ofs == 0) ? -1 : ofs), len, &handle);
         if (ret < 0)
@@ -689,16 +689,16 @@ void RGWPutObj::execute()
 
     if (!multipart) {
       rgw_obj dst_obj(s->bucket_str, s->object_str);
-      ret = rgwstore->clone_obj(dst_obj, 0, obj, 0, s->obj_size, attrs);
+      ret = rgwstore->clone_obj(s->obj_ctx, dst_obj, 0, obj, 0, s->obj_size, attrs);
       if (ret < 0)
         goto done_err;
       if (created_obj) {
-        ret = rgwstore->delete_obj(s->user.user_id, obj);
+        ret = rgwstore->delete_obj(s->obj_ctx, s->user.user_id, obj);
         if (ret < 0)
           goto done;
       }
     } else {
-      ret = rgwstore->put_obj_meta(s->user.user_id, obj, NULL, attrs, false);
+      ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, obj, NULL, attrs, false);
       if (ret < 0)
         goto done_err;
 
@@ -716,7 +716,7 @@ void RGWPutObj::execute()
 
       rgw_obj meta_obj(s->bucket_str, multipart_meta_obj, s->object_str, mp_ns);
       
-      ret  = rgwstore->put_obj_meta(s->user.user_id, meta_obj, NULL, meta_attrs, false);
+      ret  = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, meta_obj, NULL, meta_attrs, false);
     }
   }
 done:
@@ -726,7 +726,7 @@ done:
 
 done_err:
   if (created_obj)
-    rgwstore->delete_obj(s->user.user_id, obj);
+    rgwstore->delete_obj(s->obj_ctx, s->user.user_id, obj);
   drain_pending(pending);
   send_response();
 }
@@ -744,7 +744,7 @@ void RGWDeleteObj::execute()
   ret = -EINVAL;
   rgw_obj obj(s->bucket_str, s->object_str);
   if (s->object) {
-    ret = rgwstore->delete_obj(s->user.user_id, obj);
+    ret = rgwstore->delete_obj(s->obj_ctx, s->user.user_id, obj);
   }
 
   send_response();
@@ -850,7 +850,7 @@ void RGWCopyObj::execute()
 
   src_obj.init(src_bucket, src_object);
   dst_obj.init(s->bucket_str, s->object_str);
-  ret = rgwstore->copy_obj(s->user.user_id,
+  ret = rgwstore->copy_obj(s->obj_ctx, s->user.user_id,
                         dst_obj,
                         src_obj,
                         &mtime,
@@ -1064,7 +1064,7 @@ void RGWPutACLs::execute()
 
   new_policy.encode(bl);
   obj.init(s->bucket_str, s->object_str);
-  ret = rgwstore->set_attr(obj, RGW_ATTR_ACL, bl);
+  ret = rgwstore->set_attr(s->obj_ctx, obj, RGW_ATTR_ACL, bl);
 
 done:
   free(orig_data);
@@ -1122,7 +1122,7 @@ void RGWInitMultipart::execute()
     tmp_obj_name = mp.get_meta();
 
     obj.init(s->bucket_str, tmp_obj_name, s->object_str, mp_ns);
-    ret = rgwstore->put_obj_meta(s->user.user_id, obj, NULL, attrs, true);
+    ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, obj, NULL, attrs, true);
   } while (ret == -EEXIST);
 done:
   send_response();
@@ -1137,7 +1137,7 @@ static int get_multiparts_info(struct req_state *s, string& meta_oid, map<uint32
 
   rgw_obj obj(s->bucket_str, meta_oid, s->object_str, mp_ns);
 
-  int ret = rgwstore->prepare_get_obj(obj, 0, NULL, &attrs, NULL,
+  int ret = rgwstore->prepare_get_obj(s->obj_ctx, obj, 0, NULL, &attrs, NULL,
                                       NULL, NULL, NULL, NULL, NULL, NULL, &handle, &s->err);
   rgwstore->finish_get_obj(&handle);
 
@@ -1262,7 +1262,7 @@ void RGWCompleteMultipart::execute()
   attrs[RGW_ATTR_ETAG] = etag_bl;
 
   target_obj.init(s->bucket_str, s->object_str);
-  ret = rgwstore->put_obj_meta(s->user.user_id, target_obj, NULL, attrs, false);
+  ret = rgwstore->put_obj_meta(s->obj_ctx, s->user.user_id, target_obj, NULL, attrs, false);
   if (ret < 0)
     goto done;
   
@@ -1279,7 +1279,7 @@ void RGWCompleteMultipart::execute()
 
     ofs += obj_iter->second.size;
   }
-  ret = rgwstore->clone_objs(target_obj, ranges, attrs, true);
+  ret = rgwstore->clone_objs(s->obj_ctx, target_obj, ranges, attrs, true);
   if (ret < 0)
     goto done;
 
@@ -1287,11 +1287,11 @@ void RGWCompleteMultipart::execute()
   for (obj_iter = obj_parts.begin(); obj_iter != obj_parts.end(); ++obj_iter) {
     string oid = mp.get_part(obj_iter->second.num);
     rgw_obj obj(s->bucket_str, oid, s->object_str, mp_ns);
-    rgwstore->delete_obj(s->user.user_id, obj);
+    rgwstore->delete_obj(s->obj_ctx, s->user.user_id, obj);
   }
   // and also remove the metadata obj
   meta_obj.init(s->bucket_str, meta_oid, s->object_str, mp_ns);
-  rgwstore->delete_obj(s->user.user_id, meta_obj);
+  rgwstore->delete_obj(s->obj_ctx, s->user.user_id, meta_obj);
 
 done:
   send_response();
@@ -1331,13 +1331,13 @@ void RGWAbortMultipart::execute()
   for (obj_iter = obj_parts.begin(); obj_iter != obj_parts.end(); ++obj_iter) {
     string oid = mp.get_part(obj_iter->second.num);
     rgw_obj obj(s->bucket_str, oid, s->object_str, mp_ns);
-    ret = rgwstore->delete_obj(s->user.user_id, obj);
+    ret = rgwstore->delete_obj(s->obj_ctx, s->user.user_id, obj);
     if (ret < 0 && ret != -ENOENT)
       goto done;
   }
   // and also remove the metadata obj
   meta_obj.init(s->bucket_str, meta_oid, s->object_str, mp_ns);
-  ret = rgwstore->delete_obj(s->user.user_id, meta_obj);
+  ret = rgwstore->delete_obj(s->obj_ctx, s->user.user_id, meta_obj);
   if (ret == -ENOENT) {
     ret = -ERR_NO_SUCH_BUCKET;
   }
index 227d1cf1c96f89add89a1b3055de67e40b7604b9..b9a9501aecd9ecc08a175e7ee8ca4b16ea2e8205 100644 (file)
@@ -1,5 +1,6 @@
 #include <errno.h>
 #include <stdlib.h>
+#include <sys/types.h>
 
 #include "rgw_access.h"
 #include "rgw_rados.h"
@@ -333,7 +334,7 @@ int RGWRados::create_bucket(std::string& id, std::string& bucket, map<std::strin
  * exclusive: create object exclusively
  * Returns: 0 on success, -ERR# otherwise.
  */
-int RGWRados::put_obj_meta(std::string& id, rgw_obj& obj,
+int RGWRados::put_obj_meta(void *ctx, std::string& id, rgw_obj& obj,
                   time_t *mtime, map<string, bufferlist>& attrs, bool exclusive)
 {
   std::string& bucket = obj.bucket;
@@ -385,17 +386,17 @@ int RGWRados::put_obj_meta(std::string& id, rgw_obj& obj,
  * attrs: all the given attrs are written to bucket storage for the given object
  * Returns: 0 on success, -ERR# otherwise.
  */
-int RGWRados::put_obj_data(std::string& id, rgw_obj& obj,
+int RGWRados::put_obj_data(void *ctx, std::string& id, rgw_obj& obj,
                           const char *data, off_t ofs, size_t len)
 {
   void *handle;
-  int r = aio_put_obj_data(id, obj, data, ofs, len, &handle);
+  int r = aio_put_obj_data(ctx, id, obj, data, ofs, len, &handle);
   if (r < 0)
     return r;
   return aio_wait(handle);
 }
 
-int RGWRados::aio_put_obj_data(std::string& id, rgw_obj& obj,
+int RGWRados::aio_put_obj_data(void *ctx, std::string& id, rgw_obj& obj,
                               const char *data, off_t ofs, size_t len,
                                void **handle)
 {
@@ -458,7 +459,7 @@ bool RGWRados::aio_completed(void *handle)
  * err: stores any errors resulting from the get of the original object
  * Returns: 0 on success, -ERR# otherwise.
  */
-int RGWRados::copy_obj(std::string& id, rgw_obj& dest_obj,
+int RGWRados::copy_obj(void *ctx, std::string& id, rgw_obj& dest_obj,
                rgw_obj& src_obj,
                time_t *mtime,
                const time_t *mod_ptr,
@@ -488,7 +489,7 @@ int RGWRados::copy_obj(std::string& id, rgw_obj& dest_obj,
   void *handle = NULL;
 
   map<string, bufferlist> attrset;
-  ret = prepare_get_obj(src_obj, 0, &end, &attrset,
+  ret = prepare_get_obj(ctx, src_obj, 0, &end, &attrset,
                 mod_ptr, unmod_ptr, &lastmod, if_match, if_nomatch, &total_len, &obj_size, &handle, err);
 
   if (ret < 0)
@@ -496,13 +497,13 @@ int RGWRados::copy_obj(std::string& id, rgw_obj& dest_obj,
 
   off_t ofs = 0;
   do {
-    ret = get_obj(&handle, src_obj, &data, ofs, end);
+    ret = get_obj(ctx, &handle, src_obj, &data, ofs, end);
     if (ret < 0)
       return ret;
 
     // 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(id, tmp_obj, data, ((ofs == 0) ? -1 : ofs), ret);
+    r = put_obj_data(ctx, id, tmp_obj, data, ((ofs == 0) ? -1 : ofs), ret);
     free(data);
     if (r < 0)
       goto done_err;
@@ -515,11 +516,11 @@ int RGWRados::copy_obj(std::string& id, rgw_obj& dest_obj,
   }
   attrs = attrset;
 
-  ret = clone_obj(dest_obj, 0, tmp_obj, 0, end + 1, attrs);
+  ret = clone_obj(ctx, dest_obj, 0, tmp_obj, 0, end + 1, attrs);
   if (mtime)
-    obj_stat(tmp_obj, NULL, mtime);
+    obj_stat(ctx, tmp_obj, NULL, mtime);
 
-  r = rgwstore->delete_obj(id, tmp_obj, false);
+  r = rgwstore->delete_obj(ctx, id, tmp_obj, false);
   if (r < 0)
     RGW_LOG(0) << "ERROR: could not remove " << tmp_obj << dendl;
 
@@ -527,7 +528,7 @@ int RGWRados::copy_obj(std::string& id, rgw_obj& dest_obj,
 
   return ret;
 done_err:
-  rgwstore->delete_obj(id, tmp_obj, false);
+  rgwstore->delete_obj(ctx, id, tmp_obj, false);
   finish_get_obj(&handle);
   return r;
 }
@@ -553,7 +554,7 @@ int RGWRados::delete_bucket(std::string& id, std::string& bucket)
     return r;
 
   rgw_obj obj(rgw_root_bucket, bucket);
-  r = delete_obj(id, obj, true);
+  r = delete_obj(NULL, id, obj, true);
   if (r < 0)
     return r;
 
@@ -585,7 +586,7 @@ int RGWRados::purge_buckets(std::string& id, vector<std::string>& buckets)
     }
 
     rgw_obj obj(rgw_root_bucket, bucket);
-    r = delete_obj(id, obj, true);
+    r = delete_obj(NULL, id, obj, true);
     if (r < 0) {
       RGW_LOG(0) << "WARNING: could not remove bucket object: " << RGW_ROOT_BUCKET << ":" << bucket << dendl;
       ret = r;
@@ -667,7 +668,7 @@ int RGWRados::bucket_suspended(std::string& bucket, bool *suspended)
  * obj: name of the object to delete
  * Returns: 0 on success, -ERR# otherwise.
  */
-int RGWRados::delete_obj(std::string& id, rgw_obj& obj, bool sync)
+int RGWRados::delete_obj(void *ctx, std::string& id, rgw_obj& obj, bool sync)
 {
   std::string& bucket = obj.bucket;
   std::string& oid = obj.object;
@@ -692,6 +693,23 @@ int RGWRados::delete_obj(std::string& id, rgw_obj& obj, bool sync)
   return 0;
 }
 
+int RGWRados::get_obj_state(RGWRadosCtx *rctx, rgw_obj& obj, librados::IoCtx& io_ctx, string& actual_obj, RGWObjState **state)
+{
+  RGWObjState *s = rctx->get_state(obj);
+  if (s->has_attrs)
+    return 0;
+
+  *state = s;
+
+  int r = io_ctx.getxattrs(actual_obj, s->attrset);
+  if (r < 0)
+    return r;
+
+  s->has_attrs = true;
+  s->ver = io_ctx.get_last_version();
+  return 0;
+}
+
 /**
  * Get the attributes for an object.
  * bucket: name of the bucket holding the object.
@@ -700,13 +718,14 @@ int RGWRados::delete_obj(std::string& id, rgw_obj& obj, bool sync)
  * dest: bufferlist to store the result in
  * Returns: 0 on success, -ERR# otherwise.
  */
-int RGWRados::get_attr(rgw_obj& obj, const char *name, bufferlist& dest)
+int RGWRados::get_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& dest)
 {
   std::string& bucket = obj.bucket;
   std::string& oid = obj.object;
   librados::IoCtx io_ctx;
   string actual_bucket = bucket;
   string actual_obj = oid;
+  RGWRadosCtx *rctx = (RGWRadosCtx *)ctx;
 
   if (actual_obj.size() == 0) {
     actual_obj = bucket;
@@ -719,6 +738,16 @@ int RGWRados::get_attr(rgw_obj& obj, const char *name, bufferlist& dest)
 
   io_ctx.locator_set_key(obj.key);
 
+  if (rctx) {
+    RGWObjState *state;
+    r = get_obj_state(rctx, obj, io_ctx, actual_obj, &state);
+    if (r < 0)
+      return r;
+    if (state->get_attr(name, dest))
+      return 0;
+    return -ENODATA;
+  }
+  
   r = io_ctx.getxattr(actual_obj, name, dest);
   if (r < 0)
     return r;
@@ -734,13 +763,14 @@ int RGWRados::get_attr(rgw_obj& obj, const char *name, bufferlist& dest)
  * bl: the contents of the attr
  * Returns: 0 on success, -ERR# otherwise.
  */
-int RGWRados::set_attr(rgw_obj& obj, const char *name, bufferlist& bl)
+int RGWRados::set_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& bl)
 {
   std::string& bucket = obj.bucket;
   std::string& oid = obj.object;
   librados::IoCtx io_ctx;
   string actual_bucket = bucket;
   string actual_obj = oid;
+  RGWRadosCtx *rctx = (RGWRadosCtx *)ctx;
 
   if (actual_obj.size() == 0) {
     actual_obj = bucket;
@@ -753,7 +783,25 @@ int RGWRados::set_attr(rgw_obj& obj, const char *name, bufferlist& bl)
 
   io_ctx.locator_set_key(obj.key);
 
-  r = io_ctx.setxattr(actual_obj, name, bl);
+  if (rctx) {
+    RGWObjState *state;
+    r = get_obj_state(rctx, obj, io_ctx, actual_obj, &state);
+    if (r < 0)
+      return r;
+    ObjectOperation op;
+    if (state->obj_tag.length() > 0) // check for backward compatibility
+      op.cmpxattr(RGW_ATTR_ID_TAG, state->obj_tag);
+    op.setxattr(name, bl);
+
+    bufferlist outbl;
+    r = io_ctx.operate(actual_obj, &op, &outbl);
+
+    if (r >= 0)
+      state->attrset[name] = bl;
+  } else {
+    r = io_ctx.setxattr(actual_obj, name, bl);
+  }
+
   if (r < 0)
     return r;
 
@@ -783,7 +831,7 @@ int RGWRados::set_attr(rgw_obj& obj, const char *name, bufferlist& bl)
  *          (if get_data==true) length of read data,
  *          (if get_data==false) length of the object
  */
-int RGWRados::prepare_get_obj(rgw_obj& obj,
+int RGWRados::prepare_get_obj(void *ctx, rgw_obj& obj,
             off_t ofs, off_t *end,
             map<string, bufferlist> *attrs,
             const time_t *mod_ptr,
@@ -827,7 +875,7 @@ int RGWRados::prepare_get_obj(rgw_obj& obj,
   }
 
   if (attrs) {
-    r = state->io_ctx.getxattrs(oid, *attrs);
+    r = state->io_ctx.getxattrs(oid, *attrs); /* FIXME: should be get_xattrs(), using ctx */
     if (g_conf->rgw_log >= 20) {
       for (iter = attrs->begin(); iter != attrs->end(); ++iter) {
         RGW_LOG(20) << "Read xattr: " << iter->first << dendl;
@@ -860,7 +908,7 @@ int RGWRados::prepare_get_obj(rgw_obj& obj,
     }
   }
   if (if_match || if_nomatch) {
-    r = get_attr(obj, RGW_ATTR_ETAG, etag);
+    r = get_attr(ctx, obj, RGW_ATTR_ETAG, etag);
     if (r < 0)
       goto done_err;
 
@@ -902,7 +950,7 @@ done_err:
   return r;
 }
 
-int RGWRados::clone_range(rgw_obj& dst_obj, off_t dst_ofs,
+int RGWRados::clone_range(void *ctx, rgw_obj& dst_obj, off_t dst_ofs,
                           rgw_obj& src_obj, off_t src_ofs, uint64_t size)
 {
   std::string& bucket = dst_obj.bucket;
@@ -919,7 +967,7 @@ int RGWRados::clone_range(rgw_obj& dst_obj, off_t dst_ofs,
   return io_ctx.clone_range(dst_oid, dst_ofs, src_oid, src_ofs, size);
 }
 
-int RGWRados::clone_objs(rgw_obj& dst_obj,
+int RGWRados::clone_objs(void *ctx, rgw_obj& dst_obj,
                         vector<RGWCloneRangeInfo>& ranges,
                         map<string, bufferlist> attrs,
                         bool truncate_dest)
@@ -968,7 +1016,7 @@ int RGWRados::clone_objs(rgw_obj& dst_obj,
   return ret;
 }
 
-int RGWRados::get_obj(void **handle, rgw_obj& obj,
+int RGWRados::get_obj(void *ctx, void **handle, rgw_obj& obj,
             char **data, off_t ofs, off_t end)
 {
   std::string& oid = obj.object;
@@ -1014,7 +1062,7 @@ void RGWRados::finish_get_obj(void **handle)
 }
 
 /* a simple object read */
-int RGWRados::read(rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl)
+int RGWRados::read(void *ctx, rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl)
 {
   std::string& bucket = obj.bucket;
   std::string& oid = obj.object;
@@ -1029,7 +1077,7 @@ int RGWRados::read(rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl)
   return r;
 }
 
-int RGWRados::obj_stat(rgw_obj& obj, uint64_t *psize, time_t *pmtime)
+int RGWRados::obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime)
 {
   std::string& bucket = obj.bucket;
   std::string& oid = obj.object;
index 035f3ff45af16714f083f64ace813390f1c80009..890e3eed74811b69993e2d5f42b52e260b93e788 100644 (file)
@@ -7,6 +7,32 @@
 
 class RGWWatcher;
 
+struct RGWObjState {
+  bool is_atomic;
+  uint64_t ver;
+  bool has_attrs;
+  bufferlist obj_tag;
+
+  map<string, bufferlist> attrset;
+  RGWObjState() : is_atomic(false), ver(0), has_attrs(0) {}
+
+  bool get_attr(string name, bufferlist& dest) {
+    map<string, bufferlist>::iterator iter = attrset.find(name);
+    if (iter != attrset.end()) {
+      dest = iter->second;
+      return true;
+    }
+    return false;
+  }
+};
+
+struct RGWRadosCtx {
+  map<rgw_obj, RGWObjState> objs_state;
+  RGWObjState *get_state(rgw_obj& obj) {
+    return &objs_state[obj];
+  }
+};
+  
 class RGWRados  : public RGWAccess
 {
   /** Open the pool used as root for this gateway */
@@ -28,6 +54,7 @@ class RGWRados  : public RGWAccess
   librados::IoCtx root_pool_ctx;
   librados::IoCtx control_pool_ctx;
 
+  int get_obj_state(RGWRadosCtx *rctx, rgw_obj& obj, librados::IoCtx& io_ctx, string& actual_obj, RGWObjState **state);
 public:
   RGWRados() : watcher(NULL), watch_handle(0) {}
 
@@ -53,22 +80,22 @@ public:
   virtual int create_bucket(std::string& id, std::string& bucket, map<std::string,bufferlist>& attrs, bool exclusive = true, uint64_t auid = 0);
 
   /** Write/overwrite an object to the bucket storage. */
-  virtual int put_obj_meta(std::string& id, rgw_obj& obj, time_t *mtime,
+  virtual int put_obj_meta(void *ctx, std::string& id, rgw_obj& obj, time_t *mtime,
               map<std::string, bufferlist>& attrs, bool exclusive);
-  virtual int put_obj_data(std::string& id, rgw_obj& obj, const char *data,
+  virtual int put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
               off_t ofs, size_t len);
-  virtual int aio_put_obj_data(std::string& id, rgw_obj& obj, const char *data,
+  virtual int aio_put_obj_data(void *ctx, std::string& id, rgw_obj& obj, const char *data,
                                off_t ofs, size_t len, void **handle);
   virtual int aio_wait(void *handle);
   virtual bool aio_completed(void *handle);
-  virtual int clone_range(rgw_obj& dst_obj, off_t dst_ofs,
+  virtual int clone_range(void *ctx, rgw_obj& dst_obj, off_t dst_ofs,
                           rgw_obj& src_obj, off_t src_ofs, uint64_t size);
-  virtual int clone_objs(rgw_obj& dst_obj, 
+  virtual int clone_objs(void *ctx, rgw_obj& dst_obj, 
                         vector<RGWCloneRangeInfo>& ranges,
                         map<string, bufferlist> attrs, bool truncate_dest);
 
   /** Copy an object, with many extra options */
-  virtual int copy_obj(std::string& id, rgw_obj& dest_obj,
+  virtual int copy_obj(void *ctx, std::string& id, rgw_obj& dest_obj,
                rgw_obj& src_obj,
                time_t *mtime,
                const time_t *mod_ptr,
@@ -86,16 +113,16 @@ public:
   virtual int bucket_suspended(std::string& bucket, bool *suspended);
 
   /** Delete an object.*/
-  virtual int delete_obj(std::string& id, rgw_obj& src_obj, bool sync);
+  virtual int delete_obj(void *ctx, std::string& id, rgw_obj& src_obj, bool sync);
 
   /** Get the attributes for an object.*/
-  virtual int get_attr(rgw_obj& obj, const char *name, bufferlist& dest);
+  virtual int get_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& dest);
 
   /** Set an attr on an object. */
-  virtual int set_attr(rgw_obj& obj, const char *name, bufferlist& bl);
+  virtual int set_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& bl);
 
   /** Get data about an object out of RADOS and into memory. */
-  virtual int prepare_get_obj(rgw_obj& obj,
+  virtual int prepare_get_obj(void *ctx, rgw_obj& obj,
             off_t ofs, off_t *end,
             map<string, bufferlist> *attrs,
             const time_t *mod_ptr,
@@ -108,14 +135,14 @@ public:
             void **handle,
             struct rgw_err *err);
 
-  virtual int get_obj(void **handle, rgw_obj& obj,
+  virtual int get_obj(void *ctx, void **handle, rgw_obj& obj,
             char **data, off_t ofs, off_t end);
 
   virtual void finish_get_obj(void **handle);
 
-  virtual int read(rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl);
+  virtual int read(void *ctx, rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl);
 
-  virtual int obj_stat(rgw_obj& obj, uint64_t *psize, time_t *pmtime);
+  virtual int obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime);
 
   virtual int get_bucket_id(std::string& bucket);
 
@@ -130,6 +157,15 @@ public:
   virtual void finalize_watch();
   virtual int distribute(bufferlist& bl);
   virtual int watch_cb(int opcode, uint64_t ver, bufferlist& bl) { return 0; }
+
+  void *create_context() {
+    return new RGWRadosCtx();
+  }
+  void destroy_context(void *ctx) {
+    delete (RGWRadosCtx *)ctx;
+  }
+
+  void set_atomic_ops(void *ctx, rgw_obj& obj);
 };
 
 #endif
index f9835c6457b128a4e2d94145e44f1910b5328460..b92bea81c2543be548bf66c10199d83615b54eff 100644 (file)
@@ -44,12 +44,12 @@ static int put_obj(string& uid, string& bucket, string& oid, const char *data, s
 
   rgw_obj obj(bucket, oid);
 
-  int ret = rgwstore->put_obj(uid, obj, data, size, NULL, attrs);
+  int ret = rgwstore->put_obj(NULL, uid, obj, data, size, NULL, attrs);
 
   if (ret == -ENOENT) {
     ret = rgwstore->create_bucket(uid, bucket, attrs);
     if (ret >= 0)
-      ret = rgwstore->put_obj(uid, obj, data, size, NULL, attrs);
+      ret = rgwstore->put_obj(NULL, uid, obj, data, size, NULL, attrs);
   }
 
   return ret;
@@ -65,13 +65,13 @@ static int get_obj(string& bucket, string& key, bufferlist& bl)
   bufferlist::iterator iter;
   int request_len = READ_CHUNK_LEN;
   rgw_obj obj(bucket, key);
-  ret = rgwstore->prepare_get_obj(obj, 0, NULL, NULL, NULL,
+  ret = rgwstore->prepare_get_obj(NULL, obj, 0, NULL, NULL, NULL,
                                   NULL, NULL, NULL, NULL, NULL, NULL, &handle, &err);
   if (ret < 0)
     return ret;
 
   do {
-    ret = rgwstore->get_obj(&handle, obj, &data, 0, request_len - 1);
+    ret = rgwstore->get_obj(NULL, &handle, obj, &data, 0, request_len - 1);
     if (ret < 0)
       goto done;
     if (ret < request_len)
@@ -220,7 +220,7 @@ static int rgw_read_buckets_from_attr(string& user_id, RGWUserBuckets& buckets)
 {
   bufferlist bl;
   rgw_obj obj(ui_uid_bucket, user_id);
-  int ret = rgwstore->get_attr(obj, RGW_ATTR_BUCKETS, bl);
+  int ret = rgwstore->get_attr(NULL, obj, RGW_ATTR_BUCKETS, bl);
   if (ret)
     return ret;
 
@@ -258,7 +258,7 @@ int rgw_read_user_buckets(string user_id, RGWUserBuckets& buckets, bool need_sta
     rgw_obj obj(ui_uid_bucket, buckets_obj_id);
 
     do {
-      ret = rgwstore->read(obj, 0, len, bl);
+      ret = rgwstore->read(NULL, obj, 0, len, bl);
       if (ret == -ENOENT) {
         /* try to read the old format */
         ret = rgw_read_buckets_from_attr(user_id, buckets);
@@ -329,7 +329,7 @@ int rgw_write_buckets_attr(string user_id, RGWUserBuckets& buckets)
 
   rgw_obj obj(ui_uid_bucket, user_id);
 
-  int ret = rgwstore->set_attr(obj, RGW_ATTR_BUCKETS, bl);
+  int ret = rgwstore->set_attr(NULL, obj, RGW_ATTR_BUCKETS, bl);
 
   return ret;
 }
@@ -420,28 +420,28 @@ int rgw_remove_bucket(string user_id, string bucket_name, bool purge_data)
 int rgw_remove_key_index(RGWAccessKey& access_key)
 {
   rgw_obj obj(ui_key_bucket, access_key.id);
-  int ret = rgwstore->delete_obj(access_key.id, obj);
+  int ret = rgwstore->delete_obj(NULL, access_key.id, obj);
   return ret;
 }
 
 int rgw_remove_uid_index(string& uid)
 {
   rgw_obj obj(ui_uid_bucket, uid);
-  int ret = rgwstore->delete_obj(uid, obj);
+  int ret = rgwstore->delete_obj(NULL, uid, obj);
   return ret;
 }
 
 int rgw_remove_email_index(string& uid, string& email)
 {
   rgw_obj obj(ui_email_bucket, email);
-  int ret = rgwstore->delete_obj(uid, obj);
+  int ret = rgwstore->delete_obj(NULL, uid, obj);
   return ret;
 }
 
 int rgw_remove_openstack_name_index(string& uid, string& openstack_name)
 {
   rgw_obj obj(ui_openstack_bucket, openstack_name);
-  int ret = rgwstore->delete_obj(uid, obj);
+  int ret = rgwstore->delete_obj(NULL, uid, obj);
   return ret;
 }
 
@@ -473,20 +473,20 @@ int rgw_delete_user(RGWUserInfo& info, bool purge_data) {
   }
 
   rgw_obj uid_obj(ui_uid_bucket, info.user_id);
-  ret = rgwstore->delete_obj(info.user_id, uid_obj);
+  ret = rgwstore->delete_obj(NULL, info.user_id, uid_obj);
   if (ret < 0 && ret != -ENOENT)
     RGW_LOG(0) << "ERROR: could not remove " << info.user_id << ":" << uid_obj << ", should be fixed manually (err=" << ret << ")" << dendl;
 
   string buckets_obj_id;
   get_buckets_obj(info.user_id, buckets_obj_id);
   rgw_obj uid_bucks(ui_uid_bucket, buckets_obj_id);
-  ret = rgwstore->delete_obj(info.user_id, uid_bucks);
+  ret = rgwstore->delete_obj(NULL, info.user_id, uid_bucks);
   if (ret < 0 && ret != -ENOENT)
     RGW_LOG(0) << "ERROR: could not remove " << info.user_id << ":" << uid_bucks << ", should be fixed manually (err=" << ret << ")" << dendl;
   
 
   rgw_obj email_obj(ui_email_bucket, info.user_email);
-  ret = rgwstore->delete_obj(info.user_id, email_obj);
+  ret = rgwstore->delete_obj(NULL, info.user_id, email_obj);
   if (ret < 0 && ret != -ENOENT)
     RGW_LOG(0) << "ERROR: could not remove " << info.user_id << ":" << email_obj << ", should be fixed manually (err=" << ret << ")" << dendl;