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(), false);
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(), false);
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(), false);
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(), false);
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(), false);
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_TRUE(missing.is_missing(oid));
877 EXPECT_TRUE(missing.get_items().at(oid).is_delete());
878 EXPECT_EQ(prior_version, missing.get_items().at(oid).have);
879 EXPECT_EQ(version, missing.get_items().at(oid).need);
880 EXPECT_EQ(oid, missing.get_rmissing().at(e.version.version));
881 EXPECT_EQ(1U, missing.num_missing());
882 EXPECT_EQ(1U, missing.get_rmissing().size());
885 // adding a LOST_DELETE after an existing event
887 pg_missing_t missing;
888 pg_log_entry_t e = sample_e;
890 e.op = pg_log_entry_t::MODIFY;
891 EXPECT_TRUE(e.is_update());
892 EXPECT_TRUE(e.object_is_indexed());
893 EXPECT_TRUE(e.reqid_is_indexed());
894 EXPECT_FALSE(missing.is_missing(oid));
895 missing.add_next_event(e);
896 EXPECT_TRUE(missing.is_missing(oid));
897 EXPECT_FALSE(missing.get_items().at(oid).is_delete());
899 e.op = pg_log_entry_t::LOST_DELETE;
901 EXPECT_TRUE(e.is_delete());
902 missing.add_next_event(e);
903 EXPECT_TRUE(missing.is_missing(oid));
904 EXPECT_TRUE(missing.get_items().at(oid).is_delete());
905 EXPECT_EQ(prior_version, missing.get_items().at(oid).have);
906 EXPECT_EQ(e.version, missing.get_items().at(oid).need);
907 EXPECT_EQ(oid, missing.get_rmissing().at(e.version.version));
908 EXPECT_EQ(1U, missing.num_missing());
909 EXPECT_EQ(1U, missing.get_rmissing().size());
913 TEST(pg_missing_t, revise_need)
915 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
916 pg_missing_t missing;
917 // create a new entry
918 EXPECT_FALSE(missing.is_missing(oid));
919 eversion_t need(10,10);
920 missing.revise_need(oid, need, false);
921 EXPECT_TRUE(missing.is_missing(oid));
922 EXPECT_EQ(eversion_t(), missing.get_items().at(oid).have);
923 EXPECT_EQ(need, missing.get_items().at(oid).need);
924 // update an existing entry and preserve have
925 eversion_t have(1,1);
926 missing.revise_have(oid, have);
927 eversion_t new_need(10,12);
928 EXPECT_EQ(have, missing.get_items().at(oid).have);
929 missing.revise_need(oid, new_need, false);
930 EXPECT_EQ(have, missing.get_items().at(oid).have);
931 EXPECT_EQ(new_need, missing.get_items().at(oid).need);
934 TEST(pg_missing_t, revise_have)
936 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
937 pg_missing_t missing;
938 // a non existing entry means noop
939 EXPECT_FALSE(missing.is_missing(oid));
940 eversion_t have(1,1);
941 missing.revise_have(oid, have);
942 EXPECT_FALSE(missing.is_missing(oid));
943 // update an existing entry
944 eversion_t need(10,12);
945 missing.add(oid, need, have, false);
946 EXPECT_TRUE(missing.is_missing(oid));
947 eversion_t new_have(2,2);
948 EXPECT_EQ(have, missing.get_items().at(oid).have);
949 missing.revise_have(oid, new_have);
950 EXPECT_EQ(new_have, missing.get_items().at(oid).have);
951 EXPECT_EQ(need, missing.get_items().at(oid).need);
954 TEST(pg_missing_t, add)
956 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
957 pg_missing_t missing;
958 EXPECT_FALSE(missing.is_missing(oid));
959 eversion_t have(1,1);
960 eversion_t need(10,10);
961 missing.add(oid, need, have, false);
962 EXPECT_TRUE(missing.is_missing(oid));
963 EXPECT_EQ(have, missing.get_items().at(oid).have);
964 EXPECT_EQ(need, missing.get_items().at(oid).need);
967 TEST(pg_missing_t, rm)
969 // void pg_missing_t::rm(const hobject_t& oid, eversion_t v)
971 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
972 pg_missing_t missing;
973 EXPECT_FALSE(missing.is_missing(oid));
975 eversion_t need(epoch,10);
976 missing.add(oid, need, eversion_t(), false);
977 EXPECT_TRUE(missing.is_missing(oid));
978 // rm of an older version is a noop
979 missing.rm(oid, eversion_t(epoch / 2,20));
980 EXPECT_TRUE(missing.is_missing(oid));
981 // rm of a later version removes the object
982 missing.rm(oid, eversion_t(epoch * 2,20));
983 EXPECT_FALSE(missing.is_missing(oid));
985 // void pg_missing_t::rm(const std::map<hobject_t, pg_missing_item>::iterator &m)
987 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
988 pg_missing_t missing;
989 EXPECT_FALSE(missing.is_missing(oid));
990 missing.add(oid, eversion_t(), eversion_t(), false);
991 EXPECT_TRUE(missing.is_missing(oid));
992 auto m = missing.get_items().find(oid);
994 EXPECT_FALSE(missing.is_missing(oid));
998 TEST(pg_missing_t, got)
1000 // void pg_missing_t::got(const hobject_t& oid, eversion_t v)
1002 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
1003 pg_missing_t missing;
1004 // assert if the oid does not exist
1006 PrCtl unset_dumpable;
1007 EXPECT_DEATH(missing.got(oid, eversion_t()), "");
1009 EXPECT_FALSE(missing.is_missing(oid));
1011 eversion_t need(epoch,10);
1012 missing.add(oid, need, eversion_t(), false);
1013 EXPECT_TRUE(missing.is_missing(oid));
1014 // assert if that the version to be removed is lower than the version of the object
1016 PrCtl unset_dumpable;
1017 EXPECT_DEATH(missing.got(oid, eversion_t(epoch / 2,20)), "");
1019 // remove of a later version removes the object
1020 missing.got(oid, eversion_t(epoch * 2,20));
1021 EXPECT_FALSE(missing.is_missing(oid));
1023 // void pg_missing_t::got(const std::map<hobject_t, pg_missing_item>::iterator &m)
1025 hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
1026 pg_missing_t missing;
1027 EXPECT_FALSE(missing.is_missing(oid));
1028 missing.add(oid, eversion_t(), eversion_t(), false);
1029 EXPECT_TRUE(missing.is_missing(oid));
1030 auto m = missing.get_items().find(oid);
1032 EXPECT_FALSE(missing.is_missing(oid));
1036 TEST(pg_missing_t, split_into)
1039 hobject_t oid1(object_t("objname"), "key1", 123, hash1, 0, "");
1041 hobject_t oid2(object_t("objname"), "key2", 123, hash2, 0, "");
1042 pg_missing_t missing;
1043 missing.add(oid1, eversion_t(), eversion_t(), false);
1044 missing.add(oid2, eversion_t(), eversion_t(), false);
1046 child_pgid.m_seed = 1;
1048 unsigned split_bits = 1;
1049 missing.split_into(child_pgid, split_bits, &child);
1050 EXPECT_TRUE(child.is_missing(oid1));
1051 EXPECT_FALSE(child.is_missing(oid2));
1052 EXPECT_FALSE(missing.is_missing(oid1));
1053 EXPECT_TRUE(missing.is_missing(oid2));
1056 class ObjectContextTest : public ::testing::Test {
1059 static const useconds_t DELAY_MAX = 20 * 1000 * 1000;
1061 class Thread_read_lock : public Thread {
1065 explicit Thread_read_lock(ObjectContext& _obc) :
1070 void *entry() override {
1071 obc.ondisk_read_lock();
1076 class Thread_write_lock : public Thread {
1080 explicit Thread_write_lock(ObjectContext& _obc) :
1085 void *entry() override {
1086 obc.ondisk_write_lock();
1093 TEST_F(ObjectContextTest, read_write_lock)
1104 EXPECT_EQ(0, obc.writers_waiting);
1105 EXPECT_EQ(0, obc.unstable_writes);
1107 obc.ondisk_write_lock();
1109 EXPECT_EQ(0, obc.writers_waiting);
1110 EXPECT_EQ(1, obc.unstable_writes);
1112 obc.ondisk_write_lock();
1114 EXPECT_EQ(0, obc.writers_waiting);
1115 EXPECT_EQ(2, obc.unstable_writes);
1117 obc.ondisk_write_unlock();
1119 EXPECT_EQ(0, obc.writers_waiting);
1120 EXPECT_EQ(1, obc.unstable_writes);
1122 obc.ondisk_write_unlock();
1124 EXPECT_EQ(0, obc.writers_waiting);
1125 EXPECT_EQ(0, obc.unstable_writes);
1128 useconds_t delay = 0;
1135 // read_lock => wait
1136 // write_unlock => signal
1139 EXPECT_EQ(0, obc.readers_waiting);
1140 EXPECT_EQ(0, obc.readers);
1141 EXPECT_EQ(0, obc.writers_waiting);
1142 EXPECT_EQ(0, obc.unstable_writes);
1144 obc.ondisk_write_lock();
1146 EXPECT_EQ(0, obc.readers_waiting);
1147 EXPECT_EQ(0, obc.readers);
1148 EXPECT_EQ(0, obc.writers_waiting);
1149 EXPECT_EQ(1, obc.unstable_writes);
1151 Thread_read_lock t(obc);
1152 t.create("obc_read");
1155 cout << "Trying (1) with delay " << delay << "us\n";
1157 } while (obc.readers_waiting == 0 &&
1158 ( delay = delay * 2 + 1) < DELAY_MAX);
1160 EXPECT_EQ(1, obc.readers_waiting);
1161 EXPECT_EQ(0, obc.readers);
1162 EXPECT_EQ(0, obc.writers_waiting);
1163 EXPECT_EQ(1, obc.unstable_writes);
1165 obc.ondisk_write_unlock();
1168 cout << "Trying (2) with delay " << delay << "us\n";
1170 } while ((obc.readers == 0 || obc.readers_waiting == 1) &&
1171 ( delay = delay * 2 + 1) < DELAY_MAX);
1172 EXPECT_EQ(0, obc.readers_waiting);
1173 EXPECT_EQ(1, obc.readers);
1174 EXPECT_EQ(0, obc.writers_waiting);
1175 EXPECT_EQ(0, obc.unstable_writes);
1177 obc.ondisk_read_unlock();
1179 EXPECT_EQ(0, obc.readers_waiting);
1180 EXPECT_EQ(0, obc.readers);
1181 EXPECT_EQ(0, obc.writers_waiting);
1182 EXPECT_EQ(0, obc.unstable_writes);
1192 // write_lock => wait
1193 // read_unlock => signal
1196 EXPECT_EQ(0, obc.readers_waiting);
1197 EXPECT_EQ(0, obc.readers);
1198 EXPECT_EQ(0, obc.writers_waiting);
1199 EXPECT_EQ(0, obc.unstable_writes);
1201 obc.ondisk_read_lock();
1203 EXPECT_EQ(0, obc.readers_waiting);
1204 EXPECT_EQ(1, obc.readers);
1205 EXPECT_EQ(0, obc.writers_waiting);
1206 EXPECT_EQ(0, obc.unstable_writes);
1208 Thread_write_lock t(obc);
1209 t.create("obc_write");
1212 cout << "Trying (3) with delay " << delay << "us\n";
1214 } while ((obc.writers_waiting == 0) &&
1215 ( delay = delay * 2 + 1) < DELAY_MAX);
1217 EXPECT_EQ(0, obc.readers_waiting);
1218 EXPECT_EQ(1, obc.readers);
1219 EXPECT_EQ(1, obc.writers_waiting);
1220 EXPECT_EQ(0, obc.unstable_writes);
1222 obc.ondisk_read_unlock();
1225 cout << "Trying (4) with delay " << delay << "us\n";
1227 } while ((obc.unstable_writes == 0 || obc.writers_waiting == 1) &&
1228 ( delay = delay * 2 + 1) < DELAY_MAX);
1230 EXPECT_EQ(0, obc.readers_waiting);
1231 EXPECT_EQ(0, obc.readers);
1232 EXPECT_EQ(0, obc.writers_waiting);
1233 EXPECT_EQ(1, obc.unstable_writes);
1235 obc.ondisk_write_unlock();
1237 EXPECT_EQ(0, obc.readers_waiting);
1238 EXPECT_EQ(0, obc.readers);
1239 EXPECT_EQ(0, obc.writers_waiting);
1240 EXPECT_EQ(0, obc.unstable_writes);
1247 TEST(pg_pool_t_test, get_pg_num_divisor) {
1252 for (int i = 0; i < 16; ++i)
1253 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(i, 1)));
1258 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(0, 1)));
1259 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(1, 1)));
1260 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(2, 1)));
1261 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(3, 1)));
1262 ASSERT_EQ(8u, p.get_pg_num_divisor(pg_t(4, 1)));
1263 ASSERT_EQ(8u, p.get_pg_num_divisor(pg_t(5, 1)));
1264 ASSERT_EQ(8u, p.get_pg_num_divisor(pg_t(6, 1)));
1265 ASSERT_EQ(8u, p.get_pg_num_divisor(pg_t(7, 1)));
1266 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(8, 1)));
1267 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(9, 1)));
1268 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(10, 1)));
1269 ASSERT_EQ(16u, p.get_pg_num_divisor(pg_t(11, 1)));
1272 TEST(pg_pool_t_test, get_random_pg_position) {
1274 for (int i = 0; i < 100; ++i) {
1276 p.set_pg_num(1 + (rand() % 1000));
1277 p.set_pgp_num(p.get_pg_num());
1278 pg_t pgid(rand() % p.get_pg_num(), 1);
1279 uint32_t h = p.get_random_pg_position(pgid, rand());
1280 uint32_t ps = p.raw_hash_to_pg(h);
1281 cout << p.get_pg_num() << " " << pgid << ": "
1282 << h << " -> " << pg_t(ps, 1) << std::endl;
1283 ASSERT_EQ(pgid.ps(), ps);
1287 TEST(shard_id_t, iostream) {
1288 set<shard_id_t> shards;
1289 shards.insert(shard_id_t(0));
1290 shards.insert(shard_id_t(1));
1291 shards.insert(shard_id_t(2));
1294 ASSERT_EQ(out.str(), "0,1,2");
1296 shard_id_t noshard = shard_id_t::NO_SHARD;
1298 ASSERT_GT(zero, noshard);
1301 TEST(spg_t, parse) {
1302 spg_t a(pg_t(1,2), shard_id_t::NO_SHARD);
1304 spg_t b(pg_t(3,2), shard_id_t(2));
1305 std::string s = stringify(a);
1306 ASSERT_TRUE(aa.parse(s.c_str()));
1310 ASSERT_TRUE(bb.parse(s.c_str()));
1314 TEST(coll_t, parse) {
1315 const char *ok[] = {
1324 const char *bad[] = {
1328 //" 1.2_head", // hrm, this parses, which is not ideal.. pg_t's fault?
1337 for (int i = 0; ok[i]; ++i) {
1338 cout << "check ok " << ok[i] << std::endl;
1339 ASSERT_TRUE(a.parse(ok[i]));
1340 ASSERT_EQ(string(ok[i]), a.to_str());
1342 for (int i = 0; bad[i]; ++i) {
1343 cout << "check bad " << bad[i] << std::endl;
1344 ASSERT_FALSE(a.parse(bad[i]));
1348 TEST(coll_t, temp) {
1351 ASSERT_EQ(foo.to_str(), string("0.0_head"));
1353 coll_t temp = foo.get_temp();
1354 ASSERT_EQ(temp.to_str(), string("0.0_TEMP"));
1357 ASSERT_TRUE(temp.is_temp());
1358 ASSERT_TRUE(temp.is_temp(&pgid2));
1359 ASSERT_EQ(pgid, pgid2);
1362 TEST(coll_t, assigment) {
1365 ASSERT_EQ(right.to_str(), string("0.0_head"));
1367 coll_t left, middle;
1369 ASSERT_EQ(left.to_str(), string("meta"));
1370 ASSERT_EQ(middle.to_str(), string("meta"));
1372 left = middle = right;
1374 ASSERT_EQ(left.to_str(), string("0.0_head"));
1375 ASSERT_EQ(middle.to_str(), string("0.0_head"));
1377 ASSERT_NE(middle.c_str(), right.c_str());
1378 ASSERT_NE(left.c_str(), middle.c_str());
1381 TEST(hobject_t, parse) {
1385 "-1:60c2fa6d:::inc_osdmap.1:0",
1386 "-1:60c2fa6d:::inc_osdmap.1:333",
1387 "0:00000000::::head",
1388 "1:00000000:nspace:key:obj:head",
1389 "-40:00000000:nspace::obj:head",
1390 "20:00000000::key:obj:head",
1391 "20:00000000:::o%fdj:head",
1392 "20:00000000:::o%02fdj:head",
1393 "20:00000000:::_zero_%00_:head",
1397 for (unsigned i=0; v[i]; ++i) {
1399 bool b = o.parse(v[i]);
1401 cout << "failed to parse " << v[i] << std::endl;
1404 string s = stringify(o);
1406 cout << v[i] << " -> " << o << " -> " << s << std::endl;
1407 ASSERT_EQ(s, string(v[i]));
1412 TEST(ghobject_t, cmp) {
1415 sep.set_shard(shard_id_t(1));
1417 cout << min << " < " << sep << std::endl;
1418 ASSERT_TRUE(min < sep);
1420 sep.set_shard(shard_id_t::NO_SHARD);
1421 cout << "sep shard " << sep.shard_id << std::endl;
1422 ghobject_t o(hobject_t(object_t(), string(), CEPH_NOSNAP, 0x42,
1424 cout << "o " << o << std::endl;
1425 ASSERT_TRUE(o > sep);
1428 TEST(ghobject_t, parse) {
1432 "13#0:00000000::::head#",
1433 "13#0:00000000::::head#deadbeef",
1434 "#-1:60c2fa6d:::inc_osdmap.1:333#deadbeef",
1435 "#-1:60c2fa6d:::inc%02osdmap.1:333#deadbeef",
1436 "#-1:60c2fa6d:::inc_osdmap.1:333#",
1440 "#-40:00000000:nspace::obj:head#",
1444 for (unsigned i=0; v[i]; ++i) {
1446 bool b = o.parse(v[i]);
1448 cout << "failed to parse " << v[i] << std::endl;
1451 string s = stringify(o);
1453 cout << v[i] << " -> " << o << " -> " << s << std::endl;
1454 ASSERT_EQ(s, string(v[i]));
1459 TEST(pool_opts_t, invalid_opt) {
1460 EXPECT_FALSE(pool_opts_t::is_opt_name("INVALID_OPT"));
1461 PrCtl unset_dumpable;
1462 EXPECT_DEATH(pool_opts_t::get_opt_desc("INVALID_OPT"), "");
1465 TEST(pool_opts_t, scrub_min_interval) {
1466 EXPECT_TRUE(pool_opts_t::is_opt_name("scrub_min_interval"));
1467 EXPECT_EQ(pool_opts_t::get_opt_desc("scrub_min_interval"),
1468 pool_opts_t::opt_desc_t(pool_opts_t::SCRUB_MIN_INTERVAL,
1469 pool_opts_t::DOUBLE));
1472 EXPECT_FALSE(opts.is_set(pool_opts_t::SCRUB_MIN_INTERVAL));
1474 PrCtl unset_dumpable;
1475 EXPECT_DEATH(opts.get(pool_opts_t::SCRUB_MIN_INTERVAL), "");
1478 EXPECT_FALSE(opts.get(pool_opts_t::SCRUB_MIN_INTERVAL, &val));
1479 opts.set(pool_opts_t::SCRUB_MIN_INTERVAL, static_cast<double>(2015));
1480 EXPECT_TRUE(opts.get(pool_opts_t::SCRUB_MIN_INTERVAL, &val));
1481 EXPECT_EQ(val, 2015);
1482 opts.unset(pool_opts_t::SCRUB_MIN_INTERVAL);
1483 EXPECT_FALSE(opts.is_set(pool_opts_t::SCRUB_MIN_INTERVAL));
1486 TEST(pool_opts_t, scrub_max_interval) {
1487 EXPECT_TRUE(pool_opts_t::is_opt_name("scrub_max_interval"));
1488 EXPECT_EQ(pool_opts_t::get_opt_desc("scrub_max_interval"),
1489 pool_opts_t::opt_desc_t(pool_opts_t::SCRUB_MAX_INTERVAL,
1490 pool_opts_t::DOUBLE));
1493 EXPECT_FALSE(opts.is_set(pool_opts_t::SCRUB_MAX_INTERVAL));
1495 PrCtl unset_dumpable;
1496 EXPECT_DEATH(opts.get(pool_opts_t::SCRUB_MAX_INTERVAL), "");
1499 EXPECT_FALSE(opts.get(pool_opts_t::SCRUB_MAX_INTERVAL, &val));
1500 opts.set(pool_opts_t::SCRUB_MAX_INTERVAL, static_cast<double>(2015));
1501 EXPECT_TRUE(opts.get(pool_opts_t::SCRUB_MAX_INTERVAL, &val));
1502 EXPECT_EQ(val, 2015);
1503 opts.unset(pool_opts_t::SCRUB_MAX_INTERVAL);
1504 EXPECT_FALSE(opts.is_set(pool_opts_t::SCRUB_MAX_INTERVAL));
1507 TEST(pool_opts_t, deep_scrub_interval) {
1508 EXPECT_TRUE(pool_opts_t::is_opt_name("deep_scrub_interval"));
1509 EXPECT_EQ(pool_opts_t::get_opt_desc("deep_scrub_interval"),
1510 pool_opts_t::opt_desc_t(pool_opts_t::DEEP_SCRUB_INTERVAL,
1511 pool_opts_t::DOUBLE));
1514 EXPECT_FALSE(opts.is_set(pool_opts_t::DEEP_SCRUB_INTERVAL));
1516 PrCtl unset_dumpable;
1517 EXPECT_DEATH(opts.get(pool_opts_t::DEEP_SCRUB_INTERVAL), "");
1520 EXPECT_FALSE(opts.get(pool_opts_t::DEEP_SCRUB_INTERVAL, &val));
1521 opts.set(pool_opts_t::DEEP_SCRUB_INTERVAL, static_cast<double>(2015));
1522 EXPECT_TRUE(opts.get(pool_opts_t::DEEP_SCRUB_INTERVAL, &val));
1523 EXPECT_EQ(val, 2015);
1524 opts.unset(pool_opts_t::DEEP_SCRUB_INTERVAL);
1525 EXPECT_FALSE(opts.is_set(pool_opts_t::DEEP_SCRUB_INTERVAL));
1528 struct RequiredPredicate : IsPGRecoverablePredicate {
1529 unsigned required_size;
1530 RequiredPredicate(unsigned required_size) : required_size(required_size) {}
1531 bool operator()(const set<pg_shard_t> &have) const override {
1532 return have.size() >= required_size;
1536 using namespace std;
1537 struct MapPredicate {
1538 map<int, pair<PastIntervals::osd_state_t, epoch_t>> states;
1540 vector<pair<int, pair<PastIntervals::osd_state_t, epoch_t>>> _states)
1541 : states(_states.begin(), _states.end()) {}
1542 PastIntervals::osd_state_t operator()(epoch_t start, int osd, epoch_t *lost_at) {
1543 auto val = states.at(osd);
1545 *lost_at = val.second;
1550 using sit = shard_id_t;
1551 using PI = PastIntervals;
1552 using pst = pg_shard_t;
1553 using ival = PastIntervals::pg_interval_t;
1554 using ivallst = std::list<ival>;
1555 const int N = 0x7fffffff /* CRUSH_ITEM_NONE, can't import crush.h here */;
1557 struct PITest : ::testing::Test {
1562 epoch_t last_epoch_started,
1563 unsigned min_to_peer,
1564 vector<pair<int, pair<PastIntervals::osd_state_t, epoch_t>>> osd_states,
1567 set<pg_shard_t> probe,
1569 map<int, epoch_t> blocked_by,
1571 RequiredPredicate rec_pred(min_to_peer);
1572 MapPredicate map_pred(osd_states);
1574 PI::PriorSet correct(
1580 new RequiredPredicate(rec_pred));
1582 PastIntervals simple, compact;
1583 simple.update_type(ec_pool, false);
1584 compact.update_type(ec_pool, true);
1585 for (auto &&i: intervals) {
1586 simple.add_interval(ec_pool, i);
1587 compact.add_interval(ec_pool, i);
1589 PI::PriorSet simple_ps = simple.get_prior_set(
1592 new RequiredPredicate(rec_pred),
1597 PI::PriorSet compact_ps = compact.get_prior_set(
1600 new RequiredPredicate(rec_pred),
1605 ASSERT_EQ(correct, simple_ps);
1606 ASSERT_EQ(correct, compact_ps);
1610 TEST_F(PITest, past_intervals_rep) {
1612 /* ec_pool */ false,
1614 { ival{{0, 1, 2}, {0, 1, 2}, 10, 20, true, 0, 0}
1615 , ival{{ 1, 2}, { 1, 2}, 21, 30, true, 1, 1}
1616 , ival{{ 2}, { 2}, 31, 35, false, 2, 2}
1617 , ival{{0, 2}, {0, 2}, 36, 50, true, 0, 0}
1621 /* osd states at end */
1622 { make_pair(0, make_pair(PI::UP , 0))
1623 , make_pair(1, make_pair(PI::UP , 0))
1624 , make_pair(2, make_pair(PI::DOWN , 0))
1626 /* acting */ {0, 1 },
1628 /* probe */ {pst(0), pst(1)},
1630 /* blocked_by */ {},
1631 /* pg_down */ false);
1634 TEST_F(PITest, past_intervals_ec) {
1638 { ival{{0, 1, 2}, {0, 1, 2}, 10, 20, true, 0, 0}
1639 , ival{{N, 1, 2}, {N, 1, 2}, 21, 30, true, 1, 1}
1643 /* osd states at end */
1644 { make_pair(0, make_pair(PI::DOWN , 0))
1645 , make_pair(1, make_pair(PI::UP , 0))
1646 , make_pair(2, make_pair(PI::UP , 0))
1648 /* acting */ {N, 1, 2},
1650 /* probe */ {pst(1, sit(1)), pst(2, sit(2))},
1652 /* blocked_by */ {},
1653 /* pg_down */ false);
1656 TEST_F(PITest, past_intervals_rep_down) {
1658 /* ec_pool */ false,
1660 { ival{{0, 1, 2}, {0, 1, 2}, 10, 20, true, 0, 0}
1661 , ival{{ 1, 2}, { 1, 2}, 21, 30, true, 1, 1}
1662 , ival{{ 2}, { 2}, 31, 35, true, 2, 2}
1663 , ival{{0, 2}, {0, 2}, 36, 50, true, 0, 0}
1667 /* osd states at end */
1668 { make_pair(0, make_pair(PI::UP , 0))
1669 , make_pair(1, make_pair(PI::UP , 0))
1670 , make_pair(2, make_pair(PI::DOWN , 0))
1672 /* acting */ {0, 1 },
1674 /* probe */ {pst(0), pst(1)},
1676 /* blocked_by */ {{2, 0}},
1677 /* pg_down */ true);
1680 TEST_F(PITest, past_intervals_ec_down) {
1684 { ival{{0, 1, 2}, {0, 1, 2}, 10, 20, true, 0, 0}
1685 , ival{{N, 1, 2}, {N, 1, 2}, 21, 30, true, 1, 1}
1686 , ival{{N, N, 2}, {N, N, 2}, 31, 35, false, 2, 2}
1690 /* osd states at end */
1691 { make_pair(0, make_pair(PI::UP , 0))
1692 , make_pair(1, make_pair(PI::DOWN , 0))
1693 , make_pair(2, make_pair(PI::UP , 0))
1695 /* acting */ {0, N, 2},
1697 /* probe */ {pst(0, sit(0)), pst(2, sit(2))},
1699 /* blocked_by */ {{1, 0}},
1700 /* pg_down */ true);
1703 TEST_F(PITest, past_intervals_rep_no_subsets) {
1705 /* ec_pool */ false,
1707 { ival{{0, 2}, {0, 2}, 10, 20, true, 0, 0}
1708 , ival{{ 1, 2}, { 1, 2}, 21, 30, true, 1, 1}
1709 , ival{{0, 1 }, {0, 1 }, 31, 35, true, 0, 0}
1713 /* osd states at end */
1714 { make_pair(0, make_pair(PI::UP , 0))
1715 , make_pair(1, make_pair(PI::UP , 0))
1716 , make_pair(2, make_pair(PI::DOWN , 0))
1718 /* acting */ {0, 1 },
1720 /* probe */ {pst(0), pst(1)},
1722 /* blocked_by */ {},
1723 /* pg_down */ false);
1726 TEST_F(PITest, past_intervals_ec_no_subsets) {
1730 { ival{{0, N, 2}, {0, N, 2}, 10, 20, true, 0, 0}
1731 , ival{{N, 1, 2}, {N, 1, 2}, 21, 30, true, 1, 1}
1732 , ival{{0, 1, N}, {0, 1, N}, 31, 35, true, 0, 0}
1736 /* osd states at end */
1737 { make_pair(0, make_pair(PI::UP , 0))
1738 , make_pair(1, make_pair(PI::DOWN , 0))
1739 , make_pair(2, make_pair(PI::UP , 0))
1741 /* acting */ {0, N, 2},
1743 /* probe */ {pst(0, sit(0)), pst(2, sit(2))},
1745 /* blocked_by */ {{1, 0}},
1746 /* pg_down */ true);
1749 TEST_F(PITest, past_intervals_ec_no_subsets2) {
1753 { ival{{N, 1, 2}, {N, 1, 2}, 10, 20, true, 0, 0}
1754 , ival{{0, N, 2}, {0, N, 2}, 21, 30, true, 1, 1}
1755 , ival{{0, 3, N}, {0, 3, N}, 31, 35, true, 0, 0}
1759 /* osd states at end */
1760 { make_pair(0, make_pair(PI::UP , 0))
1761 , make_pair(1, make_pair(PI::DOWN , 0))
1762 , make_pair(2, make_pair(PI::UP , 0))
1763 , make_pair(3, make_pair(PI::UP , 0))
1765 /* acting */ {0, N, 2},
1767 /* probe */ {pst(0, sit(0)), pst(2, sit(2)), pst(3, sit(1))},
1769 /* blocked_by */ {},
1770 /* pg_down */ false);
1773 TEST_F(PITest, past_intervals_rep_lost) {
1775 /* ec_pool */ false,
1777 { ival{{0, 1, 2}, {0, 1, 2}, 10, 20, true, 0, 0}
1778 , ival{{ 1, 2}, { 1, 2}, 21, 30, true, 1, 1}
1779 , ival{{ 2}, { 2}, 31, 35, true, 2, 2}
1780 , ival{{0, 2}, {0, 2}, 36, 50, true, 0, 0}
1784 /* osd states at end */
1785 { make_pair(0, make_pair(PI::UP , 0))
1786 , make_pair(1, make_pair(PI::UP , 0))
1787 , make_pair(2, make_pair(PI::LOST , 55))
1789 /* acting */ {0, 1 },
1791 /* probe */ {pst(0), pst(1)},
1793 /* blocked_by */ {},
1794 /* pg_down */ false);
1797 TEST_F(PITest, past_intervals_ec_lost) {
1801 { ival{{0, N, 2}, {0, N, 2}, 10, 20, true, 0, 0}
1802 , ival{{N, 1, 2}, {N, 1, 2}, 21, 30, true, 1, 1}
1803 , ival{{0, 1, N}, {0, 1, N}, 31, 35, true, 0, 0}
1807 /* osd states at end */
1808 { make_pair(0, make_pair(PI::UP , 0))
1809 , make_pair(1, make_pair(PI::LOST , 36))
1810 , make_pair(2, make_pair(PI::UP , 0))
1812 /* acting */ {0, N, 2},
1814 /* probe */ {pst(0, sit(0)), pst(2, sit(2))},
1816 /* blocked_by */ {},
1817 /* pg_down */ false);
1823 * compile-command: "cd ../.. ;
1824 * make unittest_osd_types ;
1825 * ./unittest_osd_types # --gtest_filter=pg_missing_t.constructor