github.com/iikira/iikira-go-utils@v0.0.0-20230610031953-f2cb11cde33a/requester/uploader/block.go (about)

     1  package uploader
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"github.com/iikira/iikira-go-utils/requester/rio/speeds"
     7  	"github.com/iikira/iikira-go-utils/requester/transfer"
     8  	"io"
     9  	"os"
    10  	"sync"
    11  )
    12  
    13  type (
    14  	// SplitUnit 将 io.ReaderAt 分割单元
    15  	SplitUnit interface {
    16  		Readed64
    17  		io.Seeker
    18  		Range() transfer.Range
    19  		Left() int64
    20  	}
    21  
    22  	fileBlock struct {
    23  		readRange     transfer.Range
    24  		readed        int64
    25  		readerAt      io.ReaderAt
    26  		speedsStatRef *speeds.Speeds
    27  		rateLimit     *speeds.RateLimit
    28  		mu            sync.Mutex
    29  	}
    30  
    31  	bufioFileBlock struct {
    32  		*fileBlock
    33  		bufio *bufio.Reader
    34  	}
    35  )
    36  
    37  // SplitBlock 文件分块
    38  func SplitBlock(fileSize, blockSize int64) (blockList []*BlockState) {
    39  	gen := transfer.NewRangeListGenBlockSize(fileSize, 0, blockSize)
    40  	rangeCount := gen.RangeCount()
    41  	blockList = make([]*BlockState, 0, rangeCount)
    42  	for i := 0; i < rangeCount; i++ {
    43  		id, r := gen.GenRange()
    44  		blockList = append(blockList, &BlockState{
    45  			ID:    id,
    46  			Range: *r,
    47  		})
    48  	}
    49  	return
    50  }
    51  
    52  // NewBufioSplitUnit io.ReaderAt实现SplitUnit接口, 有Buffer支持
    53  func NewBufioSplitUnit(readerAt io.ReaderAt, readRange transfer.Range, speedsStat *speeds.Speeds, rateLimit *speeds.RateLimit) SplitUnit {
    54  	su := &fileBlock{
    55  		readerAt:      readerAt,
    56  		readRange:     readRange,
    57  		speedsStatRef: speedsStat,
    58  		rateLimit:     rateLimit,
    59  	}
    60  	return &bufioFileBlock{
    61  		fileBlock: su,
    62  		bufio:     bufio.NewReaderSize(su, BufioReadSize),
    63  	}
    64  }
    65  
    66  func (bfb *bufioFileBlock) Read(b []byte) (n int, err error) {
    67  	return bfb.bufio.Read(b) // 间接调用fileBlock 的Read
    68  }
    69  
    70  // Read 只允许一个线程读同一个文件
    71  func (fb *fileBlock) Read(b []byte) (n int, err error) {
    72  	fb.mu.Lock()
    73  	defer fb.mu.Unlock()
    74  
    75  	left := int(fb.Left())
    76  	if left <= 0 {
    77  		return 0, io.EOF
    78  	}
    79  
    80  	if len(b) > left {
    81  		n, err = fb.readerAt.ReadAt(b[:left], fb.readed+fb.readRange.Begin)
    82  	} else {
    83  		n, err = fb.readerAt.ReadAt(b, fb.readed+fb.readRange.Begin)
    84  	}
    85  
    86  	n64 := int64(n)
    87  	fb.readed += n64
    88  	if fb.rateLimit != nil {
    89  		fb.rateLimit.Add(n64) // 限速阻塞
    90  	}
    91  	if fb.speedsStatRef != nil {
    92  		fb.speedsStatRef.Add(n64)
    93  	}
    94  	return
    95  }
    96  
    97  func (fb *fileBlock) Seek(offset int64, whence int) (int64, error) {
    98  	fb.mu.Lock()
    99  	defer fb.mu.Unlock()
   100  
   101  	switch whence {
   102  	case os.SEEK_SET:
   103  		fb.readed = offset
   104  	case os.SEEK_CUR:
   105  		fb.readed += offset
   106  	case os.SEEK_END:
   107  		fb.readed = fb.readRange.End - fb.readRange.Begin + offset
   108  	default:
   109  		return 0, fmt.Errorf("unsupport whence: %d", whence)
   110  	}
   111  	if fb.readed < 0 {
   112  		fb.readed = 0
   113  	}
   114  	return fb.readed, nil
   115  }
   116  
   117  func (fb *fileBlock) Len() int64 {
   118  	return fb.readRange.End - fb.readRange.Begin
   119  }
   120  
   121  func (fb *fileBlock) Left() int64 {
   122  	return fb.readRange.End - fb.readRange.Begin - fb.readed
   123  }
   124  
   125  func (fb *fileBlock) Range() transfer.Range {
   126  	return fb.readRange
   127  }
   128  
   129  func (fb *fileBlock) Readed() int64 {
   130  	return fb.readed
   131  }