273 lines
6.6 KiB
Go
273 lines
6.6 KiB
Go
package drive
|
|
|
|
import (
|
|
"context"
|
|
"github.com/gogf/gf/v2/container/gvar"
|
|
"github.com/gogf/gf/v2/crypto/gmd5"
|
|
"github.com/gogf/gf/v2/encoding/gjson"
|
|
"github.com/gogf/gf/v2/os/gcache"
|
|
"github.com/gogf/gf/v2/os/gctx"
|
|
"github.com/gogf/gf/v2/os/gfile"
|
|
"github.com/gogf/gf/v2/os/gtime"
|
|
"github.com/gogf/gf/v2/util/gconv"
|
|
"path"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
fileIndex = "index.txt"
|
|
)
|
|
|
|
type FileIndex struct {
|
|
File string `json:"file"`
|
|
Duration time.Duration `json:"duration"`
|
|
}
|
|
type FileData struct {
|
|
Data interface{} `json:"data"`
|
|
Time int64 `json:"time"`
|
|
}
|
|
|
|
type AdapterFile struct {
|
|
FilePath string
|
|
Lock sync.Mutex
|
|
}
|
|
|
|
func (a *AdapterFile) Key2Name(key interface{}) string {
|
|
md5Str, _ := gmd5.Encrypt(key)
|
|
fileName := path.Join(md5Str[0:2], md5Str[2:4], md5Str[4:6], md5Str[16:])
|
|
fileNameAll := path.Join(a.FilePath, fileName)
|
|
|
|
return fileNameAll
|
|
}
|
|
|
|
func (a *AdapterFile) AddIndex(FileName interface{}, duration time.Duration) {
|
|
var isEdit bool
|
|
|
|
var setTime int64
|
|
if duration == 0 {
|
|
setTime = 0
|
|
} else {
|
|
setTime = gtime.Now().Add(duration).Unix()
|
|
}
|
|
saveArr := []string{
|
|
gconv.String(FileName),
|
|
strconv.FormatInt(setTime, 10),
|
|
}
|
|
saveStr := strings.Join(saveArr, "|")
|
|
|
|
gfile.ReadLines(fileIndex, func(text string) (err error) {
|
|
arr := strings.Split(text, "|")
|
|
if arr[0] == FileName {
|
|
isEdit = true
|
|
gfile.ReplaceFile(text, saveStr, fileIndex)
|
|
return
|
|
}
|
|
return
|
|
})
|
|
|
|
if isEdit {
|
|
return
|
|
}
|
|
|
|
gfile.PutContentsAppend(fileIndex, saveStr+"\n")
|
|
}
|
|
|
|
func (a *AdapterFile) DelIndex(FileName interface{}) {
|
|
//var save bool
|
|
gfile.ReadLines(fileIndex, func(text string) (err error) {
|
|
arr := strings.Split(text, "|")
|
|
if arr[0] == FileName {
|
|
//save = true
|
|
err = gfile.ReplaceFile(text+"\n", "", fileIndex)
|
|
return
|
|
}
|
|
|
|
return
|
|
})
|
|
|
|
}
|
|
|
|
func (a *AdapterFile) Set(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (err error) {
|
|
fileNameAll := a.Key2Name(key)
|
|
var send = &FileData{
|
|
Data: value,
|
|
Time: gtime.Now().Add(duration).Unix(),
|
|
}
|
|
err = gfile.PutBytes(fileNameAll, gjson.MustEncode(send))
|
|
|
|
if err != nil {
|
|
return
|
|
}
|
|
a.AddIndex(key, duration)
|
|
return
|
|
}
|
|
|
|
func (a *AdapterFile) SetMap(ctx context.Context, data map[interface{}]interface{}, duration time.Duration) (err error) {
|
|
for k, v := range data {
|
|
//fileNameAll := a.Key2Name(k)
|
|
//var send = &FileData{
|
|
// Data: v,
|
|
// Time: gtime.Now().Add(duration).Unix(),
|
|
//}
|
|
//
|
|
//err = gfile.PutBytes(fileNameAll, gconv.Bytes(send))
|
|
a.Set(ctx, k, v, duration)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a *AdapterFile) SetIfNotExist(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (ok bool, err error) {
|
|
err = a.Set(ctx, key, value, duration)
|
|
return
|
|
}
|
|
|
|
func (a *AdapterFile) SetIfNotExistFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) {
|
|
//TODO implement me
|
|
panic("implement me")
|
|
}
|
|
|
|
func (a *AdapterFile) SetIfNotExistFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (ok bool, err error) {
|
|
//TODO implement me
|
|
panic("implement me")
|
|
}
|
|
|
|
func (a *AdapterFile) Get(ctx context.Context, key interface{}) (res *gvar.Var, err error) {
|
|
var data *FileData
|
|
name := a.Key2Name(key)
|
|
if !gfile.IsFile(name) {
|
|
return
|
|
}
|
|
file := gfile.GetBytes(name)
|
|
gjson.DecodeTo(file, &data)
|
|
if data.Time < time.Now().Unix() {
|
|
a.Remove(ctx, key)
|
|
return
|
|
}
|
|
res = gvar.New(data.Data)
|
|
return
|
|
}
|
|
|
|
func (a *AdapterFile) GetOrSet(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (result *gvar.Var, err error) {
|
|
a.Set(ctx, key, value, duration)
|
|
result, err = a.Get(ctx, key)
|
|
return
|
|
}
|
|
|
|
func (a *AdapterFile) GetOrSetFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) {
|
|
value := f
|
|
a.Set(ctx, key, value, duration)
|
|
result, err = a.Get(ctx, key)
|
|
return
|
|
}
|
|
|
|
func (a *AdapterFile) GetOrSetFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) {
|
|
a.Lock.Lock()
|
|
defer a.Lock.Unlock()
|
|
result, err = a.GetOrSetFunc(ctx, key, f, duration)
|
|
return
|
|
}
|
|
|
|
func (a *AdapterFile) Contains(ctx context.Context, key interface{}) (bool, error) {
|
|
return gfile.IsFile(a.FilePath), nil
|
|
}
|
|
|
|
func (a *AdapterFile) Size(ctx context.Context) (size int, err error) {
|
|
size = int(gfile.Size(a.FilePath))
|
|
return
|
|
}
|
|
|
|
func (a *AdapterFile) Data(ctx context.Context) (data map[interface{}]interface{}, err error) {
|
|
//TODO implement me
|
|
panic("implement me")
|
|
}
|
|
|
|
func (a *AdapterFile) Keys(ctx context.Context) (keys []interface{}, err error) {
|
|
keys = make([]interface{}, 0)
|
|
gfile.ReadLines(fileIndex, func(text string) (err error) {
|
|
arr := strings.Split(text, "|")
|
|
keys = append(keys, arr[0])
|
|
return
|
|
})
|
|
return
|
|
}
|
|
|
|
func (a *AdapterFile) Values(ctx context.Context) (values []interface{}, err error) {
|
|
//TODO implement me
|
|
panic("implement me")
|
|
}
|
|
|
|
func (a *AdapterFile) Update(ctx context.Context, key interface{}, value interface{}) (oldValue *gvar.Var, exist bool, err error) {
|
|
fileNameAll := a.Key2Name(key)
|
|
getFile := gfile.GetBytes(fileNameAll)
|
|
var data *FileData
|
|
gconv.Scan(getFile, &data)
|
|
oldValue.Set(data.Data)
|
|
|
|
var send = &FileData{
|
|
Data: value,
|
|
Time: data.Time,
|
|
}
|
|
|
|
err = gfile.PutBytes(fileNameAll, gconv.Bytes(send))
|
|
if err != nil {
|
|
return
|
|
}
|
|
a.AddIndex(key, time.Duration(data.Time-gtime.Now().Unix()))
|
|
return
|
|
}
|
|
|
|
func (a *AdapterFile) UpdateExpire(ctx context.Context, key interface{}, duration time.Duration) (oldDuration time.Duration, err error) {
|
|
//TODO implement me
|
|
panic("implement me")
|
|
}
|
|
|
|
func (a *AdapterFile) GetExpire(ctx context.Context, key interface{}) (time.Duration, error) {
|
|
//TODO implement me
|
|
panic("implement me")
|
|
}
|
|
|
|
func (a *AdapterFile) Remove(ctx context.Context, keys ...interface{}) (lastValue *gvar.Var, err error) {
|
|
for _, v := range keys {
|
|
fileNameAll := a.Key2Name(v)
|
|
lastValue, err = a.Get(ctx, fileNameAll)
|
|
err = gfile.RemoveFile(fileNameAll)
|
|
//删除索引文件
|
|
a.DelIndex(v)
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func (a *AdapterFile) Clear(ctx context.Context) error {
|
|
return gfile.RemoveAll(a.FilePath)
|
|
}
|
|
|
|
func (a *AdapterFile) Close(ctx context.Context) error {
|
|
return nil
|
|
}
|
|
|
|
func NewAdapterFile(filePath string) gcache.Adapter {
|
|
fileIndex = path.Join(filePath, fileIndex)
|
|
|
|
//清空过期文件目录
|
|
delKeys := make([]interface{}, 0)
|
|
gfile.ReadLines(fileIndex, func(text string) error {
|
|
arr := strings.Split(text, "|")
|
|
if gtime.Now().Unix() > gconv.Int64(arr[1]) {
|
|
delKeys = append(delKeys, arr[0])
|
|
}
|
|
return nil
|
|
})
|
|
|
|
obj := &AdapterFile{
|
|
FilePath: filePath,
|
|
}
|
|
if len(delKeys) > 0 {
|
|
obj.Remove(gctx.New(), delKeys...)
|
|
}
|
|
|
|
return obj
|
|
}
|