]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
add CrossProcessSem::reinit, fix rados_list_parallel
authorColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Thu, 7 Jul 2011 21:44:18 +0000 (14:44 -0700)
committerColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Wed, 13 Jul 2011 21:40:49 +0000 (14:40 -0700)
Signed-off-by: Colin McCabe <colin.mccabe@dreamhost.com>
src/test/system/cross_process_sem.cc
src/test/system/cross_process_sem.h
src/test/system/rados_list_parallel.cc
src/test/system/st_rados_create_pool.cc

index 108ea21fc776d9b51460f4d1bcd05dcd70c6c1d0..667ba1cc861366937e62e34dd2c74c83a23010d8 100644 (file)
@@ -79,6 +79,27 @@ post()
   }
 }
 
+int CrossProcessSem::
+reinit(int dval)
+{
+  if (dval < 0)
+    return -EINVAL;
+  int cval;
+  if (sem_getvalue(&m_data->sem, &cval) == -1)
+    return errno;
+  if (cval < dval) {
+    int diff = dval - cval;
+    for (int i = 0; i < diff; ++i)
+      sem_post(&m_data->sem);
+  }
+  else {
+    int diff = cval - dval;
+    for (int i = 0; i < diff; ++i)
+      sem_wait(&m_data->sem);
+  }
+  return 0;
+}
+
 CrossProcessSem::
 CrossProcessSem(struct cross_process_sem_data_t *data)
   : m_data(data)
index 3f45f6b68800d3596f64234a7d116572f992cedb..d087d2929918b0cf164caaeef3f7c6b18b9f4ece 100644 (file)
@@ -29,6 +29,11 @@ public:
   /* Semaphore post */
   void post();
 
+  /* Reinitialize the semaphore to the desired value.
+   * NOT thread-safe if it is in use at the time!
+   */ 
+  int reinit(int dval);
+
 private:
   CrossProcessSem(struct cross_process_sem_data_t *data);
   struct cross_process_sem_data_t *m_data;
index 9d3d22c85448b3f853fa7cb3b151d395ea39739e..61c2b5a2caac84ef0982d405000b33604b41b6c6 100644 (file)
 #include "include/rados/librados.h"
 #include "st_rados_create_pool.h"
 #include "systest_runnable.h"
+#include "systest_settings.h"
 
 #include <errno.h>
+#include <map>
 #include <pthread.h>
 #include <semaphore.h>
 #include <sstream>
@@ -37,22 +39,6 @@ static const int RLP_NUM_OBJECTS = 50;
 static CrossProcessSem *pool_setup_sem = NULL;
 static CrossProcessSem *modify_sem = NULL;
 
-/* Rados doesn't have read-after-write consistency for pool creation events.
- * What this means is that even after the first process has created the pool,
- * we may have to wait a while before we're able to see it. We will be able to
- * see it when a new OSDMap arrives.
- */
-static int do_ioctx_create(const char *id_str, rados_t &cl,
-                          const char *pool_name, rados_ioctx_t &io_ctx)
-{
-  int ret = rados_pool_create(cl, "foo");
-  if (ret != -EEXIST) {
-    return ret;
-  }
-  ret = rados_ioctx_create(cl, "foo", &io_ctx);
-  return ret;
-}
-
 class RadosListObjectsR : public SysTestRunnable
 {
 public:
@@ -73,39 +59,38 @@ public:
     RETURN_IF_NONZERO(rados_conf_read_file(cl, NULL));
     RETURN_IF_NONZERO(rados_connect(cl));
     pool_setup_sem->wait();
+    pool_setup_sem->post();
 
     rados_ioctx_t io_ctx;
-    printf("%s: do_ioctx_create.\n", get_id_str());
-    RETURN_IF_NONZERO(do_ioctx_create(get_id_str(), cl, "foo", io_ctx));
+    RETURN_IF_NOT_VAL(-EEXIST, rados_pool_create(cl, "foo"));
+    RETURN_IF_NONZERO(rados_ioctx_create(cl, "foo", &io_ctx));
 
-//    int ret, saw = 0;
-//    const char *obj_name;
-//    char tmp[RLP_OBJECT_SZ_MAX];
+    int ret, saw = 0;
+    const char *obj_name;
     rados_list_ctx_t h;
-//    printf("%s: listing objects.\n", get_id_str());
+    printf("%s: listing objects.\n", get_id_str());
     RETURN_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) {
-//     printf("%s: rados_objects_list_next error: %d\n", get_id_str(), ret);
-//     return ret;
-//      }
-//      printf("%s: listed an object!\n", get_id_str());
-//      int len = strlen(obj_name);
-//      if (len > RLP_OBJECT_SZ_MAX)
-//     len = RLP_OBJECT_SZ_MAX;
-//      memcpy(tmp, obj_name, strlen(obj_name));
-//      printf("%s: listing object '%s'\n", get_id_str(), obj_name);
-//      ++saw;
-////      if (saw == RLP_NUM_OBJECTS / 2)
-////   modify_sem->wait();
-//    }
+    while (true) {
+      ret = rados_objects_list_next(h, &obj_name);
+      if (ret == -ENOENT) {
+       break;
+      }
+      else if (ret != 0) {
+       printf("%s: rados_objects_list_next error: %d\n", get_id_str(), ret);
+       return ret;
+      }
+      char *obj_name_copy = strdup(obj_name);
+      free(obj_name_copy);
+      if ((saw % 25) == 0) {
+       printf("%s: listed object %d...\n", get_id_str(), saw);
+      }
+      ++saw;
+      if (saw == RLP_NUM_OBJECTS / 2)
+       modify_sem->wait();
+    }
     rados_objects_list_close(h);
 
-    //printf("%s: saw %d objects\n", get_id_str(), saw);
+    printf("%s: saw %d objects\n", get_id_str(), saw);
 
     rados_ioctx_destroy(cl);
 
@@ -132,17 +117,22 @@ public:
     RETURN_IF_NONZERO(rados_create(&cl, NULL));
     rados_conf_parse_argv(cl, m_argc, m_argv);
     RETURN_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));
     pool_setup_sem->wait();
+    pool_setup_sem->post();
 
     rados_ioctx_t io_ctx;
-    RETURN_IF_NONZERO(do_ioctx_create(get_id_str(), cl, "foo", io_ctx));
+    RETURN_IF_NOT_VAL(-EEXIST, rados_pool_create(cl, "foo"));
+    RETURN_IF_NONZERO(rados_ioctx_create(cl, "foo", &io_ctx));
 
-    std::vector <std::string> to_delete;
+    std::map <int, std::string> to_delete;
     for (int i = 0; i < RLP_NUM_OBJECTS; ++i) {
       char oid[128];
       snprintf(oid, sizeof(oid), "%d.obj", i);
-      to_delete.push_back(oid);
+      to_delete[i] = oid;
     }
 
     int removed = 0;
@@ -150,7 +140,14 @@ public:
       if (to_delete.empty())
        break;
       int r = rand() % to_delete.size();
-      std::string oid(to_delete[r]);
+      std::map <int, std::string>::iterator d = to_delete.begin();
+      for (int i = 0; i < r; ++i)
+       ++d;
+      if (d == to_delete.end()) {
+       return -EDOM;
+      }
+      std::string oid(d->second);
+      to_delete.erase(d);
       ret = rados_remove(io_ctx, oid.c_str());
       if (ret != 0) {
        printf("%s: rados_remove(%s) failed with error %d\n",
@@ -158,8 +155,13 @@ public:
        return ret;
       }
       ++removed;
-      if (removed == RLP_NUM_OBJECTS / 2)
+      if ((removed % 25) == 0) {
+       printf("%s: removed %d objects...\n", get_id_str(), removed);
+      }
+      if (removed == RLP_NUM_OBJECTS / 2) {
+       printf("%s: removed half of the objects\n", get_id_str());
        modify_sem->post();
+      }
     }
 
     printf("%s: removed %d objects\n", get_id_str(), removed);
@@ -180,14 +182,31 @@ int main(int argc, const char **argv)
   RETURN_IF_NONZERO(CrossProcessSem::create(0, &pool_setup_sem));
   RETURN_IF_NONZERO(CrossProcessSem::create(1, &modify_sem));
 
-  StRadosCreatePool r1(argc, argv, pool_setup_sem, NULL, RLP_NUM_OBJECTS);
-  RadosListObjectsR r2(argc, argv);
-  RadosModifyPoolR r3(argc, argv);
-  vector < SysTestRunnable* > vec;
-  vec.push_back(&r1);
-  vec.push_back(&r2);
-  //vec.push_back(&r3);
-  std::string error = SysTestRunnable::run_until_finished(vec);
+  std::string error;
+
+  // Test 1... list objects
+//  StRadosCreatePool r1(argc, argv, pool_setup_sem, NULL, RLP_NUM_OBJECTS);
+//  RadosListObjectsR r2(argc, argv);
+//  vector < SysTestRunnable* > vec;
+//  vec.push_back(&r1);
+//  vec.push_back(&r2);
+//  error = SysTestRunnable::run_until_finished(vec);
+//  if (!error.empty()) {
+//    printf("got error: %s\n", error.c_str());
+//    return EXIT_FAILURE;
+//  }
+
+  // Test 2... list objects while they're being deleted
+  RETURN_IF_NONZERO(pool_setup_sem->reinit(0));
+  RETURN_IF_NONZERO(modify_sem->reinit(0));
+  StRadosCreatePool r3(argc, argv, pool_setup_sem, NULL, RLP_NUM_OBJECTS);
+  RadosListObjectsR r4(argc, argv);
+  RadosModifyPoolR r5(argc, argv);
+  vector < SysTestRunnable* > vec2;
+  vec2.push_back(&r3);
+  vec2.push_back(&r4);
+  vec2.push_back(&r5);
+  error = SysTestRunnable::run_until_finished(vec2);
   if (!error.empty()) {
     printf("got error: %s\n", error.c_str());
     return EXIT_FAILURE;
index 80c16d639c230579d9d111ba67fe8c92b6398576..0db494330d52564e0ba94936d7aaa7fc67faffb0 100644 (file)
@@ -61,10 +61,10 @@ run()
   RETURN_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));
   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));
   int ret = rados_pool_delete(cl, "foo");
   if (!((ret == 0) || (ret == -ENOENT))) {