| @@ -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() | |||
| } | |||
| } | |||