hlfw.ca

webbing

ref: 910a508a5ca9c521acbb7c9fab2ee06d174b38e4
dir: /data.go/

View raw version
package session

import (
	"container/list"
	"log"
	"sync"
	"time"
)

var pder = &Default{
	list: list.New(),
}

// Store - map of clients and their sessions
type Store struct {
	sid   string
	atime time.Time
	value map[interface{}]interface{}
}

func init() {
	pder.sessions = make(map[string]*list.Element, 0)
	Register("default", pder)
}

// Set - register kv into manager
func (st *Store) Set(key, value interface{}) error {
	st.value[key] = value
	pder.Update(st.sid)
	return nil
}

// Get - lookup value by key
func (st *Store) Get(key interface{}) interface{} {
	pder.Update(st.sid)
	if v, ok := st.value[key]; ok {
		return v
	}
	return nil
}

// Delete - remove value pointed to by key
func (st *Store) Delete(key interface{}) error {
	delete(st.value, key)
	pder.Update(st.sid)
	return nil
}

// ID - return session ID
func (st *Store) ID() string {
	return st.sid
}

// Default - The main session used for clients on the site
type Default struct {
	lock     sync.Mutex
	sessions map[string]*list.Element
	list     *list.List
}

// Init - create session
func (pder *Default) Init(sid string) (Session, error) {
	pder.lock.Lock()
	defer pder.lock.Unlock()
	v := make(map[interface{}]interface{}, 0)
	newsess := &Store{sid: sid, atime: time.Now(), value: v}
	element := pder.list.PushBack(newsess)
	pder.sessions[sid] = element
	return newsess, nil
}

// Read - Request session by id
func (pder *Default) Read(sid string) (Session, error) {
	if element, ok := pder.sessions[sid]; ok {
		return element.Value.(*Store), nil
	}
	return pder.Init(sid)
}

// Destroy - Remove session by id
func (pder *Default) Destroy(sid string) error {
	if element, ok := pder.sessions[sid]; ok {
		delete(pder.sessions, sid)
		pder.list.Remove(element)
	}
	return nil
}

// GC - Clean up all expired sessions
func (pder *Default) GC(maxlifetime int64) {
	log.Println("Starting GC sweep")
	pder.lock.Lock()
	defer pder.lock.Unlock()
	for {
		element := pder.list.Back()
		if element == nil {
			return
		}
		if (element.Value.(*Store).atime.Unix() + maxlifetime) >= time.Now().Unix() {
			return
		}
		pder.list.Remove(element)
		delete(pder.sessions, element.Value.(*Store).sid)
	}
}

// Update - move session labelled with ID to top of list
func (pder *Default) Update(sid string) error {
	pder.lock.Lock()
	defer pder.lock.Unlock()
	if element, ok := pder.sessions[sid]; ok {
		element.Value.(*Store).atime = time.Now()
		pder.list.MoveToFront(element)
	}
	return nil
}