]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: write and use the check_disk_state function
authorGreg Farnum <gregory.farnum@dreamhost.com>
Fri, 14 Oct 2011 16:01:04 +0000 (09:01 -0700)
committerGreg Farnum <gregory.farnum@dreamhost.com>
Thu, 20 Oct 2011 00:45:53 +0000 (17:45 -0700)
This is used to check the actual on-disk state, and encode
suggested updates for the index.
Then cls_bucket_list sends them back to the OSD.

Signed-off-by: Greg Farnum <gregory.farnum@dreamhost.com>
src/rgw/rgw_cls_api.h
src/rgw/rgw_rados.cc
src/rgw/rgw_rados.h

index 7d729844bdfd3ffdfc8ed26b0e4fdaf17e197e8f..c078cb80bc78e4cd415608f643b90676a283adbb 100644 (file)
@@ -6,6 +6,10 @@
 #include "include/types.h"
 #include "include/utime.h"
 
+
+#define CEPH_RGW_REMOVE 'r'
+#define CEPH_RGW_UPDATE 'u'
+
 enum RGWPendingState {
   CLS_RGW_STATE_PENDING_MODIFY,
   CLS_RGW_STATE_COMPLETE,
index 815fcb586f43ea339afe24774df0c56c4e9e5a51..19921c4b605ce33d3ce5be12fa179041e9172ed4 100644 (file)
@@ -2145,25 +2145,81 @@ int RGWRados::cls_bucket_list(rgw_bucket& bucket, string start, uint32_t num, ma
 
   struct rgw_bucket_dir& dir = ret.dir;
   map<string, struct rgw_bucket_dir_entry>::iterator miter;
+  bufferlist updates;
   for (miter = dir.m.begin(); miter != dir.m.end(); ++miter) {
     RGWObjEnt e;
     rgw_bucket_dir_entry& dirent = miter->second;
-    if (!dirent.exists)
-      continue;
 
+    // fill it in with initial values; we may correct later
     e.name = dirent.name;
     e.size = dirent.meta.size;
     e.mtime = dirent.meta.mtime;
     e.etag = dirent.meta.etag;
     e.owner = dirent.meta.owner;
     e.owner_display_name = dirent.meta.owner_display_name;
+
+    if (!dirent.exists || !dirent.pending_map.empty()) {
+      /* there are uncommitted ops. We need to check the current state,
+       * and if the tags are old we need to do cleanup as well. */
+      r = check_disk_state(io_ctx, bucket, dirent, e, updates);
+      if (r < 0) {
+        if (r == -ENOENT)
+          continue;
+        else
+          return r;
+      }
+    }
     m[e.name] = e;
     dout(0) << " got " << e.name << dendl;
   }
 
+  if (updates.length()) {
+    // we don't care if we lose suggested updates, send them off blindly
+    AioCompletion *c = librados::Rados::aio_create_completion(NULL, NULL, NULL);
+    r = io_ctx.aio_exec(oid, c, "rgw", "dir_suggest_changes", in, NULL);
+    c->release();
+  }
   return m.size();
 }
 
+int RGWRados::check_disk_state(librados::IoCtx& io_ctx,
+                               rgw_bucket& bucket,
+                               rgw_bucket_dir_entry& list_state,
+                               RGWObjEnt& object,
+                               bufferlist& suggested_updates)
+{
+  rgw_obj obj;
+  std::string oid, key;
+  obj.init(bucket, list_state.name);
+  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
+  int r = io_ctx.stat(oid, &object.size, &object.mtime);
+
+  list_state.pending_map.clear(); // we don't need this and it inflates size
+  if (r == -ENOENT) {
+      /* object doesn't exist right now -- hopefully because it's
+       * marked as !exists and got deleted */
+    if (list_state.exists) {
+      /* FIXME: what should happen now? Work out if there are any
+       * non-bad ways this could happen (there probably are, but annoying
+       * to handle!) */
+    }
+    // encode a suggested removal of that key
+    list_state.epoch = io_ctx.get_last_version();
+    suggested_updates.append(CEPH_RGW_REMOVE);
+    ::encode(list_state, suggested_updates);
+  }
+  if (r < 0)
+    return r;
+
+  // encode suggested updates
+  list_state.epoch = io_ctx.get_last_version();
+  list_state.meta.size = object.size;
+  list_state.meta.mtime.set_from_double(double(object.mtime));
+  suggested_updates.append(CEPH_RGW_UPDATE);
+  ::encode(list_state, suggested_updates);
+  return 0;
+}
+
 int RGWRados::cls_bucket_head(rgw_bucket& bucket, struct rgw_bucket_dir_header& header)
 {
   librados::IoCtx io_ctx;
index 405d3d513c04dff803e44aa1bf2b8ea586dd2ce4..2927229589b23bfb7d7cd9395b0cef74aab000cc 100644 (file)
@@ -320,6 +320,25 @@ public:
  private:
   int process_intent_log(rgw_bucket& bucket, string& oid,
                         time_t epoch, int flags, bool purge);
+  /**
+   * Check the actual on-disk state of the object specified
+   * by list_state, and fill in the time and size of object.
+   * Then append any changes to suggested_updates for
+   * the rgw class' dir_suggest_changes function.
+   *
+   * Note that this can maul list_state; don't use it afterwards. Also
+   * it expects object to already be filled in from list_state; it only
+   * sets the size and mtime.
+   *
+   * Returns 0 on success, -ENOENT if the object doesn't exist on disk,
+   * and -errno on other failures. (-ENOENT is not a failure, and it
+   * will encode that info as a suggested update.)
+   */
+  int check_disk_state(librados::IoCtx& io_ctx,
+                       rgw_bucket& bucket,
+                       rgw_bucket_dir_entry& list_state,
+                       RGWObjEnt& object,
+                       bufferlist& suggested_updates);
 
 };