mirror of
https://github.com/rclone/rclone.git
synced 2024-11-22 00:13:49 +01:00
serve nfs: factor caching to its own file
This commit is contained in:
parent
ce7dfa075c
commit
55b9b3e33a
32
cmd/serve/nfs/cache.go
Normal file
32
cmd/serve/nfs/cache.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//go:build unix
|
||||||
|
|
||||||
|
package nfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
billy "github.com/go-git/go-billy/v5"
|
||||||
|
nfshelper "github.com/willscott/go-nfs/helpers"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Cache controls the file handle cache implementation
|
||||||
|
type Cache interface {
|
||||||
|
// ToHandle takes a file and represents it with an opaque handle to reference it.
|
||||||
|
// In stateless nfs (when it's serving a unix fs) this can be the device + inode
|
||||||
|
// but we can generalize with a stateful local cache of handed out IDs.
|
||||||
|
ToHandle(f billy.Filesystem, path []string) []byte
|
||||||
|
|
||||||
|
// FromHandle converts from an opaque handle to the file it represents
|
||||||
|
FromHandle(fh []byte) (billy.Filesystem, []string, error)
|
||||||
|
|
||||||
|
// Invalidate the handle passed - used on rename and delete
|
||||||
|
InvalidateHandle(fs billy.Filesystem, handle []byte) error
|
||||||
|
|
||||||
|
// HandleLimit exports how many file handles can be safely stored by this cache.
|
||||||
|
HandleLimit() int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the cache of the handler to the type required by the user
|
||||||
|
func (h *Handler) setCache() (err error) {
|
||||||
|
// The default caching handler
|
||||||
|
h.Cache = nfshelper.NewCachingHandler(h, h.opt.HandleLimit)
|
||||||
|
return nil
|
||||||
|
}
|
@ -10,29 +10,35 @@ import (
|
|||||||
|
|
||||||
"github.com/go-git/go-billy/v5"
|
"github.com/go-git/go-billy/v5"
|
||||||
"github.com/rclone/rclone/fs"
|
"github.com/rclone/rclone/fs"
|
||||||
|
"github.com/rclone/rclone/fs/log"
|
||||||
"github.com/rclone/rclone/vfs"
|
"github.com/rclone/rclone/vfs"
|
||||||
"github.com/willscott/go-nfs"
|
"github.com/willscott/go-nfs"
|
||||||
nfshelper "github.com/willscott/go-nfs/helpers"
|
nfshelper "github.com/willscott/go-nfs/helpers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewHandler creates a handler for the provided filesystem
|
|
||||||
func NewHandler(vfs *vfs.VFS, opt *Options) nfs.Handler {
|
|
||||||
handler := &Handler{
|
|
||||||
vfs: vfs,
|
|
||||||
opt: opt,
|
|
||||||
billyFS: &FS{vfs: vfs},
|
|
||||||
}
|
|
||||||
handler.opt.HandleLimit = handler.opt.Limit()
|
|
||||||
handler.cache = cacheHelper(handler, handler.HandleLimit())
|
|
||||||
return handler
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handler returns a NFS backing that exposes a given file system in response to all mount requests.
|
// Handler returns a NFS backing that exposes a given file system in response to all mount requests.
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
vfs *vfs.VFS
|
vfs *vfs.VFS
|
||||||
opt *Options
|
opt *Options
|
||||||
billyFS *FS
|
billyFS *FS
|
||||||
cache nfs.Handler
|
Cache
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHandler creates a handler for the provided filesystem
|
||||||
|
func NewHandler(vfs *vfs.VFS, opt *Options) (nfs.Handler, error) {
|
||||||
|
handler := &Handler{
|
||||||
|
vfs: vfs,
|
||||||
|
opt: opt,
|
||||||
|
billyFS: &FS{vfs: vfs},
|
||||||
|
}
|
||||||
|
handler.opt.HandleLimit = handler.opt.Limit()
|
||||||
|
err := handler.setCache()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to make cache: %w", err)
|
||||||
|
}
|
||||||
|
handler.Cache = nfshelper.NewCachingHandler(handler, handler.opt.HandleLimit)
|
||||||
|
nfs.SetLogger(&logIntercepter{Level: nfs.DebugLevel})
|
||||||
|
return handler, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mount backs Mount RPC Requests, allowing for access control policies.
|
// Mount backs Mount RPC Requests, allowing for access control policies.
|
||||||
@ -58,35 +64,29 @@ func (h *Handler) FSStat(ctx context.Context, f billy.Filesystem, s *nfs.FSStat)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToHandle handled by CachingHandler
|
// ToHandle takes a file and represents it with an opaque handle to reference it.
|
||||||
func (h *Handler) ToHandle(f billy.Filesystem, s []string) []byte {
|
// In stateless nfs (when it's serving a unix fs) this can be the device + inode
|
||||||
return h.cache.ToHandle(f, s)
|
// but we can generalize with a stateful local cache of handed out IDs.
|
||||||
|
func (h *Handler) ToHandle(f billy.Filesystem, s []string) (b []byte) {
|
||||||
|
defer log.Trace("nfs", "path=%q", s)("handle=%X", &b)
|
||||||
|
return h.Cache.ToHandle(f, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromHandle handled by CachingHandler
|
// FromHandle converts from an opaque handle to the file it represents
|
||||||
func (h *Handler) FromHandle(b []byte) (billy.Filesystem, []string, error) {
|
func (h *Handler) FromHandle(b []byte) (f billy.Filesystem, s []string, err error) {
|
||||||
return h.cache.FromHandle(b)
|
defer log.Trace("nfs", "handle=%X", b)("path=%q, err=%v", &s, &err)
|
||||||
|
return h.Cache.FromHandle(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleLimit handled by cachingHandler
|
// HandleLimit exports how many file handles can be safely stored by this cache.
|
||||||
func (h *Handler) HandleLimit() int {
|
func (h *Handler) HandleLimit() int {
|
||||||
return h.opt.HandleLimit
|
return h.Cache.HandleLimit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// InvalidateHandle is called on removes or renames
|
// Invalidate the handle passed - used on rename and delete
|
||||||
func (h *Handler) InvalidateHandle(billy.Filesystem, []byte) error {
|
func (h *Handler) InvalidateHandle(f billy.Filesystem, b []byte) (err error) {
|
||||||
return nil
|
defer log.Trace("nfs", "handle=%X", b)("err=%v", &err)
|
||||||
}
|
return h.Cache.InvalidateHandle(f, b)
|
||||||
|
|
||||||
func newHandler(vfs *vfs.VFS, opt *Options) nfs.Handler {
|
|
||||||
handler := NewHandler(vfs, opt)
|
|
||||||
nfs.SetLogger(&logIntercepter{Level: nfs.DebugLevel})
|
|
||||||
return handler
|
|
||||||
}
|
|
||||||
|
|
||||||
func cacheHelper(handler nfs.Handler, limit int) nfs.Handler {
|
|
||||||
cacheHelper := nfshelper.NewCachingHandler(handler, limit)
|
|
||||||
return cacheHelper
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limit overrides the --nfs-cache-handle-limit value if out-of-range
|
// Limit overrides the --nfs-cache-handle-limit value if out-of-range
|
||||||
|
@ -37,7 +37,10 @@ func NewServer(ctx context.Context, vfs *vfs.VFS, opt *Options) (s *Server, err
|
|||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
opt: *opt,
|
opt: *opt,
|
||||||
}
|
}
|
||||||
s.handler = newHandler(vfs, opt)
|
s.handler, err = NewHandler(vfs, opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to make NFS handler: %w", err)
|
||||||
|
}
|
||||||
s.listener, err = net.Listen("tcp", s.opt.ListenAddr)
|
s.listener, err = net.Listen("tcp", s.opt.ListenAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to open listening socket: %w", err)
|
return nil, fmt.Errorf("failed to open listening socket: %w", err)
|
||||||
|
Loading…
Reference in New Issue
Block a user