2022-05-24 23:01:08 +08:00
|
|
|
|
package syncdrive
|
|
|
|
|
|
2022-06-01 21:55:03 +08:00
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"fmt"
|
|
|
|
|
mapset "github.com/deckarep/golang-set"
|
2022-06-17 06:59:04 +08:00
|
|
|
|
"github.com/tickstep/aliyunpan-api/aliyunpan"
|
2022-06-01 21:55:03 +08:00
|
|
|
|
"github.com/tickstep/aliyunpan/internal/localfile"
|
|
|
|
|
"github.com/tickstep/aliyunpan/internal/waitgroup"
|
|
|
|
|
"github.com/tickstep/aliyunpan/library/collection"
|
|
|
|
|
"github.com/tickstep/library-go/logger"
|
|
|
|
|
"path"
|
|
|
|
|
"strings"
|
|
|
|
|
"sync"
|
|
|
|
|
"time"
|
|
|
|
|
)
|
|
|
|
|
|
2022-05-24 23:01:08 +08:00
|
|
|
|
type (
|
2022-06-01 21:55:03 +08:00
|
|
|
|
FileActionTaskList []*FileActionTask
|
2022-05-24 23:01:08 +08:00
|
|
|
|
|
|
|
|
|
FileActionTaskManager struct {
|
2022-06-05 22:19:16 +08:00
|
|
|
|
mutex *sync.Mutex
|
2022-07-02 18:59:00 +08:00
|
|
|
|
localCreateMutex *sync.Mutex
|
2022-06-05 22:19:16 +08:00
|
|
|
|
folderCreateMutex *sync.Mutex
|
2022-06-01 21:55:03 +08:00
|
|
|
|
|
|
|
|
|
task *SyncTask
|
|
|
|
|
wg *waitgroup.WaitGroup
|
|
|
|
|
ctx context.Context
|
|
|
|
|
cancelFunc context.CancelFunc
|
2022-06-04 13:20:33 +08:00
|
|
|
|
|
2022-08-13 16:54:42 +08:00
|
|
|
|
fileInProcessQueue *collection.Queue
|
|
|
|
|
syncOption SyncOption
|
2022-06-23 16:40:10 +08:00
|
|
|
|
|
2022-06-24 10:36:03 +08:00
|
|
|
|
localFolderModifyCount int // 本地文件扫描变更记录次数,作为后续文件对比进程的参考以节省CPU资源
|
|
|
|
|
panFolderModifyCount int // 云盘文件扫描变更记录次数,作为后续文件对比进程的参考以节省CPU资源
|
|
|
|
|
syncActionModifyCount int // 文件对比进程检测的文件上传下载删除变更记录次数,作为后续文件上传下载处理进程的参考以节省CPU资源
|
|
|
|
|
resourceModifyMutex *sync.Mutex
|
2022-06-01 21:55:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
localFileSet struct {
|
|
|
|
|
items LocalFileList
|
|
|
|
|
localFolderPath string
|
|
|
|
|
}
|
|
|
|
|
panFileSet struct {
|
|
|
|
|
items PanFileList
|
|
|
|
|
panFolderPath string
|
2022-05-24 23:01:08 +08:00
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
2022-08-13 16:54:42 +08:00
|
|
|
|
func NewFileActionTaskManager(task *SyncTask) *FileActionTaskManager {
|
2022-05-24 23:01:08 +08:00
|
|
|
|
return &FileActionTaskManager{
|
2022-06-05 22:19:16 +08:00
|
|
|
|
mutex: &sync.Mutex{},
|
2022-07-02 18:59:00 +08:00
|
|
|
|
localCreateMutex: &sync.Mutex{},
|
2022-06-05 22:19:16 +08:00
|
|
|
|
folderCreateMutex: &sync.Mutex{},
|
|
|
|
|
task: task,
|
2022-06-04 13:20:33 +08:00
|
|
|
|
|
2022-08-13 16:54:42 +08:00
|
|
|
|
fileInProcessQueue: collection.NewFifoQueue(),
|
|
|
|
|
syncOption: task.syncOption,
|
2022-06-23 16:40:10 +08:00
|
|
|
|
|
|
|
|
|
localFolderModifyCount: 1,
|
|
|
|
|
panFolderModifyCount: 1,
|
2022-06-24 10:36:03 +08:00
|
|
|
|
syncActionModifyCount: 1,
|
|
|
|
|
resourceModifyMutex: &sync.Mutex{},
|
2022-05-24 23:01:08 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-23 16:40:10 +08:00
|
|
|
|
func (f *FileActionTaskManager) AddLocalFolderModifyCount() {
|
2022-06-24 10:36:03 +08:00
|
|
|
|
f.resourceModifyMutex.Lock()
|
|
|
|
|
defer f.resourceModifyMutex.Unlock()
|
2022-06-23 16:40:10 +08:00
|
|
|
|
f.localFolderModifyCount += 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *FileActionTaskManager) MinusLocalFolderModifyCount() {
|
2022-06-24 10:36:03 +08:00
|
|
|
|
f.resourceModifyMutex.Lock()
|
|
|
|
|
defer f.resourceModifyMutex.Unlock()
|
2022-06-23 16:40:10 +08:00
|
|
|
|
f.localFolderModifyCount -= 1
|
2022-06-24 10:36:03 +08:00
|
|
|
|
if f.localFolderModifyCount < 0 {
|
|
|
|
|
f.localFolderModifyCount = 0
|
|
|
|
|
}
|
2022-06-23 16:40:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *FileActionTaskManager) getLocalFolderModifyCount() int {
|
2022-06-24 10:36:03 +08:00
|
|
|
|
f.resourceModifyMutex.Lock()
|
|
|
|
|
defer f.resourceModifyMutex.Unlock()
|
2022-06-23 16:40:10 +08:00
|
|
|
|
return f.localFolderModifyCount
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *FileActionTaskManager) AddPanFolderModifyCount() {
|
2022-06-24 10:36:03 +08:00
|
|
|
|
f.resourceModifyMutex.Lock()
|
|
|
|
|
defer f.resourceModifyMutex.Unlock()
|
2022-06-23 16:40:10 +08:00
|
|
|
|
f.panFolderModifyCount += 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *FileActionTaskManager) MinusPanFolderModifyCount() {
|
2022-06-24 10:36:03 +08:00
|
|
|
|
f.resourceModifyMutex.Lock()
|
|
|
|
|
defer f.resourceModifyMutex.Unlock()
|
2022-06-23 16:40:10 +08:00
|
|
|
|
f.panFolderModifyCount -= 1
|
2022-06-24 10:36:03 +08:00
|
|
|
|
if f.panFolderModifyCount < 0 {
|
|
|
|
|
f.panFolderModifyCount = 0
|
|
|
|
|
}
|
2022-06-23 16:40:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *FileActionTaskManager) getPanFolderModifyCount() int {
|
2022-06-24 10:36:03 +08:00
|
|
|
|
f.resourceModifyMutex.Lock()
|
|
|
|
|
defer f.resourceModifyMutex.Unlock()
|
2022-06-23 16:40:10 +08:00
|
|
|
|
return f.panFolderModifyCount
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-24 10:36:03 +08:00
|
|
|
|
func (f *FileActionTaskManager) AddSyncActionModifyCount() {
|
|
|
|
|
f.resourceModifyMutex.Lock()
|
|
|
|
|
defer f.resourceModifyMutex.Unlock()
|
|
|
|
|
f.syncActionModifyCount += 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *FileActionTaskManager) MinusSyncActionModifyCount() {
|
|
|
|
|
f.resourceModifyMutex.Lock()
|
|
|
|
|
defer f.resourceModifyMutex.Unlock()
|
|
|
|
|
f.syncActionModifyCount -= 1
|
|
|
|
|
if f.syncActionModifyCount < 0 {
|
|
|
|
|
f.syncActionModifyCount = 0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *FileActionTaskManager) getSyncActionModifyCount() int {
|
|
|
|
|
f.resourceModifyMutex.Lock()
|
|
|
|
|
defer f.resourceModifyMutex.Unlock()
|
|
|
|
|
return f.syncActionModifyCount
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-09 14:52:49 +08:00
|
|
|
|
// Start 启动文件动作任务管理进程
|
|
|
|
|
// 通过对本地数据库的对比,决策对文件进行下载、上传、删除等动作
|
2022-06-01 21:55:03 +08:00
|
|
|
|
func (f *FileActionTaskManager) Start() error {
|
|
|
|
|
if f.ctx != nil {
|
|
|
|
|
return fmt.Errorf("task have starting")
|
|
|
|
|
}
|
2022-06-04 13:20:33 +08:00
|
|
|
|
f.wg = waitgroup.NewWaitGroup(0)
|
2022-06-01 21:55:03 +08:00
|
|
|
|
|
|
|
|
|
var cancel context.CancelFunc
|
|
|
|
|
f.ctx, cancel = context.WithCancel(context.Background())
|
|
|
|
|
f.cancelFunc = cancel
|
|
|
|
|
|
2022-06-04 13:20:33 +08:00
|
|
|
|
go f.doLocalFileDiffRoutine(f.ctx)
|
|
|
|
|
go f.doPanFileDiffRoutine(f.ctx)
|
2022-06-01 21:55:03 +08:00
|
|
|
|
go f.fileActionTaskExecutor(f.ctx)
|
2022-05-24 23:01:08 +08:00
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-01 21:55:03 +08:00
|
|
|
|
func (f *FileActionTaskManager) Stop() error {
|
|
|
|
|
if f.ctx == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
// cancel all sub task & process
|
|
|
|
|
f.cancelFunc()
|
|
|
|
|
|
|
|
|
|
// wait for finished
|
|
|
|
|
f.wg.Wait()
|
|
|
|
|
|
|
|
|
|
f.ctx = nil
|
|
|
|
|
f.cancelFunc = nil
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// getPanPathFromLocalPath 通过本地文件路径获取网盘文件的对应路径
|
|
|
|
|
func (f *FileActionTaskManager) getPanPathFromLocalPath(localPath string) string {
|
|
|
|
|
localPath = strings.ReplaceAll(localPath, "\\", "/")
|
|
|
|
|
localRootPath := strings.ReplaceAll(f.task.LocalFolderPath, "\\", "/")
|
|
|
|
|
|
|
|
|
|
relativePath := strings.TrimPrefix(localPath, localRootPath)
|
|
|
|
|
return path.Join(path.Clean(f.task.PanFolderPath), relativePath)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// getLocalPathFromPanPath 通过网盘文件路径获取对应的本地文件的对应路径
|
|
|
|
|
func (f *FileActionTaskManager) getLocalPathFromPanPath(panPath string) string {
|
|
|
|
|
panPath = strings.ReplaceAll(panPath, "\\", "/")
|
|
|
|
|
panRootPath := strings.ReplaceAll(f.task.PanFolderPath, "\\", "/")
|
|
|
|
|
|
|
|
|
|
relativePath := strings.TrimPrefix(panPath, panRootPath)
|
|
|
|
|
return path.Join(path.Clean(f.task.LocalFolderPath), relativePath)
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-04 13:20:33 +08:00
|
|
|
|
// doLocalFileDiffRoutine 对比网盘文件和本地文件信息,差异化上传或者下载文件
|
|
|
|
|
func (f *FileActionTaskManager) doLocalFileDiffRoutine(ctx context.Context) {
|
2022-06-01 21:55:03 +08:00
|
|
|
|
localFolderQueue := collection.NewFifoQueue()
|
2022-06-06 19:13:37 +08:00
|
|
|
|
var localRootFolder *LocalFileItem
|
|
|
|
|
var er error
|
2022-06-04 13:20:33 +08:00
|
|
|
|
|
|
|
|
|
f.wg.AddDelta()
|
|
|
|
|
defer f.wg.Done()
|
|
|
|
|
for {
|
|
|
|
|
select {
|
|
|
|
|
case <-ctx.Done():
|
|
|
|
|
// cancel routine & done
|
|
|
|
|
logger.Verboseln("file diff routine done")
|
|
|
|
|
return
|
|
|
|
|
default:
|
2022-06-06 19:13:37 +08:00
|
|
|
|
if localRootFolder == nil {
|
|
|
|
|
localRootFolder, er = f.task.localFileDb.Get(f.task.LocalFolderPath)
|
|
|
|
|
if er == nil {
|
|
|
|
|
localFolderQueue.Push(localRootFolder)
|
|
|
|
|
} else {
|
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-06-23 16:40:10 +08:00
|
|
|
|
// check need to do the loop or to wait
|
|
|
|
|
if f.getLocalFolderModifyCount() <= 0 {
|
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-04 13:20:33 +08:00
|
|
|
|
localFiles := LocalFileList{}
|
|
|
|
|
panFiles := PanFileList{}
|
|
|
|
|
var err error
|
|
|
|
|
var objLocal interface{}
|
|
|
|
|
|
|
|
|
|
objLocal = localFolderQueue.Pop()
|
|
|
|
|
if objLocal == nil {
|
2022-06-23 16:40:10 +08:00
|
|
|
|
// restart over & begin goto next term
|
2022-06-04 13:20:33 +08:00
|
|
|
|
localFolderQueue.Push(localRootFolder)
|
2022-06-23 16:40:10 +08:00
|
|
|
|
f.MinusLocalFolderModifyCount()
|
2022-06-04 13:20:33 +08:00
|
|
|
|
time.Sleep(3 * time.Second)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
localItem := objLocal.(*LocalFileItem)
|
|
|
|
|
localFiles, err = f.task.localFileDb.GetFileList(localItem.Path)
|
|
|
|
|
if err != nil {
|
|
|
|
|
localFiles = LocalFileList{}
|
|
|
|
|
}
|
|
|
|
|
panFiles, err = f.task.panFileDb.GetFileList(f.getPanPathFromLocalPath(localItem.Path))
|
|
|
|
|
if err != nil {
|
|
|
|
|
panFiles = PanFileList{}
|
|
|
|
|
}
|
|
|
|
|
f.doFileDiffRoutine(panFiles, localFiles, nil, localFolderQueue)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// doPanFileDiffRoutine 对比网盘文件和本地文件信息,差异化上传或者下载文件
|
|
|
|
|
func (f *FileActionTaskManager) doPanFileDiffRoutine(ctx context.Context) {
|
|
|
|
|
panFolderQueue := collection.NewFifoQueue()
|
2022-06-06 19:13:37 +08:00
|
|
|
|
var panRootFolder *PanFileItem
|
|
|
|
|
var er error
|
2022-06-01 21:55:03 +08:00
|
|
|
|
|
|
|
|
|
f.wg.AddDelta()
|
|
|
|
|
defer f.wg.Done()
|
|
|
|
|
for {
|
|
|
|
|
select {
|
|
|
|
|
case <-ctx.Done():
|
|
|
|
|
// cancel routine & done
|
|
|
|
|
logger.Verboseln("file diff routine done")
|
|
|
|
|
return
|
|
|
|
|
default:
|
2022-06-06 19:13:37 +08:00
|
|
|
|
if panRootFolder == nil {
|
|
|
|
|
panRootFolder, er = f.task.panFileDb.Get(f.task.PanFolderPath)
|
|
|
|
|
if er == nil {
|
|
|
|
|
panFolderQueue.Push(panRootFolder)
|
|
|
|
|
} else {
|
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-06-23 16:40:10 +08:00
|
|
|
|
if f.getPanFolderModifyCount() <= 0 {
|
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-01 21:55:03 +08:00
|
|
|
|
localFiles := LocalFileList{}
|
|
|
|
|
panFiles := PanFileList{}
|
|
|
|
|
var err error
|
2022-06-04 13:20:33 +08:00
|
|
|
|
var objPan interface{}
|
2022-06-01 21:55:03 +08:00
|
|
|
|
|
2022-06-04 13:20:33 +08:00
|
|
|
|
objPan = panFolderQueue.Pop()
|
|
|
|
|
if objPan == nil {
|
|
|
|
|
// restart over
|
|
|
|
|
panFolderQueue.Push(panRootFolder)
|
2022-06-23 16:40:10 +08:00
|
|
|
|
f.MinusPanFolderModifyCount()
|
2022-06-04 13:20:33 +08:00
|
|
|
|
time.Sleep(3 * time.Second)
|
2022-06-01 21:55:03 +08:00
|
|
|
|
continue
|
|
|
|
|
}
|
2022-06-04 13:20:33 +08:00
|
|
|
|
panItem := objPan.(*PanFileItem)
|
|
|
|
|
panFiles, err = f.task.panFileDb.GetFileList(panItem.Path)
|
|
|
|
|
if err != nil {
|
|
|
|
|
panFiles = PanFileList{}
|
2022-06-01 21:55:03 +08:00
|
|
|
|
}
|
2022-06-04 13:20:33 +08:00
|
|
|
|
localFiles, err = f.task.localFileDb.GetFileList(f.getLocalPathFromPanPath(panItem.Path))
|
|
|
|
|
if err != nil {
|
|
|
|
|
localFiles = LocalFileList{}
|
2022-06-01 21:55:03 +08:00
|
|
|
|
}
|
2022-06-04 13:20:33 +08:00
|
|
|
|
f.doFileDiffRoutine(panFiles, localFiles, panFolderQueue, nil)
|
|
|
|
|
time.Sleep(500 * time.Millisecond)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *FileActionTaskManager) doFileDiffRoutine(panFiles PanFileList, localFiles LocalFileList, panFolderQueue *collection.Queue, localFolderQueue *collection.Queue) {
|
|
|
|
|
// empty loop
|
|
|
|
|
if len(panFiles) == 0 && len(localFiles) == 0 {
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
localFilesSet := &localFileSet{
|
|
|
|
|
items: localFiles,
|
|
|
|
|
localFolderPath: f.task.LocalFolderPath,
|
|
|
|
|
}
|
|
|
|
|
panFilesSet := &panFileSet{
|
|
|
|
|
items: panFiles,
|
|
|
|
|
panFolderPath: f.task.PanFolderPath,
|
|
|
|
|
}
|
|
|
|
|
localFilesNeedToUpload := localFilesSet.Difference(panFilesSet)
|
|
|
|
|
panFilesNeedToDownload := panFilesSet.Difference(localFilesSet)
|
|
|
|
|
localFilesNeedToCheck, panFilesNeedToCheck := localFilesSet.Intersection(panFilesSet)
|
|
|
|
|
|
|
|
|
|
// download file from pan drive
|
2022-06-09 19:58:16 +08:00
|
|
|
|
if panFilesNeedToDownload != nil {
|
|
|
|
|
for _, file := range panFilesNeedToDownload {
|
|
|
|
|
if file.ScanStatus == ScanStatusNormal { // 下载文件
|
|
|
|
|
if f.task.Mode == DownloadOnly || f.task.Mode == SyncTwoWay {
|
2022-07-02 18:59:00 +08:00
|
|
|
|
syncItem := &SyncFileItem{
|
|
|
|
|
Action: "",
|
|
|
|
|
Status: SyncFileStatusCreate,
|
|
|
|
|
LocalFile: nil,
|
|
|
|
|
PanFile: file,
|
|
|
|
|
StatusUpdateTime: "",
|
|
|
|
|
PanFolderPath: f.task.PanFolderPath,
|
|
|
|
|
LocalFolderPath: f.task.LocalFolderPath,
|
|
|
|
|
DriveId: f.task.DriveId,
|
2022-08-13 16:54:42 +08:00
|
|
|
|
DownloadBlockSize: f.syncOption.FileDownloadBlockSize,
|
|
|
|
|
UploadBlockSize: f.syncOption.FileUploadBlockSize,
|
|
|
|
|
UseInternalUrl: f.syncOption.UseInternalUrl,
|
2022-07-02 18:59:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-09 14:52:49 +08:00
|
|
|
|
if file.IsFolder() {
|
|
|
|
|
if panFolderQueue != nil {
|
|
|
|
|
panFolderQueue.PushUnique(file)
|
|
|
|
|
}
|
2022-07-02 18:59:00 +08:00
|
|
|
|
// 创建本地文件夹,这样就可以同步空文件夹
|
|
|
|
|
syncItem.Action = SyncFileActionCreateLocalFolder
|
|
|
|
|
} else {
|
|
|
|
|
syncItem.Action = SyncFileActionDownload
|
2022-06-09 14:52:49 +08:00
|
|
|
|
}
|
2022-07-02 18:59:00 +08:00
|
|
|
|
|
2022-06-09 14:52:49 +08:00
|
|
|
|
fileActionTask := &FileActionTask{
|
2022-07-02 18:59:00 +08:00
|
|
|
|
syncItem: syncItem,
|
2022-06-09 14:52:49 +08:00
|
|
|
|
}
|
|
|
|
|
f.addToSyncDb(fileActionTask)
|
2022-06-09 19:58:16 +08:00
|
|
|
|
}
|
|
|
|
|
} else if file.ScanStatus == ScanStatusDiscard { // 删除对应本地文件(文件夹)
|
|
|
|
|
if f.task.Mode == DownloadOnly || f.task.Mode == SyncTwoWay {
|
2022-06-09 14:52:49 +08:00
|
|
|
|
fileActionTask := &FileActionTask{
|
|
|
|
|
syncItem: &SyncFileItem{
|
2022-06-10 13:55:00 +08:00
|
|
|
|
Action: SyncFileActionDeleteLocal,
|
|
|
|
|
Status: SyncFileStatusCreate,
|
|
|
|
|
LocalFile: nil,
|
|
|
|
|
PanFile: file,
|
|
|
|
|
StatusUpdateTime: "",
|
|
|
|
|
PanFolderPath: f.task.PanFolderPath,
|
|
|
|
|
LocalFolderPath: f.task.LocalFolderPath,
|
|
|
|
|
DriveId: f.task.DriveId,
|
2022-08-13 16:54:42 +08:00
|
|
|
|
DownloadBlockSize: f.syncOption.FileDownloadBlockSize,
|
|
|
|
|
UploadBlockSize: f.syncOption.FileUploadBlockSize,
|
|
|
|
|
UseInternalUrl: f.syncOption.UseInternalUrl,
|
2022-06-09 14:52:49 +08:00
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
f.addToSyncDb(fileActionTask)
|
2022-06-09 19:58:16 +08:00
|
|
|
|
} else if f.task.Mode == UploadOnly {
|
|
|
|
|
// 删除无用记录
|
|
|
|
|
f.task.panFileDb.Delete(file.Path)
|
2022-06-01 21:55:03 +08:00
|
|
|
|
}
|
2022-06-04 13:20:33 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-06-01 21:55:03 +08:00
|
|
|
|
|
2022-06-04 13:20:33 +08:00
|
|
|
|
// upload file to pan drive
|
2022-06-09 19:58:16 +08:00
|
|
|
|
if localFilesNeedToUpload != nil {
|
|
|
|
|
for _, file := range localFilesNeedToUpload {
|
|
|
|
|
if file.ScanStatus == ScanStatusNormal { // 上传文件到云盘
|
|
|
|
|
if f.task.Mode == UploadOnly || f.task.Mode == SyncTwoWay {
|
2022-07-02 18:59:00 +08:00
|
|
|
|
syncItem := &SyncFileItem{
|
|
|
|
|
Action: "",
|
|
|
|
|
Status: SyncFileStatusCreate,
|
|
|
|
|
LocalFile: file,
|
|
|
|
|
PanFile: nil,
|
|
|
|
|
StatusUpdateTime: "",
|
|
|
|
|
PanFolderPath: f.task.PanFolderPath,
|
|
|
|
|
LocalFolderPath: f.task.LocalFolderPath,
|
|
|
|
|
DriveId: f.task.DriveId,
|
2022-08-13 16:54:42 +08:00
|
|
|
|
DownloadBlockSize: f.syncOption.FileDownloadBlockSize,
|
|
|
|
|
UploadBlockSize: f.syncOption.FileUploadBlockSize,
|
|
|
|
|
UseInternalUrl: f.syncOption.UseInternalUrl,
|
2022-07-02 18:59:00 +08:00
|
|
|
|
}
|
2022-06-09 14:52:49 +08:00
|
|
|
|
if file.IsFolder() {
|
|
|
|
|
if localFolderQueue != nil {
|
|
|
|
|
localFolderQueue.PushUnique(file)
|
|
|
|
|
}
|
2022-07-02 18:59:00 +08:00
|
|
|
|
// 创建云盘文件夹,这样就可以同步空文件夹
|
|
|
|
|
syncItem.Action = SyncFileActionCreatePanFolder
|
|
|
|
|
} else {
|
|
|
|
|
syncItem.Action = SyncFileActionUpload
|
2022-06-09 14:52:49 +08:00
|
|
|
|
}
|
2022-07-02 18:59:00 +08:00
|
|
|
|
|
2022-06-09 14:52:49 +08:00
|
|
|
|
fileActionTask := &FileActionTask{
|
2022-07-02 18:59:00 +08:00
|
|
|
|
syncItem: syncItem,
|
2022-06-09 14:52:49 +08:00
|
|
|
|
}
|
|
|
|
|
f.addToSyncDb(fileActionTask)
|
2022-06-09 19:58:16 +08:00
|
|
|
|
}
|
|
|
|
|
} else if file.ScanStatus == ScanStatusDiscard { // 删除对应云盘文件(文件夹)
|
|
|
|
|
if f.task.Mode == UploadOnly || f.task.Mode == SyncTwoWay {
|
2022-06-09 14:52:49 +08:00
|
|
|
|
fileActionTask := &FileActionTask{
|
|
|
|
|
syncItem: &SyncFileItem{
|
2022-06-10 13:55:00 +08:00
|
|
|
|
Action: SyncFileActionDeletePan,
|
|
|
|
|
Status: SyncFileStatusCreate,
|
|
|
|
|
LocalFile: file,
|
|
|
|
|
PanFile: nil,
|
|
|
|
|
StatusUpdateTime: "",
|
|
|
|
|
PanFolderPath: f.task.PanFolderPath,
|
|
|
|
|
LocalFolderPath: f.task.LocalFolderPath,
|
|
|
|
|
DriveId: f.task.DriveId,
|
2022-08-13 16:54:42 +08:00
|
|
|
|
DownloadBlockSize: f.syncOption.FileDownloadBlockSize,
|
|
|
|
|
UploadBlockSize: f.syncOption.FileUploadBlockSize,
|
|
|
|
|
UseInternalUrl: f.syncOption.UseInternalUrl,
|
2022-06-09 14:52:49 +08:00
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
f.addToSyncDb(fileActionTask)
|
2022-06-09 19:58:16 +08:00
|
|
|
|
} else if f.task.Mode == DownloadOnly {
|
|
|
|
|
// 删除无用记录
|
|
|
|
|
f.task.localFileDb.Delete(file.Path)
|
2022-06-01 21:55:03 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-06-04 13:20:33 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-06-01 21:55:03 +08:00
|
|
|
|
|
2022-06-09 14:52:49 +08:00
|
|
|
|
// compare file to decide download / upload / delete
|
2022-06-04 13:20:33 +08:00
|
|
|
|
for idx, _ := range localFilesNeedToCheck {
|
|
|
|
|
localFile := localFilesNeedToCheck[idx]
|
|
|
|
|
panFile := panFilesNeedToCheck[idx]
|
2022-06-09 14:52:49 +08:00
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// do delete local / pan file check
|
|
|
|
|
//
|
|
|
|
|
if localFile.ScanStatus == ScanStatusDiscard && panFile.ScanStatus == ScanStatusDiscard {
|
|
|
|
|
// 清除过期数据项
|
|
|
|
|
f.task.localFileDb.Delete(localFile.Path)
|
|
|
|
|
f.task.panFileDb.Delete(panFile.Path)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if localFile.ScanStatus == ScanStatusDiscard && panFile.ScanStatus == ScanStatusNormal && localFile.Sha1Hash == panFile.Sha1Hash {
|
|
|
|
|
if f.task.Mode == UploadOnly || f.task.Mode == SyncTwoWay {
|
|
|
|
|
// 删除对应的云盘文件
|
|
|
|
|
deletePanFile := &FileActionTask{
|
|
|
|
|
syncItem: &SyncFileItem{
|
2022-06-10 13:55:00 +08:00
|
|
|
|
Action: SyncFileActionDeletePan,
|
|
|
|
|
Status: SyncFileStatusCreate,
|
|
|
|
|
LocalFile: localFile,
|
|
|
|
|
PanFile: panFile,
|
|
|
|
|
StatusUpdateTime: "",
|
|
|
|
|
PanFolderPath: f.task.PanFolderPath,
|
|
|
|
|
LocalFolderPath: f.task.LocalFolderPath,
|
|
|
|
|
DriveId: f.task.DriveId,
|
2022-08-13 16:54:42 +08:00
|
|
|
|
DownloadBlockSize: f.syncOption.FileDownloadBlockSize,
|
|
|
|
|
UploadBlockSize: f.syncOption.FileUploadBlockSize,
|
|
|
|
|
UseInternalUrl: f.syncOption.UseInternalUrl,
|
2022-06-09 14:52:49 +08:00
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
f.addToSyncDb(deletePanFile)
|
2022-06-09 19:58:16 +08:00
|
|
|
|
} else if f.task.Mode == DownloadOnly {
|
|
|
|
|
// 删除无用记录
|
|
|
|
|
f.task.localFileDb.Delete(localFile.Path)
|
2022-06-09 14:52:49 +08:00
|
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if panFile.ScanStatus == ScanStatusDiscard && localFile.ScanStatus == ScanStatusNormal && localFile.Sha1Hash == panFile.Sha1Hash {
|
|
|
|
|
if f.task.Mode == DownloadOnly || f.task.Mode == SyncTwoWay {
|
|
|
|
|
// 删除对应的本地文件
|
|
|
|
|
deletePanFile := &FileActionTask{
|
|
|
|
|
syncItem: &SyncFileItem{
|
2022-06-10 13:55:00 +08:00
|
|
|
|
Action: SyncFileActionDeleteLocal,
|
|
|
|
|
Status: SyncFileStatusCreate,
|
|
|
|
|
LocalFile: localFile,
|
|
|
|
|
PanFile: panFile,
|
|
|
|
|
StatusUpdateTime: "",
|
|
|
|
|
PanFolderPath: f.task.PanFolderPath,
|
|
|
|
|
LocalFolderPath: f.task.LocalFolderPath,
|
|
|
|
|
DriveId: f.task.DriveId,
|
2022-08-13 16:54:42 +08:00
|
|
|
|
DownloadBlockSize: f.syncOption.FileDownloadBlockSize,
|
|
|
|
|
UploadBlockSize: f.syncOption.FileUploadBlockSize,
|
|
|
|
|
UseInternalUrl: f.syncOption.UseInternalUrl,
|
2022-06-09 14:52:49 +08:00
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
f.addToSyncDb(deletePanFile)
|
2022-06-09 19:58:16 +08:00
|
|
|
|
} else if f.task.Mode == UploadOnly {
|
|
|
|
|
// 删除无用记录
|
|
|
|
|
f.task.panFileDb.Delete(panFile.Path)
|
2022-06-09 14:52:49 +08:00
|
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// do download / upload check
|
|
|
|
|
//
|
2022-06-04 13:20:33 +08:00
|
|
|
|
if localFile.IsFolder() {
|
|
|
|
|
if localFolderQueue != nil {
|
|
|
|
|
localFolderQueue.PushUnique(localFile)
|
|
|
|
|
}
|
|
|
|
|
if panFolderQueue != nil {
|
|
|
|
|
panFolderQueue.PushUnique(panFile)
|
|
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
2022-06-01 21:55:03 +08:00
|
|
|
|
|
2022-06-04 13:20:33 +08:00
|
|
|
|
if localFile.Sha1Hash == "" {
|
|
|
|
|
// calc sha1
|
2022-06-17 06:59:04 +08:00
|
|
|
|
if localFile.FileSize == 0 {
|
|
|
|
|
localFile.Sha1Hash = aliyunpan.DefaultZeroSizeFileContentHash
|
|
|
|
|
} else {
|
|
|
|
|
fileSum := localfile.NewLocalFileEntity(localFile.Path)
|
|
|
|
|
err := fileSum.OpenPath()
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Verbosef("文件不可读, 错误信息: %s, 跳过...\n", err)
|
2022-06-20 20:38:22 +08:00
|
|
|
|
continue
|
2022-06-17 06:59:04 +08:00
|
|
|
|
}
|
|
|
|
|
fileSum.Sum(localfile.CHECKSUM_SHA1) // block operation
|
|
|
|
|
localFile.Sha1Hash = fileSum.SHA1
|
|
|
|
|
fileSum.Close()
|
2022-06-05 22:19:16 +08:00
|
|
|
|
}
|
2022-06-01 21:55:03 +08:00
|
|
|
|
|
2022-06-04 13:20:33 +08:00
|
|
|
|
// save sha1
|
|
|
|
|
f.task.localFileDb.Update(localFile)
|
|
|
|
|
}
|
2022-06-01 21:55:03 +08:00
|
|
|
|
|
2022-06-04 13:20:33 +08:00
|
|
|
|
if strings.ToLower(panFile.Sha1Hash) == strings.ToLower(localFile.Sha1Hash) {
|
|
|
|
|
// do nothing
|
2022-06-12 17:44:16 +08:00
|
|
|
|
logger.Verboseln("file is the same, no need to update file: ", localFile.Path)
|
2022-06-04 13:20:33 +08:00
|
|
|
|
continue
|
|
|
|
|
}
|
2022-06-01 21:55:03 +08:00
|
|
|
|
|
2022-06-04 13:20:33 +08:00
|
|
|
|
// 本地文件和云盘文件SHA1不一样
|
|
|
|
|
// 不同模式同步策略不一样
|
|
|
|
|
if f.task.Mode == UploadOnly {
|
|
|
|
|
uploadLocalFile := &FileActionTask{
|
|
|
|
|
syncItem: &SyncFileItem{
|
2022-06-10 13:55:00 +08:00
|
|
|
|
Action: SyncFileActionUpload,
|
|
|
|
|
Status: SyncFileStatusCreate,
|
|
|
|
|
LocalFile: localFile,
|
|
|
|
|
PanFile: nil,
|
|
|
|
|
StatusUpdateTime: "",
|
|
|
|
|
PanFolderPath: f.task.PanFolderPath,
|
|
|
|
|
LocalFolderPath: f.task.LocalFolderPath,
|
|
|
|
|
DriveId: f.task.DriveId,
|
2022-08-13 16:54:42 +08:00
|
|
|
|
DownloadBlockSize: f.syncOption.FileDownloadBlockSize,
|
|
|
|
|
UploadBlockSize: f.syncOption.FileUploadBlockSize,
|
|
|
|
|
UseInternalUrl: f.syncOption.UseInternalUrl,
|
2022-06-04 13:20:33 +08:00
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
f.addToSyncDb(uploadLocalFile)
|
|
|
|
|
} else if f.task.Mode == DownloadOnly {
|
|
|
|
|
downloadPanFile := &FileActionTask{
|
|
|
|
|
syncItem: &SyncFileItem{
|
2022-06-10 13:55:00 +08:00
|
|
|
|
Action: SyncFileActionDownload,
|
|
|
|
|
Status: SyncFileStatusCreate,
|
|
|
|
|
LocalFile: nil,
|
|
|
|
|
PanFile: panFile,
|
|
|
|
|
StatusUpdateTime: "",
|
|
|
|
|
PanFolderPath: f.task.PanFolderPath,
|
|
|
|
|
LocalFolderPath: f.task.LocalFolderPath,
|
|
|
|
|
DriveId: f.task.DriveId,
|
2022-08-13 16:54:42 +08:00
|
|
|
|
DownloadBlockSize: f.syncOption.FileDownloadBlockSize,
|
|
|
|
|
UploadBlockSize: f.syncOption.FileUploadBlockSize,
|
|
|
|
|
UseInternalUrl: f.syncOption.UseInternalUrl,
|
2022-06-04 13:20:33 +08:00
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
f.addToSyncDb(downloadPanFile)
|
|
|
|
|
} else if f.task.Mode == SyncTwoWay {
|
2022-08-13 17:50:07 +08:00
|
|
|
|
actFlag := "unknown"
|
2022-08-13 18:38:29 +08:00
|
|
|
|
if f.syncOption.SyncPriority == SyncPriorityLocalFirst { // 本地文件优先
|
|
|
|
|
actFlag = "upload"
|
|
|
|
|
} else if f.syncOption.SyncPriority == SyncPriorityPanFirst { // 网盘文件优先
|
|
|
|
|
actFlag = "download"
|
|
|
|
|
} else {
|
2022-08-13 17:50:07 +08:00
|
|
|
|
if localFile.UpdateTimeUnix() > panFile.UpdateTimeUnix() { // upload file
|
|
|
|
|
actFlag = "upload"
|
|
|
|
|
} else if localFile.UpdateTimeUnix() < panFile.UpdateTimeUnix() { // download file
|
|
|
|
|
actFlag = "download"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if actFlag == "upload" { // upload file
|
2022-06-04 13:20:33 +08:00
|
|
|
|
uploadLocalFile := &FileActionTask{
|
|
|
|
|
syncItem: &SyncFileItem{
|
2022-06-10 13:55:00 +08:00
|
|
|
|
Action: SyncFileActionUpload,
|
|
|
|
|
Status: SyncFileStatusCreate,
|
|
|
|
|
LocalFile: localFile,
|
|
|
|
|
PanFile: nil,
|
|
|
|
|
StatusUpdateTime: "",
|
|
|
|
|
PanFolderPath: f.task.PanFolderPath,
|
|
|
|
|
LocalFolderPath: f.task.LocalFolderPath,
|
|
|
|
|
DriveId: f.task.DriveId,
|
2022-08-13 16:54:42 +08:00
|
|
|
|
DownloadBlockSize: f.syncOption.FileDownloadBlockSize,
|
|
|
|
|
UploadBlockSize: f.syncOption.FileUploadBlockSize,
|
|
|
|
|
UseInternalUrl: f.syncOption.UseInternalUrl,
|
2022-06-04 13:20:33 +08:00
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
f.addToSyncDb(uploadLocalFile)
|
2022-08-13 17:50:07 +08:00
|
|
|
|
} else if actFlag == "download" { // download file
|
2022-06-04 13:20:33 +08:00
|
|
|
|
downloadPanFile := &FileActionTask{
|
|
|
|
|
syncItem: &SyncFileItem{
|
2022-06-10 13:55:00 +08:00
|
|
|
|
Action: SyncFileActionDownload,
|
|
|
|
|
Status: SyncFileStatusCreate,
|
|
|
|
|
LocalFile: nil,
|
|
|
|
|
PanFile: panFile,
|
|
|
|
|
StatusUpdateTime: "",
|
|
|
|
|
PanFolderPath: f.task.PanFolderPath,
|
|
|
|
|
LocalFolderPath: f.task.LocalFolderPath,
|
|
|
|
|
DriveId: f.task.DriveId,
|
2022-08-13 16:54:42 +08:00
|
|
|
|
DownloadBlockSize: f.syncOption.FileDownloadBlockSize,
|
|
|
|
|
UploadBlockSize: f.syncOption.FileUploadBlockSize,
|
|
|
|
|
UseInternalUrl: f.syncOption.UseInternalUrl,
|
2022-06-04 13:20:33 +08:00
|
|
|
|
},
|
2022-06-01 21:55:03 +08:00
|
|
|
|
}
|
2022-06-04 13:20:33 +08:00
|
|
|
|
f.addToSyncDb(downloadPanFile)
|
2022-06-01 21:55:03 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-04 13:20:33 +08:00
|
|
|
|
func (f *FileActionTaskManager) addToSyncDb(fileTask *FileActionTask) {
|
2022-06-01 21:55:03 +08:00
|
|
|
|
f.mutex.Lock()
|
|
|
|
|
defer f.mutex.Unlock()
|
2022-06-04 13:20:33 +08:00
|
|
|
|
|
|
|
|
|
// check sync db
|
2022-06-01 21:55:03 +08:00
|
|
|
|
if itemInDb, e := f.task.syncFileDb.Get(fileTask.syncItem.Id()); e == nil && itemInDb != nil {
|
|
|
|
|
if itemInDb.Status == SyncFileStatusCreate || itemInDb.Status == SyncFileStatusDownloading || itemInDb.Status == SyncFileStatusUploading {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if itemInDb.Status == SyncFileStatusSuccess {
|
2022-07-02 21:41:21 +08:00
|
|
|
|
if (time.Now().Unix() - itemInDb.StatusUpdateTimeUnix()) < TimeSecondsOfOneMinute {
|
|
|
|
|
// 少于1分钟,不同步,减少同步频次
|
2022-06-01 21:55:03 +08:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-06-04 13:20:33 +08:00
|
|
|
|
if itemInDb.Status == SyncFileStatusIllegal {
|
|
|
|
|
if (time.Now().Unix() - itemInDb.StatusUpdateTimeUnix()) < TimeSecondsOf60Minute {
|
|
|
|
|
// 非法文件,少于60分钟,不同步,减少同步频次
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if itemInDb.Status == SyncFileStatusNotExisted {
|
|
|
|
|
if itemInDb.Action == SyncFileActionDownload {
|
|
|
|
|
if itemInDb.PanFile.UpdatedAt == fileTask.syncItem.PanFile.UpdatedAt {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
} else if itemInDb.Action == SyncFileActionUpload {
|
|
|
|
|
if itemInDb.LocalFile.UpdatedAt == fileTask.syncItem.LocalFile.UpdatedAt {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-06-01 21:55:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 进入任务队列
|
|
|
|
|
f.task.syncFileDb.Add(fileTask.syncItem)
|
2022-06-24 10:36:03 +08:00
|
|
|
|
|
|
|
|
|
// label file action modify
|
|
|
|
|
f.AddSyncActionModifyCount()
|
2022-06-01 21:55:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-04 13:20:33 +08:00
|
|
|
|
func (f *FileActionTaskManager) getFromSyncDb(act SyncFileAction) *FileActionTask {
|
2022-06-01 21:55:03 +08:00
|
|
|
|
f.mutex.Lock()
|
|
|
|
|
defer f.mutex.Unlock()
|
|
|
|
|
|
|
|
|
|
if act == SyncFileActionDownload {
|
|
|
|
|
if files, e := f.task.syncFileDb.GetFileList(SyncFileStatusDownloading); e == nil {
|
2022-06-04 13:20:33 +08:00
|
|
|
|
for _, file := range files {
|
|
|
|
|
if !f.fileInProcessQueue.Contains(file) {
|
|
|
|
|
return &FileActionTask{
|
2022-07-02 18:59:00 +08:00
|
|
|
|
localFileDb: f.task.localFileDb,
|
|
|
|
|
panFileDb: f.task.panFileDb,
|
|
|
|
|
syncFileDb: f.task.syncFileDb,
|
|
|
|
|
panClient: f.task.panClient,
|
|
|
|
|
syncItem: file,
|
2022-08-13 16:54:42 +08:00
|
|
|
|
maxDownloadRate: f.syncOption.MaxDownloadRate,
|
|
|
|
|
maxUploadRate: f.syncOption.MaxUploadRate,
|
2022-07-02 18:59:00 +08:00
|
|
|
|
localFolderCreateMutex: f.localCreateMutex,
|
|
|
|
|
panFolderCreateMutex: f.folderCreateMutex,
|
2022-06-04 13:20:33 +08:00
|
|
|
|
}
|
2022-06-01 21:55:03 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if act == SyncFileActionUpload {
|
|
|
|
|
if files, e := f.task.syncFileDb.GetFileList(SyncFileStatusUploading); e == nil {
|
2022-06-04 13:20:33 +08:00
|
|
|
|
for _, file := range files {
|
|
|
|
|
if !f.fileInProcessQueue.Contains(file) {
|
|
|
|
|
return &FileActionTask{
|
2022-07-02 18:59:00 +08:00
|
|
|
|
localFileDb: f.task.localFileDb,
|
|
|
|
|
panFileDb: f.task.panFileDb,
|
|
|
|
|
syncFileDb: f.task.syncFileDb,
|
|
|
|
|
panClient: f.task.panClient,
|
|
|
|
|
syncItem: file,
|
2022-08-13 16:54:42 +08:00
|
|
|
|
maxDownloadRate: f.syncOption.MaxDownloadRate,
|
|
|
|
|
maxUploadRate: f.syncOption.MaxUploadRate,
|
2022-07-02 18:59:00 +08:00
|
|
|
|
localFolderCreateMutex: f.localCreateMutex,
|
|
|
|
|
panFolderCreateMutex: f.folderCreateMutex,
|
2022-06-04 13:20:33 +08:00
|
|
|
|
}
|
2022-06-01 21:55:03 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if files, e := f.task.syncFileDb.GetFileList(SyncFileStatusCreate); e == nil {
|
|
|
|
|
if len(files) > 0 {
|
|
|
|
|
for _, file := range files {
|
2022-06-04 13:20:33 +08:00
|
|
|
|
if file.Action == act && !f.fileInProcessQueue.Contains(file) {
|
2022-06-01 21:55:03 +08:00
|
|
|
|
return &FileActionTask{
|
2022-07-02 18:59:00 +08:00
|
|
|
|
localFileDb: f.task.localFileDb,
|
|
|
|
|
panFileDb: f.task.panFileDb,
|
|
|
|
|
syncFileDb: f.task.syncFileDb,
|
|
|
|
|
panClient: f.task.panClient,
|
|
|
|
|
syncItem: file,
|
2022-08-13 16:54:42 +08:00
|
|
|
|
maxDownloadRate: f.syncOption.MaxDownloadRate,
|
|
|
|
|
maxUploadRate: f.syncOption.MaxUploadRate,
|
2022-07-02 18:59:00 +08:00
|
|
|
|
localFolderCreateMutex: f.localCreateMutex,
|
|
|
|
|
panFolderCreateMutex: f.folderCreateMutex,
|
2022-06-01 21:55:03 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-05-24 23:01:08 +08:00
|
|
|
|
return nil
|
|
|
|
|
}
|
2022-06-01 21:55:03 +08:00
|
|
|
|
|
2022-06-04 13:20:33 +08:00
|
|
|
|
// cleanSyncDbRecords 清楚同步数据库无用数据
|
|
|
|
|
func (f *FileActionTaskManager) cleanSyncDbRecords(ctx context.Context) {
|
|
|
|
|
// TODO: failed / success / illegal
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-01 21:55:03 +08:00
|
|
|
|
// fileActionTaskExecutor 异步执行文件操作
|
|
|
|
|
func (f *FileActionTaskManager) fileActionTaskExecutor(ctx context.Context) {
|
|
|
|
|
f.wg.AddDelta()
|
|
|
|
|
defer f.wg.Done()
|
|
|
|
|
|
2022-08-13 16:54:42 +08:00
|
|
|
|
downloadWaitGroup := waitgroup.NewWaitGroup(f.syncOption.FileDownloadParallel)
|
|
|
|
|
uploadWaitGroup := waitgroup.NewWaitGroup(f.syncOption.FileUploadParallel)
|
2022-07-02 18:59:00 +08:00
|
|
|
|
localFileWaitGroup := waitgroup.NewWaitGroup(1)
|
|
|
|
|
panFileWaitGroup := waitgroup.NewWaitGroup(1)
|
2022-06-04 13:20:33 +08:00
|
|
|
|
|
2022-06-01 21:55:03 +08:00
|
|
|
|
for {
|
|
|
|
|
select {
|
|
|
|
|
case <-ctx.Done():
|
|
|
|
|
// cancel routine & done
|
|
|
|
|
logger.Verboseln("file executor routine done")
|
2022-06-04 13:20:33 +08:00
|
|
|
|
downloadWaitGroup.Wait()
|
2022-06-01 21:55:03 +08:00
|
|
|
|
return
|
|
|
|
|
default:
|
2022-06-12 17:44:16 +08:00
|
|
|
|
//logger.Verboseln("do file executor process")
|
2022-06-24 10:36:03 +08:00
|
|
|
|
if f.getSyncActionModifyCount() <= 0 {
|
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
|
continue
|
|
|
|
|
}
|
2022-06-01 21:55:03 +08:00
|
|
|
|
|
2022-06-24 10:36:03 +08:00
|
|
|
|
actionIsEmptyOfThisTerm := true
|
2022-06-01 21:55:03 +08:00
|
|
|
|
// do upload
|
2022-06-05 22:19:16 +08:00
|
|
|
|
uploadItem := f.getFromSyncDb(SyncFileActionUpload)
|
|
|
|
|
if uploadItem != nil {
|
2022-06-24 10:36:03 +08:00
|
|
|
|
actionIsEmptyOfThisTerm = false
|
2022-08-13 16:54:42 +08:00
|
|
|
|
if uploadWaitGroup.Parallel() < f.syncOption.FileUploadParallel {
|
2022-06-05 22:19:16 +08:00
|
|
|
|
uploadWaitGroup.AddDelta()
|
|
|
|
|
f.fileInProcessQueue.PushUnique(uploadItem.syncItem)
|
|
|
|
|
go func() {
|
|
|
|
|
if e := uploadItem.DoAction(ctx); e == nil {
|
|
|
|
|
// success
|
2022-06-09 14:52:49 +08:00
|
|
|
|
f.fileInProcessQueue.Remove(uploadItem.syncItem)
|
2022-06-05 22:19:16 +08:00
|
|
|
|
} else {
|
|
|
|
|
// retry?
|
2022-06-09 14:52:49 +08:00
|
|
|
|
f.fileInProcessQueue.Remove(uploadItem.syncItem)
|
2022-06-05 22:19:16 +08:00
|
|
|
|
}
|
|
|
|
|
uploadWaitGroup.Done()
|
|
|
|
|
}()
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-06-01 21:55:03 +08:00
|
|
|
|
|
|
|
|
|
// do download
|
2022-06-04 13:20:33 +08:00
|
|
|
|
downloadItem := f.getFromSyncDb(SyncFileActionDownload)
|
2022-06-01 21:55:03 +08:00
|
|
|
|
if downloadItem != nil {
|
2022-06-24 10:36:03 +08:00
|
|
|
|
actionIsEmptyOfThisTerm = false
|
2022-08-13 16:54:42 +08:00
|
|
|
|
if downloadWaitGroup.Parallel() < f.syncOption.FileDownloadParallel {
|
2022-06-04 13:20:33 +08:00
|
|
|
|
downloadWaitGroup.AddDelta()
|
|
|
|
|
f.fileInProcessQueue.PushUnique(downloadItem.syncItem)
|
|
|
|
|
go func() {
|
2022-06-05 00:00:28 +08:00
|
|
|
|
if e := downloadItem.DoAction(ctx); e == nil {
|
2022-06-04 13:20:33 +08:00
|
|
|
|
// success
|
2022-06-09 14:52:49 +08:00
|
|
|
|
f.fileInProcessQueue.Remove(downloadItem.syncItem)
|
2022-06-04 13:20:33 +08:00
|
|
|
|
} else {
|
|
|
|
|
// retry?
|
2022-06-09 14:52:49 +08:00
|
|
|
|
f.fileInProcessQueue.Remove(downloadItem.syncItem)
|
2022-06-04 13:20:33 +08:00
|
|
|
|
}
|
|
|
|
|
downloadWaitGroup.Done()
|
|
|
|
|
}()
|
|
|
|
|
}
|
2022-06-01 21:55:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-09 14:52:49 +08:00
|
|
|
|
// delete local
|
|
|
|
|
deleteLocalItem := f.getFromSyncDb(SyncFileActionDeleteLocal)
|
|
|
|
|
if deleteLocalItem != nil {
|
2022-06-24 10:36:03 +08:00
|
|
|
|
actionIsEmptyOfThisTerm = false
|
2022-07-02 18:59:00 +08:00
|
|
|
|
if localFileWaitGroup.Parallel() < 1 {
|
|
|
|
|
localFileWaitGroup.AddDelta()
|
2022-06-09 14:52:49 +08:00
|
|
|
|
f.fileInProcessQueue.PushUnique(deleteLocalItem.syncItem)
|
|
|
|
|
go func() {
|
|
|
|
|
if e := deleteLocalItem.DoAction(ctx); e == nil {
|
|
|
|
|
// success
|
|
|
|
|
f.fileInProcessQueue.Remove(deleteLocalItem.syncItem)
|
|
|
|
|
} else {
|
|
|
|
|
// retry?
|
|
|
|
|
f.fileInProcessQueue.Remove(deleteLocalItem.syncItem)
|
|
|
|
|
}
|
2022-07-02 18:59:00 +08:00
|
|
|
|
localFileWaitGroup.Done()
|
2022-06-09 14:52:49 +08:00
|
|
|
|
}()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// delete pan
|
|
|
|
|
deletePanItem := f.getFromSyncDb(SyncFileActionDeletePan)
|
|
|
|
|
if deletePanItem != nil {
|
2022-06-24 10:36:03 +08:00
|
|
|
|
actionIsEmptyOfThisTerm = false
|
2022-07-02 18:59:00 +08:00
|
|
|
|
if panFileWaitGroup.Parallel() < 1 {
|
|
|
|
|
panFileWaitGroup.AddDelta()
|
2022-06-09 14:52:49 +08:00
|
|
|
|
f.fileInProcessQueue.PushUnique(deletePanItem.syncItem)
|
|
|
|
|
go func() {
|
|
|
|
|
if e := deletePanItem.DoAction(ctx); e == nil {
|
|
|
|
|
// success
|
|
|
|
|
f.fileInProcessQueue.Remove(deletePanItem.syncItem)
|
|
|
|
|
} else {
|
|
|
|
|
// retry?
|
|
|
|
|
f.fileInProcessQueue.Remove(deletePanItem.syncItem)
|
|
|
|
|
}
|
2022-07-02 18:59:00 +08:00
|
|
|
|
panFileWaitGroup.Done()
|
|
|
|
|
}()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// create local folder
|
|
|
|
|
createLocalFolderItem := f.getFromSyncDb(SyncFileActionCreateLocalFolder)
|
|
|
|
|
if createLocalFolderItem != nil {
|
|
|
|
|
actionIsEmptyOfThisTerm = false
|
|
|
|
|
if localFileWaitGroup.Parallel() < 1 {
|
|
|
|
|
localFileWaitGroup.AddDelta()
|
|
|
|
|
f.fileInProcessQueue.PushUnique(createLocalFolderItem.syncItem)
|
|
|
|
|
go func() {
|
|
|
|
|
if e := createLocalFolderItem.DoAction(ctx); e == nil {
|
|
|
|
|
// success
|
|
|
|
|
f.fileInProcessQueue.Remove(createLocalFolderItem.syncItem)
|
|
|
|
|
} else {
|
|
|
|
|
// retry?
|
|
|
|
|
f.fileInProcessQueue.Remove(createLocalFolderItem.syncItem)
|
|
|
|
|
}
|
|
|
|
|
localFileWaitGroup.Done()
|
|
|
|
|
}()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// create pan folder
|
|
|
|
|
createPanFolderItem := f.getFromSyncDb(SyncFileActionCreatePanFolder)
|
|
|
|
|
if createPanFolderItem != nil {
|
|
|
|
|
actionIsEmptyOfThisTerm = false
|
|
|
|
|
if panFileWaitGroup.Parallel() < 1 {
|
|
|
|
|
panFileWaitGroup.AddDelta()
|
|
|
|
|
f.fileInProcessQueue.PushUnique(createPanFolderItem.syncItem)
|
|
|
|
|
go func() {
|
|
|
|
|
if e := createPanFolderItem.DoAction(ctx); e == nil {
|
|
|
|
|
// success
|
|
|
|
|
f.fileInProcessQueue.Remove(createPanFolderItem.syncItem)
|
|
|
|
|
} else {
|
|
|
|
|
// retry?
|
|
|
|
|
f.fileInProcessQueue.Remove(createPanFolderItem.syncItem)
|
|
|
|
|
}
|
|
|
|
|
panFileWaitGroup.Done()
|
2022-06-09 14:52:49 +08:00
|
|
|
|
}()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-24 10:36:03 +08:00
|
|
|
|
// check action list is empty or not
|
|
|
|
|
if actionIsEmptyOfThisTerm {
|
|
|
|
|
// all action queue is empty
|
|
|
|
|
// complete one loop
|
|
|
|
|
f.MinusSyncActionModifyCount()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// delay for next term
|
|
|
|
|
time.Sleep(1 * time.Second)
|
2022-06-01 21:55:03 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// getRelativePath 获取文件的相对路径
|
|
|
|
|
func (l *localFileSet) getRelativePath(localPath string) string {
|
|
|
|
|
localPath = strings.ReplaceAll(localPath, "\\", "/")
|
|
|
|
|
localRootPath := strings.ReplaceAll(l.localFolderPath, "\\", "/")
|
|
|
|
|
relativePath := strings.TrimPrefix(localPath, localRootPath)
|
|
|
|
|
return path.Clean(relativePath)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Intersection 交集
|
|
|
|
|
func (l *localFileSet) Intersection(other *panFileSet) (LocalFileList, PanFileList) {
|
|
|
|
|
localFilePathSet := mapset.NewThreadUnsafeSet()
|
|
|
|
|
relativePathLocalMap := map[string]*LocalFileItem{}
|
|
|
|
|
for _, item := range l.items {
|
|
|
|
|
rp := l.getRelativePath(item.Path)
|
|
|
|
|
relativePathLocalMap[rp] = item
|
|
|
|
|
localFilePathSet.Add(rp)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
localFileList := LocalFileList{}
|
|
|
|
|
panFileList := PanFileList{}
|
|
|
|
|
for _, item := range other.items {
|
|
|
|
|
rp := other.getRelativePath(item.Path)
|
|
|
|
|
if localFilePathSet.Contains(rp) {
|
|
|
|
|
localFileList = append(localFileList, relativePathLocalMap[rp])
|
|
|
|
|
panFileList = append(panFileList, item)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return localFileList, panFileList
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Difference 差集
|
|
|
|
|
func (l *localFileSet) Difference(other *panFileSet) LocalFileList {
|
|
|
|
|
panFilePathSet := mapset.NewThreadUnsafeSet()
|
|
|
|
|
for _, item := range other.items {
|
|
|
|
|
rp := other.getRelativePath(item.Path)
|
|
|
|
|
panFilePathSet.Add(rp)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
localFileList := LocalFileList{}
|
|
|
|
|
for _, item := range l.items {
|
|
|
|
|
rp := l.getRelativePath(item.Path)
|
|
|
|
|
if !panFilePathSet.Contains(rp) {
|
|
|
|
|
localFileList = append(localFileList, item)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return localFileList
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// getRelativePath 获取文件的相对路径
|
|
|
|
|
func (p *panFileSet) getRelativePath(panPath string) string {
|
|
|
|
|
panPath = strings.ReplaceAll(panPath, "\\", "/")
|
|
|
|
|
panRootPath := strings.ReplaceAll(p.panFolderPath, "\\", "/")
|
|
|
|
|
relativePath := strings.TrimPrefix(panPath, panRootPath)
|
|
|
|
|
return path.Clean(relativePath)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Intersection 交集
|
|
|
|
|
func (p *panFileSet) Intersection(other *localFileSet) (PanFileList, LocalFileList) {
|
|
|
|
|
localFilePathSet := mapset.NewThreadUnsafeSet()
|
|
|
|
|
relativePathLocalMap := map[string]*LocalFileItem{}
|
|
|
|
|
for _, item := range other.items {
|
|
|
|
|
rp := other.getRelativePath(item.Path)
|
|
|
|
|
relativePathLocalMap[rp] = item
|
|
|
|
|
localFilePathSet.Add(rp)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
localFileList := LocalFileList{}
|
|
|
|
|
panFileList := PanFileList{}
|
|
|
|
|
for _, item := range p.items {
|
|
|
|
|
rp := p.getRelativePath(item.Path)
|
|
|
|
|
if localFilePathSet.Contains(rp) {
|
|
|
|
|
localFileList = append(localFileList, relativePathLocalMap[rp])
|
|
|
|
|
panFileList = append(panFileList, item)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return panFileList, localFileList
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Difference 差集
|
|
|
|
|
func (p *panFileSet) Difference(other *localFileSet) PanFileList {
|
|
|
|
|
localFilePathSet := mapset.NewThreadUnsafeSet()
|
|
|
|
|
for _, item := range other.items {
|
|
|
|
|
rp := other.getRelativePath(item.Path)
|
|
|
|
|
localFilePathSet.Add(rp)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
panFileList := PanFileList{}
|
|
|
|
|
for _, item := range p.items {
|
|
|
|
|
rp := p.getRelativePath(item.Path)
|
|
|
|
|
if !localFilePathSet.Contains(rp) {
|
|
|
|
|
panFileList = append(panFileList, item)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return panFileList
|
|
|
|
|
}
|