topology: treat a nil ttl as the empty ttl when looking for duplicate volume ids

Volume layouts are keyed by ttl.String(), so a nil ttl and the empty ttl
share one layout. ttlEqual told them apart, so a replica reported with a nil
ttl into a layout created with the empty ttl matched its own layout as a
duplicate, and every copy was quarantined.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Chris LuandClaude Opus 5.5 committed 2026-11-12 21:54:45 -08:00
1 parent 917cf534db
commit 29eae72328
2 files changed
+25 -4

No files matched your search

+24
View File
@@ -73,6 +73,30 @@ func TestSameLayoutReplicaIsNotDuplicate(t *testing.T) {
}
}
func TestSameLayoutReplicaWithoutTtlIsNotDuplicate(t *testing.T) {
topo := NewTopology("topo", nil, 128, 3, false)
rp, _ := super_block.NewReplicaPlacementFromString("001")
dn1 := NewDataNode("server1")
dn1.Ip = "10.0.0.1"
dn1.Port = 8080
dn2 := NewDataNode("server2")
dn2.Ip = "10.0.0.2"
dn2.Port = 8080
v1 := storage.VolumeInfo{Id: 7, Collection: "a", ReplicaPlacement: rp, Ttl: needle.EMPTY_TTL}
v2 := storage.VolumeInfo{Id: 7, Collection: "a", ReplicaPlacement: rp}
dn1.UpdateVolumes([]storage.VolumeInfo{v1})
dn2.UpdateVolumes([]storage.VolumeInfo{v2})
topo.RegisterVolumeLayout(v1, dn1)
topo.RegisterVolumeLayout(v2, dn2)
topo.duplicateFlagChecks.Wait()
if topo.isQuarantined(dn1, v1.Id) || topo.isQuarantined(dn2, v2.Id) {
t.Fatal("a nil ttl and the empty ttl share one layout, so the replica is not a duplicate")
}
}
func TestSameNodeVolumeMoveIsNotDuplicate(t *testing.T) {
topo := NewTopology("topo", nil, 128, 3, false)
rp, _ := super_block.NewReplicaPlacementFromString("000")
+1 -4
View File
@@ -1084,10 +1084,7 @@ func volumeLayoutKey(collection string, rp *super_block.ReplicaPlacement, ttl *n
}
func ttlEqual(a, b *needle.TTL) bool {
if a == nil || b == nil {
return a == b
}
return a.ToUint32() == b.ToUint32()
return a.String() == b.String()
}
// findDuplicateVolumeLayouts reports every layout that already holds v.Id on