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