Implement RPC skeleton for regular/EC volumes scrubbing. (#8187)

* Implement RPC skeleton for regular/EC volumes scrubbing.

See https://github.com/seaweedfs/seaweedfs/issues/8018 for details.

* Minor proto improvements for `ScrubVolume()`, `ScrubEcVolume()`:

  - Add fields for scrubbing details in `ScrubVolumeResponse` and `ScrubEcVolumeResponse`,
    instead of reporting these through RPC errors.
  - Return a list of broken shards when scrubbing EC volumes, via `EcShardInfo'.
This commit is contained in:
Lisandro Pin
2026-02-03 02:55:04 +01:00
committed by GitHub
parent 345ac950b6
commit ff5a8f0579
7 changed files with 950 additions and 296 deletions

View File

@@ -5,6 +5,7 @@ import (
"os"
"path/filepath"
"runtime"
"slices"
"strconv"
"strings"
"sync"
@@ -395,6 +396,38 @@ func (l *DiskLocation) FindVolume(vid needle.VolumeId) (*Volume, bool) {
return v, ok
}
// Returns all regular volume IDs stored at this location.
func (l *DiskLocation) VolumeIds() []needle.VolumeId {
l.volumesLock.RLock()
defer l.volumesLock.RUnlock()
vids := make([]needle.VolumeId, len(l.volumes))
i := 0
for vid := range l.volumes {
vids[i] = vid
i++
}
slices.Sort(vids)
return vids
}
// Returns all EC volume IDs stored at this location.
func (l *DiskLocation) EcVolumeIds() []needle.VolumeId {
l.ecVolumesLock.RLock()
defer l.ecVolumesLock.RUnlock()
vids := make([]needle.VolumeId, len(l.ecVolumes))
i := 0
for vid := range l.ecVolumes {
vids[i] = vid
i++
}
slices.Sort(vids)
return vids
}
func (l *DiskLocation) VolumesLen() int {
l.volumesLock.RLock()
defer l.volumesLock.RUnlock()

View File

@@ -1,10 +1,12 @@
package storage
import (
"reflect"
"testing"
"time"
"github.com/seaweedfs/seaweedfs/weed/storage/backend"
"github.com/seaweedfs/seaweedfs/weed/storage/erasure_coding"
"github.com/seaweedfs/seaweedfs/weed/storage/needle"
"github.com/seaweedfs/seaweedfs/weed/storage/types"
"github.com/seaweedfs/seaweedfs/weed/util"
@@ -75,5 +77,26 @@ func TestUnUsedSpace(t *testing.T) {
if unUsedSpace != 0 {
t.Errorf("unUsedSpace incorrect: %d != %d", unUsedSpace, 0)
}
}
func TestResolveVolumeIDs(t *testing.T) {
l := DiskLocation{
volumes: map[needle.VolumeId]*Volume{
0: &Volume{},
1: &Volume{},
2: &Volume{},
},
ecVolumes: map[needle.VolumeId]*erasure_coding.EcVolume{
3: &erasure_coding.EcVolume{},
4: &erasure_coding.EcVolume{},
5: &erasure_coding.EcVolume{},
},
}
if got, want := l.VolumeIds(), []needle.VolumeId{0, 1, 2}; !reflect.DeepEqual(got, want) {
t.Errorf("wanted volume IDs %v, got %v", want, got)
}
if got, want := l.EcVolumeIds(), []needle.VolumeId{3, 4, 5}; !reflect.DeepEqual(got, want) {
t.Errorf("wanted EC volume IDs %v, got %v", want, got)
}
}