no cache archive reader
This commit is contained in:
parent
bcda69daad
commit
5591f145a9
16 changed files with 579 additions and 272 deletions
src/export/nfs
|
@ -4,8 +4,8 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
"slices"
|
||||
"time"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"git.kmsign.ru/royalcat/tstor/pkg/go-nfs"
|
||||
"git.kmsign.ru/royalcat/tstor/src/config"
|
||||
|
@ -14,29 +14,51 @@ import (
|
|||
"github.com/royalcat/kv"
|
||||
)
|
||||
|
||||
const lifetime = time.Hour * 24
|
||||
type handle []string
|
||||
|
||||
const sep = "\",\""
|
||||
|
||||
func (p handle) String() string {
|
||||
return strings.Join(p, sep)
|
||||
}
|
||||
|
||||
// MarshalBinary implements kv.Binary.
|
||||
func (p handle) MarshalBinary() (data []byte, err error) {
|
||||
return []byte(strings.Join(p, sep)), nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements kv.Binary.
|
||||
func (p *handle) UnmarshalBinary(data []byte) error {
|
||||
path := strings.Split(string(data), sep)
|
||||
*p = path
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ kv.Binary = (*handle)(nil)
|
||||
|
||||
func bytesToPath(path []string) string {
|
||||
return strings.Join(path, sep)
|
||||
}
|
||||
|
||||
// NewKvHandler provides a basic to/from-file handle cache that can be tuned with a smaller cache of active directory listings.
|
||||
func NewKvHandler(h nfs.Handler, fs nfs.Filesystem) (nfs.Handler, error) {
|
||||
activeHandles, err := kv.NewBadgerKVMarhsler[uuid.UUID, []string](path.Join(config.Config.Mounts.NFS.CachePath, "handlers"))
|
||||
activeHandles, err := kv.NewBadgerKVMarhsler[uuid.UUID, handle](path.Join(config.Config.Mounts.NFS.CachePath, "handlers"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if s, ok := activeHandles.(kv.BadgerStore); ok {
|
||||
// db := s.BadgerDB()
|
||||
// enable with managed database
|
||||
// go func() {
|
||||
// for n := range time.NewTimer(lifetime / 2).C {
|
||||
// db.SetDiscardTs(uint64(n.Add(-lifetime).Unix()))
|
||||
// }
|
||||
// }()
|
||||
// }
|
||||
reverseCache := map[string]uuid.UUID{}
|
||||
|
||||
activeHandles.Range(context.Background(), func(k uuid.UUID, v handle) bool {
|
||||
reverseCache[v.String()] = k
|
||||
return true
|
||||
})
|
||||
|
||||
return &CachingHandler{
|
||||
Handler: h,
|
||||
fs: fs,
|
||||
activeHandles: activeHandles,
|
||||
reverseCache: reverseCache,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -44,32 +66,36 @@ func NewKvHandler(h nfs.Handler, fs nfs.Filesystem) (nfs.Handler, error) {
|
|||
type CachingHandler struct {
|
||||
nfs.Handler
|
||||
|
||||
fs nfs.Filesystem
|
||||
activeHandles kv.Store[uuid.UUID, []string]
|
||||
mu sync.RWMutex
|
||||
|
||||
fs nfs.Filesystem
|
||||
|
||||
activeHandles kv.Store[uuid.UUID, handle]
|
||||
reverseCache map[string]uuid.UUID
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (c *CachingHandler) ToHandle(_ nfs.Filesystem, path []string) []byte {
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
var id uuid.UUID
|
||||
c.activeHandles.Range(ctx, func(k uuid.UUID, v []string) bool {
|
||||
if slices.Equal(path, v) {
|
||||
id = k
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
cacheKey := handle(path).String()
|
||||
|
||||
if cacheId, ok := c.reverseCache[cacheKey]; ok {
|
||||
id = cacheId
|
||||
}
|
||||
|
||||
if id != uuid.Nil {
|
||||
return id[:]
|
||||
}
|
||||
|
||||
id = uuid.New()
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
id = uuid.New()
|
||||
c.reverseCache[cacheKey] = id
|
||||
c.activeHandles.Set(ctx, id, path)
|
||||
|
||||
return id[:]
|
||||
|
@ -77,11 +103,14 @@ func (c *CachingHandler) ToHandle(_ nfs.Filesystem, path []string) []byte {
|
|||
|
||||
// FromHandle converts from an opaque handle to the file it represents
|
||||
func (c *CachingHandler) FromHandle(fh []byte) (nfs.Filesystem, []string, error) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
id, err := uuid.FromBytes(fh)
|
||||
if err != nil {
|
||||
return nil, []string{}, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
paths, found, err := c.activeHandles.Get(ctx, id)
|
||||
|
@ -93,7 +122,7 @@ func (c *CachingHandler) FromHandle(fh []byte) (nfs.Filesystem, []string, error)
|
|||
return c.fs, paths, nil
|
||||
}
|
||||
|
||||
return nil, []string{}, &nfs.NFSStatusError{NFSStatus: nfs.NFSStatusStale}
|
||||
return nil, nil, &nfs.NFSStatusError{NFSStatus: nfs.NFSStatusStale}
|
||||
}
|
||||
|
||||
func (c *CachingHandler) InvalidateHandle(fs nfs.Filesystem, handle []byte) error {
|
||||
|
@ -103,8 +132,7 @@ func (c *CachingHandler) InvalidateHandle(fs nfs.Filesystem, handle []byte) erro
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.activeHandles.Delete(ctx, id)
|
||||
return nil
|
||||
return c.activeHandles.Delete(ctx, id)
|
||||
}
|
||||
|
||||
const maxInt = int(^uint(0) >> 1)
|
||||
|
@ -114,14 +142,14 @@ func (c *CachingHandler) HandleLimit() int {
|
|||
return maxInt
|
||||
}
|
||||
|
||||
func hasPrefix(path, prefix []string) bool {
|
||||
if len(prefix) > len(path) {
|
||||
return false
|
||||
}
|
||||
for i, e := range prefix {
|
||||
if path[i] != e {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
// func hasPrefix(path, prefix []string) bool {
|
||||
// if len(prefix) > len(path) {
|
||||
// return false
|
||||
// }
|
||||
// for i, e := range prefix {
|
||||
// if path[i] != e {
|
||||
// return false
|
||||
// }
|
||||
// }
|
||||
// return true
|
||||
// }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue