mirror of
https://github.com/kopia/kopia.git
synced 2026-01-25 06:48:48 -05:00
* cachefs: make cache read O(1) instead of O(n) Move the wrapping of fs.Entry before caching rather than doing it everytime we try to read from the cache.
83 lines
1.6 KiB
Go
83 lines
1.6 KiB
Go
// Package cachefs implements a wrapper that caches filesystem actions.
|
|
package cachefs
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/kopia/kopia/fs"
|
|
)
|
|
|
|
// DirectoryCacher reads and potentially caches directory entries for a given directory.
|
|
type DirectoryCacher interface {
|
|
Readdir(ctx context.Context, d fs.Directory, w EntryWrapper) (fs.Entries, error)
|
|
}
|
|
|
|
type cacheContext struct {
|
|
cacher DirectoryCacher
|
|
}
|
|
|
|
type directory struct {
|
|
ctx *cacheContext
|
|
fs.Directory
|
|
}
|
|
|
|
func (d *directory) Child(ctx context.Context, name string) (fs.Entry, error) {
|
|
e, err := d.Directory.Child(ctx, name)
|
|
if err != nil {
|
|
// nolint:wrapcheck
|
|
return nil, err
|
|
}
|
|
|
|
return wrapWithContext(e, d.ctx), nil
|
|
}
|
|
|
|
func (d *directory) Readdir(ctx context.Context) (fs.Entries, error) {
|
|
entries, err := d.ctx.cacher.Readdir(ctx, d.Directory, func(e fs.Entry) fs.Entry {
|
|
return wrapWithContext(e, d.ctx)
|
|
})
|
|
if err != nil {
|
|
// nolint:wrapcheck
|
|
return entries, err
|
|
}
|
|
|
|
// nolint:wrapcheck
|
|
return entries, err
|
|
}
|
|
|
|
type file struct {
|
|
ctx *cacheContext
|
|
fs.File
|
|
}
|
|
|
|
type symlink struct {
|
|
ctx *cacheContext
|
|
fs.Symlink
|
|
}
|
|
|
|
// Wrap returns an Entry that wraps another Entry and caches directory reads.
|
|
func Wrap(e fs.Entry, cacher DirectoryCacher) fs.Entry {
|
|
return wrapWithContext(e, &cacheContext{cacher})
|
|
}
|
|
|
|
func wrapWithContext(e fs.Entry, opts *cacheContext) fs.Entry {
|
|
switch e := e.(type) {
|
|
case fs.Directory:
|
|
return fs.Directory(&directory{opts, e})
|
|
|
|
case fs.File:
|
|
return fs.File(&file{opts, e})
|
|
|
|
case fs.Symlink:
|
|
return fs.Symlink(&symlink{opts, e})
|
|
|
|
default:
|
|
return e
|
|
}
|
|
}
|
|
|
|
var (
|
|
_ fs.Directory = &directory{}
|
|
_ fs.File = &file{}
|
|
_ fs.Symlink = &symlink{}
|
|
)
|