@@ -130,6 +130,7 @@ constexpr const char* EntireDatabaseTag = "entire_database";
130
130
131
131
NLs::TCheckFunc LsCheckDiskQuotaExceeded (
132
132
const TMap<TString, EDiskUsageStatus>& expectedExceeders,
133
+ bool enableSeparateQuotasFeatureFlag,
133
134
const TString& debugHint = " "
134
135
) {
135
136
return [=] (const NKikimrScheme::TEvDescribeSchemeResult& record) {
@@ -166,8 +167,19 @@ NLs::TCheckFunc LsCheckDiskQuotaExceeded(
166
167
receivedQuotas.data_size_soft_quota ()
167
168
}
168
169
);
169
-
170
+
170
171
TMap<TString, EDiskUsageStatus> exceeders = CheckStoragePoolsQuotas (parsedUsage, parsedQuotas);
172
+ if (enableSeparateQuotasFeatureFlag) {
173
+ // ignore the status of the overall quota
174
+ exceeders.erase (EntireDatabaseTag);
175
+ } else {
176
+ // ignore the statuses of the separate storage pool quotas
177
+ TMap<TString, EDiskUsageStatus> onlyOverallStatus;
178
+ if (auto * overallStatus = exceeders.FindPtr (EntireDatabaseTag)) {
179
+ onlyOverallStatus.emplace (EntireDatabaseTag, *overallStatus);
180
+ }
181
+ std::swap (exceeders, onlyOverallStatus);
182
+ }
171
183
UNIT_ASSERT_VALUES_EQUAL_C (exceeders, expectedExceeders,
172
184
debugHint << " , subdomain's disk space usage:\n " << desc.GetDiskSpaceUsage ().DebugString ()
173
185
);
@@ -181,9 +193,9 @@ void CheckQuotaExceedance(TTestActorRuntime& runtime,
181
193
bool expectExceeded,
182
194
const TString& debugHint = " "
183
195
) {
184
- TestDescribeResult (DescribePath (runtime, schemeShard, pathToSubdomain),
185
- { LsCheckDiskQuotaExceeded (expectExceeded, debugHint) }
186
- );
196
+ TestDescribeResult (DescribePath (runtime, schemeShard, pathToSubdomain), {
197
+ LsCheckDiskQuotaExceeded (expectExceeded, debugHint)
198
+ } );
187
199
}
188
200
189
201
void CheckQuotaExceedance (TTestActorRuntime& runtime,
@@ -192,9 +204,13 @@ void CheckQuotaExceedance(TTestActorRuntime& runtime,
192
204
const TMap<TString, EDiskUsageStatus>& expectedExceeders,
193
205
const TString& debugHint = " "
194
206
) {
195
- TestDescribeResult (DescribePath (runtime, schemeShard, pathToSubdomain),
196
- { LsCheckDiskQuotaExceeded (expectedExceeders, debugHint) }
197
- );
207
+ TestDescribeResult (DescribePath (runtime, schemeShard, pathToSubdomain), {
208
+ LsCheckDiskQuotaExceeded (
209
+ expectedExceeders,
210
+ runtime.GetAppData ().FeatureFlags .GetEnableSeparateDiskSpaceQuotas (),
211
+ debugHint
212
+ )
213
+ });
198
214
}
199
215
200
216
TVector<ui64> GetTableShards (TTestActorRuntime& runtime,
@@ -3207,6 +3223,8 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) {
3207
3223
opts.EnableTopicDiskSubDomainQuota (false );
3208
3224
3209
3225
TTestEnv env (runtime, opts);
3226
+ runtime.GetAppData ().FeatureFlags .SetEnableSeparateDiskSpaceQuotas (false );
3227
+
3210
3228
ui64 txId = 100 ;
3211
3229
3212
3230
auto waitForTableStats = [&](ui32 shards) {
@@ -3435,6 +3453,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) {
3435
3453
runtime.SetLogPriority (NKikimrServices::PERSQUEUE_READ_BALANCER, NLog::PRI_TRACE);
3436
3454
3437
3455
runtime.GetAppData ().PQConfig .SetBalancerWakeupIntervalSec (1 );
3456
+ runtime.GetAppData ().FeatureFlags .SetEnableSeparateDiskSpaceQuotas (false );
3438
3457
3439
3458
ui64 txId = 100 ;
3440
3459
@@ -3482,7 +3501,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardSubDomainTest) {
3482
3501
3483
3502
auto stats = NPQ::GetReadBalancerPeriodicTopicStats (runtime, balancerId);
3484
3503
UNIT_ASSERT_EQUAL_C (false , stats->Record .GetSubDomainOutOfSpace (), " SubDomainOutOfSpace from ReadBalancer" );
3485
-
3504
+
3486
3505
auto msg = TString (24_MB, ' _' );
3487
3506
3488
3507
ui32 seqNo = 100 ;
@@ -3517,7 +3536,9 @@ Y_UNIT_TEST_SUITE(TStoragePoolsQuotasTest) {
3517
3536
opts.EnablePersistentPartitionStats (true );
3518
3537
opts.EnableBackgroundCompaction (false );
3519
3538
TTestEnv env (runtime, opts);
3520
-
3539
+
3540
+ runtime.GetAppData ().FeatureFlags .SetEnableSeparateDiskSpaceQuotas (true );
3541
+
3521
3542
NDataShard::gDbStatsReportInterval = TDuration::Seconds (0 );
3522
3543
NDataShard::gDbStatsDataSizeResolution = 1 ;
3523
3544
NDataShard::gDbStatsRowCountResolution = 1 ;
@@ -3610,7 +3631,7 @@ Y_UNIT_TEST_SUITE(TStoragePoolsQuotasTest) {
3610
3631
UpdateRow (runtime, " SomeTable" , 1 , " some_value_for_the_key" , shards[0 ]);
3611
3632
{
3612
3633
const auto tableStats = WaitTableStats (runtime, shards[0 ]).GetTableStats ();
3613
- // channels' usage statistics appears only after a table compaction
3634
+ // channels' usage statistics appears only after a table compaction
3614
3635
UNIT_ASSERT_VALUES_EQUAL_C (tableStats.ChannelsSize (), 0 , tableStats.DebugString ());
3615
3636
}
3616
3637
CheckQuotaExceedance (runtime, tenantSchemeShard, " /MyRoot/SomeDatabase" , false , DEBUG_HINT);
@@ -3636,7 +3657,7 @@ Y_UNIT_TEST_SUITE(TStoragePoolsQuotasTest) {
3636
3657
3637
3658
TTestEnvOptions opts;
3638
3659
TTestEnv env (runtime, opts);
3639
-
3660
+
3640
3661
ui64 txId = 100 ;
3641
3662
3642
3663
constexpr const char * databaseDescription = R"(
@@ -3678,8 +3699,8 @@ Y_UNIT_TEST_SUITE(TStoragePoolsQuotasTest) {
3678
3699
3679
3700
// This test might start failing, because disk space usage of the created table might change
3680
3701
// due to changes in the storage implementation.
3681
- // To fix the test you need to update canonical quotas and / or batch sizes .
3682
- Y_UNIT_TEST_FLAG (DifferentQuotasInteraction, IsExternalSubdomain) {
3702
+ // To fix the test you need to update canonical quotas and the content of the table .
3703
+ Y_UNIT_TEST_FLAGS (DifferentQuotasInteraction, IsExternalSubdomain, EnableSeparateQuotas ) {
3683
3704
TTestBasicRuntime runtime;
3684
3705
runtime.SetLogPriority (NKikimrServices::FLAT_TX_SCHEMESHARD, NLog::PRI_TRACE);
3685
3706
@@ -3688,8 +3709,7 @@ Y_UNIT_TEST_SUITE(TStoragePoolsQuotasTest) {
3688
3709
opts.EnablePersistentPartitionStats (true );
3689
3710
opts.EnableBackgroundCompaction (false );
3690
3711
TTestEnv env (runtime, opts);
3691
- bool bTreeIndex = runtime.GetAppData ().FeatureFlags .GetEnableLocalDBBtreeIndex ();
3692
-
3712
+
3693
3713
NDataShard::gDbStatsReportInterval = TDuration::Seconds (0 );
3694
3714
NDataShard::gDbStatsDataSizeResolution = 1 ;
3695
3715
NDataShard::gDbStatsRowCountResolution = 1 ;
@@ -3798,43 +3818,46 @@ Y_UNIT_TEST_SUITE(TStoragePoolsQuotasTest) {
3798
3818
3799
3819
const auto updateAndCheck = [&](ui32 rowsToUpdate,
3800
3820
const TString& value,
3801
- bool compact,
3802
3821
const TMap<TString, EDiskUsageStatus>& expectedExceeders,
3803
3822
const TString& debugHint = " "
3804
3823
) {
3805
3824
for (ui32 i = 0 ; i < rowsToUpdate; ++i) {
3806
3825
UpdateRow (runtime, " SomeTable" , i, value, shards[0 ]);
3807
3826
}
3808
- if (compact) {
3809
- CompactTableAndCheckResult (runtime, shards[0 ], tableId);
3810
- }
3827
+ CompactTableAndCheckResult (runtime, shards[0 ], tableId);
3811
3828
WaitTableStats (runtime, shards[0 ]);
3812
3829
CheckQuotaExceedance (runtime, tenantSchemeShard, " /MyRoot/SomeDatabase" , expectedExceeders, debugHint);
3813
3830
};
3814
3831
3815
- // Warning: calculated empirically, might need an update if the test fails.
3816
- // The logic of the test expects:
3817
- // batchSizes[0] <= batchSizes[1] <= batchSizes[2],
3818
- // because rows are never deleted, only updated.
3819
- const std::array<ui32, 3 > batchSizes = {25 , 35 , bTreeIndex ? 60u : 50u };
3820
-
3821
- constexpr const char * longText = " this_text_is_very_long_and_takes_a_lot_of_disk_space" ;
3822
- constexpr const char * middleLengthText = " this_text_is_significantly_shorter" ;
3823
-
3824
- // Test scenario:
3825
- // 1) break only the entire database hard quota, don't break others,
3826
- updateAndCheck (batchSizes[0 ], longText, false , {{EntireDatabaseTag, EDiskUsageStatus::AboveHardQuota}}, DEBUG_HINT);
3827
- updateAndCheck (0 , " " , true , {}, DEBUG_HINT);
3828
-
3829
- // 2) break only the large_kind hard quota, don't break other hard quotas,
3830
- updateAndCheck (batchSizes[1 ], longText, true ,
3831
- {{" large_kind" , EDiskUsageStatus::AboveHardQuota}, {EntireDatabaseTag, EDiskUsageStatus::InBetween}}, DEBUG_HINT
3832
- );
3833
- updateAndCheck (batchSizes[1 ], middleLengthText, true , {{" large_kind" , EDiskUsageStatus::InBetween}}, DEBUG_HINT);
3834
- updateAndCheck (batchSizes[1 ], " extra_short_text" , true , {}, DEBUG_HINT);
3832
+ // Warning: calculated empirically, might need an update if the test fails!
3833
+ constexpr ui32 lessRows = 37u ;
3834
+ const ui32 moreRows = runtime.GetAppData ().FeatureFlags .GetEnableLocalDBBtreeIndex () ? 60u : 50u ;
3835
+
3836
+ const TString longText = TString (64 , ' a' );;
3837
+ const TString mediumText = TString (32 , ' a' );
3838
+ const TString shortText = TString (16 , ' a' );
3839
+ const TString tinyText = TString (8 , ' a' );
3835
3840
3836
- // 3) break only the fast_kind hard quota, don't break others.
3837
- updateAndCheck (batchSizes[2 ], " shortest" , true , {{" fast_kind" , EDiskUsageStatus::AboveHardQuota}}, DEBUG_HINT);
3841
+ runtime.GetAppData ().FeatureFlags .SetEnableSeparateDiskSpaceQuotas (EnableSeparateQuotas);
3842
+ if (!EnableSeparateQuotas) {
3843
+ // write a lot of data to break the overall hard quota
3844
+ updateAndCheck (lessRows, longText, {{EntireDatabaseTag, EDiskUsageStatus::AboveHardQuota}}, DEBUG_HINT);
3845
+ } else {
3846
+ // There are two columns in the table: key and value. Key is stored at the fast storage, value at the large storage.
3847
+ // We can:
3848
+ // - simultaneously increase the consumption of the both storage pools by increasing the number of rows in the table
3849
+ // - increase or decrease the consumption of the large storage by making the value longer / shorter
3850
+ // Test scenario:
3851
+ // 1) write a small number of rows (little fast storage consumption), but a long text that breaks the large kind hard quota
3852
+ // 2) the same small number of rows, but a medium text that gets the large kind storage consumption in between the soft and the large quotas
3853
+ // 3) the same small number of rows, but a short text that gets the large kind storage consumption below the soft quota
3854
+ // 4) a bigger number of rows, but a tiny text to break only the fast kind hard quota
3855
+ updateAndCheck (lessRows, longText, {{" large_kind" , EDiskUsageStatus::AboveHardQuota}}, DEBUG_HINT);
3856
+ updateAndCheck (lessRows, mediumText, {{" large_kind" , EDiskUsageStatus::InBetween}}, DEBUG_HINT);
3857
+ updateAndCheck (lessRows, shortText, {}, DEBUG_HINT);
3858
+
3859
+ updateAndCheck (moreRows, tinyText, {{" fast_kind" , EDiskUsageStatus::AboveHardQuota}}, DEBUG_HINT);
3860
+ }
3838
3861
3839
3862
// step 4: drop the table
3840
3863
TestDropTable (runtime, tenantSchemeShard, ++txId, " /MyRoot/SomeDatabase" , " SomeTable" );
0 commit comments