package memoryprovider
import (
"container/list"
"log"
"sync"
"time"
"xapp/components/httpmod/http/session"
)
type MemorySessionProvider struct {
lock sync.Mutex
sessions map[string]*list.Element
elList *list.List
}
var providerInst = &MemorySessionProvider{
elList: list.New(),
sessions: make(map[string]*list.Element),
}
func providerInstance() *MemorySessionProvider {
return providerInst
}
var registerMemoryProvider sync.Once
func DoRegister() {
registerMemoryProvider.Do(func() {
session.RegisterProvider("memory", providerInst)
})
}
func (pder *MemorySessionProvider) SessionInit(sid string) (session.Session, error) {
pder.lock.Lock()
defer pder.lock.Unlock()
newsess := &SessionStore{
sid: sid,
timeAccessed: time.Now(),
infoColl: make(map[interface{}]interface{}, 0),
}
element := pder.elList.PushBack(newsess)
pder.sessions[sid] = element
return newsess, nil
}
func (pder *MemorySessionProvider) SessionRead(sid string) (session.Session, error) {
if sess := pder.loadExistingSession(sid); sess != nil {
return sess, nil
}
return pder.SessionInit(sid)
}
func (pder *MemorySessionProvider) loadExistingSession(sid string) session.Session {
pder.lock.Lock()
defer pder.lock.Unlock()
if element, ok := pder.sessions[sid]; ok {
return element.Value.(*SessionStore)
}
return nil
}
func (pder *MemorySessionProvider) SessionDestroy(sid string) error {
pder.lock.Lock()
defer pder.lock.Unlock()
if element, ok := pder.sessions[sid]; ok {
delete(pder.sessions, sid)
pder.elList.Remove(element)
}
return nil
}
// maxlifetime in milliseconds
func (pder *MemorySessionProvider) SessionGC(maxlifetime int64) {
pder.lock.Lock()
defer pder.lock.Unlock()
log.Println("list len is now:", pder.elList.Len())
for {
element := pder.elList.Back()
if element == nil {
break
}
ss := element.Value.(*SessionStore)
if ss.timeAccessed.Unix()*1000+maxlifetime < time.Now().Unix()*1000 {
pder.elList.Remove(element)
delete(pder.sessions, ss.sid)
} else {
break
}
}
log.Println("list len(after gc):", pder.elList.Len())
}
func (pder *MemorySessionProvider) SessionUpdate(sid string) {
pder.lock.Lock()
defer pder.lock.Unlock()
if element, ok := pder.sessions[sid]; ok {
element.Value.(*SessionStore).timeAccessed = time.Now()
pder.elList.MoveToFront(element)
}
}
单个的Session:
package memoryprovider
import (
"time"
)
type SessionStore struct {
sid string // unique session id
timeAccessed time.Time // last access time
infoColl map[interface{}]interface{} // session value stored inside
}
func (st *SessionStore) Set(key, value interface{}) error {
st.infoColl[key] = value
providerInstance().SessionUpdate(st.sid)
return nil
}
func (st *SessionStore) Get(key interface{}) interface{} {
providerInstance().SessionUpdate(st.sid)
if v, ok := st.infoColl[key]; ok {
return v
} else {
return nil
}
return nil
}
func (st *SessionStore) Delete(key interface{}) error {
delete(st.infoColl, key)
providerInstance().SessionUpdate(st.sid)
return nil
}
func (st *SessionStore) SessionID() string {
return st.sid
}