massif.out.*
rados_list_parallel
rados_open_pools_parallel
+rados_delete_pools_parallel
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
--- /dev/null
+// -*- 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;
+}
{
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) {
{
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) {
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);
}
// 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);
}
// 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);
}
// 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);
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);
// 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;
// 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;
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];
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)
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;
}
{
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;
#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);