diff --git a/weed/admin/dash/ec_shard_management.go b/weed/admin/dash/ec_shard_management.go index 34574ecdb..54fd5760c 100644 --- a/weed/admin/dash/ec_shard_management.go +++ b/weed/admin/dash/ec_shard_management.go @@ -68,7 +68,7 @@ func (s *AdminServer) GetClusterEcShards(page int, pageSize int, sortBy string, // Create individual shard entries for each shard this server has shardBits := ecShardInfo.EcIndexBits - for shardId := 0; shardId < erasure_coding.TotalShardsCount; shardId++ { + for shardId := 0; shardId < erasure_coding.MaxShardCount; shardId++ { if (shardBits & (1 << uint(shardId))) != 0 { // Mark this shard as present for this volume volumeShardsMap[volumeId][shardId] = true @@ -112,13 +112,13 @@ func (s *AdminServer) GetClusterEcShards(page int, pageSize int, sortBy string, shardCount := len(shardsPresent) // Find which shards are missing for this volume across ALL servers - for shardId := 0; shardId < erasure_coding.TotalShardsCount; shardId++ { + for shardId := 0; shardId < erasure_coding.MaxShardCount; shardId++ { if !shardsPresent[shardId] { missingShards = append(missingShards, shardId) } } - isComplete := (shardCount == erasure_coding.TotalShardsCount) + isComplete := (shardCount == erasure_coding.MaxShardCount) volumeCompleteness[volumeId] = isComplete volumeMissingShards[volumeId] = missingShards @@ -332,7 +332,7 @@ func (s *AdminServer) GetClusterEcVolumes(page int, pageSize int, sortBy string, // Process each shard this server has for this volume shardBits := ecShardInfo.EcIndexBits - for shardId := 0; shardId < erasure_coding.TotalShardsCount; shardId++ { + for shardId := 0; shardId < erasure_coding.MaxShardCount; shardId++ { if (shardBits & (1 << uint(shardId))) != 0 { // Record shard location volume.ShardLocations[shardId] = node.Id @@ -394,7 +394,7 @@ func (s *AdminServer) GetClusterEcVolumes(page int, pageSize int, sortBy string, // Find missing shards var missingShards []int - for shardId := 0; shardId < erasure_coding.TotalShardsCount; shardId++ { + for shardId := 0; shardId < erasure_coding.MaxShardCount; shardId++ { if _, exists := volume.ShardLocations[shardId]; !exists { missingShards = append(missingShards, shardId) } @@ -523,7 +523,7 @@ func sortEcVolumes(volumes []EcVolumeWithShards, sortBy string, sortOrder string // getShardCount returns the number of shards represented by the bitmap func getShardCount(ecIndexBits uint32) int { count := 0 - for i := 0; i < erasure_coding.TotalShardsCount; i++ { + for i := 0; i < erasure_coding.MaxShardCount; i++ { if (ecIndexBits & (1 << uint(i))) != 0 { count++ } @@ -534,7 +534,7 @@ func getShardCount(ecIndexBits uint32) int { // getMissingShards returns a slice of missing shard IDs for a volume func getMissingShards(ecIndexBits uint32) []int { var missing []int - for i := 0; i < erasure_coding.TotalShardsCount; i++ { + for i := 0; i < erasure_coding.MaxShardCount; i++ { if (ecIndexBits & (1 << uint(i))) == 0 { missing = append(missing, i) } @@ -614,7 +614,7 @@ func (s *AdminServer) GetEcVolumeDetails(volumeID uint32, sortBy string, sortOrd // Create individual shard entries for each shard this server has shardBits := ecShardInfo.EcIndexBits - for shardId := 0; shardId < erasure_coding.TotalShardsCount; shardId++ { + for shardId := 0; shardId < erasure_coding.MaxShardCount; shardId++ { if (shardBits & (1 << uint(shardId))) != 0 { ecShard := EcShardWithInfo{ VolumeID: ecShardInfo.Id, @@ -698,11 +698,11 @@ func (s *AdminServer) GetEcVolumeDetails(volumeID uint32, sortBy string, sortOrd } totalUniqueShards := len(foundShards) - isComplete := (totalUniqueShards == erasure_coding.TotalShardsCount) + isComplete := (totalUniqueShards == erasure_coding.MaxShardCount) // Calculate missing shards var missingShards []int - for i := 0; i < erasure_coding.TotalShardsCount; i++ { + for i := 0; i < erasure_coding.MaxShardCount; i++ { if !foundShards[i] { missingShards = append(missingShards, i) } diff --git a/weed/shell/command_ec_common.go b/weed/shell/command_ec_common.go index 665daa1b8..3616c4e16 100644 --- a/weed/shell/command_ec_common.go +++ b/weed/shell/command_ec_common.go @@ -622,7 +622,8 @@ func (ecb *ecBalancer) deleteDuplicatedEcShards(collection string) error { func (ecb *ecBalancer) doDeduplicateEcShards(collection string, vid needle.VolumeId, locations []*EcNode) error { // check whether this volume has ecNodes that are over average - shardToLocations := make([][]*EcNode, erasure_coding.TotalShardsCount) + // Use MaxShardCount (32) to support custom EC ratios + shardToLocations := make([][]*EcNode, erasure_coding.MaxShardCount) for _, ecNode := range locations { shardBits := findEcVolumeShards(ecNode, vid) for _, shardId := range shardBits.ShardIds() { diff --git a/weed/shell/command_ec_rebuild.go b/weed/shell/command_ec_rebuild.go index 8cae77434..2e8d9b239 100644 --- a/weed/shell/command_ec_rebuild.go +++ b/weed/shell/command_ec_rebuild.go @@ -261,12 +261,13 @@ type EcShardLocations [][]*EcNode func (ecShardMap EcShardMap) registerEcNode(ecNode *EcNode, collection string) { for _, diskInfo := range ecNode.info.DiskInfos { for _, shardInfo := range diskInfo.EcShardInfos { - if shardInfo.Collection == collection { - existing, found := ecShardMap[needle.VolumeId(shardInfo.Id)] - if !found { - existing = make([][]*EcNode, erasure_coding.TotalShardsCount) - ecShardMap[needle.VolumeId(shardInfo.Id)] = existing - } + if shardInfo.Collection == collection { + existing, found := ecShardMap[needle.VolumeId(shardInfo.Id)] + if !found { + // Use MaxShardCount (32) to support custom EC ratios + existing = make([][]*EcNode, erasure_coding.MaxShardCount) + ecShardMap[needle.VolumeId(shardInfo.Id)] = existing + } for _, shardId := range erasure_coding.ShardBits(shardInfo.EcIndexBits).ShardIds() { existing[shardId] = append(existing[shardId], ecNode) } diff --git a/weed/storage/store_ec.go b/weed/storage/store_ec.go index 0126ad9d4..6a26b4ae0 100644 --- a/weed/storage/store_ec.go +++ b/weed/storage/store_ec.go @@ -350,7 +350,8 @@ func (s *Store) recoverOneRemoteEcShardInterval(needleId types.NeedleId, ecVolum return 0, false, fmt.Errorf("failed to create encoder: %w", err) } - bufs := make([][]byte, erasure_coding.TotalShardsCount) + // Use MaxShardCount to support custom EC ratios up to 32 shards + bufs := make([][]byte, erasure_coding.MaxShardCount) var wg sync.WaitGroup ecVolume.ShardLocationsLock.RLock() diff --git a/weed/topology/topology_ec.go b/weed/topology/topology_ec.go index 844e92f55..7097cb84b 100644 --- a/weed/topology/topology_ec.go +++ b/weed/topology/topology_ec.go @@ -10,7 +10,8 @@ import ( type EcShardLocations struct { Collection string - Locations [erasure_coding.TotalShardsCount][]*DataNode + // Use MaxShardCount (32) to support custom EC ratios + Locations [erasure_coding.MaxShardCount][]*DataNode } func (t *Topology) SyncDataNodeEcShards(shardInfos []*master_pb.VolumeEcShardInformationMessage, dn *DataNode) (newShards, deletedShards []*erasure_coding.EcVolumeInfo) { diff --git a/weed/worker/tasks/erasure_coding/ec_task.go b/weed/worker/tasks/erasure_coding/ec_task.go index 18f192bc9..df7fc94f9 100644 --- a/weed/worker/tasks/erasure_coding/ec_task.go +++ b/weed/worker/tasks/erasure_coding/ec_task.go @@ -374,7 +374,8 @@ func (t *ErasureCodingTask) generateEcShardsLocally(localFiles map[string]string var generatedShards []string var totalShardSize int64 - for i := 0; i < erasure_coding.TotalShardsCount; i++ { + // Check up to MaxShardCount (32) to support custom EC ratios + for i := 0; i < erasure_coding.MaxShardCount; i++ { shardFile := fmt.Sprintf("%s.ec%02d", baseName, i) if info, err := os.Stat(shardFile); err == nil { shardKey := fmt.Sprintf("ec%02d", i)