]>
Commit | Line | Data |
---|---|---|
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 | ||
18 | using namespace librados; | |
19 | ||
20 | typedef RadosTestNSCleanup LibRadosList; | |
7c673cae | 21 | typedef RadosTestECNSCleanup LibRadosListEC; |
7c673cae FG |
22 | typedef RadosTestNP LibRadosListNP; |
23 | ||
24 | ||
25 | TEST_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 |
41 | TEST_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 | |
59 | static 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 | ||
85 | TEST_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 | |
154 | TEST_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. | |
190 | std::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 | ||
200 | TEST_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 | ||
275 | TEST_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 |
291 | TEST_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 | |
354 | TEST_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 |
387 | TEST_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 | ||
424 | TEST_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 | ||
472 | TEST_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 | } |