aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorilnaz <ilnaz@ydb.tech>2022-08-18 22:10:48 +0300
committerilnaz <ilnaz@ydb.tech>2022-08-18 22:10:48 +0300
commit3c53778e01c3bd4a75198c93b4b005fbae4b9bf5 (patch)
tree45190ecd99eff487d35e0d6f6879d0b11c05936e
parent83b688fff15469399dba5db3790ceef6ab8399ef (diff)
downloadydb-3c53778e01c3bd4a75198c93b4b005fbae4b9bf5.tar.gz
Ignore backup tables when calculating quotas
-rw-r--r--ydb/core/tx/schemeshard/schemeshard__delete_tablet_reply.cpp2
-rw-r--r--ydb/core/tx/schemeshard/schemeshard__init.cpp7
-rw-r--r--ydb/core/tx/schemeshard/schemeshard__operation_common.cpp2
-rw-r--r--ydb/core/tx/schemeshard/schemeshard__operation_copy_table.cpp21
-rw-r--r--ydb/core/tx/schemeshard/schemeshard__operation_drop_table.cpp6
-rw-r--r--ydb/core/tx/schemeshard/schemeshard__operation_move_table.cpp7
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_impl.cpp18
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_impl.h1
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_info_types.h39
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_path.cpp36
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_path_element.cpp18
-rw-r--r--ydb/core/tx/schemeshard/schemeshard_path_element.h6
-rw-r--r--ydb/core/tx/schemeshard/ut_base.cpp71
13 files changed, 196 insertions, 38 deletions
diff --git a/ydb/core/tx/schemeshard/schemeshard__delete_tablet_reply.cpp b/ydb/core/tx/schemeshard/schemeshard__delete_tablet_reply.cpp
index d5c39e7d7b..5e45475c9f 100644
--- a/ydb/core/tx/schemeshard/schemeshard__delete_tablet_reply.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard__delete_tablet_reply.cpp
@@ -126,7 +126,7 @@ struct TSchemeShard::TTxDeleteTabletReply : public TSchemeShard::TRwTxBase {
path->DecShardsInside();
auto domain = Self->ResolveDomainInfo(path);
- domain->RemoveInternalShard(ShardIdx);
+ domain->RemoveInternalShard(ShardIdx, Self->IsBackupTable(pathId));
switch (tabletType) {
case ETabletType::SequenceShard:
domain->RemoveSequenceShard(ShardIdx);
diff --git a/ydb/core/tx/schemeshard/schemeshard__init.cpp b/ydb/core/tx/schemeshard/schemeshard__init.cpp
index 4622e908fd..f66a3875e6 100644
--- a/ydb/core/tx/schemeshard/schemeshard__init.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard__init.cpp
@@ -3680,7 +3680,7 @@ struct TSchemeShard::TTxInit : public TTransactionBase<TSchemeShard> {
path->IncShardsInside();
auto domainInfo = Self->ResolveDomainInfo(pathId); //domain should't be dropeed?
- domainInfo->AddInternalShard(shardIdx);
+ domainInfo->AddInternalShard(shardIdx, Self->IsBackupTable(pathId));
switch (si.second.TabletType) {
case ETabletType::DataShard:
@@ -3776,8 +3776,9 @@ struct TSchemeShard::TTxInit : public TTransactionBase<TSchemeShard> {
}
if (!path->IsRoot()) {
- parent->IncAliveChildren();
- inclusivedomainInfo->IncPathsInside();
+ const bool isBackupTable = Self->IsBackupTable(item.first);
+ parent->IncAliveChildren(1, isBackupTable);
+ inclusivedomainInfo->IncPathsInside(1, isBackupTable);
}
Self->TabletCounters->Simple()[COUNTER_USER_ATTRIBUTES_COUNT].Add(path->UserAttrs->Size());
diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_common.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_common.cpp
index 4ef28ff926..cdb777eaed 100644
--- a/ydb/core/tx/schemeshard/schemeshard__operation_common.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard__operation_common.cpp
@@ -394,7 +394,7 @@ void NTableState::UpdatePartitioningForCopyTable(TOperationId operationId, TTxSt
dstTableInfo->PerShardPartitionConfig.erase(shard.Idx);
context.SS->PersistShardDeleted(db, shard.Idx, context.SS->ShardInfos[shard.Idx].BindedChannels);
context.SS->ShardInfos.erase(shard.Idx);
- domainInfo->RemoveInternalShard(shard.Idx);
+ domainInfo->RemoveInternalShard(shard.Idx, context.SS->IsBackupTable(pathId));
context.SS->DecrementPathDbRefCount(pathId, "remove shard from txState");
context.SS->ShardRemoved(shard.Idx);
}
diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_copy_table.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_copy_table.cpp
index 3f41a88f4e..3d636dd02e 100644
--- a/ydb/core/tx/schemeshard/schemeshard__operation_copy_table.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard__operation_copy_table.cpp
@@ -398,6 +398,9 @@ public:
const ui32 maxShardsToCreate = srcPath.Shards();
const TString acl = Transaction.GetModifyACL().GetDiffACL();
+ auto schema = Transaction.GetCreateTable();
+ const bool isBackup = schema.GetIsBackup();
+
TPath dstPath = parent.Child(name);
{
TPath::TChecker checks = dstPath.Check();
@@ -420,13 +423,17 @@ public:
checks
.IsValidLeafName()
.IsTheSameDomain(srcPath)
- .PathsLimit()
- .DirChildrenLimit()
- .ShardsLimit(maxShardsToCreate)
.PathShardsLimit(maxShardsToCreate)
.IsValidACL(acl);
}
+ if (checks && !isBackup) {
+ checks
+ .PathsLimit()
+ .DirChildrenLimit()
+ .ShardsLimit(maxShardsToCreate);
+ }
+
if (!checks) {
TString explain = TStringBuilder() << "path fail checks"
<< ", path: " << dstPath.PathString();
@@ -479,9 +486,7 @@ public:
}
}
- auto schema = Transaction.GetCreateTable();
const bool omitFollowers = schema.GetOmitFollowers();
- const bool isBackup = schema.GetIsBackup();
PrepareScheme(&schema, name, srcTableInfo, context);
schema.SetIsBackup(isBackup);
@@ -633,10 +638,10 @@ public:
const ui32 shardsToCreate = tableInfo->GetPartitions().size();
Y_VERIFY_S(shardsToCreate <= maxShardsToCreate, "shardsToCreate: " << shardsToCreate << " maxShardsToCreate: " << maxShardsToCreate);
- dstPath.DomainInfo()->IncPathsInside();
- dstPath.DomainInfo()->AddInternalShards(txState);
+ dstPath.DomainInfo()->IncPathsInside(1, isBackup);
+ dstPath.DomainInfo()->AddInternalShards(txState, isBackup);
dstPath.Base()->IncShardsInside(shardsToCreate);
- parent.Base()->IncAliveChildren();
+ parent.Base()->IncAliveChildren(1, isBackup);
State = NextState();
SetState(SelectStateFunc(State));
diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_drop_table.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_drop_table.cpp
index 2d9e55d2ca..edc660084b 100644
--- a/ydb/core/tx/schemeshard/schemeshard__operation_drop_table.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard__operation_drop_table.cpp
@@ -35,11 +35,13 @@ void DropPath(NIceDb::TNiceDb& db,
context.SS->TabletCounters->Simple()[COUNTER_USER_ATTRIBUTES_COUNT].Sub(path->UserAttrs->Size());
context.SS->PersistUserAttributes(db, path->PathId, path->UserAttrs, nullptr);
+ const auto isBackupTable = context.SS->IsBackupTable(path->PathId);
+
auto domainInfo = context.SS->ResolveDomainInfo(path->PathId);
- domainInfo->DecPathsInside();
+ domainInfo->DecPathsInside(1, isBackupTable);
auto parentDir = path.Parent();
- parentDir->DecAliveChildren();
+ parentDir->DecAliveChildren(1, isBackupTable);
++parentDir->DirAlterVersion;
context.SS->PersistPathDirAlterVersion(db, parentDir.Base());
diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_move_table.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_move_table.cpp
index 0a6c643789..0a274a19d2 100644
--- a/ydb/core/tx/schemeshard/schemeshard__operation_move_table.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard__operation_move_table.cpp
@@ -143,15 +143,16 @@ void MarkSrcDropped(NIceDb::TNiceDb& db,
const TTxState& txState,
TPath& srcPath)
{
+ const auto isBackupTable = context.SS->IsBackupTable(srcPath->PathId);
+ srcPath.Parent()->DecAliveChildren(1, isBackupTable);
+ srcPath.DomainInfo()->DecPathsInside(1, isBackupTable);
+
srcPath->SetDropped(txState.PlanStep, operationId.GetTxId());
context.SS->PersistDropStep(db, srcPath->PathId, txState.PlanStep, operationId);
context.SS->Tables.at(srcPath->PathId)->DetachShardsStats();
context.SS->PersistRemoveTable(db, srcPath->PathId, context.Ctx);
context.SS->PersistUserAttributes(db, srcPath->PathId, srcPath->UserAttrs, nullptr);
- srcPath.Parent()->DecAliveChildren();
- srcPath.DomainInfo()->DecPathsInside();
-
IncParentDirAlterVersionWithRepublish(operationId, srcPath, context);
}
diff --git a/ydb/core/tx/schemeshard/schemeshard_impl.cpp b/ydb/core/tx/schemeshard/schemeshard_impl.cpp
index 49c45cf3ab..d4da387937 100644
--- a/ydb/core/tx/schemeshard/schemeshard_impl.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard_impl.cpp
@@ -1234,6 +1234,16 @@ const TTableInfo* TSchemeShard::GetMainTableForIndex(TPathId indexTableId) const
return Tables.FindPtr(grandParentId)->Get();
}
+bool TSchemeShard::IsBackupTable(TPathId pathId) const {
+ auto it = Tables.find(pathId);
+ if (it == Tables.end()) {
+ return false;
+ }
+
+ Y_VERIFY(it->second);
+ return it->second->IsBackup;
+}
+
TPathElement::EPathState TSchemeShard::CalcPathState(TTxState::ETxType txType, TPathElement::EPathState oldState) {
// Do not change state if PathId is dropped. It can't become alive.
switch (oldState) {
@@ -4316,12 +4326,14 @@ void TSchemeShard::MarkAsDroping(TPathElement::TPtr node, TTxId txId, const TAct
}
void TSchemeShard::UncountNode(TPathElement::TPtr node) {
+ const auto isBackupTable = IsBackupTable(node->PathId);
+
if (node->IsDomainRoot()) {
- ResolveDomainInfo(node->ParentPathId)->DecPathsInside();
+ ResolveDomainInfo(node->ParentPathId)->DecPathsInside(1, isBackupTable);
} else {
- ResolveDomainInfo(node)->DecPathsInside();
+ ResolveDomainInfo(node)->DecPathsInside(1, isBackupTable);
}
- PathsById.at(node->ParentPathId)->DecAliveChildren();
+ PathsById.at(node->ParentPathId)->DecAliveChildren(1, isBackupTable);
TabletCounters->Simple()[COUNTER_USER_ATTRIBUTES_COUNT].Sub(node->UserAttrs->Size());
diff --git a/ydb/core/tx/schemeshard/schemeshard_impl.h b/ydb/core/tx/schemeshard/schemeshard_impl.h
index 6c6be75b96..fe2ab6c568 100644
--- a/ydb/core/tx/schemeshard/schemeshard_impl.h
+++ b/ydb/core/tx/schemeshard/schemeshard_impl.h
@@ -476,6 +476,7 @@ public:
ui64 GetAliveChildren(TPathElement::TPtr pathEl, const std::optional<TPathElement::EPathType>& type = std::nullopt) const;
const TTableInfo* GetMainTableForIndex(TPathId indexTableId) const;
+ bool IsBackupTable(TPathId pathId) const;
TPathId ResolvePathIdForDomain(TPathId pathId) const;
TPathId ResolvePathIdForDomain(TPathElement::TPtr pathEl) const;
diff --git a/ydb/core/tx/schemeshard/schemeshard_info_types.h b/ydb/core/tx/schemeshard/schemeshard_info_types.h
index 2b076dbf2d..c094e1540a 100644
--- a/ydb/core/tx/schemeshard/schemeshard_info_types.h
+++ b/ydb/core/tx/schemeshard/schemeshard_info_types.h
@@ -1369,14 +1369,28 @@ struct TSubDomainInfo: TSimpleRefCount<TSubDomainInfo> {
PathsInsideCount = val;
}
- void IncPathsInside(ui64 delta = 1) {
+ ui64 GetBackupPaths() const {
+ return BackupPathsCount;
+ }
+
+ void IncPathsInside(ui64 delta = 1, bool isBackup = false) {
Y_VERIFY(Max<ui64>() - PathsInsideCount >= delta);
PathsInsideCount += delta;
+
+ if (isBackup) {
+ Y_VERIFY(Max<ui64>() - BackupPathsCount >= delta);
+ BackupPathsCount += delta;
+ }
}
- void DecPathsInside(ui64 delta = 1) {
+ void DecPathsInside(ui64 delta = 1, bool isBackup = false) {
Y_VERIFY_S(PathsInsideCount >= delta, "PathsInsideCount: " << PathsInsideCount << " delta: " << delta);
PathsInsideCount -= delta;
+
+ if (isBackup) {
+ Y_VERIFY_S(BackupPathsCount >= delta, "BackupPathsCount: " << BackupPathsCount << " delta: " << delta);
+ BackupPathsCount -= delta;
+ }
}
ui64 GetPQPartitionsInside() const {
@@ -1426,6 +1440,10 @@ struct TSubDomainInfo: TSimpleRefCount<TSubDomainInfo> {
return InternalShards.size();
}
+ ui64 GetBackupShards() const {
+ return BackupShards.size();
+ }
+
void ActualizeAlterData(const THashMap<TShardIdx, TShardInfo>& allShards, TInstant now, bool isExternal, IQuotaCounters* counters) {
Y_VERIFY(AlterData);
@@ -1600,27 +1618,34 @@ struct TSubDomainInfo: TSimpleRefCount<TSubDomainInfo> {
return PrivateShards;
}
- void AddInternalShard(TShardIdx shardId) {
+ void AddInternalShard(TShardIdx shardId, bool isBackup = false) {
InternalShards.insert(shardId);
+ if (isBackup) {
+ BackupShards.insert(shardId);
+ }
}
const THashSet<TShardIdx>& GetInternalShards() const {
return InternalShards;
}
- void AddInternalShards(const TTxState& txState) {
+ void AddInternalShards(const TTxState& txState, bool isBackup = false) {
for (auto txShard: txState.Shards) {
if (txShard.Operation != TTxState::CreateParts) {
continue;
}
- AddInternalShard(txShard.Idx);
+ AddInternalShard(txShard.Idx, isBackup);
}
}
- void RemoveInternalShard(TShardIdx shardIdx) {
+ void RemoveInternalShard(TShardIdx shardIdx, bool isBackup = false) {
auto it = InternalShards.find(shardIdx);
Y_VERIFY_S(it != InternalShards.end(), "shardIdx: " << shardIdx);
InternalShards.erase(it);
+
+ if (isBackup) {
+ BackupShards.erase(shardIdx);
+ }
}
const THashSet<TShardIdx>& GetSequenceShards() const {
@@ -1883,9 +1908,11 @@ private:
TSchemeQuotas SchemeQuotas;
ui64 PathsInsideCount = 0;
+ ui64 BackupPathsCount = 0;
TDiskSpaceUsage DiskSpaceUsage;
THashSet<TShardIdx> InternalShards;
+ THashSet<TShardIdx> BackupShards;
THashSet<TShardIdx> SequenceShards;
THashSet<TShardIdx> ReplicationControllers;
diff --git a/ydb/core/tx/schemeshard/schemeshard_path.cpp b/ydb/core/tx/schemeshard/schemeshard_path.cpp
index 3fc23bee5f..d2c908c92e 100644
--- a/ydb/core/tx/schemeshard/schemeshard_path.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard_path.cpp
@@ -796,8 +796,15 @@ const TPath::TChecker& TPath::TChecker::PathsLimit(ui64 delta, TPath::TChecker::
}
TSubDomainInfo::TPtr domainInfo = Path.DomainInfo();
+ const auto pathsTotal = domainInfo->GetPathsInside();
+ const auto backupPaths = domainInfo->GetBackupPaths();
- if (!delta || domainInfo->GetPathsInside() + delta <= domainInfo->GetSchemeLimits().MaxPaths) {
+ Y_VERIFY_S(pathsTotal >= backupPaths, "Constraint violation"
+ << ": path: " << Path.PathString()
+ << ", paths total: " << pathsTotal
+ << ", backup paths: " << backupPaths);
+
+ if (!delta || (pathsTotal - backupPaths) + delta <= domainInfo->GetSchemeLimits().MaxPaths) {
return *this;
}
@@ -805,7 +812,8 @@ const TPath::TChecker& TPath::TChecker::PathsLimit(ui64 delta, TPath::TChecker::
Status = status;
Explain << "paths count has reached maximum value in the domain"
<< ", paths limit for domain: " << domainInfo->GetSchemeLimits().MaxPaths
- << ", paths count inside domain: " << domainInfo->GetPathsInside()
+ << ", paths count inside domain: " << pathsTotal
+ << ", backup paths: " << backupPaths
<< ", intention to create new paths: " << delta;
return *this;
}
@@ -816,11 +824,16 @@ const TPath::TChecker& TPath::TChecker::DirChildrenLimit(ui64 delta, TPath::TChe
}
TSubDomainInfo::TPtr domainInfo = Path.DomainInfo();
-
auto parent = Path.Parent();
- ui64 aliveChildren = parent.Base()->GetAliveChildren();
+ const auto aliveChildren = parent.Base()->GetAliveChildren();
+ const auto backupChildren = parent.Base()->GetBackupChildren();
- if (!delta || aliveChildren + delta <= domainInfo->GetSchemeLimits().MaxChildrenInDir) {
+ Y_VERIFY_S(aliveChildren >= backupChildren, "Constraint violation"
+ << ": path: " << parent.PathString()
+ << ", alive children: " << aliveChildren
+ << ", backup children: " << backupChildren);
+
+ if (!delta || (aliveChildren - backupChildren) + delta <= domainInfo->GetSchemeLimits().MaxChildrenInDir) {
return *this;
}
@@ -829,6 +842,7 @@ const TPath::TChecker& TPath::TChecker::DirChildrenLimit(ui64 delta, TPath::TChe
Explain << "children count has reached maximum value in the dir"
<< ", children limit for domain dir: " << domainInfo->GetSchemeLimits().MaxChildrenInDir
<< ", children count inside dir: " << aliveChildren
+ << ", backup children: " << backupChildren
<< ", intention to create new children: " << delta;
return *this;
}
@@ -839,8 +853,15 @@ const TPath::TChecker& TPath::TChecker::ShardsLimit(ui64 delta, TPath::TChecker:
}
TSubDomainInfo::TPtr domainInfo = Path.DomainInfo();
+ const auto shardsTotal = domainInfo->GetShardsInside();
+ const auto backupShards = domainInfo->GetBackupShards();
+
+ Y_VERIFY_S(shardsTotal >= backupShards, "Constraint violation"
+ << ": path: " << Path.PathString()
+ << ", shards total: " << shardsTotal
+ << ", backup shards: " << backupShards);
- if (!delta || domainInfo->GetShardsInside() + delta <= domainInfo->GetSchemeLimits().MaxShards) {
+ if (!delta || (shardsTotal - backupShards) + delta <= domainInfo->GetSchemeLimits().MaxShards) {
return *this;
}
@@ -848,7 +869,8 @@ const TPath::TChecker& TPath::TChecker::ShardsLimit(ui64 delta, TPath::TChecker:
Status = status;
Explain << "shards count has reached maximum value in the domain"
<< ", shards limit for domain: " << domainInfo->GetSchemeLimits().MaxShards
- << ", shards count inside domain: " << domainInfo->GetShardsInside()
+ << ", shards count inside domain: " << shardsTotal
+ << ", backup shards: " << backupShards
<< ", intention to create new shards: " << delta;
return *this;
}
diff --git a/ydb/core/tx/schemeshard/schemeshard_path_element.cpp b/ydb/core/tx/schemeshard/schemeshard_path_element.cpp
index 09c225372c..a317287412 100644
--- a/ydb/core/tx/schemeshard/schemeshard_path_element.cpp
+++ b/ydb/core/tx/schemeshard/schemeshard_path_element.cpp
@@ -20,14 +20,28 @@ void TPathElement::SetAliveChildren(ui64 val) {
AliveChildrenCount = val;
}
-void TPathElement::IncAliveChildren(ui64 delta) {
+ui64 TPathElement::GetBackupChildren() const {
+ return BackupChildrenCount;
+}
+
+void TPathElement::IncAliveChildren(ui64 delta, bool isBackup) {
Y_VERIFY(Max<ui64>() - AliveChildrenCount >= delta);
AliveChildrenCount += delta;
+
+ if (isBackup) {
+ Y_VERIFY(Max<ui64>() - BackupChildrenCount >= delta);
+ BackupChildrenCount += delta;
+ }
}
-void TPathElement::DecAliveChildren(ui64 delta) {
+void TPathElement::DecAliveChildren(ui64 delta, bool isBackup) {
Y_VERIFY(AliveChildrenCount >= delta);
AliveChildrenCount -= delta;
+
+ if (isBackup) {
+ Y_VERIFY(BackupChildrenCount >= delta);
+ BackupChildrenCount -= delta;
+ }
}
ui64 TPathElement::GetShardsInside() const {
diff --git a/ydb/core/tx/schemeshard/schemeshard_path_element.h b/ydb/core/tx/schemeshard/schemeshard_path_element.h
index 499f661130..9844676d02 100644
--- a/ydb/core/tx/schemeshard/schemeshard_path_element.h
+++ b/ydb/core/tx/schemeshard/schemeshard_path_element.h
@@ -341,14 +341,16 @@ struct TPathElement : TSimpleRefCount<TPathElement> {
private:
ui64 AliveChildrenCount = 0;
+ ui64 BackupChildrenCount = 0;
ui64 ShardsInsideCount = 0;
TChildrenCont Children;
public:
TPathElement(TPathId pathId, TPathId parentPathId, TPathId domainPathId, const TString& name, const TString& owner);
ui64 GetAliveChildren() const;
void SetAliveChildren(ui64 val);
- void IncAliveChildren(ui64 delta = 1);
- void DecAliveChildren(ui64 delta = 1);
+ ui64 GetBackupChildren() const;
+ void IncAliveChildren(ui64 delta = 1, bool isBackup = false);
+ void DecAliveChildren(ui64 delta = 1, bool isBackup = false);
ui64 GetShardsInside() const;
void SetShardsInside(ui64 val);
void IncShardsInside(ui64 delta = 1);
diff --git a/ydb/core/tx/schemeshard/ut_base.cpp b/ydb/core/tx/schemeshard/ut_base.cpp
index 092492d316..e883604f18 100644
--- a/ydb/core/tx/schemeshard/ut_base.cpp
+++ b/ydb/core/tx/schemeshard/ut_base.cpp
@@ -3488,6 +3488,13 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) {
TTestEnv env(runtime);
ui64 txId = 100;
+ // these limits should have no effect on backup tables
+ TSchemeLimits limits;
+ limits.MaxPaths = 4;
+ limits.MaxShards = 4;
+ limits.MaxChildrenInDir = 3;
+ SetSchemeshardSchemaLimits(runtime, limits);
+
// create src table
TestCreateTable(runtime, ++txId, "/MyRoot", R"(
Name: "Table"
@@ -3527,6 +3534,70 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) {
NLs::IsBackupTable(true),
});
+ // negative tests
+
+ // shards limit
+ TestCreateTable(runtime, ++txId, "/MyRoot", R"(
+ Name: "Table2"
+ Columns { Name: "key" Type: "Uint32"}
+ Columns { Name: "value" Type: "Utf8"}
+ KeyColumnNames: ["key"]
+ UniformPartitionsCount: 4
+ )", {NKikimrScheme::StatusResourceExhausted});
+
+ // ok
+ TestCreateTable(runtime, ++txId, "/MyRoot", R"(
+ Name: "Table2"
+ Columns { Name: "key" Type: "Uint32"}
+ Columns { Name: "value" Type: "Utf8"}
+ KeyColumnNames: ["key"]
+ )");
+ env.TestWaitNotification(runtime, txId);
+
+ TestMkDir(runtime, ++txId, "/MyRoot", "Dir");
+ env.TestWaitNotification(runtime, txId);
+
+ // children limit
+ TestCreateTable(runtime, ++txId, "/MyRoot", R"(
+ Name: "Table3"
+ Columns { Name: "key" Type: "Uint32"}
+ Columns { Name: "value" Type: "Utf8"}
+ KeyColumnNames: ["key"]
+ )", {NKikimrScheme::StatusResourceExhausted});
+
+ // ok
+ TestCreateTable(runtime, ++txId, "/MyRoot/Dir", R"(
+ Name: "Table3"
+ Columns { Name: "key" Type: "Uint32"}
+ Columns { Name: "value" Type: "Utf8"}
+ KeyColumnNames: ["key"]
+ )");
+ env.TestWaitNotification(runtime, txId);
+
+ // paths limit
+ TestCreateTable(runtime, ++txId, "/MyRoot/Dir", R"(
+ Name: "Table4"
+ Columns { Name: "key" Type: "Uint32"}
+ Columns { Name: "value" Type: "Utf8"}
+ KeyColumnNames: ["key"]
+ )", {NKikimrScheme::StatusResourceExhausted});
+
+ // free quota
+ TestDropTable(runtime, ++txId, "/MyRoot", "Table2");
+ env.TestWaitNotification(runtime, txId);
+
+ // ok
+ TestCreateTable(runtime, ++txId, "/MyRoot/Dir", R"(
+ Name: "Table4"
+ Columns { Name: "key" Type: "Uint32"}
+ Columns { Name: "value" Type: "Utf8"}
+ KeyColumnNames: ["key"]
+ )");
+ env.TestWaitNotification(runtime, txId);
+
+ // reset limits to default
+ SetSchemeshardSchemaLimits(runtime, TSchemeLimits());
+
// cannot create new table with 'IsBackup'
TestCreateTable(runtime, ++txId, "/MyRoot", R"(
Name: "TableForBackup"