milvus/pkg/util/cache/lru_impl.go
jaime c9d0c157ec
Move some modules from internal to public package (#22572)
Signed-off-by: jaime <yun.zhang@zilliz.com>
2023-04-06 19:14:32 +08:00

99 lines
2.5 KiB
Go

// Licensed to the LF AI & Data foundation under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import (
"container/list"
)
// lruCache is a LRU cache.
type lruCache struct {
cache *cache
cap int64
ls list.List
}
// init initializes cache list.
func (l *lruCache) init(c *cache, cap int64) {
l.cache = c
l.cap = cap
l.ls.Init()
}
// write adds new entry to the cache and returns evicted entry if necessary.
func (l *lruCache) write(en *entry) *entry {
// Fast path
if en.accessList != nil {
// Entry existed, update its status instead.
l.markAccess(en)
return nil
}
// Try to add new entry to the list
cen := l.cache.getOrSet(en)
if cen == nil {
// Brand new entry, add to the LRU list.
en.accessList = l.ls.PushFront(en)
} else {
// Entry has already been added, update its value instead.
cen.setValue(en.getValue())
cen.setWriteTime(en.getWriteTime())
if cen.accessList == nil {
// Entry is loaded to the cache but not yet registered.
cen.accessList = l.ls.PushFront(cen)
} else {
l.markAccess(cen)
}
}
if l.cap > 0 && int64(l.ls.Len()) > l.cap {
// Remove the last element when capacity exceeded.
en = getEntry(l.ls.Back())
return l.remove(en)
}
return nil
}
// access updates cache entry for a get.
func (l *lruCache) access(en *entry) {
if en.accessList != nil {
l.markAccess(en)
}
}
// markAccess marks the element has just been accessed.
// en.accessList must not be null.
func (l *lruCache) markAccess(en *entry) {
l.ls.MoveToFront(en.accessList)
}
// remove an entry from the cache.
func (l *lruCache) remove(en *entry) *entry {
if en.accessList == nil {
// Already deleted
return nil
}
l.cache.delete(en)
l.ls.Remove(en.accessList)
en.accessList = nil
return en
}
// iterate walks through all lists by access time.
func (l *lruCache) iterate(fn func(en *entry) bool) {
iterateListFromBack(&l.ls, fn)
}