]>
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 | ||
20effc67 | 18 | using namespace std; |
7c673cae FG |
19 | using namespace librados; |
20 | ||
21 | typedef RadosTestNSCleanup LibRadosList; | |
7c673cae | 22 | typedef RadosTestECNSCleanup LibRadosListEC; |
7c673cae FG |
23 | typedef RadosTestNP LibRadosListNP; |
24 | ||
25 | ||
26 | TEST_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 |
42 | TEST_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 | |
60 | static 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 | ||
86 | TEST_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 | |
155 | TEST_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. | |
191 | std::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 | ||
201 | TEST_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 | ||
276 | TEST_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 |
292 | TEST_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 | |
355 | TEST_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 |
388 | TEST_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 | ||
425 | TEST_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 | ||
473 | TEST_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 | } |