diff --git a/weed/storage/volume_info.go b/weed/storage/volume_info.go index e993c9c58..5608d596c 100644 --- a/weed/storage/volume_info.go +++ b/weed/storage/volume_info.go @@ -10,23 +10,29 @@ import ( "github.com/seaweedfs/seaweedfs/weed/storage/super_block" ) +// Held for every volume replica, so the fields are grouped by size rather than +// by meaning: interleaved, each one-byte field rounds up to a whole word. type VolumeInfo struct { - Id needle.VolumeId - Size uint64 - ReplicaPlacement *super_block.ReplicaPlacement - Ttl *needle.TTL - DiskType string - DiskId uint32 Collection string - Version needle.Version - FileCount int - DeleteCount int - DeletedByteCount uint64 - ReadOnly bool - CompactRevision uint32 - ModifiedAtSecond int64 + DiskType string RemoteStorageName string RemoteStorageKey string + + ReplicaPlacement *super_block.ReplicaPlacement + Ttl *needle.TTL + + Size uint64 + FileCount int + DeleteCount int + DeletedByteCount uint64 + ModifiedAtSecond int64 + + Id needle.VolumeId + DiskId uint32 + CompactRevision uint32 + + Version needle.Version + ReadOnly bool } func NewVolumeInfo(m *master_pb.VolumeInformationMessage) (vi VolumeInfo, err error) { diff --git a/weed/storage/volume_info_layout_test.go b/weed/storage/volume_info_layout_test.go new file mode 100644 index 000000000..6d862b96d --- /dev/null +++ b/weed/storage/volume_info_layout_test.go @@ -0,0 +1,34 @@ +package storage + +import ( + "reflect" + "testing" + "unsafe" +) + +// Nothing else in the package would notice if someone grouped the fields by +// meaning again, and the padding is multiplied by every volume a master holds. +func TestVolumeInfoHasNoInteriorPadding(t *testing.T) { + typ := reflect.TypeOf(VolumeInfo{}) + + var used, interior uintptr + prevEnd := uintptr(0) + for i := 0; i < typ.NumField(); i++ { + f := typ.Field(i) + if gap := f.Offset - prevEnd; gap > 0 { + t.Errorf("%d bytes of padding before %s, at offset %d: order the fields by size so they pack", + gap, f.Name, prevEnd) + interior += gap + } + used += f.Type.Size() + prevEnd = f.Offset + f.Type.Size() + } + + size := unsafe.Sizeof(VolumeInfo{}) + if tail := size - prevEnd; tail > 7 { + t.Errorf("%d bytes of padding at the end, more than alignment requires", tail) + } + if interior == 0 { + t.Logf("%d bytes of fields in a %d byte struct", used, size) + } +}