mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-01 04:05:54 +00:00
* shell: say which read-only volumes volume.vacuum leaves alone volume.vacuum without -volumeId runs the same sweep as the automatic vacuum, which skips read-only volumes, and the master's response carries no result. An operator whose disk filled up runs the command, sees it return, and watches nothing change (issue #11516). Before issuing the request, list the read-only volumes whose garbage is at or above the threshold and point at -volumeId, which is the explicit path PR #9861 opened for them. The help text says the same. * shell: volume.vacuum hint survives a failed listing and looks at every replica Review follow-ups: a failed topology listing no longer stops a sweep without -volumeId, it only drops the hint; a volume counts as read-only when any replica is, with the garbage ratio taken from the replica that reports the most, which is what the sweep itself does; a converted index that reports deletes without sizes is listed rather than hidden; and the threshold is printed as given instead of rounded to two decimals. * shell: do not guess a garbage ratio for a converted index The master cannot compute one for a volume that reports deletes without their sizes, and a guess of 1 would send the operator to -volumeId for a volume the server may decline at that threshold. Leave it out and say so.
59 lines
2.8 KiB
Go
59 lines
2.8 KiB
Go
package shell
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/pb/master_pb"
|
|
)
|
|
|
|
func vacuumTestTopology(nodes ...*master_pb.DataNodeInfo) *master_pb.TopologyInfo {
|
|
return &master_pb.TopologyInfo{
|
|
DataCenterInfos: []*master_pb.DataCenterInfo{{
|
|
RackInfos: []*master_pb.RackInfo{{DataNodeInfos: nodes}},
|
|
}},
|
|
}
|
|
}
|
|
|
|
func vacuumTestNode(volumes ...*master_pb.VolumeInformationMessage) *master_pb.DataNodeInfo {
|
|
return &master_pb.DataNodeInfo{
|
|
DiskInfos: map[string]*master_pb.DiskInfo{"": {VolumeInfos: volumes}},
|
|
}
|
|
}
|
|
|
|
func TestReadOnlyVolumesAboveThreshold(t *testing.T) {
|
|
readOnlyHalfGarbage := &master_pb.VolumeInformationMessage{Id: 1, Collection: "a", Size: 100, DeletedByteCount: 50, ReadOnly: true}
|
|
writableMostlyGarbage := &master_pb.VolumeInformationMessage{Id: 2, Collection: "a", Size: 100, DeletedByteCount: 90}
|
|
readOnlyLittleGarbage := &master_pb.VolumeInformationMessage{Id: 3, Collection: "a", Size: 100, DeletedByteCount: 10, ReadOnly: true}
|
|
readOnlyOtherCollection := &master_pb.VolumeInformationMessage{Id: 4, Collection: "b", Size: 100, DeletedByteCount: 100, ReadOnly: true}
|
|
readOnlyEmpty := &master_pb.VolumeInformationMessage{Id: 5, Collection: "a", Size: 0, DeletedByteCount: 0, ReadOnly: true}
|
|
readOnlyAtThreshold := &master_pb.VolumeInformationMessage{Id: 6, Collection: "a", Size: 100, DeletedByteCount: 30, ReadOnly: true}
|
|
// the sweep skips a volume when any replica is read-only, and the garbage
|
|
// may sit on the other replica
|
|
mixedReadOnlyReplica := &master_pb.VolumeInformationMessage{Id: 7, Collection: "a", Size: 100, DeletedByteCount: 5, ReadOnly: true}
|
|
mixedWritableReplica := &master_pb.VolumeInformationMessage{Id: 7, Collection: "a", Size: 100, DeletedByteCount: 60}
|
|
// a converted index reports deletes without their sizes; the ratio is not
|
|
// knowable from here, so it is not listed
|
|
readOnlyConvertedIndex := &master_pb.VolumeInformationMessage{Id: 8, Collection: "a", Size: 100, DeleteCount: 2, DeletedByteCount: 0, ReadOnly: true}
|
|
|
|
topo := vacuumTestTopology(
|
|
vacuumTestNode(readOnlyHalfGarbage, writableMostlyGarbage, readOnlyLittleGarbage, readOnlyEmpty, readOnlyAtThreshold, mixedReadOnlyReplica, readOnlyConvertedIndex),
|
|
// the second replica of volume 1 must not list it twice
|
|
vacuumTestNode(readOnlyHalfGarbage, readOnlyOtherCollection, mixedWritableReplica),
|
|
)
|
|
|
|
got := readOnlyVolumesAboveThreshold(topo, "a", 0.3)
|
|
if want := []uint32{1, 6, 7}; !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("collection a, threshold 0.3: got %v, want %v", got, want)
|
|
}
|
|
|
|
got = readOnlyVolumesAboveThreshold(topo, "", 0.3)
|
|
if want := []uint32{1, 4, 6, 7}; !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("all collections, threshold 0.3: got %v, want %v", got, want)
|
|
}
|
|
|
|
if got := readOnlyVolumesAboveThreshold(topo, "a", 0.95); len(got) != 0 {
|
|
t.Fatalf("threshold 0.95: got %v, want none", got)
|
|
}
|
|
}
|