]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: cache obj version
authorYehuda Sadeh <yehuda@inktank.com>
Sat, 11 May 2013 05:02:20 +0000 (22:02 -0700)
committerYehuda Sadeh <yehuda@inktank.com>
Sat, 11 May 2013 05:02:20 +0000 (22:02 -0700)
Also keep bucket objv_tracker on the request state.

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

index 97a5e47d0f7961a485a0f3118a2f8b8f32a0181b..5b96eb45b0886bc63e689d7fbde39ef165e8be23 100644 (file)
@@ -86,6 +86,9 @@ void ObjectCache::put(string& name, ObjectCacheInfo& info)
 
   if (info.flags & CACHE_FLAG_DATA)
     target.data = info.data;
+
+  if (info.flags & CACHE_FLAG_OBJV)
+    target.version = info.version;
 }
 
 void ObjectCache::remove(string& name)
index d920b3ae1ce9272e513319324fdfb92919d391c5..e32a921d1c634f9cc95752e0005b9781c2006384 100644 (file)
@@ -13,10 +13,11 @@ enum {
   REMOVE_OBJ,
 };
 
-#define CACHE_FLAG_DATA           0x1
-#define CACHE_FLAG_XATTRS         0x2
-#define CACHE_FLAG_META           0x4
-#define CACHE_FLAG_MODIFY_XATTRS  0x8
+#define CACHE_FLAG_DATA           0x01
+#define CACHE_FLAG_XATTRS         0x02
+#define CACHE_FLAG_META           0x04
+#define CACHE_FLAG_MODIFY_XATTRS  0x08
+#define CACHE_FLAG_OBJV           0x10
 
 #define mydout(v) lsubdout(T::cct, rgw, v)
 
@@ -54,11 +55,12 @@ struct ObjectCacheInfo {
   map<string, bufferlist> xattrs;
   map<string, bufferlist> rm_xattrs;
   ObjectMetaInfo meta;
+  obj_version version;
 
   ObjectCacheInfo() : status(0), flags(0), epoch(0) {}
 
   void encode(bufferlist& bl) const {
-    ENCODE_START(4, 3, bl);
+    ENCODE_START(5, 3, bl);
     ::encode(status, bl);
     ::encode(flags, bl);
     ::encode(data, bl);
@@ -66,10 +68,11 @@ struct ObjectCacheInfo {
     ::encode(meta, bl);
     ::encode(rm_xattrs, bl);
     ::encode(epoch, bl);
+    ::encode(version, bl);
     ENCODE_FINISH(bl);
   }
   void decode(bufferlist::iterator& bl) {
-    DECODE_START_LEGACY_COMPAT_LEN(4, 3, 3, bl);
+    DECODE_START_LEGACY_COMPAT_LEN(5, 3, 3, bl);
     ::decode(status, bl);
     ::decode(flags, bl);
     ::decode(data, bl);
@@ -79,6 +82,8 @@ struct ObjectCacheInfo {
       ::decode(rm_xattrs, bl);
     if (struct_v >= 4)
       ::decode(epoch, bl);
+    if (struct_v >= 5)
+      ::decode(version, bl);
     DECODE_FINISH(bl);
   }
   void dump(Formatter *f) const;
@@ -248,7 +253,12 @@ int RGWCache<T>::get_obj(void *ctx, RGWObjVersionTracker *objv_tracker, void **h
   string name = normal_name(obj.bucket, oid);
 
   ObjectCacheInfo info;
-  if (cache.get(name, info, CACHE_FLAG_DATA) == 0) {
+
+  uint32_t flags = CACHE_FLAG_DATA;
+  if (objv_tracker)
+    flags |= CACHE_FLAG_OBJV;
+  
+  if (cache.get(name, info, flags) == 0) {
     if (info.status < 0)
       return info.status;
 
@@ -259,6 +269,8 @@ int RGWCache<T>::get_obj(void *ctx, RGWObjVersionTracker *objv_tracker, void **h
     obl.clear();
 
     i.copy_all(obl);
+    if (objv_tracker)
+      objv_tracker->read_version = info.version;
     return bl.length();
   }
   int r = T::get_obj(ctx, objv_tracker, handle, obj, obl, ofs, end);
@@ -281,7 +293,10 @@ int RGWCache<T>::get_obj(void *ctx, RGWObjVersionTracker *objv_tracker, void **h
   bufferlist::iterator o = obl.begin();
   o.copy_all(bl);
   info.status = 0;
-  info.flags = CACHE_FLAG_DATA;
+  info.flags = flags;
+  if (objv_tracker) {
+    info.version = objv_tracker->read_version;
+  }
   cache.put(name, info);
   return r;
 }
@@ -299,6 +314,10 @@ int RGWCache<T>::set_attr(void *ctx, rgw_obj& obj, const char *attr_name, buffer
     info.xattrs[attr_name] = bl;
     info.status = 0;
     info.flags = CACHE_FLAG_MODIFY_XATTRS;
+    if (objv_tracker) {
+      info.version = objv_tracker->write_version;
+      info.flags |= CACHE_FLAG_OBJV;
+    }
   }
   int ret = T::set_attr(ctx, obj, attr_name, bl, objv_tracker);
   if (cacheable) {
@@ -334,6 +353,10 @@ int RGWCache<T>::set_attrs(void *ctx, rgw_obj& obj,
       info.rm_xattrs = *rmattrs;
     info.status = 0;
     info.flags = CACHE_FLAG_MODIFY_XATTRS;
+    if (objv_tracker) {
+      info.version = objv_tracker->write_version;
+      info.flags |= CACHE_FLAG_OBJV;
+    }
   }
   int ret = T::set_attrs(ctx, obj, attrs, rmattrs, objv_tracker);
   if (cacheable) {
@@ -372,6 +395,10 @@ int RGWCache<T>::put_obj_meta_impl(void *ctx, rgw_obj& obj, uint64_t size, time_
       info.data = *data;
       info.flags |= CACHE_FLAG_DATA;
     }
+    if (objv_tracker) {
+      info.version = objv_tracker->write_version;
+      info.flags |= CACHE_FLAG_OBJV;
+    }
   }
   int ret = T::put_obj_meta_impl(ctx, obj, size, mtime, attrs, category, flags, rmattrs, data, manifest, ptag, remove_objs,
                                  modify_version, objv_tracker);
@@ -443,7 +470,10 @@ int RGWCache<T>::obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmti
   uint64_t epoch;
 
   ObjectCacheInfo info;
-  int r = cache.get(name, info, CACHE_FLAG_META | CACHE_FLAG_XATTRS);
+  uint32_t flags = CACHE_FLAG_META | CACHE_FLAG_XATTRS;
+  if (objv_tracker)
+    flags |= CACHE_FLAG_OBJV;
+  int r = cache.get(name, info, flags);
   if (r == 0) {
     if (info.status < 0)
       return info.status;
@@ -451,6 +481,8 @@ int RGWCache<T>::obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmti
     size = info.meta.size;
     mtime = info.meta.mtime;
     epoch = info.epoch;
+    if (objv_tracker)
+      objv_tracker->read_version = info.version;
     goto done;
   }
   r = T::obj_stat(ctx, obj, &size, &mtime, &epoch, &info.xattrs, first_chunk, objv_tracker);
@@ -466,6 +498,10 @@ int RGWCache<T>::obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmti
   info.meta.mtime = mtime;
   info.meta.size = size;
   info.flags = CACHE_FLAG_META | CACHE_FLAG_XATTRS;
+  if (objv_tracker) {
+    info.flags |= CACHE_FLAG_OBJV;
+    info.version = objv_tracker->read_version;
+  }
   cache.put(name, info);
 done:
   if (psize)
index 67b1074d64a61befdf0809e1e28f6281b973c34f..1d8c32da98c44d166cbacdb5892ba5a65fc1ef77 100644 (file)
@@ -29,6 +29,8 @@
 #include "include/utime.h"
 #include "rgw_acl.h"
 #include "rgw_cors.h"
+#include "cls/version/cls_version_types.h"
+#include "include/rados/librados.hpp"
 
 using namespace std;
 
@@ -602,6 +604,37 @@ struct RGWEnv;
 
 class RGWClientIO;
 
+struct RGWObjVersionTracker {
+  obj_version read_version;
+  obj_version write_version;
+
+  obj_version *version_for_read() {
+    return &read_version;
+  }
+
+  obj_version *version_for_write() {
+    if (write_version.ver == 0)
+      return NULL;
+
+    return &write_version;
+  }
+
+  obj_version *version_for_check() {
+    if (read_version.ver == 0)
+      return NULL;
+
+    return &read_version;
+  }
+
+  void prepare_op_for_read(librados::ObjectReadOperation *op);
+  void prepare_op_for_write(librados::ObjectWriteOperation *op);
+
+  void apply_write() {
+    read_version = write_version;
+    write_version = obj_version();
+  }
+};
+
 /** Store all the state necessary to complete and respond to an HTTP request*/
 struct req_state {
    CephContext *cct;
@@ -639,6 +672,8 @@ struct req_state {
    ACLOwner bucket_owner;
    ACLOwner owner;
 
+   RGWObjVersionTracker objv_tracker;
+
    map<string, string> x_meta_map;
    bool has_bad_meta;
 
index d4a38eb775a4132f753aaa227aad474525ba3893..799971d1f19b24146e1958137b8a88182a97765a 100644 (file)
@@ -187,14 +187,14 @@ static int policy_from_attrset(CephContext *cct, map<string, bufferlist>& attrse
  * object: name of the object to get the ACL for.
  * Returns: 0 on success, -ERR# otherwise.
  */
-static int get_policy_from_attr(CephContext *cct, RGWRados *store, void *ctx, RGWAccessControlPolicy *policy, rgw_obj& obj)
+static int get_policy_from_attr(CephContext *cct, RGWRados *store, void *ctx, RGWAccessControlPolicy *policy, rgw_obj& obj,
+                                RGWObjVersionTracker *objv_tracker)
 {
   bufferlist bl;
   int ret = 0;
 
   if (obj.bucket.name.size()) {
-    RGWObjVersionTracker objv_tracker;
-    ret = store->get_attr(ctx, obj, RGW_ATTR_ACL, bl, &objv_tracker);
+    ret = store->get_attr(ctx, obj, RGW_ATTR_ACL, bl, objv_tracker);
 
     if (ret >= 0) {
       bufferlist::iterator iter = bl.begin();
@@ -214,7 +214,7 @@ static int get_policy_from_attr(CephContext *cct, RGWRados *store, void *ctx, RG
       /* object exists, but policy is broken */
       RGWBucketInfo info;
       RGWUserInfo uinfo;
-      int r = store->get_bucket_info(ctx, obj.bucket.name, info, &objv_tracker);
+      int r = store->get_bucket_info(ctx, obj.bucket.name, info, objv_tracker);
       if (r < 0)
         goto done;
       r = rgw_get_user_info_by_uid(store, info.owner, uinfo);
@@ -258,14 +258,14 @@ static int read_policy(RGWRados *store, struct req_state *s, RGWBucketInfo& buck
   } else {
     obj.init(bucket, oid);
   }
-  int ret = get_policy_from_attr(s->cct, store, s->obj_ctx, policy, obj);
+  int ret = get_policy_from_attr(s->cct, store, s->obj_ctx, policy, obj, &s->objv_tracker);
   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(s->cct);
     string no_object;
     rgw_obj no_obj(bucket, no_object);
-    ret = get_policy_from_attr(s->cct, store, s->obj_ctx, &bucket_policy, no_obj);
+    ret = get_policy_from_attr(s->cct, store, s->obj_ctx, &bucket_policy, no_obj, &s->objv_tracker);
     if (ret < 0)
       return ret;
     string& owner = bucket_policy.get_owner().get_id();
@@ -297,8 +297,7 @@ int rgw_build_policies(RGWRados *store, struct req_state *s, bool only_bucket, b
 
   RGWBucketInfo bucket_info;
   if (s->bucket_name_str.size()) {
-    RGWObjVersionTracker objv_tracker;
-    ret = store->get_bucket_info(s->obj_ctx, s->bucket_name_str, bucket_info, &objv_tracker);
+    ret = store->get_bucket_info(s->obj_ctx, s->bucket_name_str, bucket_info, &s->objv_tracker);
     if (ret < 0) {
       ldout(s->cct, 0) << "NOTICE: couldn't get bucket from bucket_name (name=" << s->bucket_name_str << ")" << dendl;
       return ret;
@@ -499,8 +498,7 @@ int RGWGetObj::handle_user_manifest(const char *prefix)
 
   if (bucket_name.compare(s->bucket.name) != 0) {
     RGWBucketInfo bucket_info;
-    RGWObjVersionTracker objv_tracker;
-    int r = store->get_bucket_info(NULL, bucket_name, bucket_info, &objv_tracker);
+    int r = store->get_bucket_info(NULL, bucket_name, bucket_info, &s->objv_tracker);
     if (r < 0) {
       ldout(s->cct, 0) << "could not get bucket info for bucket=" << bucket_name << dendl;
       return r;
@@ -855,7 +853,7 @@ void RGWCreateBucket::execute()
 
   s->bucket_owner.set_id(s->user.user_id);
   s->bucket_owner.set_name(s->user.display_name);
-  r = get_policy_from_attr(s->cct, store, s->obj_ctx, &old_policy, obj);
+  r = get_policy_from_attr(s->cct, store, s->obj_ctx, &old_policy, obj, &s->objv_tracker);
   if (r >= 0)  {
     if (old_policy.get_owner().get_id().compare(s->user.user_id) != 0) {
       ret = -EEXIST;
@@ -885,8 +883,7 @@ void RGWCreateBucket::execute()
      */
     RGWBucketInfo info;
     map<string, bufferlist> attrs;
-    RGWObjVersionTracker objv_tracker;
-    int r = store->get_bucket_info(NULL, s->bucket.name, info, &objv_tracker, &attrs);
+    int r = store->get_bucket_info(NULL, s->bucket.name, info, &s->objv_tracker, &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;
@@ -1584,10 +1581,8 @@ void RGWPutMetadata::execute()
 
   rgw_get_request_metadata(s, attrs);
 
-  RGWObjVersionTracker objv_tracker;
-
   /* no need to track object versioning, need it for bucket's data only */
-  RGWObjVersionTracker *ptracker = (s->object ? NULL : &objv_tracker);
+  RGWObjVersionTracker *ptracker = (s->object ? NULL : &s->objv_tracker);
 
   /* check if obj exists, read orig attrs */
   ret = get_obj_attrs(store, s, obj, orig_attrs, NULL, ptracker);
@@ -1893,8 +1888,7 @@ void RGWPutACLs::execute()
     *_dout << dendl;
   }
 
-  RGWObjVersionTracker objv_tracker;
-  RGWObjVersionTracker *ptracker = (s->object ? NULL : &objv_tracker);
+  RGWObjVersionTracker *ptracker = (s->object ? NULL : &s->objv_tracker);
 
   new_policy.encode(bl);
   obj.init(s->bucket, s->object_str);
@@ -1972,8 +1966,7 @@ void RGWPutCORS::execute()
     *_dout << dendl;
   }
 
-  RGWObjVersionTracker objv_tracker;
-  RGWObjVersionTracker *ptracker = (s->object ? NULL : &objv_tracker);
+  RGWObjVersionTracker *ptracker = (s->object ? NULL : &s->objv_tracker);
 
   string no_obj;
   cors_config->encode(bl);
@@ -2005,8 +1998,7 @@ void RGWDeleteCORS::execute()
   map<string, bufferlist> orig_attrs, attrs, rmattrs;
   map<string, bufferlist>::iterator iter;
 
-  RGWObjVersionTracker objv_tracker;
-  RGWObjVersionTracker *ptracker = (s->object ? NULL : &objv_tracker);
+  RGWObjVersionTracker *ptracker = (s->object ? NULL : &s->objv_tracker);
 
   /* check if obj exists, read orig attrs */
   ret = get_obj_attrs(store, s, obj, orig_attrs, NULL, ptracker);
index 444fdecf1a23ee7535996778577a39bf7ed58b16..f487a98b7d52228932a62f85db441e89b36f469a 100644 (file)
@@ -42,37 +42,6 @@ static inline void get_obj_bucket_and_oid_key(rgw_obj& obj, rgw_bucket& bucket,
   prepend_bucket_marker(bucket, obj.key, key);
 }
 
-struct RGWObjVersionTracker {
-  obj_version read_version;
-  obj_version write_version;
-
-  obj_version *version_for_read() {
-    return &read_version;
-  }
-
-  obj_version *version_for_write() {
-    if (write_version.ver == 0)
-      return NULL;
-
-    return &write_version;
-  }
-
-  obj_version *version_for_check() {
-    if (read_version.ver == 0)
-      return NULL;
-
-    return &read_version;
-  }
-
-  void prepare_op_for_read(librados::ObjectReadOperation *op);
-  void prepare_op_for_write(librados::ObjectWriteOperation *op);
-
-  void apply_write() {
-    read_version = write_version;
-    write_version = obj_version();
-  }
-};
-
 struct RGWUsageBatch {
   map<utime_t, rgw_usage_log_entry> m;