Beego/session/sess_file.go

141 lines
2.8 KiB
Go
Raw Normal View History

package session
import (
"io/ioutil"
"os"
"path"
"path/filepath"
"sync"
"time"
)
var (
filepder = &FileProvider{}
gcmaxlifetime int64
)
type FileSessionStore struct {
f *os.File
sid string
lock sync.RWMutex
values map[interface{}]interface{}
}
func (fs *FileSessionStore) Set(key, value interface{}) error {
fs.lock.Lock()
defer fs.lock.Unlock()
fs.values[key] = value
fs.updatecontent()
return nil
}
func (fs *FileSessionStore) Get(key interface{}) interface{} {
fs.lock.RLock()
defer fs.lock.RUnlock()
fs.updatecontent()
if v, ok := fs.values[key]; ok {
return v
} else {
return nil
}
return nil
}
func (fs *FileSessionStore) Delete(key interface{}) error {
fs.lock.Lock()
defer fs.lock.Unlock()
delete(fs.values, key)
fs.updatecontent()
return nil
}
func (fs *FileSessionStore) SessionID() string {
return fs.sid
}
func (fs *FileSessionStore) SessionRelease() {
fs.f.Close()
}
func (fs *FileSessionStore) updatecontent() {
if len(fs.values) > 0 {
b, err := encodeGob(fs.values)
if err != nil {
return
}
fs.f.Write(b)
}
}
type FileProvider struct {
maxlifetime int64
savePath string
}
func (fp *FileProvider) SessionInit(maxlifetime int64, savePath string) error {
fp.maxlifetime = maxlifetime
fp.savePath = savePath
return nil
}
func (fp *FileProvider) SessionRead(sid string) (SessionStore, error) {
err := os.MkdirAll(path.Join(fp.savePath, string(sid[0]), string(sid[1])), 0777)
if err != nil {
println(err.Error())
}
_, err = os.Stat(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
var f *os.File
if err == nil {
f, err = os.OpenFile(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid), os.O_RDWR, 0777)
} else if os.IsNotExist(err) {
f, err = os.Create(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
} else {
return nil, err
}
os.Chtimes(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid), time.Now(), time.Now())
var kv map[interface{}]interface{}
b, err := ioutil.ReadAll(f)
if err != nil {
return nil, err
}
if len(b) == 0 {
kv = make(map[interface{}]interface{})
} else {
kv, err = decodeGob(b)
if err != nil {
return nil, err
}
}
f.Close()
f, err = os.Create(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
ss := &FileSessionStore{f: f, sid: sid, values: kv}
return ss, nil
}
func (fp *FileProvider) SessionDestroy(sid string) error {
os.Remove(path.Join(fp.savePath))
return nil
}
func (fp *FileProvider) SessionGC() {
gcmaxlifetime = fp.maxlifetime
filepath.Walk(fp.savePath, gcpath)
}
func gcpath(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
if (info.ModTime().Unix() + gcmaxlifetime) < time.Now().Unix() {
os.Remove(path)
}
return nil
}
func init() {
Register("file", filepder)
}