mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-10 07:11:08 +00:00
lib/fs: Set expiry after DirNames in case-fs (#7794)
This commit is contained in:
parent
da0e5edbec
commit
08e3cd1cce
@ -386,7 +386,6 @@ func (f *caseFilesystem) checkCaseExisting(name string) error {
|
||||
}
|
||||
|
||||
type defaultRealCaser struct {
|
||||
fs Filesystem
|
||||
cache caseCache
|
||||
}
|
||||
|
||||
@ -396,13 +395,12 @@ func newDefaultRealCaser(fs Filesystem) *defaultRealCaser {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
caser := &defaultRealCaser{
|
||||
fs: fs,
|
||||
return &defaultRealCaser{
|
||||
cache: caseCache{
|
||||
fs: fs,
|
||||
TwoQueueCache: cache,
|
||||
},
|
||||
}
|
||||
return caser
|
||||
}
|
||||
|
||||
func (r *defaultRealCaser) realCase(name string) (string, error) {
|
||||
@ -414,27 +412,6 @@ func (r *defaultRealCaser) realCase(name string) (string, error) {
|
||||
for _, comp := range PathComponents(name) {
|
||||
node := r.cache.getExpireAdd(realName)
|
||||
|
||||
node.once.Do(func() {
|
||||
dirNames, err := r.fs.DirNames(realName)
|
||||
if err != nil {
|
||||
r.cache.Remove(realName)
|
||||
node.err = err
|
||||
return
|
||||
}
|
||||
|
||||
num := len(dirNames)
|
||||
node.children = make(map[string]struct{}, num)
|
||||
node.lowerToReal = make(map[string]string, num)
|
||||
lastLower := ""
|
||||
for _, n := range dirNames {
|
||||
node.children[n] = struct{}{}
|
||||
lower := UnicodeLowercaseNormalized(n)
|
||||
if lower != lastLower {
|
||||
node.lowerToReal[lower] = n
|
||||
lastLower = n
|
||||
}
|
||||
}
|
||||
})
|
||||
if node.err != nil {
|
||||
return "", node.err
|
||||
}
|
||||
@ -457,10 +434,29 @@ func (r *defaultRealCaser) dropCache() {
|
||||
r.cache.Purge()
|
||||
}
|
||||
|
||||
func newCaseNode() *caseNode {
|
||||
return &caseNode{
|
||||
expires: time.Now().Add(caseCacheTimeout),
|
||||
type caseCache struct {
|
||||
*lru.TwoQueueCache
|
||||
fs Filesystem
|
||||
mut sync.Mutex
|
||||
}
|
||||
|
||||
// getExpireAdd gets an entry for the given key. If no entry exists, or it is
|
||||
// expired a new one is created and added to the cache.
|
||||
func (c *caseCache) getExpireAdd(key string) *caseNode {
|
||||
c.mut.Lock()
|
||||
defer c.mut.Unlock()
|
||||
v, ok := c.Get(key)
|
||||
if !ok {
|
||||
node := newCaseNode(key, c.fs)
|
||||
c.Add(key, node)
|
||||
return node
|
||||
}
|
||||
node := v.(*caseNode)
|
||||
if node.expires.Before(time.Now()) {
|
||||
node = newCaseNode(key, c.fs)
|
||||
c.Add(key, node)
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// The keys to children are "real", case resolved names of the path
|
||||
@ -474,30 +470,32 @@ type caseNode struct {
|
||||
expires time.Time
|
||||
lowerToReal map[string]string
|
||||
children map[string]struct{}
|
||||
once sync.Once
|
||||
err error
|
||||
}
|
||||
|
||||
type caseCache struct {
|
||||
*lru.TwoQueueCache
|
||||
mut sync.Mutex
|
||||
}
|
||||
|
||||
// getExpireAdd gets an entry for the given key. If no entry exists, or it is
|
||||
// expired a new one is created and added to the cache.
|
||||
func (c *caseCache) getExpireAdd(key string) *caseNode {
|
||||
c.mut.Lock()
|
||||
defer c.mut.Unlock()
|
||||
v, ok := c.Get(key)
|
||||
if !ok {
|
||||
node := newCaseNode()
|
||||
c.Add(key, node)
|
||||
func newCaseNode(name string, filesystem Filesystem) *caseNode {
|
||||
node := new(caseNode)
|
||||
dirNames, err := filesystem.DirNames(name)
|
||||
// Set expiry after calling DirNames in case this is super-slow
|
||||
// (e.g. dirs with many children on android)
|
||||
node.expires = time.Now().Add(caseCacheTimeout)
|
||||
if err != nil {
|
||||
node.err = err
|
||||
return node
|
||||
}
|
||||
node := v.(*caseNode)
|
||||
if node.expires.Before(time.Now()) {
|
||||
node = newCaseNode()
|
||||
c.Add(key, node)
|
||||
|
||||
num := len(dirNames)
|
||||
node.children = make(map[string]struct{}, num)
|
||||
node.lowerToReal = make(map[string]string, num)
|
||||
lastLower := ""
|
||||
for _, n := range dirNames {
|
||||
node.children[n] = struct{}{}
|
||||
lower := UnicodeLowercaseNormalized(n)
|
||||
if lower != lastLower {
|
||||
node.lowerToReal[lower] = n
|
||||
lastLower = n
|
||||
}
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user