github.com/qjfoidnh/BaiduPCS-Go@v0.0.0-20231011165705-caa18a3765f3/requester/transfer/rangelist.go (about) 1 package transfer 2 3 import ( 4 "errors" 5 "fmt" 6 "github.com/qjfoidnh/BaiduPCS-Go/pcsutil/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 //rangeCount = int(math.Ceil(float64(gen.total) / float64(gen.blockSize))) 116 case RangeGenMode_BlockSize: 117 rangeCount = int((gen.total - gen.begin) / gen.blockSize) 118 if gen.total%gen.blockSize != 0 { 119 rangeCount++ 120 } 121 } 122 return 123 } 124 125 // LoadBegin 返回begin 126 func (gen *RangeListGen) LoadBegin() (begin int64) { 127 gen.mu.Lock() 128 begin = gen.begin 129 gen.mu.Unlock() 130 return 131 } 132 133 // LoadBlockSize 返回blockSize 134 func (gen *RangeListGen) LoadBlockSize() (blockSize int64) { 135 switch gen.rangeGenMode { 136 case RangeGenMode_Default: 137 if gen.blockSize <= 0 { 138 gen.blockSize = (gen.total - gen.begin) / int64(gen.parallel) 139 if gen.blockSize < 256 * converter.KB { 140 gen.blockSize = 256 * converter.KB 141 } 142 } 143 blockSize = gen.blockSize 144 case RangeGenMode_BlockSize: 145 blockSize = gen.blockSize 146 } 147 return 148 } 149 150 // IsDone 是否已分配完成 151 func (gen *RangeListGen) IsDone() bool { 152 return gen.begin >= gen.total 153 } 154 155 // GenRange 生成 Range 156 func (gen *RangeListGen) GenRange() (index int, r *Range) { 157 var ( 158 end int64 159 ) 160 if gen.parallel < 1 { 161 gen.parallel = 1 162 } 163 switch gen.rangeGenMode { 164 case RangeGenMode_Default: 165 gen.LoadBlockSize() 166 gen.mu.Lock() 167 defer gen.mu.Unlock() 168 169 if gen.IsDone() { 170 return gen.count, nil 171 } 172 173 gen.count++ 174 if gen.count >= gen.parallel { 175 end = gen.total 176 } else { 177 end = gen.begin + gen.blockSize 178 } 179 180 //end = gen.begin + gen.blockSize 181 if end >= gen.total { 182 end = gen.total 183 } 184 185 r = &Range{ 186 Begin: gen.begin, 187 End: end, 188 } 189 190 gen.begin = end 191 index = gen.count - 1 192 return 193 case RangeGenMode_BlockSize: 194 if gen.blockSize <= 0 { 195 gen.blockSize = DefaultBlockSize 196 } 197 gen.mu.Lock() 198 defer gen.mu.Unlock() 199 200 if gen.IsDone() { 201 return gen.count, nil 202 } 203 204 gen.count++ 205 end = gen.begin + gen.blockSize 206 if end >= gen.total { 207 end = gen.total 208 } 209 r = &Range{ 210 Begin: gen.begin, 211 End: end, 212 } 213 gen.begin = end 214 index = gen.count - 1 215 return 216 } 217 218 return 0, nil 219 }