diff --git a/weed/server/volume_grpc_erasure_coding.go b/weed/server/volume_grpc_erasure_coding.go index fe4454725..af32e801a 100644 --- a/weed/server/volume_grpc_erasure_coding.go +++ b/weed/server/volume_grpc_erasure_coding.go @@ -7,6 +7,7 @@ import ( "math" "os" "path" + "strconv" "strings" "time" @@ -338,13 +339,30 @@ func checkEcVolumeStatus(bName string, location *storage.DiskLocation) (hasEcxFi hasIdxFile = true continue } - if strings.HasPrefix(fileInfo.Name(), bName+".ec") { + if isEcDataShardFile(fileInfo.Name(), bName) { existingShardCount++ } } 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) { glog.V(0).Infof("VolumeEcShardsMount: %v", req) diff --git a/weed/server/volume_grpc_erasure_coding_test.go b/weed/server/volume_grpc_erasure_coding_test.go new file mode 100644 index 000000000..9cce6c14e --- /dev/null +++ b/weed/server/volume_grpc_erasure_coding_test.go @@ -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) + } +} +