osd/osd_types: add pg_t::is_merge() method

This checks if we are a merge *source*, and if so, who the parent (target)
will be.

Signed-off-by: Sage Weil <sage@redhat.com>
This commit is contained in:
Sage Weil 2018-02-15 21:13:27 -06:00
parent 71f4691909
commit 0540492461
3 changed files with 54 additions and 0 deletions

View File

@ -558,6 +558,23 @@ unsigned pg_t::get_split_bits(unsigned pg_num) const {
return p - 1;
}
bool pg_t::is_merge(unsigned old_pg_num, unsigned new_pg_num,
pg_t *parent) const
{
if (m_seed < old_pg_num &&
m_seed >= new_pg_num) {
if (parent) {
pg_t t = *this;
while (t.m_seed >= new_pg_num) {
t = t.get_parent();
}
*parent = t;
}
return true;
}
return false;
}
pg_t pg_t::get_parent() const
{
unsigned bits = cbits(m_seed);

View File

@ -412,6 +412,8 @@ struct pg_t {
bool is_split(unsigned old_pg_num, unsigned new_pg_num, set<pg_t> *pchildren) const;
bool is_merge(unsigned old_pg_num, unsigned new_pg_num, pg_t *parent) const;
/**
* Returns b such that for all object o:
* ~((~0)<<b) & o.hash) == 0 iff o is in the pg for *this
@ -539,6 +541,15 @@ struct spg_t {
}
return is_split;
}
bool is_merge(unsigned old_pg_num, unsigned new_pg_num, spg_t *parent) const {
spg_t out = *this;
bool r = pgid.is_merge(old_pg_num, new_pg_num, &out.pgid);
if (r && parent) {
*parent = out;
}
return r;
}
bool is_no_shard() const {
return shard == shard_id_t::NO_SHARD;
}

View File

@ -668,6 +668,32 @@ TEST(pg_t, split)
}
TEST(pg_t, merge)
{
pg_t pgid, parent;
bool b;
pgid = pg_t(7, 0);
b = pgid.is_merge(8, 7, &parent);
ASSERT_TRUE(b);
ASSERT_EQ(parent, pg_t(3, 0));
b = pgid.is_merge(8, 5, &parent);
ASSERT_TRUE(b);
ASSERT_EQ(parent, pg_t(3, 0));
b = pgid.is_merge(8, 4, &parent);
ASSERT_TRUE(b);
ASSERT_EQ(parent, pg_t(3, 0));
b = pgid.is_merge(8, 3, &parent);
ASSERT_TRUE(b);
ASSERT_EQ(parent, pg_t(1, 0));
b = pgid.is_merge(9, 8, &parent);
ASSERT_FALSE(b);
}
TEST(pg_missing_t, constructor)
{
pg_missing_t missing;