Browse Source

fix: replace TotalShardsCount with MaxShardCount for custom EC ratio support

Critical fixes to support custom EC ratios > 14 shards:

disk_location_ec.go:
- validateEcVolume: Check shards 0-31 instead of 0-13 during validation
- removeEcVolumeFiles: Remove shards 0-31 instead of 0-13 during cleanup

ec_volume_info.go ShardBits methods:
- ShardIds(): Iterate up to MaxShardCount (32) instead of TotalShardsCount (14)
- ToUint32Slice(): Iterate up to MaxShardCount (32)
- IndexToShardId(): Iterate up to MaxShardCount (32)
- MinusParityShards(): Remove shards 10-31 instead of 10-13 (added note about Phase 2)
- Minus() shard size copy: Iterate up to MaxShardCount (32)
- resizeShardSizes(): Iterate up to MaxShardCount (32)

Without these changes:
- Custom EC ratios > 14 total shards would fail validation on startup
- Shards 14-31 would never be discovered or cleaned up
- ShardBits operations would miss shards >= 14

These changes are backward compatible - MaxShardCount (32) includes
the default TotalShardsCount (14), so existing 10+4 volumes work as before.
pull/7396/head
chrislu 1 month ago
parent
commit
38626b6a56
  1. 9
      weed/storage/disk_location_ec.go
  2. 14
      weed/storage/erasure_coding/ec_volume_info.go

9
weed/storage/disk_location_ec.go

@ -398,8 +398,8 @@ func (l *DiskLocation) validateEcVolume(collection string, vid needle.VolumeId)
var actualShardSize int64 = -1
// Count shards and validate they all have the same size (required for Reed-Solomon EC)
// Shard files (.ec00 - .ec13) are always in l.Directory, not l.IdxDirectory
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++ {
shardFileName := baseFileName + erasure_coding.ToExt(i)
fi, err := os.Stat(shardFileName)
@ -472,8 +472,9 @@ func (l *DiskLocation) removeEcVolumeFiles(collection string, vid needle.VolumeI
removeFile(indexBaseFileName+".ecx", "EC index file")
removeFile(indexBaseFileName+".ecj", "EC journal file")
// Remove all EC shard files (.ec00 ~ .ec13) from data directory
for i := 0; i < erasure_coding.TotalShardsCount; i++ {
// Remove all EC shard files (.ec00 ~ .ec31) from data directory
// Use MaxShardCount (32) to support custom EC ratios
for i := 0; i < erasure_coding.MaxShardCount; i++ {
removeFile(baseFileName+erasure_coding.ToExt(i), "EC shard file")
}
}

14
weed/storage/erasure_coding/ec_volume_info.go

@ -87,7 +87,7 @@ func (ecInfo *EcVolumeInfo) Minus(other *EcVolumeInfo) *EcVolumeInfo {
// Copy shard sizes for remaining shards
retIndex := 0
for shardId := ShardId(0); shardId < TotalShardsCount && retIndex < len(ret.ShardSizes); shardId++ {
for shardId := ShardId(0); shardId < MaxShardCount && retIndex < len(ret.ShardSizes); shardId++ {
if ret.ShardBits.HasShardId(shardId) {
if size, exists := ecInfo.GetShardSize(shardId); exists {
ret.ShardSizes[retIndex] = size
@ -135,7 +135,7 @@ func (b ShardBits) HasShardId(id ShardId) bool {
}
func (b ShardBits) ShardIds() (ret []ShardId) {
for i := ShardId(0); i < TotalShardsCount; i++ {
for i := ShardId(0); i < MaxShardCount; i++ {
if b.HasShardId(i) {
ret = append(ret, i)
}
@ -144,7 +144,7 @@ func (b ShardBits) ShardIds() (ret []ShardId) {
}
func (b ShardBits) ToUint32Slice() (ret []uint32) {
for i := uint32(0); i < TotalShardsCount; i++ {
for i := uint32(0); i < MaxShardCount; i++ {
if b.HasShardId(ShardId(i)) {
ret = append(ret, i)
}
@ -168,7 +168,9 @@ func (b ShardBits) Plus(other ShardBits) ShardBits {
}
func (b ShardBits) MinusParityShards() ShardBits {
for i := DataShardsCount; i < TotalShardsCount; i++ {
// Note: This method assumes default 10+4 EC layout where parity shards are IDs 10-31
// For custom EC ratios in Phase 2, this would need to accept an ECContext parameter
for i := DataShardsCount; i < MaxShardCount; i++ {
b = b.RemoveShardId(ShardId(i))
}
return b
@ -209,7 +211,7 @@ func (b ShardBits) IndexToShardId(index int) (shardId ShardId, found bool) {
}
currentIndex := 0
for i := ShardId(0); i < TotalShardsCount; i++ {
for i := ShardId(0); i < MaxShardCount; i++ {
if b.HasShardId(i) {
if currentIndex == index {
return i, true
@ -238,7 +240,7 @@ func (ecInfo *EcVolumeInfo) resizeShardSizes(prevShardBits ShardBits) {
// Copy existing sizes to new positions based on current ShardBits
if len(ecInfo.ShardSizes) > 0 {
newIndex := 0
for shardId := ShardId(0); shardId < TotalShardsCount && newIndex < expectedLength; shardId++ {
for shardId := ShardId(0); shardId < MaxShardCount && newIndex < expectedLength; shardId++ {
if ecInfo.ShardBits.HasShardId(shardId) {
// Try to find the size for this shard in the old array using previous ShardBits
if oldIndex, found := prevShardBits.ShardIdToIndex(shardId); found && oldIndex < len(ecInfo.ShardSizes) {

Loading…
Cancel
Save