mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-20 13:30:46 +02:00
NewReplicaPlacementFromByte formatted the byte with fmt.Sprintf and parsed the result back, allocating a string and a ReplicaPlacement every call. The master calls it once per volume in every heartbeat, and keeps the pointer for the lifetime of the volume, so a cluster with 1.6M volume replicas carries 1.6M of these where a handful of distinct values exist. The table is a flat pointer-free array, so it costs 6KB of static data and no heap objects however few placements a cluster actually uses. A byte only ever decodes to a valid placement, so the table is complete and the error return stays nil. BenchmarkSyncDataNodeRegistration/100000Volumes 500601 allocs/op -> 300589 allocs/op
64 lines
1.5 KiB
Go
64 lines
1.5 KiB
Go
package super_block
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
)
|
|
|
|
func TestReplicaPlacementFromByteMatchesString(t *testing.T) {
|
|
for b := 0; b < 256; b++ {
|
|
want, err := NewReplicaPlacementFromString(fmt.Sprintf("%03d", b))
|
|
if err != nil {
|
|
t.Fatalf("byte %d: %v", b, err)
|
|
}
|
|
got, err := NewReplicaPlacementFromByte(byte(b))
|
|
if err != nil {
|
|
t.Fatalf("byte %d: %v", b, err)
|
|
}
|
|
if !got.Equals(want) {
|
|
t.Errorf("byte %d: got %+v, want %+v", b, got, want)
|
|
}
|
|
if got.Byte() != byte(b) {
|
|
t.Errorf("byte %d: round trip gave %d", b, got.Byte())
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestReplicaPlacementSerialDeserial(t *testing.T) {
|
|
rp, _ := NewReplicaPlacementFromString("001")
|
|
newRp, _ := NewReplicaPlacementFromByte(rp.Byte())
|
|
if rp.String() != newRp.String() {
|
|
println("expected:", rp.String(), "actual:", newRp.String())
|
|
t.Fail()
|
|
}
|
|
}
|
|
|
|
func TestReplicaPlacementHasReplication(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
replicaPlacement string
|
|
want bool
|
|
}{
|
|
{"empty replica placement", "", false},
|
|
{"no replication", "000", false},
|
|
{"same rack replication", "100", true},
|
|
{"diff rack replication", "020", true},
|
|
{"DC replication", "003", true},
|
|
{"full replication", "155", true},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
rp, err := NewReplicaPlacementFromString(tc.replicaPlacement)
|
|
if err != nil {
|
|
t.Errorf("failed to initialize ReplicaPlacement: %v", err)
|
|
return
|
|
}
|
|
|
|
if got, want := rp.HasReplication(), tc.want; got != want {
|
|
t.Errorf("expected %v, got %v", want, got)
|
|
}
|
|
})
|
|
}
|
|
}
|