github.com/qjfoidnh/BaiduPCS-Go@v0.0.0-20231011165705-caa18a3765f3/requester/uploader/multiuploader.go (about) 1 package uploader 2 3 import ( 4 "context" 5 "github.com/qjfoidnh/BaiduPCS-Go/baidupcs/pcserror" 6 "github.com/qjfoidnh/BaiduPCS-Go/pcsutil" 7 "github.com/qjfoidnh/BaiduPCS-Go/pcsutil/converter" 8 "github.com/qjfoidnh/BaiduPCS-Go/requester" 9 "github.com/qjfoidnh/BaiduPCS-Go/requester/rio" 10 "github.com/qjfoidnh/BaiduPCS-Go/requester/rio/speeds" 11 "sync" 12 "time" 13 ) 14 15 type ( 16 // MultiUpload 支持多线程的上传, 可用于断点续传 17 MultiUpload interface { 18 Precreate(fileSize int64, policy string) (err pcserror.Error) 19 TmpFile(ctx context.Context, partseq int, partOffset int64, readerlen64 rio.ReaderLen64) (checksum string, terr error) 20 CreateSuperFile(policy string, checksumList ...string) (cerr error) 21 } 22 23 // MultiUploader 多线程上传 24 MultiUploader struct { 25 onExecuteEvent requester.Event //开始上传事件 26 onSuccessEvent requester.Event //成功上传事件 27 onFinishEvent requester.Event //结束上传事件 28 onCancelEvent requester.Event //取消上传事件 29 onErrorEvent requester.EventOnError //上传出错事件 30 onUploadStatusEvent UploadStatusFunc //上传状态事件 31 32 instanceState *InstanceState 33 34 multiUpload MultiUpload // 上传体接口 35 file rio.ReaderAtLen64 // 上传 36 config *MultiUploaderConfig 37 workers workerList 38 speedsStat *speeds.Speeds 39 rateLimit *speeds.RateLimit 40 41 executeTime time.Time 42 finished chan struct{} 43 canceled chan struct{} 44 closeCanceledOnce sync.Once 45 updateInstanceStateChan chan struct{} 46 } 47 48 // MultiUploaderConfig 多线程上传配置 49 MultiUploaderConfig struct { 50 Parallel int // 上传并发量 51 BlockSize int64 // 上传分块 52 MaxRate int64 // 限制最大上传速度 53 Policy string // 文件重名策略 54 } 55 ) 56 57 // NewMultiUploader 初始化上传 58 func NewMultiUploader(multiUpload MultiUpload, file rio.ReaderAtLen64, config *MultiUploaderConfig) *MultiUploader { 59 return &MultiUploader{ 60 multiUpload: multiUpload, 61 file: file, 62 config: config, 63 } 64 } 65 66 // SetInstanceState 设置InstanceState, 断点续传信息 67 func (muer *MultiUploader) SetInstanceState(is *InstanceState) { 68 muer.instanceState = is 69 } 70 71 func (muer *MultiUploader) lazyInit() { 72 if muer.finished == nil { 73 muer.finished = make(chan struct{}, 1) 74 } 75 if muer.canceled == nil { 76 muer.canceled = make(chan struct{}) 77 } 78 if muer.updateInstanceStateChan == nil { 79 muer.updateInstanceStateChan = make(chan struct{}, 1) 80 } 81 if muer.config == nil { 82 muer.config = &MultiUploaderConfig{} 83 } 84 if muer.config.Parallel <= 0 { 85 muer.config.Parallel = 4 86 } 87 if muer.config.BlockSize <= 0 { 88 muer.config.BlockSize = 1 * converter.GB 89 } 90 if muer.speedsStat == nil { 91 muer.speedsStat = &speeds.Speeds{} 92 } 93 } 94 95 func (muer *MultiUploader) check() { 96 if muer.file == nil { 97 panic("file is nil") 98 } 99 if muer.multiUpload == nil { 100 panic("multiUpload is nil") 101 } 102 } 103 104 // Execute 执行上传 105 func (muer *MultiUploader) Execute() { 106 muer.check() 107 muer.lazyInit() 108 // 初始化限速 109 if muer.config.MaxRate > 0 { 110 muer.rateLimit = speeds.NewRateLimit(muer.config.MaxRate) 111 defer muer.rateLimit.Stop() 112 } 113 114 // 分配任务 115 if muer.instanceState != nil { 116 muer.workers = muer.getWorkerListByInstanceState(muer.instanceState) 117 uploaderVerbose.Infof("upload task CREATED from instance state\n") 118 } else { 119 muer.workers = muer.getWorkerListByInstanceState(&InstanceState{ 120 BlockList: SplitBlock(muer.file.Len(), muer.config.BlockSize), 121 }) 122 123 uploaderVerbose.Infof("upload task CREATED: block size: %d, num: %d\n", muer.config.BlockSize, len(muer.workers)) 124 } 125 126 // 开始上传 127 muer.executeTime = time.Now() 128 pcsutil.Trigger(muer.onExecuteEvent) 129 130 muer.uploadStatusEvent() 131 132 err := muer.upload() 133 134 // 完成 135 muer.finished <- struct{}{} 136 if err != nil { 137 if err == context.Canceled { 138 if muer.onCancelEvent != nil { 139 muer.onCancelEvent() 140 } 141 } else if muer.onErrorEvent != nil { 142 muer.onErrorEvent(err) 143 } 144 } else { 145 pcsutil.TriggerOnSync(muer.onSuccessEvent) 146 } 147 pcsutil.TriggerOnSync(muer.onFinishEvent) 148 } 149 150 // InstanceState 返回断点续传信息 151 func (muer *MultiUploader) InstanceState() *InstanceState { 152 blockStates := make([]*BlockState, 0, len(muer.workers)) 153 for _, wer := range muer.workers { 154 blockStates = append(blockStates, &BlockState{ 155 ID: wer.id, 156 Range: wer.splitUnit.Range(), 157 CheckSum: wer.checksum, 158 }) 159 } 160 return &InstanceState{ 161 BlockList: blockStates, 162 } 163 } 164 165 // Cancel 取消上传 166 func (muer *MultiUploader) Cancel() { 167 close(muer.canceled) 168 } 169 170 //OnExecute 设置开始上传事件 171 func (muer *MultiUploader) OnExecute(onExecuteEvent requester.Event) { 172 muer.onExecuteEvent = onExecuteEvent 173 } 174 175 //OnSuccess 设置成功上传事件 176 func (muer *MultiUploader) OnSuccess(onSuccessEvent requester.Event) { 177 muer.onSuccessEvent = onSuccessEvent 178 } 179 180 //OnFinish 设置结束上传事件 181 func (muer *MultiUploader) OnFinish(onFinishEvent requester.Event) { 182 muer.onFinishEvent = onFinishEvent 183 } 184 185 //OnCancel 设置取消上传事件 186 func (muer *MultiUploader) OnCancel(onCancelEvent requester.Event) { 187 muer.onCancelEvent = onCancelEvent 188 } 189 190 //OnError 设置上传发生错误事件 191 func (muer *MultiUploader) OnError(onErrorEvent requester.EventOnError) { 192 muer.onErrorEvent = onErrorEvent 193 } 194 195 //OnUploadStatusEvent 设置上传状态事件 196 func (muer *MultiUploader) OnUploadStatusEvent(f UploadStatusFunc) { 197 muer.onUploadStatusEvent = f 198 }