You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							87 lines
						
					
					
						
							2.7 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							87 lines
						
					
					
						
							2.7 KiB
						
					
					
				
								package erasure_coding
							 | 
						|
								
							 | 
						|
								import (
							 | 
						|
									"github.com/chrislusf/seaweedfs/weed/storage/types"
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								type Interval struct {
							 | 
						|
									BlockIndex          int
							 | 
						|
									InnerBlockOffset    int64
							 | 
						|
									Size                types.Size
							 | 
						|
									IsLargeBlock        bool
							 | 
						|
									LargeBlockRowsCount int
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func LocateData(largeBlockLength, smallBlockLength int64, datSize int64, offset int64, size types.Size) (intervals []Interval) {
							 | 
						|
									blockIndex, isLargeBlock, innerBlockOffset := locateOffset(largeBlockLength, smallBlockLength, datSize, offset)
							 | 
						|
								
							 | 
						|
									// adding DataShardsCount*smallBlockLength to ensure we can derive the number of large block size from a shard size
							 | 
						|
									nLargeBlockRows := int((datSize + DataShardsCount*smallBlockLength) / (largeBlockLength * DataShardsCount))
							 | 
						|
								
							 | 
						|
									for size > 0 {
							 | 
						|
										interval := Interval{
							 | 
						|
											BlockIndex:          blockIndex,
							 | 
						|
											InnerBlockOffset:    innerBlockOffset,
							 | 
						|
											IsLargeBlock:        isLargeBlock,
							 | 
						|
											LargeBlockRowsCount: nLargeBlockRows,
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										blockRemaining := largeBlockLength - innerBlockOffset
							 | 
						|
										if !isLargeBlock {
							 | 
						|
											blockRemaining = smallBlockLength - innerBlockOffset
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										if int64(size) <= blockRemaining {
							 | 
						|
											interval.Size = size
							 | 
						|
											intervals = append(intervals, interval)
							 | 
						|
											return
							 | 
						|
										}
							 | 
						|
										interval.Size = types.Size(blockRemaining)
							 | 
						|
										intervals = append(intervals, interval)
							 | 
						|
								
							 | 
						|
										size -= interval.Size
							 | 
						|
										blockIndex += 1
							 | 
						|
										if isLargeBlock && blockIndex == nLargeBlockRows*DataShardsCount {
							 | 
						|
											isLargeBlock = false
							 | 
						|
											blockIndex = 0
							 | 
						|
										}
							 | 
						|
										innerBlockOffset = 0
							 | 
						|
								
							 | 
						|
									}
							 | 
						|
									return
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func locateOffset(largeBlockLength, smallBlockLength int64, datSize int64, offset int64) (blockIndex int, isLargeBlock bool, innerBlockOffset int64) {
							 | 
						|
									largeRowSize := largeBlockLength * DataShardsCount
							 | 
						|
									nLargeBlockRows := datSize / (largeBlockLength * DataShardsCount)
							 | 
						|
								
							 | 
						|
									// if offset is within the large block area
							 | 
						|
									if offset < nLargeBlockRows*largeRowSize {
							 | 
						|
										isLargeBlock = true
							 | 
						|
										blockIndex, innerBlockOffset = locateOffsetWithinBlocks(largeBlockLength, offset)
							 | 
						|
										return
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									isLargeBlock = false
							 | 
						|
									offset -= nLargeBlockRows * largeRowSize
							 | 
						|
									blockIndex, innerBlockOffset = locateOffsetWithinBlocks(smallBlockLength, offset)
							 | 
						|
									return
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func locateOffsetWithinBlocks(blockLength int64, offset int64) (blockIndex int, innerBlockOffset int64) {
							 | 
						|
									blockIndex = int(offset / blockLength)
							 | 
						|
									innerBlockOffset = offset % blockLength
							 | 
						|
									return
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func (interval Interval) ToShardIdAndOffset(largeBlockSize, smallBlockSize int64) (ShardId, int64) {
							 | 
						|
									ecFileOffset := interval.InnerBlockOffset
							 | 
						|
									rowIndex := interval.BlockIndex / DataShardsCount
							 | 
						|
									if interval.IsLargeBlock {
							 | 
						|
										ecFileOffset += int64(rowIndex) * largeBlockSize
							 | 
						|
									} else {
							 | 
						|
										ecFileOffset += int64(interval.LargeBlockRowsCount)*largeBlockSize + int64(rowIndex)*smallBlockSize
							 | 
						|
									}
							 | 
						|
									ecFileIndex := interval.BlockIndex % DataShardsCount
							 | 
						|
									return ShardId(ecFileIndex), ecFileOffset
							 | 
						|
								}
							 |