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 }