Browse Source

解决死锁问题

feature_gxh
Sydonian 6 months ago
parent
commit
1a1d52ef9f
1 changed files with 33 additions and 17 deletions
  1. +33
    -17
      client/internal/mount/vfs/cache/file.go

+ 33
- 17
client/internal/mount/vfs/cache/file.go View File

@@ -107,7 +107,8 @@ type CacheFile struct {
readers []*CacheFileHandle
writers []*CacheFileHandle
saveMetaChan chan any
stopSaveChan chan any
saveMetaLock *sync.Mutex
stopSaveMeta *bool
isDeleted bool

level CacheLevel
@@ -170,7 +171,8 @@ func createNewCacheFile(cache *Cache, pathComps []string) (*CacheFile, error) {
info: info,
rwLock: &sync.RWMutex{},
saveMetaChan: make(chan any, 1),
stopSaveChan: make(chan any),
saveMetaLock: &sync.Mutex{},
stopSaveMeta: new(bool),
level: LevelComplete,
metaFile: metaFile,
dataFile: dataFile,
@@ -178,7 +180,7 @@ func createNewCacheFile(cache *Cache, pathComps []string) (*CacheFile, error) {
state: cacheState{},
}

go ch.serving(ch.saveMetaChan, ch.stopSaveChan)
go ch.serving(ch.saveMetaChan, ch.stopSaveMeta)

return ch, nil
}
@@ -242,7 +244,8 @@ func loadCacheFile(cache *Cache, pathComps []string) (*CacheFile, error) {
info: *info,
rwLock: &sync.RWMutex{},
saveMetaChan: make(chan any, 1),
stopSaveChan: make(chan any),
saveMetaLock: &sync.Mutex{},
stopSaveMeta: new(bool),
level: LevelComplete,
metaFile: metaFile,
dataFile: dataFile,
@@ -250,7 +253,7 @@ func loadCacheFile(cache *Cache, pathComps []string) (*CacheFile, error) {
state: cacheState{},
}

go ch.serving(ch.saveMetaChan, ch.stopSaveChan)
go ch.serving(ch.saveMetaChan, ch.stopSaveMeta)

return ch, nil
}
@@ -300,7 +303,8 @@ func newCacheFileFromObject(cache *Cache, pathComps []string, obj *clitypes.Obje
remoteObj: obj,
rwLock: &sync.RWMutex{},
saveMetaChan: make(chan any, 1),
stopSaveChan: make(chan any),
saveMetaLock: &sync.Mutex{},
stopSaveMeta: new(bool),
level: LevelComplete,
metaFile: metaFile,
dataFile: dataFile,
@@ -308,7 +312,7 @@ func newCacheFileFromObject(cache *Cache, pathComps []string, obj *clitypes.Obje
state: cacheState{},
}

go ch.serving(ch.saveMetaChan, ch.stopSaveChan)
go ch.serving(ch.saveMetaChan, ch.stopSaveMeta)

return ch, nil
}
@@ -366,6 +370,12 @@ func (f *CacheFile) Release() {
}

func (f *CacheFile) LevelDown(level CacheLevel) bool {
if level <= LevelReadOnly {
// 如果降级到不需要保存元数据的级别,就要先暂停保存元数据的操作
f.saveMetaLock.Lock()
defer f.saveMetaLock.Unlock()
}

f.rwLock.Lock()
defer f.rwLock.Unlock()

@@ -393,10 +403,11 @@ func (f *CacheFile) LevelDown(level CacheLevel) bool {
// TODO 日志
f.saveMeta(f.info)
}
// 这里会等待直到saveMeta线程退出
f.stopSaveChan <- nil
f.saveMetaChan = nil
f.stopSaveChan = nil
// 由于已经获取了saveMetaLock,所以这里设置true之后调用metaFile.Close不会导致saveMeta线程的保存失败
// 因为saveMeta线程会先检查stopSaveMete的值
*f.stopSaveMeta = true
f.stopSaveMeta = nil
f.metaFile.Close()

f.level = LevelReadOnly
@@ -447,11 +458,11 @@ func (f *CacheFile) LevelUp(level CacheLevel) bool {
}

f.saveMetaChan = make(chan any, 1)
f.stopSaveChan = make(chan any)
f.stopSaveMeta = new(bool)
f.metaFile = metaFile
f.level = LevelMetaLoaded

go f.serving(f.saveMetaChan, f.stopSaveChan)
go f.serving(f.saveMetaChan, f.stopSaveMeta)

if level <= f.level {
break
@@ -654,8 +665,8 @@ func (f *CacheFile) Truncate(size int64) error {
return nil
}

func (f *CacheFile) serving(saveMetaChan chan any, stopSaveChan chan any) {
ticker := time.NewTicker(time.Second * 5)
func (f *CacheFile) serving(saveMetaChan chan any, stopSaveMeta *bool) {
ticker := time.NewTicker(time.Second * 30)
defer ticker.Stop()

for {
@@ -665,17 +676,21 @@ func (f *CacheFile) serving(saveMetaChan chan any, stopSaveChan chan any) {
return
}

case <-stopSaveChan:
return

case <-ticker.C:
}

f.saveMetaLock.Lock()
if *stopSaveMeta {
f.saveMetaLock.Unlock()
break
}

f.rwLock.RLock()
info := f.info.Clone()
// 如果文件已被删除,则不能再保存元数据,防止覆盖掉新创建的同名文件
if f.isDeleted {
f.rwLock.RUnlock()
f.saveMetaLock.Unlock()
break
}

@@ -684,6 +699,7 @@ func (f *CacheFile) serving(saveMetaChan chan any, stopSaveChan chan any) {
// TODO 错误日志
f.saveMeta(info)
f.metaFile.Sync()
f.saveMetaLock.Unlock()
}
}



Loading…
Cancel
Save