diff options
author | Alexander Rutkovsky <alexvru@mail.ru> | 2022-04-01 15:42:59 +0300 |
---|---|---|
committer | Alexander Rutkovsky <alexvru@mail.ru> | 2022-04-01 15:42:59 +0300 |
commit | 3e90a80f9f0f98a69d5562e3c1d62e39d69e21b2 (patch) | |
tree | 94ce0903d294a6c57ab0285798f7b545add9e473 | |
parent | 4e76cc5d4cc746da6a513b9d90741a18c89c5326 (diff) | |
download | ydb-3e90a80f9f0f98a69d5562e3c1d62e39d69e21b2.tar.gz |
Fix group mapper bug KIKIMR-14580
ref:fe3b40cfdfa08aff38d16bb09282e16688a8b579
-rw-r--r-- | ydb/core/mind/bscontroller/group_mapper.cpp | 45 | ||||
-rw-r--r-- | ydb/core/mind/bscontroller/group_mapper_ut.cpp | 47 |
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; } } - } |