Skip to content

Commit

Permalink
Merge pull request #23 from ydb-platform/NBS-4414
Browse files Browse the repository at this point in the history
NBS-4414: resync fast path should work even if there are fresh devices; added a ut for the resync with fresh devices case
  • Loading branch information
qkrorlqr authored Dec 31, 2023
2 parents d4a6dca + a0691f6 commit e5aedfa
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,6 @@ void TMirrorPartitionResyncActor::ProcessReadRequestSyncPath(
}
}

if (replicas.size() != Replicas.size()) {
ProcessReadRequestSlowPath(
NActors::IEventHandlePtr(ev.Release()),
range,
ctx);
return;
}
ProcessReadRequestFastPath(ev, std::move(replicas), range, ctx);
}

Expand All @@ -61,6 +54,11 @@ void TMirrorPartitionResyncActor::ProcessReadRequestFastPath(
TBlockRange64 range,
const TActorContext& ctx)
{
LOG_DEBUG(ctx, TBlockStoreComponents::PARTITION,
"[%s] Resync read fast path %s",
PartConfig->GetName().c_str(),
DescribeRange(range).c_str());

TFastPathRecord fastPathRecord{
.Ev{NActors::IEventHandlePtr(ev.Release())},
.BlockRange{range}};
Expand Down Expand Up @@ -101,6 +99,11 @@ void TMirrorPartitionResyncActor::ProcessReadRequestFastPath(
TBlockRange64 range,
const TActorContext& ctx)
{
LOG_DEBUG(ctx, TBlockStoreComponents::PARTITION,
"[%s] Resync read local fast path %s",
PartConfig->GetName().c_str(),
DescribeRange(range).c_str());

auto blockSize = PartConfig->GetBlockSize();
auto msg = ev->Get();
TFastPathRecord fastPathRecord{
Expand Down Expand Up @@ -131,6 +134,11 @@ void TMirrorPartitionResyncActor::ProcessReadRequestSlowPath(
TBlockRange64 range,
const TActorContext& ctx)
{
LOG_DEBUG(ctx, TBlockStoreComponents::PARTITION,
"[%s] Resync read slow path %s",
PartConfig->GetName().c_str(),
DescribeRange(range).c_str());

const auto rangeId = BlockRange2RangeId(range, PartConfig->GetBlockSize());
for (ui32 id = rangeId.first; id <= rangeId.second; ++id) {
const auto blockRange =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ struct TTestEnv

for (ui32 i = TBlockStoreComponents::START; i < TBlockStoreComponents::END; ++i) {
Runtime.SetLogPriority(i, NLog::PRI_INFO);
// Runtime.SetLogPriority(i, NLog::PRI_DEBUG);
Runtime.SetLogPriority(i, NLog::PRI_DEBUG);
}
Runtime.SetLogPriority(TBlockStoreComponents::PARTITION, NLog::PRI_DEBUG);
// Runtime.SetLogPriority(NLog::InvalidComponent, NLog::PRI_DEBUG);
Expand Down Expand Up @@ -1257,7 +1257,7 @@ Y_UNIT_TEST_SUITE(TMirrorPartitionResyncTest)
UNIT_ASSERT_VALUES_EQUAL(3072, resyncIndex);
}

Y_UNIT_TEST(ShouldTreatFreshDevicesProperly)
void DoTestShouldTreatFreshDevicesProperly(bool afterResync)
{
TTestBasicRuntime runtime;
TTestEnv env(runtime, {"vasya#1", "vasya#2"});
Expand All @@ -1272,49 +1272,80 @@ Y_UNIT_TEST_SUITE(TMirrorPartitionResyncTest)
env.WriteReplica(1, range2, 'D');
env.WriteReplica(2, range2, 'D');

env.CatchEvents(TEvNonreplPartitionPrivate::EvResyncNextRange);
env.StartResync();
env.ResyncController.WaitForResyncedRangeCount(5);
UNIT_ASSERT(env.ResyncController.ResyncFinished);

// Trigger sequential reading from different replicas
for (const auto& block: env.ReadMirror(range1)) {
auto read = [&] (TBlockRange64 range) {
return afterResync
? env.ReadMirror(range)
: env.ReadActor(env.ActorId, range);
};

// Read a range which doesn't really require a resync
// Devices in replicas #1 and #2 have different data but those devices
// are fresh so they shouldn't be taken into account
for (const auto& block: read(range1)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'A'), block);
}
for (const auto& block: env.ReadMirror(range1)) {
for (const auto& block: read(range1)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'A'), block);
}
for (const auto& block: env.ReadMirror(range1)) {
for (const auto& block: read(range1)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'A'), block);
}
for (const auto& block: env.ReadMirror(range2)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'D'), block);
}
for (const auto& block: env.ReadMirror(range2)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'D'), block);
}
for (const auto& block: env.ReadMirror(range2)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'D'), block);
}

// Check individual replicas
for (const auto& block: env.ReadReplica(0, range1)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'A'), block);
}
for (const auto& block: env.ReadReplica(1, range1)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'B'), block);
}
for (const auto& block: env.ReadReplica(2, range1)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'B'), block);
// unblock resync
// XXX may trigger immediate resync and not actually test the
// slow path that happens during resync
env.ReleaseEvents();

if (afterResync) {
env.ResyncController.WaitForResyncedRangeCount(5);
UNIT_ASSERT(env.ResyncController.ResyncFinished);
}
for (const auto& block: env.ReadReplica(0, range2)) {

// Trigger sequential reading from different replicas
for (const auto& block: read(range2)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'D'), block);
}
for (const auto& block: env.ReadReplica(1, range2)) {
for (const auto& block: read(range2)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'D'), block);
}
for (const auto& block: env.ReadReplica(2, range2)) {
for (const auto& block: read(range2)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'D'), block);
}

if (afterResync) {
// Check individual replicas
for (const auto& block: env.ReadReplica(0, range1)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'A'), block);
}
for (const auto& block: env.ReadReplica(1, range1)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'B'), block);
}
for (const auto& block: env.ReadReplica(2, range1)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'B'), block);
}
for (const auto& block: env.ReadReplica(0, range2)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'D'), block);
}
for (const auto& block: env.ReadReplica(1, range2)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'D'), block);
}
for (const auto& block: env.ReadReplica(2, range2)) {
UNIT_ASSERT_VALUES_EQUAL(TString(DefaultBlockSize, 'D'), block);
}
}
}

Y_UNIT_TEST(ShouldTreatFreshDevicesProperlyAfterResync)
{
DoTestShouldTreatFreshDevicesProperly(true);
}

Y_UNIT_TEST(ShouldTreatFreshDevicesProperlyDuringResync)
{
DoTestShouldTreatFreshDevicesProperly(false);
}
}

Expand Down

0 comments on commit e5aedfa

Please sign in to comment.