1
// Copyright 2018 The CubeFS Authors.
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
7
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12
// implied. See the License for the specific language governing
13
// permissions and limitations under the License.
22
"github.com/cubefs/cubefs/proto"
23
"github.com/cubefs/cubefs/util/log"
27
// MinInodeCacheEvictNum is used in the foreground eviction.
28
// When clearing the inodes from the cache, it stops as soon as 10 inodes have been evicted.
29
MinInodeCacheEvictNum = 10
30
// MaxInodeCacheEvictNum is used in the back ground. We can evict 200000 inodes at max.
31
MaxInodeCacheEvictNum = 200000
33
BgEvictionInterval = 2 * time.Minute
36
// InodeCache defines the structure of the inode cache.
37
type InodeCache struct {
39
cache map[uint64]*list.Element
41
expiration time.Duration
45
// NewInodeCache returns a new inode cache.
46
func NewInodeCache(exp time.Duration, maxElements int) *InodeCache {
48
cache: make(map[uint64]*list.Element),
51
maxElements: maxElements,
53
go ic.backgroundEviction()
57
// Put puts the given inode info into the inode cache.
58
func (ic *InodeCache) Put(info *proto.InodeInfo) {
60
old, ok := ic.cache[info.Inode]
62
ic.lruList.Remove(old)
63
delete(ic.cache, info.Inode)
66
if ic.lruList.Len() >= ic.maxElements {
70
inodeSetExpiration(info, ic.expiration)
71
element := ic.lruList.PushFront(info)
72
ic.cache[info.Inode] = element
74
// log.LogDebugf("InodeCache put inode: inode(%v)", info.Inode)
77
// Get returns the inode info based on the given inode number.
78
func (ic *InodeCache) Get(ino uint64) *proto.InodeInfo {
80
element, ok := ic.cache[ino]
86
info := element.Value.(*proto.InodeInfo)
87
if inodeExpired(info) && DisableMetaCache {
89
// log.LogDebugf("InodeCache GetConnect expired: now(%v) inode(%v), expired(%d)", time.Now().Format(LogTimeFormat), info.Inode, info.Expiration())
96
// Delete deletes the inode info based on the given inode number.
97
func (ic *InodeCache) Delete(ino uint64) {
98
// log.LogDebugf("InodeCache Delete: ino(%v)", ino)
100
element, ok := ic.cache[ino]
102
ic.lruList.Remove(element)
103
delete(ic.cache, ino)
108
// Foreground eviction cares more about the speed.
109
// Background eviction evicts all expired items from the cache.
110
// The caller should grab the WRITE lock of the inode cache.
111
func (ic *InodeCache) evict(foreground bool) {
114
for i := 0; i < MinInodeCacheEvictNum; i++ {
115
element := ic.lruList.Back()
120
// For background eviction, if all expired items have been evicted, just return
121
// But for foreground eviction, we need to evict at least MinInodeCacheEvictNum inodes.
122
// The foreground eviction, does not need to care if the inode has expired or not.
123
info := element.Value.(*proto.InodeInfo)
124
if !foreground && !inodeExpired(info) {
128
// log.LogDebugf("InodeCache GetConnect expired: now(%v) inode(%v)", time.Now().Format(LogTimeFormat), info.Inode)
129
ic.lruList.Remove(element)
130
delete(ic.cache, info.Inode)
134
// For background eviction, we need to continue evict all expired items from the cache
139
for i := 0; i < MaxInodeCacheEvictNum; i++ {
140
element := ic.lruList.Back()
144
info := element.Value.(*proto.InodeInfo)
145
if !inodeExpired(info) {
148
// log.LogDebugf("InodeCache GetConnect expired: now(%v) inode(%v)", time.Now().Format(LogTimeFormat), info.Inode)
149
ic.lruList.Remove(element)
150
delete(ic.cache, info.Inode)
155
func (ic *InodeCache) backgroundEviction() {
156
t := time.NewTicker(BgEvictionInterval)
160
log.LogInfof("InodeCache: start BG evict")
161
if !DisableMetaCache {
162
log.LogInfof("InodeCache: no need to do BG evict")
169
elapsed := time.Since(start)
170
log.LogInfof("InodeCache: total inode cache(%d), cost(%d)ns", ic.lruList.Len(), elapsed.Nanoseconds())