]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librados/list_cxx.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / test / librados / list_cxx.cc
CommitLineData
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
20using namespace librados;
21
22typedef RadosTestPPNSCleanup LibRadosListPP;
23typedef RadosTestECPPNSCleanup LibRadosListECPP;
24
25TEST_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
41TEST_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
67TEST_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
99TEST_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
124static 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
149TEST_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
201TEST_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
227TEST_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
255TEST_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
344TEST_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
398TEST_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
415TEST_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
442TEST_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
475TEST_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
501TEST_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
542TEST_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
569TEST_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
598TEST_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
640TEST_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
679TEST_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
736TEST_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}