]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/osd/types.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / test / osd / types.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2011 New Dream Network
7 * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
8 *
9 * Author: Loic Dachary <loic@dachary.org>
10 *
11 * This is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public
13 * License version 2, as published by the Free Software
14 * Foundation. See file COPYING.
15 *
16 */
17
18 #include "include/types.h"
19 #include "osd/osd_types.h"
20 #include "osd/OSDMap.h"
21 #include "gtest/gtest.h"
22 #include "include/coredumpctl.h"
23 #include "common/Thread.h"
24 #include "include/stringify.h"
25 #include "osd/ReplicatedBackend.h"
26
27 #include <sstream>
28
29 TEST(hobject, prefixes0)
30 {
31 uint32_t mask = 0xE947FA20;
32 uint32_t bits = 12;
33 int64_t pool = 0;
34
35 set<string> prefixes_correct;
36 prefixes_correct.insert(string("0000000000000000.02A"));
37
38 set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
39 ASSERT_EQ(prefixes_out, prefixes_correct);
40 }
41
42 TEST(hobject, prefixes1)
43 {
44 uint32_t mask = 0x0000000F;
45 uint32_t bits = 6;
46 int64_t pool = 20;
47
48 set<string> prefixes_correct;
49 prefixes_correct.insert(string("0000000000000014.F0"));
50 prefixes_correct.insert(string("0000000000000014.F4"));
51 prefixes_correct.insert(string("0000000000000014.F8"));
52 prefixes_correct.insert(string("0000000000000014.FC"));
53
54 set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
55 ASSERT_EQ(prefixes_out, prefixes_correct);
56 }
57
58 TEST(hobject, prefixes2)
59 {
60 uint32_t mask = 0xDEADBEAF;
61 uint32_t bits = 25;
62 int64_t pool = 0;
63
64 set<string> prefixes_correct;
65 prefixes_correct.insert(string("0000000000000000.FAEBDA0"));
66 prefixes_correct.insert(string("0000000000000000.FAEBDA2"));
67 prefixes_correct.insert(string("0000000000000000.FAEBDA4"));
68 prefixes_correct.insert(string("0000000000000000.FAEBDA6"));
69 prefixes_correct.insert(string("0000000000000000.FAEBDA8"));
70 prefixes_correct.insert(string("0000000000000000.FAEBDAA"));
71 prefixes_correct.insert(string("0000000000000000.FAEBDAC"));
72 prefixes_correct.insert(string("0000000000000000.FAEBDAE"));
73
74 set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
75 ASSERT_EQ(prefixes_out, prefixes_correct);
76 }
77
78 TEST(hobject, prefixes3)
79 {
80 uint32_t mask = 0xE947FA20;
81 uint32_t bits = 32;
82 int64_t pool = 0x23;
83
84 set<string> prefixes_correct;
85 prefixes_correct.insert(string("0000000000000023.02AF749E"));
86
87 set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
88 ASSERT_EQ(prefixes_out, prefixes_correct);
89 }
90
91 TEST(hobject, prefixes4)
92 {
93 uint32_t mask = 0xE947FA20;
94 uint32_t bits = 0;
95 int64_t pool = 0x23;
96
97 set<string> prefixes_correct;
98 prefixes_correct.insert(string("0000000000000023."));
99
100 set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
101 ASSERT_EQ(prefixes_out, prefixes_correct);
102 }
103
104 TEST(hobject, prefixes5)
105 {
106 uint32_t mask = 0xDEADBEAF;
107 uint32_t bits = 1;
108 int64_t pool = 0x34AC5D00;
109
110 set<string> prefixes_correct;
111 prefixes_correct.insert(string("0000000034AC5D00.1"));
112 prefixes_correct.insert(string("0000000034AC5D00.3"));
113 prefixes_correct.insert(string("0000000034AC5D00.5"));
114 prefixes_correct.insert(string("0000000034AC5D00.7"));
115 prefixes_correct.insert(string("0000000034AC5D00.9"));
116 prefixes_correct.insert(string("0000000034AC5D00.B"));
117 prefixes_correct.insert(string("0000000034AC5D00.D"));
118 prefixes_correct.insert(string("0000000034AC5D00.F"));
119
120 set<string> prefixes_out(hobject_t::get_prefixes(bits, mask, pool));
121 ASSERT_EQ(prefixes_out, prefixes_correct);
122 }
123
124 TEST(pg_interval_t, check_new_interval)
125 {
126 // iterate through all 4 combinations
127 for (unsigned i = 0; i < 4; ++i) {
128 bool compact = i & 1;
129 bool ec_pool = i & 2;
130 //
131 // Create a situation where osdmaps are the same so that
132 // each test case can diverge from it using minimal code.
133 //
134 int osd_id = 1;
135 epoch_t epoch = 40;
136 ceph::shared_ptr<OSDMap> osdmap(new OSDMap());
137 osdmap->set_max_osd(10);
138 osdmap->set_state(osd_id, CEPH_OSD_EXISTS);
139 osdmap->set_epoch(epoch);
140 ceph::shared_ptr<OSDMap> lastmap(new OSDMap());
141 lastmap->set_max_osd(10);
142 lastmap->set_state(osd_id, CEPH_OSD_EXISTS);
143 lastmap->set_epoch(epoch);
144 epoch_t same_interval_since = epoch;
145 epoch_t last_epoch_clean = same_interval_since;
146 int64_t pool_id = 200;
147 int pg_num = 4;
148 __u8 min_size = 2;
149 boost::scoped_ptr<IsPGRecoverablePredicate> recoverable(new ReplicatedBackend::RPCRecPred());
150 {
151 OSDMap::Incremental inc(epoch + 1);
152 inc.new_pools[pool_id].min_size = min_size;
153 inc.new_pools[pool_id].set_pg_num(pg_num);
154 inc.new_up_thru[osd_id] = epoch + 1;
155 osdmap->apply_incremental(inc);
156 lastmap->apply_incremental(inc);
157 }
158 vector<int> new_acting;
159 new_acting.push_back(osd_id);
160 new_acting.push_back(osd_id + 1);
161 vector<int> old_acting = new_acting;
162 int old_primary = osd_id;
163 int new_primary = osd_id;
164 vector<int> new_up;
165 new_up.push_back(osd_id);
166 int old_up_primary = osd_id;
167 int new_up_primary = osd_id;
168 vector<int> old_up = new_up;
169 pg_t pgid;
170 pgid.set_pool(pool_id);
171
172 //
173 // Do nothing if there are no modifications in
174 // acting, up or pool size and that the pool is not
175 // being split
176 //
177 {
178 PastIntervals past_intervals; past_intervals.update_type(ec_pool, compact);
179
180 ASSERT_TRUE(past_intervals.empty());
181 ASSERT_FALSE(PastIntervals::check_new_interval(old_primary,
182 new_primary,
183 old_acting,
184 new_acting,
185 old_up_primary,
186 new_up_primary,
187 old_up,
188 new_up,
189 same_interval_since,
190 last_epoch_clean,
191 osdmap,
192 lastmap,
193 pgid,
194 recoverable.get(),
195 &past_intervals));
196 ASSERT_TRUE(past_intervals.empty());
197 }
198
199 //
200 // The acting set has changed
201 //
202 {
203 vector<int> new_acting;
204 int _new_primary = osd_id + 1;
205 new_acting.push_back(_new_primary);
206
207 PastIntervals past_intervals; past_intervals.update_type(ec_pool, compact);
208
209 ASSERT_TRUE(past_intervals.empty());
210 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary,
211 new_primary,
212 old_acting,
213 new_acting,
214 old_up_primary,
215 new_up_primary,
216 old_up,
217 new_up,
218 same_interval_since,
219 last_epoch_clean,
220 osdmap,
221 lastmap,
222 pgid,
223 recoverable.get(),
224 &past_intervals));
225 old_primary = new_primary;
226 }
227
228 //
229 // The up set has changed
230 //
231 {
232 vector<int> new_up;
233 int _new_primary = osd_id + 1;
234 new_up.push_back(_new_primary);
235
236 PastIntervals past_intervals; past_intervals.update_type(ec_pool, compact);
237
238 ASSERT_TRUE(past_intervals.empty());
239 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary,
240 new_primary,
241 old_acting,
242 new_acting,
243 old_up_primary,
244 new_up_primary,
245 old_up,
246 new_up,
247 same_interval_since,
248 last_epoch_clean,
249 osdmap,
250 lastmap,
251 pgid,
252 recoverable.get(),
253 &past_intervals));
254 }
255
256 //
257 // The up primary has changed
258 //
259 {
260 vector<int> new_up;
261 int _new_up_primary = osd_id + 1;
262
263 PastIntervals past_intervals; past_intervals.update_type(ec_pool, compact);
264
265 ASSERT_TRUE(past_intervals.empty());
266 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary,
267 new_primary,
268 old_acting,
269 new_acting,
270 old_up_primary,
271 _new_up_primary,
272 old_up,
273 new_up,
274 same_interval_since,
275 last_epoch_clean,
276 osdmap,
277 lastmap,
278 pgid,
279 recoverable.get(),
280 &past_intervals));
281 }
282
283 //
284 // PG is splitting
285 //
286 {
287 ceph::shared_ptr<OSDMap> osdmap(new OSDMap());
288 osdmap->set_max_osd(10);
289 osdmap->set_state(osd_id, CEPH_OSD_EXISTS);
290 osdmap->set_epoch(epoch);
291 int new_pg_num = pg_num ^ 2;
292 OSDMap::Incremental inc(epoch + 1);
293 inc.new_pools[pool_id].min_size = min_size;
294 inc.new_pools[pool_id].set_pg_num(new_pg_num);
295 osdmap->apply_incremental(inc);
296
297 PastIntervals past_intervals; past_intervals.update_type(ec_pool, compact);
298
299 ASSERT_TRUE(past_intervals.empty());
300 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary,
301 new_primary,
302 old_acting,
303 new_acting,
304 old_up_primary,
305 new_up_primary,
306 old_up,
307 new_up,
308 same_interval_since,
309 last_epoch_clean,
310 osdmap,
311 lastmap,
312 pgid,
313 recoverable.get(),
314 &past_intervals));
315 }
316
317 //
318 // PG size has changed
319 //
320 {
321 ceph::shared_ptr<OSDMap> osdmap(new OSDMap());
322 osdmap->set_max_osd(10);
323 osdmap->set_state(osd_id, CEPH_OSD_EXISTS);
324 osdmap->set_epoch(epoch);
325 OSDMap::Incremental inc(epoch + 1);
326 __u8 new_min_size = min_size + 1;
327 inc.new_pools[pool_id].min_size = new_min_size;
328 inc.new_pools[pool_id].set_pg_num(pg_num);
329 osdmap->apply_incremental(inc);
330
331 PastIntervals past_intervals; past_intervals.update_type(ec_pool, compact);
332
333 ASSERT_TRUE(past_intervals.empty());
334 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary,
335 new_primary,
336 old_acting,
337 new_acting,
338 old_up_primary,
339 new_up_primary,
340 old_up,
341 new_up,
342 same_interval_since,
343 last_epoch_clean,
344 osdmap,
345 lastmap,
346 pgid,
347 recoverable.get(),
348 &past_intervals));
349 }
350
351 //
352 // The old acting set was empty : the previous interval could not
353 // have been rw
354 //
355 {
356 vector<int> old_acting;
357
358 PastIntervals past_intervals; past_intervals.update_type(ec_pool, compact);
359
360 ostringstream out;
361
362 ASSERT_TRUE(past_intervals.empty());
363 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary,
364 new_primary,
365 old_acting,
366 new_acting,
367 old_up_primary,
368 new_up_primary,
369 old_up,
370 new_up,
371 same_interval_since,
372 last_epoch_clean,
373 osdmap,
374 lastmap,
375 pgid,
376 recoverable.get(),
377 &past_intervals,
378 &out));
379 ASSERT_NE(string::npos, out.str().find("acting set is too small"));
380 }
381
382 //
383 // The old acting set did not have enough osd : it could
384 // not have been rw
385 //
386 {
387 vector<int> old_acting;
388 old_acting.push_back(osd_id);
389
390 //
391 // see http://tracker.ceph.com/issues/5780
392 // the size of the old acting set should be compared
393 // with the min_size of the old osdmap
394 //
395 // The new osdmap is created so that it triggers the
396 // bug.
397 //
398 ceph::shared_ptr<OSDMap> osdmap(new OSDMap());
399 osdmap->set_max_osd(10);
400 osdmap->set_state(osd_id, CEPH_OSD_EXISTS);
401 osdmap->set_epoch(epoch);
402 OSDMap::Incremental inc(epoch + 1);
403 __u8 new_min_size = old_acting.size();
404 inc.new_pools[pool_id].min_size = new_min_size;
405 inc.new_pools[pool_id].set_pg_num(pg_num);
406 osdmap->apply_incremental(inc);
407
408 ostringstream out;
409
410 PastIntervals past_intervals; past_intervals.update_type(ec_pool, compact);
411
412 ASSERT_TRUE(past_intervals.empty());
413 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary,
414 new_primary,
415 old_acting,
416 new_acting,
417 old_up_primary,
418 new_up_primary,
419 old_up,
420 new_up,
421 same_interval_since,
422 last_epoch_clean,
423 osdmap,
424 lastmap,
425 pgid,
426 recoverable.get(),
427 &past_intervals,
428 &out));
429 ASSERT_NE(string::npos, out.str().find("acting set is too small"));
430 }
431
432 //
433 // The acting set changes. The old acting set primary was up during the
434 // previous interval and may have been rw.
435 //
436 {
437 vector<int> new_acting;
438 new_acting.push_back(osd_id + 4);
439 new_acting.push_back(osd_id + 5);
440
441 ostringstream out;
442
443 PastIntervals past_intervals; past_intervals.update_type(ec_pool, compact);
444
445 ASSERT_TRUE(past_intervals.empty());
446 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary,
447 new_primary,
448 old_acting,
449 new_acting,
450 old_up_primary,
451 new_up_primary,
452 old_up,
453 new_up,
454 same_interval_since,
455 last_epoch_clean,
456 osdmap,
457 lastmap,
458 pgid,
459 recoverable.get(),
460 &past_intervals,
461 &out));
462 ASSERT_NE(string::npos, out.str().find("includes interval"));
463 }
464 //
465 // The acting set changes. The old acting set primary was not up
466 // during the old interval but last_epoch_clean is in the
467 // old interval and it may have been rw.
468 //
469 {
470 vector<int> new_acting;
471 new_acting.push_back(osd_id + 4);
472 new_acting.push_back(osd_id + 5);
473
474 ceph::shared_ptr<OSDMap> lastmap(new OSDMap());
475 lastmap->set_max_osd(10);
476 lastmap->set_state(osd_id, CEPH_OSD_EXISTS);
477 lastmap->set_epoch(epoch);
478 OSDMap::Incremental inc(epoch + 1);
479 inc.new_pools[pool_id].min_size = min_size;
480 inc.new_pools[pool_id].set_pg_num(pg_num);
481 inc.new_up_thru[osd_id] = epoch - 10;
482 lastmap->apply_incremental(inc);
483
484 ostringstream out;
485
486 PastIntervals past_intervals; past_intervals.update_type(ec_pool, compact);
487
488 ASSERT_TRUE(past_intervals.empty());
489 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary,
490 new_primary,
491 old_acting,
492 new_acting,
493 old_up_primary,
494 new_up_primary,
495 old_up,
496 new_up,
497 same_interval_since,
498 last_epoch_clean,
499 osdmap,
500 lastmap,
501 pgid,
502 recoverable.get(),
503 &past_intervals,
504 &out));
505 ASSERT_NE(string::npos, out.str().find("presumed to have been rw"));
506 }
507
508 //
509 // The acting set changes. The old acting set primary was not up
510 // during the old interval and last_epoch_clean is before the
511 // old interval : the previous interval could not possibly have
512 // been rw.
513 //
514 {
515 vector<int> new_acting;
516 new_acting.push_back(osd_id + 4);
517 new_acting.push_back(osd_id + 5);
518
519 epoch_t last_epoch_clean = epoch - 10;
520
521 ceph::shared_ptr<OSDMap> lastmap(new OSDMap());
522 lastmap->set_max_osd(10);
523 lastmap->set_state(osd_id, CEPH_OSD_EXISTS);
524 lastmap->set_epoch(epoch);
525 OSDMap::Incremental inc(epoch + 1);
526 inc.new_pools[pool_id].min_size = min_size;
527 inc.new_pools[pool_id].set_pg_num(pg_num);
528 inc.new_up_thru[osd_id] = last_epoch_clean;
529 lastmap->apply_incremental(inc);
530
531 ostringstream out;
532
533 PastIntervals past_intervals; past_intervals.update_type(ec_pool, compact);
534
535 ASSERT_TRUE(past_intervals.empty());
536 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary,
537 new_primary,
538 old_acting,
539 new_acting,
540 old_up_primary,
541 new_up_primary,
542 old_up,
543 new_up,
544 same_interval_since,
545 last_epoch_clean,
546 osdmap,
547 lastmap,
548 pgid,
549 recoverable.get(),
550 &past_intervals,
551 &out));
552 ASSERT_NE(string::npos, out.str().find("does not include interval"));
553 }
554 } // end for, didn't want to reindent
555 }
556
557 TEST(pg_t, get_ancestor)
558 {
559 ASSERT_EQ(pg_t(0, 0, -1), pg_t(16, 0, -1).get_ancestor(16));
560 ASSERT_EQ(pg_t(1, 0, -1), pg_t(17, 0, -1).get_ancestor(16));
561 ASSERT_EQ(pg_t(0, 0, -1), pg_t(16, 0, -1).get_ancestor(8));
562 ASSERT_EQ(pg_t(16, 0, -1), pg_t(16, 0, -1).get_ancestor(80));
563 ASSERT_EQ(pg_t(16, 0, -1), pg_t(16, 0, -1).get_ancestor(83));
564 ASSERT_EQ(pg_t(1, 0, -1), pg_t(1321, 0, -1).get_ancestor(123).get_ancestor(8));
565 ASSERT_EQ(pg_t(3, 0, -1), pg_t(1323, 0, -1).get_ancestor(123).get_ancestor(8));
566 ASSERT_EQ(pg_t(3, 0, -1), pg_t(1323, 0, -1).get_ancestor(8));
567 }
568
569 TEST(pg_t, split)
570 {
571 pg_t pgid(0, 0, -1);
572 set<pg_t> s;
573 bool b;
574
575 s.clear();
576 b = pgid.is_split(1, 1, &s);
577 ASSERT_TRUE(!b);
578
579 s.clear();
580 b = pgid.is_split(2, 4, NULL);
581 ASSERT_TRUE(b);
582 b = pgid.is_split(2, 4, &s);
583 ASSERT_TRUE(b);
584 ASSERT_EQ(1u, s.size());
585 ASSERT_TRUE(s.count(pg_t(2, 0, -1)));
586
587 s.clear();
588 b = pgid.is_split(2, 8, &s);
589 ASSERT_TRUE(b);
590 ASSERT_EQ(3u, s.size());
591 ASSERT_TRUE(s.count(pg_t(2, 0, -1)));
592 ASSERT_TRUE(s.count(pg_t(4, 0, -1)));
593 ASSERT_TRUE(s.count(pg_t(6, 0, -1)));
594
595 s.clear();
596 b = pgid.is_split(3, 8, &s);
597 ASSERT_TRUE(b);
598 ASSERT_EQ(1u, s.size());
599 ASSERT_TRUE(s.count(pg_t(4, 0, -1)));
600
601 s.clear();
602 b = pgid.is_split(6, 8, NULL);
603 ASSERT_TRUE(!b);
604 b = pgid.is_split(6, 8, &s);
605 ASSERT_TRUE(!b);
606 ASSERT_EQ(0u, s.size());
607
608 pgid = pg_t(1, 0, -1);
609
610 s.clear();
611 b = pgid.is_split(2, 4, &s);
612 ASSERT_TRUE(b);
613 ASSERT_EQ(1u, s.size());
614 ASSERT_TRUE(s.count(pg_t(3, 0, -1)));
615
616 s.clear();
617 b = pgid.is_split(2, 6, &s);
618 ASSERT_TRUE(b);
619 ASSERT_EQ(2u, s.size());
620 ASSERT_TRUE(s.count(pg_t(3, 0, -1)));
621 ASSERT_TRUE(s.count(pg_t(5, 0, -1)));
622
623 s.clear();
624 b = pgid.is_split(2, 8, &s);
625 ASSERT_TRUE(b);
626 ASSERT_EQ(3u, s.size());
627 ASSERT_TRUE(s.count(pg_t(3, 0, -1)));
628 ASSERT_TRUE(s.count(pg_t(5, 0, -1)));
629 ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
630
631 s.clear();
632 b = pgid.is_split(4, 8, &s);
633 ASSERT_TRUE(b);
634 ASSERT_EQ(1u, s.size());
635 ASSERT_TRUE(s.count(pg_t(5, 0, -1)));
636
637 s.clear();
638 b = pgid.is_split(3, 8, &s);
639 ASSERT_TRUE(b);
640 ASSERT_EQ(3u, s.size());
641 ASSERT_TRUE(s.count(pg_t(3, 0, -1)));
642 ASSERT_TRUE(s.count(pg_t(5, 0, -1)));
643 ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
644
645 s.clear();
646 b = pgid.is_split(6, 8, &s);
647 ASSERT_TRUE(!b);
648 ASSERT_EQ(0u, s.size());
649
650 pgid = pg_t(3, 0, -1);
651
652 s.clear();
653 b = pgid.is_split(7, 8, &s);
654 ASSERT_TRUE(b);
655 ASSERT_EQ(1u, s.size());
656 ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
657
658 s.clear();
659 b = pgid.is_split(7, 12, &s);
660 ASSERT_TRUE(b);
661 ASSERT_EQ(2u, s.size());
662 ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
663 ASSERT_TRUE(s.count(pg_t(11, 0, -1)));
664
665 s.clear();
666 b = pgid.is_split(7, 11, &s);
667 ASSERT_TRUE(b);
668 ASSERT_EQ(1u, s.size());
669 ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
670
671 }
672
673 TEST(pg_missing_t, constructor)
674 {
675 pg_missing_t missing;
676 EXPECT_EQ((unsigned int)0, missing.num_missing());
677 EXPECT_FALSE(missing.have_missing());
678 }
679
680 TEST(pg_missing_t, have_missing)
681 {
682 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
683 pg_missing_t missing;
684 EXPECT_FALSE(missing.have_missing());
685 missing.add(oid, eversion_t(), eversion_t());
686 EXPECT_TRUE(missing.have_missing());
687 }
688
689 TEST(pg_missing_t, claim)
690 {
691 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
692 pg_missing_t missing;
693 EXPECT_FALSE(missing.have_missing());
694 missing.add(oid, eversion_t(), eversion_t());
695 EXPECT_TRUE(missing.have_missing());
696
697 pg_missing_t other;
698 EXPECT_FALSE(other.have_missing());
699
700 other.claim(missing);
701 EXPECT_TRUE(other.have_missing());
702 }
703
704 TEST(pg_missing_t, is_missing)
705 {
706 // pg_missing_t::is_missing(const hobject_t& oid) const
707 {
708 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
709 pg_missing_t missing;
710 EXPECT_FALSE(missing.is_missing(oid));
711 missing.add(oid, eversion_t(), eversion_t());
712 EXPECT_TRUE(missing.is_missing(oid));
713 }
714
715 // bool pg_missing_t::is_missing(const hobject_t& oid, eversion_t v) const
716 {
717 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
718 pg_missing_t missing;
719 eversion_t need(10,5);
720 EXPECT_FALSE(missing.is_missing(oid, eversion_t()));
721 missing.add(oid, need, eversion_t());
722 EXPECT_TRUE(missing.is_missing(oid));
723 EXPECT_FALSE(missing.is_missing(oid, eversion_t()));
724 EXPECT_TRUE(missing.is_missing(oid, need));
725 }
726 }
727
728 TEST(pg_missing_t, have_old)
729 {
730 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
731 pg_missing_t missing;
732 EXPECT_EQ(eversion_t(), missing.have_old(oid));
733 missing.add(oid, eversion_t(), eversion_t());
734 EXPECT_EQ(eversion_t(), missing.have_old(oid));
735 eversion_t have(1,1);
736 missing.revise_have(oid, have);
737 EXPECT_EQ(have, missing.have_old(oid));
738 }
739
740 TEST(pg_missing_t, add_next_event)
741 {
742 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
743 hobject_t oid_other(object_t("other"), "key", 9123, 9456, 0, "");
744 eversion_t version(10,5);
745 eversion_t prior_version(3,4);
746 pg_log_entry_t sample_e(pg_log_entry_t::DELETE, oid, version, prior_version,
747 0, osd_reqid_t(entity_name_t::CLIENT(777), 8, 999),
748 utime_t(8,9), 0);
749
750 // new object (MODIFY)
751 {
752 pg_missing_t missing;
753 pg_log_entry_t e = sample_e;
754
755 e.op = pg_log_entry_t::MODIFY;
756 e.prior_version = eversion_t();
757 EXPECT_TRUE(e.is_update());
758 EXPECT_TRUE(e.object_is_indexed());
759 EXPECT_TRUE(e.reqid_is_indexed());
760 EXPECT_FALSE(missing.is_missing(oid));
761 missing.add_next_event(e);
762 EXPECT_TRUE(missing.is_missing(oid));
763 EXPECT_EQ(eversion_t(), missing.get_items().at(oid).have);
764 EXPECT_EQ(oid, missing.get_rmissing().at(e.version.version));
765 EXPECT_EQ(1U, missing.num_missing());
766 EXPECT_EQ(1U, missing.get_rmissing().size());
767
768 // adding the same object replaces the previous one
769 missing.add_next_event(e);
770 EXPECT_TRUE(missing.is_missing(oid));
771 EXPECT_EQ(1U, missing.num_missing());
772 EXPECT_EQ(1U, missing.get_rmissing().size());
773 }
774
775 // new object (CLONE)
776 {
777 pg_missing_t missing;
778 pg_log_entry_t e = sample_e;
779
780 e.op = pg_log_entry_t::CLONE;
781 e.prior_version = eversion_t();
782 EXPECT_TRUE(e.is_clone());
783 EXPECT_TRUE(e.object_is_indexed());
784 EXPECT_FALSE(e.reqid_is_indexed());
785 EXPECT_FALSE(missing.is_missing(oid));
786 missing.add_next_event(e);
787 EXPECT_TRUE(missing.is_missing(oid));
788 EXPECT_EQ(eversion_t(), missing.get_items().at(oid).have);
789 EXPECT_EQ(oid, missing.get_rmissing().at(e.version.version));
790 EXPECT_EQ(1U, missing.num_missing());
791 EXPECT_EQ(1U, missing.get_rmissing().size());
792
793 // adding the same object replaces the previous one
794 missing.add_next_event(e);
795 EXPECT_TRUE(missing.is_missing(oid));
796 EXPECT_EQ(1U, missing.num_missing());
797 EXPECT_EQ(1U, missing.get_rmissing().size());
798 }
799
800 // existing object (MODIFY)
801 {
802 pg_missing_t missing;
803 pg_log_entry_t e = sample_e;
804
805 e.op = pg_log_entry_t::MODIFY;
806 e.prior_version = eversion_t();
807 EXPECT_TRUE(e.is_update());
808 EXPECT_TRUE(e.object_is_indexed());
809 EXPECT_TRUE(e.reqid_is_indexed());
810 EXPECT_FALSE(missing.is_missing(oid));
811 missing.add_next_event(e);
812 EXPECT_TRUE(missing.is_missing(oid));
813 EXPECT_EQ(eversion_t(), missing.get_items().at(oid).have);
814 EXPECT_EQ(oid, missing.get_rmissing().at(e.version.version));
815 EXPECT_EQ(1U, missing.num_missing());
816 EXPECT_EQ(1U, missing.get_rmissing().size());
817
818 // adding the same object with a different version
819 e.prior_version = prior_version;
820 missing.add_next_event(e);
821 EXPECT_EQ(eversion_t(), missing.get_items().at(oid).have);
822 EXPECT_TRUE(missing.is_missing(oid));
823 EXPECT_EQ(1U, missing.num_missing());
824 EXPECT_EQ(1U, missing.get_rmissing().size());
825 }
826
827 // object with prior version (MODIFY)
828 {
829 pg_missing_t missing;
830 pg_log_entry_t e = sample_e;
831
832 e.op = pg_log_entry_t::MODIFY;
833 EXPECT_TRUE(e.is_update());
834 EXPECT_TRUE(e.object_is_indexed());
835 EXPECT_TRUE(e.reqid_is_indexed());
836 EXPECT_FALSE(missing.is_missing(oid));
837 missing.add_next_event(e);
838 EXPECT_TRUE(missing.is_missing(oid));
839 EXPECT_EQ(prior_version, missing.get_items().at(oid).have);
840 EXPECT_EQ(version, missing.get_items().at(oid).need);
841 EXPECT_EQ(oid, missing.get_rmissing().at(e.version.version));
842 EXPECT_EQ(1U, missing.num_missing());
843 EXPECT_EQ(1U, missing.get_rmissing().size());
844 }
845
846 // obsolete (BACKLOG)
847 {
848 pg_missing_t missing;
849 pg_log_entry_t e = sample_e;
850
851 e.op = pg_log_entry_t::BACKLOG;
852 EXPECT_TRUE(e.is_backlog());
853 EXPECT_TRUE(e.object_is_indexed());
854 EXPECT_FALSE(e.reqid_is_indexed());
855 EXPECT_FALSE(missing.is_missing(oid));
856 PrCtl unset_dumpable;
857 EXPECT_DEATH(missing.add_next_event(e), "");
858 }
859
860 // adding a DELETE matching an existing event
861 {
862 pg_missing_t missing;
863 pg_log_entry_t e = sample_e;
864
865 e.op = pg_log_entry_t::MODIFY;
866 EXPECT_TRUE(e.is_update());
867 EXPECT_TRUE(e.object_is_indexed());
868 EXPECT_TRUE(e.reqid_is_indexed());
869 EXPECT_FALSE(missing.is_missing(oid));
870 missing.add_next_event(e);
871 EXPECT_TRUE(missing.is_missing(oid));
872
873 e.op = pg_log_entry_t::DELETE;
874 EXPECT_TRUE(e.is_delete());
875 missing.add_next_event(e);
876 EXPECT_FALSE(missing.have_missing());
877 }
878
879 // ERROR op should only be used for dup detection
880 {
881 pg_missing_t missing;
882 pg_log_entry_t e = sample_e;
883
884 e.op = pg_log_entry_t::ERROR;
885 e.return_code = -ENOENT;
886 EXPECT_FALSE(e.is_update());
887 EXPECT_FALSE(e.object_is_indexed());
888 EXPECT_TRUE(e.reqid_is_indexed());
889 EXPECT_FALSE(missing.is_missing(oid));
890 missing.add_next_event(e);
891 EXPECT_FALSE(missing.is_missing(oid));
892 EXPECT_FALSE(e.object_is_indexed());
893 EXPECT_TRUE(e.reqid_is_indexed());
894 }
895
896 // ERROR op should not affect previous entries
897 {
898 pg_missing_t missing;
899 pg_log_entry_t modify = sample_e;
900
901 modify.op = pg_log_entry_t::MODIFY;
902 EXPECT_FALSE(missing.is_missing(oid));
903 missing.add_next_event(modify);
904 EXPECT_TRUE(missing.is_missing(oid));
905 EXPECT_EQ(missing.get_items().at(oid).need, version);
906
907 pg_log_entry_t error = sample_e;
908 error.op = pg_log_entry_t::ERROR;
909 error.return_code = -ENOENT;
910 error.version = eversion_t(11, 5);
911 missing.add_next_event(error);
912 EXPECT_TRUE(missing.is_missing(oid));
913 EXPECT_EQ(missing.get_items().at(oid).need, version);
914 }
915 }
916
917 TEST(pg_missing_t, revise_need)
918 {
919 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
920 pg_missing_t missing;
921 // create a new entry
922 EXPECT_FALSE(missing.is_missing(oid));
923 eversion_t need(10,10);
924 missing.revise_need(oid, need);
925 EXPECT_TRUE(missing.is_missing(oid));
926 EXPECT_EQ(eversion_t(), missing.get_items().at(oid).have);
927 EXPECT_EQ(need, missing.get_items().at(oid).need);
928 // update an existing entry and preserve have
929 eversion_t have(1,1);
930 missing.revise_have(oid, have);
931 eversion_t new_need(10,12);
932 EXPECT_EQ(have, missing.get_items().at(oid).have);
933 missing.revise_need(oid, new_need);
934 EXPECT_EQ(have, missing.get_items().at(oid).have);
935 EXPECT_EQ(new_need, missing.get_items().at(oid).need);
936 }
937
938 TEST(pg_missing_t, revise_have)
939 {
940 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
941 pg_missing_t missing;
942 // a non existing entry means noop
943 EXPECT_FALSE(missing.is_missing(oid));
944 eversion_t have(1,1);
945 missing.revise_have(oid, have);
946 EXPECT_FALSE(missing.is_missing(oid));
947 // update an existing entry
948 eversion_t need(10,12);
949 missing.add(oid, need, have);
950 EXPECT_TRUE(missing.is_missing(oid));
951 eversion_t new_have(2,2);
952 EXPECT_EQ(have, missing.get_items().at(oid).have);
953 missing.revise_have(oid, new_have);
954 EXPECT_EQ(new_have, missing.get_items().at(oid).have);
955 EXPECT_EQ(need, missing.get_items().at(oid).need);
956 }
957
958 TEST(pg_missing_t, add)
959 {
960 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
961 pg_missing_t missing;
962 EXPECT_FALSE(missing.is_missing(oid));
963 eversion_t have(1,1);
964 eversion_t need(10,10);
965 missing.add(oid, need, have);
966 EXPECT_TRUE(missing.is_missing(oid));
967 EXPECT_EQ(have, missing.get_items().at(oid).have);
968 EXPECT_EQ(need, missing.get_items().at(oid).need);
969 }
970
971 TEST(pg_missing_t, rm)
972 {
973 // void pg_missing_t::rm(const hobject_t& oid, eversion_t v)
974 {
975 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
976 pg_missing_t missing;
977 EXPECT_FALSE(missing.is_missing(oid));
978 epoch_t epoch = 10;
979 eversion_t need(epoch,10);
980 missing.add(oid, need, eversion_t());
981 EXPECT_TRUE(missing.is_missing(oid));
982 // rm of an older version is a noop
983 missing.rm(oid, eversion_t(epoch / 2,20));
984 EXPECT_TRUE(missing.is_missing(oid));
985 // rm of a later version removes the object
986 missing.rm(oid, eversion_t(epoch * 2,20));
987 EXPECT_FALSE(missing.is_missing(oid));
988 }
989 // void pg_missing_t::rm(const std::map<hobject_t, pg_missing_item>::iterator &m)
990 {
991 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
992 pg_missing_t missing;
993 EXPECT_FALSE(missing.is_missing(oid));
994 missing.add(oid, eversion_t(), eversion_t());
995 EXPECT_TRUE(missing.is_missing(oid));
996 auto m = missing.get_items().find(oid);
997 missing.rm(m);
998 EXPECT_FALSE(missing.is_missing(oid));
999 }
1000 }
1001
1002 TEST(pg_missing_t, got)
1003 {
1004 // void pg_missing_t::got(const hobject_t& oid, eversion_t v)
1005 {
1006 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
1007 pg_missing_t missing;
1008 // assert if the oid does not exist
1009 {
1010 PrCtl unset_dumpable;
1011 EXPECT_DEATH(missing.got(oid, eversion_t()), "");
1012 }
1013 EXPECT_FALSE(missing.is_missing(oid));
1014 epoch_t epoch = 10;
1015 eversion_t need(epoch,10);
1016 missing.add(oid, need, eversion_t());
1017 EXPECT_TRUE(missing.is_missing(oid));
1018 // assert if that the version to be removed is lower than the version of the object
1019 {
1020 PrCtl unset_dumpable;
1021 EXPECT_DEATH(missing.got(oid, eversion_t(epoch / 2,20)), "");
1022 }
1023 // remove of a later version removes the object
1024 missing.got(oid, eversion_t(epoch * 2,20));
1025 EXPECT_FALSE(missing.is_missing(oid));
1026 }
1027 // void pg_missing_t::got(const std::map<hobject_t, pg_missing_item>::iterator &m)
1028 {
1029 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
1030 pg_missing_t missing;
1031 EXPECT_FALSE(missing.is_missing(oid));
1032 missing.add(oid, eversion_t(), eversion_t());
1033 EXPECT_TRUE(missing.is_missing(oid));
1034 auto m = missing.get_items().find(oid);
1035 missing.got(m);
1036 EXPECT_FALSE(missing.is_missing(oid));
1037 }
1038 }
1039
1040 TEST(pg_missing_t, split_into)
1041 {
1042 uint32_t hash1 = 1;
1043 hobject_t oid1(object_t("objname"), "key1", 123, hash1, 0, "");
1044 uint32_t hash2 = 2;
1045 hobject_t oid2(object_t("objname"), "key2", 123, hash2, 0, "");
1046 pg_missing_t missing;
1047 missing.add(oid1, eversion_t(), eversion_t());
1048 missing.add(oid2, eversion_t(), eversion_t());
1049 pg_t child_pgid;
1050 child_pgid.m_seed = 1;
1051 pg_missing_t child;
1052 unsigned split_bits = 1;
1053 missing.split_into(child_pgid, split_bits, &child);
1054 EXPECT_TRUE(child.is_missing(oid1));
1055 EXPECT_FALSE(child.is_missing(oid2));
1056 EXPECT_FALSE(missing.is_missing(oid1));
1057 EXPECT_TRUE(missing.is_missing(oid2));
1058 }
1059
1060 class ObjectContextTest : public ::testing::Test {
1061 protected:
1062
1063 static const useconds_t DELAY_MAX = 20 * 1000 * 1000;
1064
1065 class Thread_read_lock : public Thread {
1066 public:
1067 ObjectContext &obc;
1068
1069 explicit Thread_read_lock(ObjectContext& _obc) :
1070 obc(_obc)
1071 {
1072 }
1073
1074 void *entry() override {
1075 obc.ondisk_read_lock();
1076 return NULL;
1077 }
1078 };
1079
1080 class Thread_write_lock : public Thread {
1081 public:
1082 ObjectContext &obc;
1083
1084 explicit Thread_write_lock(ObjectContext& _obc) :
1085 obc(_obc)
1086 {
1087 }
1088
1089 void *entry() override {
1090 obc.ondisk_write_lock();
1091 return NULL;
1092 }
1093 };
1094
1095 };
1096
1097 TEST_F(ObjectContextTest, read_write_lock)
1098 {
1099 {
1100 ObjectContext obc;
1101
1102 //
1103 // write_lock
1104 // write_lock
1105 // write_unlock
1106 // write_unlock
1107 //
1108 EXPECT_EQ(0, obc.writers_waiting);
1109 EXPECT_EQ(0, obc.unstable_writes);
1110
1111 obc.ondisk_write_lock();
1112
1113 EXPECT_EQ(0, obc.writers_waiting);
1114 EXPECT_EQ(1, obc.unstable_writes);
1115
1116 obc.ondisk_write_lock();
1117
1118 EXPECT_EQ(0, obc.writers_waiting);
1119 EXPECT_EQ(2, obc.unstable_writes);
1120
1121 obc.ondisk_write_unlock();
1122
1123 EXPECT_EQ(0, obc.writers_waiting);
1124 EXPECT_EQ(1, obc.unstable_writes);
1125
1126 obc.ondisk_write_unlock();
1127
1128 EXPECT_EQ(0, obc.writers_waiting);
1129 EXPECT_EQ(0, obc.unstable_writes);
1130 }
1131
1132 useconds_t delay = 0;
1133
1134 {
1135 ObjectContext obc;
1136
1137 //
1138 // write_lock
1139 // read_lock => wait
1140 // write_unlock => signal
1141 // read_unlock
1142 //
1143 EXPECT_EQ(0, obc.readers_waiting);
1144 EXPECT_EQ(0, obc.readers);
1145 EXPECT_EQ(0, obc.writers_waiting);
1146 EXPECT_EQ(0, obc.unstable_writes);
1147
1148 obc.ondisk_write_lock();
1149
1150 EXPECT_EQ(0, obc.readers_waiting);
1151 EXPECT_EQ(0, obc.readers);
1152 EXPECT_EQ(0, obc.writers_waiting);
1153 EXPECT_EQ(1, obc.unstable_writes);
1154
1155 Thread_read_lock t(obc);
1156 t.create("obc_read");
1157
1158 do {
1159 cout << "Trying (1) with delay " << delay << "us\n";
1160 usleep(delay);
1161 } while (obc.readers_waiting == 0 &&
1162 ( delay = delay * 2 + 1) < DELAY_MAX);
1163
1164 EXPECT_EQ(1, obc.readers_waiting);
1165 EXPECT_EQ(0, obc.readers);
1166 EXPECT_EQ(0, obc.writers_waiting);
1167 EXPECT_EQ(1, obc.unstable_writes);
1168
1169 obc.ondisk_write_unlock();
1170
1171 do {
1172 cout << "Trying (2) with delay " << delay << "us\n";
1173 usleep(delay);
1174 } while ((obc.readers == 0 || obc.readers_waiting == 1) &&
1175 ( delay = delay * 2 + 1) < DELAY_MAX);
1176 EXPECT_EQ(0, obc.readers_waiting);
1177 EXPECT_EQ(1, obc.readers);
1178 EXPECT_EQ(0, obc.writers_waiting);
1179 EXPECT_EQ(0, obc.unstable_writes);
1180
1181 obc.ondisk_read_unlock();
1182
1183 EXPECT_EQ(0, obc.readers_waiting);
1184 EXPECT_EQ(0, obc.readers);
1185 EXPECT_EQ(0, obc.writers_waiting);
1186 EXPECT_EQ(0, obc.unstable_writes);
1187
1188 t.join();
1189 }
1190
1191 {
1192 ObjectContext obc;
1193
1194 //
1195 // read_lock
1196 // write_lock => wait
1197 // read_unlock => signal
1198 // write_unlock
1199 //
1200 EXPECT_EQ(0, obc.readers_waiting);
1201 EXPECT_EQ(0, obc.readers);
1202 EXPECT_EQ(0, obc.writers_waiting);
1203 EXPECT_EQ(0, obc.unstable_writes);
1204
1205 obc.ondisk_read_lock();
1206
1207 EXPECT_EQ(0, obc.readers_waiting);
1208 EXPECT_EQ(1, obc.readers);
1209 EXPECT_EQ(0, obc.writers_waiting);
1210 EXPECT_EQ(0, obc.unstable_writes);
1211
1212 Thread_write_lock t(obc);
1213 t.create("obc_write");
1214
1215 do {
1216 cout << "Trying (3) with delay " << delay << "us\n";
1217 usleep(delay);
1218 } while ((obc.writers_waiting == 0) &&
1219 ( delay = delay * 2 + 1) < DELAY_MAX);
1220
1221 EXPECT_EQ(0, obc.readers_waiting);
1222 EXPECT_EQ(1, obc.readers);
1223 EXPECT_EQ(1, obc.writers_waiting);
1224 EXPECT_EQ(0, obc.unstable_writes);
1225
1226 obc.ondisk_read_unlock();
1227
1228 do {
1229 cout << "Trying (4) with delay " << delay << "us\n";
1230 usleep(delay);
1231 } while ((obc.unstable_writes == 0 || obc.writers_waiting == 1) &&
1232 ( delay = delay * 2 + 1) < DELAY_MAX);
1233
1234 EXPECT_EQ(0, obc.readers_waiting);
1235 EXPECT_EQ(0, obc.readers);
1236 EXPECT_EQ(0, obc.writers_waiting);
1237 EXPECT_EQ(1, obc.unstable_writes);
1238
1239 obc.ondisk_write_unlock();
1240
1241 EXPECT_EQ(0, obc.readers_waiting);
1242 EXPECT_EQ(0, obc.readers);
1243 EXPECT_EQ(0, obc.writers_waiting);
1244 EXPECT_EQ(0, obc.unstable_writes);
1245
1246 t.join();
1247 }
1248
1249 }
1250
1251 TEST(pg_pool_t_test, get_pg_num_divisor) {
1252 pg_pool_t p;
1253 p.set_pg_num(16);
1254 p.set_pgp_num(16);
1255
1256 for (int i = 0; i < 16; ++i)
1257 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(i, 1)));
1258
1259 p.set_pg_num(12);
1260 p.set_pgp_num(12);
1261 //cout << "num " << p.get_pg_num()
1262 // << " mask " << p.get_pg_num_mask() << std::endl;
1263 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(0, 1)));
1264 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(1, 1)));
1265 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(2, 1)));
1266 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(3, 1)));
1267 ASSERT_EQ(8u, p.get_pg_num_divisor(pg_t(4, 1)));
1268 ASSERT_EQ(8u, p.get_pg_num_divisor(pg_t(5, 1)));
1269 ASSERT_EQ(8u, p.get_pg_num_divisor(pg_t(6, 1)));
1270 ASSERT_EQ(8u, p.get_pg_num_divisor(pg_t(7, 1)));
1271 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(8, 1)));
1272 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(9, 1)));
1273 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(10, 1)));
1274 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(11, 1)));
1275 }
1276
1277 TEST(pg_pool_t_test, get_random_pg_position) {
1278 srand(getpid());
1279 for (int i = 0; i < 100; ++i) {
1280 pg_pool_t p;
1281 p.set_pg_num(1 + (rand() % 1000));
1282 p.set_pgp_num(p.get_pg_num());
1283 pg_t pgid(rand() % p.get_pg_num(), 1);
1284 uint32_t h = p.get_random_pg_position(pgid, rand());
1285 uint32_t ps = p.raw_hash_to_pg(h);
1286 cout << p.get_pg_num() << " " << pgid << ": "
1287 << h << " -> " << pg_t(ps, 1) << std::endl;
1288 ASSERT_EQ(pgid.ps(), ps);
1289 }
1290 }
1291
1292 TEST(shard_id_t, iostream) {
1293 set<shard_id_t> shards;
1294 shards.insert(shard_id_t(0));
1295 shards.insert(shard_id_t(1));
1296 shards.insert(shard_id_t(2));
1297 ostringstream out;
1298 out << shards;
1299 ASSERT_EQ(out.str(), "0,1,2");
1300
1301 shard_id_t noshard = shard_id_t::NO_SHARD;
1302 shard_id_t zero(0);
1303 ASSERT_GT(zero, noshard);
1304 }
1305
1306 TEST(spg_t, parse) {
1307 spg_t a(pg_t(1,2), shard_id_t::NO_SHARD);
1308 spg_t aa, bb;
1309 spg_t b(pg_t(3,2), shard_id_t(2));
1310 std::string s = stringify(a);
1311 ASSERT_TRUE(aa.parse(s.c_str()));
1312 ASSERT_EQ(a, aa);
1313
1314 s = stringify(b);
1315 ASSERT_TRUE(bb.parse(s.c_str()));
1316 ASSERT_EQ(b, bb);
1317 }
1318
1319 TEST(coll_t, parse) {
1320 const char *ok[] = {
1321 "meta",
1322 "1.2_head",
1323 "1.2_TEMP",
1324 "1.2s3_head",
1325 "1.3s2_TEMP",
1326 "1.2s0_head",
1327 0
1328 };
1329 const char *bad[] = {
1330 "foo",
1331 "1.2_food",
1332 "1.2_head ",
1333 //" 1.2_head", // hrm, this parses, which is not ideal.. pg_t's fault?
1334 "1.2_temp",
1335 "1.2_HEAD",
1336 "1.xS3_HEAD",
1337 "1.2s_HEAD",
1338 "1.2sfoo_HEAD",
1339 0
1340 };
1341 coll_t a;
1342 for (int i = 0; ok[i]; ++i) {
1343 cout << "check ok " << ok[i] << std::endl;
1344 ASSERT_TRUE(a.parse(ok[i]));
1345 ASSERT_EQ(string(ok[i]), a.to_str());
1346 }
1347 for (int i = 0; bad[i]; ++i) {
1348 cout << "check bad " << bad[i] << std::endl;
1349 ASSERT_FALSE(a.parse(bad[i]));
1350 }
1351 }
1352
1353 TEST(coll_t, temp) {
1354 spg_t pgid;
1355 coll_t foo(pgid);
1356 ASSERT_EQ(foo.to_str(), string("0.0_head"));
1357
1358 coll_t temp = foo.get_temp();
1359 ASSERT_EQ(temp.to_str(), string("0.0_TEMP"));
1360
1361 spg_t pgid2;
1362 ASSERT_TRUE(temp.is_temp());
1363 ASSERT_TRUE(temp.is_temp(&pgid2));
1364 ASSERT_EQ(pgid, pgid2);
1365 }
1366
1367 TEST(coll_t, assigment) {
1368 spg_t pgid;
1369 coll_t right(pgid);
1370 ASSERT_EQ(right.to_str(), string("0.0_head"));
1371
1372 coll_t left, middle;
1373
1374 ASSERT_EQ(left.to_str(), string("meta"));
1375 ASSERT_EQ(middle.to_str(), string("meta"));
1376
1377 left = middle = right;
1378
1379 ASSERT_EQ(left.to_str(), string("0.0_head"));
1380 ASSERT_EQ(middle.to_str(), string("0.0_head"));
1381
1382 ASSERT_NE(middle.c_str(), right.c_str());
1383 ASSERT_NE(left.c_str(), middle.c_str());
1384 }
1385
1386 TEST(hobject_t, parse) {
1387 const char *v[] = {
1388 "MIN",
1389 "MAX",
1390 "-1:60c2fa6d:::inc_osdmap.1:0",
1391 "-1:60c2fa6d:::inc_osdmap.1:333",
1392 "0:00000000::::head",
1393 "1:00000000:nspace:key:obj:head",
1394 "-40:00000000:nspace::obj:head",
1395 "20:00000000::key:obj:head",
1396 "20:00000000:::o%fdj:head",
1397 "20:00000000:::o%02fdj:head",
1398 "20:00000000:::_zero_%00_:head",
1399 NULL
1400 };
1401
1402 for (unsigned i=0; v[i]; ++i) {
1403 hobject_t o;
1404 bool b = o.parse(v[i]);
1405 if (!b) {
1406 cout << "failed to parse " << v[i] << std::endl;
1407 ASSERT_TRUE(false);
1408 }
1409 string s = stringify(o);
1410 if (s != v[i]) {
1411 cout << v[i] << " -> " << o << " -> " << s << std::endl;
1412 ASSERT_EQ(s, string(v[i]));
1413 }
1414 }
1415 }
1416
1417 TEST(ghobject_t, cmp) {
1418 ghobject_t min;
1419 ghobject_t sep;
1420 sep.set_shard(shard_id_t(1));
1421 sep.hobj.pool = -1;
1422 cout << min << " < " << sep << std::endl;
1423 ASSERT_TRUE(min < sep);
1424
1425 sep.set_shard(shard_id_t::NO_SHARD);
1426 cout << "sep shard " << sep.shard_id << std::endl;
1427 ghobject_t o(hobject_t(object_t(), string(), CEPH_NOSNAP, 0x42,
1428 1, string()));
1429 cout << "o " << o << std::endl;
1430 ASSERT_TRUE(o > sep);
1431 }
1432
1433 TEST(ghobject_t, parse) {
1434 const char *v[] = {
1435 "GHMIN",
1436 "GHMAX",
1437 "13#0:00000000::::head#",
1438 "13#0:00000000::::head#deadbeef",
1439 "#-1:60c2fa6d:::inc_osdmap.1:333#deadbeef",
1440 "#-1:60c2fa6d:::inc%02osdmap.1:333#deadbeef",
1441 "#-1:60c2fa6d:::inc_osdmap.1:333#",
1442 "1#MIN#deadbeefff",
1443 "1#MAX#",
1444 "#MAX#123",
1445 "#-40:00000000:nspace::obj:head#",
1446 NULL
1447 };
1448
1449 for (unsigned i=0; v[i]; ++i) {
1450 ghobject_t o;
1451 bool b = o.parse(v[i]);
1452 if (!b) {
1453 cout << "failed to parse " << v[i] << std::endl;
1454 ASSERT_TRUE(false);
1455 }
1456 string s = stringify(o);
1457 if (s != v[i]) {
1458 cout << v[i] << " -> " << o << " -> " << s << std::endl;
1459 ASSERT_EQ(s, string(v[i]));
1460 }
1461 }
1462 }
1463
1464 TEST(pool_opts_t, invalid_opt) {
1465 EXPECT_FALSE(pool_opts_t::is_opt_name("INVALID_OPT"));
1466 PrCtl unset_dumpable;
1467 EXPECT_DEATH(pool_opts_t::get_opt_desc("INVALID_OPT"), "");
1468 }
1469
1470 TEST(pool_opts_t, scrub_min_interval) {
1471 EXPECT_TRUE(pool_opts_t::is_opt_name("scrub_min_interval"));
1472 EXPECT_EQ(pool_opts_t::get_opt_desc("scrub_min_interval"),
1473 pool_opts_t::opt_desc_t(pool_opts_t::SCRUB_MIN_INTERVAL,
1474 pool_opts_t::DOUBLE));
1475
1476 pool_opts_t opts;
1477 EXPECT_FALSE(opts.is_set(pool_opts_t::SCRUB_MIN_INTERVAL));
1478 {
1479 PrCtl unset_dumpable;
1480 EXPECT_DEATH(opts.get(pool_opts_t::SCRUB_MIN_INTERVAL), "");
1481 }
1482 double val;
1483 EXPECT_FALSE(opts.get(pool_opts_t::SCRUB_MIN_INTERVAL, &val));
1484 opts.set(pool_opts_t::SCRUB_MIN_INTERVAL, static_cast<double>(2015));
1485 EXPECT_TRUE(opts.get(pool_opts_t::SCRUB_MIN_INTERVAL, &val));
1486 EXPECT_EQ(val, 2015);
1487 opts.unset(pool_opts_t::SCRUB_MIN_INTERVAL);
1488 EXPECT_FALSE(opts.is_set(pool_opts_t::SCRUB_MIN_INTERVAL));
1489 }
1490
1491 TEST(pool_opts_t, scrub_max_interval) {
1492 EXPECT_TRUE(pool_opts_t::is_opt_name("scrub_max_interval"));
1493 EXPECT_EQ(pool_opts_t::get_opt_desc("scrub_max_interval"),
1494 pool_opts_t::opt_desc_t(pool_opts_t::SCRUB_MAX_INTERVAL,
1495 pool_opts_t::DOUBLE));
1496
1497 pool_opts_t opts;
1498 EXPECT_FALSE(opts.is_set(pool_opts_t::SCRUB_MAX_INTERVAL));
1499 {
1500 PrCtl unset_dumpable;
1501 EXPECT_DEATH(opts.get(pool_opts_t::SCRUB_MAX_INTERVAL), "");
1502 }
1503 double val;
1504 EXPECT_FALSE(opts.get(pool_opts_t::SCRUB_MAX_INTERVAL, &val));
1505 opts.set(pool_opts_t::SCRUB_MAX_INTERVAL, static_cast<double>(2015));
1506 EXPECT_TRUE(opts.get(pool_opts_t::SCRUB_MAX_INTERVAL, &val));
1507 EXPECT_EQ(val, 2015);
1508 opts.unset(pool_opts_t::SCRUB_MAX_INTERVAL);
1509 EXPECT_FALSE(opts.is_set(pool_opts_t::SCRUB_MAX_INTERVAL));
1510 }
1511
1512 TEST(pool_opts_t, deep_scrub_interval) {
1513 EXPECT_TRUE(pool_opts_t::is_opt_name("deep_scrub_interval"));
1514 EXPECT_EQ(pool_opts_t::get_opt_desc("deep_scrub_interval"),
1515 pool_opts_t::opt_desc_t(pool_opts_t::DEEP_SCRUB_INTERVAL,
1516 pool_opts_t::DOUBLE));
1517
1518 pool_opts_t opts;
1519 EXPECT_FALSE(opts.is_set(pool_opts_t::DEEP_SCRUB_INTERVAL));
1520 {
1521 PrCtl unset_dumpable;
1522 EXPECT_DEATH(opts.get(pool_opts_t::DEEP_SCRUB_INTERVAL), "");
1523 }
1524 double val;
1525 EXPECT_FALSE(opts.get(pool_opts_t::DEEP_SCRUB_INTERVAL, &val));
1526 opts.set(pool_opts_t::DEEP_SCRUB_INTERVAL, static_cast<double>(2015));
1527 EXPECT_TRUE(opts.get(pool_opts_t::DEEP_SCRUB_INTERVAL, &val));
1528 EXPECT_EQ(val, 2015);
1529 opts.unset(pool_opts_t::DEEP_SCRUB_INTERVAL);
1530 EXPECT_FALSE(opts.is_set(pool_opts_t::DEEP_SCRUB_INTERVAL));
1531 }
1532
1533 struct RequiredPredicate : IsPGRecoverablePredicate {
1534 unsigned required_size;
1535 RequiredPredicate(unsigned required_size) : required_size(required_size) {}
1536 bool operator()(const set<pg_shard_t> &have) const override {
1537 return have.size() >= required_size;
1538 }
1539 };
1540
1541 using namespace std;
1542 struct MapPredicate {
1543 map<int, pair<PastIntervals::osd_state_t, epoch_t>> states;
1544 MapPredicate(
1545 vector<pair<int, pair<PastIntervals::osd_state_t, epoch_t>>> _states)
1546 : states(_states.begin(), _states.end()) {}
1547 PastIntervals::osd_state_t operator()(epoch_t start, int osd, epoch_t *lost_at) {
1548 auto val = states.at(osd);
1549 if (lost_at)
1550 *lost_at = val.second;
1551 return val.first;
1552 }
1553 };
1554
1555 using sit = shard_id_t;
1556 using PI = PastIntervals;
1557 using pst = pg_shard_t;
1558 using ival = PastIntervals::pg_interval_t;
1559 using ivallst = std::list<ival>;
1560 const int N = 0x7fffffff /* CRUSH_ITEM_NONE, can't import crush.h here */;
1561
1562 struct PITest : ::testing::Test {
1563 PITest() {}
1564 void run(
1565 bool ec_pool,
1566 ivallst intervals,
1567 epoch_t last_epoch_started,
1568 unsigned min_to_peer,
1569 vector<pair<int, pair<PastIntervals::osd_state_t, epoch_t>>> osd_states,
1570 vector<int> up,
1571 vector<int> acting,
1572 set<pg_shard_t> probe,
1573 set<int> down,
1574 map<int, epoch_t> blocked_by,
1575 bool pg_down) {
1576 RequiredPredicate rec_pred(min_to_peer);
1577 MapPredicate map_pred(osd_states);
1578
1579 PI::PriorSet correct(
1580 ec_pool,
1581 probe,
1582 down,
1583 blocked_by,
1584 pg_down,
1585 new RequiredPredicate(rec_pred));
1586
1587 PastIntervals simple, compact;
1588 simple.update_type(ec_pool, false);
1589 compact.update_type(ec_pool, true);
1590 for (auto &&i: intervals) {
1591 simple.add_interval(ec_pool, i);
1592 compact.add_interval(ec_pool, i);
1593 }
1594 PI::PriorSet simple_ps = simple.get_prior_set(
1595 ec_pool,
1596 last_epoch_started,
1597 new RequiredPredicate(rec_pred),
1598 map_pred,
1599 up,
1600 acting,
1601 nullptr);
1602 PI::PriorSet compact_ps = compact.get_prior_set(
1603 ec_pool,
1604 last_epoch_started,
1605 new RequiredPredicate(rec_pred),
1606 map_pred,
1607 up,
1608 acting,
1609 nullptr);
1610 ASSERT_EQ(correct, simple_ps);
1611 ASSERT_EQ(correct, compact_ps);
1612 }
1613 };
1614
1615 TEST_F(PITest, past_intervals_rep) {
1616 run(
1617 /* ec_pool */ false,
1618 /* intervals */
1619 { ival{{0, 1, 2}, {0, 1, 2}, 10, 20, true, 0, 0}
1620 , ival{{ 1, 2}, { 1, 2}, 21, 30, true, 1, 1}
1621 , ival{{ 2}, { 2}, 31, 35, false, 2, 2}
1622 , ival{{0, 2}, {0, 2}, 36, 50, true, 0, 0}
1623 },
1624 /* les */ 5,
1625 /* min_peer */ 1,
1626 /* osd states at end */
1627 { make_pair(0, make_pair(PI::UP , 0))
1628 , make_pair(1, make_pair(PI::UP , 0))
1629 , make_pair(2, make_pair(PI::DOWN , 0))
1630 },
1631 /* acting */ {0, 1 },
1632 /* up */ {0, 1 },
1633 /* probe */ {pst(0), pst(1)},
1634 /* down */ {2},
1635 /* blocked_by */ {},
1636 /* pg_down */ false);
1637 }
1638
1639 TEST_F(PITest, past_intervals_ec) {
1640 run(
1641 /* ec_pool */ true,
1642 /* intervals */
1643 { ival{{0, 1, 2}, {0, 1, 2}, 10, 20, true, 0, 0}
1644 , ival{{N, 1, 2}, {N, 1, 2}, 21, 30, true, 1, 1}
1645 },
1646 /* les */ 5,
1647 /* min_peer */ 2,
1648 /* osd states at end */
1649 { make_pair(0, make_pair(PI::DOWN , 0))
1650 , make_pair(1, make_pair(PI::UP , 0))
1651 , make_pair(2, make_pair(PI::UP , 0))
1652 },
1653 /* acting */ {N, 1, 2},
1654 /* up */ {N, 1, 2},
1655 /* probe */ {pst(1, sit(1)), pst(2, sit(2))},
1656 /* down */ {0},
1657 /* blocked_by */ {},
1658 /* pg_down */ false);
1659 }
1660
1661 TEST_F(PITest, past_intervals_rep_down) {
1662 run(
1663 /* ec_pool */ false,
1664 /* intervals */
1665 { ival{{0, 1, 2}, {0, 1, 2}, 10, 20, true, 0, 0}
1666 , ival{{ 1, 2}, { 1, 2}, 21, 30, true, 1, 1}
1667 , ival{{ 2}, { 2}, 31, 35, true, 2, 2}
1668 , ival{{0, 2}, {0, 2}, 36, 50, true, 0, 0}
1669 },
1670 /* les */ 5,
1671 /* min_peer */ 1,
1672 /* osd states at end */
1673 { make_pair(0, make_pair(PI::UP , 0))
1674 , make_pair(1, make_pair(PI::UP , 0))
1675 , make_pair(2, make_pair(PI::DOWN , 0))
1676 },
1677 /* acting */ {0, 1 },
1678 /* up */ {0, 1 },
1679 /* probe */ {pst(0), pst(1)},
1680 /* down */ {2},
1681 /* blocked_by */ {{2, 0}},
1682 /* pg_down */ true);
1683 }
1684
1685 TEST_F(PITest, past_intervals_ec_down) {
1686 run(
1687 /* ec_pool */ true,
1688 /* intervals */
1689 { ival{{0, 1, 2}, {0, 1, 2}, 10, 20, true, 0, 0}
1690 , ival{{N, 1, 2}, {N, 1, 2}, 21, 30, true, 1, 1}
1691 , ival{{N, N, 2}, {N, N, 2}, 31, 35, false, 2, 2}
1692 },
1693 /* les */ 5,
1694 /* min_peer */ 2,
1695 /* osd states at end */
1696 { make_pair(0, make_pair(PI::UP , 0))
1697 , make_pair(1, make_pair(PI::DOWN , 0))
1698 , make_pair(2, make_pair(PI::UP , 0))
1699 },
1700 /* acting */ {0, N, 2},
1701 /* up */ {0, N, 2},
1702 /* probe */ {pst(0, sit(0)), pst(2, sit(2))},
1703 /* down */ {1},
1704 /* blocked_by */ {{1, 0}},
1705 /* pg_down */ true);
1706 }
1707
1708 TEST_F(PITest, past_intervals_rep_no_subsets) {
1709 run(
1710 /* ec_pool */ false,
1711 /* intervals */
1712 { ival{{0, 2}, {0, 2}, 10, 20, true, 0, 0}
1713 , ival{{ 1, 2}, { 1, 2}, 21, 30, true, 1, 1}
1714 , ival{{0, 1 }, {0, 1 }, 31, 35, true, 0, 0}
1715 },
1716 /* les */ 5,
1717 /* min_peer */ 1,
1718 /* osd states at end */
1719 { make_pair(0, make_pair(PI::UP , 0))
1720 , make_pair(1, make_pair(PI::UP , 0))
1721 , make_pair(2, make_pair(PI::DOWN , 0))
1722 },
1723 /* acting */ {0, 1 },
1724 /* up */ {0, 1 },
1725 /* probe */ {pst(0), pst(1)},
1726 /* down */ {2},
1727 /* blocked_by */ {},
1728 /* pg_down */ false);
1729 }
1730
1731 TEST_F(PITest, past_intervals_ec_no_subsets) {
1732 run(
1733 /* ec_pool */ true,
1734 /* intervals */
1735 { ival{{0, N, 2}, {0, N, 2}, 10, 20, true, 0, 0}
1736 , ival{{N, 1, 2}, {N, 1, 2}, 21, 30, true, 1, 1}
1737 , ival{{0, 1, N}, {0, 1, N}, 31, 35, true, 0, 0}
1738 },
1739 /* les */ 5,
1740 /* min_peer */ 2,
1741 /* osd states at end */
1742 { make_pair(0, make_pair(PI::UP , 0))
1743 , make_pair(1, make_pair(PI::DOWN , 0))
1744 , make_pair(2, make_pair(PI::UP , 0))
1745 },
1746 /* acting */ {0, N, 2},
1747 /* up */ {0, N, 2},
1748 /* probe */ {pst(0, sit(0)), pst(2, sit(2))},
1749 /* down */ {1},
1750 /* blocked_by */ {{1, 0}},
1751 /* pg_down */ true);
1752 }
1753
1754 TEST_F(PITest, past_intervals_ec_no_subsets2) {
1755 run(
1756 /* ec_pool */ true,
1757 /* intervals */
1758 { ival{{N, 1, 2}, {N, 1, 2}, 10, 20, true, 0, 0}
1759 , ival{{0, N, 2}, {0, N, 2}, 21, 30, true, 1, 1}
1760 , ival{{0, 3, N}, {0, 3, N}, 31, 35, true, 0, 0}
1761 },
1762 /* les */ 31,
1763 /* min_peer */ 2,
1764 /* osd states at end */
1765 { make_pair(0, make_pair(PI::UP , 0))
1766 , make_pair(1, make_pair(PI::DOWN , 0))
1767 , make_pair(2, make_pair(PI::UP , 0))
1768 , make_pair(3, make_pair(PI::UP , 0))
1769 },
1770 /* acting */ {0, N, 2},
1771 /* up */ {0, N, 2},
1772 /* probe */ {pst(0, sit(0)), pst(2, sit(2)), pst(3, sit(1))},
1773 /* down */ {1},
1774 /* blocked_by */ {},
1775 /* pg_down */ false);
1776 }
1777
1778 TEST_F(PITest, past_intervals_rep_lost) {
1779 run(
1780 /* ec_pool */ false,
1781 /* intervals */
1782 { ival{{0, 1, 2}, {0, 1, 2}, 10, 20, true, 0, 0}
1783 , ival{{ 1, 2}, { 1, 2}, 21, 30, true, 1, 1}
1784 , ival{{ 2}, { 2}, 31, 35, true, 2, 2}
1785 , ival{{0, 2}, {0, 2}, 36, 50, true, 0, 0}
1786 },
1787 /* les */ 5,
1788 /* min_peer */ 1,
1789 /* osd states at end */
1790 { make_pair(0, make_pair(PI::UP , 0))
1791 , make_pair(1, make_pair(PI::UP , 0))
1792 , make_pair(2, make_pair(PI::LOST , 55))
1793 },
1794 /* acting */ {0, 1 },
1795 /* up */ {0, 1 },
1796 /* probe */ {pst(0), pst(1)},
1797 /* down */ {2},
1798 /* blocked_by */ {},
1799 /* pg_down */ false);
1800 }
1801
1802 TEST_F(PITest, past_intervals_ec_lost) {
1803 run(
1804 /* ec_pool */ true,
1805 /* intervals */
1806 { ival{{0, N, 2}, {0, N, 2}, 10, 20, true, 0, 0}
1807 , ival{{N, 1, 2}, {N, 1, 2}, 21, 30, true, 1, 1}
1808 , ival{{0, 1, N}, {0, 1, N}, 31, 35, true, 0, 0}
1809 },
1810 /* les */ 5,
1811 /* min_peer */ 2,
1812 /* osd states at end */
1813 { make_pair(0, make_pair(PI::UP , 0))
1814 , make_pair(1, make_pair(PI::LOST , 36))
1815 , make_pair(2, make_pair(PI::UP , 0))
1816 },
1817 /* acting */ {0, N, 2},
1818 /* up */ {0, N, 2},
1819 /* probe */ {pst(0, sit(0)), pst(2, sit(2))},
1820 /* down */ {1},
1821 /* blocked_by */ {},
1822 /* pg_down */ false);
1823 }
1824
1825
1826 /*
1827 * Local Variables:
1828 * compile-command: "cd ../.. ;
1829 * make unittest_osd_types ;
1830 * ./unittest_osd_types # --gtest_filter=pg_missing_t.constructor
1831 * "
1832 * End:
1833 */