github.com/upyun/upx@v0.4.7-0.20240419023638-b184a7cb7c10/partial/chunk.go (about)

     1  package partial
     2  
     3  import (
     4  	"sync/atomic"
     5  )
     6  
     7  type Chunk struct {
     8  	// 切片的顺序
     9  	index int64
    10  
    11  	// 切片内容的在源文件的开始地址
    12  	start int64
    13  
    14  	// 切片内容在源文件的结束地址
    15  	end int64
    16  
    17  	// 切片任务的下载错误
    18  	err error
    19  
    20  	// 下载完的切片的具体内容
    21  	buffer []byte
    22  }
    23  
    24  func NewChunk(index, start, end int64) *Chunk {
    25  	chunk := &Chunk{
    26  		start: start,
    27  		end:   end,
    28  		index: index,
    29  	}
    30  	return chunk
    31  }
    32  
    33  func (p *Chunk) SetData(bytes []byte) {
    34  	p.buffer = bytes
    35  }
    36  
    37  func (p *Chunk) SetError(err error) {
    38  	p.err = err
    39  }
    40  
    41  func (p *Chunk) Error() error {
    42  	return p.err
    43  }
    44  
    45  func (p *Chunk) Data() []byte {
    46  	return p.buffer
    47  }
    48  
    49  // 切片乱序写入后,将切片顺序读取
    50  type ChunksSorter struct {
    51  	// 已经读取的切片数量
    52  	readCount int64
    53  
    54  	// 切片的所有总数
    55  	chunkCount int64
    56  
    57  	// 线程数,用于阻塞写入
    58  	works int64
    59  
    60  	// 存储切片的缓存区
    61  	chunks []chan *Chunk
    62  }
    63  
    64  func NewChunksSorter(chunkCount int64, works int) *ChunksSorter {
    65  	chunks := make([]chan *Chunk, works)
    66  	for i := 0; i < len(chunks); i++ {
    67  		chunks[i] = make(chan *Chunk)
    68  	}
    69  
    70  	return &ChunksSorter{
    71  		chunkCount: chunkCount,
    72  		works:      int64(works),
    73  		chunks:     chunks,
    74  	}
    75  }
    76  
    77  // 将数据写入到缓存区,如果该缓存已满,则会被阻塞
    78  func (p *ChunksSorter) Write(chunk *Chunk) {
    79  	p.chunks[chunk.index%p.works] <- chunk
    80  }
    81  
    82  // 关闭 workId 下的通道
    83  func (p *ChunksSorter) Close(workId int) {
    84  	if (len(p.chunks) - 1) >= workId {
    85  		close(p.chunks[workId])
    86  	}
    87  }
    88  
    89  // 顺序读取切片,如果下一个切片没有下载完,则会被阻塞
    90  func (p *ChunksSorter) Read() *Chunk {
    91  	if p.chunkCount == 0 {
    92  		return nil
    93  	}
    94  	i := atomic.AddInt64(&p.readCount, 1)
    95  	chunk := <-p.chunks[(i-1)%p.works]
    96  	return chunk
    97  }