122 lines
2.3 KiB
Go
122 lines
2.3 KiB
Go
package session
|
|
|
|
import (
|
|
"container/list"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
var prov = &Provider{list: list.New()}
|
|
|
|
type MemSessionStore struct {
|
|
timeAccessed time.Time
|
|
value map[interface{}]interface{}
|
|
sid string
|
|
}
|
|
|
|
func (m *MemSessionStore) Set(key interface{}, value interface{}) error {
|
|
m.value[key] = value
|
|
err := prov.SessionUpdate(m.sid)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *MemSessionStore) Get(key interface{}) interface{} {
|
|
err := prov.SessionUpdate(m.sid)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
if v, ok := m.value[key]; ok {
|
|
return v
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *MemSessionStore) Delete(key interface{}) error {
|
|
delete(m.value, key)
|
|
err := prov.SessionUpdate(m.sid)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *MemSessionStore) SessionID() string {
|
|
return m.sid
|
|
}
|
|
|
|
type Provider struct {
|
|
sessions map[string]*list.Element
|
|
list *list.List
|
|
lock sync.Mutex
|
|
}
|
|
|
|
func (p *Provider) SessionInit(sid string) (ISession, error) {
|
|
prov.lock.Lock()
|
|
defer prov.lock.Unlock()
|
|
v := make(map[interface{}]interface{}, 0)
|
|
newSess := &MemSessionStore{sid: sid, timeAccessed: time.Now(), value: v}
|
|
elem := prov.list.PushBack(newSess)
|
|
prov.sessions[sid] = elem
|
|
return newSess, nil
|
|
}
|
|
|
|
func (p *Provider) SessionRead(sid string) (ISession, error) {
|
|
if element, ok := prov.sessions[sid]; ok {
|
|
return element.Value.(*MemSessionStore), nil
|
|
}
|
|
|
|
sess, err := prov.SessionInit(sid)
|
|
return sess, err
|
|
}
|
|
|
|
func (p *Provider) SessionDestroy(sid string) error {
|
|
if element, ok := prov.sessions[sid]; ok {
|
|
delete(prov.sessions, sid)
|
|
prov.list.Remove(element)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *Provider) SessionGC(maxLifeTime int64) {
|
|
prov.lock.Lock()
|
|
defer prov.lock.Unlock()
|
|
|
|
for {
|
|
element := prov.list.Back()
|
|
if element == nil {
|
|
break
|
|
}
|
|
|
|
if (element.Value.(*MemSessionStore).timeAccessed.Unix() + maxLifeTime) < time.Now().Unix() {
|
|
prov.list.Remove(element)
|
|
delete(prov.sessions, element.Value.(*MemSessionStore).sid)
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
func (p *Provider) SessionUpdate(sid string) error {
|
|
p.lock.Lock()
|
|
defer p.lock.Unlock()
|
|
if elem, ok := p.sessions[sid]; ok {
|
|
elem.Value.(*MemSessionStore).timeAccessed = time.Now()
|
|
p.list.MoveToFront(elem)
|
|
return nil
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func init() {
|
|
prov.sessions = make(map[string]*list.Element, 0)
|
|
Register("memory", prov)
|
|
}
|