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