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

     1  package transfer
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"github.com/iikira/iikira-go-utils/utils/converter"
     7  	"sync"
     8  	"sync/atomic"
     9  )
    10  
    11  type (
    12  	//RangeList 请求范围列表
    13  	RangeList []*Range
    14  
    15  	//RangeListGen Range 生成器
    16  	RangeListGen struct {
    17  		total        int64
    18  		begin        int64
    19  		blockSize    int64
    20  		parallel     int
    21  		count        int // 已生成次数
    22  		rangeGenMode RangeGenMode
    23  		mu           sync.Mutex
    24  	}
    25  )
    26  
    27  const (
    28  	// DefaultBlockSize 默认的BlockSize
    29  	DefaultBlockSize = 256 * converter.KB
    30  )
    31  
    32  var (
    33  	// ErrUnknownRangeGenMode RangeGenMode 非法
    34  	ErrUnknownRangeGenMode = errors.New("Unknown RangeGenMode")
    35  )
    36  
    37  //Len 长度
    38  func (r *Range) Len() int64 {
    39  	return r.LoadEnd() - r.LoadBegin()
    40  }
    41  
    42  //LoadBegin 读取Begin, 原子操作
    43  func (r *Range) LoadBegin() int64 {
    44  	return atomic.LoadInt64(&r.Begin)
    45  }
    46  
    47  //AddBegin 增加Begin, 原子操作
    48  func (r *Range) AddBegin(i int64) (newi int64) {
    49  	return atomic.AddInt64(&r.Begin, i)
    50  }
    51  
    52  //LoadEnd 读取End, 原子操作
    53  func (r *Range) LoadEnd() int64 {
    54  	return atomic.LoadInt64(&r.End)
    55  }
    56  
    57  //StoreBegin 储存End, 原子操作
    58  func (r *Range) StoreBegin(end int64) {
    59  	atomic.StoreInt64(&r.Begin, end)
    60  }
    61  
    62  //StoreEnd 储存End, 原子操作
    63  func (r *Range) StoreEnd(end int64) {
    64  	atomic.StoreInt64(&r.End, end)
    65  }
    66  
    67  // ShowDetails 显示Range细节
    68  func (r *Range) ShowDetails() string {
    69  	return fmt.Sprintf("{%d-%d}", r.LoadBegin(), r.LoadEnd())
    70  }
    71  
    72  //Len 获取所有的Range的剩余长度
    73  func (rl *RangeList) Len() int64 {
    74  	var l int64
    75  	for _, wrange := range *rl {
    76  		if wrange == nil {
    77  			continue
    78  		}
    79  		l += wrange.Len()
    80  	}
    81  	return l
    82  }
    83  
    84  // NewRangeListGenDefault 初始化默认Range生成器, 根据parallel平均生成
    85  func NewRangeListGenDefault(totalSize, begin int64, count, parallel int) *RangeListGen {
    86  	return &RangeListGen{
    87  		total:        totalSize,
    88  		begin:        begin,
    89  		parallel:     parallel,
    90  		count:        count,
    91  		rangeGenMode: RangeGenMode_Default,
    92  	}
    93  }
    94  
    95  // NewRangeListGenBlockSize 初始化Range生成器, 根据blockSize生成
    96  func NewRangeListGenBlockSize(totalSize, begin, blockSize int64) *RangeListGen {
    97  	return &RangeListGen{
    98  		total:        totalSize,
    99  		begin:        begin,
   100  		blockSize:    blockSize,
   101  		rangeGenMode: RangeGenMode_BlockSize,
   102  	}
   103  }
   104  
   105  // RangeGenMode 返回Range生成方式
   106  func (gen *RangeListGen) RangeGenMode() RangeGenMode {
   107  	return gen.rangeGenMode
   108  }
   109  
   110  // RangeCount 返回预计生成的Range数量
   111  func (gen *RangeListGen) RangeCount() (rangeCount int) {
   112  	switch gen.rangeGenMode {
   113  	case RangeGenMode_Default:
   114  		rangeCount = gen.parallel - gen.count
   115  	case RangeGenMode_BlockSize:
   116  		rangeCount = int((gen.total - gen.begin) / gen.blockSize)
   117  		if gen.total%gen.blockSize != 0 {
   118  			rangeCount++
   119  		}
   120  	}
   121  	return
   122  }
   123  
   124  // LoadBegin 返回begin
   125  func (gen *RangeListGen) LoadBegin() (begin int64) {
   126  	gen.mu.Lock()
   127  	begin = gen.begin
   128  	gen.mu.Unlock()
   129  	return
   130  }
   131  
   132  // LoadBlockSize 返回blockSize
   133  func (gen *RangeListGen) LoadBlockSize() (blockSize int64) {
   134  	switch gen.rangeGenMode {
   135  	case RangeGenMode_Default:
   136  		if gen.blockSize <= 0 {
   137  			gen.blockSize = (gen.total - gen.begin) / int64(gen.parallel)
   138  		}
   139  		blockSize = gen.blockSize
   140  	case RangeGenMode_BlockSize:
   141  		blockSize = gen.blockSize
   142  	}
   143  	return
   144  }
   145  
   146  // IsDone 是否已分配完成
   147  func (gen *RangeListGen) IsDone() bool {
   148  	return gen.begin >= gen.total
   149  }
   150  
   151  // GenRange 生成 Range
   152  func (gen *RangeListGen) GenRange() (index int, r *Range) {
   153  	var (
   154  		end int64
   155  	)
   156  	if gen.parallel < 1 {
   157  		gen.parallel = 1
   158  	}
   159  	switch gen.rangeGenMode {
   160  	case RangeGenMode_Default:
   161  		gen.LoadBlockSize()
   162  		gen.mu.Lock()
   163  		defer gen.mu.Unlock()
   164  
   165  		if gen.IsDone() {
   166  			return gen.count, nil
   167  		}
   168  
   169  		gen.count++
   170  		if gen.count >= gen.parallel {
   171  			end = gen.total
   172  		} else {
   173  			end = gen.begin + gen.blockSize
   174  		}
   175  		r = &Range{
   176  			Begin: gen.begin,
   177  			End:   end,
   178  		}
   179  
   180  		gen.begin = end
   181  		index = gen.count - 1
   182  		return
   183  	case RangeGenMode_BlockSize:
   184  		if gen.blockSize <= 0 {
   185  			gen.blockSize = DefaultBlockSize
   186  		}
   187  		gen.mu.Lock()
   188  		defer gen.mu.Unlock()
   189  
   190  		if gen.IsDone() {
   191  			return gen.count, nil
   192  		}
   193  
   194  		gen.count++
   195  		end = gen.begin + gen.blockSize
   196  		if end >= gen.total {
   197  			end = gen.total
   198  		}
   199  		r = &Range{
   200  			Begin: gen.begin,
   201  			End:   end,
   202  		}
   203  		gen.begin = end
   204  		index = gen.count - 1
   205  		return
   206  	}
   207  
   208  	return 0, nil
   209  }