mirror of
https://github.com/cubefs/cubefs.git
synced 2026-08-02 02:00:56 +00:00
139 lines
3.0 KiB
Go
139 lines
3.0 KiB
Go
package fs
|
|
|
|
import (
|
|
"container/list"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/cubefs/cubefs/sdk/meta"
|
|
)
|
|
|
|
const (
|
|
MinSummaryCacheEvictNum = 10
|
|
MaxSummaryCacheEvictNum = 200000
|
|
SummaryBgEvictionInterval = 2 * time.Minute
|
|
DefaultSummaryExpiration = 2 * time.Minute
|
|
MaxSummaryCache = 1000000
|
|
)
|
|
|
|
// SummaryCache defines the structure of the content-summary cache.
|
|
type SummaryCache struct {
|
|
sync.RWMutex
|
|
cache map[uint64]*list.Element
|
|
lruList *list.List
|
|
expiration time.Duration
|
|
maxElements int
|
|
}
|
|
|
|
// summaryCacheElement defines the structure of the content-summary cache's element.
|
|
type summaryCacheElement struct {
|
|
ino uint64
|
|
info *meta.SummaryInfo
|
|
expiration int64
|
|
}
|
|
|
|
// NewSummaryCache returns a new content-summary cache.
|
|
func NewSummaryCache(exp time.Duration, maxElement int) *SummaryCache {
|
|
sc := &SummaryCache{
|
|
cache: make(map[uint64]*list.Element),
|
|
lruList: list.New(),
|
|
expiration: exp,
|
|
maxElements: maxElement,
|
|
}
|
|
go sc.backgroundEviction()
|
|
return sc
|
|
}
|
|
|
|
// Put puts the given summary info into the content-summary cache.
|
|
func (sc *SummaryCache) Put(inode uint64, summaryInfo *meta.SummaryInfo) {
|
|
sc.Lock()
|
|
old, ok := sc.cache[inode]
|
|
if ok {
|
|
sc.lruList.Remove(old)
|
|
delete(sc.cache, inode)
|
|
}
|
|
if sc.lruList.Len() >= sc.maxElements {
|
|
sc.evict(true)
|
|
}
|
|
element := sc.lruList.PushFront(&summaryCacheElement{
|
|
ino: inode,
|
|
info: summaryInfo,
|
|
expiration: time.Now().Add(sc.expiration).UnixNano(),
|
|
})
|
|
sc.cache[inode] = element
|
|
sc.Unlock()
|
|
}
|
|
|
|
// Get returns the content-summary info based on the given inode number.
|
|
func (sc *SummaryCache) Get(inode uint64) *meta.SummaryInfo {
|
|
sc.RLock()
|
|
element, ok := sc.cache[inode]
|
|
if !ok {
|
|
sc.RUnlock()
|
|
return nil
|
|
}
|
|
info := element.Value.(*summaryCacheElement)
|
|
if cacheExpired(info) {
|
|
sc.RUnlock()
|
|
return nil
|
|
}
|
|
sc.RUnlock()
|
|
return info.info
|
|
}
|
|
|
|
// Delete deletes the content-summary info based on the given inode number.
|
|
func (sc *SummaryCache) Delete(inode uint64) {
|
|
sc.Lock()
|
|
element, ok := sc.cache[inode]
|
|
if ok {
|
|
sc.lruList.Remove(element)
|
|
delete(sc.cache, inode)
|
|
}
|
|
sc.Unlock()
|
|
}
|
|
|
|
func (sc *SummaryCache) evict(foreground bool) {
|
|
for i := 0; i < MinSummaryCacheEvictNum; i++ {
|
|
element := sc.lruList.Back()
|
|
if element == nil {
|
|
return
|
|
}
|
|
info := element.Value.(*summaryCacheElement)
|
|
if !foreground && !cacheExpired(info) {
|
|
return
|
|
}
|
|
sc.lruList.Remove(element)
|
|
delete(sc.cache, info.ino)
|
|
}
|
|
if foreground {
|
|
return
|
|
}
|
|
|
|
for i := 0; i < MaxSummaryCacheEvictNum; i++ {
|
|
element := sc.lruList.Back()
|
|
if element == nil {
|
|
break
|
|
}
|
|
info := element.Value.(*summaryCacheElement)
|
|
if !cacheExpired(info) {
|
|
break
|
|
}
|
|
sc.lruList.Remove(element)
|
|
delete(sc.cache, info.ino)
|
|
}
|
|
}
|
|
|
|
func (sc *SummaryCache) backgroundEviction() {
|
|
t := time.NewTicker(SummaryBgEvictionInterval)
|
|
defer t.Stop()
|
|
for range t.C {
|
|
sc.Lock()
|
|
sc.evict(false)
|
|
sc.Unlock()
|
|
}
|
|
}
|
|
|
|
func cacheExpired(info *summaryCacheElement) bool {
|
|
return time.Now().UnixNano() > info.expiration
|
|
}
|