diff options
author | alexvru <alexvru@ydb.tech> | 2023-03-16 15:18:57 +0300 |
---|---|---|
committer | alexvru <alexvru@ydb.tech> | 2023-03-16 15:18:57 +0300 |
commit | e3736cae776451f7494d5e73342c04e88226ab96 (patch) | |
tree | 7fa2121a56cb2735f7dca6a50a47a49f6595a490 | |
parent | 15d1a0bf99bc8e273d39978cebdcaa3368ede0d7 (diff) | |
download | ydb-e3736cae776451f7494d5e73342c04e88226ab96.tar.gz |
Improve BSC donor handling code
-rw-r--r-- | ydb/core/mind/bscontroller/bsc.cpp | 20 | ||||
-rw-r--r-- | ydb/core/mind/bscontroller/config.cpp | 97 | ||||
-rw-r--r-- | ydb/core/mind/bscontroller/config.h | 2 | ||||
-rw-r--r-- | ydb/core/mind/bscontroller/config_fit_groups.cpp | 77 | ||||
-rw-r--r-- | ydb/core/mind/bscontroller/impl.h | 23 | ||||
-rw-r--r-- | ydb/core/mind/bscontroller/load_everything.cpp | 27 | ||||
-rw-r--r-- | ydb/core/mind/bscontroller/monitoring.cpp | 17 | ||||
-rw-r--r-- | ydb/core/mind/bscontroller/register_node.cpp | 11 | ||||
-rw-r--r-- | ydb/core/mind/bscontroller/self_heal.cpp | 2 |
9 files changed, 165 insertions, 111 deletions
diff --git a/ydb/core/mind/bscontroller/bsc.cpp b/ydb/core/mind/bscontroller/bsc.cpp index 0baaee3690..1e23c67ef0 100644 --- a/ydb/core/mind/bscontroller/bsc.cpp +++ b/ydb/core/mind/bscontroller/bsc.cpp @@ -216,24 +216,26 @@ void TBlobStorageController::ValidateInternalState() { const auto it = vslot->PDisk->VSlotsOnPDisk.find(vslotId.VSlotId); Y_VERIFY(it != vslot->PDisk->VSlotsOnPDisk.end()); Y_VERIFY(it->second == vslot.Get()); + const TGroupInfo *group = FindGroup(vslot->GroupId); if (!vslot->IsBeingDeleted() && vslot->Mood != TMood::Donor) { - Y_VERIFY(vslot->Group == FindGroup(vslot->GroupId)); + Y_VERIFY(group); + Y_VERIFY(vslot->Group == group); } else { Y_VERIFY(!vslot->Group); } if (vslot->Mood == TMood::Donor) { - const TVSlotInfo *acceptor = FindVSlot(vslot->AcceptorVSlotId); - Y_VERIFY(acceptor); - auto& donors = acceptor->Donors; - const auto it = std::find(donors.begin(), donors.end(), std::make_pair(vslotId, vslot->GetVDiskId())); - Y_VERIFY(it != donors.end()); + const TVSlotInfo *acceptor = FindAcceptor(*vslot); + Y_VERIFY(!acceptor->IsBeingDeleted()); + Y_VERIFY(acceptor->Mood != TMood::Donor); + Y_VERIFY(acceptor->Donors.contains(vslotId)); } - for (const auto& [donorVSlotId, donorVDiskId] : vslot->Donors) { + for (const TVSlotId& donorVSlotId : vslot->Donors) { const TVSlotInfo *donor = FindVSlot(donorVSlotId); Y_VERIFY(donor); - Y_VERIFY(donor->GetVDiskId() == donorVDiskId); Y_VERIFY(donor->Mood == TMood::Donor); - Y_VERIFY(donor->AcceptorVSlotId == vslotId); + Y_VERIFY(donor->GroupId == vslot->GroupId); + Y_VERIFY(donor->GroupGeneration < vslot->GroupGeneration + group->ContentChanged); + Y_VERIFY(donor->GetShortVDiskId() == vslot->GetShortVDiskId()); } if (vslot->Group) { if (vslot->Status == NKikimrBlobStorage::EVDiskStatus::READY) { diff --git a/ydb/core/mind/bscontroller/config.cpp b/ydb/core/mind/bscontroller/config.cpp index 1be709779c..9f45b21245 100644 --- a/ydb/core/mind/bscontroller/config.cpp +++ b/ydb/core/mind/bscontroller/config.cpp @@ -155,7 +155,14 @@ namespace NKikimr::NBsController { if (const TGroupInfo *group = State.Groups.Find(vslotInfo.GroupId); group && mood != TMood::Delete) { item.SetStoragePoolName(State.StoragePools.Get().at(group->StoragePoolId).Name); - SerializeDonors(&item, vslotInfo, *group); + + auto vslotFinder = [this](const TVSlotId& vslotId, auto&& callback) { + if (const TVSlotInfo *vslot = State.VSlots.Find(vslotId)) { + callback(*vslot); + } + }; + + SerializeDonors(&item, vslotInfo, *group, vslotFinder); } else { Y_VERIFY(mood != TMood::Donor); } @@ -564,7 +571,7 @@ namespace NKikimr::NBsController { } } - void TBlobStorageController::TConfigState::DestroyVSlot(const TVSlotId vslotId) { + void TBlobStorageController::TConfigState::DestroyVSlot(const TVSlotId vslotId, const TVSlotInfo *ensureAcceptorSlot) { // obtain mutable slot pointer TVSlotInfo *mutableSlot = VSlots.FindForUpdate(vslotId); Y_VERIFY(mutableSlot); @@ -575,17 +582,33 @@ namespace NKikimr::NBsController { if (mutableSlot->Mood == TMood::Donor) { // this is the donor disk and it is being deleted; here we have to inform the acceptor disk of changed // donor set by simply removing the donor disk - TVSlotInfo *mutableAcceptor = VSlots.FindForUpdate(mutableSlot->AcceptorVSlotId); + const TGroupInfo *group = Groups.Find(mutableSlot->GroupId); + Y_VERIFY(group); + const ui32 orderNumber = group->Topology->GetOrderNumber(mutableSlot->GetShortVDiskId()); + const TVSlotInfo *acceptor = group->VDisksInGroup[orderNumber]; + Y_VERIFY(acceptor); + Y_VERIFY(!acceptor->IsBeingDeleted()); + Y_VERIFY(acceptor->Mood != TMood::Donor); + Y_VERIFY(mutableSlot->GroupId == acceptor->GroupId && mutableSlot->GroupGeneration < acceptor->GroupGeneration && + mutableSlot->GetShortVDiskId() == acceptor->GetShortVDiskId()); + + TVSlotInfo *mutableAcceptor = VSlots.FindForUpdate(acceptor->VSlotId); Y_VERIFY(mutableAcceptor); + Y_VERIFY_S(!ensureAcceptorSlot || ensureAcceptorSlot == mutableAcceptor, + "EnsureAcceptor# " << ensureAcceptorSlot->VSlotId << ':' << ensureAcceptorSlot->GetVDiskId() + << " MutableAcceptor# " << mutableAcceptor->VSlotId << ':' << mutableAcceptor->GetVDiskId() + << " Slot# " << mutableSlot->VSlotId << ':' << mutableSlot->GetVDiskId()); + auto& donors = mutableAcceptor->Donors; - const auto it = std::find(donors.begin(), donors.end(), std::make_pair(vslotId, mutableSlot->GetVDiskId())); - Y_VERIFY(it != donors.end()); - donors.erase(it); + const size_t numErased = donors.erase(vslotId); + Y_VERIFY(numErased == 1); + } else { + Y_VERIFY(!ensureAcceptorSlot); } - for (const auto& [donorVSlotId, donorVDiskId] : std::exchange(mutableSlot->Donors, {})) { - // this is the acceptor disk and we have to delete all the donors as they are not needed anymore - DestroyVSlot(donorVSlotId); + // this is the acceptor disk and we have to delete all the donors as they are not needed anymore + for (auto& donors = mutableSlot->Donors; !donors.empty(); ) { + DestroyVSlot(*donors.begin(), mutableSlot); } // remove slot info from the PDisk @@ -623,24 +646,30 @@ namespace NKikimr::NBsController { const auto it = vslot.PDisk->VSlotsOnPDisk.find(vslotId.VSlotId); Y_VERIFY(it != vslot.PDisk->VSlotsOnPDisk.end()); Y_VERIFY(it->second == &vslot); + const TGroupInfo *group = Groups.Find(vslot.GroupId); if (!vslot.IsBeingDeleted() && vslot.Mood != TMood::Donor) { - Y_VERIFY(vslot.Group == Groups.Find(vslot.GroupId)); + Y_VERIFY(group); + Y_VERIFY(vslot.Group == group); } else { Y_VERIFY(!vslot.Group); } if (vslot.Mood == TMood::Donor) { - const TVSlotInfo *acceptor = VSlots.Find(vslot.AcceptorVSlotId); + Y_VERIFY(vslot.Donors.empty()); + Y_VERIFY(group); + const ui32 orderNumber = group->Topology->GetOrderNumber(vslot.GetShortVDiskId()); + const TVSlotInfo *acceptor = group->VDisksInGroup[orderNumber]; Y_VERIFY(acceptor); - auto& donors = acceptor->Donors; - const auto it = std::find(donors.begin(), donors.end(), std::make_pair(vslotId, vslot.GetVDiskId())); - Y_VERIFY(it != donors.end()); + Y_VERIFY(!acceptor->IsBeingDeleted()); + Y_VERIFY(acceptor->Mood != TMood::Donor); + Y_VERIFY(acceptor->Donors.contains(vslotId)); } - for (const auto& [donorVSlotId, donorVDiskId] : vslot.Donors) { + for (const TVSlotId& donorVSlotId : vslot.Donors) { const TVSlotInfo *donor = VSlots.Find(donorVSlotId); Y_VERIFY(donor); - Y_VERIFY(donor->GetVDiskId() == donorVDiskId); Y_VERIFY(donor->Mood == TMood::Donor); - Y_VERIFY(donor->AcceptorVSlotId == vslotId); + Y_VERIFY(donor->GroupId == vslot.GroupId); + Y_VERIFY(donor->GroupGeneration < vslot.GroupGeneration + group->ContentChanged); + Y_VERIFY(donor->GetShortVDiskId() == vslot.GetShortVDiskId()); } }); Groups.ForEach([&](const auto& groupId, const auto& group) { @@ -857,11 +886,11 @@ namespace NKikimr::NBsController { pb->MutableVDiskMetrics()->CopyFrom(vslot.Metrics); pb->MutableVDiskMetrics()->ClearVDiskId(); pb->SetStatus(NKikimrBlobStorage::EVDiskStatus_Name(vslot.Status)); - for (const auto& [vslotId, vdiskId] : vslot.Donors) { + for (const TVSlotId& vslotId : vslot.Donors) { auto *item = pb->AddDonors(); Serialize(item->MutableVSlotId(), vslotId); - VDiskIDFromVDiskID(vdiskId, item->MutableVDiskId()); finder(vslotId, [item](const TVSlotInfo& vslot) { + VDiskIDFromVDiskID(vslot.GetVDiskId(), item->MutableVDiskId()); item->MutableVDiskMetrics()->CopyFrom(vslot.Metrics); item->MutableVDiskMetrics()->ClearVDiskId(); }); @@ -886,7 +915,7 @@ namespace NKikimr::NBsController { } void TBlobStorageController::SerializeDonors(NKikimrBlobStorage::TNodeWardenServiceSet::TVDisk *vdisk, - const TVSlotInfo& vslot, const TGroupInfo& group) { + const TVSlotInfo& vslot, const TGroupInfo& group, const TVSlotFinder& finder) { if (vslot.Mood == TMood::Donor) { ui32 numFailRealms = 0, numFailDomainsPerFailRealm = 0, numVDisksPerFailDomain = 0; for (const TVSlotInfo *slot : group.VDisksInGroup) { @@ -901,10 +930,32 @@ namespace NKikimr::NBsController { pb->SetNumVDisksPerFailDomain(numVDisksPerFailDomain); pb->SetErasureSpecies(group.ErasureSpecies); } - for (const auto& [vslotId, vdiskId] : vslot.Donors) { + + std::vector<std::pair<TVDiskID, TVSlotId>> donors; + for (const TVSlotId& donorVSlotId : vslot.Donors) { + std::optional<TVDiskID> vdiskId; + finder(donorVSlotId, [&](const TVSlotInfo& donor) { + vdiskId.emplace(donor.GetVDiskId()); + }); + Y_VERIFY(vdiskId); + donors.emplace_back(*vdiskId, donorVSlotId); + } + + std::sort(donors.begin(), donors.end()); + if (!donors.empty()) { + for (size_t i = 0; i < donors.size() - 1; ++i) { + const auto& x = donors[i].first; + const auto& y = donors[i + 1].first; + Y_VERIFY(x.GroupID == y.GroupID); + Y_VERIFY(x.GroupGeneration < y.GroupGeneration); + Y_VERIFY(TVDiskIdShort(x) == TVDiskIdShort(y)); + } + } + + for (const auto& [donorVDiskId, donorVSlotId] : donors) { auto *pb = vdisk->AddDonors(); - VDiskIDFromVDiskID(vdiskId, pb->MutableVDiskId()); - Serialize(pb->MutableVDiskLocation(), vslotId); + VDiskIDFromVDiskID(donorVDiskId, pb->MutableVDiskId()); + Serialize(pb->MutableVDiskLocation(), donorVSlotId); } } diff --git a/ydb/core/mind/bscontroller/config.h b/ydb/core/mind/bscontroller/config.h index 0f7fc5749c..8ffe76abf0 100644 --- a/ydb/core/mind/bscontroller/config.h +++ b/ydb/core/mind/bscontroller/config.h @@ -205,7 +205,7 @@ namespace NKikimr { return res; } - void DestroyVSlot(const TVSlotId vslotId); + void DestroyVSlot(const TVSlotId vslotId, const TVSlotInfo *ensureAcceptorSlot = nullptr); void CheckConsistency() const; diff --git a/ydb/core/mind/bscontroller/config_fit_groups.cpp b/ydb/core/mind/bscontroller/config_fit_groups.cpp index ea833da15d..a5ec4df6bb 100644 --- a/ydb/core/mind/bscontroller/config_fit_groups.cpp +++ b/ydb/core/mind/bscontroller/config_fit_groups.cpp @@ -169,8 +169,6 @@ namespace NKikimr { // mapping for audit log TMap<TVDiskIdShort, TVSlotId> replacedSlots; - TStackVec<std::pair<TVSlotId, bool>, 32> replaceQueue; - THashMap<TVDiskIdShort, TPDiskId> replacedDisks; i64 requiredSpace = Min<i64>(); bool sanitizingRequest = (State.SanitizingRequests.find(groupId) != State.SanitizingRequests.end()); @@ -213,9 +211,7 @@ namespace NKikimr { // get the current PDisk in the desired slot and replace it with the target one; if the target // PDisk id is zero, then new PDisk will be picked up automatically g[vslot->RingIdx][vslot->FailDomainIdx][vslot->VDiskIdx] = targetPDiskId; - replacedSlots.emplace(TVDiskIdShort(vslot->RingIdx, vslot->FailDomainIdx, vslot->VDiskIdx), vslot->VSlotId); - replaceQueue.emplace_back(vslot->VSlotId, State.SuppressDonorMode.count(vslot->VSlotId)); - replacedDisks.emplace(vslot->GetShortVDiskId(), vslot->VSlotId.ComprisingPDiskId()); + replacedSlots.emplace(vslot->GetShortVDiskId(), vslot->VSlotId); } else { preservedSlots.emplace(vslot->GetVDiskId(), vslot->VSlotId); auto& m = vslot->Metrics; @@ -249,17 +245,18 @@ namespace NKikimr { if (hasMissingSlots || !IgnoreGroupSanityChecks) { TGroupMapper::TForbiddenPDisks forbid; for (const auto& vslot : groupInfo->VDisksInGroup) { - for (const auto& [vslotId, vdiskId] : vslot->Donors) { + const TVDiskIdShort vdiskId = vslot->GetShortVDiskId(); + for (const TVSlotId& vslotId : vslot->Donors) { if (group[vdiskId.FailRealm][vdiskId.FailDomain][vdiskId.VDisk] == TPDiskId()) { forbid.insert(vslotId.ComprisingPDiskId()); } } } - if ((replacedDisks.empty() && sanitizingRequest) || - (State.Self.IsGroupLayoutSanitizerEnabled() && replacedDisks.size() == 1 && hasMissingSlots)) { + if ((replacedSlots.empty() && sanitizingRequest) || + (State.Self.IsGroupLayoutSanitizerEnabled() && replacedSlots.size() == 1 && hasMissingSlots)) { auto result = SanitizeGroup(groupId, group, std::move(forbid), requiredSpace, AllowUnusableDisks); - if (replacedDisks.empty()) { + if (replacedSlots.empty()) { // update information about replaced disks for (const TVSlotInfo *vslot : groupInfo->VDisksInGroup) { if (vslot->GetShortVDiskId() == result.first) { @@ -267,13 +264,15 @@ namespace NKikimr { Y_VERIFY(it != preservedSlots.end()); preservedSlots.erase(it); replacedSlots.emplace(result.first, vslot->VSlotId); - replaceQueue.emplace_back(vslot->VSlotId, State.SuppressDonorMode.count(vslot->VSlotId)); - replacedDisks.emplace(result.first, vslot->VSlotId.ComprisingPDiskId()); break; } } } } else { + THashMap<TVDiskIdShort, TPDiskId> replacedDisks; + for (const auto& [vdiskId, vslotId] : replacedSlots) { + replacedDisks.emplace(vdiskId, vslotId.ComprisingPDiskId()); + } AllocateGroup(groupId, group, replacedDisks, std::move(forbid), requiredSpace, AllowUnusableDisks); } if (!IgnoreVSlotQuotaCheck) { @@ -288,6 +287,26 @@ namespace NKikimr { } } + // make list of donors and dispose unused slots + std::vector<TVSlotId> donors; + for (const auto& [vdiskId, vslotId] : replacedSlots) { + const bool suppressDonorMode = State.SuppressDonorMode.contains(vslotId); + if (State.DonorMode && !suppressDonorMode && !State.UncommittedVSlots.count(vslotId)) { + donors.push_back(vslotId); + } else { + if (adjustSpaceAvailable) { + const TVSlotInfo *slot = State.VSlots.Find(vslotId); + Y_VERIFY(slot); + if (!slot->PDisk->SlotSpaceEnforced(State.Self)) { + // mark the space from destroyed slot as available + Mapper->AdjustSpaceAvailable(vslotId.ComprisingPDiskId(), slot->Metrics.GetAllocatedSize()); + } + } + + State.DestroyVSlot(vslotId); + } + } + // create slots for the new group auto newSlots = CreateVSlotsForGroup(groupInfo, group, preservedSlots); groupInfo->ContentChanged = true; @@ -347,36 +366,16 @@ namespace NKikimr { (Replacements, makeReplacements())); } - for (const auto& [vslotId, suppressDonorMode] : replaceQueue) { - if (State.DonorMode && !suppressDonorMode && !State.UncommittedVSlots.count(vslotId)) { - TVSlotInfo *mutableSlot = State.VSlots.FindForUpdate(vslotId); - Y_VERIFY(mutableSlot); - // make slot the donor one for the newly created slot - const auto it = newSlots.find(mutableSlot->GetShortVDiskId()); - Y_VERIFY(it != newSlots.end()); - mutableSlot->MakeDonorFor(it->second); - for (const auto& [donorVSlotId, donorVDiskId] : it->second->Donors) { - TVSlotInfo *mutableDonor = State.VSlots.FindForUpdate(donorVSlotId); - Y_VERIFY(mutableDonor); - Y_VERIFY(mutableDonor->Mood == TMood::Donor); - mutableDonor->AcceptorVSlotId = it->second->VSlotId; - } - } else { - if (adjustSpaceAvailable) { - const TVSlotInfo *slot = State.VSlots.Find(vslotId); - Y_VERIFY(slot); - if (!slot->PDisk->SlotSpaceEnforced(State.Self)) { - // mark the space from destroyed slot as available - Mapper->AdjustSpaceAvailable(vslotId.ComprisingPDiskId(), slot->Metrics.GetAllocatedSize()); - } - } - - State.DestroyVSlot(vslotId); - } + for (const TVSlotId& vslotId : donors) { + TVSlotInfo *mutableSlot = State.VSlots.FindForUpdate(vslotId); + Y_VERIFY(mutableSlot); + const auto it = newSlots.find(mutableSlot->GetShortVDiskId()); + Y_VERIFY(it != newSlots.end()); + mutableSlot->MakeDonorFor(it->second); } - } else { - Y_VERIFY(replaceQueue.empty()); } + + State.CheckConsistency(); } private: diff --git a/ydb/core/mind/bscontroller/impl.h b/ydb/core/mind/bscontroller/impl.h index 46e068df85..a4e84d0a80 100644 --- a/ydb/core/mind/bscontroller/impl.h +++ b/ydb/core/mind/bscontroller/impl.h @@ -97,8 +97,7 @@ public: Table::VDiskIdx::Type VDiskIdx = 0; Table::Mood::Type Mood; TIndirectReferable<TGroupInfo>::TPtr Group; // group to which this VSlot belongs (or nullptr if it doesn't belong to any) - std::vector<std::pair<TVSlotId, TVDiskID>> Donors; // a set of alive donors for this disk - TVSlotId AcceptorVSlotId; + THashSet<TVSlotId> Donors; // a set of alive donors for this disk (which are not being deleted) TInstant LastSeenReady; // volatile state @@ -214,10 +213,13 @@ public: void MakeDonorFor(TVSlotInfo *newSlot) { Y_VERIFY(newSlot); Y_VERIFY(!IsBeingDeleted()); + Y_VERIFY(GroupId == newSlot->GroupId); + Y_VERIFY(GetShortVDiskId() == newSlot->GetShortVDiskId()); Mood = TMood::Donor; Group = nullptr; // we are not part of this group anymore - Donors.emplace_back(VSlotId, GetVDiskId()); - newSlot->Donors = std::exchange(Donors, {}); + Donors.insert(VSlotId); + Donors.swap(newSlot->Donors); + Y_VERIFY(Donors.empty()); } TVDiskID GetVDiskId() const { @@ -1500,6 +1502,17 @@ private: void ValidateInternalState(); + const TVSlotInfo* FindAcceptor(const TVSlotInfo& donor) { + Y_VERIFY(donor.Mood == TMood::Donor); + TGroupInfo *group = FindGroup(donor.GroupId); + Y_VERIFY(group); + const ui32 orderNumber = group->Topology->GetOrderNumber(donor.GetShortVDiskId()); + const TVSlotInfo *acceptor = group->VDisksInGroup[orderNumber]; + Y_VERIFY(donor.GroupId == acceptor->GroupId && donor.GroupGeneration < acceptor->GroupGeneration && + donor.GetShortVDiskId() == acceptor->GetShortVDiskId()); + return acceptor; + } + TVSlotInfo* FindVSlot(TVSlotId id) { auto it = VSlots.find(id); return it != VSlots.end() ? it->second.Get() : nullptr; @@ -2140,7 +2153,7 @@ public: static void Serialize(NKikimrBlobStorage::TBaseConfig::TVSlot *pb, const TVSlotInfo &vslot, const TVSlotFinder& finder); static void Serialize(NKikimrBlobStorage::TBaseConfig::TGroup *pb, const TGroupInfo &group); static void SerializeDonors(NKikimrBlobStorage::TNodeWardenServiceSet::TVDisk *vdisk, const TVSlotInfo& vslot, - const TGroupInfo& group); + const TGroupInfo& group, const TVSlotFinder& finder); static void SerializeGroupInfo(NKikimrBlobStorage::TGroupInfo *group, const TGroupInfo& groupInfo, const TString& storagePoolName, const TMaybe<TKikimrScopeId>& scopeId); }; diff --git a/ydb/core/mind/bscontroller/load_everything.cpp b/ydb/core/mind/bscontroller/load_everything.cpp index 32b47f4549..3cbe0b3cd6 100644 --- a/ydb/core/mind/bscontroller/load_everything.cpp +++ b/ydb/core/mind/bscontroller/load_everything.cpp @@ -376,28 +376,11 @@ public: group->FinishVDisksInGroup(); } - // fixup donors and acceptors - { - std::map<TGroupId, std::map<TVDiskIdShort, std::vector<TVSlotInfo*>>> map; - for (const auto& [vslotId, vslot] : Self->VSlots) { - if (!vslot->IsBeingDeleted()) { - map[vslot->GroupId][vslot->GetShortVDiskId()].push_back(vslot.Get()); - } - } - for (auto& [groupId, disks] : map) { - for (auto& [shortVDiskId, array] : disks) { - auto comp = [](const TVSlotInfo *x, const TVSlotInfo *y) { - Y_VERIFY(x->GroupGeneration != y->GroupGeneration); - return x->GroupGeneration < y->GroupGeneration; - }; - std::sort(array.begin(), array.end(), comp); - TVSlotInfo *acceptor = array.back(); - for (size_t i = 0; i < array.size() - 1; ++i) { - Y_VERIFY(array[i]->Mood == TMood::Donor); - array[i]->AcceptorVSlotId = acceptor->VSlotId; - acceptor->Donors.emplace_back(array[i]->VSlotId, array[i]->GetVDiskId()); - } - } + // tie donors and acceptors + for (const auto& [vslotId, vslot] : Self->VSlots) { + if (vslot->Mood == TMood::Donor) { + const TVSlotInfo *acceptor = Self->FindAcceptor(*vslot); + const_cast<TVSlotInfo&>(*acceptor).Donors.insert(vslotId); } } diff --git a/ydb/core/mind/bscontroller/monitoring.cpp b/ydb/core/mind/bscontroller/monitoring.cpp index 11a07212ad..f95b39b1a1 100644 --- a/ydb/core/mind/bscontroller/monitoring.cpp +++ b/ydb/core/mind/bscontroller/monitoring.cpp @@ -1196,7 +1196,7 @@ void TBlobStorageController::RenderGroupDetail(IOutputStream &out, TGroupId grou std::vector<const TVSlotInfo*> donors; for (const TVSlotInfo *slot : group->VDisksInGroup) { RenderVSlotRow(out, *slot); - for (const auto& [vslotId, vdiskId] : slot->Donors) { + for (const TVSlotId& vslotId : slot->Donors) { if (const auto *x = FindVSlot(vslotId)) { donors.push_back(x); } @@ -1291,17 +1291,16 @@ void TBlobStorageController::RenderVSlotRow(IOutputStream& out, const TVSlotInfo } } TABLED() { - if (vslot.AcceptorVSlotId != TVSlotId()) { - if (const auto *x = FindVSlot(vslot.AcceptorVSlotId)) { - out << "<strong>donor for <a href='#" << x->GetVDiskId() << "'>" << vslot.AcceptorVSlotId << "</a></strong>"; - } else { - out << "?"; - } + if (vslot.Mood == TMood::Donor) { + const auto *x = FindAcceptor(vslot); + out << "<strong>donor for <a href='#" << x->GetVDiskId() << "'>" << x->VSlotId << "</a></strong>"; } else { bool first = true; - for (const auto& [vslotId, vdiskId] : vslot.Donors) { + for (const TVSlotId& donorVSlotId : vslot.Donors) { out << (std::exchange(first, false) ? "" : "<br/>"); - out << "<a href='#" << vdiskId.ToString() << "'>" << vdiskId << "</a> at " << vslotId; + const TVSlotInfo *donor = FindVSlot(donorVSlotId); + const TVDiskID vdiskId = donor->GetVDiskId(); + out << "<a href='#" << vdiskId.ToString() << "'>" << vdiskId << "</a> at " << donorVSlotId; } } } diff --git a/ydb/core/mind/bscontroller/register_node.cpp b/ydb/core/mind/bscontroller/register_node.cpp index d048549f73..8f4aef31e7 100644 --- a/ydb/core/mind/bscontroller/register_node.cpp +++ b/ydb/core/mind/bscontroller/register_node.cpp @@ -427,7 +427,14 @@ void TBlobStorageController::ReadVSlot(const TVSlotInfo& vslot, TEvBlobStorage:: if (TGroupInfo *group = FindGroup(vslot.GroupId)) { const TStoragePoolInfo& info = StoragePools.at(group->StoragePoolId); vDisk->SetStoragePoolName(info.Name); - SerializeDonors(vDisk, vslot, *group); + + auto vslotFinder = [this](const TVSlotId& vslotId, auto&& callback) { + if (const TVSlotInfo *vslot = FindVSlot(vslotId)) { + callback(*vslot); + } + }; + + SerializeDonors(vDisk, vslot, *group, vslotFinder); } else { Y_VERIFY(vslot.Mood != TMood::Donor); } @@ -535,4 +542,4 @@ void TBlobStorageController::EraseKnownDrivesOnDisconnected(TNodeInfo *nodeInfo) nodeInfo->KnownDrives.clear(); } -} // NKikimr::NBsController
\ No newline at end of file +} // NKikimr::NBsController diff --git a/ydb/core/mind/bscontroller/self_heal.cpp b/ydb/core/mind/bscontroller/self_heal.cpp index 13c67af6eb..336630a404 100644 --- a/ydb/core/mind/bscontroller/self_heal.cpp +++ b/ydb/core/mind/bscontroller/self_heal.cpp @@ -662,7 +662,7 @@ namespace NKikimr::NBsController { if (slot->Status == NKikimrBlobStorage::EVDiskStatus::READY) { // we can release donor slots without further notice then the VDisk is completely replicated; we // intentionally use GetStatus() here instead of IsReady() to prevent waiting - for (const auto& [donorVSlotId, donorVDiskId] : slot->Donors) { + for (const TVSlotId& donorVSlotId : slot->Donors) { if (!dropDonorEv) { dropDonorEv.reset(new TEvPrivate::TEvDropDonor); } |