tablets: Include pending replica in get_shard()

We need to move get_shard() from tablet_info to tablet_map in order to
have access to transition_info.
This commit is contained in:
Tomasz Grabiec
2023-05-09 11:43:57 +02:00
parent e8dd5e34c3
commit e44e6033d8
3 changed files with 74 additions and 9 deletions

View File

@@ -105,6 +105,23 @@ void tablet_map::set_tablet_transition_info(tablet_id id, tablet_transition_info
_transitions.insert_or_assign(id, std::move(info));
}
std::optional<shard_id> tablet_map::get_shard(tablet_id tid, host_id host) const {
auto&& info = get_tablet_info(tid);
for (auto&& r : info.replicas) {
if (r.host == host) {
return r.shard;
}
}
auto tinfo = get_tablet_transition_info(tid);
if (tinfo && tinfo->pending_replica.host == host) {
return tinfo->pending_replica.shard;
}
return std::nullopt;
}
future<> tablet_map::clear_gently() {
return utils::clear_gently(_tablets);
}

View File

@@ -52,15 +52,6 @@ using tablet_replica_set = utils::small_vector<tablet_replica, 3>;
struct tablet_info {
tablet_replica_set replicas;
std::optional<shard_id> get_shard(host_id host) const {
for (auto&& r : replicas) {
if (r.host == host) {
return r.shard;
}
}
return std::nullopt;
}
bool operator==(const tablet_info&) const = default;
};
@@ -148,6 +139,12 @@ public:
return tablet_id(size_t(t) + 1);
}
/// Returns shard id which is a replica for a given tablet on a given host.
/// If there is no replica on a given host, returns nullopt.
/// If the topology is transitional, also considers the new replica set.
/// The old replica set is preferred in case of ambiguity.
std::optional<shard_id> get_shard(tablet_id, host_id) const;
const tablet_container& tablets() const {
return _tablets;
}

View File

@@ -212,6 +212,57 @@ SEASTAR_TEST_CASE(test_tablet_metadata_persistence) {
}, tablet_cql_test_config());
}
SEASTAR_TEST_CASE(test_get_shard) {
return do_with_cql_env_thread([] (cql_test_env& e) {
auto h1 = host_id(utils::UUID_gen::get_time_UUID());
auto h2 = host_id(utils::UUID_gen::get_time_UUID());
auto h3 = host_id(utils::UUID_gen::get_time_UUID());
auto table1 = table_id(utils::UUID_gen::get_time_UUID());
tablet_metadata tm;
tablet_id tid;
tablet_id tid1;
{
tablet_map tmap(2);
tid = tmap.first_tablet();
tmap.set_tablet(tid, tablet_info {
tablet_replica_set {
tablet_replica {h1, 0},
tablet_replica {h3, 5},
}
});
tid1 = *tmap.next_tablet(tid);
tmap.set_tablet(tid1, tablet_info {
tablet_replica_set {
tablet_replica {h1, 2},
tablet_replica {h3, 1},
}
});
tmap.set_tablet_transition_info(tid, tablet_transition_info {
tablet_replica_set {
tablet_replica {h1, 0},
tablet_replica {h2, 3},
},
tablet_replica {h2, 3}
});
tm.set_tablet_map(table1, std::move(tmap));
}
auto&& tmap = tm.get_tablet_map(table1);
BOOST_REQUIRE_EQUAL(tmap.get_shard(tid1, h1), std::make_optional(shard_id(2)));
BOOST_REQUIRE(!tmap.get_shard(tid1, h2));
BOOST_REQUIRE_EQUAL(tmap.get_shard(tid1, h3), std::make_optional(shard_id(1)));
BOOST_REQUIRE_EQUAL(tmap.get_shard(tid, h1), std::make_optional(shard_id(0)));
BOOST_REQUIRE_EQUAL(tmap.get_shard(tid, h2), std::make_optional(shard_id(3)));
BOOST_REQUIRE_EQUAL(tmap.get_shard(tid, h3), std::make_optional(shard_id(5)));
}, tablet_cql_test_config());
}
SEASTAR_TEST_CASE(test_large_tablet_metadata) {
return do_with_cql_env_thread([] (cql_test_env& e) {
tablet_metadata tm;