]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
Create rados_delete_pools_parallel test
authorColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Wed, 13 Jul 2011 22:11:44 +0000 (15:11 -0700)
committerColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Wed, 13 Jul 2011 22:25:54 +0000 (15:25 -0700)
* add rados_delete_pools_parallel test

* change RETURN_IF_NOT_VAL -> RETURN1_IF_NOT_VAL.
We want to return a non-zero error code when the value is something we
don't expect, even if that unexpected value is 0.

* st_rados_list_objects: add option to ignore list errors (for the
deletion test)

Signed-off-by: Colin McCabe <colin.mccabe@dreamhost.com>
src/.gitignore
src/Makefile.am
src/test/system/rados_delete_pools_parallel.cc [new file with mode: 0644]
src/test/system/rados_list_parallel.cc
src/test/system/rados_open_pools_parallel.cc
src/test/system/st_rados_create_pool.cc
src/test/system/st_rados_list_objects.cc
src/test/system/st_rados_list_objects.h
src/test/system/systest_runnable.h

index 17779dd7cee1c3b494484fac126a22947dd4f6fe..bdcddef8d0b6b8aa2776db6a7de57618a23a6daa 100644 (file)
@@ -90,3 +90,4 @@ ceph.conf
 massif.out.*
 rados_list_parallel
 rados_open_pools_parallel
+rados_delete_pools_parallel
index cb9f631aa2c5b64fc78f5a9163455f36a729a737..42e393a22b44bbca926856d476f961319c777e48 100644 (file)
@@ -396,6 +396,20 @@ rados_open_pools_parallel_SOURCES = \
 rados_open_pools_parallel_LDADD = libsystest.la librados.la
 bin_DEBUGPROGRAMS += rados_open_pools_parallel
 
+rados_list_parallel_SOURCES = \
+       test/system/rados_list_parallel.cc \
+       test/system/st_rados_create_pool.cc \
+       test/system/st_rados_list_objects.cc
+rados_list_parallel_LDADD = libsystest.la librados.la
+bin_DEBUGPROGRAMS += rados_list_parallel
+
+rados_delete_pools_parallel_SOURCES = \
+       test/system/rados_delete_pools_parallel.cc \
+       test/system/st_rados_create_pool.cc \
+       test/system/st_rados_list_objects.cc
+rados_delete_pools_parallel_LDADD = libsystest.la librados.la
+bin_DEBUGPROGRAMS += rados_delete_pools_parallel
+
 ## unit tests
 
 # target to build but not run the unit tests
diff --git a/src/test/system/rados_delete_pools_parallel.cc b/src/test/system/rados_delete_pools_parallel.cc
new file mode 100644 (file)
index 0000000..ccc6bb1
--- /dev/null
@@ -0,0 +1,149 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+* Ceph - scalable distributed file system
+*
+* Copyright (C) 2011 New Dream Network
+*
+* This is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License version 2.1, as published by the Free Software
+* Foundation.  See file COPYING.
+*
+*/
+
+#include "cross_process_sem.h"
+#include "include/rados/librados.h"
+#include "st_rados_create_pool.h"
+#include "st_rados_list_objects.h"
+#include "systest_runnable.h"
+#include "systest_settings.h"
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <sstream>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <time.h>
+#include <vector>
+
+using std::ostringstream;
+using std::string;
+using std::vector;
+
+static int g_num_objects = 50;
+
+/*
+ * rados_delete_pools_parallel
+ *
+ * This tests creation and deletion races.
+ *
+ * EXPECT:            * can delete a pool while another user is using it
+ *                    * operations on pools return error codes after the pools
+ *                      are deleted
+ *
+ * DO NOT EXPECT      * hangs, crashes
+ */
+class StRadosDeletePool : public SysTestRunnable
+{
+public:
+  StRadosDeletePool(int argc, const char **argv,
+                 CrossProcessSem *pool_setup_sem, CrossProcessSem *delete_pool_sem,
+                 const std::string &pool_name)
+    : SysTestRunnable(argc, argv),
+      m_pool_setup_sem(pool_setup_sem), m_delete_pool_sem(delete_pool_sem),
+      m_pool_name(pool_name)
+  {
+  }
+
+  ~StRadosDeletePool()
+  {
+  }
+
+  int run()
+  {
+    rados_t cl;
+    RETURN1_IF_NONZERO(rados_create(&cl, NULL));
+    rados_conf_parse_argv(cl, m_argc, m_argv);
+    RETURN1_IF_NONZERO(rados_conf_read_file(cl, NULL));
+    RETURN1_IF_NONZERO(rados_connect(cl));
+    m_pool_setup_sem->wait();
+    m_pool_setup_sem->post();
+
+    rados_ioctx_t io_ctx;
+    RETURN1_IF_NOT_VAL(-EEXIST, rados_pool_create(cl, m_pool_name.c_str()));
+    RETURN1_IF_NONZERO(rados_ioctx_create(cl, m_pool_name.c_str(), &io_ctx));
+    rados_ioctx_destroy(io_ctx);
+    rados_pool_delete(cl, m_pool_name.c_str());
+    if (m_delete_pool_sem)
+      m_delete_pool_sem->post();
+    rados_shutdown(cl);
+    return 0;
+  }
+
+private:
+  CrossProcessSem *m_pool_setup_sem;
+  CrossProcessSem *m_delete_pool_sem;
+  std::string m_pool_name;
+};
+
+const char *get_id_str()
+{
+  return "main";
+}
+
+int main(int argc, const char **argv)
+{
+  const char *num_objects = getenv("NUM_OBJECTS");
+  if (num_objects) {
+    g_num_objects = atoi(num_objects); 
+    if (g_num_objects == 0)
+      return 100;
+  }
+
+  CrossProcessSem *pool_setup_sem = NULL;
+  RETURN1_IF_NONZERO(CrossProcessSem::create(0, &pool_setup_sem));
+  CrossProcessSem *delete_pool_sem = NULL;
+  RETURN1_IF_NONZERO(CrossProcessSem::create(0, &delete_pool_sem));
+
+  // first test: create a pool, then delete that pool
+  {
+    StRadosCreatePool r1(argc, argv, pool_setup_sem, NULL, 50);
+    StRadosDeletePool r2(argc, argv, pool_setup_sem, NULL, "foo");
+    vector < SysTestRunnable* > vec;
+    vec.push_back(&r1);
+    vec.push_back(&r2);
+    std::string error = SysTestRunnable::run_until_finished(vec);
+    if (!error.empty()) {
+      printf("test1: got error: %s\n", error.c_str());
+      return EXIT_FAILURE;
+    }
+  }
+
+  // second test: create a pool, the list objects in that pool while it's
+  // being deleted.
+  RETURN1_IF_NONZERO(pool_setup_sem->reinit(0));
+  RETURN1_IF_NONZERO(delete_pool_sem->reinit(0));
+  {
+    StRadosCreatePool r1(argc, argv, pool_setup_sem, NULL, g_num_objects);
+    StRadosDeletePool r2(argc, argv,
+                        pool_setup_sem, delete_pool_sem, "foo");
+    StRadosListObjects r3(argc, argv, true, g_num_objects / 2,
+                         pool_setup_sem, delete_pool_sem);
+    vector < SysTestRunnable* > vec;
+    vec.push_back(&r1);
+    vec.push_back(&r2);
+    vec.push_back(&r3);
+    std::string error = SysTestRunnable::run_until_finished(vec);
+    if (!error.empty()) {
+      printf("test2: got error: %s\n", error.c_str());
+      return EXIT_FAILURE;
+    }
+  }
+
+  printf("******* SUCCESS **********\n"); 
+  return EXIT_SUCCESS;
+}
index 369939ef4126697234bb9980d3e36a74fabc52c6..be2e8a2163cc78384b04d1a8059b2b83dba830ed 100644 (file)
@@ -56,19 +56,19 @@ public:
   {
     int ret;
     rados_t cl;
-    RETURN_IF_NONZERO(rados_create(&cl, NULL));
+    RETURN1_IF_NONZERO(rados_create(&cl, NULL));
     rados_conf_parse_argv(cl, m_argc, m_argv);
-    RETURN_IF_NONZERO(rados_conf_read_file(cl, NULL));
+    RETURN1_IF_NONZERO(rados_conf_read_file(cl, NULL));
     std::string log_name = SysTestSettings::inst().get_log_name(get_id_str());
     if (!log_name.empty())
       rados_conf_set(cl, "log_file", log_name.c_str());
-    RETURN_IF_NONZERO(rados_connect(cl));
+    RETURN1_IF_NONZERO(rados_connect(cl));
     pool_setup_sem->wait();
     pool_setup_sem->post();
 
     rados_ioctx_t io_ctx;
-    RETURN_IF_NOT_VAL(-EEXIST, rados_pool_create(cl, "foo"));
-    RETURN_IF_NONZERO(rados_ioctx_create(cl, "foo", &io_ctx));
+    RETURN1_IF_NOT_VAL(-EEXIST, rados_pool_create(cl, "foo"));
+    RETURN1_IF_NONZERO(rados_ioctx_create(cl, "foo", &io_ctx));
 
     std::map <int, std::string> to_delete;
     for (int i = 0; i < g_num_objects; ++i) {
@@ -132,19 +132,19 @@ public:
   {
     int ret;
     rados_t cl;
-    RETURN_IF_NONZERO(rados_create(&cl, NULL));
+    RETURN1_IF_NONZERO(rados_create(&cl, NULL));
     rados_conf_parse_argv(cl, m_argc, m_argv);
-    RETURN_IF_NONZERO(rados_conf_read_file(cl, NULL));
+    RETURN1_IF_NONZERO(rados_conf_read_file(cl, NULL));
     std::string log_name = SysTestSettings::inst().get_log_name(get_id_str());
     if (!log_name.empty())
       rados_conf_set(cl, "log_file", log_name.c_str());
-    RETURN_IF_NONZERO(rados_connect(cl));
+    RETURN1_IF_NONZERO(rados_connect(cl));
     pool_setup_sem->wait();
     pool_setup_sem->post();
 
     rados_ioctx_t io_ctx;
-    RETURN_IF_NOT_VAL(-EEXIST, rados_pool_create(cl, "foo"));
-    RETURN_IF_NONZERO(rados_ioctx_create(cl, "foo", &io_ctx));
+    RETURN1_IF_NOT_VAL(-EEXIST, rados_pool_create(cl, "foo"));
+    RETURN1_IF_NONZERO(rados_ioctx_create(cl, "foo", &io_ctx));
 
     std::map <int, std::string> to_add;
     for (int i = 0; i < g_num_objects; ++i) {
@@ -209,15 +209,16 @@ int main(int argc, const char **argv)
       return 100;
   }
 
-  RETURN_IF_NONZERO(CrossProcessSem::create(0, &pool_setup_sem));
-  RETURN_IF_NONZERO(CrossProcessSem::create(1, &modify_sem));
+  RETURN1_IF_NONZERO(CrossProcessSem::create(0, &pool_setup_sem));
+  RETURN1_IF_NONZERO(CrossProcessSem::create(1, &modify_sem));
 
   std::string error;
 
   // Test 1... list objects
   {
     StRadosCreatePool r1(argc, argv, pool_setup_sem, NULL, g_num_objects);
-    StRadosListObjects r2(argc, argv, g_num_objects, pool_setup_sem, modify_sem);
+    StRadosListObjects r2(argc, argv, false, g_num_objects,
+                         pool_setup_sem, modify_sem);
     vector < SysTestRunnable* > vec;
     vec.push_back(&r1);
     vec.push_back(&r2);
@@ -229,11 +230,12 @@ int main(int argc, const char **argv)
   }
 
   // Test 2... list objects while they're being deleted
-  RETURN_IF_NONZERO(pool_setup_sem->reinit(0));
-  RETURN_IF_NONZERO(modify_sem->reinit(0));
+  RETURN1_IF_NONZERO(pool_setup_sem->reinit(0));
+  RETURN1_IF_NONZERO(modify_sem->reinit(0));
   {
     StRadosCreatePool r1(argc, argv, pool_setup_sem, NULL, g_num_objects);
-    StRadosListObjects r2(argc, argv, g_num_objects, pool_setup_sem, modify_sem);
+    StRadosListObjects r2(argc, argv, false, g_num_objects / 2,
+                         pool_setup_sem, modify_sem);
     RadosDeleteObjectsR r3(argc, argv);
     vector < SysTestRunnable* > vec;
     vec.push_back(&r1);
@@ -247,11 +249,12 @@ int main(int argc, const char **argv)
   }
 
   // Test 3... list objects while others are being added
-  RETURN_IF_NONZERO(pool_setup_sem->reinit(0));
-  RETURN_IF_NONZERO(modify_sem->reinit(0));
+  RETURN1_IF_NONZERO(pool_setup_sem->reinit(0));
+  RETURN1_IF_NONZERO(modify_sem->reinit(0));
   {
     StRadosCreatePool r1(argc, argv, pool_setup_sem, NULL, g_num_objects);
-    StRadosListObjects r2(argc, argv, g_num_objects, pool_setup_sem, modify_sem);
+    StRadosListObjects r2(argc, argv, false, g_num_objects / 2,
+                         pool_setup_sem, modify_sem);
     RadosAddObjectsR r3(argc, argv, "obj2");
     vector < SysTestRunnable* > vec;
     vec.push_back(&r1);
@@ -265,11 +268,12 @@ int main(int argc, const char **argv)
   }
 
   // Test 4... list objects while others are being added and deleted
-  RETURN_IF_NONZERO(pool_setup_sem->reinit(0));
-  RETURN_IF_NONZERO(modify_sem->reinit(0));
+  RETURN1_IF_NONZERO(pool_setup_sem->reinit(0));
+  RETURN1_IF_NONZERO(modify_sem->reinit(0));
   {
     StRadosCreatePool r1(argc, argv, pool_setup_sem, NULL, g_num_objects);
-    StRadosListObjects r2(argc, argv, g_num_objects, pool_setup_sem, modify_sem);
+    StRadosListObjects r2(argc, argv, false, g_num_objects / 2,
+                         pool_setup_sem, modify_sem);
     RadosAddObjectsR r3(argc, argv, "obj2");
     RadosAddObjectsR r4(argc, argv, "obj3");
     RadosDeleteObjectsR r5(argc, argv);
index aee95a210844c3e20ce8673b57e8d06801ed0a2a..a02662d723b209a961a3034b1ff6b08d558203ec 100644 (file)
@@ -62,21 +62,21 @@ public:
   int run()
   {
     rados_t cl;
-    RETURN_IF_NONZERO(rados_create(&cl, NULL));
+    RETURN1_IF_NONZERO(rados_create(&cl, NULL));
     rados_conf_parse_argv(cl, m_argc, m_argv);
     std::string log_name = SysTestSettings::inst().get_log_name(get_id_str());
     if (!log_name.empty())
       rados_conf_set(cl, "log_file", log_name.c_str());
-    RETURN_IF_NONZERO(rados_conf_read_file(cl, NULL));
-    RETURN_IF_NONZERO(rados_connect(cl));
+    RETURN1_IF_NONZERO(rados_conf_read_file(cl, NULL));
+    RETURN1_IF_NONZERO(rados_connect(cl));
     if (m_pool_setup_sem)
       m_pool_setup_sem->wait();
 
     printf("%s: rados_pool_create.\n", get_id_str());
-    RETURN_IF_NOT_VAL(-EEXIST, rados_pool_create(cl, "foo"));
+    RETURN1_IF_NOT_VAL(-EEXIST, rados_pool_create(cl, "foo"));
     rados_ioctx_t io_ctx;
     printf("%s: rados_ioctx_create.\n", get_id_str());
-    RETURN_IF_NOT_VAL(0, rados_ioctx_create(cl, "foo", &io_ctx));
+    RETURN1_IF_NOT_VAL(0, rados_ioctx_create(cl, "foo", &io_ctx));
     if (m_open_pool_sem)
       m_open_pool_sem->post();
     rados_ioctx_destroy(io_ctx);
@@ -99,7 +99,7 @@ int main(int argc, const char **argv)
   // first test: create a pool, shut down the client, access that 
   // pool in a different process.
   CrossProcessSem *pool_setup_sem = NULL;
-  RETURN_IF_NONZERO(CrossProcessSem::create(0, &pool_setup_sem));
+  RETURN1_IF_NONZERO(CrossProcessSem::create(0, &pool_setup_sem));
   StRadosCreatePool r1(argc, argv, pool_setup_sem, NULL, 50);
   StRadosOpenPool r2(argc, argv, pool_setup_sem, NULL);
   vector < SysTestRunnable* > vec;
@@ -114,9 +114,9 @@ int main(int argc, const char **argv)
   // second test: create a pool, access that 
   // pool in a different process, THEN shut down the first client.
   CrossProcessSem *pool_setup_sem2 = NULL;
-  RETURN_IF_NONZERO(CrossProcessSem::create(0, &pool_setup_sem2));
+  RETURN1_IF_NONZERO(CrossProcessSem::create(0, &pool_setup_sem2));
   CrossProcessSem *open_pool_sem2 = NULL;
-  RETURN_IF_NONZERO(CrossProcessSem::create(0, &open_pool_sem2));
+  RETURN1_IF_NONZERO(CrossProcessSem::create(0, &open_pool_sem2));
   StRadosCreatePool r3(argc, argv, pool_setup_sem2, open_pool_sem2, 50);
   StRadosOpenPool r4(argc, argv, pool_setup_sem2, open_pool_sem2);
   vector < SysTestRunnable* > vec2;
index 4bced3ce9acaf3927d8803b303717dd8861661eb..a56c0d668c53100340f12326912a5d7c6a90861d 100644 (file)
@@ -57,22 +57,22 @@ int StRadosCreatePool::
 run()
 {
   rados_t cl;
-  RETURN_IF_NONZERO(rados_create(&cl, NULL));
+  RETURN1_IF_NONZERO(rados_create(&cl, NULL));
   rados_conf_parse_argv(cl, m_argc, m_argv);
   rados_conf_parse_argv(cl, m_argc, m_argv);
-  RETURN_IF_NONZERO(rados_conf_read_file(cl, NULL));
+  RETURN1_IF_NONZERO(rados_conf_read_file(cl, NULL));
   std::string log_name = SysTestSettings::inst().get_log_name(get_id_str());
   if (!log_name.empty())
     rados_conf_set(cl, "log_file", log_name.c_str());
-  RETURN_IF_NONZERO(rados_connect(cl));
+  RETURN1_IF_NONZERO(rados_connect(cl));
   int ret = rados_pool_delete(cl, "foo");
   if (!((ret == 0) || (ret == -ENOENT))) {
     printf("%s: rados_pool_delete error %d\n", get_id_str(), ret);
     return ret;
   }
-  RETURN_IF_NONZERO(rados_pool_create(cl, "foo"));
+  RETURN1_IF_NONZERO(rados_pool_create(cl, "foo"));
   rados_ioctx_t io_ctx;
-  RETURN_IF_NONZERO(rados_ioctx_create(cl, "foo", &io_ctx));
+  RETURN1_IF_NONZERO(rados_ioctx_create(cl, "foo", &io_ctx));
 
   for (int i = 0; i < m_num_objects; ++i) {
     char oid[128];
index 41ba15dde00bb3068a91bf0cae906c778884f54a..1c124e7167a583c2c83dab37ebd9ad4be918968c 100644 (file)
 using std::ostringstream;
 
 StRadosListObjects::
-StRadosListObjects(int argc, const char **argv, int midway_cnt,
+StRadosListObjects(int argc, const char **argv,
+                  bool accept_list_errors, int midway_cnt,
        CrossProcessSem *pool_setup_sem, CrossProcessSem *midway_sem)
   : SysTestRunnable(argc, argv),
+    m_accept_list_errors(accept_list_errors),
     m_midway_cnt(midway_cnt),
     m_pool_setup_sem(pool_setup_sem),
     m_midway_sem(midway_sem)
@@ -46,28 +48,30 @@ int StRadosListObjects::
 run()
 {
   rados_t cl;
-  RETURN_IF_NONZERO(rados_create(&cl, NULL));
+  RETURN1_IF_NONZERO(rados_create(&cl, NULL));
   rados_conf_parse_argv(cl, m_argc, m_argv);
-  RETURN_IF_NONZERO(rados_conf_read_file(cl, NULL));
-  RETURN_IF_NONZERO(rados_connect(cl));
+  RETURN1_IF_NONZERO(rados_conf_read_file(cl, NULL));
+  RETURN1_IF_NONZERO(rados_connect(cl));
   m_pool_setup_sem->wait();
   m_pool_setup_sem->post();
 
   rados_ioctx_t io_ctx;
-  RETURN_IF_NOT_VAL(-EEXIST, rados_pool_create(cl, "foo"));
-  RETURN_IF_NONZERO(rados_ioctx_create(cl, "foo", &io_ctx));
+  RETURN1_IF_NOT_VAL(-EEXIST, rados_pool_create(cl, "foo"));
+  RETURN1_IF_NONZERO(rados_ioctx_create(cl, "foo", &io_ctx));
 
   int ret, saw = 0;
   const char *obj_name;
   rados_list_ctx_t h;
   printf("%s: listing objects.\n", get_id_str());
-  RETURN_IF_NONZERO(rados_objects_list_open(io_ctx, &h));
+  RETURN1_IF_NONZERO(rados_objects_list_open(io_ctx, &h));
   while (true) {
     ret = rados_objects_list_next(h, &obj_name);
     if (ret == -ENOENT) {
       break;
     }
     else if (ret != 0) {
+      if (m_accept_list_errors)
+       break;
       printf("%s: rados_objects_list_next error: %d\n", get_id_str(), ret);
       return ret;
     }
index ded99a9b34c20b4aae473fe72a3e8bd26ea2995a..e57bdf1d1a2091fea6cd4fa91ab98eb5b5fd950e 100644 (file)
@@ -32,11 +32,13 @@ class StRadosListObjects : public SysTestRunnable
 {
 public:
   static std::string get_random_buf(int sz);
-  StRadosListObjects(int argc, const char **argv, int midway_cnt,
+  StRadosListObjects(int argc, const char **argv, bool accept_list_errors,
+       int midway_cnt,
        CrossProcessSem *pool_setup_sem, CrossProcessSem *midway_sem);
   ~StRadosListObjects();
   virtual int run();
 private:
+  bool m_accept_list_errors;
   int m_midway_cnt;
   CrossProcessSem *m_pool_setup_sem;
   CrossProcessSem *m_midway_sem;
index 8962152c1205bf0e3fb33fa0cf7f16cd31c37923..8fb59f4c68d37029df619468c3c6b2b006f344b0 100644 (file)
 #include <string>
 #include <vector>
 
-#define RETURN_IF_NOT_VAL(expected, expr) \
+#define RETURN1_IF_NOT_VAL(expected, expr) \
   do {\
     int _rinv_ret = expr;\
     if (_rinv_ret != expected) {\
       printf("%s: file %s, line %d: expected %d, got %d\n",\
             get_id_str(), __FILE__, __LINE__, expected, _rinv_ret);\
-      return _rinv_ret;\
+      return 1; \
     }\
   } while(0);
 
-#define RETURN_IF_NONZERO(expr) \
-  RETURN_IF_NOT_VAL(0, expr)
+#define RETURN1_IF_NONZERO(expr) \
+  RETURN1_IF_NOT_VAL(0, expr)
 
 extern void* systest_runnable_pthread_helper(void *arg);