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  }