]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librados/list.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / test / librados / list.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3#include "include/rados/librados.h"
4#include "include/rados/librados.hpp"
5#include "include/stringify.h"
6#include "test/librados/test.h"
31f18b77 7#include "test/librados/test_common.h"
7c673cae
FG
8#include "test/librados/TestCase.h"
9#include "global/global_context.h"
10
11#include "include/types.h"
12#include "common/hobject.h"
13#include "gtest/gtest.h"
14#include <errno.h>
15#include <string>
16#include <stdexcept>
17
20effc67 18using namespace std;
7c673cae
FG
19using namespace librados;
20
21typedef RadosTestNSCleanup LibRadosList;
7c673cae 22typedef RadosTestECNSCleanup LibRadosListEC;
7c673cae
FG
23typedef RadosTestNP LibRadosListNP;
24
25
26TEST_F(LibRadosList, ListObjects) {
27 char buf[128];
28 memset(buf, 0xcc, sizeof(buf));
29 ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
30 rados_list_ctx_t ctx;
31 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
32 const char *entry;
33 bool foundit = false;
34 while (rados_nobjects_list_next(ctx, &entry, NULL, NULL) != -ENOENT) {
35 foundit = true;
36 ASSERT_EQ(std::string(entry), "foo");
37 }
38 ASSERT_TRUE(foundit);
39 rados_nobjects_list_close(ctx);
40}
41
f67539c2
TL
42TEST_F(LibRadosList, ListObjectsZeroInName) {
43 char buf[128];
44 memset(buf, 0xcc, sizeof(buf));
45 ASSERT_EQ(0, rados_write(ioctx, "foo\0bar", buf, sizeof(buf), 0));
46 rados_list_ctx_t ctx;
47 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
48 const char *entry;
49 size_t entry_size;
50 bool foundit = false;
51 while (rados_nobjects_list_next2(ctx, &entry, NULL, NULL,
52 &entry_size, NULL, NULL) != -ENOENT) {
53 foundit = true;
54 ASSERT_EQ(std::string(entry, entry_size), "foo\0bar");
55 }
56 ASSERT_TRUE(foundit);
57 rados_nobjects_list_close(ctx);
58}
7c673cae
FG
59
60static void check_list(
61 std::set<std::string>& myset,
62 rados_list_ctx_t& ctx,
11fdf7f2 63 const std::string &check_nspace)
7c673cae
FG
64{
65 const char *entry, *nspace;
66 cout << "myset " << myset << std::endl;
67 // we should see every item exactly once.
68 int ret;
69 while ((ret = rados_nobjects_list_next(ctx, &entry, NULL, &nspace)) == 0) {
70 std::string test_name;
71 if (check_nspace == all_nspaces) {
72 test_name = std::string(nspace) + ":" + std::string(entry);
73 } else {
74 ASSERT_TRUE(std::string(nspace) == check_nspace);
75 test_name = std::string(entry);
76 }
77 cout << test_name << std::endl;
78
79 ASSERT_TRUE(myset.end() != myset.find(test_name));
80 myset.erase(test_name);
81 }
82 ASSERT_EQ(-ENOENT, ret);
83 ASSERT_TRUE(myset.empty());
84}
85
86TEST_F(LibRadosList, ListObjectsNS) {
87 char buf[128];
88 memset(buf, 0xcc, sizeof(buf));
89 // Create :foo1, :foo2, :foo3, n1:foo1, ns1:foo4, ns1:foo5, ns2:foo6, n2:foo7
90 rados_ioctx_set_namespace(ioctx, "");
91 ASSERT_EQ(0, rados_write(ioctx, "foo1", buf, sizeof(buf), 0));
92 rados_ioctx_set_namespace(ioctx, "ns1");
93 ASSERT_EQ(0, rados_write(ioctx, "foo1", buf, sizeof(buf), 0));
94 rados_ioctx_set_namespace(ioctx, "");
95 ASSERT_EQ(0, rados_write(ioctx, "foo2", buf, sizeof(buf), 0));
96 ASSERT_EQ(0, rados_write(ioctx, "foo3", buf, sizeof(buf), 0));
97 rados_ioctx_set_namespace(ioctx, "ns1");
98 ASSERT_EQ(0, rados_write(ioctx, "foo4", buf, sizeof(buf), 0));
99 ASSERT_EQ(0, rados_write(ioctx, "foo5", buf, sizeof(buf), 0));
100 rados_ioctx_set_namespace(ioctx, "ns2");
101 ASSERT_EQ(0, rados_write(ioctx, "foo6", buf, sizeof(buf), 0));
102 ASSERT_EQ(0, rados_write(ioctx, "foo7", buf, sizeof(buf), 0));
103
11fdf7f2
TL
104 char nspace[4];
105 ASSERT_EQ(-ERANGE, rados_ioctx_get_namespace(ioctx, nspace, 3));
106 ASSERT_EQ(static_cast<int>(strlen("ns2")),
107 rados_ioctx_get_namespace(ioctx, nspace, sizeof(nspace)));
108 ASSERT_EQ(0, strcmp("ns2", nspace));
109
7c673cae
FG
110 std::set<std::string> def, ns1, ns2, all;
111 def.insert(std::string("foo1"));
112 def.insert(std::string("foo2"));
113 def.insert(std::string("foo3"));
114 ns1.insert(std::string("foo1"));
115 ns1.insert(std::string("foo4"));
116 ns1.insert(std::string("foo5"));
117 ns2.insert(std::string("foo6"));
118 ns2.insert(std::string("foo7"));
119 all.insert(std::string(":foo1"));
120 all.insert(std::string(":foo2"));
121 all.insert(std::string(":foo3"));
122 all.insert(std::string("ns1:foo1"));
123 all.insert(std::string("ns1:foo4"));
124 all.insert(std::string("ns1:foo5"));
125 all.insert(std::string("ns2:foo6"));
126 all.insert(std::string("ns2:foo7"));
127
128 rados_list_ctx_t ctx;
129 // Check default namespace ""
130 rados_ioctx_set_namespace(ioctx, "");
131 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
132 check_list(def, ctx, "");
133 rados_nobjects_list_close(ctx);
134
135 // Check namespace "ns1"
136 rados_ioctx_set_namespace(ioctx, "ns1");
137 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
138 check_list(ns1, ctx, "ns1");
139 rados_nobjects_list_close(ctx);
140
141 // Check namespace "ns2"
142 rados_ioctx_set_namespace(ioctx, "ns2");
143 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
144 check_list(ns2, ctx, "ns2");
145 rados_nobjects_list_close(ctx);
146
147 // Check ALL namespaces
148 rados_ioctx_set_namespace(ioctx, LIBRADOS_ALL_NSPACES);
149 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
150 check_list(all, ctx, all_nspaces);
151 rados_nobjects_list_close(ctx);
152}
153
7c673cae
FG
154
155TEST_F(LibRadosList, ListObjectsStart) {
156 char buf[128];
157 memset(buf, 0xcc, sizeof(buf));
158
159 for (int i=0; i<16; ++i) {
160 string n = stringify(i);
161 ASSERT_EQ(0, rados_write(ioctx, n.c_str(), buf, sizeof(buf), 0));
162 }
163
164 rados_list_ctx_t ctx;
165 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
166 std::map<int, std::set<std::string> > pg_to_obj;
167 const char *entry;
168 while (rados_nobjects_list_next(ctx, &entry, NULL, NULL) == 0) {
169 uint32_t pos = rados_nobjects_list_get_pg_hash_position(ctx);
170 std::cout << entry << " " << pos << std::endl;
171 pg_to_obj[pos].insert(entry);
172 }
173 rados_nobjects_list_close(ctx);
174
175 std::map<int, std::set<std::string> >::reverse_iterator p =
176 pg_to_obj.rbegin();
177 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
178 while (p != pg_to_obj.rend()) {
179 ASSERT_EQ((uint32_t)p->first, rados_nobjects_list_seek(ctx, p->first));
180 ASSERT_EQ(0, rados_nobjects_list_next(ctx, &entry, NULL, NULL));
181 std::cout << "have " << entry << " expect one of " << p->second << std::endl;
182 ASSERT_TRUE(p->second.count(entry));
183 ++p;
184 }
185 rados_nobjects_list_close(ctx);
186}
187
11fdf7f2
TL
188// this function replicates
189// librados::operator<<(std::ostream& os, const librados::ObjectCursor& oc)
190// because we don't want to use librados in librados client.
191std::ostream& operator<<(std::ostream&os, const rados_object_list_cursor& oc)
192{
193 if (oc) {
194 os << *(hobject_t *)oc;
195 } else {
196 os << hobject_t{};
7c673cae 197 }
11fdf7f2 198 return os;
7c673cae
FG
199}
200
201TEST_F(LibRadosList, ListObjectsCursor) {
202 char buf[128];
203 memset(buf, 0xcc, sizeof(buf));
204
205 const int max_objs = 16;
206
207 for (int i=0; i<max_objs; ++i) {
208 string n = stringify(i);
209 ASSERT_EQ(0, rados_write(ioctx, n.c_str(), buf, sizeof(buf), 0));
210 }
211
212 {
213 rados_list_ctx_t ctx;
214 const char *entry;
215 rados_object_list_cursor cursor;
216 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
217 ASSERT_EQ(rados_nobjects_list_get_cursor(ctx, &cursor), 0);
218 rados_object_list_cursor first_cursor = cursor;
11fdf7f2 219 cout << "x cursor=" << cursor << std::endl;
7c673cae
FG
220 while (rados_nobjects_list_next(ctx, &entry, NULL, NULL) == 0) {
221 string oid = entry;
222 ASSERT_EQ(rados_nobjects_list_get_cursor(ctx, &cursor), 0);
11fdf7f2 223 cout << "> oid=" << oid << " cursor=" << cursor << std::endl;
7c673cae
FG
224 }
225 rados_nobjects_list_seek_cursor(ctx, first_cursor);
226 ASSERT_EQ(rados_nobjects_list_next(ctx, &entry, NULL, NULL), 0);
11fdf7f2 227 cout << "FIRST> seek to " << first_cursor << " oid=" << string(entry) << std::endl;
7c673cae
FG
228 }
229 rados_list_ctx_t ctx;
230 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
231
232 std::map<rados_object_list_cursor, string> cursor_to_obj;
233 int count = 0;
234
235 const char *entry;
236 while (rados_nobjects_list_next(ctx, &entry, NULL, NULL) == 0) {
237 rados_object_list_cursor cursor;
238 ASSERT_EQ(rados_nobjects_list_get_cursor(ctx, &cursor), 0);
239 string oid = entry;
11fdf7f2 240 cout << ": oid=" << oid << " cursor=" << cursor << std::endl;
7c673cae
FG
241 cursor_to_obj[cursor] = oid;
242
243 rados_nobjects_list_seek_cursor(ctx, cursor);
11fdf7f2 244 cout << ": seek to " << cursor << std::endl;
7c673cae 245 ASSERT_EQ(rados_nobjects_list_next(ctx, &entry, NULL, NULL), 0);
11fdf7f2 246 cout << "> " << cursor << " -> " << entry << std::endl;
7c673cae
FG
247 ASSERT_EQ(string(entry), oid);
248 ASSERT_LT(count, max_objs); /* avoid infinite loops due to bad seek */
249
250 ++count;
251 }
252
253 ASSERT_EQ(count, max_objs);
254
255 auto p = cursor_to_obj.rbegin();
256 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
257 while (p != cursor_to_obj.rend()) {
11fdf7f2 258 cout << ": seek to " << p->first << std::endl;
7c673cae
FG
259 rados_object_list_cursor cursor;
260 rados_object_list_cursor oid(p->first);
261 rados_nobjects_list_seek_cursor(ctx, oid);
262 ASSERT_EQ(rados_nobjects_list_get_cursor(ctx, &cursor), 0);
11fdf7f2 263 cout << ": cursor()=" << cursor << " expected=" << oid << std::endl;
7c673cae
FG
264 // ASSERT_EQ(ObjectCursor(oid), ObjectCursor(cursor));
265 ASSERT_EQ(rados_nobjects_list_next(ctx, &entry, NULL, NULL), 0);
11fdf7f2 266 cout << "> " << cursor << " -> " << entry << std::endl;
7c673cae
FG
267 cout << ": entry=" << entry << " expected=" << p->second << std::endl;
268 ASSERT_EQ(p->second, string(entry));
269
270 ++p;
271
272 rados_object_list_cursor_free(ctx, cursor);
273 }
274}
275
276TEST_F(LibRadosListEC, ListObjects) {
277 char buf[128];
278 memset(buf, 0xcc, sizeof(buf));
279 ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
280 rados_list_ctx_t ctx;
281 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
282 const char *entry;
283 bool foundit = false;
284 while (rados_nobjects_list_next(ctx, &entry, NULL, NULL) != -ENOENT) {
285 foundit = true;
286 ASSERT_EQ(std::string(entry), "foo");
287 }
288 ASSERT_TRUE(foundit);
289 rados_nobjects_list_close(ctx);
290}
291
7c673cae
FG
292TEST_F(LibRadosListEC, ListObjectsNS) {
293 char buf[128];
294 memset(buf, 0xcc, sizeof(buf));
295 // Create :foo1, :foo2, :foo3, n1:foo1, ns1:foo4, ns1:foo5, ns2:foo6, n2:foo7
296 rados_ioctx_set_namespace(ioctx, "");
297 ASSERT_EQ(0, rados_write(ioctx, "foo1", buf, sizeof(buf), 0));
298 rados_ioctx_set_namespace(ioctx, "ns1");
299 ASSERT_EQ(0, rados_write(ioctx, "foo1", buf, sizeof(buf), 0));
300 rados_ioctx_set_namespace(ioctx, "");
301 ASSERT_EQ(0, rados_write(ioctx, "foo2", buf, sizeof(buf), 0));
302 ASSERT_EQ(0, rados_write(ioctx, "foo3", buf, sizeof(buf), 0));
303 rados_ioctx_set_namespace(ioctx, "ns1");
304 ASSERT_EQ(0, rados_write(ioctx, "foo4", buf, sizeof(buf), 0));
305 ASSERT_EQ(0, rados_write(ioctx, "foo5", buf, sizeof(buf), 0));
306 rados_ioctx_set_namespace(ioctx, "ns2");
307 ASSERT_EQ(0, rados_write(ioctx, "foo6", buf, sizeof(buf), 0));
308 ASSERT_EQ(0, rados_write(ioctx, "foo7", buf, sizeof(buf), 0));
309
310 std::set<std::string> def, ns1, ns2, all;
311 def.insert(std::string("foo1"));
312 def.insert(std::string("foo2"));
313 def.insert(std::string("foo3"));
314 ns1.insert(std::string("foo1"));
315 ns1.insert(std::string("foo4"));
316 ns1.insert(std::string("foo5"));
317 ns2.insert(std::string("foo6"));
318 ns2.insert(std::string("foo7"));
319 all.insert(std::string(":foo1"));
320 all.insert(std::string(":foo2"));
321 all.insert(std::string(":foo3"));
322 all.insert(std::string("ns1:foo1"));
323 all.insert(std::string("ns1:foo4"));
324 all.insert(std::string("ns1:foo5"));
325 all.insert(std::string("ns2:foo6"));
326 all.insert(std::string("ns2:foo7"));
327
328 rados_list_ctx_t ctx;
329 // Check default namespace ""
330 rados_ioctx_set_namespace(ioctx, "");
331 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
332 check_list(def, ctx, "");
333 rados_nobjects_list_close(ctx);
334
335 // Check default namespace "ns1"
336 rados_ioctx_set_namespace(ioctx, "ns1");
337 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
338 check_list(ns1, ctx, "ns1");
339 rados_nobjects_list_close(ctx);
340
341 // Check default namespace "ns2"
342 rados_ioctx_set_namespace(ioctx, "ns2");
343 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
344 check_list(ns2, ctx, "ns2");
345 rados_nobjects_list_close(ctx);
346
347 // Check all namespaces
348 rados_ioctx_set_namespace(ioctx, LIBRADOS_ALL_NSPACES);
349 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
350 check_list(all, ctx, all_nspaces);
351 rados_nobjects_list_close(ctx);
352}
353
7c673cae
FG
354
355TEST_F(LibRadosListEC, ListObjectsStart) {
356 char buf[128];
357 memset(buf, 0xcc, sizeof(buf));
358
359 for (int i=0; i<16; ++i) {
360 string n = stringify(i);
361 ASSERT_EQ(0, rados_write(ioctx, n.c_str(), buf, sizeof(buf), 0));
362 }
363
364 rados_list_ctx_t ctx;
365 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
366 std::map<int, std::set<std::string> > pg_to_obj;
367 const char *entry;
368 while (rados_nobjects_list_next(ctx, &entry, NULL, NULL) == 0) {
369 uint32_t pos = rados_nobjects_list_get_pg_hash_position(ctx);
370 std::cout << entry << " " << pos << std::endl;
371 pg_to_obj[pos].insert(entry);
372 }
373 rados_nobjects_list_close(ctx);
374
375 std::map<int, std::set<std::string> >::reverse_iterator p =
376 pg_to_obj.rbegin();
377 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
378 while (p != pg_to_obj.rend()) {
379 ASSERT_EQ((uint32_t)p->first, rados_nobjects_list_seek(ctx, p->first));
380 ASSERT_EQ(0, rados_nobjects_list_next(ctx, &entry, NULL, NULL));
381 std::cout << "have " << entry << " expect one of " << p->second << std::endl;
382 ASSERT_TRUE(p->second.count(entry));
383 ++p;
384 }
385 rados_nobjects_list_close(ctx);
386}
387
7c673cae
FG
388TEST_F(LibRadosListNP, ListObjectsError) {
389 std::string pool_name;
390 rados_t cluster;
391 rados_ioctx_t ioctx;
392 pool_name = get_temp_pool_name();
393 ASSERT_EQ("", create_one_pool(pool_name, &cluster));
394 ASSERT_EQ(0, rados_ioctx_create(cluster, pool_name.c_str(), &ioctx));
395 char buf[128];
396 memset(buf, 0xcc, sizeof(buf));
397 rados_ioctx_set_namespace(ioctx, "");
398 ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0));
399
400 //ASSERT_EQ(0, rados_pool_delete(cluster, pool_name.c_str()));
401 {
402 char *buf, *st;
403 size_t buflen, stlen;
404 string c = "{\"prefix\":\"osd pool rm\",\"pool\": \"" + pool_name +
405 "\",\"pool2\":\"" + pool_name +
11fdf7f2 406 "\",\"yes_i_really_really_mean_it_not_faking\": true}";
7c673cae
FG
407 const char *cmd[2] = { c.c_str(), 0 };
408 ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
31f18b77 409 ASSERT_EQ(0, rados_wait_for_latest_osdmap(cluster));
7c673cae
FG
410 }
411
412 rados_list_ctx_t ctx;
413 ASSERT_EQ(0, rados_nobjects_list_open(ioctx, &ctx));
414 const char *entry;
415 ASSERT_EQ(-ENOENT, rados_nobjects_list_next(ctx, &entry, NULL, NULL));
416 rados_nobjects_list_close(ctx);
417 rados_ioctx_destroy(ioctx);
418 rados_shutdown(cluster);
419}
420
421
422
423// ---------------------------------------------
424
425TEST_F(LibRadosList, EnumerateObjects) {
426 char buf[128];
427 memset(buf, 0xcc, sizeof(buf));
428
429 const uint32_t n_objects = 16;
430 for (unsigned i=0; i<n_objects; ++i) {
431 ASSERT_EQ(0, rados_write(ioctx, stringify(i).c_str(), buf, sizeof(buf), 0));
432 }
433
434 // Ensure a non-power-of-two PG count to avoid only
435 // touching the easy path.
28e407b8
AA
436 ASSERT_TRUE(set_pg_num(&s_cluster, pool_name, 11).empty());
437 ASSERT_TRUE(set_pgp_num(&s_cluster, pool_name, 11).empty());
7c673cae
FG
438
439 std::set<std::string> saw_obj;
440 rados_object_list_cursor c = rados_object_list_begin(ioctx);
441 rados_object_list_cursor end = rados_object_list_end(ioctx);
442 while(!rados_object_list_is_end(ioctx, c))
443 {
444 rados_object_list_item results[12];
445 memset(results, 0, sizeof(rados_object_list_item) * 12);
446 rados_object_list_cursor temp_end = rados_object_list_end(ioctx);
447 int r = rados_object_list(ioctx, c, temp_end,
448 12, NULL, 0, results, &c);
449 rados_object_list_cursor_free(ioctx, temp_end);
450 ASSERT_GE(r, 0);
451 for (int i = 0; i < r; ++i) {
452 std::string oid(results[i].oid, results[i].oid_length);
453 if (saw_obj.count(oid)) {
454 std::cerr << "duplicate obj " << oid << std::endl;
455 }
456 ASSERT_FALSE(saw_obj.count(oid));
457 saw_obj.insert(oid);
458 }
459 rados_object_list_free(12, results);
460 }
461 rados_object_list_cursor_free(ioctx, c);
462 rados_object_list_cursor_free(ioctx, end);
463
464 for (unsigned i=0; i<n_objects; ++i) {
465 if (!saw_obj.count(stringify(i))) {
466 std::cerr << "missing object " << i << std::endl;
467 }
468 ASSERT_TRUE(saw_obj.count(stringify(i)));
469 }
470 ASSERT_EQ(n_objects, saw_obj.size());
471}
472
473TEST_F(LibRadosList, EnumerateObjectsSplit) {
474 char buf[128];
475 memset(buf, 0xcc, sizeof(buf));
476
477 const uint32_t n_objects = 16;
478 for (unsigned i=0; i<n_objects; ++i) {
479 ASSERT_EQ(0, rados_write(ioctx, stringify(i).c_str(), buf, sizeof(buf), 0));
480 }
481
482 // Ensure a non-power-of-two PG count to avoid only
483 // touching the easy path.
20effc67
TL
484 if (auto error = set_pg_num(&s_cluster, pool_name, 11); !error.empty()) {
485 GTEST_FAIL() << error;
486 }
487 if (auto error = set_pgp_num(&s_cluster, pool_name, 11); !error.empty()) {
488 GTEST_FAIL() << error;
489 }
7c673cae
FG
490
491 rados_object_list_cursor begin = rados_object_list_begin(ioctx);
492 rados_object_list_cursor end = rados_object_list_end(ioctx);
493
494 // Step through an odd number of shards
495 unsigned m = 5;
496 std::set<std::string> saw_obj;
497 for (unsigned n = 0; n < m; ++n) {
498 rados_object_list_cursor shard_start = rados_object_list_begin(ioctx);;
499 rados_object_list_cursor shard_end = rados_object_list_end(ioctx);;
500
501 rados_object_list_slice(
502 ioctx,
503 begin,
504 end,
505 n,
506 m,
507 &shard_start,
508 &shard_end);
509 std::cout << "split " << n << "/" << m << " -> "
510 << *(hobject_t*)shard_start << " "
511 << *(hobject_t*)shard_end << std::endl;
512
513 rados_object_list_cursor c = shard_start;
514 //while(c < shard_end)
515 while(rados_object_list_cursor_cmp(ioctx, c, shard_end) == -1)
516 {
517 rados_object_list_item results[12];
518 memset(results, 0, sizeof(rados_object_list_item) * 12);
519 int r = rados_object_list(ioctx,
520 c, shard_end,
521 12, NULL, 0, results, &c);
522 ASSERT_GE(r, 0);
523 for (int i = 0; i < r; ++i) {
524 std::string oid(results[i].oid, results[i].oid_length);
525 if (saw_obj.count(oid)) {
526 std::cerr << "duplicate obj " << oid << std::endl;
527 }
528 ASSERT_FALSE(saw_obj.count(oid));
529 saw_obj.insert(oid);
530 }
531 rados_object_list_free(12, results);
532 }
533 rados_object_list_cursor_free(ioctx, shard_start);
534 rados_object_list_cursor_free(ioctx, shard_end);
535 }
536
537 rados_object_list_cursor_free(ioctx, begin);
538 rados_object_list_cursor_free(ioctx, end);
539
540 for (unsigned i=0; i<n_objects; ++i) {
541 if (!saw_obj.count(stringify(i))) {
542 std::cerr << "missing object " << i << std::endl;
543 }
544 ASSERT_TRUE(saw_obj.count(stringify(i)));
545 }
546 ASSERT_EQ(n_objects, saw_obj.size());
547}