]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: track object versions between reads and writes
authorYehuda Sadeh <yehuda@inktank.com>
Tue, 19 Mar 2013 14:32:16 +0000 (07:32 -0700)
committerYehuda Sadeh <yehuda@inktank.com>
Wed, 8 May 2013 17:57:12 +0000 (10:57 -0700)
Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
src/rgw/rgw_admin.cc
src/rgw/rgw_cache.h
src/rgw/rgw_metadata.cc
src/rgw/rgw_metadata.h
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 f27d819baf5580185013707d4e271906d6d84f16..eb1b3b92c63b793905fc04bc0499941c6971c271 100644 (file)
@@ -549,6 +549,7 @@ int main(int argc, char **argv)
   RGWBucketAdminOpState bucket_op;
   string infile;
   string metadata_key;
+  RGWObjVersionTracker objv_tracker;
 
   std::string val;
   std::ostringstream errs;
index 2364aab3e4f5aabd27ca577d61be2d923195fac9..ec09552b5241ac0f5ba221179045175a37610420 100644 (file)
@@ -193,13 +193,14 @@ public:
                    map<std::string, bufferlist>& attrs, RGWObjCategory category, int flags,
                    map<std::string, bufferlist>* rmattrs, const bufferlist *data,
                    RGWObjManifest *manifest, const string *ptag, list<string> *remove_objs,
-                   bool modify_version, obj_version *objv);
+                   bool modify_version, RGWObjVersionTracker *objv_tracker);
   int put_obj_data(void *ctx, rgw_obj& obj, const char *data,
               off_t ofs, size_t len, bool exclusive);
 
-  int get_obj(void *ctx, obj_version *objv, void **handle, rgw_obj& obj, bufferlist& bl, off_t ofs, off_t end);
+  int get_obj(void *ctx, RGWObjVersionTracker *objv_tracker, void **handle, rgw_obj& obj, bufferlist& bl, off_t ofs, off_t end);
 
-  int obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime, uint64_t *epoch, map<string, bufferlist> *attrs, bufferlist *first_chunk, obj_version *objv);
+  int obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime, uint64_t *epoch, map<string, bufferlist> *attrs,
+               bufferlist *first_chunk, RGWObjVersionTracker *objv_tracker);
 
   int delete_obj(void *ctx, rgw_obj& obj);
 };
@@ -235,13 +236,13 @@ int RGWCache<T>::delete_obj(void *ctx, rgw_obj& obj)
 }
 
 template <class T>
-int RGWCache<T>::get_obj(void *ctx, obj_version *objv, void **handle, rgw_obj& obj, bufferlist& obl, off_t ofs, off_t end)
+int RGWCache<T>::get_obj(void *ctx, RGWObjVersionTracker *objv_tracker, void **handle, rgw_obj& obj, bufferlist& obl, off_t ofs, off_t end)
 {
   rgw_bucket bucket;
   string oid;
   normalize_bucket_and_obj(obj.bucket, obj.object, bucket, oid);
   if (bucket.name[0] != '.' || ofs != 0)
-    return T::get_obj(ctx, objv, handle, obj, obl, ofs, end);
+    return T::get_obj(ctx, objv_tracker, handle, obj, obl, ofs, end);
 
   string name = normal_name(obj.bucket, oid);
 
@@ -259,7 +260,7 @@ int RGWCache<T>::get_obj(void *ctx, obj_version *objv, void **handle, rgw_obj& o
     i.copy_all(obl);
     return bl.length();
   }
-  int r = T::get_obj(ctx, objv, handle, obj, obl, ofs, end);
+  int r = T::get_obj(ctx, objv_tracker, handle, obj, obl, ofs, end);
   if (r < 0) {
     if (r == -ENOENT) { // only update ENOENT, we'd rather retry other errors
       info.status = r;
@@ -353,7 +354,7 @@ int RGWCache<T>::put_obj_meta_impl(void *ctx, rgw_obj& obj, uint64_t size, time_
                               map<std::string, bufferlist>& attrs, RGWObjCategory category, int flags,
                               map<std::string, bufferlist>* rmattrs, const bufferlist *data,
                               RGWObjManifest *manifest, const string *ptag, list<string> *remove_objs,
-                              bool modify_version, obj_version *objv)
+                              bool modify_version, RGWObjVersionTracker *objv_tracker)
 {
   rgw_bucket bucket;
   string oid;
@@ -371,7 +372,7 @@ int RGWCache<T>::put_obj_meta_impl(void *ctx, rgw_obj& obj, uint64_t size, time_
     }
   }
   int ret = T::put_obj_meta_impl(ctx, obj, size, mtime, attrs, category, flags, rmattrs, data, manifest, ptag, remove_objs,
-                                 modify_version, objv);
+                                 modify_version, objv_tracker);
   if (cacheable) {
     string name = normal_name(bucket, oid);
     if (ret >= 0) {
@@ -425,13 +426,13 @@ int RGWCache<T>::put_obj_data(void *ctx, rgw_obj& obj, const char *data,
 template <class T>
 int RGWCache<T>::obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime,
                           uint64_t *pepoch, map<string, bufferlist> *attrs,
-                          bufferlist *first_chunk, obj_version *objv)
+                          bufferlist *first_chunk, RGWObjVersionTracker *objv_tracker)
 {
   rgw_bucket bucket;
   string oid;
   normalize_bucket_and_obj(obj.bucket, obj.object, bucket, oid);
   if (bucket.name[0] != '.')
-    return T::obj_stat(ctx, obj, psize, pmtime, pepoch, attrs, first_chunk, objv);
+    return T::obj_stat(ctx, obj, psize, pmtime, pepoch, attrs, first_chunk, objv_tracker);
 
   string name = normal_name(bucket, oid);
 
@@ -450,7 +451,7 @@ int RGWCache<T>::obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmti
     epoch = info.epoch;
     goto done;
   }
-  r = T::obj_stat(ctx, obj, &size, &mtime, &epoch, &info.xattrs, first_chunk, objv);
+  r = T::obj_stat(ctx, obj, &size, &mtime, &epoch, &info.xattrs, first_chunk, objv_tracker);
   if (r < 0) {
     if (r == -ENOENT) {
       info.status = r;
index 9296dc28e78b06f56fc31bdfbf2e4dcf7de1dea5..a1fc151275193f8efc4520b03315842709208081 100644 (file)
@@ -24,7 +24,9 @@ public:
   virtual string get_type() { return string(); }
 
   virtual int get(RGWRados *store, string& entry, RGWMetadataObject **obj) { return -ENOTSUP; }
-  virtual int put(RGWRados *store, string& entry, obj_version& objv, JSONObj *obj) { return -ENOTSUP; }
+  virtual int put(RGWRados *store, string& entry, RGWObjVersionTracker& objv_tracker, JSONObj *obj) { return -ENOTSUP; }
+  virtual int put_obj(RGWRados *store, string& key, bufferlist& bl, bool exclusive,
+                      RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs) { return -ENOTSUP; }
 
   virtual int list_keys_init(RGWRados *store, void **phandle) {
     iter_data *data = new iter_data;
@@ -77,6 +79,15 @@ int RGWMetadataManager::register_handler(RGWMetadataHandler *handler)
   return 0;
 }
 
+RGWMetadataHandler *RGWMetadataManager::get_handler(const char *type)
+{
+  map<string, RGWMetadataHandler *>::iterator iter = handlers.find(type);
+  if (iter == handlers.end())
+    return NULL;
+
+  return iter->second;
+}
+
 void RGWMetadataManager::parse_metadata_key(const string& metadata_key, string& type, string& entry)
 {
   int pos = metadata_key.find(':');
@@ -151,17 +162,20 @@ int RGWMetadataManager::put(string& metadata_key, bufferlist& bl)
   }
 
   string meadata_key;
-  obj_version objv;
+  RGWObjVersionTracker objv_tracker;
+
+  obj_version *objv = &objv_tracker.write_version;
+
 
   JSONDecoder::decode_json("key", metadata_key, &parser);
-  JSONDecoder::decode_json("ver", objv, &parser);
+  JSONDecoder::decode_json("ver", *objv, &parser);
 
   JSONObj *jo = parser.find_obj("data");
   if (!jo) {
     return -EINVAL;
   }
 
-  return handler->put(store, entry, objv, jo);
+  return handler->put(store, entry, objv_tracker, jo);
 }
 
 
@@ -224,3 +238,9 @@ void RGWMetadataManager::get_sections(list<string>& sections)
 }
 
 
+int RGWMetadataManager::put_obj(RGWMetadataHandler *handler, string& key, bufferlist& bl, bool exclusive,
+                                RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs)
+{
+  return handler->put_obj(store, key, bl, exclusive, objv_tracker, pattrs);
+}
+
index eb052e7b03cc75a193e0bc6d4edf820356b1aa2e..d432447e43fa6c15c018ebd7d8eacad89fc15226 100644 (file)
@@ -10,6 +10,7 @@
 
 class RGWRados;
 class JSONObj;
+class RGWObjVersionTracker;
 
 struct obj_version;
 
@@ -25,13 +26,21 @@ public:
   virtual void dump(Formatter *f) const = 0;
 };
 
+class RGWMetadataManager;
+
 class RGWMetadataHandler {
+  friend class RGWMetadataManager;
+
+protected:
+  virtual int put_obj(RGWRados *store, string& key, bufferlist& bl, bool exclusive,
+                      RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs = NULL) = 0;
 public:
   virtual ~RGWMetadataHandler() {}
   virtual string get_type() = 0;
 
   virtual int get(RGWRados *store, string& entry, RGWMetadataObject **obj) = 0;
-  virtual int put(RGWRados *store, string& entry, obj_version& objv, JSONObj *obj) = 0;
+  virtual int put(RGWRados *store, string& entry, RGWObjVersionTracker& objv_tracker, JSONObj *obj) = 0;
+
 
   virtual int list_keys_init(RGWRados *store, void **phandle) = 0;
   virtual int list_keys_next(void *handle, int max, list<string>& keys, bool *truncated) = 0;
@@ -52,6 +61,10 @@ public:
 
   int register_handler(RGWMetadataHandler *handler);
 
+  RGWMetadataHandler *get_handler(const char *type);
+
+  int put_obj(RGWMetadataHandler *handler, string& key, bufferlist& bl, bool exclusive,
+              RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs = NULL);
   int get(string& metadata_key, Formatter *f);
   int put(string& metadata_key, bufferlist& bl);
 
index 745692a51c70ca6219f01cb3c3c3934ded616883..d455e5635d98d40065d4cbaed7c39ffa7b73946b 100644 (file)
@@ -418,6 +418,34 @@ int RGWRegionMap::update(RGWRegion& region)
   return 0;
 }
 
+
+void RGWObjVersionTracker::prepare_op_for_read(ObjectReadOperation *op)
+{
+  obj_version *check_objv = version_for_check();
+
+  if (check_objv) {
+    cls_version_check(*op, *check_objv, VER_COND_EQ);
+  }
+
+  cls_version_read(*op, &read_version);
+}
+
+void RGWObjVersionTracker::prepare_op_for_write(ObjectWriteOperation *op)
+{
+  obj_version *check_objv = version_for_check();
+  obj_version *modify_version = version_for_write();
+
+  if (check_objv) {
+    cls_version_check(*op, *check_objv, VER_COND_EQ);
+  }
+
+  if (modify_version) {
+    cls_version_set(*op, *modify_version);
+  } else {
+    cls_version_inc(*op);
+  }
+}
+
 void RGWObjManifest::append(RGWObjManifest& m)
 {
   map<uint64_t, RGWObjManifestPart>::iterator iter;
@@ -1410,7 +1438,7 @@ int RGWRados::put_obj_meta_impl(void *ctx, rgw_obj& obj,  uint64_t size,
                  const string *ptag,
                   list<string> *remove_objs,
                   bool modify_version,
-                  obj_version *objv)
+                  RGWObjVersionTracker *objv_tracker)
 {
   rgw_bucket bucket;
   std::string oid, key;
@@ -1439,12 +1467,8 @@ int RGWRados::put_obj_meta_impl(void *ctx, rgw_obj& obj,  uint64_t size,
       return r;
   }
 
-  if (modify_version) {
-    if (objv) {
-      cls_version_set(op, *objv);
-    } else {
-      cls_version_inc(op);
-    }
+  if (objv_tracker) {
+    objv_tracker->prepare_op_for_write(&op);
   }
 
   if (data) {
@@ -1508,6 +1532,10 @@ int RGWRados::put_obj_meta_impl(void *ctx, rgw_obj& obj,  uint64_t size,
   if (r < 0)
     goto done_cancel;
 
+  if (objv_tracker) {
+    objv_tracker->apply_write();
+  }
+
   epoch = io_ctx.get_last_version();
 
   r = complete_atomic_overwrite(rctx, state, obj);
@@ -2239,7 +2267,7 @@ static void generate_fake_tag(CephContext *cct, map<string, bufferlist>& attrset
   tag_bl.append(tag.c_str(), tag.size() + 1);
 }
 
-int RGWRados::get_obj_state(RGWRadosCtx *rctx, rgw_obj& obj, RGWObjState **state, obj_version *objv)
+int RGWRados::get_obj_state(RGWRadosCtx *rctx, rgw_obj& obj, RGWObjState **state, RGWObjVersionTracker *objv_tracker)
 {
   RGWObjState *s = rctx->get_state(obj);
   ldout(cct, 20) << "get_obj_state: rctx=" << (void *)rctx << " obj=" << obj << " state=" << (void *)s << " s->prefetch_data=" << s->prefetch_data << dendl;
@@ -2247,7 +2275,7 @@ int RGWRados::get_obj_state(RGWRadosCtx *rctx, rgw_obj& obj, RGWObjState **state
   if (s->has_attrs)
     return 0;
 
-  int r = obj_stat(rctx, obj, &s->size, &s->mtime, &s->epoch, &s->attrset, (s->prefetch_data ? &s->data : NULL), objv);
+  int r = obj_stat(rctx, obj, &s->size, &s->mtime, &s->epoch, &s->attrset, (s->prefetch_data ? &s->data : NULL), objv_tracker);
   if (r == -ENOENT) {
     s->exists = false;
     s->has_attrs = true;
@@ -2642,7 +2670,7 @@ int RGWRados::prepare_get_obj(void *ctx, rgw_obj& obj,
             const char *if_nomatch,
             uint64_t *total_size,
             uint64_t *obj_size,
-            obj_version *objv,
+            RGWObjVersionTracker *objv_tracker,
             void **handle,
             struct rgw_err *err)
 {
@@ -2679,7 +2707,7 @@ int RGWRados::prepare_get_obj(void *ctx, rgw_obj& obj,
     rctx = new_ctx;
   }
 
-  r = get_obj_state(rctx, obj, &astate, objv);
+  r = get_obj_state(rctx, obj, &astate, objv_tracker);
   if (r < 0)
     goto done_err;
 
@@ -2983,7 +3011,7 @@ int RGWRados::clone_objs(void *ctx, rgw_obj& dst_obj,
 }
 
 
-int RGWRados::get_obj(void *ctx, obj_version *objv, void **handle, rgw_obj& obj,
+int RGWRados::get_obj(void *ctx, RGWObjVersionTracker *objv_tracker, void **handle, rgw_obj& obj,
                       bufferlist& bl, off_t ofs, off_t end)
 {
   rgw_bucket bucket;
@@ -3053,8 +3081,8 @@ int RGWRados::get_obj(void *ctx, obj_version *objv, void **handle, rgw_obj& obj,
       goto done_ret;
   }
 
-  if (objv) {
-    cls_version_check(op, *objv, VER_COND_EQ);
+  if (objv_tracker) {
+    objv_tracker->prepare_op_for_read(&op);
   }
 
   read_len = len;
@@ -3561,7 +3589,7 @@ int RGWRados::read(void *ctx, rgw_obj& obj, off_t ofs, size_t size, bufferlist&
 }
 
 int RGWRados::obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime, uint64_t *epoch, map<string, bufferlist> *attrs, bufferlist *first_chunk,
-                       obj_version *objv)
+                       RGWObjVersionTracker *objv_tracker)
 {
   rgw_bucket bucket;
   std::string oid, key;
@@ -3578,8 +3606,8 @@ int RGWRados::obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime,
   time_t mtime = 0;
 
   ObjectReadOperation op;
-  if (objv) {
-    cls_version_read(op, objv);
+  if (objv_tracker) {
+    objv_tracker->prepare_op_for_read(&op);
   }
   op.getxattrs(&attrset, NULL);
   op.stat(&size, &mtime, NULL);
index b262e6dc4b519d46b5425bbce6106053524e0c48..47c42b548ab034cba6f0d1b0dd4df3a144555780 100644 (file)
@@ -41,6 +41,37 @@ 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;
 
@@ -183,7 +214,7 @@ struct RGWObjState {
   bufferlist data;
   bool prefetch_data;
   bool keep_tail;
-  obj_version objv;
+  RGWObjVersionTracker objv_tracker;
 
   map<string, bufferlist> attrset;
   RGWObjState() : is_atomic(false), has_attrs(0), exists(false),
@@ -467,7 +498,7 @@ class RGWRados
   Mutex bucket_id_lock;
   uint64_t max_bucket_id;
 
-  int get_obj_state(RGWRadosCtx *rctx, rgw_obj& obj, RGWObjState **state, obj_version *objv);
+  int get_obj_state(RGWRadosCtx *rctx, rgw_obj& obj, RGWObjState **state, RGWObjVersionTracker *objv_tracker);
   int append_atomic_test(RGWRadosCtx *rctx, rgw_obj& obj,
                          librados::ObjectOperation& op, RGWObjState **state);
   int prepare_atomic_for_write_impl(RGWRadosCtx *rctx, rgw_obj& obj,
@@ -642,11 +673,12 @@ public:
     const string *ptag;
     list<string> *remove_objs;
     bool modify_version;
-    obj_version *objv;
+    RGWObjVersionTracker *objv_tracker;
 
     PutObjMetaExtraParams() : mtime(NULL), rmattrs(NULL),
                      data(NULL), manifest(NULL), ptag(NULL),
-                     remove_objs(NULL), modify_version(false), objv(NULL) {}
+                     remove_objs(NULL), modify_version(false),
+                     objv_tracker(NULL) {}
   };
 
   /** Write/overwrite an object to the bucket storage. */
@@ -654,7 +686,7 @@ public:
               map<std::string, bufferlist>& attrs, RGWObjCategory category, int flags,
               map<std::string, bufferlist>* rmattrs, const bufferlist *data,
               RGWObjManifest *manifest, const string *ptag, list<string> *remove_objs,
-              bool modify_version, obj_version *objv);
+              bool modify_version, RGWObjVersionTracker *objv_tracker);
 
   virtual int put_obj_meta(void *ctx, rgw_obj& obj, uint64_t size,
               map<std::string, bufferlist>& attrs, RGWObjCategory category, int flags,
@@ -668,7 +700,7 @@ public:
                            RGWObjCategory category, int flags, PutObjMetaExtraParams& params) {
     return put_obj_meta_impl(ctx, obj, size, params.mtime, attrs, category, flags,
                         params.rmattrs, params.data, params.manifest, params.ptag, params.remove_objs,
-                        params.modify_version, params.objv);
+                        params.modify_version, params.objv_tracker);
   }
 
   virtual int put_obj_data(void *ctx, rgw_obj& obj, const char *data,
@@ -677,7 +709,7 @@ public:
                                off_t ofs, bool exclusive, void **handle);
   /* note that put_obj doesn't set category on an object, only use it for none user objects */
   int put_system_obj(void *ctx, rgw_obj& obj, const char *data, size_t len, bool exclusive,
-              time_t *mtime, map<std::string, bufferlist>& attrs, obj_version *objv) {
+              time_t *mtime, map<std::string, bufferlist>& attrs, RGWObjVersionTracker *objv_tracker) {
     bufferlist bl;
     bl.append(data, len);
     int flags = PUT_OBJ_CREATE;
@@ -688,7 +720,7 @@ public:
     ep.mtime = mtime;
     ep.data = &bl;
     ep.modify_version = true;
-    ep.objv = objv;
+    ep.objv_tracker = objv_tracker;
 
     int ret = put_obj_meta(ctx, obj, len, attrs, RGW_OBJ_CATEGORY_NONE, flags, ep);
     return ret;
@@ -830,11 +862,11 @@ public:
             const char *if_nomatch,
             uint64_t *total_size,
             uint64_t *obj_size,
-            obj_version *objv,
+            RGWObjVersionTracker *objv_tracker,
             void **handle,
             struct rgw_err *err);
 
-  virtual int get_obj(void *ctx, obj_version *objv, void **handle, rgw_obj& obj,
+  virtual int get_obj(void *ctx, RGWObjVersionTracker *objv_tracker, void **handle, rgw_obj& obj,
                       bufferlist& bl, off_t ofs, off_t end);
 
   virtual void finish_get_obj(void **handle);
@@ -863,7 +895,7 @@ public:
 
   virtual int obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime,
                        uint64_t *epoch, map<string, bufferlist> *attrs, bufferlist *first_chunk,
-                       obj_version *objv);
+                       RGWObjVersionTracker *objv_tracker);
 
   virtual bool supports_omap() { return true; }
   int omap_get_vals(rgw_obj& obj, bufferlist& header, const std::string& marker, uint64_t count, std::map<string, bufferlist>& m);
index b36c182c2e4262e6de4f113455db0b0b6cf570fe..473a8b245c2fb6e78903c45d00e9ce0b277483c4 100644 (file)
@@ -15,7 +15,7 @@
 static map<string, string> ext_mime_map;
 
 int rgw_put_system_obj(RGWRados *rgwstore, rgw_bucket& bucket, string& oid, const char *data, size_t size, bool exclusive,
-                       obj_version *objv, map<string, bufferlist> *pattrs)
+                       RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs)
 {
   map<string,bufferlist> no_attrs;
   if (!pattrs)
@@ -23,18 +23,19 @@ int rgw_put_system_obj(RGWRados *rgwstore, rgw_bucket& bucket, string& oid, cons
 
   rgw_obj obj(bucket, oid);
 
-  int ret = rgwstore->put_system_obj(NULL, obj, data, size, exclusive, NULL, *pattrs, objv);
+  int ret = rgwstore->put_system_obj(NULL, obj, data, size, exclusive, NULL, *pattrs, objv_tracker);
 
   if (ret == -ENOENT) {
     ret = rgwstore->create_pool(bucket);
     if (ret >= 0)
-      ret = rgwstore->put_system_obj(NULL, obj, data, size, exclusive, NULL, *pattrs, objv);
+      ret = rgwstore->put_system_obj(NULL, obj, data, size, exclusive, NULL, *pattrs, objv_tracker);
   }
 
   return ret;
 }
 
-int rgw_get_system_obj(RGWRados *rgwstore, void *ctx, rgw_bucket& bucket, string& key, bufferlist& bl, obj_version *objv, map<string, bufferlist> *pattrs)
+int rgw_get_system_obj(RGWRados *rgwstore, void *ctx, rgw_bucket& bucket, string& key, bufferlist& bl,
+                       RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs)
 {
   int ret;
   struct rgw_err err;
@@ -42,13 +43,15 @@ int rgw_get_system_obj(RGWRados *rgwstore, void *ctx, rgw_bucket& bucket, string
   bufferlist::iterator iter;
   int request_len = READ_CHUNK_LEN;
   rgw_obj obj(bucket, key);
+
   do {
     ret = rgwstore->prepare_get_obj(ctx, obj, NULL, NULL, pattrs, NULL,
-                                  NULL, NULL, NULL, NULL, NULL, NULL, objv, &handle, &err);
+                                  NULL, NULL, NULL, NULL, NULL, NULL, objv_tracker, &handle, &err);
     if (ret < 0)
       return ret;
 
-    ret = rgwstore->get_obj(ctx, objv, &handle, obj, bl, 0, request_len - 1);
+    ret = rgwstore->get_obj(ctx, objv_tracker, &handle, obj, bl, 0, request_len - 1);
+#warning FIXME objv_tracker
     rgwstore->finish_get_obj(&handle);
     if (ret < 0)
       return ret;
index 01b5b1bbcd21dc0a9c476904440aead1d55b6dba..5c79525ad8f1bb58061a2c8b341aa9c66d929e92 100644 (file)
@@ -7,11 +7,14 @@
 #include "rgw_common.h"
 
 class RGWRados;
+class RGWObjVersionTracker;
 
 struct obj_version;
 
-int rgw_put_system_obj(RGWRados *rgwstore, rgw_bucket& bucket, string& oid, const char *data, size_t size, bool exclusive, obj_version *objv, map<string, bufferlist> *pattrs = NULL);
-int rgw_get_system_obj(RGWRados *rgwstore, void *ctx, rgw_bucket& bucket, string& key, bufferlist& bl, obj_version *objv, map<string, bufferlist> *pattrs = NULL);
+int rgw_put_system_obj(RGWRados *rgwstore, rgw_bucket& bucket, string& oid, const char *data, size_t size, bool exclusive,
+                       RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs = NULL);
+int rgw_get_system_obj(RGWRados *rgwstore, void *ctx, rgw_bucket& bucket, string& key, bufferlist& bl,
+                       RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs = NULL);
 
 int rgw_tools_init(CephContext *cct);
 void rgw_tools_cleanup();
index f194f1ee35559e8e45279a46eb45cd0cf48eded4..a6b72923f556e0b74d8b2e3488110cebc8034694 100644 (file)
@@ -23,6 +23,9 @@
 using namespace std;
 
 
+static RGWMetadataHandler *user_meta_handler = NULL;
+
+
 /**
  * Get the anonymous (ie, unauthenticated) user info.
  */
@@ -42,7 +45,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(RGWRados *store, RGWUserInfo& info, RGWUserInfo *old_info, obj_version *objv, bool exclusive)
+int rgw_store_user_info(RGWRados *store, RGWUserInfo& info, RGWUserInfo *old_info, RGWObjVersionTracker *objv_tracker, bool exclusive)
 {
   bufferlist bl;
   info.encode(bl);
@@ -88,14 +91,15 @@ int rgw_store_user_info(RGWRados *store, RGWUserInfo& info, RGWUserInfo *old_inf
   ::encode(ui, data_bl);
   ::encode(info, data_bl);
 
-  ret = rgw_put_system_obj(store, store->zone.user_uid_pool, info.user_id, data_bl.c_str(), data_bl.length(), exclusive, objv);
+  ret = store->meta_mgr->put_obj(user_meta_handler, info.user_id, data_bl, exclusive, objv_tracker);
   if (ret < 0)
     return ret;
 
   if (!info.user_email.empty()) {
     if (!old_info ||
         old_info->user_email.compare(info.user_email) != 0) { /* only if new index changed */
-      ret = rgw_put_system_obj(store, store->zone.user_email_pool, info.user_email, link_bl.c_str(), link_bl.length(), exclusive, objv);
+      ret = rgw_put_system_obj(store, store->zone.user_email_pool, info.user_email,
+                               link_bl.c_str(), link_bl.length(), exclusive, NULL);
       if (ret < 0)
         return ret;
     }
@@ -108,7 +112,9 @@ int rgw_store_user_info(RGWRados *store, RGWUserInfo& info, RGWUserInfo *old_inf
       if (old_info && old_info->access_keys.count(iter->first) != 0)
        continue;
 
-      ret = rgw_put_system_obj(store, store->zone.user_keys_pool, k.id, link_bl.c_str(), link_bl.length(), exclusive, objv);
+      ret = rgw_put_system_obj(store, store->zone.user_keys_pool, k.id,
+                               link_bl.c_str(), link_bl.length(), exclusive,
+                               NULL);
       if (ret < 0)
         return ret;
     }
@@ -120,7 +126,9 @@ int rgw_store_user_info(RGWRados *store, RGWUserInfo& info, RGWUserInfo *old_inf
     if (old_info && old_info->swift_keys.count(siter->first) != 0)
       continue;
 
-    ret = rgw_put_system_obj(store, store->zone.user_swift_pool, k.id, link_bl.c_str(), link_bl.length(), exclusive, objv);
+    ret = rgw_put_system_obj(store, store->zone.user_swift_pool, k.id,
+                             link_bl.c_str(), link_bl.length(), exclusive,
+                             NULL);
     if (ret < 0)
       return ret;
   }
@@ -128,7 +136,7 @@ int rgw_store_user_info(RGWRados *store, RGWUserInfo& info, RGWUserInfo *old_inf
   return ret;
 }
 
-int rgw_get_user_info_from_index(RGWRados *store, string& key, rgw_bucket& bucket, RGWUserInfo& info)
+int rgw_get_user_info_from_index(RGWRados *store, string& key, rgw_bucket& bucket, RGWUserInfo& info, RGWObjVersionTracker *objv_tracker)
 {
   bufferlist bl;
   RGWUID uid;
@@ -140,7 +148,7 @@ int rgw_get_user_info_from_index(RGWRados *store, string& key, rgw_bucket& bucke
   bufferlist::iterator iter = bl.begin();
   try {
     ::decode(uid, iter);
-    return rgw_get_user_info_by_uid(store, uid.user_id, info);
+    return rgw_get_user_info_by_uid(store, uid.user_id, info, objv_tracker);
   } catch (buffer::error& err) {
     ldout(store->ctx(), 0) << "ERROR: failed to decode user info, caught buffer::error" << dendl;
     return -EIO;
@@ -153,12 +161,12 @@ int rgw_get_user_info_from_index(RGWRados *store, string& key, rgw_bucket& bucke
  * Given a uid, finds the user info associated with it.
  * returns: 0 on success, -ERR# on failure (including nonexistence)
  */
-static int rgw_read_uid_info(RGWRados *store, string& uid, RGWUserInfo& info, obj_version *objv)
+int rgw_get_user_info_by_uid(RGWRados *store, string& uid, RGWUserInfo& info, RGWObjVersionTracker *objv_tracker)
 {
   bufferlist bl;
   RGWUID user_id;
 
-  int ret = rgw_get_system_obj(store, NULL, store->zone.user_uid_pool, uid, bl, objv);
+  int ret = rgw_get_system_obj(store, NULL, store->zone.user_uid_pool, uid, bl, objv_tracker);
   if (ret < 0)
     return ret;
 
@@ -180,36 +188,31 @@ static int rgw_read_uid_info(RGWRados *store, string& uid, RGWUserInfo& info, ob
   return 0;
 }
 
-int rgw_get_user_info_by_uid(RGWRados *store, string& uid, RGWUserInfo& info)
-{
-  return rgw_read_uid_info(store, uid, info, NULL);
-}
-
 /**
  * Given an email, finds the user info associated with it.
  * returns: 0 on success, -ERR# on failure (including nonexistence)
  */
-int rgw_get_user_info_by_email(RGWRados *store, string& email, RGWUserInfo& info)
+int rgw_get_user_info_by_email(RGWRados *store, string& email, RGWUserInfo& info, RGWObjVersionTracker *objv_tracker)
 {
-  return rgw_get_user_info_from_index(store, email, store->zone.user_email_pool, info);
+  return rgw_get_user_info_from_index(store, email, store->zone.user_email_pool, info, objv_tracker);
 }
 
 /**
  * Given an swift username, finds the user_info associated with it.
  * returns: 0 on success, -ERR# on failure (including nonexistence)
  */
-extern int rgw_get_user_info_by_swift(RGWRados *store, string& swift_name, RGWUserInfo& info)
+extern int rgw_get_user_info_by_swift(RGWRados *store, string& swift_name, RGWUserInfo& info, RGWObjVersionTracker *objv_tracker)
 {
-  return rgw_get_user_info_from_index(store, swift_name, store->zone.user_swift_pool, info);
+  return rgw_get_user_info_from_index(store, swift_name, store->zone.user_swift_pool, info, objv_tracker);
 }
 
 /**
  * Given an access key, finds the user info associated with it.
  * returns: 0 on success, -ERR# on failure (including nonexistence)
  */
-extern int rgw_get_user_info_by_access_key(RGWRados *store, string& access_key, RGWUserInfo& info)
+extern int rgw_get_user_info_by_access_key(RGWRados *store, string& access_key, RGWUserInfo& info, RGWObjVersionTracker *objv_tracker)
 {
-  return rgw_get_user_info_from_index(store, access_key, store->zone.user_keys_pool, info);
+  return rgw_get_user_info_from_index(store, access_key, store->zone.user_keys_pool, info, objv_tracker);
 }
 
 int rgw_remove_key_index(RGWRados *store, RGWAccessKey& access_key)
@@ -1477,16 +1480,16 @@ int RGWUser::init(RGWUserAdminOpState& op_state)
   }
 
   if (!uid.empty() && (uid.compare(RGW_USER_ANON_ID) != 0))
-    found = (rgw_get_user_info_by_uid(store, uid, user_info) >= 0);
+    found = (rgw_get_user_info_by_uid(store, uid, user_info, &op_state.objv) >= 0);
 
   if (!user_email.empty() && !found)
-    found = (rgw_get_user_info_by_email(store, user_email, user_info) >= 0);
+    found = (rgw_get_user_info_by_email(store, user_email, user_info, &op_state.objv) >= 0);
 
   if (!swift_user.empty() && !found)
-    found = (rgw_get_user_info_by_swift(store, swift_user, user_info) >= 0);
+    found = (rgw_get_user_info_by_swift(store, swift_user, user_info, &op_state.objv) >= 0);
 
   if (!access_key.empty() && !found)
-    found = (rgw_get_user_info_by_access_key(store, access_key, user_info) >= 0);
+    found = (rgw_get_user_info_by_access_key(store, access_key, user_info, &op_state.objv) >= 0);
 
   op_state.set_existing_user(found);
   if (found) {
@@ -2237,32 +2240,31 @@ public:
   int get(RGWRados *store, string& entry, RGWMetadataObject **obj) {
     RGWUserInfo info;
 
-    obj_version objv;
+    RGWObjVersionTracker objv_tracker;
 
-    int ret = rgw_read_uid_info(store, entry, info, &objv);
+    int ret = rgw_get_user_info_by_uid(store, entry, info, &objv_tracker);
     if (ret < 0)
       return ret;
 
-    RGWUserMetadataObject *mdo = new RGWUserMetadataObject(info, objv);
+    RGWUserMetadataObject *mdo = new RGWUserMetadataObject(info, objv_tracker.read_version);
 
     *obj = mdo;
 
     return 0;
   }
 
-  int put(RGWRados *store, string& entry, obj_version& objv, JSONObj *obj) {
+  int put(RGWRados *store, string& entry, RGWObjVersionTracker& objv_tracker, JSONObj *obj) {
     RGWUserInfo info;
 
     decode_json_obj(info, obj);
 
     RGWUserInfo old_info;
-    obj_version old_objv;
-    int ret = rgw_read_uid_info(store, entry, old_info, &old_objv);
+    int ret = rgw_get_user_info_by_uid(store, entry, old_info, &objv_tracker);
     if (ret < 0)
       return ret;
 
 
-    ret = rgw_store_user_info(store, info, &old_info, &objv, false);
+    ret = rgw_store_user_info(store, info, &old_info, &objv_tracker, false);
     if (ret < 0)
       return ret;
 
@@ -2274,6 +2276,13 @@ public:
     RGWListRawObjsCtx ctx;
   };
 
+  int put_obj(RGWRados *store, string& key, bufferlist& bl, bool exclusive,
+              RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs) {
+    return rgw_put_system_obj(store, store->zone.user_uid_pool, key,
+                              bl.c_str(), bl.length(), exclusive,
+                              objv_tracker, pattrs);
+  }
+
   int list_keys_init(RGWRados *store, void **phandle)
   {
     list_keys_info *info = new list_keys_info;
@@ -2322,5 +2331,6 @@ public:
 
 void rgw_user_init(RGWMetadataManager *mm)
 {
-  mm->register_handler(new RGWUserMetadataHandler);
+  user_meta_handler = new RGWUserMetadataHandler;
+  mm->register_handler(user_meta_handler);
 }
index 1aa09e73bb722cc69bf929d7075221930797a470..72eb42b0ad1bf96884ddf2559d69c63cff1a82df 100644 (file)
@@ -51,27 +51,27 @@ 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(RGWRados *store, RGWUserInfo& info, RGWUserInfo *old_info, obj_version *objv, bool exclusive);
+extern int rgw_store_user_info(RGWRados *store, RGWUserInfo& info, RGWUserInfo *old_info, RGWObjVersionTracker *objv_tracker, bool exclusive);
 /**
  * Given an email, finds the user info associated with it.
  * returns: 0 on success, -ERR# on failure (including nonexistence)
  */
-extern int rgw_get_user_info_by_uid(RGWRados *store, string& user_id, RGWUserInfo& info);
+extern int rgw_get_user_info_by_uid(RGWRados *store, string& user_id, RGWUserInfo& info, RGWObjVersionTracker *objv_tracker = NULL);
 /**
  * Given an swift username, finds the user info associated with it.
  * returns: 0 on success, -ERR# on failure (including nonexistence)
  */
-extern int rgw_get_user_info_by_email(RGWRados *store, string& email, RGWUserInfo& info);
+extern int rgw_get_user_info_by_email(RGWRados *store, string& email, RGWUserInfo& info, RGWObjVersionTracker *objv_tracker = NULL);
 /**
  * Given an swift username, finds the user info associated with it.
  * returns: 0 on success, -ERR# on failure (including nonexistence)
  */
-extern int rgw_get_user_info_by_swift(RGWRados *store, string& swift_name, RGWUserInfo& info);
+extern int rgw_get_user_info_by_swift(RGWRados *store, string& swift_name, RGWUserInfo& info, RGWObjVersionTracker *objv_tracker = NULL);
 /**
  * Given an access key, finds the user info associated with it.
  * returns: 0 on success, -ERR# on failure (including nonexistence)
  */
-extern int rgw_get_user_info_by_access_key(RGWRados *store, string& access_key, RGWUserInfo& info);
+extern int rgw_get_user_info_by_access_key(RGWRados *store, string& access_key, RGWUserInfo& info, RGWObjVersionTracker *objv_tracker = NULL);
 /**
  * Given an RGWUserInfo, deletes the user and its bucket ACLs.
  */
@@ -139,6 +139,7 @@ struct RGWUserAdminOpState {
   uint32_t max_buckets;
   __u8 suspended;
   std::string caps;
+  RGWObjVersionTracker objv;
 
   // subuser attributes
   std::string subuser;