fix(topology): restore active count after vacuum recovery (#9770)

This commit is contained in:
steve.wei
2026-06-01 15:23:22 -07:00
committed by GitHub
parent 2386fa550a
commit 1313600b9e
2 changed files with 67 additions and 4 deletions
+18 -4
View File
@@ -788,9 +788,15 @@ func (vl *VolumeLayout) SetVolumeUnavailable(dn *DataNode, vid needle.VolumeId)
}
return false
}
func (vl *VolumeLayout) SetVolumeAvailable(dn *DataNode, vid needle.VolumeId, isReadOnly, isFullCapacity bool) bool {
func (vl *VolumeLayout) SetVolumeAvailable(dn *DataNode, vid needle.VolumeId, isReadOnly, isFullCapacity bool) (becameWritable bool) {
restoreActiveVolumeCount := false
vl.accessLock.Lock()
defer vl.accessLock.Unlock()
defer func() {
vl.accessLock.Unlock()
if restoreActiveVolumeCount {
vl.adjustActiveVolumeCount(vid, +1)
}
}()
vInfo, err := dn.GetVolumesById(vid)
if err != nil {
@@ -804,9 +810,17 @@ func (vl *VolumeLayout) SetVolumeAvailable(dn *DataNode, vid needle.VolumeId, is
}
if vl.enoughCopies(vid) {
return vl.setVolumeWritable(vid)
becameWritable = vl.setVolumeWritable(vid)
if becameWritable {
if st := vl.sizeTracking[vid]; st != nil && !st.fullSince.IsZero() {
// fullSince marks a prior capacity-full removal that already
// decremented activeVolumeCount. Re-adding must pair it once.
st.fullSince = time.Time{}
restoreActiveVolumeCount = true
}
}
}
return false
return becameWritable
}
func (vl *VolumeLayout) enoughCopies(vid needle.VolumeId) bool {
@@ -67,3 +67,52 @@ func TestSetVolumeCapacityFullStampsFullSinceAndRecovers(t *testing.T) {
t.Fatalf("expected fullSince cleared after recovery")
}
}
func TestSetVolumeAvailableRestoresActiveCountForCapacityFullVolume(t *testing.T) {
layout := `
{
"dc1":{
"rack1":{
"server1":{
"volumes":[
{"id":1, "size":4000, "replication":"000"}
],
"limit":10
}
}
}
}
`
topo, vl := setupPickTest(t, layout, 10000)
initialActive := topo.diskUsages.usages[types.HardDriveType].activeVolumeCount
if !vl.SetVolumeCapacityFull(1) {
t.Fatalf("SetVolumeCapacityFull should report the volume was writable")
}
vl.AdjustActiveVolumeCountForFull(1)
if got := topo.diskUsages.usages[types.HardDriveType].activeVolumeCount; got != initialActive-1 {
t.Fatalf("expected activeVolumeCount decremented to %d, got %d", initialActive-1, got)
}
vl.accessLock.RLock()
dn := vl.vid2location[1].list[0]
vl.accessLock.RUnlock()
if !vl.SetVolumeAvailable(dn, 1, false, false) {
t.Fatalf("SetVolumeAvailable should report the volume became writable")
}
if got := topo.diskUsages.usages[types.HardDriveType].activeVolumeCount; got != initialActive {
t.Fatalf("expected SetVolumeAvailable to restore activeVolumeCount to %d, got %d", initialActive, got)
}
if !vl.sizeTracking[1].fullSince.IsZero() {
t.Fatalf("expected SetVolumeAvailable to clear fullSince after restoring activeVolumeCount")
}
advanceSizeTrackingClock(vl, 1, capacityRecoveryDelay+time.Second)
if vl.UpdateVolumeSize(1, 4000, 0) {
t.Fatalf("heartbeat recovery should not fire after SetVolumeAvailable already restored the volume")
}
if got := topo.diskUsages.usages[types.HardDriveType].activeVolumeCount; got != initialActive {
t.Fatalf("expected activeVolumeCount to remain %d, got %d", initialActive, got)
}
}