aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Rutkovsky <alexvru@mail.ru>2022-04-01 15:42:59 +0300
committerAlexander Rutkovsky <alexvru@mail.ru>2022-04-01 15:42:59 +0300
commit3e90a80f9f0f98a69d5562e3c1d62e39d69e21b2 (patch)
tree94ce0903d294a6c57ab0285798f7b545add9e473
parent4e76cc5d4cc746da6a513b9d90741a18c89c5326 (diff)
downloadydb-3e90a80f9f0f98a69d5562e3c1d62e39d69e21b2.tar.gz
Fix group mapper bug KIKIMR-14580
ref:fe3b40cfdfa08aff38d16bb09282e16688a8b579
-rw-r--r--ydb/core/mind/bscontroller/group_mapper.cpp45
-rw-r--r--ydb/core/mind/bscontroller/group_mapper_ut.cpp47
2 files changed, 90 insertions, 2 deletions
diff --git a/ydb/core/mind/bscontroller/group_mapper.cpp b/ydb/core/mind/bscontroller/group_mapper.cpp
index 39ab52d2725..945487c7ee2 100644
--- a/ydb/core/mind/bscontroller/group_mapper.cpp
+++ b/ydb/core/mind/bscontroller/group_mapper.cpp
@@ -277,6 +277,51 @@ namespace NKikimr::NBsController {
Y_FAIL();
}
}
+
+ ui32 numMatchingDisksInDomain = 0;
+ ui32 numMatchingDomainsInRealm = 0;
+ ui32 numMatchingRealmsInRealmGroup = 0;
+
+ const ui32 numFailRealms = Self.Geom.GetNumFailRealms();
+ const ui32 numFailDomainsPerFailRealm = Self.Geom.GetNumFailDomainsPerFailRealm();
+ const ui32 numVDisksPerFailDomain = Self.Geom.GetNumVDisksPerFailDomain();
+
+ auto advance = [&](bool domainExhausted, bool realmExhausted, bool realmGroupExhausted, const TPDiskLayoutPosition& prev) {
+ if (domainExhausted) {
+ if (numMatchingDisksInDomain < numVDisksPerFailDomain) {
+ ForbiddenEntities.Set(prev.Domain);
+ } else {
+ ++numMatchingDomainsInRealm;
+ }
+ numMatchingDisksInDomain = 0;
+ }
+ if (realmExhausted) {
+ if (numMatchingDomainsInRealm < numFailDomainsPerFailRealm) {
+ ForbiddenEntities.Set(prev.Realm);
+ } else {
+ ++numMatchingRealmsInRealmGroup;
+ }
+ numMatchingDomainsInRealm = 0;
+ }
+ if (realmGroupExhausted) {
+ if (numMatchingRealmsInRealmGroup < numFailRealms) {
+ ForbiddenEntities.Set(prev.RealmGroup);
+ }
+ numMatchingRealmsInRealmGroup = 0;
+ }
+ };
+
+ if (const auto *begin = Self.PDiskByPosition.data(), *end = begin + Self.PDiskByPosition.size(); begin != end) {
+ --end;
+ while (begin != end) {
+ numMatchingDisksInDomain += begin->second->Matching || Ctx.NewGroupContent.contains(begin->second->PDiskId);
+ const auto& prev = begin++->first;
+ const auto& cur = begin->first;
+ advance(prev.Domain != cur.Domain, prev.Realm != cur.Realm, prev.RealmGroup != cur.RealmGroup, prev);
+ }
+ numMatchingDisksInDomain += begin->second->Matching || Ctx.NewGroupContent.contains(begin->second->PDiskId);
+ advance(true, true, true, begin->first);
+ }
}
TPDiskId AddBestDisk(ui32 realmIdx, ui32 domainIdx) {
diff --git a/ydb/core/mind/bscontroller/group_mapper_ut.cpp b/ydb/core/mind/bscontroller/group_mapper_ut.cpp
index 56af47039c3..d19bd44cc27 100644
--- a/ydb/core/mind/bscontroller/group_mapper_ut.cpp
+++ b/ydb/core/mind/bscontroller/group_mapper_ut.cpp
@@ -146,7 +146,7 @@ public:
if (!success) {
Ctest << "error# " << error << Endl;
}
- UNIT_ASSERT(success);
+ UNIT_ASSERT_C(success, error);
TGroupRecord& record = Groups[groupId];
record.Group = group;
for (const auto& realm : group) {
@@ -477,6 +477,50 @@ Y_UNIT_TEST_SUITE(TGroupMapperTest) {
}
}
+ Y_UNIT_TEST(NonUniformClusterMirror3dcWithUnusableDomain) {
+ std::vector<std::vector<ui32>> disposition{
+ { // datacenter1
+ 4, 4, 4, 4, 4, 2, 2, 4, 2, 5, 5, 5,
+ },
+ { // datacenter2
+ 2, 2, 2, 2, 2, 2, 1, 1, 2, 4, 8, 8, 9,
+ },
+ { // datacenter3
+ 4, 4, 1, 3, 4, 4, 2, 6, 9, 8,
+ },
+ { // datacenter4
+ 1,
+ },
+ };
+ TTestContext context(disposition, 4);
+ TGroupMapper mapper(TTestContext::CreateGroupGeometry(TBlobStorageGroupType::ErasureMirror3dc));
+ context.PopulateGroupMapper(mapper, 9);
+ for (ui32 i = 0; i < context.GetTotalDisks() - 4; ++i) {
+ Ctest << i << "/" << (context.GetTotalDisks() - 4) << Endl;
+ TGroupMapper::TGroupDefinition group;
+ context.AllocateGroup(mapper, group);
+ context.CheckGroupErasure(group);
+
+ TVector<ui32> slots = context.GetSlots();
+ UNIT_ASSERT(slots);
+ ui32 min = Max<ui32>();
+ ui32 max = 0;
+ for (const ui32 x : slots) {
+ if (x) {
+ min = Min(min, x);
+ max = Max(max, x);
+ }
+ }
+ UNIT_ASSERT_C(max - min <= 1, Sprintf("min# %" PRIu32 " max# %" PRIu32, min, max));
+ }
+ TVector<ui32> slots = context.GetSlots();
+ for (ui32 numSlots : slots) {
+ if (numSlots) {
+ UNIT_ASSERT_VALUES_EQUAL(9, numSlots);
+ }
+ }
+ }
+
Y_UNIT_TEST(MakeDisksUnusable) {
TTestContext context(1, 1, 10, 1, 1);
TVector<ui32> groupIds;
@@ -793,5 +837,4 @@ Y_UNIT_TEST_SUITE(TGroupMapperTest) {
Ctest << Endl;
}
}
-
}