Finish the delete and sync by physics.

This commit is contained in:
lishuang 2020-07-11 19:56:13 +08:00
parent f16d48b432
commit 7fe673068b
5 changed files with 165 additions and 10 deletions

View File

@ -38,7 +38,7 @@ type Matter struct {
Md5 string `json:"md5" gorm:"type:varchar(45)"` Md5 string `json:"md5" gorm:"type:varchar(45)"`
Size int64 `json:"size" gorm:"type:bigint(20) not null;default:0"` Size int64 `json:"size" gorm:"type:bigint(20) not null;default:0"`
Privacy bool `json:"privacy" gorm:"type:tinyint(1) not null;default:0"` Privacy bool `json:"privacy" gorm:"type:tinyint(1) not null;default:0"`
Path string `json:"path" gorm:"type:varchar(1024)"` Path string `json:"path" gorm:"type:varchar(1024);index:idx_p"`
Times int64 `json:"times" gorm:"type:bigint(20) not null;default:0"` Times int64 `json:"times" gorm:"type:bigint(20) not null;default:0"`
Parent *Matter `json:"parent" gorm:"-"` Parent *Matter `json:"parent" gorm:"-"`
Children []*Matter `json:"-" gorm:"-"` Children []*Matter `json:"-" gorm:"-"`

View File

@ -13,6 +13,7 @@ import (
"net/http" "net/http"
"os" "os"
"path" "path"
"path/filepath"
"regexp" "regexp"
"strings" "strings"
"time" "time"
@ -284,7 +285,6 @@ func (this *MatterService) Upload(request *http.Request, file io.Reader, user *U
} }
dirAbsolutePath := dirMatter.AbsolutePath() dirAbsolutePath := dirMatter.AbsolutePath()
dirRelativePath := dirMatter.Path
count := this.matterDao.CountByUserUuidAndPuuidAndDirAndName(user.Uuid, dirMatter.Uuid, false, filename) count := this.matterDao.CountByUserUuidAndPuuidAndDirAndName(user.Uuid, dirMatter.Uuid, false, filename)
if count > 0 { if count > 0 {
@ -292,7 +292,6 @@ func (this *MatterService) Upload(request *http.Request, file io.Reader, user *U
} }
fileAbsolutePath := dirAbsolutePath + "/" + filename fileAbsolutePath := dirAbsolutePath + "/" + filename
fileRelativePath := dirRelativePath + "/" + filename
util.MakeDirAll(dirAbsolutePath) util.MakeDirAll(dirAbsolutePath)
@ -340,6 +339,16 @@ func (this *MatterService) Upload(request *http.Request, file io.Reader, user *U
} }
} }
matter := this.CreateNonDirMatter(dirMatter, filename, fileSize, privacy, user)
return matter
}
// create a non dir matter.
func (this *MatterService) CreateNonDirMatter(dirMatter *Matter, filename string, fileSize int64, privacy bool, user *User) *Matter {
dirRelativePath := dirMatter.Path
fileRelativePath := dirRelativePath + "/" + filename
//write to db. //write to db.
matter := &Matter{ matter := &Matter{
Puuid: dirMatter.Uuid, Puuid: dirMatter.Uuid,
@ -363,6 +372,21 @@ func (this *MatterService) Upload(request *http.Request, file io.Reader, user *U
return matter return matter
} }
// create a non dir matter.
func (this *MatterService) UpdateNonDirMatter(matter *Matter, fileSize int64, user *User) *Matter {
matter.Size = fileSize
matter = this.matterDao.Save(matter)
//compute the size of directory
go core.RunWithRecovery(func() {
this.ComputeRouteSize(matter.Puuid, user)
})
return matter
}
// compute route size. It will compute upward until root directory // compute route size. It will compute upward until root directory
func (this *MatterService) ComputeRouteSize(matterUuid string, user *User) { func (this *MatterService) ComputeRouteSize(matterUuid string, user *User) {
@ -1051,21 +1075,38 @@ func (this *MatterService) adjustPath(matter *Matter, parentMatter *Matter) {
} }
//delete someone's EyeblueTank files according to physics files. //delete someone's EyeblueTank files according to physics files.
func (this *MatterService) DeleteByPhysics(user *User) { func (this *MatterService) DeleteByPhysics(request *http.Request, user *User) {
if user == nil { if user == nil {
panic(result.BadRequest("user cannot be nil.")) panic(result.BadRequest("user cannot be nil."))
} }
//scan user's file. //scan user's file. scan level by level.
this.matterDao.PageHandle("", user.Uuid, "", "", func(matter *Matter) { rootMatter := NewRootMatter(user)
this.logger.Info("handle %s", matter.Name) this.deleteFolderByPhysics(request, rootMatter, user)
})
} }
func (this *MatterService) deleteFolderByPhysics(request *http.Request, dirMatter *Matter, user *User) {
//scan user's file. scan level by level.
this.matterDao.PageHandle(dirMatter.Uuid, user.Uuid, "", "", func(matter *Matter) {
if matter.Dir {
//delete children first.
this.deleteFolderByPhysics(request, matter, user)
}
if !util.PathExists(matter.AbsolutePath()) {
this.logger.Info("physics file not exist. delete from tank. %s", matter.Name)
this.AtomicDelete(nil, matter, user)
}
})
}
//scan someone's physics files to EyeblueTank //scan someone's physics files to EyeblueTank
func (this *MatterService) Scan(user *User) { func (this *MatterService) ScanPhysics(request *http.Request, user *User) {
if user == nil { if user == nil {
panic(result.BadRequest("user cannot be nil.")) panic(result.BadRequest("user cannot be nil."))
@ -1074,4 +1115,77 @@ func (this *MatterService) Scan(user *User) {
rootDirPath := GetUserMatterRootDir(user.Username) rootDirPath := GetUserMatterRootDir(user.Username)
this.logger.Info("scan %s's root dir %s", user.Username, rootDirPath) this.logger.Info("scan %s's root dir %s", user.Username, rootDirPath)
rootExists := util.PathExists(rootDirPath)
if !rootExists {
util.MakeDirAll(rootDirPath)
}
rootFileInfo, err := os.Lstat(rootDirPath)
if err != nil {
panic(result.BadRequest("cannot get root file info."))
}
rootMatter := NewRootMatter(user)
this.scanPhysicsFolder(request, rootFileInfo, rootMatter, user)
}
func (this *MatterService) scanPhysicsFolder(request *http.Request, dirInfo os.FileInfo, dirMatter *Matter, user *User) {
if !dirInfo.IsDir() {
return
}
//fetch all matters under this folder.
_, matters := this.matterDao.PlainPage(0, 1000, dirMatter.Uuid, user.Uuid, "", "", nil, nil)
nameMatterMap := make(map[string]*Matter)
for _, m := range matters {
nameMatterMap[m.Name] = m
}
dirPath := dirMatter.AbsolutePath()
names, err := util.ReadDirNames(dirPath)
if err != nil {
this.logger.Error("occur error when ReadDirNames %s %s", dirPath, err.Error())
return
}
for _, name := range names {
fileFullPath := filepath.Join(dirPath, name)
fileInfo, err := os.Lstat(fileFullPath)
if err != nil {
this.logger.Error("occur error when Lstat %s %s", name, err.Error())
continue
}
//find ther matter
var matter *Matter
_, ok := nameMatterMap[name]
if ok {
//exits. check the basic info.
matter = nameMatterMap[name]
//only check the fileSize.
if !matter.Dir {
if matter.Size != fileInfo.Size() {
this.logger.Info("update matter: %s size %d -> %d", name, matter.Size, fileInfo.Size())
this.UpdateNonDirMatter(matter, fileInfo.Size(), user)
}
}
} else {
if fileInfo.IsDir() {
//create folder.
matter = this.createDirectory(request, dirMatter, name, user)
//recursive scan this folder.
this.scanPhysicsFolder(request, fileInfo, matter, user)
} else {
//not exist. add basic info.
this.logger.Info("Create matter: %s size %d", name, fileInfo.Size())
matter = this.CreateNonDirMatter(dirMatter, name, fileInfo.Size(), true, user)
}
}
}
} }

View File

@ -444,7 +444,8 @@ func (this *UserController) Scan(writer http.ResponseWriter, request *http.Reque
uuid := request.FormValue("uuid") uuid := request.FormValue("uuid")
currentUser := this.userDao.CheckByUuid(uuid) currentUser := this.userDao.CheckByUuid(uuid)
this.matterService.Scan(currentUser) this.matterService.DeleteByPhysics(request, currentUser)
this.matterService.ScanPhysics(request, currentUser)
return this.Success("OK") return this.Success("OK")
} }

View File

@ -45,6 +45,27 @@ func TestEveryOneSecondCron(t *testing.T) {
} }
func TestSimpleCron(t *testing.T) {
i := 0
var c *cron.Cron
var spec string
//新标准。
c = cron.New()
spec = "@every 2s"
_, _ = c.AddFunc(spec, func() {
i++
log.Println("cron running:", i)
})
c.Start()
time.Sleep(70 * time.Second)
}
func TestValidateCron(t *testing.T) { func TestValidateCron(t *testing.T) {
spec := "@every 1s" spec := "@every 1s"

View File

@ -243,3 +243,22 @@ func UniformPath(p string) string {
p = strings.TrimSuffix(p, "/") p = strings.TrimSuffix(p, "/")
return p return p
} }
// readDirNames reads the directory named by dirname and returns
// see filepath.readDirNames
func ReadDirNames(dirname string) ([]string, error) {
f, err := os.Open(dirname)
if err != nil {
return nil, err
}
names, err := f.Readdirnames(-1)
if err != nil {
return nil, err
}
err = f.Close()
if err != nil {
return nil, err
}
return names, nil
}