github.com/qjfoidnh/BaiduPCS-Go@v0.0.0-20231011165705-caa18a3765f3/internal/pcsfunctions/pcsupload/upload_database.go (about) 1 package pcsupload 2 3 import ( 4 "errors" 5 "github.com/qjfoidnh/BaiduPCS-Go/internal/pcsconfig" 6 "github.com/qjfoidnh/BaiduPCS-Go/pcsutil/checksum" 7 "github.com/qjfoidnh/BaiduPCS-Go/pcsutil/converter" 8 "github.com/qjfoidnh/BaiduPCS-Go/pcsutil/jsonhelper" 9 "github.com/qjfoidnh/BaiduPCS-Go/requester/uploader" 10 "os" 11 "path/filepath" 12 "strings" 13 "sync" 14 "time" 15 ) 16 17 type ( 18 // Uploading 未完成上传的信息 19 Uploading struct { 20 *checksum.LocalFileMeta 21 State *uploader.InstanceState `json:"state"` 22 } 23 24 // UploadingDatabase 未完成上传的数据库 25 UploadingDatabase struct { 26 lock sync.RWMutex 27 UploadingList []*Uploading `json:"upload_state"` 28 Timestamp int64 `json:"timestamp"` 29 30 dataFile *os.File 31 } 32 ) 33 34 // NewUploadingDatabase 初始化未完成上传的数据库, 从库中读取内容 35 func NewUploadingDatabase() (ud *UploadingDatabase, err error) { 36 file, err := os.OpenFile(filepath.Join(pcsconfig.GetConfigDir(), UploadingFileName), os.O_CREATE|os.O_RDWR, 0777) 37 if err != nil { 38 return nil, err 39 } 40 41 ud = &UploadingDatabase{ 42 dataFile: file, 43 } 44 info, err := file.Stat() 45 if err != nil { 46 return nil, err 47 } 48 49 if info.Size() <= 0 { 50 return ud, nil 51 } 52 53 err = jsonhelper.UnmarshalData(file, ud) 54 if err != nil { 55 _, err = file.Write([]byte("")) 56 if err != nil { 57 return nil, err 58 } 59 } 60 61 return ud, nil 62 } 63 64 // Save 保存内容 65 func (ud *UploadingDatabase) Save() error { 66 if ud.dataFile == nil { 67 return errors.New("dataFile is nil") 68 } 69 70 ud.Timestamp = time.Now().Unix() 71 72 var ( 73 builder = &strings.Builder{} 74 err = jsonhelper.MarshalData(builder, ud) 75 ) 76 if err != nil { 77 panic(err) 78 } 79 80 err = ud.dataFile.Truncate(int64(builder.Len())) 81 if err != nil { 82 return err 83 } 84 85 str := builder.String() 86 _, err = ud.dataFile.WriteAt(converter.ToBytes(str), 0) 87 if err != nil { 88 return err 89 } 90 91 return nil 92 } 93 94 // UpdateUploading 更新正在上传 95 func (ud *UploadingDatabase) UpdateUploading(meta *checksum.LocalFileMeta, state *uploader.InstanceState) { 96 ud.lock.RLock() 97 defer ud.lock.RUnlock() 98 if meta == nil { 99 return 100 } 101 meta.CompleteAbsPath() 102 for k, uploading := range ud.UploadingList { 103 if uploading.LocalFileMeta == nil { 104 continue 105 } 106 if uploading.LocalFileMeta.EqualLengthMD5(meta) || uploading.LocalFileMeta.Path == meta.Path { 107 ud.UploadingList[k].State = state 108 return 109 } 110 } 111 112 ud.UploadingList = append(ud.UploadingList, &Uploading{ 113 LocalFileMeta: meta, 114 State: state, 115 }) 116 } 117 118 func (ud *UploadingDatabase) deleteIndex(k int) { 119 ud.UploadingList = append(ud.UploadingList[:k], ud.UploadingList[k+1:]...) 120 } 121 122 // Delete 删除 123 func (ud *UploadingDatabase) Delete(meta *checksum.LocalFileMeta) bool { 124 ud.lock.Lock() 125 defer ud.lock.Unlock() 126 if meta == nil { 127 return false 128 } 129 meta.CompleteAbsPath() 130 for k, uploading := range ud.UploadingList { 131 if uploading.LocalFileMeta == nil { 132 continue 133 } 134 if uploading.LocalFileMeta.EqualLengthMD5(meta) || uploading.LocalFileMeta.Path == meta.Path { 135 ud.deleteIndex(k) 136 return true 137 } 138 } 139 return false 140 } 141 142 // Search 搜索 143 func (ud *UploadingDatabase) Search(meta *checksum.LocalFileMeta) *uploader.InstanceState { 144 if meta == nil { 145 return nil 146 } 147 148 meta.CompleteAbsPath() 149 ud.clearModTimeChange() 150 for _, uploading := range ud.UploadingList { 151 if uploading.LocalFileMeta == nil { 152 continue 153 } 154 if uploading.LocalFileMeta.EqualLengthMD5(meta) { 155 return uploading.State 156 } 157 if uploading.LocalFileMeta.Path == meta.Path { 158 // 移除旧的信息 159 // 目前只是比较了文件大小 160 if meta.Length != uploading.LocalFileMeta.Length { 161 ud.Delete(meta) 162 return nil 163 } 164 165 meta.MD5 = uploading.LocalFileMeta.MD5 166 meta.SliceMD5 = uploading.LocalFileMeta.SliceMD5 167 return uploading.State 168 } 169 } 170 return nil 171 } 172 173 func (ud *UploadingDatabase) clearModTimeChange() { 174 ud.lock.Lock() 175 defer ud.lock.Unlock() 176 for i := 0; i < len(ud.UploadingList); i++ { 177 uploading := ud.UploadingList[i] 178 if uploading.LocalFileMeta == nil { 179 continue 180 } 181 182 if uploading.ModTime == -1 { // 忽略 183 continue 184 } 185 186 info, err := os.Stat(uploading.LocalFileMeta.Path) 187 if err != nil { 188 ud.deleteIndex(i) 189 i-- 190 pcsUploadVerbose.Warnf("clear invalid file path: %s, err: %s\n", uploading.LocalFileMeta.Path, err) 191 continue 192 } 193 194 if uploading.LocalFileMeta.ModTime != info.ModTime().Unix() { 195 ud.deleteIndex(i) 196 i-- 197 pcsUploadVerbose.Infof("clear modified file path: %s\n", uploading.LocalFileMeta.Path) 198 continue 199 } 200 } 201 } 202 203 // Close 关闭数据库 204 func (ud *UploadingDatabase) Close() error { 205 return ud.dataFile.Close() 206 }