1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2011 New Dream Network
7 * Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
9 * Author: Loic Dachary <loic@dachary.org>
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.
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"
29 TEST(hobject
, prefixes0
)
31 uint32_t mask
= 0xE947FA20;
35 set
<string
> prefixes_correct
;
36 prefixes_correct
.insert(string("0000000000000000.02A"));
38 set
<string
> prefixes_out(hobject_t::get_prefixes(bits
, mask
, pool
));
39 ASSERT_EQ(prefixes_out
, prefixes_correct
);
42 TEST(hobject
, prefixes1
)
44 uint32_t mask
= 0x0000000F;
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"));
54 set
<string
> prefixes_out(hobject_t::get_prefixes(bits
, mask
, pool
));
55 ASSERT_EQ(prefixes_out
, prefixes_correct
);
58 TEST(hobject
, prefixes2
)
60 uint32_t mask
= 0xDEADBEAF;
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"));
74 set
<string
> prefixes_out(hobject_t::get_prefixes(bits
, mask
, pool
));
75 ASSERT_EQ(prefixes_out
, prefixes_correct
);
78 TEST(hobject
, prefixes3
)
80 uint32_t mask
= 0xE947FA20;
84 set
<string
> prefixes_correct
;
85 prefixes_correct
.insert(string("0000000000000023.02AF749E"));
87 set
<string
> prefixes_out(hobject_t::get_prefixes(bits
, mask
, pool
));
88 ASSERT_EQ(prefixes_out
, prefixes_correct
);
91 TEST(hobject
, prefixes4
)
93 uint32_t mask
= 0xE947FA20;
97 set
<string
> prefixes_correct
;
98 prefixes_correct
.insert(string("0000000000000023."));
100 set
<string
> prefixes_out(hobject_t::get_prefixes(bits
, mask
, pool
));
101 ASSERT_EQ(prefixes_out
, prefixes_correct
);
104 TEST(hobject
, prefixes5
)
106 uint32_t mask
= 0xDEADBEAF;
108 int64_t pool
= 0x34AC5D00;
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"));
120 set
<string
> prefixes_out(hobject_t::get_prefixes(bits
, mask
, pool
));
121 ASSERT_EQ(prefixes_out
, prefixes_correct
);
124 TEST(pg_interval_t
, check_new_interval
)
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;
131 // Create a situation where osdmaps are the same so that
132 // each test case can diverge from it using minimal code.
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;
149 boost::scoped_ptr
<IsPGRecoverablePredicate
> recoverable(new ReplicatedBackend::RPCRecPred());
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
);
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
;
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
;
170 pgid
.set_pool(pool_id
);
173 // Do nothing if there are no modifications in
174 // acting, up or pool size and that the pool is not
178 PastIntervals past_intervals
; past_intervals
.update_type(ec_pool
, compact
);
180 ASSERT_TRUE(past_intervals
.empty());
181 ASSERT_FALSE(PastIntervals::check_new_interval(old_primary
,
196 ASSERT_TRUE(past_intervals
.empty());
200 // The acting set has changed
203 vector
<int> new_acting
;
204 int _new_primary
= osd_id
+ 1;
205 new_acting
.push_back(_new_primary
);
207 PastIntervals past_intervals
; past_intervals
.update_type(ec_pool
, compact
);
209 ASSERT_TRUE(past_intervals
.empty());
210 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary
,
225 old_primary
= new_primary
;
229 // The up set has changed
233 int _new_primary
= osd_id
+ 1;
234 new_up
.push_back(_new_primary
);
236 PastIntervals past_intervals
; past_intervals
.update_type(ec_pool
, compact
);
238 ASSERT_TRUE(past_intervals
.empty());
239 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary
,
257 // The up primary has changed
261 int _new_up_primary
= osd_id
+ 1;
263 PastIntervals past_intervals
; past_intervals
.update_type(ec_pool
, compact
);
265 ASSERT_TRUE(past_intervals
.empty());
266 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary
,
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
);
297 PastIntervals past_intervals
; past_intervals
.update_type(ec_pool
, compact
);
299 ASSERT_TRUE(past_intervals
.empty());
300 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary
,
318 // PG size has changed
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
);
331 PastIntervals past_intervals
; past_intervals
.update_type(ec_pool
, compact
);
333 ASSERT_TRUE(past_intervals
.empty());
334 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary
,
352 // The old acting set was empty : the previous interval could not
356 vector
<int> old_acting
;
358 PastIntervals past_intervals
; past_intervals
.update_type(ec_pool
, compact
);
362 ASSERT_TRUE(past_intervals
.empty());
363 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary
,
379 ASSERT_NE(string::npos
, out
.str().find("acting set is too small"));
383 // The old acting set did not have enough osd : it could
387 vector
<int> old_acting
;
388 old_acting
.push_back(osd_id
);
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
395 // The new osdmap is created so that it triggers the
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
);
410 PastIntervals past_intervals
; past_intervals
.update_type(ec_pool
, compact
);
412 ASSERT_TRUE(past_intervals
.empty());
413 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary
,
429 ASSERT_NE(string::npos
, out
.str().find("acting set is too small"));
433 // The acting set changes. The old acting set primary was up during the
434 // previous interval and may have been rw.
437 vector
<int> new_acting
;
438 new_acting
.push_back(osd_id
+ 4);
439 new_acting
.push_back(osd_id
+ 5);
443 PastIntervals past_intervals
; past_intervals
.update_type(ec_pool
, compact
);
445 ASSERT_TRUE(past_intervals
.empty());
446 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary
,
462 ASSERT_NE(string::npos
, out
.str().find("includes interval"));
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.
470 vector
<int> new_acting
;
471 new_acting
.push_back(osd_id
+ 4);
472 new_acting
.push_back(osd_id
+ 5);
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
);
486 PastIntervals past_intervals
; past_intervals
.update_type(ec_pool
, compact
);
488 ASSERT_TRUE(past_intervals
.empty());
489 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary
,
505 ASSERT_NE(string::npos
, out
.str().find("presumed to have been rw"));
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
515 vector
<int> new_acting
;
516 new_acting
.push_back(osd_id
+ 4);
517 new_acting
.push_back(osd_id
+ 5);
519 epoch_t last_epoch_clean
= epoch
- 10;
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
);
533 PastIntervals past_intervals
; past_intervals
.update_type(ec_pool
, compact
);
535 ASSERT_TRUE(past_intervals
.empty());
536 ASSERT_TRUE(PastIntervals::check_new_interval(old_primary
,
552 ASSERT_NE(string::npos
, out
.str().find("does not include interval"));
554 } // end for, didn't want to reindent
557 TEST(pg_t
, get_ancestor
)
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));
576 b
= pgid
.is_split(1, 1, &s
);
580 b
= pgid
.is_split(2, 4, NULL
);
582 b
= pgid
.is_split(2, 4, &s
);
584 ASSERT_EQ(1u, s
.size());
585 ASSERT_TRUE(s
.count(pg_t(2, 0, -1)));
588 b
= pgid
.is_split(2, 8, &s
);
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)));
596 b
= pgid
.is_split(3, 8, &s
);
598 ASSERT_EQ(1u, s
.size());
599 ASSERT_TRUE(s
.count(pg_t(4, 0, -1)));
602 b
= pgid
.is_split(6, 8, NULL
);
604 b
= pgid
.is_split(6, 8, &s
);
606 ASSERT_EQ(0u, s
.size());
608 pgid
= pg_t(1, 0, -1);
611 b
= pgid
.is_split(2, 4, &s
);
613 ASSERT_EQ(1u, s
.size());
614 ASSERT_TRUE(s
.count(pg_t(3, 0, -1)));
617 b
= pgid
.is_split(2, 6, &s
);
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)));
624 b
= pgid
.is_split(2, 8, &s
);
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)));
632 b
= pgid
.is_split(4, 8, &s
);
634 ASSERT_EQ(1u, s
.size());
635 ASSERT_TRUE(s
.count(pg_t(5, 0, -1)));
638 b
= pgid
.is_split(3, 8, &s
);
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)));
646 b
= pgid
.is_split(6, 8, &s
);
648 ASSERT_EQ(0u, s
.size());
650 pgid
= pg_t(3, 0, -1);
653 b
= pgid
.is_split(7, 8, &s
);
655 ASSERT_EQ(1u, s
.size());
656 ASSERT_TRUE(s
.count(pg_t(7, 0, -1)));
659 b
= pgid
.is_split(7, 12, &s
);
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)));
666 b
= pgid
.is_split(7, 11, &s
);
668 ASSERT_EQ(1u, s
.size());
669 ASSERT_TRUE(s
.count(pg_t(7, 0, -1)));
673 TEST(pg_missing_t
, constructor
)
675 pg_missing_t missing
;
676 EXPECT_EQ((unsigned int)0, missing
.num_missing());
677 EXPECT_FALSE(missing
.have_missing());
680 TEST(pg_missing_t
, have_missing
)
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());
689 TEST(pg_missing_t
, claim
)
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());
698 EXPECT_FALSE(other
.have_missing());
700 other
.claim(missing
);
701 EXPECT_TRUE(other
.have_missing());
704 TEST(pg_missing_t
, is_missing
)
706 // pg_missing_t::is_missing(const hobject_t& oid) const
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
));
715 // bool pg_missing_t::is_missing(const hobject_t& oid, eversion_t v) const
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
));
728 TEST(pg_missing_t
, have_old
)
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
));
740 TEST(pg_missing_t
, add_next_event
)
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),
750 // new object (MODIFY)
752 pg_missing_t missing
;
753 pg_log_entry_t e
= sample_e
;
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());
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());
775 // new object (CLONE)
777 pg_missing_t missing
;
778 pg_log_entry_t e
= sample_e
;
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());
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());
800 // existing object (MODIFY)
802 pg_missing_t missing
;
803 pg_log_entry_t e
= sample_e
;
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());
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());
827 // object with prior version (MODIFY)
829 pg_missing_t missing
;
830 pg_log_entry_t e
= sample_e
;
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());
846 // obsolete (BACKLOG)
848 pg_missing_t missing
;
849 pg_log_entry_t e
= sample_e
;
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
), "");
860 // adding a DELETE matching an existing event
862 pg_missing_t missing
;
863 pg_log_entry_t e
= sample_e
;
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
));
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());
879 // ERROR op should only be used for dup detection
881 pg_missing_t missing
;
882 pg_log_entry_t e
= sample_e
;
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());
896 // ERROR op should not affect previous entries
898 pg_missing_t missing
;
899 pg_log_entry_t modify
= sample_e
;
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
);
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
);
917 TEST(pg_missing_t
, revise_need
)
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
);
938 TEST(pg_missing_t
, revise_have
)
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
);
958 TEST(pg_missing_t
, add
)
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
);
971 TEST(pg_missing_t
, rm
)
973 // void pg_missing_t::rm(const hobject_t& oid, eversion_t v)
975 hobject_t
oid(object_t("objname"), "key", 123, 456, 0, "");
976 pg_missing_t missing
;
977 EXPECT_FALSE(missing
.is_missing(oid
));
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
));
989 // void pg_missing_t::rm(const std::map<hobject_t, pg_missing_item>::iterator &m)
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
);
998 EXPECT_FALSE(missing
.is_missing(oid
));
1002 TEST(pg_missing_t
, got
)
1004 // void pg_missing_t::got(const hobject_t& oid, eversion_t v)
1006 hobject_t
oid(object_t("objname"), "key", 123, 456, 0, "");
1007 pg_missing_t missing
;
1008 // assert if the oid does not exist
1010 PrCtl unset_dumpable
;
1011 EXPECT_DEATH(missing
.got(oid
, eversion_t()), "");
1013 EXPECT_FALSE(missing
.is_missing(oid
));
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
1020 PrCtl unset_dumpable
;
1021 EXPECT_DEATH(missing
.got(oid
, eversion_t(epoch
/ 2,20)), "");
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
));
1027 // void pg_missing_t::got(const std::map<hobject_t, pg_missing_item>::iterator &m)
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
);
1036 EXPECT_FALSE(missing
.is_missing(oid
));
1040 TEST(pg_missing_t
, split_into
)
1043 hobject_t
oid1(object_t("objname"), "key1", 123, hash1
, 0, "");
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());
1050 child_pgid
.m_seed
= 1;
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
));
1060 class ObjectContextTest
: public ::testing::Test
{
1063 static const useconds_t DELAY_MAX
= 20 * 1000 * 1000;
1065 class Thread_read_lock
: public Thread
{
1069 explicit Thread_read_lock(ObjectContext
& _obc
) :
1074 void *entry() override
{
1075 obc
.ondisk_read_lock();
1080 class Thread_write_lock
: public Thread
{
1084 explicit Thread_write_lock(ObjectContext
& _obc
) :
1089 void *entry() override
{
1090 obc
.ondisk_write_lock();
1097 TEST_F(ObjectContextTest
, read_write_lock
)
1108 EXPECT_EQ(0, obc
.writers_waiting
);
1109 EXPECT_EQ(0, obc
.unstable_writes
);
1111 obc
.ondisk_write_lock();
1113 EXPECT_EQ(0, obc
.writers_waiting
);
1114 EXPECT_EQ(1, obc
.unstable_writes
);
1116 obc
.ondisk_write_lock();
1118 EXPECT_EQ(0, obc
.writers_waiting
);
1119 EXPECT_EQ(2, obc
.unstable_writes
);
1121 obc
.ondisk_write_unlock();
1123 EXPECT_EQ(0, obc
.writers_waiting
);
1124 EXPECT_EQ(1, obc
.unstable_writes
);
1126 obc
.ondisk_write_unlock();
1128 EXPECT_EQ(0, obc
.writers_waiting
);
1129 EXPECT_EQ(0, obc
.unstable_writes
);
1132 useconds_t delay
= 0;
1139 // read_lock => wait
1140 // write_unlock => signal
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
);
1148 obc
.ondisk_write_lock();
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
);
1155 Thread_read_lock
t(obc
);
1156 t
.create("obc_read");
1159 cout
<< "Trying (1) with delay " << delay
<< "us\n";
1161 } while (obc
.readers_waiting
== 0 &&
1162 ( delay
= delay
* 2 + 1) < DELAY_MAX
);
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
);
1169 obc
.ondisk_write_unlock();
1172 cout
<< "Trying (2) with delay " << delay
<< "us\n";
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
);
1181 obc
.ondisk_read_unlock();
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
);
1196 // write_lock => wait
1197 // read_unlock => signal
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
);
1205 obc
.ondisk_read_lock();
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
);
1212 Thread_write_lock
t(obc
);
1213 t
.create("obc_write");
1216 cout
<< "Trying (3) with delay " << delay
<< "us\n";
1218 } while ((obc
.writers_waiting
== 0) &&
1219 ( delay
= delay
* 2 + 1) < DELAY_MAX
);
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
);
1226 obc
.ondisk_read_unlock();
1229 cout
<< "Trying (4) with delay " << delay
<< "us\n";
1231 } while ((obc
.unstable_writes
== 0 || obc
.writers_waiting
== 1) &&
1232 ( delay
= delay
* 2 + 1) < DELAY_MAX
);
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
);
1239 obc
.ondisk_write_unlock();
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
);
1251 TEST(pg_pool_t_test
, get_pg_num_divisor
) {
1256 for (int i
= 0; i
< 16; ++i
)
1257 ASSERT_EQ(16u, p
.get_pg_num_divisor(pg_t(i
, 1)));
1262 ASSERT_EQ(16u, p
.get_pg_num_divisor(pg_t(0, 1)));
1263 ASSERT_EQ(16u, p
.get_pg_num_divisor(pg_t(1, 1)));
1264 ASSERT_EQ(16u, p
.get_pg_num_divisor(pg_t(2, 1)));
1265 ASSERT_EQ(16u, p
.get_pg_num_divisor(pg_t(3, 1)));
1266 ASSERT_EQ(8u, p
.get_pg_num_divisor(pg_t(4, 1)));
1267 ASSERT_EQ(8u, p
.get_pg_num_divisor(pg_t(5, 1)));
1268 ASSERT_EQ(8u, p
.get_pg_num_divisor(pg_t(6, 1)));
1269 ASSERT_EQ(8u, p
.get_pg_num_divisor(pg_t(7, 1)));
1270 ASSERT_EQ(16u, p
.get_pg_num_divisor(pg_t(8, 1)));
1271 ASSERT_EQ(16u, p
.get_pg_num_divisor(pg_t(9, 1)));
1272 ASSERT_EQ(16u, p
.get_pg_num_divisor(pg_t(10, 1)));
1273 ASSERT_EQ(16u, p
.get_pg_num_divisor(pg_t(11, 1)));
1276 TEST(pg_pool_t_test
, get_random_pg_position
) {
1278 for (int i
= 0; i
< 100; ++i
) {
1280 p
.set_pg_num(1 + (rand() % 1000));
1281 p
.set_pgp_num(p
.get_pg_num());
1282 pg_t
pgid(rand() % p
.get_pg_num(), 1);
1283 uint32_t h
= p
.get_random_pg_position(pgid
, rand());
1284 uint32_t ps
= p
.raw_hash_to_pg(h
);
1285 cout
<< p
.get_pg_num() << " " << pgid
<< ": "
1286 << h
<< " -> " << pg_t(ps
, 1) << std::endl
;
1287 ASSERT_EQ(pgid
.ps(), ps
);
1291 TEST(shard_id_t
, iostream
) {
1292 set
<shard_id_t
> shards
;
1293 shards
.insert(shard_id_t(0));
1294 shards
.insert(shard_id_t(1));
1295 shards
.insert(shard_id_t(2));
1298 ASSERT_EQ(out
.str(), "0,1,2");
1300 shard_id_t noshard
= shard_id_t::NO_SHARD
;
1302 ASSERT_GT(zero
, noshard
);
1305 TEST(spg_t
, parse
) {
1306 spg_t
a(pg_t(1,2), shard_id_t::NO_SHARD
);
1308 spg_t
b(pg_t(3,2), shard_id_t(2));
1309 std::string s
= stringify(a
);
1310 ASSERT_TRUE(aa
.parse(s
.c_str()));
1314 ASSERT_TRUE(bb
.parse(s
.c_str()));
1318 TEST(coll_t
, parse
) {
1319 const char *ok
[] = {
1328 const char *bad
[] = {
1332 //" 1.2_head", // hrm, this parses, which is not ideal.. pg_t's fault?
1341 for (int i
= 0; ok
[i
]; ++i
) {
1342 cout
<< "check ok " << ok
[i
] << std::endl
;
1343 ASSERT_TRUE(a
.parse(ok
[i
]));
1344 ASSERT_EQ(string(ok
[i
]), a
.to_str());
1346 for (int i
= 0; bad
[i
]; ++i
) {
1347 cout
<< "check bad " << bad
[i
] << std::endl
;
1348 ASSERT_FALSE(a
.parse(bad
[i
]));
1352 TEST(coll_t
, temp
) {
1355 ASSERT_EQ(foo
.to_str(), string("0.0_head"));
1357 coll_t temp
= foo
.get_temp();
1358 ASSERT_EQ(temp
.to_str(), string("0.0_TEMP"));
1361 ASSERT_TRUE(temp
.is_temp());
1362 ASSERT_TRUE(temp
.is_temp(&pgid2
));
1363 ASSERT_EQ(pgid
, pgid2
);
1366 TEST(coll_t
, assigment
) {
1369 ASSERT_EQ(right
.to_str(), string("0.0_head"));
1371 coll_t left
, middle
;
1373 ASSERT_EQ(left
.to_str(), string("meta"));
1374 ASSERT_EQ(middle
.to_str(), string("meta"));
1376 left
= middle
= right
;
1378 ASSERT_EQ(left
.to_str(), string("0.0_head"));
1379 ASSERT_EQ(middle
.to_str(), string("0.0_head"));
1381 ASSERT_NE(middle
.c_str(), right
.c_str());
1382 ASSERT_NE(left
.c_str(), middle
.c_str());
1385 TEST(hobject_t
, parse
) {
1389 "-1:60c2fa6d:::inc_osdmap.1:0",
1390 "-1:60c2fa6d:::inc_osdmap.1:333",
1391 "0:00000000::::head",
1392 "1:00000000:nspace:key:obj:head",
1393 "-40:00000000:nspace::obj:head",
1394 "20:00000000::key:obj:head",
1395 "20:00000000:::o%fdj:head",
1396 "20:00000000:::o%02fdj:head",
1397 "20:00000000:::_zero_%00_:head",
1401 for (unsigned i
=0; v
[i
]; ++i
) {
1403 bool b
= o
.parse(v
[i
]);
1405 cout
<< "failed to parse " << v
[i
] << std::endl
;
1408 string s
= stringify(o
);
1410 cout
<< v
[i
] << " -> " << o
<< " -> " << s
<< std::endl
;
1411 ASSERT_EQ(s
, string(v
[i
]));
1416 TEST(ghobject_t
, cmp
) {
1419 sep
.set_shard(shard_id_t(1));
1421 cout
<< min
<< " < " << sep
<< std::endl
;
1422 ASSERT_TRUE(min
< sep
);
1424 sep
.set_shard(shard_id_t::NO_SHARD
);
1425 cout
<< "sep shard " << sep
.shard_id
<< std::endl
;
1426 ghobject_t
o(hobject_t(object_t(), string(), CEPH_NOSNAP
, 0x42,
1428 cout
<< "o " << o
<< std::endl
;
1429 ASSERT_TRUE(o
> sep
);
1432 TEST(ghobject_t
, parse
) {
1436 "13#0:00000000::::head#",
1437 "13#0:00000000::::head#deadbeef",
1438 "#-1:60c2fa6d:::inc_osdmap.1:333#deadbeef",
1439 "#-1:60c2fa6d:::inc%02osdmap.1:333#deadbeef",
1440 "#-1:60c2fa6d:::inc_osdmap.1:333#",
1444 "#-40:00000000:nspace::obj:head#",
1448 for (unsigned i
=0; v
[i
]; ++i
) {
1450 bool b
= o
.parse(v
[i
]);
1452 cout
<< "failed to parse " << v
[i
] << std::endl
;
1455 string s
= stringify(o
);
1457 cout
<< v
[i
] << " -> " << o
<< " -> " << s
<< std::endl
;
1458 ASSERT_EQ(s
, string(v
[i
]));
1463 TEST(pool_opts_t
, invalid_opt
) {
1464 EXPECT_FALSE(pool_opts_t::is_opt_name("INVALID_OPT"));
1465 PrCtl unset_dumpable
;
1466 EXPECT_DEATH(pool_opts_t::get_opt_desc("INVALID_OPT"), "");
1469 TEST(pool_opts_t
, scrub_min_interval
) {
1470 EXPECT_TRUE(pool_opts_t::is_opt_name("scrub_min_interval"));
1471 EXPECT_EQ(pool_opts_t::get_opt_desc("scrub_min_interval"),
1472 pool_opts_t::opt_desc_t(pool_opts_t::SCRUB_MIN_INTERVAL
,
1473 pool_opts_t::DOUBLE
));
1476 EXPECT_FALSE(opts
.is_set(pool_opts_t::SCRUB_MIN_INTERVAL
));
1478 PrCtl unset_dumpable
;
1479 EXPECT_DEATH(opts
.get(pool_opts_t::SCRUB_MIN_INTERVAL
), "");
1482 EXPECT_FALSE(opts
.get(pool_opts_t::SCRUB_MIN_INTERVAL
, &val
));
1483 opts
.set(pool_opts_t::SCRUB_MIN_INTERVAL
, static_cast<double>(2015));
1484 EXPECT_TRUE(opts
.get(pool_opts_t::SCRUB_MIN_INTERVAL
, &val
));
1485 EXPECT_EQ(val
, 2015);
1486 opts
.unset(pool_opts_t::SCRUB_MIN_INTERVAL
);
1487 EXPECT_FALSE(opts
.is_set(pool_opts_t::SCRUB_MIN_INTERVAL
));
1490 TEST(pool_opts_t
, scrub_max_interval
) {
1491 EXPECT_TRUE(pool_opts_t::is_opt_name("scrub_max_interval"));
1492 EXPECT_EQ(pool_opts_t::get_opt_desc("scrub_max_interval"),
1493 pool_opts_t::opt_desc_t(pool_opts_t::SCRUB_MAX_INTERVAL
,
1494 pool_opts_t::DOUBLE
));
1497 EXPECT_FALSE(opts
.is_set(pool_opts_t::SCRUB_MAX_INTERVAL
));
1499 PrCtl unset_dumpable
;
1500 EXPECT_DEATH(opts
.get(pool_opts_t::SCRUB_MAX_INTERVAL
), "");
1503 EXPECT_FALSE(opts
.get(pool_opts_t::SCRUB_MAX_INTERVAL
, &val
));
1504 opts
.set(pool_opts_t::SCRUB_MAX_INTERVAL
, static_cast<double>(2015));
1505 EXPECT_TRUE(opts
.get(pool_opts_t::SCRUB_MAX_INTERVAL
, &val
));
1506 EXPECT_EQ(val
, 2015);
1507 opts
.unset(pool_opts_t::SCRUB_MAX_INTERVAL
);
1508 EXPECT_FALSE(opts
.is_set(pool_opts_t::SCRUB_MAX_INTERVAL
));
1511 TEST(pool_opts_t
, deep_scrub_interval
) {
1512 EXPECT_TRUE(pool_opts_t::is_opt_name("deep_scrub_interval"));
1513 EXPECT_EQ(pool_opts_t::get_opt_desc("deep_scrub_interval"),
1514 pool_opts_t::opt_desc_t(pool_opts_t::DEEP_SCRUB_INTERVAL
,
1515 pool_opts_t::DOUBLE
));
1518 EXPECT_FALSE(opts
.is_set(pool_opts_t::DEEP_SCRUB_INTERVAL
));
1520 PrCtl unset_dumpable
;
1521 EXPECT_DEATH(opts
.get(pool_opts_t::DEEP_SCRUB_INTERVAL
), "");
1524 EXPECT_FALSE(opts
.get(pool_opts_t::DEEP_SCRUB_INTERVAL
, &val
));
1525 opts
.set(pool_opts_t::DEEP_SCRUB_INTERVAL
, static_cast<double>(2015));
1526 EXPECT_TRUE(opts
.get(pool_opts_t::DEEP_SCRUB_INTERVAL
, &val
));
1527 EXPECT_EQ(val
, 2015);
1528 opts
.unset(pool_opts_t::DEEP_SCRUB_INTERVAL
);
1529 EXPECT_FALSE(opts
.is_set(pool_opts_t::DEEP_SCRUB_INTERVAL
));
1532 struct RequiredPredicate
: IsPGRecoverablePredicate
{
1533 unsigned required_size
;
1534 RequiredPredicate(unsigned required_size
) : required_size(required_size
) {}
1535 bool operator()(const set
<pg_shard_t
> &have
) const override
{
1536 return have
.size() >= required_size
;
1540 using namespace std
;
1541 struct MapPredicate
{
1542 map
<int, pair
<PastIntervals::osd_state_t
, epoch_t
>> states
;
1544 vector
<pair
<int, pair
<PastIntervals::osd_state_t
, epoch_t
>>> _states
)
1545 : states(_states
.begin(), _states
.end()) {}
1546 PastIntervals::osd_state_t
operator()(epoch_t start
, int osd
, epoch_t
*lost_at
) {
1547 auto val
= states
.at(osd
);
1549 *lost_at
= val
.second
;
1554 using sit
= shard_id_t
;
1555 using PI
= PastIntervals
;
1556 using pst
= pg_shard_t
;
1557 using ival
= PastIntervals::pg_interval_t
;
1558 using ivallst
= std::list
<ival
>;
1559 const int N
= 0x7fffffff /* CRUSH_ITEM_NONE, can't import crush.h here */;
1561 struct PITest
: ::testing::Test
{
1566 epoch_t last_epoch_started
,
1567 unsigned min_to_peer
,
1568 vector
<pair
<int, pair
<PastIntervals::osd_state_t
, epoch_t
>>> osd_states
,
1571 set
<pg_shard_t
> probe
,
1573 map
<int, epoch_t
> blocked_by
,
1575 RequiredPredicate
rec_pred(min_to_peer
);
1576 MapPredicate
map_pred(osd_states
);
1578 PI::PriorSet
correct(
1584 new RequiredPredicate(rec_pred
));
1586 PastIntervals simple
, compact
;
1587 simple
.update_type(ec_pool
, false);
1588 compact
.update_type(ec_pool
, true);
1589 for (auto &&i
: intervals
) {
1590 simple
.add_interval(ec_pool
, i
);
1591 compact
.add_interval(ec_pool
, i
);
1593 PI::PriorSet simple_ps
= simple
.get_prior_set(
1596 new RequiredPredicate(rec_pred
),
1601 PI::PriorSet compact_ps
= compact
.get_prior_set(
1604 new RequiredPredicate(rec_pred
),
1609 ASSERT_EQ(correct
, simple_ps
);
1610 ASSERT_EQ(correct
, compact_ps
);
1614 TEST_F(PITest
, past_intervals_rep
) {
1616 /* ec_pool */ false,
1618 { ival
{{0, 1, 2}, {0, 1, 2}, 10, 20, true, 0, 0}
1619 , ival
{{ 1, 2}, { 1, 2}, 21, 30, true, 1, 1}
1620 , ival
{{ 2}, { 2}, 31, 35, false, 2, 2}
1621 , ival
{{0, 2}, {0, 2}, 36, 50, true, 0, 0}
1625 /* osd states at end */
1626 { make_pair(0, make_pair(PI::UP
, 0))
1627 , make_pair(1, make_pair(PI::UP
, 0))
1628 , make_pair(2, make_pair(PI::DOWN
, 0))
1630 /* acting */ {0, 1 },
1632 /* probe */ {pst(0), pst(1)},
1634 /* blocked_by */ {},
1635 /* pg_down */ false);
1638 TEST_F(PITest
, past_intervals_ec
) {
1642 { ival
{{0, 1, 2}, {0, 1, 2}, 10, 20, true, 0, 0}
1643 , ival
{{N
, 1, 2}, {N
, 1, 2}, 21, 30, true, 1, 1}
1647 /* osd states at end */
1648 { make_pair(0, make_pair(PI::DOWN
, 0))
1649 , make_pair(1, make_pair(PI::UP
, 0))
1650 , make_pair(2, make_pair(PI::UP
, 0))
1652 /* acting */ {N
, 1, 2},
1654 /* probe */ {pst(1, sit(1)), pst(2, sit(2))},
1656 /* blocked_by */ {},
1657 /* pg_down */ false);
1660 TEST_F(PITest
, past_intervals_rep_down
) {
1662 /* ec_pool */ false,
1664 { ival
{{0, 1, 2}, {0, 1, 2}, 10, 20, true, 0, 0}
1665 , ival
{{ 1, 2}, { 1, 2}, 21, 30, true, 1, 1}
1666 , ival
{{ 2}, { 2}, 31, 35, true, 2, 2}
1667 , ival
{{0, 2}, {0, 2}, 36, 50, true, 0, 0}
1671 /* osd states at end */
1672 { make_pair(0, make_pair(PI::UP
, 0))
1673 , make_pair(1, make_pair(PI::UP
, 0))
1674 , make_pair(2, make_pair(PI::DOWN
, 0))
1676 /* acting */ {0, 1 },
1678 /* probe */ {pst(0), pst(1)},
1680 /* blocked_by */ {{2, 0}},
1681 /* pg_down */ true);
1684 TEST_F(PITest
, past_intervals_ec_down
) {
1688 { ival
{{0, 1, 2}, {0, 1, 2}, 10, 20, true, 0, 0}
1689 , ival
{{N
, 1, 2}, {N
, 1, 2}, 21, 30, true, 1, 1}
1690 , ival
{{N
, N
, 2}, {N
, N
, 2}, 31, 35, false, 2, 2}
1694 /* osd states at end */
1695 { make_pair(0, make_pair(PI::UP
, 0))
1696 , make_pair(1, make_pair(PI::DOWN
, 0))
1697 , make_pair(2, make_pair(PI::UP
, 0))
1699 /* acting */ {0, N
, 2},
1701 /* probe */ {pst(0, sit(0)), pst(2, sit(2))},
1703 /* blocked_by */ {{1, 0}},
1704 /* pg_down */ true);
1707 TEST_F(PITest
, past_intervals_rep_no_subsets
) {
1709 /* ec_pool */ false,
1711 { ival
{{0, 2}, {0, 2}, 10, 20, true, 0, 0}
1712 , ival
{{ 1, 2}, { 1, 2}, 21, 30, true, 1, 1}
1713 , ival
{{0, 1 }, {0, 1 }, 31, 35, true, 0, 0}
1717 /* osd states at end */
1718 { make_pair(0, make_pair(PI::UP
, 0))
1719 , make_pair(1, make_pair(PI::UP
, 0))
1720 , make_pair(2, make_pair(PI::DOWN
, 0))
1722 /* acting */ {0, 1 },
1724 /* probe */ {pst(0), pst(1)},
1726 /* blocked_by */ {},
1727 /* pg_down */ false);
1730 TEST_F(PITest
, past_intervals_ec_no_subsets
) {
1734 { ival
{{0, N
, 2}, {0, N
, 2}, 10, 20, true, 0, 0}
1735 , ival
{{N
, 1, 2}, {N
, 1, 2}, 21, 30, true, 1, 1}
1736 , ival
{{0, 1, N
}, {0, 1, N
}, 31, 35, true, 0, 0}
1740 /* osd states at end */
1741 { make_pair(0, make_pair(PI::UP
, 0))
1742 , make_pair(1, make_pair(PI::DOWN
, 0))
1743 , make_pair(2, make_pair(PI::UP
, 0))
1745 /* acting */ {0, N
, 2},
1747 /* probe */ {pst(0, sit(0)), pst(2, sit(2))},
1749 /* blocked_by */ {{1, 0}},
1750 /* pg_down */ true);
1753 TEST_F(PITest
, past_intervals_ec_no_subsets2
) {
1757 { ival
{{N
, 1, 2}, {N
, 1, 2}, 10, 20, true, 0, 0}
1758 , ival
{{0, N
, 2}, {0, N
, 2}, 21, 30, true, 1, 1}
1759 , ival
{{0, 3, N
}, {0, 3, N
}, 31, 35, true, 0, 0}
1763 /* osd states at end */
1764 { make_pair(0, make_pair(PI::UP
, 0))
1765 , make_pair(1, make_pair(PI::DOWN
, 0))
1766 , make_pair(2, make_pair(PI::UP
, 0))
1767 , make_pair(3, make_pair(PI::UP
, 0))
1769 /* acting */ {0, N
, 2},
1771 /* probe */ {pst(0, sit(0)), pst(2, sit(2)), pst(3, sit(1))},
1773 /* blocked_by */ {},
1774 /* pg_down */ false);
1777 TEST_F(PITest
, past_intervals_rep_lost
) {
1779 /* ec_pool */ false,
1781 { ival
{{0, 1, 2}, {0, 1, 2}, 10, 20, true, 0, 0}
1782 , ival
{{ 1, 2}, { 1, 2}, 21, 30, true, 1, 1}
1783 , ival
{{ 2}, { 2}, 31, 35, true, 2, 2}
1784 , ival
{{0, 2}, {0, 2}, 36, 50, true, 0, 0}
1788 /* osd states at end */
1789 { make_pair(0, make_pair(PI::UP
, 0))
1790 , make_pair(1, make_pair(PI::UP
, 0))
1791 , make_pair(2, make_pair(PI::LOST
, 55))
1793 /* acting */ {0, 1 },
1795 /* probe */ {pst(0), pst(1)},
1797 /* blocked_by */ {},
1798 /* pg_down */ false);
1801 TEST_F(PITest
, past_intervals_ec_lost
) {
1805 { ival
{{0, N
, 2}, {0, N
, 2}, 10, 20, true, 0, 0}
1806 , ival
{{N
, 1, 2}, {N
, 1, 2}, 21, 30, true, 1, 1}
1807 , ival
{{0, 1, N
}, {0, 1, N
}, 31, 35, true, 0, 0}
1811 /* osd states at end */
1812 { make_pair(0, make_pair(PI::UP
, 0))
1813 , make_pair(1, make_pair(PI::LOST
, 36))
1814 , make_pair(2, make_pair(PI::UP
, 0))
1816 /* acting */ {0, N
, 2},
1818 /* probe */ {pst(0, sit(0)), pst(2, sit(2))},
1820 /* blocked_by */ {},
1821 /* pg_down */ false);
1827 * compile-command: "cd ../.. ;
1828 * make unittest_osd_types ;
1829 * ./unittest_osd_types # --gtest_filter=pg_missing_t.constructor