mirror of https://github.com/cloudreve/Cloudreve
Feat: use sync.pool to obtain new FileSystem instance
parent
de4793aacb
commit
5b9de0e097
|
@ -11,8 +11,16 @@ import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FSPool 文件系统资源池
|
||||||
|
var FSPool = sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return &FileSystem{}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// FileHeader 上传来的文件数据处理器
|
// FileHeader 上传来的文件数据处理器
|
||||||
type FileHeader interface {
|
type FileHeader interface {
|
||||||
io.Reader
|
io.Reader
|
||||||
|
@ -77,12 +85,35 @@ type FileSystem struct {
|
||||||
Handler Handler
|
Handler Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getEmptyFS 从pool中获取新的FileSystem
|
||||||
|
func getEmptyFS() *FileSystem {
|
||||||
|
fs := FSPool.Get().(*FileSystem)
|
||||||
|
return fs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recycle 回收FileSystem资源
|
||||||
|
func (fs *FileSystem) Recycle() {
|
||||||
|
fs.reset()
|
||||||
|
FSPool.Put(fs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset 重设文件系统,以便回收使用
|
||||||
|
func (fs *FileSystem) reset() {
|
||||||
|
fs.User = nil
|
||||||
|
fs.CleanTargets()
|
||||||
|
fs.Policy = nil
|
||||||
|
fs.BeforeUpload = fs.BeforeUpload[:0]
|
||||||
|
fs.AfterUpload = fs.AfterUpload[:0]
|
||||||
|
fs.AfterValidateFailed = fs.AfterValidateFailed[:0]
|
||||||
|
fs.AfterUploadCanceled = fs.AfterUploadCanceled[:0]
|
||||||
|
fs.BeforeFileDownload = fs.BeforeFileDownload[:0]
|
||||||
|
fs.Handler = nil
|
||||||
|
}
|
||||||
|
|
||||||
// NewFileSystem 初始化一个文件系统
|
// NewFileSystem 初始化一个文件系统
|
||||||
func NewFileSystem(user *model.User) (*FileSystem, error) {
|
func NewFileSystem(user *model.User) (*FileSystem, error) {
|
||||||
fs := &FileSystem{
|
fs := getEmptyFS()
|
||||||
User: user,
|
fs.User = user
|
||||||
}
|
|
||||||
|
|
||||||
// 分配存储策略适配器
|
// 分配存储策略适配器
|
||||||
err := fs.dispatchHandler()
|
err := fs.dispatchHandler()
|
||||||
|
|
||||||
|
@ -92,9 +123,8 @@ func NewFileSystem(user *model.User) (*FileSystem, error) {
|
||||||
|
|
||||||
// NewAnonymousFileSystem 初始化匿名文件系统
|
// NewAnonymousFileSystem 初始化匿名文件系统
|
||||||
func NewAnonymousFileSystem() (*FileSystem, error) {
|
func NewAnonymousFileSystem() (*FileSystem, error) {
|
||||||
fs := &FileSystem{
|
fs := getEmptyFS()
|
||||||
User: &model.User{},
|
fs.User = &model.User{}
|
||||||
}
|
|
||||||
|
|
||||||
// 如果是主机模式下,则为匿名文件系统分配游客用户组
|
// 如果是主机模式下,则为匿名文件系统分配游客用户组
|
||||||
if conf.SystemConfig.Mode == "master" {
|
if conf.SystemConfig.Mode == "master" {
|
||||||
|
@ -182,6 +212,6 @@ func (fs *FileSystem) SetTargetFileByIDs(ids []uint) error {
|
||||||
|
|
||||||
// CleanTargets 清空目标
|
// CleanTargets 清空目标
|
||||||
func (fs *FileSystem) CleanTargets() {
|
func (fs *FileSystem) CleanTargets() {
|
||||||
fs.FileTarget = []model.File{}
|
fs.FileTarget = fs.FileTarget[:0]
|
||||||
fs.DirTarget = []model.Folder{}
|
fs.DirTarget = fs.DirTarget[:0]
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,3 +133,18 @@ func TestNewAnonymousFileSystem(t *testing.T) {
|
||||||
asserts.Nil(fs)
|
asserts.Nil(fs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFileSystem_Recycle(t *testing.T) {
|
||||||
|
fs := &FileSystem{
|
||||||
|
User: &model.User{},
|
||||||
|
Policy: &model.Policy{},
|
||||||
|
FileTarget: []model.File{model.File{}},
|
||||||
|
DirTarget: []model.Folder{model.Folder{}},
|
||||||
|
AfterUpload: []Hook{GenericAfterUpdate},
|
||||||
|
}
|
||||||
|
fs.Recycle()
|
||||||
|
newFS := getEmptyFS()
|
||||||
|
if fs != newFS {
|
||||||
|
t.Error("指针不一致")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ func (handler Handler) Delete(ctx context.Context, files []string) ([]string, er
|
||||||
|
|
||||||
// Thumb 获取文件缩略图
|
// Thumb 获取文件缩略图
|
||||||
func (handler Handler) Thumb(ctx context.Context, path string) (*response.ContentResponse, error) {
|
func (handler Handler) Thumb(ctx context.Context, path string) (*response.ContentResponse, error) {
|
||||||
return nil, nil
|
return nil, errors.New("未实现")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Source 获取外链URL
|
// Source 获取外链URL
|
||||||
|
|
|
@ -75,6 +75,7 @@ func GetSource(c *gin.Context) {
|
||||||
c.JSON(200, serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err))
|
c.JSON(200, serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
|
|
||||||
// 获取文件ID
|
// 获取文件ID
|
||||||
fileID, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
fileID, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||||
|
@ -109,6 +110,7 @@ func Thumb(c *gin.Context) {
|
||||||
c.JSON(200, serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err))
|
c.JSON(200, serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
|
|
||||||
// 获取文件ID
|
// 获取文件ID
|
||||||
fileID, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
fileID, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||||
|
@ -261,6 +263,7 @@ func FileUploadStream(c *gin.Context) {
|
||||||
c.JSON(200, serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err))
|
c.JSON(200, serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
|
|
||||||
// 给文件系统分配钩子
|
// 给文件系统分配钩子
|
||||||
fs.Use("BeforeUpload", filesystem.HookValidateFile)
|
fs.Use("BeforeUpload", filesystem.HookValidateFile)
|
||||||
|
|
|
@ -24,6 +24,7 @@ func SlaveUpload(c *gin.Context) {
|
||||||
c.JSON(200, serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err))
|
c.JSON(200, serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
fs.Handler = local.Handler{}
|
fs.Handler = local.Handler{}
|
||||||
|
|
||||||
// 从请求中取得上传策略
|
// 从请求中取得上传策略
|
||||||
|
|
|
@ -19,6 +19,7 @@ func (service *DirectoryService) ListDirectory(c *gin.Context) serializer.Respon
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
|
|
||||||
// 上下文
|
// 上下文
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
@ -43,9 +44,12 @@ func (service *DirectoryService) CreateDirectory(c *gin.Context) serializer.Resp
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
|
|
||||||
// 上下文
|
// 上下文
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// 创建目录
|
// 创建目录
|
||||||
err = fs.CreateDirectory(ctx, service.Path)
|
err = fs.CreateDirectory(ctx, service.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -39,6 +39,7 @@ func (service *DownloadService) DownloadArchived(ctx context.Context, c *gin.Con
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
|
|
||||||
// 查找打包的临时文件
|
// 查找打包的临时文件
|
||||||
zipPath, exist := cache.Get("archive_" + service.ID)
|
zipPath, exist := cache.Get("archive_" + service.ID)
|
||||||
|
@ -74,6 +75,7 @@ func (service *FileAnonymousGetService) Download(ctx context.Context, c *gin.Con
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serializer.Err(serializer.CodeGroupNotAllowed, err.Error(), err)
|
return serializer.Err(serializer.CodeGroupNotAllowed, err.Error(), err)
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
|
|
||||||
// 查找文件
|
// 查找文件
|
||||||
err = fs.SetTargetFileByIDs([]uint{service.ID})
|
err = fs.SetTargetFileByIDs([]uint{service.ID})
|
||||||
|
@ -103,6 +105,7 @@ func (service *SingleFileService) CreateDocPreviewSession(ctx context.Context, c
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
|
|
||||||
// 获取文件临时下载地址
|
// 获取文件临时下载地址
|
||||||
downloadURL, err := fs.GetDownloadURL(ctx, service.Path, "doc_preview_timeout")
|
downloadURL, err := fs.GetDownloadURL(ctx, service.Path, "doc_preview_timeout")
|
||||||
|
@ -130,6 +133,7 @@ func (service *SingleFileService) CreateDownloadSession(ctx context.Context, c *
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
|
|
||||||
// 获取下载地址
|
// 获取下载地址
|
||||||
downloadURL, err := fs.GetDownloadURL(ctx, service.Path, "download_timeout")
|
downloadURL, err := fs.GetDownloadURL(ctx, service.Path, "download_timeout")
|
||||||
|
@ -150,6 +154,7 @@ func (service *DownloadService) Download(ctx context.Context, c *gin.Context) se
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
|
|
||||||
// 查找打包的临时文件
|
// 查找打包的临时文件
|
||||||
file, exist := cache.Get("download_" + service.ID)
|
file, exist := cache.Get("download_" + service.ID)
|
||||||
|
@ -189,6 +194,7 @@ func (service *SingleFileService) PreviewContent(ctx context.Context, c *gin.Con
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
|
|
||||||
// 获取文件流
|
// 获取文件流
|
||||||
rs, err := fs.GetDownloadContent(ctx, service.Path)
|
rs, err := fs.GetDownloadContent(ctx, service.Path)
|
||||||
|
@ -230,6 +236,7 @@ func (service *SingleFileService) PutContent(ctx context.Context, c *gin.Context
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
|
|
||||||
// 取得现有文件
|
// 取得现有文件
|
||||||
exist, originFile := fs.IsFileExist(service.Path)
|
exist, originFile := fs.IsFileExist(service.Path)
|
||||||
|
|
|
@ -42,6 +42,7 @@ func (service *ItemService) Archive(ctx context.Context, c *gin.Context) seriali
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
|
|
||||||
// 检查用户组权限
|
// 检查用户组权限
|
||||||
if !fs.User.Group.OptionsSerialized.ArchiveDownloadEnabled {
|
if !fs.User.Group.OptionsSerialized.ArchiveDownloadEnabled {
|
||||||
|
@ -91,6 +92,7 @@ func (service *ItemService) Delete(ctx context.Context, c *gin.Context) serializ
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
|
|
||||||
// 删除对象
|
// 删除对象
|
||||||
err = fs.Delete(ctx, service.Dirs, service.Items)
|
err = fs.Delete(ctx, service.Dirs, service.Items)
|
||||||
|
@ -111,6 +113,7 @@ func (service *ItemMoveService) Move(ctx context.Context, c *gin.Context) serial
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
|
|
||||||
// 移动对象
|
// 移动对象
|
||||||
err = fs.Move(ctx, service.Src.Dirs, service.Src.Items, service.SrcDir, service.Dst)
|
err = fs.Move(ctx, service.Src.Dirs, service.Src.Items, service.SrcDir, service.Dst)
|
||||||
|
@ -136,6 +139,7 @@ func (service *ItemMoveService) Copy(ctx context.Context, c *gin.Context) serial
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
|
|
||||||
// 复制对象
|
// 复制对象
|
||||||
err = fs.Copy(ctx, service.Src.Dirs, service.Src.Items, service.SrcDir, service.Dst)
|
err = fs.Copy(ctx, service.Src.Dirs, service.Src.Items, service.SrcDir, service.Dst)
|
||||||
|
@ -161,6 +165,7 @@ func (service *ItemRenameService) Rename(ctx context.Context, c *gin.Context) se
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
return serializer.Err(serializer.CodePolicyNotAllowed, err.Error(), err)
|
||||||
}
|
}
|
||||||
|
defer fs.Recycle()
|
||||||
|
|
||||||
// 重命名对象
|
// 重命名对象
|
||||||
err = fs.Rename(ctx, service.Src.Dirs, service.Src.Items, service.NewName)
|
err = fs.Rename(ctx, service.Src.Dirs, service.Src.Items, service.NewName)
|
||||||
|
|
Loading…
Reference in New Issue