Skip to content

Commit

Permalink
NBS-4827 extract TNonreplicatedPartitionMigrationCommonActor (#194)
Browse files Browse the repository at this point in the history
* NBS-4827 extract TNonreplicatedPartitionMigrationCommonActor

* NBS-4827 better isolate classes

* NBS-4827 comments

* NBS-4827 fix review issues
  • Loading branch information
drbasic authored Jan 30, 2024
1 parent 9a7b260 commit 024c54e
Show file tree
Hide file tree
Showing 19 changed files with 945 additions and 939 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "migration_timeout_calculator.h"

#include <cloud/blockstore/libs/storage/core/config.h>
#include <cloud/blockstore/libs/storage/partition_nonrepl/config.h>

namespace NCloud::NBlockStore::NStorage {

///////////////////////////////////////////////////////////////////////////////

TMigrationTimeoutCalculator::TMigrationTimeoutCalculator(
TStorageConfigPtr config,
TNonreplicatedPartitionConfigPtr partitionConfig)
: Config(std::move(config))
, PartitionConfig(std::move(partitionConfig))
{}

TDuration TMigrationTimeoutCalculator::CalculateTimeout(
TBlockRange64 nextProcessingRange) const
{
const ui32 maxMigrationBandwidthMiBs = Config->GetMaxMigrationBandwidth();
const ui32 expectedDiskAgentSize = Config->GetExpectedDiskAgentSize();

// migration range is 4_MB
const auto migrationFactorPerAgent = maxMigrationBandwidthMiBs / 4;

if (PartitionConfig->GetUseSimpleMigrationBandwidthLimiter()) {
return TDuration::Seconds(1) / migrationFactorPerAgent;
}

const auto& sourceDevices = PartitionConfig->GetDevices();
const auto requests =
PartitionConfig->ToDeviceRequests(nextProcessingRange);

ui32 agentDeviceCount = 0;
if (!requests.empty()) {
agentDeviceCount = CountIf(
sourceDevices,
[&](const auto& d)
{ return d.GetAgentId() == requests.front().Device.GetAgentId(); });
}

const auto factor =
Max(migrationFactorPerAgent * agentDeviceCount / expectedDiskAgentSize,
1U);

return TDuration::Seconds(1) / factor;
}

} // namespace NCloud::NBlockStore::NStorage
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include <cloud/blockstore/libs/common/block_range.h>
#include <cloud/blockstore/libs/storage/core/public.h>
#include <cloud/blockstore/libs/storage/partition_nonrepl/public.h>

#include <util/datetime/base.h>

namespace NCloud::NBlockStore::NStorage {

// Calculates the time during which a 4MB block should migrate.
class TMigrationTimeoutCalculator
{
private:
const TStorageConfigPtr Config;
TNonreplicatedPartitionConfigPtr PartitionConfig;

public:
TMigrationTimeoutCalculator(
TStorageConfigPtr config,
TNonreplicatedPartitionConfigPtr partitionConfig);

[[nodiscard]] TDuration CalculateTimeout(
TBlockRange64 nextProcessingRange) const;
};

} // namespace NCloud::NBlockStore::NStorage
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#include "migration_timeout_calculator.h"

#include <cloud/blockstore/config/storage.pb.h>
#include <cloud/blockstore/libs/storage/core/config.h>
#include <cloud/blockstore/libs/storage/partition_nonrepl/config.h>

#include <library/cpp/testing/unittest/registar.h>

namespace NCloud::NBlockStore::NStorage {

////////////////////////////////////////////////////////////////////////////////

namespace {

TDevices MakeDevices()
{
TDevices result;
{
auto* device = result.Add();
device->SetAgentId("Agent#1");
device->SetBlocksCount(1024);
device->SetDeviceUUID("1_1");
}
{
auto* device = result.Add();
device->SetAgentId("Agent#1");
device->SetBlocksCount(1024);
device->SetDeviceUUID("1_2");
}
{
auto* device = result.Add();
device->SetAgentId("Agent#2");
device->SetBlocksCount(1024);
device->SetDeviceUUID("2_1");
}
{
auto* device = result.Add();
device->SetAgentId("Agent#1");
device->SetBlocksCount(1024);
device->SetDeviceUUID("1_3");
}
return result;
}

TStorageConfigPtr MakeStorageConfig(ui32 expectedDiskAgentSize)
{
NProto::TStorageServiceConfig storageConfig;
storageConfig.SetMaxMigrationBandwidth(16);
storageConfig.SetExpectedDiskAgentSize(expectedDiskAgentSize);

return std::make_shared<TStorageConfig>(std::move(storageConfig), nullptr);
}

TNonreplicatedPartitionConfigPtr MakePartitionConfig(
TDevices devices,
bool useSimpleMigrationBandwidthLimiter)
{
return std::make_shared<TNonreplicatedPartitionConfig>(
devices,
NProto::VOLUME_IO_OK,
"vol0",
4_KB,
TNonreplicatedPartitionConfig::TVolumeInfo{
Now(),
// only SSD/HDD distinction matters
NProto::STORAGE_MEDIA_SSD_NONREPLICATED},
NActors::TActorId(),
false, // muteIOErrors
false, // markBlocksUsed
THashSet<TString>(), // freshDeviceIds
TDuration::Zero(), // maxTimedOutDeviceStateDuration
false, // maxTimedOutDeviceStateDurationOverridden
useSimpleMigrationBandwidthLimiter);
}

} // namespace

Y_UNIT_TEST_SUITE(TMigrationCalculatorTest)
{
Y_UNIT_TEST(ShouldCalculateMigrationTimeout)
{
TMigrationTimeoutCalculator timeoutCalculator(
MakeStorageConfig(4),
MakePartitionConfig(MakeDevices(), false));

// Devices #1, #2, #4 belong to Agent#1, device #3 belong to Agent#2.
// Therefore, we expect a timeout of 3 times less for 1,2,4 devices than
// for the 3rd device.

UNIT_ASSERT_VALUES_EQUAL(
TDuration::Seconds(1) / 3,
timeoutCalculator.CalculateTimeout(
TBlockRange64::WithLength(1024 * 0, 1024)));

UNIT_ASSERT_VALUES_EQUAL(
TDuration::Seconds(1) / 3,
timeoutCalculator.CalculateTimeout(
TBlockRange64::WithLength(1024 * 1, 1024)));

//
UNIT_ASSERT_VALUES_EQUAL(
TDuration::Seconds(1),
timeoutCalculator.CalculateTimeout(
TBlockRange64::WithLength(1024 * 2, 1024)));

UNIT_ASSERT_VALUES_EQUAL(
TDuration::Seconds(1) / 3,
timeoutCalculator.CalculateTimeout(
TBlockRange64::WithLength(1024 * 3, 1024)));
}

Y_UNIT_TEST(ShouldCalculateMigrationTimeoutWithSimpleLimiter)
{
TMigrationTimeoutCalculator timeoutCalculator(
MakeStorageConfig(100500),
MakePartitionConfig(MakeDevices(), true));

// When UseSimpleMigrationBandwidthLimiter enabled we expect the same
// timeout for all devices. This timeout does not depend on the expected
// number of devices on the agent (ExpectedDiskAgentSize).

UNIT_ASSERT_VALUES_EQUAL(
TDuration::Seconds(1) / 4,
timeoutCalculator.CalculateTimeout(
TBlockRange64::WithLength(1024 * 0, 1024)));

UNIT_ASSERT_VALUES_EQUAL(
TDuration::Seconds(1) / 4,
timeoutCalculator.CalculateTimeout(
TBlockRange64::WithLength(1024 * 1, 1024)));

UNIT_ASSERT_VALUES_EQUAL(
TDuration::Seconds(1) / 4,
timeoutCalculator.CalculateTimeout(
TBlockRange64::WithLength(1024 * 2, 1024)));

UNIT_ASSERT_VALUES_EQUAL(
TDuration::Seconds(1) / 4,
timeoutCalculator.CalculateTimeout(
TBlockRange64::WithLength(1024 * 3, 1024)));
}
}

} // namespace NCloud::NBlockStore::NStorage
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ SRCS(

PEERDIR(
cloud/blockstore/libs/common

cloud/storage/core/libs/common
)

Expand Down
Loading

0 comments on commit 024c54e

Please sign in to comment.