@@ -7,6 +7,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -338,13 +339,30 @@ func checkEcVolumeStatus(bName string, location *storage.DiskLocation) (hasEcxFi
|
|||||||
hasIdxFile = true
|
hasIdxFile = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(fileInfo.Name(), bName+".ec") {
|
if isEcDataShardFile(fileInfo.Name(), bName) {
|
||||||
existingShardCount++
|
existingShardCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hasEcxFile, hasIdxFile, existingShardCount, nil
|
return hasEcxFile, hasIdxFile, existingShardCount, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isEcDataShardFile(fileName, baseName string) bool {
|
||||||
|
const ecDataShardSuffixLen = 2 // ".ecNN"
|
||||||
|
prefix := baseName + ".ec"
|
||||||
|
if !strings.HasPrefix(fileName, prefix) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
suffix := strings.TrimPrefix(fileName, prefix)
|
||||||
|
if len(suffix) != ecDataShardSuffixLen {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
shardId, err := strconv.Atoi(suffix)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return shardId >= 0 && shardId < erasure_coding.MaxShardCount
|
||||||
|
}
|
||||||
|
|
||||||
func (vs *VolumeServer) VolumeEcShardsMount(ctx context.Context, req *volume_server_pb.VolumeEcShardsMountRequest) (*volume_server_pb.VolumeEcShardsMountResponse, error) {
|
func (vs *VolumeServer) VolumeEcShardsMount(ctx context.Context, req *volume_server_pb.VolumeEcShardsMountRequest) (*volume_server_pb.VolumeEcShardsMountResponse, error) {
|
||||||
|
|
||||||
glog.V(0).Infof("VolumeEcShardsMount: %v", req)
|
glog.V(0).Infof("VolumeEcShardsMount: %v", req)
|
||||||
|
|||||||
57
weed/server/volume_grpc_erasure_coding_test.go
Normal file
57
weed/server/volume_grpc_erasure_coding_test.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package weed_server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/seaweedfs/seaweedfs/weed/storage"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCheckEcVolumeStatusCountOnlyDataShards(t *testing.T) {
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
dataDir := filepath.Join(tempDir, "data")
|
||||||
|
idxDir := filepath.Join(tempDir, "idx")
|
||||||
|
if err := os.MkdirAll(dataDir, 0o755); err != nil {
|
||||||
|
t.Fatalf("mkdir data dir: %v", err)
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll(idxDir, 0o755); err != nil {
|
||||||
|
t.Fatalf("mkdir idx dir: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
baseName := "7"
|
||||||
|
filesToCreate := []string{
|
||||||
|
filepath.Join(dataDir, baseName+".ec00"),
|
||||||
|
filepath.Join(dataDir, baseName+".ec09"),
|
||||||
|
filepath.Join(dataDir, baseName+".ec13"),
|
||||||
|
filepath.Join(idxDir, baseName+".ecx"),
|
||||||
|
filepath.Join(idxDir, baseName+".ecj"),
|
||||||
|
filepath.Join(idxDir, baseName+".idx"),
|
||||||
|
}
|
||||||
|
for _, fileName := range filesToCreate {
|
||||||
|
if err := os.WriteFile(fileName, []byte("x"), 0o644); err != nil {
|
||||||
|
t.Fatalf("create %s: %v", fileName, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
location := &storage.DiskLocation{
|
||||||
|
Directory: dataDir,
|
||||||
|
IdxDirectory: idxDir,
|
||||||
|
}
|
||||||
|
|
||||||
|
hasEcxFile, hasIdxFile, shardCount, err := checkEcVolumeStatus(baseName, location)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("checkEcVolumeStatus: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasEcxFile {
|
||||||
|
t.Fatalf("expected hasEcxFile=true")
|
||||||
|
}
|
||||||
|
if !hasIdxFile {
|
||||||
|
t.Fatalf("expected hasIdxFile=true")
|
||||||
|
}
|
||||||
|
if shardCount != 3 {
|
||||||
|
t.Fatalf("expected shardCount=3, got %d", shardCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user