]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
ceph_test_rados: test cache_flush, cache_try_flush, cache_evict
authorSage Weil <sage@inktank.com>
Thu, 12 Dec 2013 21:21:31 +0000 (13:21 -0800)
committerSage Weil <sage@inktank.com>
Fri, 20 Dec 2013 00:40:00 +0000 (16:40 -0800)
Signed-off-by: Sage Weil <sage@inktank.com>
src/test/osd/RadosModel.h
src/test/osd/TestRados.cc

index 5112c09f4aa880e262d6ba904b017166cb53413a..b6eebfc9d9f4546072702d3ace5211fc3475ac28 100644 (file)
@@ -19,6 +19,7 @@
 #include "TestOpStat.h"
 #include "test/librados/test.h"
 #include "common/sharedptr_registry.hpp"
+#include "common/errno.h"
 #include "osd/HitSet.h"
 
 #ifndef RADOSMODEL_H
@@ -55,7 +56,10 @@ enum TestOpType {
   TEST_OP_COPY_FROM,
   TEST_OP_HIT_SET_LIST,
   TEST_OP_UNDIRTY,
-  TEST_OP_IS_DIRTY
+  TEST_OP_IS_DIRTY,
+  TEST_OP_CACHE_FLUSH,
+  TEST_OP_CACHE_TRY_FLUSH,
+  TEST_OP_CACHE_EVICT
 };
 
 class TestWatchContext : public librados::WatchCtx {
@@ -422,7 +426,8 @@ public:
         ++i) {
       map<string,ObjectDesc>::iterator j = i->second.find(oid);
       if (j != i->second.end()) {
-       j->second.version = version;
+       if (version)
+         j->second.version = version;
        j->second.dirty = dirty;
        cout << __func__ << " oid " << oid
             << " v " << version << " " << j->second.most_recent()
@@ -1699,8 +1704,6 @@ public:
   {
     context->state_lock.Lock();
 
-    assert(context->find_object(oid, &old_value)); // FIXME snap?
-
     pair<TestOp*, TestOp::CallbackInfo*> *cb_arg =
       new pair<TestOp*, TestOp::CallbackInfo*>(this,
                                               new TestOp::CallbackInfo(0));
@@ -1725,6 +1728,8 @@ public:
     context->oid_in_use.erase(oid);
     context->oid_not_in_use.insert(oid);
 
+    assert(context->find_object(oid, &old_value)); // FIXME snap?
+
     int r = completion->get_return_value();
     if (r == 0) {
       cout << num << ":  " << (dirty ? "dirty" : "clean") << std::endl;
@@ -1752,4 +1757,154 @@ public:
 
 
 
+class CacheFlushOp : public TestOp {
+public:
+  librados::AioCompletion *completion;
+  librados::ObjectWriteOperation op;
+  string oid;
+  bool blocking;
+
+  CacheFlushOp(int n,
+              RadosTestContext *context,
+              const string &oid,
+              TestOpStat *stat,
+              bool b)
+    : TestOp(n, context, stat),
+      completion(NULL),
+      oid(oid),
+      blocking(b)
+  {}
+
+  void _begin()
+  {
+    context->state_lock.Lock();
+    pair<TestOp*, TestOp::CallbackInfo*> *cb_arg =
+      new pair<TestOp*, TestOp::CallbackInfo*>(this,
+                                              new TestOp::CallbackInfo(0));
+    completion = context->rados.aio_create_completion((void *) cb_arg,
+                                                     &write_callback, 0);
+    // leave object in unused list so that we race with other operations
+    //context->oid_in_use.insert(oid);
+    //context->oid_not_in_use.erase(oid);
+    context->state_lock.Unlock();
+
+    unsigned flags = librados::OPERATION_IGNORE_CACHE;
+    if (blocking) {
+      op.cache_flush();
+    } else {
+      op.cache_try_flush();
+      flags = librados::OPERATION_SKIPRWLOCKS;
+    }
+    int r = context->io_ctx.aio_operate(context->prefix+oid, completion,
+                                       &op, flags);
+    assert(!r);
+  }
+
+  void _finish(CallbackInfo *info)
+  {
+    context->state_lock.Lock();
+    assert(!done);
+    assert(completion->is_complete());
+    //context->oid_in_use.erase(oid);
+    //context->oid_not_in_use.insert(oid);
+    int r = completion->get_return_value();
+    cout << num << ":  got " << cpp_strerror(r) << std::endl;
+    if (r == 0) {
+      context->update_object_version(oid, 0, false);
+    } else if (r == -EBUSY) {
+      assert(!blocking);
+    } else if (r == -EINVAL) {
+      // caching not enabled?
+    } else if (r == -ENOENT) {
+      // may have raced with a remove?
+    } else {
+      assert(0 == "shouldn't happen");
+    }
+    context->kick();
+    done = true;
+    context->state_lock.Unlock();
+  }
+
+  bool finished()
+  {
+    return done;
+  }
+
+  string getType()
+  {
+    return "CacheFlushOp";
+  }
+};
+
+class CacheEvictOp : public TestOp {
+public:
+  librados::AioCompletion *completion;
+  librados::ObjectWriteOperation op;
+  string oid;
+
+  CacheEvictOp(int n,
+              RadosTestContext *context,
+              const string &oid,
+              TestOpStat *stat)
+    : TestOp(n, context, stat),
+      completion(NULL),
+      oid(oid)
+  {}
+
+  void _begin()
+  {
+    context->state_lock.Lock();
+    pair<TestOp*, TestOp::CallbackInfo*> *cb_arg =
+      new pair<TestOp*, TestOp::CallbackInfo*>(this,
+                                              new TestOp::CallbackInfo(0));
+    completion = context->rados.aio_create_completion((void *) cb_arg,
+                                                     &write_callback, 0);
+    // leave object in unused list so that we race with other operations
+    //context->oid_in_use.insert(oid);
+    //context->oid_not_in_use.erase(oid);
+    context->state_lock.Unlock();
+
+    op.cache_evict();
+    int r = context->io_ctx.aio_operate(context->prefix+oid, completion,
+                                       &op, librados::OPERATION_IGNORE_CACHE);
+    assert(!r);
+  }
+
+  void _finish(CallbackInfo *info)
+  {
+    context->state_lock.Lock();
+    assert(!done);
+    assert(completion->is_complete());
+    //context->oid_in_use.erase(oid);
+    //context->oid_not_in_use.insert(oid);
+    int r = completion->get_return_value();
+    cout << num << ":  got " << cpp_strerror(r) << std::endl;
+    if (r == 0) {
+      context->update_object_version(oid, completion->get_version64(), false);
+    } else if (r == -EBUSY) {
+      // raced with something that dirtied the object
+    } else if (r == -EINVAL) {
+      // caching not enabled?
+    } else if (r == -ENOENT) {
+      // may have raced with a remove?
+    } else {
+      assert(0 == "shouldn't happen");
+    }
+    context->kick();
+    done = true;
+    context->state_lock.Unlock();
+  }
+
+  bool finished()
+  {
+    return done;
+  }
+
+  string getType()
+  {
+    return "CacheEvictOp";
+  }
+};
+
+
 #endif
index e1b17b747d6c2bf2651b651377958b0fd289cd7d..23f93939cd109fa2de94e2476914be9c0ceebdee 100644 (file)
@@ -183,6 +183,27 @@ private:
        return new IsDirtyOp(m_op, &context, oid, m_stats);
       }
 
+    case TEST_OP_CACHE_FLUSH:
+      {
+       oid = *(rand_choose(context.oid_not_in_use));
+       cout << "cache_flush oid " << oid << std::endl;
+       return new CacheFlushOp(m_op, &context, oid, m_stats, true);
+      }
+
+    case TEST_OP_CACHE_TRY_FLUSH:
+      {
+       oid = *(rand_choose(context.oid_not_in_use));
+       cout << "cache_try_flush oid " << oid << std::endl;
+       return new CacheFlushOp(m_op, &context, oid, m_stats, false);
+      }
+
+    case TEST_OP_CACHE_EVICT:
+      {
+       oid = *(rand_choose(context.oid_not_in_use));
+       cout << "cache_evict oid " << oid << std::endl;
+       return new CacheEvictOp(m_op, &context, oid, m_stats);
+      }
+
     default:
       cerr << "Invalid op type " << type << std::endl;
       assert(0);
@@ -227,6 +248,9 @@ int main(int argc, char **argv)
     { TEST_OP_HIT_SET_LIST, "hit_set_list" },
     { TEST_OP_IS_DIRTY, "is_dirty" },
     { TEST_OP_UNDIRTY, "undirty" },
+    { TEST_OP_CACHE_FLUSH, "cache_flush" },
+    { TEST_OP_CACHE_TRY_FLUSH, "cache_try_flush" },
+    { TEST_OP_CACHE_EVICT, "cache_evict" },
     { TEST_OP_READ /* grr */, NULL },
   };