1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2011 New Dream Network
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include "cross_process_sem.h"
16 #include "include/rados/librados.h"
17 #include "include/stringify.h"
18 #include "st_rados_create_pool.h"
19 #include "st_rados_list_objects.h"
20 #include "systest_runnable.h"
21 #include "systest_settings.h"
26 #include <semaphore.h>
34 #include <sys/types.h>
37 using std::ostringstream;
41 static int g_num_objects = 50;
43 static CrossProcessSem *pool_setup_sem = NULL;
44 static CrossProcessSem *modify_sem = NULL;
46 class RadosDeleteObjectsR : public SysTestRunnable
49 RadosDeleteObjectsR(int argc, const char **argv,
50 const std::string &pool_name)
51 : SysTestRunnable(argc, argv), m_pool_name(pool_name)
55 ~RadosDeleteObjectsR() override
59 int run(void) override
63 RETURN1_IF_NONZERO(rados_create(&cl, NULL));
64 rados_conf_parse_argv(cl, m_argc, m_argv);
65 RETURN1_IF_NONZERO(rados_conf_read_file(cl, NULL));
66 rados_conf_parse_env(cl, NULL);
67 std::string log_name = SysTestSettings::inst().get_log_name(get_id_str());
68 if (!log_name.empty())
69 rados_conf_set(cl, "log_file", log_name.c_str());
70 RETURN1_IF_NONZERO(rados_connect(cl));
71 pool_setup_sem->wait();
72 pool_setup_sem->post();
75 rados_pool_create(cl, m_pool_name.c_str());
76 RETURN1_IF_NONZERO(rados_ioctx_create(cl, m_pool_name.c_str(), &io_ctx));
78 std::map <int, std::string> to_delete;
79 for (int i = 0; i < g_num_objects; ++i) {
81 snprintf(oid, sizeof(oid), "%d.obj", i);
87 if (to_delete.empty())
89 int r = rand() % to_delete.size();
90 std::map <int, std::string>::iterator d = to_delete.begin();
91 for (int i = 0; i < r; ++i)
93 if (d == to_delete.end()) {
97 std::string oid(d->second);
99 int ret = rados_remove(io_ctx, oid.c_str());
101 printf("%s: rados_remove(%s) failed with error %d\n",
102 get_id_str(), oid.c_str(), ret);
107 if ((removed % 25) == 0) {
108 printf("%s: removed %d objects...\n", get_id_str(), removed);
110 if (removed == g_num_objects / 2) {
111 printf("%s: removed half of the objects\n", get_id_str());
116 printf("%s: removed %d objects\n", get_id_str(), removed);
119 rados_ioctx_destroy(io_ctx);
125 std::string m_pool_name;
128 class RadosAddObjectsR : public SysTestRunnable
131 RadosAddObjectsR(int argc, const char **argv,
132 const std::string &pool_name,
133 const std::string &suffix)
134 : SysTestRunnable(argc, argv),
135 m_pool_name(pool_name),
140 ~RadosAddObjectsR() override
144 int run(void) override
148 RETURN1_IF_NONZERO(rados_create(&cl, NULL));
149 rados_conf_parse_argv(cl, m_argc, m_argv);
150 RETURN1_IF_NONZERO(rados_conf_read_file(cl, NULL));
151 rados_conf_parse_env(cl, NULL);
152 std::string log_name = SysTestSettings::inst().get_log_name(get_id_str());
153 if (!log_name.empty())
154 rados_conf_set(cl, "log_file", log_name.c_str());
155 RETURN1_IF_NONZERO(rados_connect(cl));
156 pool_setup_sem->wait();
157 pool_setup_sem->post();
159 rados_ioctx_t io_ctx;
160 rados_pool_create(cl, m_pool_name.c_str());
161 RETURN1_IF_NONZERO(rados_ioctx_create(cl, m_pool_name.c_str(), &io_ctx));
163 std::map <int, std::string> to_add;
164 for (int i = 0; i < g_num_objects; ++i) {
166 snprintf(oid, sizeof(oid), "%d%s", i, m_suffix.c_str());
174 int r = rand() % to_add.size();
175 std::map <int, std::string>::iterator d = to_add.begin();
176 for (int i = 0; i < r; ++i)
178 if (d == to_add.end()) {
182 std::string oid(d->second);
185 std::string buf(StRadosCreatePool::get_random_buf(256));
186 int ret = rados_write(io_ctx, oid.c_str(), buf.c_str(), buf.size(), 0);
188 printf("%s: rados_write(%s) failed with error %d\n",
189 get_id_str(), oid.c_str(), ret);
194 if ((added % 25) == 0) {
195 printf("%s: added %d objects...\n", get_id_str(), added);
197 if (added == g_num_objects / 2) {
198 printf("%s: added half of the objects\n", get_id_str());
203 printf("%s: added %d objects\n", get_id_str(), added);
206 rados_ioctx_destroy(io_ctx);
212 std::string m_pool_name;
213 std::string m_suffix;
216 const char *get_id_str()
221 int main(int argc, const char **argv)
223 const char *num_objects = getenv("NUM_OBJECTS");
224 const std::string pool = get_temp_pool_name(argv[0]);
226 g_num_objects = atoi(num_objects);
227 if (g_num_objects == 0)
231 RETURN1_IF_NONZERO(CrossProcessSem::create(0, &pool_setup_sem));
232 RETURN1_IF_NONZERO(CrossProcessSem::create(1, &modify_sem));
236 // Test 1... list objects
238 StRadosCreatePool r1(argc, argv, NULL, pool_setup_sem, NULL,
239 pool, g_num_objects, ".obj");
240 StRadosListObjects r2(argc, argv, pool, false, g_num_objects,
241 pool_setup_sem, modify_sem, NULL);
242 vector < SysTestRunnable* > vec;
245 error = SysTestRunnable::run_until_finished(vec);
246 if (!error.empty()) {
247 printf("got error: %s\n", error.c_str());
252 // Test 2... list objects while they're being deleted
253 RETURN1_IF_NONZERO(pool_setup_sem->reinit(0));
254 RETURN1_IF_NONZERO(modify_sem->reinit(0));
256 StRadosCreatePool r1(argc, argv, NULL, pool_setup_sem, NULL,
257 pool, g_num_objects, ".obj");
258 StRadosListObjects r2(argc, argv, pool, false, g_num_objects / 2,
259 pool_setup_sem, modify_sem, NULL);
260 RadosDeleteObjectsR r3(argc, argv, pool);
261 vector < SysTestRunnable* > vec;
265 error = SysTestRunnable::run_until_finished(vec);
266 if (!error.empty()) {
267 printf("got error: %s\n", error.c_str());
272 // Test 3... list objects while others are being added
273 RETURN1_IF_NONZERO(pool_setup_sem->reinit(0));
274 RETURN1_IF_NONZERO(modify_sem->reinit(0));
276 StRadosCreatePool r1(argc, argv, NULL, pool_setup_sem, NULL,
277 pool, g_num_objects, ".obj");
278 StRadosListObjects r2(argc, argv, pool, false, g_num_objects / 2,
279 pool_setup_sem, modify_sem, NULL);
280 RadosAddObjectsR r3(argc, argv, pool, ".obj2");
281 vector < SysTestRunnable* > vec;
285 error = SysTestRunnable::run_until_finished(vec);
286 if (!error.empty()) {
287 printf("got error: %s\n", error.c_str());
292 // Test 4... list objects while others are being added and deleted
293 RETURN1_IF_NONZERO(pool_setup_sem->reinit(0));
294 RETURN1_IF_NONZERO(modify_sem->reinit(0));
296 StRadosCreatePool r1(argc, argv, NULL, pool_setup_sem, NULL,
297 pool, g_num_objects, ".obj");
298 StRadosListObjects r2(argc, argv, pool, false, g_num_objects / 2,
299 pool_setup_sem, modify_sem, NULL);
300 RadosAddObjectsR r3(argc, argv, pool, ".obj2");
301 RadosAddObjectsR r4(argc, argv, pool, ".obj3");
302 RadosDeleteObjectsR r5(argc, argv, pool);
303 vector < SysTestRunnable* > vec;
309 error = SysTestRunnable::run_until_finished(vec);
310 if (!error.empty()) {
311 printf("got error: %s\n", error.c_str());
316 // Test 5... list objects while they are being modified
317 RETURN1_IF_NONZERO(pool_setup_sem->reinit(0));
318 RETURN1_IF_NONZERO(modify_sem->reinit(0));
320 StRadosCreatePool r1(argc, argv, NULL, pool_setup_sem, NULL,
321 pool, g_num_objects, ".obj");
322 StRadosListObjects r2(argc, argv, pool, false, g_num_objects / 2,
323 pool_setup_sem, modify_sem, NULL);
324 // AddObjects with the same 'suffix' as used in StRadosCreatePool
325 RadosAddObjectsR r3(argc, argv, pool, ".obj");
326 vector < SysTestRunnable* > vec;
330 error = SysTestRunnable::run_until_finished(vec);
331 if (!error.empty()) {
332 printf("got error: %s\n", error.c_str());
338 rados_create(&cl, NULL);
339 rados_conf_parse_argv(cl, argc, argv);
340 rados_conf_parse_argv(cl, argc, argv);
341 rados_conf_read_file(cl, NULL);
342 rados_conf_parse_env(cl, NULL);
344 rados_pool_delete(cl, pool.c_str());
346 printf("******* SUCCESS **********\n");