aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralexvru <alexvru@ydb.tech>2023-03-16 15:18:57 +0300
committeralexvru <alexvru@ydb.tech>2023-03-16 15:18:57 +0300
commite3736cae776451f7494d5e73342c04e88226ab96 (patch)
tree7fa2121a56cb2735f7dca6a50a47a49f6595a490
parent15d1a0bf99bc8e273d39978cebdcaa3368ede0d7 (diff)
downloadydb-e3736cae776451f7494d5e73342c04e88226ab96.tar.gz
Improve BSC donor handling code
-rw-r--r--ydb/core/mind/bscontroller/bsc.cpp20
-rw-r--r--ydb/core/mind/bscontroller/config.cpp97
-rw-r--r--ydb/core/mind/bscontroller/config.h2
-rw-r--r--ydb/core/mind/bscontroller/config_fit_groups.cpp77
-rw-r--r--ydb/core/mind/bscontroller/impl.h23
-rw-r--r--ydb/core/mind/bscontroller/load_everything.cpp27
-rw-r--r--ydb/core/mind/bscontroller/monitoring.cpp17
-rw-r--r--ydb/core/mind/bscontroller/register_node.cpp11
-rw-r--r--ydb/core/mind/bscontroller/self_heal.cpp2
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);
}