use cachingfs
This commit is contained in:
parent
892908fcf5
commit
61b665af13
10 changed files with 1963 additions and 2 deletions
151
vendor/github.com/hanwen/go-fuse/unionfs/cachingfs.go
generated
vendored
Normal file
151
vendor/github.com/hanwen/go-fuse/unionfs/cachingfs.go
generated
vendored
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package unionfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
"github.com/hanwen/go-fuse/fuse/nodefs"
|
||||
"github.com/hanwen/go-fuse/fuse/pathfs"
|
||||
)
|
||||
|
||||
const _XATTRSEP = "@XATTR@"
|
||||
|
||||
type attrResponse struct {
|
||||
*fuse.Attr
|
||||
fuse.Status
|
||||
}
|
||||
|
||||
type xattrResponse struct {
|
||||
data []byte
|
||||
fuse.Status
|
||||
}
|
||||
|
||||
type dirResponse struct {
|
||||
entries []fuse.DirEntry
|
||||
fuse.Status
|
||||
}
|
||||
|
||||
type linkResponse struct {
|
||||
linkContent string
|
||||
fuse.Status
|
||||
}
|
||||
|
||||
// Caches filesystem metadata.
|
||||
type cachingFileSystem struct {
|
||||
pathfs.FileSystem
|
||||
|
||||
attributes *TimedCache
|
||||
dirs *TimedCache
|
||||
links *TimedCache
|
||||
xattr *TimedCache
|
||||
}
|
||||
|
||||
func readDir(fs pathfs.FileSystem, name string) *dirResponse {
|
||||
origStream, code := fs.OpenDir(name, nil)
|
||||
|
||||
r := &dirResponse{nil, code}
|
||||
if !code.Ok() {
|
||||
return r
|
||||
}
|
||||
r.entries = origStream
|
||||
return r
|
||||
}
|
||||
|
||||
func getAttr(fs pathfs.FileSystem, name string) *attrResponse {
|
||||
a, code := fs.GetAttr(name, nil)
|
||||
return &attrResponse{
|
||||
Attr: a,
|
||||
Status: code,
|
||||
}
|
||||
}
|
||||
|
||||
func getXAttr(fs pathfs.FileSystem, nameAttr string) *xattrResponse {
|
||||
ns := strings.SplitN(nameAttr, _XATTRSEP, 2)
|
||||
a, code := fs.GetXAttr(ns[0], ns[1], nil)
|
||||
return &xattrResponse{
|
||||
data: a,
|
||||
Status: code,
|
||||
}
|
||||
}
|
||||
|
||||
func readLink(fs pathfs.FileSystem, name string) *linkResponse {
|
||||
a, code := fs.Readlink(name, nil)
|
||||
return &linkResponse{
|
||||
linkContent: a,
|
||||
Status: code,
|
||||
}
|
||||
}
|
||||
|
||||
func NewCachingFileSystem(fs pathfs.FileSystem, ttl time.Duration) pathfs.FileSystem {
|
||||
c := new(cachingFileSystem)
|
||||
c.FileSystem = fs
|
||||
c.attributes = NewTimedCache(func(n string) (interface{}, bool) {
|
||||
a := getAttr(fs, n)
|
||||
return a, a.Ok()
|
||||
}, ttl)
|
||||
c.dirs = NewTimedCache(func(n string) (interface{}, bool) {
|
||||
d := readDir(fs, n)
|
||||
return d, d.Ok()
|
||||
}, ttl)
|
||||
c.links = NewTimedCache(func(n string) (interface{}, bool) {
|
||||
l := readLink(fs, n)
|
||||
return l, l.Ok()
|
||||
}, ttl)
|
||||
c.xattr = NewTimedCache(func(n string) (interface{}, bool) {
|
||||
l := getXAttr(fs, n)
|
||||
return l, l.Ok()
|
||||
}, ttl)
|
||||
return c
|
||||
}
|
||||
|
||||
func (fs *cachingFileSystem) DropCache() {
|
||||
for _, c := range []*TimedCache{fs.attributes, fs.dirs, fs.links, fs.xattr} {
|
||||
c.DropAll(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *cachingFileSystem) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
|
||||
if name == _DROP_CACHE {
|
||||
return &fuse.Attr{
|
||||
Mode: fuse.S_IFREG | 0777,
|
||||
}, fuse.OK
|
||||
}
|
||||
|
||||
r := fs.attributes.Get(name).(*attrResponse)
|
||||
return r.Attr, r.Status
|
||||
}
|
||||
|
||||
func (fs *cachingFileSystem) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
|
||||
key := name + _XATTRSEP + attr
|
||||
r := fs.xattr.Get(key).(*xattrResponse)
|
||||
return r.data, r.Status
|
||||
}
|
||||
|
||||
func (fs *cachingFileSystem) Readlink(name string, context *fuse.Context) (string, fuse.Status) {
|
||||
r := fs.links.Get(name).(*linkResponse)
|
||||
return r.linkContent, r.Status
|
||||
}
|
||||
|
||||
func (fs *cachingFileSystem) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) {
|
||||
r := fs.dirs.Get(name).(*dirResponse)
|
||||
return r.entries, r.Status
|
||||
}
|
||||
|
||||
func (fs *cachingFileSystem) String() string {
|
||||
return fmt.Sprintf("cachingFileSystem(%v)", fs.FileSystem)
|
||||
}
|
||||
|
||||
func (fs *cachingFileSystem) Open(name string, flags uint32, context *fuse.Context) (f nodefs.File, status fuse.Status) {
|
||||
if flags&fuse.O_ANYWRITE != 0 && name == _DROP_CACHE {
|
||||
log.Println("Dropping cache for", fs)
|
||||
fs.DropCache()
|
||||
}
|
||||
return fs.FileSystem.Open(name, flags, context)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue