Skip to content

Commit 3d5d2fa

Browse files
authored
Unfortunately MemProvider Init does not actually Init properly (#6692)
* Unfortunately MemProvider Init does not actually Init properly Worse all of its members are private and you cannot update them. Simple fix copy it in to modules session. Signed-off-by: Andrew Thornton <[email protected]> * Fix misspelling
1 parent 6cb127d commit 3d5d2fa

File tree

2 files changed

+218
-1
lines changed

2 files changed

+218
-1
lines changed

modules/session/memory.go

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
// Copyright 2013 Beego Authors
2+
// Copyright 2014 The Macaron Authors
3+
// Copyright 2019 The Gitea Authors
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License"): you may
6+
// not use this file except in compliance with the License. You may obtain
7+
// a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
// License for the specific language governing permissions and limitations
15+
// under the License.
16+
17+
package session
18+
19+
import (
20+
"container/list"
21+
"fmt"
22+
"sync"
23+
"time"
24+
25+
"github.com/go-macaron/session"
26+
)
27+
28+
// MemStore represents a in-memory session store implementation.
29+
type MemStore struct {
30+
sid string
31+
lock sync.RWMutex
32+
data map[interface{}]interface{}
33+
lastAccess time.Time
34+
}
35+
36+
// NewMemStore creates and returns a memory session store.
37+
func NewMemStore(sid string) *MemStore {
38+
return &MemStore{
39+
sid: sid,
40+
data: make(map[interface{}]interface{}),
41+
lastAccess: time.Now(),
42+
}
43+
}
44+
45+
// Set sets value to given key in session.
46+
func (s *MemStore) Set(key, val interface{}) error {
47+
s.lock.Lock()
48+
defer s.lock.Unlock()
49+
50+
s.data[key] = val
51+
return nil
52+
}
53+
54+
// Get gets value by given key in session.
55+
func (s *MemStore) Get(key interface{}) interface{} {
56+
s.lock.RLock()
57+
defer s.lock.RUnlock()
58+
59+
return s.data[key]
60+
}
61+
62+
// Delete deletes a key from session.
63+
func (s *MemStore) Delete(key interface{}) error {
64+
s.lock.Lock()
65+
defer s.lock.Unlock()
66+
67+
delete(s.data, key)
68+
return nil
69+
}
70+
71+
// ID returns current session ID.
72+
func (s *MemStore) ID() string {
73+
return s.sid
74+
}
75+
76+
// Release releases resource and save data to provider.
77+
func (*MemStore) Release() error {
78+
return nil
79+
}
80+
81+
// Flush deletes all session data.
82+
func (s *MemStore) Flush() error {
83+
s.lock.Lock()
84+
defer s.lock.Unlock()
85+
86+
s.data = make(map[interface{}]interface{})
87+
return nil
88+
}
89+
90+
// MemProvider represents a in-memory session provider implementation.
91+
type MemProvider struct {
92+
lock sync.RWMutex
93+
maxLifetime int64
94+
data map[string]*list.Element
95+
// A priority list whose lastAccess newer gets higher priority.
96+
list *list.List
97+
}
98+
99+
// Init initializes memory session provider.
100+
func (p *MemProvider) Init(maxLifetime int64, _ string) error {
101+
p.lock.Lock()
102+
p.maxLifetime = maxLifetime
103+
p.lock.Unlock()
104+
return nil
105+
}
106+
107+
// update expands time of session store by given ID.
108+
func (p *MemProvider) update(sid string) error {
109+
p.lock.Lock()
110+
defer p.lock.Unlock()
111+
112+
if e, ok := p.data[sid]; ok {
113+
e.Value.(*MemStore).lastAccess = time.Now()
114+
p.list.MoveToFront(e)
115+
return nil
116+
}
117+
return nil
118+
}
119+
120+
// Read returns raw session store by session ID.
121+
func (p *MemProvider) Read(sid string) (_ session.RawStore, err error) {
122+
p.lock.RLock()
123+
e, ok := p.data[sid]
124+
p.lock.RUnlock()
125+
126+
if ok {
127+
if err = p.update(sid); err != nil {
128+
return nil, err
129+
}
130+
return e.Value.(*MemStore), nil
131+
}
132+
133+
// Create a new session.
134+
p.lock.Lock()
135+
defer p.lock.Unlock()
136+
137+
s := NewMemStore(sid)
138+
p.data[sid] = p.list.PushBack(s)
139+
return s, nil
140+
}
141+
142+
// Exist returns true if session with given ID exists.
143+
func (p *MemProvider) Exist(sid string) bool {
144+
p.lock.RLock()
145+
defer p.lock.RUnlock()
146+
147+
_, ok := p.data[sid]
148+
return ok
149+
}
150+
151+
// Destory deletes a session by session ID.
152+
func (p *MemProvider) Destory(sid string) error {
153+
p.lock.Lock()
154+
defer p.lock.Unlock()
155+
156+
e, ok := p.data[sid]
157+
if !ok {
158+
return nil
159+
}
160+
161+
p.list.Remove(e)
162+
delete(p.data, sid)
163+
return nil
164+
}
165+
166+
// Regenerate regenerates a session store from old session ID to new one.
167+
func (p *MemProvider) Regenerate(oldsid, sid string) (session.RawStore, error) {
168+
if p.Exist(sid) {
169+
return nil, fmt.Errorf("new sid '%s' already exists", sid)
170+
}
171+
172+
s, err := p.Read(oldsid)
173+
if err != nil {
174+
return nil, err
175+
}
176+
177+
if err = p.Destory(oldsid); err != nil {
178+
return nil, err
179+
}
180+
181+
s.(*MemStore).sid = sid
182+
183+
p.lock.Lock()
184+
defer p.lock.Unlock()
185+
p.data[sid] = p.list.PushBack(s)
186+
return s, nil
187+
}
188+
189+
// Count counts and returns number of sessions.
190+
func (p *MemProvider) Count() int {
191+
return p.list.Len()
192+
}
193+
194+
// GC calls GC to clean expired sessions.
195+
func (p *MemProvider) GC() {
196+
p.lock.RLock()
197+
for {
198+
// No session in the list.
199+
e := p.list.Back()
200+
if e == nil {
201+
break
202+
}
203+
204+
if (e.Value.(*MemStore).lastAccess.Unix() + p.maxLifetime) < time.Now().Unix() {
205+
p.lock.RUnlock()
206+
p.lock.Lock()
207+
p.list.Remove(e)
208+
delete(p.data, e.Value.(*MemStore).sid)
209+
p.lock.Unlock()
210+
p.lock.RLock()
211+
} else {
212+
break
213+
}
214+
}
215+
p.lock.RUnlock()
216+
}

modules/session/virtual.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package session
66

77
import (
8+
"container/list"
89
"encoding/json"
910
"fmt"
1011
"sync"
@@ -38,7 +39,7 @@ func (o *VirtualSessionProvider) Init(gclifetime int64, config string) error {
3839
// This is only slightly more wrong than modules/setting/session.go:23
3940
switch opts.Provider {
4041
case "memory":
41-
o.provider = &session.MemProvider{}
42+
o.provider = &MemProvider{list: list.New(), data: make(map[string]*list.Element)}
4243
case "file":
4344
o.provider = &session.FileProvider{}
4445
case "redis":

0 commit comments

Comments
 (0)