217c3a2e by astaxie

Merge pull request #508 from voidd/develop

Couchbase session provider
2 parents ff6120cb 04c2ba01
1 package session
2
3 import (
4 "github.com/couchbaselabs/go-couchbase"
5 "net/http"
6 "strings"
7 "sync"
8 )
9
10 var couchbpder = &CouchbaseProvider{}
11
12 type CouchbaseSessionStore struct {
13 b *couchbase.Bucket
14 sid string
15 lock sync.RWMutex
16 values map[interface{}]interface{}
17 maxlifetime int64
18 }
19
20 type CouchbaseProvider struct {
21 maxlifetime int64
22 savePath string
23 pool string
24 bucket string
25 b *couchbase.Bucket
26 }
27
28 func (cs *CouchbaseSessionStore) Set(key, value interface{}) error {
29 cs.lock.Lock()
30 defer cs.lock.Unlock()
31 cs.values[key] = value
32 return nil
33 }
34
35 func (cs *CouchbaseSessionStore) Get(key interface{}) interface{} {
36 cs.lock.RLock()
37 defer cs.lock.RUnlock()
38 if v, ok := cs.values[key]; ok {
39 return v
40 } else {
41 return nil
42 }
43 return nil
44 }
45
46 func (cs *CouchbaseSessionStore) Delete(key interface{}) error {
47 cs.lock.Lock()
48 defer cs.lock.Unlock()
49 delete(cs.values, key)
50 return nil
51 }
52
53 func (cs *CouchbaseSessionStore) Flush() error {
54 cs.lock.Lock()
55 defer cs.lock.Unlock()
56 cs.values = make(map[interface{}]interface{})
57 return nil
58 }
59
60 func (cs *CouchbaseSessionStore) SessionID() string {
61 return cs.sid
62 }
63
64 func (cs *CouchbaseSessionStore) SessionRelease(w http.ResponseWriter) {
65 defer cs.b.Close()
66
67 // if rs.values is empty, return directly
68 if len(cs.values) < 1 {
69 cs.b.Delete(cs.sid)
70 return
71 }
72
73 bo, err := encodeGob(cs.values)
74 if err != nil {
75 return
76 }
77
78 cs.b.Set(cs.sid, int(cs.maxlifetime), bo)
79 }
80
81 func (cp *CouchbaseProvider) getBucket() *couchbase.Bucket {
82 c, err := couchbase.Connect(cp.savePath)
83 if err != nil {
84 return nil
85 }
86
87 pool, err := c.GetPool(cp.pool)
88 if err != nil {
89 return nil
90 }
91
92 bucket, err := pool.GetBucket(cp.bucket)
93 if err != nil {
94 return nil
95 }
96
97 return bucket
98 }
99
100 // init couchbase session
101 // savepath like couchbase server REST/JSON URL
102 // e.g. http://host:port/, Pool, Bucket
103 func (cp *CouchbaseProvider) SessionInit(maxlifetime int64, savePath string) error {
104 cp.maxlifetime = maxlifetime
105 configs := strings.Split(savePath, ",")
106 if len(configs) > 0 {
107 cp.savePath = configs[0]
108 }
109 if len(configs) > 1 {
110 cp.pool = configs[1]
111 }
112 if len(configs) > 2 {
113 cp.bucket = configs[2]
114 }
115
116 return nil
117 }
118
119 // read couchbase session by sid
120 func (cp *CouchbaseProvider) SessionRead(sid string) (SessionStore, error) {
121 cp.b = cp.getBucket()
122
123 var doc []byte
124
125 err := cp.b.Get(sid, &doc)
126 var kv map[interface{}]interface{}
127 if doc == nil {
128 kv = make(map[interface{}]interface{})
129 } else {
130 kv, err = decodeGob(doc)
131 if err != nil {
132 return nil, err
133 }
134 }
135
136 cs := &CouchbaseSessionStore{b: cp.b, sid: sid, values: kv, maxlifetime: cp.maxlifetime}
137 return cs, nil
138 }
139
140 func (cp *CouchbaseProvider) SessionExist(sid string) bool {
141 cp.b = cp.getBucket()
142 defer cp.b.Close()
143
144 var doc []byte
145
146 if err := cp.b.Get(sid, &doc); err != nil || doc == nil {
147 return false
148 } else {
149 return true
150 }
151 }
152
153 func (cp *CouchbaseProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) {
154 cp.b = cp.getBucket()
155
156 var doc []byte
157 if err := cp.b.Get(oldsid, &doc); err != nil || doc == nil {
158 cp.b.Set(sid, int(cp.maxlifetime), "")
159 } else {
160 err := cp.b.Delete(oldsid)
161 if err != nil {
162 return nil, err
163 }
164 _, _ = cp.b.Add(sid, int(cp.maxlifetime), doc)
165 }
166
167 err := cp.b.Get(sid, &doc)
168 if err != nil {
169 return nil, err
170 }
171 var kv map[interface{}]interface{}
172 if doc == nil {
173 kv = make(map[interface{}]interface{})
174 } else {
175 kv, err = decodeGob(doc)
176 if err != nil {
177 return nil, err
178 }
179 }
180
181 cs := &CouchbaseSessionStore{b: cp.b, sid: sid, values: kv, maxlifetime: cp.maxlifetime}
182 return cs, nil
183 }
184
185 func (cp *CouchbaseProvider) SessionDestroy(sid string) error {
186 cp.b = cp.getBucket()
187 defer cp.b.Close()
188
189 cp.b.Delete(sid)
190 return nil
191 }
192
193 func (cp *CouchbaseProvider) SessionGC() {
194 return
195 }
196
197 func (cp *CouchbaseProvider) SessionAll() int {
198 return 0
199 }
200
201 func init() {
202 Register("couchbase", couchbpder)
203 }
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!