104 lines
1.9 KiB
Go
104 lines
1.9 KiB
Go
package cache
|
|
|
|
import (
|
|
"crypto/md5"
|
|
"fmt"
|
|
"os"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type FileCache struct {
|
|
mu sync.Mutex
|
|
locks map[string]*sync.Mutex
|
|
Dir string
|
|
}
|
|
|
|
func (fc *FileCache) getLock(key string) *sync.Mutex {
|
|
fc.mu.Lock()
|
|
defer fc.mu.Unlock()
|
|
if fc.locks == nil {
|
|
fc.locks = make(map[string]*sync.Mutex)
|
|
}
|
|
if _, ok := fc.locks[key]; !ok {
|
|
fc.locks[key] = new(sync.Mutex)
|
|
}
|
|
return fc.locks[key]
|
|
}
|
|
|
|
func (c *FileCache) Get(key string, value interface{}) error {
|
|
data, _ := c.getValue(key)
|
|
err := DecodeValue(data, value)
|
|
return err
|
|
}
|
|
|
|
// 获取值,如果文件不存在或者过期,返回空,过滤掉错误
|
|
func (c *FileCache) getValue(key string) (string, error) {
|
|
f := c.fileName(key)
|
|
fileInfo, err := os.Stat(f)
|
|
if err != nil {
|
|
//文件不存在
|
|
return "", nil
|
|
}
|
|
difT := time.Now().Sub(fileInfo.ModTime())
|
|
if difT >= 0 {
|
|
os.Remove(f)
|
|
return "", nil
|
|
}
|
|
data, err := os.ReadFile(f)
|
|
if err != nil {
|
|
return "", nil
|
|
}
|
|
return string(data), nil
|
|
}
|
|
|
|
// 保存值
|
|
func (c *FileCache) saveValue(key string, value string, exp int) error {
|
|
f := c.fileName(key)
|
|
lock := c.getLock(f)
|
|
lock.Lock()
|
|
defer lock.Unlock()
|
|
|
|
err := os.WriteFile(f, ([]byte)(value), 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if exp <= 0 {
|
|
exp = MaxTimeOut
|
|
}
|
|
expFromNow := time.Now().Add(time.Duration(exp) * time.Second)
|
|
err = os.Chtimes(f, expFromNow, expFromNow)
|
|
return err
|
|
}
|
|
|
|
func (c *FileCache) Set(key string, value interface{}, exp int) error {
|
|
str, err := EncodeValue(value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = c.saveValue(key, str, exp)
|
|
return err
|
|
}
|
|
|
|
func (c *FileCache) SetDir(path string) {
|
|
c.Dir = path
|
|
}
|
|
|
|
func (c *FileCache) fileName(key string) string {
|
|
f := c.Dir + string(os.PathSeparator) + fmt.Sprintf("%x", md5.Sum([]byte(key)))
|
|
return f
|
|
}
|
|
|
|
func (c *FileCache) Gc() error {
|
|
//检查文件过期时间,并删除
|
|
return nil
|
|
}
|
|
|
|
func NewFileCache() *FileCache {
|
|
return &FileCache{
|
|
locks: make(map[string]*sync.Mutex),
|
|
Dir: os.TempDir(),
|
|
}
|
|
}
|