In #9701 there was a change that put the mutex used for `getExpireAdd` directly in `defaultRealCaser`, which is erroneous because multiple filesystems can share the same `caseCache`. ### Purpose Fixes #9836 and [Slow sync sending files from Android](https://forum.syncthing.net/t/slow-sync-sending-files-from-android/24208?u=marbens). There may be other issues caused by `getExpireAdd` conflicting with itself, though. ### Testing Unit tests pass and the case cache and conflict detection _seem_ to behave correctly. Signed-off-by: Marcus B Spencer <marcus@marcusspencer.us>
This commit is contained in:
+17
-12
@@ -397,10 +397,13 @@ func (f *caseFilesystem) checkCaseExisting(name string) error {
|
|||||||
type defaultRealCaser struct {
|
type defaultRealCaser struct {
|
||||||
cache *caseCache
|
cache *caseCache
|
||||||
fs Filesystem
|
fs Filesystem
|
||||||
mut sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type caseCache = lru.TwoQueueCache[string, *caseNode]
|
type caseCache struct {
|
||||||
|
*lru.TwoQueueCache[string, *caseNode]
|
||||||
|
|
||||||
|
mut sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
func newCaseCache() *caseCache {
|
func newCaseCache() *caseCache {
|
||||||
cache, err := lru.New2Q[string, *caseNode](caseCacheItemLimit)
|
cache, err := lru.New2Q[string, *caseNode](caseCacheItemLimit)
|
||||||
@@ -408,7 +411,9 @@ func newCaseCache() *caseCache {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return cache
|
return &caseCache{
|
||||||
|
TwoQueueCache: cache,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *defaultRealCaser) realCase(name string) (string, error) {
|
func (r *defaultRealCaser) realCase(name string) (string, error) {
|
||||||
@@ -418,7 +423,7 @@ func (r *defaultRealCaser) realCase(name string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, comp := range PathComponents(name) {
|
for _, comp := range PathComponents(name) {
|
||||||
node := r.getExpireAdd(realName)
|
node := r.cache.getExpireAdd(realName, r.fs)
|
||||||
|
|
||||||
if node.err != nil {
|
if node.err != nil {
|
||||||
return "", node.err
|
return "", node.err
|
||||||
@@ -444,18 +449,18 @@ func (r *defaultRealCaser) dropCache() {
|
|||||||
|
|
||||||
// getExpireAdd gets an entry for the given key. If no entry exists, or it is
|
// 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.
|
// expired a new one is created and added to the cache.
|
||||||
func (r *defaultRealCaser) getExpireAdd(key string) *caseNode {
|
func (c *caseCache) getExpireAdd(key string, fs Filesystem) *caseNode {
|
||||||
r.mut.Lock()
|
c.mut.Lock()
|
||||||
defer r.mut.Unlock()
|
defer c.mut.Unlock()
|
||||||
node, ok := r.cache.Get(key)
|
node, ok := c.Get(key)
|
||||||
if !ok {
|
if !ok {
|
||||||
node := newCaseNode(key, r.fs)
|
node := newCaseNode(key, fs)
|
||||||
r.cache.Add(key, node)
|
c.Add(key, node)
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
if node.expires.Before(time.Now()) {
|
if node.expires.Before(time.Now()) {
|
||||||
node = newCaseNode(key, r.fs)
|
node = newCaseNode(key, fs)
|
||||||
r.cache.Add(key, node)
|
c.Add(key, node)
|
||||||
}
|
}
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user