]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | #include <errno.h> | |
4 | #include <string> | |
5 | #include <stdexcept> | |
6 | ||
7 | #include "gtest/gtest.h" | |
8 | ||
9 | #include "include/rados/librados.hpp" | |
10 | #include "include/stringify.h" | |
11 | #include "include/types.h" | |
12 | #include "common/hobject.h" | |
13 | #include "test/librados/test_cxx.h" | |
14 | #include "test/librados/test_common.h" | |
15 | #include "test/librados/testcase_cxx.h" | |
16 | #include "global/global_context.h" | |
17 | ||
1e59de90 TL |
18 | #include "crimson_utils.h" |
19 | ||
11fdf7f2 TL |
20 | using namespace librados; |
21 | ||
22 | typedef RadosTestPPNSCleanup LibRadosListPP; | |
23 | typedef RadosTestECPPNSCleanup LibRadosListECPP; | |
24 | ||
25 | TEST_F(LibRadosListPP, ListObjectsPP) { | |
26 | char buf[128]; | |
27 | memset(buf, 0xcc, sizeof(buf)); | |
28 | bufferlist bl1; | |
29 | bl1.append(buf, sizeof(buf)); | |
30 | ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0)); | |
31 | NObjectIterator iter(ioctx.nobjects_begin()); | |
32 | bool foundit = false; | |
33 | while (iter != ioctx.nobjects_end()) { | |
34 | foundit = true; | |
35 | ASSERT_EQ((*iter).get_oid(), "foo"); | |
36 | ++iter; | |
37 | } | |
38 | ASSERT_TRUE(foundit); | |
39 | } | |
40 | ||
41 | TEST_F(LibRadosListPP, ListObjectsTwicePP) { | |
42 | char buf[128]; | |
43 | memset(buf, 0xcc, sizeof(buf)); | |
44 | bufferlist bl1; | |
45 | bl1.append(buf, sizeof(buf)); | |
46 | ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0)); | |
47 | NObjectIterator iter(ioctx.nobjects_begin()); | |
48 | bool foundit = false; | |
49 | while (iter != ioctx.nobjects_end()) { | |
50 | foundit = true; | |
51 | ASSERT_EQ((*iter).get_oid(), "foo"); | |
52 | ++iter; | |
53 | } | |
54 | ASSERT_TRUE(foundit); | |
55 | ++iter; | |
56 | ASSERT_TRUE(iter == ioctx.nobjects_end()); | |
57 | foundit = false; | |
58 | iter.seek(0); | |
59 | while (iter != ioctx.nobjects_end()) { | |
60 | foundit = true; | |
61 | ASSERT_EQ((*iter).get_oid(), "foo"); | |
62 | ++iter; | |
63 | } | |
64 | ASSERT_TRUE(foundit); | |
65 | } | |
66 | ||
67 | TEST_F(LibRadosListPP, ListObjectsCopyIterPP) { | |
68 | char buf[128]; | |
69 | memset(buf, 0xcc, sizeof(buf)); | |
70 | bufferlist bl1; | |
71 | bl1.append(buf, sizeof(buf)); | |
72 | ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0)); | |
73 | ||
74 | // make sure this is still valid after the original iterators are gone | |
75 | NObjectIterator iter3; | |
76 | { | |
77 | NObjectIterator iter(ioctx.nobjects_begin()); | |
78 | NObjectIterator iter2(iter); | |
79 | iter3 = iter2; | |
80 | ASSERT_EQ((*iter).get_oid(), "foo"); | |
81 | ++iter; | |
82 | ASSERT_TRUE(iter == ioctx.nobjects_end()); | |
83 | ++iter; | |
84 | ASSERT_TRUE(iter == ioctx.nobjects_end()); | |
85 | ||
86 | ASSERT_EQ(iter2->get_oid(), "foo"); | |
87 | ASSERT_EQ(iter3->get_oid(), "foo"); | |
88 | ++iter2; | |
89 | ASSERT_TRUE(iter2 == ioctx.nobjects_end()); | |
90 | } | |
91 | ||
92 | ASSERT_EQ(iter3->get_oid(), "foo"); | |
93 | iter3 = iter3; | |
94 | ASSERT_EQ(iter3->get_oid(), "foo"); | |
95 | ++iter3; | |
96 | ASSERT_TRUE(iter3 == ioctx.nobjects_end()); | |
97 | } | |
98 | ||
99 | TEST_F(LibRadosListPP, ListObjectsEndIter) { | |
100 | char buf[128]; | |
101 | memset(buf, 0xcc, sizeof(buf)); | |
102 | bufferlist bl1; | |
103 | bl1.append(buf, sizeof(buf)); | |
104 | ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0)); | |
105 | ||
106 | NObjectIterator iter(ioctx.nobjects_begin()); | |
107 | NObjectIterator iter_end(ioctx.nobjects_end()); | |
108 | NObjectIterator iter_end2 = ioctx.nobjects_end(); | |
109 | ASSERT_TRUE(iter_end == iter_end2); | |
110 | ASSERT_TRUE(iter_end == ioctx.nobjects_end()); | |
111 | ASSERT_TRUE(iter_end2 == ioctx.nobjects_end()); | |
112 | ||
113 | ASSERT_EQ(iter->get_oid(), "foo"); | |
114 | ++iter; | |
115 | ASSERT_TRUE(iter == ioctx.nobjects_end()); | |
116 | ASSERT_TRUE(iter == iter_end); | |
117 | ASSERT_TRUE(iter == iter_end2); | |
118 | NObjectIterator iter2 = iter; | |
119 | ASSERT_TRUE(iter2 == ioctx.nobjects_end()); | |
120 | ASSERT_TRUE(iter2 == iter_end); | |
121 | ASSERT_TRUE(iter2 == iter_end2); | |
122 | } | |
123 | ||
124 | static void check_listpp(std::set<std::string>& myset, IoCtx& ioctx, const std::string &check_nspace) | |
125 | { | |
126 | NObjectIterator iter(ioctx.nobjects_begin()); | |
127 | std::set<std::string> orig_set(myset); | |
128 | /** | |
129 | * During splitting, we might see duplicate items. | |
130 | * We assert that every object returned is in myset and that | |
131 | * we don't hit ENOENT until we have hit every item in myset | |
132 | * at least once. | |
133 | */ | |
134 | while (iter != ioctx.nobjects_end()) { | |
135 | std::string test_name; | |
136 | if (check_nspace == all_nspaces) { | |
137 | test_name = iter->get_nspace() + ":" + iter->get_oid(); | |
138 | } else { | |
139 | ASSERT_TRUE(iter->get_nspace() == check_nspace); | |
140 | test_name = iter->get_oid(); | |
141 | } | |
142 | ASSERT_TRUE(orig_set.end() != orig_set.find(test_name)); | |
143 | myset.erase(test_name); | |
144 | ++iter; | |
145 | } | |
146 | ASSERT_TRUE(myset.empty()); | |
147 | } | |
148 | ||
149 | TEST_F(LibRadosListPP, ListObjectsPPNS) { | |
150 | char buf[128]; | |
151 | memset(buf, 0xcc, sizeof(buf)); | |
152 | bufferlist bl1; | |
153 | bl1.append(buf, sizeof(buf)); | |
154 | // Create :foo1, :foo2, :foo3, n1:foo1, ns1:foo4, ns1:foo5, ns2:foo6, n2:foo7 | |
155 | ioctx.set_namespace(""); | |
156 | ASSERT_EQ(0, ioctx.write("foo1", bl1, sizeof(buf), 0)); | |
157 | ioctx.set_namespace("ns1"); | |
158 | ASSERT_EQ(0, ioctx.write("foo1", bl1, sizeof(buf), 0)); | |
159 | ioctx.set_namespace(""); | |
160 | ASSERT_EQ(0, ioctx.write("foo2", bl1, sizeof(buf), 0)); | |
161 | ASSERT_EQ(0, ioctx.write("foo3", bl1, sizeof(buf), 0)); | |
162 | ioctx.set_namespace("ns1"); | |
163 | ASSERT_EQ(0, ioctx.write("foo4", bl1, sizeof(buf), 0)); | |
164 | ASSERT_EQ(0, ioctx.write("foo5", bl1, sizeof(buf), 0)); | |
165 | ioctx.set_namespace("ns2"); | |
166 | ASSERT_EQ(0, ioctx.write("foo6", bl1, sizeof(buf), 0)); | |
167 | ASSERT_EQ(0, ioctx.write("foo7", bl1, sizeof(buf), 0)); | |
168 | ASSERT_EQ(std::string("ns2"), ioctx.get_namespace()); | |
169 | ||
170 | std::set<std::string> def, ns1, ns2, all; | |
171 | def.insert(std::string("foo1")); | |
172 | def.insert(std::string("foo2")); | |
173 | def.insert(std::string("foo3")); | |
174 | ns1.insert(std::string("foo1")); | |
175 | ns1.insert(std::string("foo4")); | |
176 | ns1.insert(std::string("foo5")); | |
177 | ns2.insert(std::string("foo6")); | |
178 | ns2.insert(std::string("foo7")); | |
179 | all.insert(std::string(":foo1")); | |
180 | all.insert(std::string(":foo2")); | |
181 | all.insert(std::string(":foo3")); | |
182 | all.insert(std::string("ns1:foo1")); | |
183 | all.insert(std::string("ns1:foo4")); | |
184 | all.insert(std::string("ns1:foo5")); | |
185 | all.insert(std::string("ns2:foo6")); | |
186 | all.insert(std::string("ns2:foo7")); | |
187 | ||
188 | ioctx.set_namespace(""); | |
189 | check_listpp(def, ioctx, ""); | |
190 | ||
191 | ioctx.set_namespace("ns1"); | |
192 | check_listpp(ns1, ioctx, "ns1"); | |
193 | ||
194 | ioctx.set_namespace("ns2"); | |
195 | check_listpp(ns2, ioctx, "ns2"); | |
196 | ||
197 | ioctx.set_namespace(all_nspaces); | |
198 | check_listpp(all, ioctx, all_nspaces); | |
199 | } | |
200 | ||
201 | TEST_F(LibRadosListPP, ListObjectsManyPP) { | |
202 | char buf[128]; | |
203 | memset(buf, 0xcc, sizeof(buf)); | |
204 | bufferlist bl; | |
205 | bl.append(buf, sizeof(buf)); | |
206 | ||
207 | for (int i=0; i<256; ++i) { | |
208 | ASSERT_EQ(0, ioctx.write(stringify(i), bl, bl.length(), 0)); | |
209 | } | |
210 | ||
211 | librados::NObjectIterator it = ioctx.nobjects_begin(); | |
212 | std::set<std::string> saw_obj; | |
213 | std::set<int> saw_pg; | |
214 | for (; it != ioctx.nobjects_end(); ++it) { | |
215 | std::cout << it->get_oid() | |
216 | << " " << it.get_pg_hash_position() << std::endl; | |
217 | saw_obj.insert(it->get_oid()); | |
218 | saw_pg.insert(it.get_pg_hash_position()); | |
219 | } | |
220 | std::cout << "saw " << saw_pg.size() << " pgs " << std::endl; | |
221 | ||
222 | // make sure they are 0..n | |
223 | for (unsigned i = 0; i < saw_pg.size(); ++i) | |
224 | ASSERT_TRUE(saw_pg.count(i)); | |
225 | } | |
226 | ||
227 | TEST_F(LibRadosListPP, ListObjectsStartPP) { | |
228 | char buf[128]; | |
229 | memset(buf, 0xcc, sizeof(buf)); | |
230 | bufferlist bl; | |
231 | bl.append(buf, sizeof(buf)); | |
232 | ||
233 | for (int i=0; i<16; ++i) { | |
234 | ASSERT_EQ(0, ioctx.write(stringify(i), bl, bl.length(), 0)); | |
235 | } | |
236 | ||
237 | librados::NObjectIterator it = ioctx.nobjects_begin(); | |
238 | std::map<int, std::set<std::string> > pg_to_obj; | |
239 | for (; it != ioctx.nobjects_end(); ++it) { | |
240 | std::cout << it->get_oid() << " " << it.get_pg_hash_position() << std::endl; | |
241 | pg_to_obj[it.get_pg_hash_position()].insert(it->get_oid()); | |
242 | } | |
243 | ||
244 | std::map<int, std::set<std::string> >::reverse_iterator p = | |
245 | pg_to_obj.rbegin(); | |
246 | it = ioctx.nobjects_begin(p->first); | |
247 | while (p != pg_to_obj.rend()) { | |
248 | ASSERT_EQ((uint32_t)p->first, it.seek(p->first)); | |
249 | std::cout << "have " << it->get_oid() << " expect one of " << p->second << std::endl; | |
250 | ASSERT_TRUE(p->second.count(it->get_oid())); | |
251 | ++p; | |
252 | } | |
253 | } | |
254 | ||
255 | TEST_F(LibRadosListPP, ListObjectsCursorNSPP) { | |
256 | char buf[128]; | |
257 | memset(buf, 0xcc, sizeof(buf)); | |
258 | bufferlist bl; | |
259 | bl.append(buf, sizeof(buf)); | |
260 | ||
261 | const int max_objs = 16; | |
262 | ||
263 | map<string, string> oid_to_ns; | |
264 | ||
265 | for (int i=0; i<max_objs; ++i) { | |
266 | stringstream ss; | |
267 | ss << "ns" << i / 4; | |
268 | ioctx.set_namespace(ss.str()); | |
269 | string oid = stringify(i); | |
270 | ASSERT_EQ(0, ioctx.write(oid, bl, bl.length(), 0)); | |
271 | ||
272 | oid_to_ns[oid] = ss.str(); | |
273 | } | |
274 | ||
275 | ioctx.set_namespace(all_nspaces); | |
276 | ||
277 | librados::NObjectIterator it = ioctx.nobjects_begin(); | |
278 | std::map<librados::ObjectCursor, string> cursor_to_obj; | |
279 | ||
280 | int count = 0; | |
281 | ||
282 | librados::ObjectCursor seek_cursor; | |
283 | ||
284 | map<string, list<librados::ObjectCursor> > ns_to_cursors; | |
285 | ||
286 | for (it = ioctx.nobjects_begin(); it != ioctx.nobjects_end(); ++it) { | |
287 | librados::ObjectCursor cursor = it.get_cursor(); | |
288 | string oid = it->get_oid(); | |
289 | cout << "> oid=" << oid << " cursor=" << it.get_cursor() << std::endl; | |
290 | } | |
291 | ||
292 | vector<string> objs_order; | |
293 | ||
294 | for (it = ioctx.nobjects_begin(); it != ioctx.nobjects_end(); ++it, ++count) { | |
295 | librados::ObjectCursor cursor = it.get_cursor(); | |
296 | string oid = it->get_oid(); | |
297 | std::cout << oid << " " << it.get_pg_hash_position() << std::endl; | |
298 | cout << ": oid=" << oid << " cursor=" << it.get_cursor() << std::endl; | |
299 | cursor_to_obj[cursor] = oid; | |
300 | ||
301 | ASSERT_EQ(oid_to_ns[oid], it->get_nspace()); | |
302 | ||
303 | it.seek(cursor); | |
304 | cout << ": seek to " << cursor << " it.cursor=" << it.get_cursor() << std::endl; | |
305 | ASSERT_EQ(oid, it->get_oid()); | |
306 | ASSERT_LT(count, max_objs); /* avoid infinite loops due to bad seek */ | |
307 | ||
308 | ns_to_cursors[it->get_nspace()].push_back(cursor); | |
309 | ||
310 | if (count == max_objs/2) { | |
311 | seek_cursor = cursor; | |
312 | } | |
313 | objs_order.push_back(it->get_oid()); | |
314 | } | |
315 | ||
316 | ASSERT_EQ(count, max_objs); | |
317 | ||
318 | /* check that reading past seek also works */ | |
319 | cout << "seek_cursor=" << seek_cursor << std::endl; | |
320 | it.seek(seek_cursor); | |
321 | for (count = max_objs/2; count < max_objs; ++count, ++it) { | |
322 | ASSERT_EQ(objs_order[count], it->get_oid()); | |
323 | } | |
324 | ||
325 | /* seek to all cursors, check that we get expected obj */ | |
326 | for (auto& niter : ns_to_cursors) { | |
327 | const string& ns = niter.first; | |
328 | list<librados::ObjectCursor>& cursors = niter.second; | |
329 | ||
330 | for (auto& cursor : cursors) { | |
331 | cout << ": seek to " << cursor << std::endl; | |
332 | it.seek(cursor); | |
333 | ASSERT_EQ(cursor, it.get_cursor()); | |
334 | string& expected_oid = cursor_to_obj[cursor]; | |
335 | cout << ": it->get_cursor()=" << it.get_cursor() << " expected=" << cursor << std::endl; | |
336 | cout << ": it->get_oid()=" << it->get_oid() << " expected=" << expected_oid << std::endl; | |
337 | cout << ": it->get_nspace()=" << it->get_oid() << " expected=" << ns << std::endl; | |
338 | ASSERT_EQ(expected_oid, it->get_oid()); | |
339 | ASSERT_EQ(it->get_nspace(), ns); | |
340 | } | |
341 | } | |
342 | } | |
343 | ||
344 | TEST_F(LibRadosListPP, ListObjectsCursorPP) { | |
345 | char buf[128]; | |
346 | memset(buf, 0xcc, sizeof(buf)); | |
347 | bufferlist bl; | |
348 | bl.append(buf, sizeof(buf)); | |
349 | ||
350 | const int max_objs = 16; | |
351 | ||
352 | for (int i=0; i<max_objs; ++i) { | |
353 | stringstream ss; | |
354 | ss << "ns" << i / 4; | |
355 | ioctx.set_namespace(ss.str()); | |
356 | ASSERT_EQ(0, ioctx.write(stringify(i), bl, bl.length(), 0)); | |
357 | } | |
358 | ||
359 | ioctx.set_namespace(all_nspaces); | |
360 | ||
361 | librados::NObjectIterator it = ioctx.nobjects_begin(); | |
362 | std::map<librados::ObjectCursor, string> cursor_to_obj; | |
363 | ||
364 | int count = 0; | |
365 | ||
366 | for (; it != ioctx.nobjects_end(); ++it, ++count) { | |
367 | librados::ObjectCursor cursor = it.get_cursor(); | |
368 | string oid = it->get_oid(); | |
369 | std::cout << oid << " " << it.get_pg_hash_position() << std::endl; | |
370 | cout << ": oid=" << oid << " cursor=" << it.get_cursor() << std::endl; | |
371 | cursor_to_obj[cursor] = oid; | |
372 | ||
373 | it.seek(cursor); | |
374 | cout << ": seek to " << cursor << std::endl; | |
375 | ASSERT_EQ(oid, it->get_oid()); | |
376 | ASSERT_LT(count, max_objs); /* avoid infinite loops due to bad seek */ | |
377 | } | |
378 | ||
379 | ASSERT_EQ(count, max_objs); | |
380 | ||
381 | auto p = cursor_to_obj.rbegin(); | |
382 | it = ioctx.nobjects_begin(); | |
383 | while (p != cursor_to_obj.rend()) { | |
384 | cout << ": seek to " << p->first << std::endl; | |
385 | it.seek(p->first); | |
386 | ASSERT_EQ(p->first, it.get_cursor()); | |
387 | cout << ": it->get_cursor()=" << it.get_cursor() << " expected=" << p->first << std::endl; | |
388 | cout << ": it->get_oid()=" << it->get_oid() << " expected=" << p->second << std::endl; | |
389 | ASSERT_EQ(p->second, it->get_oid()); | |
390 | ||
391 | librados::NObjectIterator it2 = ioctx.nobjects_begin(it.get_cursor()); | |
392 | ASSERT_EQ(it2->get_oid(), it->get_oid()); | |
393 | ||
394 | ++p; | |
395 | } | |
396 | } | |
397 | ||
398 | TEST_F(LibRadosListECPP, ListObjectsPP) { | |
1e59de90 | 399 | SKIP_IF_CRIMSON(); |
11fdf7f2 TL |
400 | char buf[128]; |
401 | memset(buf, 0xcc, sizeof(buf)); | |
402 | bufferlist bl1; | |
403 | bl1.append(buf, sizeof(buf)); | |
404 | ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0)); | |
405 | NObjectIterator iter(ioctx.nobjects_begin()); | |
406 | bool foundit = false; | |
407 | while (iter != ioctx.nobjects_end()) { | |
408 | foundit = true; | |
409 | ASSERT_EQ((*iter).get_oid(), "foo"); | |
410 | ++iter; | |
411 | } | |
412 | ASSERT_TRUE(foundit); | |
413 | } | |
414 | ||
415 | TEST_F(LibRadosListECPP, ListObjectsTwicePP) { | |
1e59de90 | 416 | SKIP_IF_CRIMSON(); |
11fdf7f2 TL |
417 | char buf[128]; |
418 | memset(buf, 0xcc, sizeof(buf)); | |
419 | bufferlist bl1; | |
420 | bl1.append(buf, sizeof(buf)); | |
421 | ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0)); | |
422 | NObjectIterator iter(ioctx.nobjects_begin()); | |
423 | bool foundit = false; | |
424 | while (iter != ioctx.nobjects_end()) { | |
425 | foundit = true; | |
426 | ASSERT_EQ((*iter).get_oid(), "foo"); | |
427 | ++iter; | |
428 | } | |
429 | ASSERT_TRUE(foundit); | |
430 | ++iter; | |
431 | ASSERT_TRUE(iter == ioctx.nobjects_end()); | |
432 | foundit = false; | |
433 | iter.seek(0); | |
434 | while (iter != ioctx.nobjects_end()) { | |
435 | foundit = true; | |
436 | ASSERT_EQ((*iter).get_oid(), "foo"); | |
437 | ++iter; | |
438 | } | |
439 | ASSERT_TRUE(foundit); | |
440 | } | |
441 | ||
442 | TEST_F(LibRadosListECPP, ListObjectsCopyIterPP) { | |
1e59de90 | 443 | SKIP_IF_CRIMSON(); |
11fdf7f2 TL |
444 | char buf[128]; |
445 | memset(buf, 0xcc, sizeof(buf)); | |
446 | bufferlist bl1; | |
447 | bl1.append(buf, sizeof(buf)); | |
448 | ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0)); | |
449 | ||
450 | // make sure this is still valid after the original iterators are gone | |
451 | NObjectIterator iter3; | |
452 | { | |
453 | NObjectIterator iter(ioctx.nobjects_begin()); | |
454 | NObjectIterator iter2(iter); | |
455 | iter3 = iter2; | |
456 | ASSERT_EQ((*iter).get_oid(), "foo"); | |
457 | ++iter; | |
458 | ASSERT_TRUE(iter == ioctx.nobjects_end()); | |
459 | ++iter; | |
460 | ASSERT_TRUE(iter == ioctx.nobjects_end()); | |
461 | ||
462 | ASSERT_EQ(iter2->get_oid(), "foo"); | |
463 | ASSERT_EQ(iter3->get_oid(), "foo"); | |
464 | ++iter2; | |
465 | ASSERT_TRUE(iter2 == ioctx.nobjects_end()); | |
466 | } | |
467 | ||
468 | ASSERT_EQ(iter3->get_oid(), "foo"); | |
469 | iter3 = iter3; | |
470 | ASSERT_EQ(iter3->get_oid(), "foo"); | |
471 | ++iter3; | |
472 | ASSERT_TRUE(iter3 == ioctx.nobjects_end()); | |
473 | } | |
474 | ||
475 | TEST_F(LibRadosListECPP, ListObjectsEndIter) { | |
1e59de90 | 476 | SKIP_IF_CRIMSON(); |
11fdf7f2 TL |
477 | char buf[128]; |
478 | memset(buf, 0xcc, sizeof(buf)); | |
479 | bufferlist bl1; | |
480 | bl1.append(buf, sizeof(buf)); | |
481 | ASSERT_EQ(0, ioctx.write("foo", bl1, sizeof(buf), 0)); | |
482 | ||
483 | NObjectIterator iter(ioctx.nobjects_begin()); | |
484 | NObjectIterator iter_end(ioctx.nobjects_end()); | |
485 | NObjectIterator iter_end2 = ioctx.nobjects_end(); | |
486 | ASSERT_TRUE(iter_end == iter_end2); | |
487 | ASSERT_TRUE(iter_end == ioctx.nobjects_end()); | |
488 | ASSERT_TRUE(iter_end2 == ioctx.nobjects_end()); | |
489 | ||
490 | ASSERT_EQ(iter->get_oid(), "foo"); | |
491 | ++iter; | |
492 | ASSERT_TRUE(iter == ioctx.nobjects_end()); | |
493 | ASSERT_TRUE(iter == iter_end); | |
494 | ASSERT_TRUE(iter == iter_end2); | |
495 | NObjectIterator iter2 = iter; | |
496 | ASSERT_TRUE(iter2 == ioctx.nobjects_end()); | |
497 | ASSERT_TRUE(iter2 == iter_end); | |
498 | ASSERT_TRUE(iter2 == iter_end2); | |
499 | } | |
500 | ||
501 | TEST_F(LibRadosListECPP, ListObjectsPPNS) { | |
1e59de90 | 502 | SKIP_IF_CRIMSON(); |
11fdf7f2 TL |
503 | char buf[128]; |
504 | memset(buf, 0xcc, sizeof(buf)); | |
505 | bufferlist bl1; | |
506 | bl1.append(buf, sizeof(buf)); | |
507 | // Create :foo1, :foo2, :foo3, n1:foo1, ns1:foo4, ns1:foo5, ns2:foo6, n2:foo7 | |
508 | ioctx.set_namespace(""); | |
509 | ASSERT_EQ(0, ioctx.write("foo1", bl1, sizeof(buf), 0)); | |
510 | ioctx.set_namespace("ns1"); | |
511 | ASSERT_EQ(0, ioctx.write("foo1", bl1, sizeof(buf), 0)); | |
512 | ioctx.set_namespace(""); | |
513 | ASSERT_EQ(0, ioctx.write("foo2", bl1, sizeof(buf), 0)); | |
514 | ASSERT_EQ(0, ioctx.write("foo3", bl1, sizeof(buf), 0)); | |
515 | ioctx.set_namespace("ns1"); | |
516 | ASSERT_EQ(0, ioctx.write("foo4", bl1, sizeof(buf), 0)); | |
517 | ASSERT_EQ(0, ioctx.write("foo5", bl1, sizeof(buf), 0)); | |
518 | ioctx.set_namespace("ns2"); | |
519 | ASSERT_EQ(0, ioctx.write("foo6", bl1, sizeof(buf), 0)); | |
520 | ASSERT_EQ(0, ioctx.write("foo7", bl1, sizeof(buf), 0)); | |
521 | ||
522 | std::set<std::string> def, ns1, ns2; | |
523 | def.insert(std::string("foo1")); | |
524 | def.insert(std::string("foo2")); | |
525 | def.insert(std::string("foo3")); | |
526 | ns1.insert(std::string("foo1")); | |
527 | ns1.insert(std::string("foo4")); | |
528 | ns1.insert(std::string("foo5")); | |
529 | ns2.insert(std::string("foo6")); | |
530 | ns2.insert(std::string("foo7")); | |
531 | ||
532 | ioctx.set_namespace(""); | |
533 | check_listpp(def, ioctx, ""); | |
534 | ||
535 | ioctx.set_namespace("ns1"); | |
536 | check_listpp(ns1, ioctx, "ns1"); | |
537 | ||
538 | ioctx.set_namespace("ns2"); | |
539 | check_listpp(ns2, ioctx, "ns2"); | |
540 | } | |
541 | ||
542 | TEST_F(LibRadosListECPP, ListObjectsManyPP) { | |
1e59de90 | 543 | SKIP_IF_CRIMSON(); |
11fdf7f2 TL |
544 | char buf[128]; |
545 | memset(buf, 0xcc, sizeof(buf)); | |
546 | bufferlist bl; | |
547 | bl.append(buf, sizeof(buf)); | |
548 | ||
549 | for (int i=0; i<256; ++i) { | |
550 | ASSERT_EQ(0, ioctx.write(stringify(i), bl, bl.length(), 0)); | |
551 | } | |
552 | ||
553 | librados::NObjectIterator it = ioctx.nobjects_begin(); | |
554 | std::set<std::string> saw_obj; | |
555 | std::set<int> saw_pg; | |
556 | for (; it != ioctx.nobjects_end(); ++it) { | |
557 | std::cout << it->get_oid() | |
558 | << " " << it.get_pg_hash_position() << std::endl; | |
559 | saw_obj.insert(it->get_oid()); | |
560 | saw_pg.insert(it.get_pg_hash_position()); | |
561 | } | |
562 | std::cout << "saw " << saw_pg.size() << " pgs " << std::endl; | |
563 | ||
564 | // make sure they are 0..n | |
565 | for (unsigned i = 0; i < saw_pg.size(); ++i) | |
566 | ASSERT_TRUE(saw_pg.count(i)); | |
567 | } | |
568 | ||
569 | TEST_F(LibRadosListECPP, ListObjectsStartPP) { | |
1e59de90 | 570 | SKIP_IF_CRIMSON(); |
11fdf7f2 TL |
571 | char buf[128]; |
572 | memset(buf, 0xcc, sizeof(buf)); | |
573 | bufferlist bl; | |
574 | bl.append(buf, sizeof(buf)); | |
575 | ||
576 | for (int i=0; i<16; ++i) { | |
577 | ASSERT_EQ(0, ioctx.write(stringify(i), bl, bl.length(), 0)); | |
578 | } | |
579 | ||
580 | librados::NObjectIterator it = ioctx.nobjects_begin(); | |
581 | std::map<int, std::set<std::string> > pg_to_obj; | |
582 | for (; it != ioctx.nobjects_end(); ++it) { | |
583 | std::cout << it->get_oid() << " " << it.get_pg_hash_position() << std::endl; | |
584 | pg_to_obj[it.get_pg_hash_position()].insert(it->get_oid()); | |
585 | } | |
586 | ||
587 | std::map<int, std::set<std::string> >::reverse_iterator p = | |
588 | pg_to_obj.rbegin(); | |
589 | it = ioctx.nobjects_begin(p->first); | |
590 | while (p != pg_to_obj.rend()) { | |
591 | ASSERT_EQ((uint32_t)p->first, it.seek(p->first)); | |
592 | std::cout << "have " << it->get_oid() << " expect one of " << p->second << std::endl; | |
593 | ASSERT_TRUE(p->second.count(it->get_oid())); | |
594 | ++p; | |
595 | } | |
596 | } | |
597 | ||
598 | TEST_F(LibRadosListPP, ListObjectsFilterPP) { | |
599 | char buf[128]; | |
600 | memset(buf, 0xcc, sizeof(buf)); | |
601 | bufferlist obj_content; | |
602 | obj_content.append(buf, sizeof(buf)); | |
603 | ||
604 | std::string target_str = "content"; | |
605 | ||
606 | // Write xattr bare, no ::encod'ing | |
607 | bufferlist target_val; | |
608 | target_val.append(target_str); | |
609 | bufferlist nontarget_val; | |
610 | nontarget_val.append("rhubarb"); | |
611 | ||
612 | ASSERT_EQ(0, ioctx.write("has_xattr", obj_content, obj_content.length(), 0)); | |
613 | ASSERT_EQ(0, ioctx.write("has_wrong_xattr", obj_content, obj_content.length(), 0)); | |
614 | ASSERT_EQ(0, ioctx.write("no_xattr", obj_content, obj_content.length(), 0)); | |
615 | ||
616 | ASSERT_EQ(0, ioctx.setxattr("has_xattr", "theattr", target_val)); | |
617 | ASSERT_EQ(0, ioctx.setxattr("has_wrong_xattr", "theattr", nontarget_val)); | |
618 | ||
619 | bufferlist filter_bl; | |
620 | std::string filter_name = "plain"; | |
621 | encode(filter_name, filter_bl); | |
622 | encode("_theattr", filter_bl); | |
623 | encode(target_str, filter_bl); | |
624 | ||
625 | NObjectIterator iter(ioctx.nobjects_begin(filter_bl)); | |
626 | bool foundit = false; | |
627 | int k = 0; | |
628 | while (iter != ioctx.nobjects_end()) { | |
629 | foundit = true; | |
630 | // We should only see the object that matches the filter | |
631 | ASSERT_EQ((*iter).get_oid(), "has_xattr"); | |
632 | // We should only see it once | |
633 | ASSERT_EQ(k, 0); | |
634 | ++iter; | |
635 | ++k; | |
636 | } | |
637 | ASSERT_TRUE(foundit); | |
638 | } | |
639 | ||
640 | TEST_F(LibRadosListPP, EnumerateObjectsPP) { | |
641 | char buf[128]; | |
642 | memset(buf, 0xcc, sizeof(buf)); | |
643 | bufferlist bl; | |
644 | bl.append(buf, sizeof(buf)); | |
645 | ||
646 | const uint32_t n_objects = 16; | |
647 | for (unsigned i=0; i<n_objects; ++i) { | |
648 | ASSERT_EQ(0, ioctx.write(stringify(i), bl, sizeof(buf), 0)); | |
649 | } | |
650 | ||
651 | std::set<std::string> saw_obj; | |
652 | ObjectCursor c = ioctx.object_list_begin(); | |
653 | ObjectCursor end = ioctx.object_list_end(); | |
654 | while(!ioctx.object_list_is_end(c)) | |
655 | { | |
656 | std::vector<ObjectItem> result; | |
657 | int r = ioctx.object_list(c, end, 12, {}, &result, &c); | |
658 | ASSERT_GE(r, 0); | |
659 | ASSERT_EQ(r, (int)result.size()); | |
660 | for (int i = 0; i < r; ++i) { | |
661 | auto oid = result[i].oid; | |
662 | if (saw_obj.count(oid)) { | |
663 | std::cerr << "duplicate obj " << oid << std::endl; | |
664 | } | |
665 | ASSERT_FALSE(saw_obj.count(oid)); | |
666 | saw_obj.insert(oid); | |
667 | } | |
668 | } | |
669 | ||
670 | for (unsigned i=0; i<n_objects; ++i) { | |
671 | if (!saw_obj.count(stringify(i))) { | |
672 | std::cerr << "missing object " << i << std::endl; | |
673 | } | |
674 | ASSERT_TRUE(saw_obj.count(stringify(i))); | |
675 | } | |
676 | ASSERT_EQ(n_objects, saw_obj.size()); | |
677 | } | |
678 | ||
679 | TEST_F(LibRadosListPP, EnumerateObjectsSplitPP) { | |
680 | char buf[128]; | |
681 | memset(buf, 0xcc, sizeof(buf)); | |
682 | bufferlist bl; | |
683 | bl.append(buf, sizeof(buf)); | |
684 | ||
685 | const uint32_t n_objects = 16; | |
686 | for (unsigned i=0; i<n_objects; ++i) { | |
687 | ASSERT_EQ(0, ioctx.write(stringify(i), bl, sizeof(buf), 0)); | |
688 | } | |
689 | ||
690 | ObjectCursor begin = ioctx.object_list_begin(); | |
691 | ObjectCursor end = ioctx.object_list_end(); | |
692 | ||
693 | // Step through an odd number of shards | |
694 | unsigned m = 5; | |
695 | std::set<std::string> saw_obj; | |
696 | for (unsigned n = 0; n < m; ++n) { | |
697 | ObjectCursor shard_start; | |
698 | ObjectCursor shard_end; | |
699 | ||
700 | ioctx.object_list_slice( | |
701 | begin, | |
702 | end, | |
703 | n, | |
704 | m, | |
705 | &shard_start, | |
706 | &shard_end); | |
707 | ||
708 | ObjectCursor c(shard_start); | |
709 | while(c < shard_end) | |
710 | { | |
711 | std::vector<ObjectItem> result; | |
712 | int r = ioctx.object_list(c, shard_end, 12, {}, &result, &c); | |
713 | ASSERT_GE(r, 0); | |
714 | ||
715 | for (const auto & i : result) { | |
716 | const auto &oid = i.oid; | |
717 | if (saw_obj.count(oid)) { | |
718 | std::cerr << "duplicate obj " << oid << std::endl; | |
719 | } | |
720 | ASSERT_FALSE(saw_obj.count(oid)); | |
721 | saw_obj.insert(oid); | |
722 | } | |
723 | } | |
724 | } | |
725 | ||
726 | for (unsigned i=0; i<n_objects; ++i) { | |
727 | if (!saw_obj.count(stringify(i))) { | |
728 | std::cerr << "missing object " << i << std::endl; | |
729 | } | |
730 | ASSERT_TRUE(saw_obj.count(stringify(i))); | |
731 | } | |
732 | ASSERT_EQ(n_objects, saw_obj.size()); | |
733 | } | |
734 | ||
735 | ||
736 | TEST_F(LibRadosListPP, EnumerateObjectsFilterPP) { | |
737 | char buf[128]; | |
738 | memset(buf, 0xcc, sizeof(buf)); | |
739 | bufferlist obj_content; | |
740 | obj_content.append(buf, sizeof(buf)); | |
741 | ||
742 | std::string target_str = "content"; | |
743 | ||
744 | // Write xattr bare, no ::encod'ing | |
745 | bufferlist target_val; | |
746 | target_val.append(target_str); | |
747 | bufferlist nontarget_val; | |
748 | nontarget_val.append("rhubarb"); | |
749 | ||
750 | ASSERT_EQ(0, ioctx.write("has_xattr", obj_content, obj_content.length(), 0)); | |
751 | ASSERT_EQ(0, ioctx.write("has_wrong_xattr", obj_content, obj_content.length(), 0)); | |
752 | ASSERT_EQ(0, ioctx.write("no_xattr", obj_content, obj_content.length(), 0)); | |
753 | ||
754 | ASSERT_EQ(0, ioctx.setxattr("has_xattr", "theattr", target_val)); | |
755 | ASSERT_EQ(0, ioctx.setxattr("has_wrong_xattr", "theattr", nontarget_val)); | |
756 | ||
757 | bufferlist filter_bl; | |
758 | std::string filter_name = "plain"; | |
759 | encode(filter_name, filter_bl); | |
760 | encode("_theattr", filter_bl); | |
761 | encode(target_str, filter_bl); | |
762 | ||
763 | ObjectCursor c = ioctx.object_list_begin(); | |
764 | ObjectCursor end = ioctx.object_list_end(); | |
765 | bool foundit = false; | |
766 | while(!ioctx.object_list_is_end(c)) | |
767 | { | |
768 | std::vector<ObjectItem> result; | |
769 | int r = ioctx.object_list(c, end, 12, filter_bl, &result, &c); | |
770 | ASSERT_GE(r, 0); | |
771 | ASSERT_EQ(r, (int)result.size()); | |
772 | for (int i = 0; i < r; ++i) { | |
773 | auto oid = result[i].oid; | |
774 | // We should only see the object that matches the filter | |
775 | ASSERT_EQ(oid, "has_xattr"); | |
776 | // We should only see it once | |
777 | ASSERT_FALSE(foundit); | |
778 | foundit = true; | |
779 | } | |
780 | } | |
781 | ASSERT_TRUE(foundit); | |
782 | } |