package lru import ( "container/list" _ "gitee.com/timedb/wheatCache/conf" "gitee.com/timedb/wheatCache/pkg/errorx" "gitee.com/timedb/wheatCache/pkg/event" "gitee.com/timedb/wheatCache/pkg/proto" "gitee.com/timedb/wheatCache/pkg/structure" "gitee.com/timedb/wheatCache/pkg/util" "github.com/spf13/viper" "sync/atomic" ) type keyBaseValue struct { key string val structure.KeyBaseInterface } type SingleCache struct { maxsize int64 //最大的长度 clearSize int64 // 清理长度 nowSize int64 // 现在的长度 li *list.List lruMap map[string]*list.Element lruMaxDiverSize int lruDriver event.DriverInterface lruConsumer event.ConsumerInterface lruCleanProduce event.ProduceInterface // 发送清理事件 } // UpdateLruSize 更新现在的长度 func (lru *SingleCache) UpdateLruSize(length structure.UpdateLength) { atomic.AddInt64(&lru.nowSize, int64(length)) } func cacheInit() (int64, int64, int) { maxSize := viper.GetString("lruCache.maxSize") retMaxSize, maxErr := util.ParseSizeToBit(maxSize) if maxErr != nil { return 0, 0, 0 } if retMaxSize == 0 { retMaxSize = defaultLruMaxSize } clearSize := viper.GetString("lruCache.clearSize") retClearSize, clearErr := util.ParseSizeToBit(clearSize) if clearErr != nil { return 0, 0, 0 } if retClearSize == 0 { retClearSize = defaultLruClearSize } maxDriver := viper.GetInt("lruCache.eventDriverSize") if maxDriver == 0 { maxDriver = defaultLruEventDriver } return retMaxSize, retClearSize, maxDriver } // NewLRUCache lru初始化 func NewLRUCache() *SingleCache { maxSize, clearSize, maxDriverSize := cacheInit() lruDriver := event.NewDriver(maxDriverSize) lruCacheOnce.Do(func() { lru := &SingleCache{ maxsize: maxSize, clearSize: clearSize, nowSize: 0, li: list.New(), lruMap: make(map[string]*list.Element), lruMaxDiverSize: maxDriverSize, lruDriver: lruDriver, lruConsumer: event.NewConsumer(lruDriver), lruCleanProduce: event.NewProduce(lruDriver), } lruCache = lru go lru.lruSingleWork() }) return lruCache } // GetDriver 获取驱动 func (lru *SingleCache) GetDriver() event.DriverInterface { return lru.lruDriver } //Add 增加 func (lru *SingleCache) Add(key *proto.BaseKey, val structure.KeyBaseInterface) { keyBaseVal := &keyBaseValue{ key: key.Key, val: val, } if elVal, ok := lru.lruMap[key.Key]; ok { lru.li.MoveToFront(elVal) elVal.Value = keyBaseVal return } valEl := lru.li.PushFront(keyBaseVal) lru.lruMap[key.Key] = valEl //增加大小 lru.UpdateLruSize(structure.UpdateLength(valEl.Value.(*keyBaseValue).val.SizeByte())) } // Get 查找key对应的value func (lru *SingleCache) Get(key *proto.BaseKey) (structure.KeyBaseInterface, bool) { if lru.lruMap == nil { return nil, false } if elVal, ok := lru.lruMap[key.Key]; ok { lru.li.MoveToFront(elVal) return elVal.Value.(*keyBaseValue).val, true } return nil, false } //Del 删除机制 func (lru *SingleCache) Del() error { if lru.lruMap == nil { return errorx.New("lru is nil") } data := lru.li.Back() delete(lru.lruMap, data.Value.(*keyBaseValue).key) //删除大小 lru.UpdateLruSize(structure.UpdateLength(-1 * data.Value.(*keyBaseValue).val.SizeByte())) lru.li.Remove(data) return nil } //DelByKey 根据key删除 func (lru *SingleCache) DelByKey(key *proto.BaseKey) error { if lru.lruMap == nil { return errorx.New("lru is nil") } if _, ok := lru.lruMap[key.Key]; ok { delete(lru.lruMap, key.Key) return nil } return errorx.New("lru no this key") } func (lru *SingleCache) DelToClearSize() error { if lru.lruMap == nil { return errorx.New("lru is nil") } for { if lru.nowSize > lru.clearSize*1/3 { //del自动给nowSize进行大小的改变 lru.Del() } else { break } } return nil }