use cachingfs
This commit is contained in:
parent
892908fcf5
commit
61b665af13
10 changed files with 1963 additions and 2 deletions
125
vendor/github.com/hanwen/go-fuse/unionfs/dircache.go
generated
vendored
Normal file
125
vendor/github.com/hanwen/go-fuse/unionfs/dircache.go
generated
vendored
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
// 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 (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
"github.com/hanwen/go-fuse/fuse/pathfs"
|
||||
)
|
||||
|
||||
// newDirnameMap reads the contents of the given directory. On error,
|
||||
// returns a nil map. This forces reloads in the dirCache until we
|
||||
// succeed.
|
||||
func newDirnameMap(fs pathfs.FileSystem, dir string) map[string]bool {
|
||||
stream, code := fs.OpenDir(dir, nil)
|
||||
if code == fuse.ENOENT {
|
||||
// The directory not existing is not an error.
|
||||
return map[string]bool{}
|
||||
}
|
||||
|
||||
if !code.Ok() {
|
||||
return nil
|
||||
}
|
||||
|
||||
result := make(map[string]bool)
|
||||
for _, e := range stream {
|
||||
if e.Mode&fuse.S_IFREG != 0 {
|
||||
result[e.Name] = true
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// dirCache caches names in a directory for some time.
|
||||
//
|
||||
// If called when the cache is expired, the filenames are read afresh in
|
||||
// the background.
|
||||
type dirCache struct {
|
||||
dir string
|
||||
ttl time.Duration
|
||||
fs pathfs.FileSystem
|
||||
// Protects data below.
|
||||
lock sync.RWMutex
|
||||
|
||||
// If nil, you may call refresh() to schedule a new one.
|
||||
names map[string]bool
|
||||
updateRunning bool
|
||||
}
|
||||
|
||||
func (c *dirCache) setMap(newMap map[string]bool) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
c.names = newMap
|
||||
c.updateRunning = false
|
||||
_ = time.AfterFunc(c.ttl,
|
||||
func() { c.DropCache() })
|
||||
}
|
||||
|
||||
func (c *dirCache) DropCache() {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
c.names = nil
|
||||
}
|
||||
|
||||
// Try to refresh: if another update is already running, do nothing,
|
||||
// otherwise, read the directory and set it.
|
||||
func (c *dirCache) maybeRefresh() {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
if c.updateRunning {
|
||||
return
|
||||
}
|
||||
c.updateRunning = true
|
||||
go func() {
|
||||
newmap := newDirnameMap(c.fs, c.dir)
|
||||
c.setMap(newmap)
|
||||
}()
|
||||
}
|
||||
|
||||
func (c *dirCache) RemoveEntry(name string) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
if c.names == nil {
|
||||
go c.maybeRefresh()
|
||||
return
|
||||
}
|
||||
|
||||
delete(c.names, name)
|
||||
}
|
||||
|
||||
func (c *dirCache) AddEntry(name string) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
if c.names == nil {
|
||||
go c.maybeRefresh()
|
||||
return
|
||||
}
|
||||
|
||||
c.names[name] = true
|
||||
}
|
||||
|
||||
func newDirCache(fs pathfs.FileSystem, dir string, ttl time.Duration) *dirCache {
|
||||
dc := new(dirCache)
|
||||
dc.dir = dir
|
||||
dc.fs = fs
|
||||
dc.ttl = ttl
|
||||
return dc
|
||||
}
|
||||
|
||||
func (c *dirCache) HasEntry(name string) (mapPresent bool, found bool) {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
|
||||
if c.names == nil {
|
||||
go c.maybeRefresh()
|
||||
return false, false
|
||||
}
|
||||
|
||||
return true, c.names[name]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue