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) }