diff options
| author | Alexander Rutkovsky <[email protected]> | 2022-04-01 15:42:59 +0300 | 
|---|---|---|
| committer | Alexander Rutkovsky <[email protected]> | 2022-04-01 15:42:59 +0300 | 
| commit | 3e90a80f9f0f98a69d5562e3c1d62e39d69e21b2 (patch) | |
| tree | 94ce0903d294a6c57ab0285798f7b545add9e473 | |
| parent | 4e76cc5d4cc746da6a513b9d90741a18c89c5326 (diff) | |
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;          }      } -  } | 
