From 044cdea1d469b690987b8ebfcfb2584a5c86a1d0 Mon Sep 17 00:00:00 2001 From: hexxa Date: Fri, 4 Mar 2022 16:06:29 +0800 Subject: [PATCH] fix(files): refactor upload mgr as upload info store --- src/db/fileinfostore/file_info_store.go | 6 ++ src/db/fileinfostore/upload_info_store.go | 114 ++++++++++++++++++++++ src/handlers/fileshdr/handlers.go | 18 ++-- src/server/server_files_test.go | 3 +- src/server/testdata/test_quickshare.db | Bin 524288 -> 524288 bytes 5 files changed, 131 insertions(+), 10 deletions(-) create mode 100644 src/db/fileinfostore/upload_info_store.go diff --git a/src/db/fileinfostore/file_info_store.go b/src/db/fileinfostore/file_info_store.go index 7935e5a..6812ede 100644 --- a/src/db/fileinfostore/file_info_store.go +++ b/src/db/fileinfostore/file_info_store.go @@ -54,6 +54,12 @@ type IFileInfoStore interface { SetSha1(itemPath, sign string) error GetInfos(itemPaths []string) (map[string]*FileInfo, error) GetSharingDir(hashID string) (string, error) + // upload info + AddUploadInfo(user, filePath, tmpPath string, fileSize int64) error + SetUploadInfo(user, filePath string, newUploaded int64) error + GetUploadInfo(user, filePath string) (string, int64, int64, error) + DelUploadInfo(user, filePath string) error + ListUploadInfo(user string) ([]*UploadInfo, error) } type FileInfoStore struct { diff --git a/src/db/fileinfostore/upload_info_store.go b/src/db/fileinfostore/upload_info_store.go new file mode 100644 index 0000000..d352fab --- /dev/null +++ b/src/db/fileinfostore/upload_info_store.go @@ -0,0 +1,114 @@ +package fileinfostore + +import ( + "encoding/json" + "errors" + "fmt" +) + +var ( + ErrCreateExisting = errors.New("create upload info which already exists") + ErrGreaterThanSize = errors.New("uploaded is greater than file size") + ErrUploadNotFound = errors.New("upload info not found") + + uploadsPrefix = "uploads" +) + +type UploadInfo struct { + RealFilePath string `json:"realFilePath"` + Size int64 `json:"size"` + Uploaded int64 `json:"uploaded"` +} + +func UploadNS(user string) string { + return fmt.Sprintf("%s/%s", uploadsPrefix, user) +} + +func (fi *FileInfoStore) AddUploadInfo(user, filePath, tmpPath string, fileSize int64) error { + ns := UploadNS(user) + err := fi.store.AddNamespace(ns) + if err != nil { + return err + } + + _, ok := fi.store.GetStringIn(ns, tmpPath) + if ok { + return ErrCreateExisting + } + + info := &UploadInfo{ + RealFilePath: filePath, + Size: fileSize, + Uploaded: 0, + } + infoBytes, err := json.Marshal(info) + if err != nil { + return err + } + + return fi.store.SetStringIn(ns, tmpPath, string(infoBytes)) +} + +func (fi *FileInfoStore) SetUploadInfo(user, filePath string, newUploaded int64) error { + realFilePath, fileSize, _, err := fi.GetUploadInfo(user, filePath) + if err != nil { + return err + } else if newUploaded > fileSize { + return ErrGreaterThanSize + } + + newInfo := &UploadInfo{ + RealFilePath: realFilePath, + Size: fileSize, + Uploaded: newUploaded, + } + newInfoBytes, err := json.Marshal(newInfo) + if err != nil { + return err + } + return fi.store.SetStringIn(UploadNS(user), filePath, string(newInfoBytes)) +} + +func (fi *FileInfoStore) GetUploadInfo(user, filePath string) (string, int64, int64, error) { + ns := UploadNS(user) + infoBytes, ok := fi.store.GetStringIn(ns, filePath) + if !ok { + return "", 0, 0, ErrUploadNotFound + } + + info := &UploadInfo{} + err := json.Unmarshal([]byte(infoBytes), info) + if err != nil { + return "", 0, 0, err + } + + return info.RealFilePath, info.Size, info.Uploaded, nil +} + +func (fi *FileInfoStore) DelUploadInfo(user, filePath string) error { + return fi.store.DelInt64In(UploadNS(user), filePath) +} + +func (fi *FileInfoStore) ListUploadInfo(user string) ([]*UploadInfo, error) { + ns := UploadNS(user) + if !fi.store.HasNamespace(ns) { + return nil, nil + } + + infoMap, err := fi.store.ListStringsIn(ns) + if err != nil { + return nil, err + } + + infos := []*UploadInfo{} + for _, infoStr := range infoMap { + info := &UploadInfo{} + err = json.Unmarshal([]byte(infoStr), info) + if err != nil { + return nil, err + } + infos = append(infos, info) + } + + return infos, nil +} diff --git a/src/handlers/fileshdr/handlers.go b/src/handlers/fileshdr/handlers.go index 7296b29..b215a7d 100644 --- a/src/handlers/fileshdr/handlers.go +++ b/src/handlers/fileshdr/handlers.go @@ -434,7 +434,7 @@ func (h *FileHandlers) UploadChunk(c *gin.Context) { locker.Exec(func() { var err error - _, fileSize, uploaded, err := h.uploadMgr.GetInfo(userID, tmpFilePath) + _, fileSize, uploaded, err := h.deps.FileInfos().GetUploadInfo(userID, tmpFilePath) if err != nil { c.JSON(q.ErrResp(c, 500, err)) return @@ -455,7 +455,7 @@ func (h *FileHandlers) UploadChunk(c *gin.Context) { return } - err = h.uploadMgr.SetInfo(userID, tmpFilePath, req.Offset+int64(wrote)) + err = h.deps.FileInfos().SetUploadInfo(userID, tmpFilePath, req.Offset+int64(wrote)) if err != nil { c.JSON(q.ErrResp(c, 500, err)) return @@ -474,7 +474,7 @@ func (h *FileHandlers) UploadChunk(c *gin.Context) { c.JSON(q.ErrResp(c, 500, fmt.Errorf("%s error: %w", req.Path, err))) return } - err = h.uploadMgr.DelInfo(userID, tmpFilePath) + err = h.deps.FileInfos().DelUploadInfo(userID, tmpFilePath) if err != nil { c.JSON(q.ErrResp(c, 500, err)) return @@ -594,7 +594,7 @@ func (h *FileHandlers) UploadStatus(c *gin.Context) { tmpFilePath := q.UploadPath(userName, filePath) locker := h.NewAutoLocker(c, lockName(tmpFilePath)) locker.Exec(func() { - _, fileSize, uploaded, err := h.uploadMgr.GetInfo(userID, tmpFilePath) + _, fileSize, uploaded, err := h.deps.FileInfos().GetUploadInfo(userID, tmpFilePath) if err != nil { if os.IsNotExist(err) { c.JSON(q.ErrResp(c, 404, err)) @@ -842,19 +842,19 @@ func lockName(filePath string) string { } type ListUploadingsResp struct { - UploadInfos []*UploadInfo `json:"uploadInfos"` + UploadInfos []*fileinfostore.UploadInfo `json:"uploadInfos"` } func (h *FileHandlers) ListUploadings(c *gin.Context) { userID := c.MustGet(q.UserIDParam).(string) - infos, err := h.uploadMgr.ListInfo(userID) + infos, err := h.deps.FileInfos().ListUploadInfo(userID) if err != nil { c.JSON(q.ErrResp(c, 500, err)) return } if infos == nil { - infos = []*UploadInfo{} + infos = []*fileinfostore.UploadInfo{} } c.JSON(200, &ListUploadingsResp{UploadInfos: infos}) } @@ -884,7 +884,7 @@ func (h *FileHandlers) DelUploading(c *gin.Context) { tmpFilePath := q.UploadPath(userName, filePath) locker := h.NewAutoLocker(c, lockName(tmpFilePath)) locker.Exec(func() { - _, size, _, err := h.uploadMgr.GetInfo(userID, tmpFilePath) + _, size, _, err := h.deps.FileInfos().GetUploadInfo(userID, tmpFilePath) if err != nil { c.JSON(q.ErrResp(c, 500, err)) return @@ -906,7 +906,7 @@ func (h *FileHandlers) DelUploading(c *gin.Context) { } } - err = h.uploadMgr.DelInfo(userID, tmpFilePath) + err = h.deps.FileInfos().DelUploadInfo(userID, tmpFilePath) if err != nil { c.JSON(q.ErrResp(c, 500, err)) return diff --git a/src/server/server_files_test.go b/src/server/server_files_test.go index adbb692..fdaceeb 100644 --- a/src/server/server_files_test.go +++ b/src/server/server_files_test.go @@ -11,6 +11,7 @@ import ( "time" "github.com/ihexxa/quickshare/src/client" + "github.com/ihexxa/quickshare/src/db/fileinfostore" q "github.com/ihexxa/quickshare/src/handlers" "github.com/ihexxa/quickshare/src/handlers/fileshdr" ) @@ -630,7 +631,7 @@ func TestFileHandlers(t *testing.T) { t.Fatal(res.StatusCode) } - gotInfos := map[string]*fileshdr.UploadInfo{} + gotInfos := map[string]*fileinfostore.UploadInfo{} for _, info := range lResp.UploadInfos { gotInfos[info.RealFilePath] = info } diff --git a/src/server/testdata/test_quickshare.db b/src/server/testdata/test_quickshare.db index 85048df491659cc8dda01b95ab8d3d12f8d847b5..b512ca2612902f52271dd2b59072a3441a3ecb8f 100644 GIT binary patch delta 81 zcmZo@P-tjSnBX8Vfq{_$1lBIU6jz*>v|+np0OJP!NdgW66QMF!6`!SYwyH}&WSSJ( a6d2nSnA#MW+Z0&Z6j<97*p?}