Fetch the repository succeeded.
package gogocache
import (
"bufio"
"fmt"
"gitee.com/Gogo-gitee/gogo-cache/log"
"gitee.com/Gogo-gitee/gogo-cache/persistence"
"gitee.com/Gogo-gitee/gogo-cache/singleflight"
"hash/crc32"
"os"
)
// Hash 哈希函数
type Hash func(data []byte) uint32
// CacheGroup 统一管理多个cache
type CacheGroup struct {
cacheNum int
getter Getter
mainCache []cache
hash Hash
// use singleflight.Group to make sure that
// each key is only fetched once
loader *singleflight.Group
}
//Getter 定义获取数据源的接口
type Getter interface {
Get(key string) ([]byte, error)
}
//GetterFunc 实现Getter接口的一个函数
type GetterFunc func(key string) ([]byte, error)
//GetterFunc 实现了getter的接口
func (f GetterFunc) Get(key string) ([]byte, error) {
return f(key)
}
// NewGroup 新建group的实例
func NewGroup(cacheBytes int64, getter Getter, cacheNum int, fn Hash) *CacheGroup {
caches := make([]cache, cacheNum)
for i, _ := range caches {
caches[i] = cache{cacheBytes: cacheBytes}
}
g := &CacheGroup{
cacheNum: cacheNum,
getter: getter,
hash: fn,
mainCache: caches,
loader: &singleflight.Group{},
}
if g.hash == nil {
g.hash = crc32.ChecksumIEEE
}
//恢复原来的键值对
file, err := os.OpenFile("./persistence.txt", os.O_CREATE|os.O_RDONLY, 0666)
if err != nil {
log.Error(err)
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
key := scanner.Text()
// do anything with strLine
if scanner.Scan() {
value := scanner.Bytes()
g.recover(key, ByteView{Bytes: value})
}
}
return g
}
//getCacheNo 获取key对应的cache下标
func (g *CacheGroup) getCacheNo(key string) int {
hash := int(g.hash([]byte(key))) % g.cacheNum
return hash
}
// Get 从cache里面查找key
func (g *CacheGroup) Get(key string) (ByteView, error) {
if key == "" {
return ByteView{}, fmt.Errorf("key is required")
}
cacheNo := g.getCacheNo(key)
log.Debugf("searching %s from %d", key, cacheNo)
if v, ok := g.mainCache[cacheNo].get(key); ok {
log.Debugf("[GogoCache] hit")
return v, nil
} else {
if g.getter == nil {
return ByteView{}, fmt.Errorf("[GogoCache] not hit")
} else {
return g.getLocally(key)
}
}
}
//getLocally 从数据源中获取数据
func (g *CacheGroup) getLocally(key string) (ByteView, error) {
bytes, err := g.getter.Get(key)
if err != nil || len(bytes) == 0 {
return ByteView{}, err
}
log.Debugf("got from local %v", bytes)
value := ByteView{Bytes: cloneBytes(bytes)}
//回源以后,异步写入数据
g.Set(key, value)
return value, nil
}
//recover 恢复键值对
func (g *CacheGroup) recover(key string, value ByteView) {
cacheNo := g.getCacheNo(key)
g.mainCache[cacheNo].add(key, value)
}
//Set set加入键值对
func (g *CacheGroup) Set(key string, value ByteView) {
persistence.Record(key, value.Bytes)
cacheNo := g.getCacheNo(key)
log.Debugf("write key: %s value: %v to cache no: %d\n", key, value, cacheNo)
g.mainCache[cacheNo].add(key, value)
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。