cubefs

Форк
0
/
summarycache.go 
144 строки · 3.0 Кб
1
package fs
2

3
import (
4
	"container/list"
5
	"sync"
6
	"time"
7

8
	"github.com/cubefs/cubefs/sdk/meta"
9
)
10

11
const (
12
	MinSummaryCacheEvictNum   = 10
13
	MaxSummaryCacheEvictNum   = 200000
14
	SummaryBgEvictionInterval = 2 * time.Minute
15
	DefaultSummaryExpiration  = 2 * time.Minute
16
	MaxSummaryCache           = 1000000
17
)
18

19
// SummaryCache defines the structure of the content-summary cache.
20
type SummaryCache struct {
21
	sync.RWMutex
22
	cache       map[uint64]*list.Element
23
	lruList     *list.List
24
	expiration  time.Duration
25
	maxElements int
26
}
27

28
// summaryCacheElement defines the structure of the content-summary cache's element.
29
type summaryCacheElement struct {
30
	ino        uint64
31
	info       *meta.SummaryInfo
32
	expiration int64
33
}
34

35
// NewSummaryCache returns a new content-summary cache.
36
func NewSummaryCache(exp time.Duration, maxElement int) *SummaryCache {
37
	sc := &SummaryCache{
38
		cache:       make(map[uint64]*list.Element),
39
		lruList:     list.New(),
40
		expiration:  exp,
41
		maxElements: maxElement,
42
	}
43
	go sc.backgroundEviction()
44
	return sc
45
}
46

47
// Put puts the given summary info into the content-summary cache.
48
func (sc *SummaryCache) Put(inode uint64, summaryInfo *meta.SummaryInfo) {
49
	sc.Lock()
50
	old, ok := sc.cache[inode]
51
	if ok {
52
		sc.lruList.Remove(old)
53
		delete(sc.cache, inode)
54
	}
55
	if sc.lruList.Len() >= sc.maxElements {
56
		sc.evict(true)
57
	}
58
	element := sc.lruList.PushFront(&summaryCacheElement{
59
		ino:        inode,
60
		info:       summaryInfo,
61
		expiration: time.Now().Add(sc.expiration).UnixNano(),
62
	})
63
	sc.cache[inode] = element
64
	sc.Unlock()
65
}
66

67
// Get returns the content-summary info based on the given inode number.
68
func (sc *SummaryCache) Get(inode uint64) *meta.SummaryInfo {
69
	sc.RLock()
70
	element, ok := sc.cache[inode]
71
	if !ok {
72
		sc.RUnlock()
73
		return nil
74
	}
75
	info := element.Value.(*summaryCacheElement)
76
	if cacheExpired(info) {
77
		sc.RUnlock()
78
		return nil
79
	}
80
	sc.RUnlock()
81
	return info.info
82
}
83

84
// Delete deletes the content-summary info based on the given inode number.
85
func (sc *SummaryCache) Delete(inode uint64) {
86
	sc.Lock()
87
	element, ok := sc.cache[inode]
88
	if ok {
89
		sc.lruList.Remove(element)
90
		delete(sc.cache, inode)
91
	}
92
	sc.Unlock()
93
}
94

95
func (sc *SummaryCache) evict(foreground bool) {
96
	for i := 0; i < MinSummaryCacheEvictNum; i++ {
97
		element := sc.lruList.Back()
98
		if element == nil {
99
			return
100
		}
101
		info := element.Value.(*summaryCacheElement)
102
		if !foreground && !cacheExpired(info) {
103
			return
104
		}
105
		sc.lruList.Remove(element)
106
		delete(sc.cache, info.ino)
107
	}
108
	if foreground {
109
		return
110
	}
111

112
	for i := 0; i < MaxSummaryCacheEvictNum; i++ {
113
		element := sc.lruList.Back()
114
		if element == nil {
115
			break
116
		}
117
		info := element.Value.(*summaryCacheElement)
118
		if !cacheExpired(info) {
119
			break
120
		}
121
		sc.lruList.Remove(element)
122
		delete(sc.cache, info.ino)
123
	}
124
}
125

126
func (sc *SummaryCache) backgroundEviction() {
127
	t := time.NewTicker(SummaryBgEvictionInterval)
128
	defer t.Stop()
129
	for {
130
		select {
131
		case <-t.C:
132
			sc.Lock()
133
			sc.evict(false)
134
			sc.Unlock()
135
		}
136
	}
137
}
138

139
func cacheExpired(info *summaryCacheElement) bool {
140
	if time.Now().UnixNano() > info.expiration {
141
		return true
142
	}
143
	return false
144
}
145

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.