]>
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 | ||
1e59de90 TL |
18 | #include "crimson_utils.h" |
19 | ||
20effc67 | 20 | using namespace std; |
7c673cae FG |
21 | using namespace librados; |
22 | ||
23 | typedef RadosTestNSCleanup LibRadosList; | |
7c673cae | 24 | typedef RadosTestECNSCleanup LibRadosListEC; |
7c673cae FG |
25 | typedef RadosTestNP LibRadosListNP; |
26 | ||
27 | ||
28 | TEST_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 |
44 | TEST_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 | |
62 | static 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 | ||
88 | TEST_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 | |
157 | TEST_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. | |
193 | std::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 | ||
203 | TEST_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 | ||
278 | TEST_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 | 295 | TEST_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 | |
359 | TEST_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 |
393 | TEST_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 | ||
430 | TEST_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 | ||
479 | TEST_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 | } |