forked from devfeel/dotweb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstore_runtime.go
127 lines (115 loc) · 3.36 KB
/
store_runtime.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package session
import (
"container/list"
"sync"
"time"
)
// MemProvider Implement the provider interface
type RuntimeStore struct {
lock *sync.RWMutex // locker
sessions map[string]*list.Element // map in memory
list *list.List // for gc
maxlifetime int64
}
func NewRuntimeStore(config *StoreConfig) *RuntimeStore {
return &RuntimeStore{
lock: new(sync.RWMutex),
sessions: make(map[string]*list.Element),
list: new(list.List),
maxlifetime: config.Maxlifetime,
}
}
// SessionRead get session state by sessionId
func (store *RuntimeStore) SessionRead(sessionId string) (*SessionState, error) {
store.lock.RLock()
if element, ok := store.sessions[sessionId]; ok {
go store.SessionAccess(sessionId)
store.lock.RUnlock()
return element.Value.(*SessionState), nil
}
store.lock.RUnlock()
//if sessionId of state not exist, create a new state
state := NewSessionState(store, sessionId, make(map[interface{}]interface{}))
store.lock.Lock()
element := store.list.PushFront(state)
store.sessions[sessionId] = element
store.lock.Unlock()
return state, nil
}
// SessionExist check session state exist by sessionId
func (store *RuntimeStore) SessionExist(sessionId string) bool {
store.lock.RLock()
defer store.lock.RUnlock()
if _, ok := store.sessions[sessionId]; ok {
return true
}
return false
}
//SessionUpdate update session state in store
func (store *RuntimeStore) SessionUpdate(state *SessionState) error {
store.lock.RLock()
if element, ok := store.sessions[state.sessionId]; ok { //state has exist
go store.SessionAccess(state.sessionId)
store.lock.RUnlock()
element.Value.(*SessionState).values = state.values //only assist update whole session state
return nil
}
store.lock.RUnlock()
//if sessionId of state not exist, create a new state
new_state := NewSessionState(store, state.sessionId, state.values)
store.lock.Lock()
new_element := store.list.PushFront(new_state)
store.sessions[state.sessionId] = new_element
store.lock.Unlock()
return nil
}
// SessionRemove delete session state in store
func (store *RuntimeStore) SessionRemove(sessionId string) error {
store.lock.Lock()
defer store.lock.Unlock()
if element, ok := store.sessions[sessionId]; ok {
delete(store.sessions, sessionId)
store.list.Remove(element)
return nil
}
return nil
}
// SessionGC clean expired session stores in memory session
func (store *RuntimeStore) SessionGC() int {
num := 0
store.lock.RLock()
for {
element := store.list.Back()
if element == nil {
break
}
if (element.Value.(*SessionState).timeAccessed.Unix() + store.maxlifetime) < time.Now().Unix() {
store.lock.RUnlock()
store.lock.Lock()
store.list.Remove(element)
delete(store.sessions, element.Value.(*SessionState).SessionID())
num += 1
store.lock.Unlock()
store.lock.RLock()
} else {
break
}
}
store.lock.RUnlock()
return num
}
// SessionAll get count number of memory session
func (store *RuntimeStore) SessionCount() int {
return store.list.Len()
}
// SessionAccess expand time of session store by id in memory session
func (store *RuntimeStore) SessionAccess(sessionId string) error {
store.lock.Lock()
defer store.lock.Unlock()
if element, ok := store.sessions[sessionId]; ok {
element.Value.(*SessionState).timeAccessed = time.Now()
store.list.MoveToFront(element)
return nil
}
return nil
}