Skip to content

Commit

Permalink
issue-1823: allowing FS size decrease with a Force flag + some cleanup (
Browse files Browse the repository at this point in the history
#1828)

* issue-1823: allowing FS size decrease with a Force flag + some cleanup

* issue-1823: fixed format string

* issue-1823: tablet_ut.cpp - BlockCount can be decreased now
  • Loading branch information
qkrorlqr committed Aug 21, 2024
1 parent b6945f3 commit 6bc430c
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class TAlterFileStoreActor final
const TRequestInfoPtr RequestInfo;
const TString FileSystemId;
const NProto::TFileStorePerformanceProfile PerformanceProfile;
const bool Alter = false;
const bool Alter;
const bool Force;

NKikimrFileStore::TConfig Config;

Expand Down Expand Up @@ -81,6 +82,7 @@ TAlterFileStoreActor::TAlterFileStoreActor(
, RequestInfo(std::move(requestInfo))
, FileSystemId(request.GetFileSystemId())
, Alter(true)
, Force(false)
{
Config.SetCloudId(request.GetCloudId());
Config.SetFolderId(request.GetFolderId());
Expand All @@ -96,6 +98,8 @@ TAlterFileStoreActor::TAlterFileStoreActor(
, RequestInfo(std::move(requestInfo))
, FileSystemId(request.GetFileSystemId())
, PerformanceProfile(request.GetPerformanceProfile())
, Alter(false)
, Force(request.GetForce())
{
Config.SetBlocksCount(request.GetBlocksCount());
Config.SetVersion(request.GetConfigVersion());
Expand Down Expand Up @@ -137,7 +141,7 @@ void TAlterFileStoreActor::HandleDescribeFileStoreResponse(
const bool allocateMixed0 = thirdChannelDataKind == EChannelDataKind::Mixed0;

if (!Alter) {
if (config.GetBlocksCount() > Config.GetBlocksCount()) {
if (config.GetBlocksCount() > Config.GetBlocksCount() && !Force) {
ReplyAndDie(
ctx,
MakeError(E_ARGUMENT, "Cannot decrease filestore size"));
Expand Down
197 changes: 140 additions & 57 deletions cloud/filestore/libs/storage/service/service_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,28 +60,36 @@ Y_UNIT_TEST_SUITE(TStorageServiceTest)
service.CreateFileStore("test", 1'000);

auto response = service.GetFileStoreInfo("test")->Record.GetFileStore();
UNIT_ASSERT_VALUES_EQUAL(response.GetFileSystemId(), "test");
UNIT_ASSERT_VALUES_EQUAL(response.GetCloudId(), "test");
UNIT_ASSERT_VALUES_EQUAL(response.GetFolderId(), "test");
UNIT_ASSERT_VALUES_EQUAL(response.GetBlocksCount(), 1'000);
UNIT_ASSERT_VALUES_EQUAL(response.GetBlockSize(), DefaultBlockSize);
UNIT_ASSERT_VALUES_EQUAL(response.GetConfigVersion(), 1);
UNIT_ASSERT_VALUES_EQUAL("test", response.GetFileSystemId());
UNIT_ASSERT_VALUES_EQUAL("test", response.GetCloudId());
UNIT_ASSERT_VALUES_EQUAL("test", response.GetFolderId());
UNIT_ASSERT_VALUES_EQUAL(1'000, response.GetBlocksCount());
UNIT_ASSERT_VALUES_EQUAL(DefaultBlockSize, response.GetBlockSize());
UNIT_ASSERT_VALUES_EQUAL(1, response.GetConfigVersion());

const auto& profile = response.GetPerformanceProfile();
UNIT_ASSERT(!profile.GetThrottlingEnabled());
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxReadIops(), 100);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxWriteIops(), 300);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxReadBandwidth(), 30_MB);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxWriteBandwidth(), 30_MB);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxPostponedWeight(), 128_MB);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxPostponedTime(), TDuration::Seconds(20).MilliSeconds());
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxPostponedCount(), 1024);
UNIT_ASSERT_VALUES_EQUAL(profile.GetBoostTime(), TDuration::Minutes(30).MilliSeconds());
UNIT_ASSERT_VALUES_EQUAL(profile.GetBoostRefillTime(), TDuration::Hours(12).MilliSeconds());
UNIT_ASSERT_VALUES_EQUAL(profile.GetBoostPercentage(), 400);
UNIT_ASSERT_VALUES_EQUAL(profile.GetBurstPercentage(), 10);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxWriteCostMultiplier(), 20);
UNIT_ASSERT_VALUES_EQUAL(profile.GetDefaultPostponedRequestWeight(), 4_KB);
UNIT_ASSERT_VALUES_EQUAL(100, profile.GetMaxReadIops());
UNIT_ASSERT_VALUES_EQUAL(300, profile.GetMaxWriteIops());
UNIT_ASSERT_VALUES_EQUAL(30_MB, profile.GetMaxReadBandwidth());
UNIT_ASSERT_VALUES_EQUAL(30_MB, profile.GetMaxWriteBandwidth());
UNIT_ASSERT_VALUES_EQUAL(128_MB, profile.GetMaxPostponedWeight());
UNIT_ASSERT_VALUES_EQUAL(
TDuration::Seconds(20).MilliSeconds(),
profile.GetMaxPostponedTime());
UNIT_ASSERT_VALUES_EQUAL(1024, profile.GetMaxPostponedCount());
UNIT_ASSERT_VALUES_EQUAL(
TDuration::Minutes(30).MilliSeconds(),
profile.GetBoostTime());
UNIT_ASSERT_VALUES_EQUAL(
TDuration::Hours(12).MilliSeconds(),
profile.GetBoostRefillTime());
UNIT_ASSERT_VALUES_EQUAL(400, profile.GetBoostPercentage());
UNIT_ASSERT_VALUES_EQUAL(10, profile.GetBurstPercentage());
UNIT_ASSERT_VALUES_EQUAL(20, profile.GetMaxWriteCostMultiplier());
UNIT_ASSERT_VALUES_EQUAL(
4_KB,
profile.GetDefaultPostponedRequestWeight());

service.DestroyFileStore("test");
service.AssertGetFileStoreInfoFailed("test");
Expand All @@ -99,28 +107,36 @@ Y_UNIT_TEST_SUITE(TStorageServiceTest)
service.AlterFileStore("test", "yyyy", "zzzz");

auto response = service.GetFileStoreInfo("test")->Record.GetFileStore();
UNIT_ASSERT_VALUES_EQUAL(response.GetFileSystemId(), "test");
UNIT_ASSERT_VALUES_EQUAL(response.GetCloudId(), "yyyy");
UNIT_ASSERT_VALUES_EQUAL(response.GetFolderId(), "zzzz");
UNIT_ASSERT_VALUES_EQUAL(response.GetBlocksCount(), 1'000);
UNIT_ASSERT_VALUES_EQUAL(response.GetBlockSize(), DefaultBlockSize);
UNIT_ASSERT_VALUES_EQUAL(response.GetConfigVersion(), 2);
UNIT_ASSERT_VALUES_EQUAL("test", response.GetFileSystemId());
UNIT_ASSERT_VALUES_EQUAL("yyyy", response.GetCloudId());
UNIT_ASSERT_VALUES_EQUAL("zzzz", response.GetFolderId());
UNIT_ASSERT_VALUES_EQUAL(1'000, response.GetBlocksCount());
UNIT_ASSERT_VALUES_EQUAL(DefaultBlockSize, response.GetBlockSize());
UNIT_ASSERT_VALUES_EQUAL(2, response.GetConfigVersion());

const auto& profile = response.GetPerformanceProfile();
UNIT_ASSERT(!profile.GetThrottlingEnabled());
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxReadIops(), 100);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxWriteIops(), 300);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxReadBandwidth(), 30_MB);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxWriteBandwidth(), 30_MB);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxPostponedWeight(), 128_MB);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxPostponedTime(), TDuration::Seconds(20).MilliSeconds());
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxPostponedCount(), 1024);
UNIT_ASSERT_VALUES_EQUAL(profile.GetBoostTime(), TDuration::Minutes(30).MilliSeconds());
UNIT_ASSERT_VALUES_EQUAL(profile.GetBoostRefillTime(), TDuration::Hours(12).MilliSeconds());
UNIT_ASSERT_VALUES_EQUAL(profile.GetBoostPercentage(), 400);
UNIT_ASSERT_VALUES_EQUAL(profile.GetBurstPercentage(), 10);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxWriteCostMultiplier(), 20);
UNIT_ASSERT_VALUES_EQUAL(profile.GetDefaultPostponedRequestWeight(), 4_KB);
UNIT_ASSERT_VALUES_EQUAL(100, profile.GetMaxReadIops());
UNIT_ASSERT_VALUES_EQUAL(300, profile.GetMaxWriteIops());
UNIT_ASSERT_VALUES_EQUAL(30_MB, profile.GetMaxReadBandwidth());
UNIT_ASSERT_VALUES_EQUAL(30_MB, profile.GetMaxWriteBandwidth());
UNIT_ASSERT_VALUES_EQUAL(128_MB, profile.GetMaxPostponedWeight());
UNIT_ASSERT_VALUES_EQUAL(
TDuration::Seconds(20).MilliSeconds(),
profile.GetMaxPostponedTime());
UNIT_ASSERT_VALUES_EQUAL(1024, profile.GetMaxPostponedCount());
UNIT_ASSERT_VALUES_EQUAL(
TDuration::Minutes(30).MilliSeconds(),
profile.GetBoostTime());
UNIT_ASSERT_VALUES_EQUAL(
TDuration::Hours(12).MilliSeconds(),
profile.GetBoostRefillTime());
UNIT_ASSERT_VALUES_EQUAL(400, profile.GetBoostPercentage());
UNIT_ASSERT_VALUES_EQUAL(10, profile.GetBurstPercentage());
UNIT_ASSERT_VALUES_EQUAL(20, profile.GetMaxWriteCostMultiplier());
UNIT_ASSERT_VALUES_EQUAL(
4_KB,
profile.GetDefaultPostponedRequestWeight());
}

Y_UNIT_TEST(ShouldResizeFileStore)
Expand All @@ -135,33 +151,100 @@ Y_UNIT_TEST_SUITE(TStorageServiceTest)
service.ResizeFileStore("test", 100'000'000);

auto response = service.GetFileStoreInfo("test")->Record.GetFileStore();
UNIT_ASSERT_VALUES_EQUAL(response.GetFileSystemId(), "test");
UNIT_ASSERT_VALUES_EQUAL(response.GetCloudId(), "test");
UNIT_ASSERT_VALUES_EQUAL(response.GetFolderId(), "test");
UNIT_ASSERT_VALUES_EQUAL(response.GetBlocksCount(), 100'000'000);
UNIT_ASSERT_VALUES_EQUAL(response.GetBlockSize(), DefaultBlockSize);
UNIT_ASSERT_VALUES_EQUAL(response.GetConfigVersion(), 2);
UNIT_ASSERT_VALUES_EQUAL("test", response.GetFileSystemId());
UNIT_ASSERT_VALUES_EQUAL("test", response.GetCloudId());
UNIT_ASSERT_VALUES_EQUAL("test", response.GetFolderId());
UNIT_ASSERT_VALUES_EQUAL(100'000'000, response.GetBlocksCount());
UNIT_ASSERT_VALUES_EQUAL(DefaultBlockSize, response.GetBlockSize());
UNIT_ASSERT_VALUES_EQUAL(2, response.GetConfigVersion());

const auto& profile = response.GetPerformanceProfile();
UNIT_ASSERT(!profile.GetThrottlingEnabled());
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxReadIops(), 200);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxWriteIops(), 600);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxReadBandwidth(), 60_MB);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxWriteBandwidth(), 60_MB);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxPostponedWeight(), 128_MB);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxPostponedTime(), TDuration::Seconds(20).MilliSeconds());
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxPostponedCount(), 1024);
UNIT_ASSERT_VALUES_EQUAL(profile.GetBoostTime(), TDuration::Minutes(30).MilliSeconds());
UNIT_ASSERT_VALUES_EQUAL(profile.GetBoostRefillTime(), TDuration::Hours(12).MilliSeconds());
UNIT_ASSERT_VALUES_EQUAL(profile.GetBoostPercentage(), 200);
UNIT_ASSERT_VALUES_EQUAL(profile.GetBurstPercentage(), 10);
UNIT_ASSERT_VALUES_EQUAL(profile.GetMaxWriteCostMultiplier(), 20);
UNIT_ASSERT_VALUES_EQUAL(profile.GetDefaultPostponedRequestWeight(), 4_KB);
UNIT_ASSERT_VALUES_EQUAL(200, profile.GetMaxReadIops());
UNIT_ASSERT_VALUES_EQUAL(600, profile.GetMaxWriteIops());
UNIT_ASSERT_VALUES_EQUAL(60_MB, profile.GetMaxReadBandwidth());
UNIT_ASSERT_VALUES_EQUAL(60_MB, profile.GetMaxWriteBandwidth());
UNIT_ASSERT_VALUES_EQUAL(128_MB, profile.GetMaxPostponedWeight());
UNIT_ASSERT_VALUES_EQUAL(
TDuration::Seconds(20).MilliSeconds(),
profile.GetMaxPostponedTime());
UNIT_ASSERT_VALUES_EQUAL(1024, profile.GetMaxPostponedCount());
UNIT_ASSERT_VALUES_EQUAL(
TDuration::Minutes(30).MilliSeconds(),
profile.GetBoostTime());
UNIT_ASSERT_VALUES_EQUAL(
TDuration::Hours(12).MilliSeconds(),
profile.GetBoostRefillTime());
UNIT_ASSERT_VALUES_EQUAL(200, profile.GetBoostPercentage());
UNIT_ASSERT_VALUES_EQUAL(10, profile.GetBurstPercentage());
UNIT_ASSERT_VALUES_EQUAL(20, profile.GetMaxWriteCostMultiplier());
UNIT_ASSERT_VALUES_EQUAL(
4_KB,
profile.GetDefaultPostponedRequestWeight());

service.AssertResizeFileStoreFailed("test", 1'000);
service.AssertResizeFileStoreFailed("test", 0);
}

Y_UNIT_TEST(ShouldDownsizeFileStore)
{
TTestEnv env;
env.CreateSubDomain("nfs");

ui32 nodeIdx = env.CreateNode("nfs");

TServiceClient service(env.GetRuntime(), nodeIdx);
service.CreateFileStore("test", 100'000'000);

{
service.SendResizeFileStoreRequest("test", 10'000'000);
auto response = service.RecvResizeFileStoreResponse();
UNIT_ASSERT_VALUES_EQUAL_C(
E_ARGUMENT,
response->GetStatus(),
response->GetErrorReason());

service.SendResizeFileStoreRequest("test", 10'000'000, true);
response = service.RecvResizeFileStoreResponse();
UNIT_ASSERT_VALUES_EQUAL_C(
S_OK,
response->GetStatus(),
response->GetErrorReason());
}

auto response = service.GetFileStoreInfo("test")->Record.GetFileStore();
UNIT_ASSERT_VALUES_EQUAL("test", response.GetFileSystemId());
UNIT_ASSERT_VALUES_EQUAL("test", response.GetCloudId());
UNIT_ASSERT_VALUES_EQUAL("test", response.GetFolderId());
UNIT_ASSERT_VALUES_EQUAL(100'000'00, response.GetBlocksCount());
UNIT_ASSERT_VALUES_EQUAL(DefaultBlockSize, response.GetBlockSize());
UNIT_ASSERT_VALUES_EQUAL(2, response.GetConfigVersion());

const auto& profile = response.GetPerformanceProfile();
UNIT_ASSERT(!profile.GetThrottlingEnabled());
UNIT_ASSERT_VALUES_EQUAL(200, profile.GetMaxReadIops());
UNIT_ASSERT_VALUES_EQUAL(600, profile.GetMaxWriteIops());
UNIT_ASSERT_VALUES_EQUAL(60_MB, profile.GetMaxReadBandwidth());
UNIT_ASSERT_VALUES_EQUAL(60_MB, profile.GetMaxWriteBandwidth());
UNIT_ASSERT_VALUES_EQUAL(128_MB, profile.GetMaxPostponedWeight());
UNIT_ASSERT_VALUES_EQUAL(
TDuration::Seconds(20).MilliSeconds(),
profile.GetMaxPostponedTime());
UNIT_ASSERT_VALUES_EQUAL(1024, profile.GetMaxPostponedCount());
UNIT_ASSERT_VALUES_EQUAL(
TDuration::Minutes(30).MilliSeconds(),
profile.GetBoostTime());
UNIT_ASSERT_VALUES_EQUAL(
TDuration::Hours(12).MilliSeconds(),
profile.GetBoostRefillTime());
UNIT_ASSERT_VALUES_EQUAL(400, profile.GetBoostPercentage());
UNIT_ASSERT_VALUES_EQUAL(10, profile.GetBurstPercentage());
UNIT_ASSERT_VALUES_EQUAL(20, profile.GetMaxWriteCostMultiplier());
UNIT_ASSERT_VALUES_EQUAL(
4_KB,
profile.GetDefaultPostponedRequestWeight());
}

Y_UNIT_TEST(ShouldResizeFileStoreWithCustomPerformanceProfile)
{
TTestEnv env;
Expand Down
55 changes: 28 additions & 27 deletions cloud/filestore/libs/storage/tablet/tablet_actor_updateconfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,6 @@ TString ValidateUpdateConfigRequest(
<< ")";
}

const ui64 oldBlockCount = oldConfig.GetBlocksCount();
const ui64 newBlockCount = newConfig.GetBlocksCount();

if (oldBlockCount > newBlockCount) {
return TStringBuilder()
<< "it's not allowed to decrease blockCount"
<< " (old: " << oldBlockCount
<< ", new: " << newBlockCount
<< ")";
}

const ui32 oldChannelCount = oldConfig.ExplicitChannelProfilesSize();
const ui32 newChannelCount = newConfig.ExplicitChannelProfilesSize();

Expand All @@ -53,28 +42,28 @@ TString ValidateUpdateConfigRequest(
}

using TChannelDiff = std::tuple<ui32, EChannelDataKind, EChannelDataKind>;
TVector<TChannelDiff> ChangedChannels;
TVector<TChannelDiff> changedChannels;

for (ui32 channel = 0; channel < oldChannelCount; ++channel) {
for (ui32 c = 0; c < oldChannelCount; ++c) {
const auto oldDataKind = static_cast<EChannelDataKind>(oldConfig
.GetExplicitChannelProfiles(channel)
.GetExplicitChannelProfiles(c)
.GetDataKind());

const auto newDataKind = static_cast<EChannelDataKind>(newConfig
.GetExplicitChannelProfiles(channel)
.GetExplicitChannelProfiles(c)
.GetDataKind());

if (oldDataKind != newDataKind) {
ChangedChannels.emplace_back(channel, oldDataKind, newDataKind);
changedChannels.emplace_back(c, oldDataKind, newDataKind);
}
}

if (ChangedChannels) {
if (changedChannels) {
auto error = TStringBuilder()
<< "it's not allowed to change dataKind of existing channels [";

for (const auto& [channel, oldDataKind, newDataKind]: ChangedChannels) {
error << " (channel: " << channel
for (const auto& [c, oldDataKind, newDataKind]: changedChannels) {
error << " (channel: " << c
<< ", oldDataKind: " << ToString(oldDataKind)
<< ", newDataKind: " << ToString(newDataKind)
<< ") ";
Expand All @@ -88,24 +77,24 @@ TString ValidateUpdateConfigRequest(
// Resizing tablet: check new channels dataKind.

using TChannelDesc = std::tuple<ui32, EChannelDataKind>;
TVector<TChannelDesc> BadNewChannels;
TVector<TChannelDesc> badNewChannels;

for (ui32 channel = oldChannelCount; channel < newChannelCount; ++channel) {
for (ui32 c = oldChannelCount; c < newChannelCount; ++c) {
const auto dataKind = static_cast<EChannelDataKind>(newConfig
.GetExplicitChannelProfiles(channel)
.GetExplicitChannelProfiles(c)
.GetDataKind());

if (dataKind != EChannelDataKind::Mixed) {
BadNewChannels.emplace_back(channel, dataKind);
badNewChannels.emplace_back(c, dataKind);
}
}

if (BadNewChannels) {
if (badNewChannels) {
auto error = TStringBuilder()
<< "it's allowed to add new channels with Mixed dataKind only [";

for (const auto& [channel, dataKind]: BadNewChannels) {
error << " (channel: " << channel
for (const auto& [c, dataKind]: badNewChannels) {
error << " (channel: " << c
<< ", dataKind: " << ToString(dataKind)
<< ") ";
}
Expand Down Expand Up @@ -164,7 +153,7 @@ void TIndexTabletActor::HandleUpdateConfig(
// Config update occured due to alter/resize.
if (auto error = ValidateUpdateConfigRequest(oldConfig, newConfig)) {
LOG_ERROR(ctx, TFileStoreComponents::TABLET,
"%s Failed to update config [txId: %d]: %s",
"%s Failed to update config [txId: %lu]: %s",
LogTag.c_str(),
txId,
error.c_str());
Expand All @@ -183,6 +172,18 @@ void TIndexTabletActor::HandleUpdateConfig(
return;
}

const ui64 oldBlockCount = oldConfig.GetBlocksCount();
const ui64 newBlockCount = newConfig.GetBlocksCount();

if (oldBlockCount > newBlockCount) {
LOG_WARN(ctx, TFileStoreComponents::TABLET,
"%s BlocksCount will be decreased %lu -> %lu [txId: %lu]",
LogTag.c_str(),
oldBlockCount,
newBlockCount,
txId);
}

ExecuteTx<TUpdateConfig>(
ctx,
std::move(requestInfo),
Expand Down
Loading

0 comments on commit 6bc430c

Please sign in to comment.