74804bc5 by astaxie

Merge pull request #490 from fuxiaohei/develop

add comments for session and toolbox package
2 parents 2fb57583 1d08a54f
...@@ -11,12 +11,15 @@ import ( ...@@ -11,12 +11,15 @@ import (
11 11
12 var cookiepder = &CookieProvider{} 12 var cookiepder = &CookieProvider{}
13 13
14 // Cookie SessionStore
14 type CookieSessionStore struct { 15 type CookieSessionStore struct {
15 sid string 16 sid string
16 values map[interface{}]interface{} //session data 17 values map[interface{}]interface{} // session data
17 lock sync.RWMutex 18 lock sync.RWMutex
18 } 19 }
19 20
21 // Set value to cookie session.
22 // the value are encoded as gob with hash block string.
20 func (st *CookieSessionStore) Set(key, value interface{}) error { 23 func (st *CookieSessionStore) Set(key, value interface{}) error {
21 st.lock.Lock() 24 st.lock.Lock()
22 defer st.lock.Unlock() 25 defer st.lock.Unlock()
...@@ -24,6 +27,7 @@ func (st *CookieSessionStore) Set(key, value interface{}) error { ...@@ -24,6 +27,7 @@ func (st *CookieSessionStore) Set(key, value interface{}) error {
24 return nil 27 return nil
25 } 28 }
26 29
30 // Get value from cookie session
27 func (st *CookieSessionStore) Get(key interface{}) interface{} { 31 func (st *CookieSessionStore) Get(key interface{}) interface{} {
28 st.lock.RLock() 32 st.lock.RLock()
29 defer st.lock.RUnlock() 33 defer st.lock.RUnlock()
...@@ -35,6 +39,7 @@ func (st *CookieSessionStore) Get(key interface{}) interface{} { ...@@ -35,6 +39,7 @@ func (st *CookieSessionStore) Get(key interface{}) interface{} {
35 return nil 39 return nil
36 } 40 }
37 41
42 // Delete value in cookie session
38 func (st *CookieSessionStore) Delete(key interface{}) error { 43 func (st *CookieSessionStore) Delete(key interface{}) error {
39 st.lock.Lock() 44 st.lock.Lock()
40 defer st.lock.Unlock() 45 defer st.lock.Unlock()
...@@ -42,6 +47,7 @@ func (st *CookieSessionStore) Delete(key interface{}) error { ...@@ -42,6 +47,7 @@ func (st *CookieSessionStore) Delete(key interface{}) error {
42 return nil 47 return nil
43 } 48 }
44 49
50 // Clean all values in cookie session
45 func (st *CookieSessionStore) Flush() error { 51 func (st *CookieSessionStore) Flush() error {
46 st.lock.Lock() 52 st.lock.Lock()
47 defer st.lock.Unlock() 53 defer st.lock.Unlock()
...@@ -49,10 +55,12 @@ func (st *CookieSessionStore) Flush() error { ...@@ -49,10 +55,12 @@ func (st *CookieSessionStore) Flush() error {
49 return nil 55 return nil
50 } 56 }
51 57
58 // Return id of this cookie session
52 func (st *CookieSessionStore) SessionID() string { 59 func (st *CookieSessionStore) SessionID() string {
53 return st.sid 60 return st.sid
54 } 61 }
55 62
63 // Write cookie session to http response cookie
56 func (st *CookieSessionStore) SessionRelease(w http.ResponseWriter) { 64 func (st *CookieSessionStore) SessionRelease(w http.ResponseWriter) {
57 str, err := encodeCookie(cookiepder.block, 65 str, err := encodeCookie(cookiepder.block,
58 cookiepder.config.SecurityKey, 66 cookiepder.config.SecurityKey,
...@@ -79,12 +87,21 @@ type cookieConfig struct { ...@@ -79,12 +87,21 @@ type cookieConfig struct {
79 Maxage int `json:"maxage"` 87 Maxage int `json:"maxage"`
80 } 88 }
81 89
90 // Cookie session provider
82 type CookieProvider struct { 91 type CookieProvider struct {
83 maxlifetime int64 92 maxlifetime int64
84 config *cookieConfig 93 config *cookieConfig
85 block cipher.Block 94 block cipher.Block
86 } 95 }
87 96
97 // Init cookie session provider with max lifetime and config json.
98 // maxlifetime is ignored.
99 // json config:
100 // securityKey - hash string
101 // blockKey - gob encode hash string. it's saved as aes crypto.
102 // securityName - recognized name in encoded cookie string
103 // cookieName - cookie name
104 // maxage - cookie max life time.
88 func (pder *CookieProvider) SessionInit(maxlifetime int64, config string) error { 105 func (pder *CookieProvider) SessionInit(maxlifetime int64, config string) error {
89 pder.config = &cookieConfig{} 106 pder.config = &cookieConfig{}
90 err := json.Unmarshal([]byte(config), pder.config) 107 err := json.Unmarshal([]byte(config), pder.config)
...@@ -104,6 +121,8 @@ func (pder *CookieProvider) SessionInit(maxlifetime int64, config string) error ...@@ -104,6 +121,8 @@ func (pder *CookieProvider) SessionInit(maxlifetime int64, config string) error
104 return nil 121 return nil
105 } 122 }
106 123
124 // Get SessionStore in cooke.
125 // decode cooke string to map and put into SessionStore with sid.
107 func (pder *CookieProvider) SessionRead(sid string) (SessionStore, error) { 126 func (pder *CookieProvider) SessionRead(sid string) (SessionStore, error) {
108 maps, _ := decodeCookie(pder.block, 127 maps, _ := decodeCookie(pder.block,
109 pder.config.SecurityKey, 128 pder.config.SecurityKey,
...@@ -116,26 +135,32 @@ func (pder *CookieProvider) SessionRead(sid string) (SessionStore, error) { ...@@ -116,26 +135,32 @@ func (pder *CookieProvider) SessionRead(sid string) (SessionStore, error) {
116 return rs, nil 135 return rs, nil
117 } 136 }
118 137
138 // Cookie session is always existed
119 func (pder *CookieProvider) SessionExist(sid string) bool { 139 func (pder *CookieProvider) SessionExist(sid string) bool {
120 return true 140 return true
121 } 141 }
122 142
143 // Implement method, no used.
123 func (pder *CookieProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) { 144 func (pder *CookieProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) {
124 return nil, nil 145 return nil, nil
125 } 146 }
126 147
148 // Implement method, no used.
127 func (pder *CookieProvider) SessionDestroy(sid string) error { 149 func (pder *CookieProvider) SessionDestroy(sid string) error {
128 return nil 150 return nil
129 } 151 }
130 152
153 // Implement method, no used.
131 func (pder *CookieProvider) SessionGC() { 154 func (pder *CookieProvider) SessionGC() {
132 return 155 return
133 } 156 }
134 157
158 // Implement method, return 0.
135 func (pder *CookieProvider) SessionAll() int { 159 func (pder *CookieProvider) SessionAll() int {
136 return 0 160 return 0
137 } 161 }
138 162
163 // Implement method, no used.
139 func (pder *CookieProvider) SessionUpdate(sid string) error { 164 func (pder *CookieProvider) SessionUpdate(sid string) error {
140 return nil 165 return nil
141 } 166 }
......
...@@ -18,6 +18,7 @@ var ( ...@@ -18,6 +18,7 @@ var (
18 gcmaxlifetime int64 18 gcmaxlifetime int64
19 ) 19 )
20 20
21 // File session store
21 type FileSessionStore struct { 22 type FileSessionStore struct {
22 f *os.File 23 f *os.File
23 sid string 24 sid string
...@@ -25,6 +26,7 @@ type FileSessionStore struct { ...@@ -25,6 +26,7 @@ type FileSessionStore struct {
25 values map[interface{}]interface{} 26 values map[interface{}]interface{}
26 } 27 }
27 28
29 // Set value to file session
28 func (fs *FileSessionStore) Set(key, value interface{}) error { 30 func (fs *FileSessionStore) Set(key, value interface{}) error {
29 fs.lock.Lock() 31 fs.lock.Lock()
30 defer fs.lock.Unlock() 32 defer fs.lock.Unlock()
...@@ -32,6 +34,7 @@ func (fs *FileSessionStore) Set(key, value interface{}) error { ...@@ -32,6 +34,7 @@ func (fs *FileSessionStore) Set(key, value interface{}) error {
32 return nil 34 return nil
33 } 35 }
34 36
37 // Get value from file session
35 func (fs *FileSessionStore) Get(key interface{}) interface{} { 38 func (fs *FileSessionStore) Get(key interface{}) interface{} {
36 fs.lock.RLock() 39 fs.lock.RLock()
37 defer fs.lock.RUnlock() 40 defer fs.lock.RUnlock()
...@@ -43,6 +46,7 @@ func (fs *FileSessionStore) Get(key interface{}) interface{} { ...@@ -43,6 +46,7 @@ func (fs *FileSessionStore) Get(key interface{}) interface{} {
43 return nil 46 return nil
44 } 47 }
45 48
49 // Delete value in file session by given key
46 func (fs *FileSessionStore) Delete(key interface{}) error { 50 func (fs *FileSessionStore) Delete(key interface{}) error {
47 fs.lock.Lock() 51 fs.lock.Lock()
48 defer fs.lock.Unlock() 52 defer fs.lock.Unlock()
...@@ -50,6 +54,7 @@ func (fs *FileSessionStore) Delete(key interface{}) error { ...@@ -50,6 +54,7 @@ func (fs *FileSessionStore) Delete(key interface{}) error {
50 return nil 54 return nil
51 } 55 }
52 56
57 // Clean all values in file session
53 func (fs *FileSessionStore) Flush() error { 58 func (fs *FileSessionStore) Flush() error {
54 fs.lock.Lock() 59 fs.lock.Lock()
55 defer fs.lock.Unlock() 60 defer fs.lock.Unlock()
...@@ -57,10 +62,12 @@ func (fs *FileSessionStore) Flush() error { ...@@ -57,10 +62,12 @@ func (fs *FileSessionStore) Flush() error {
57 return nil 62 return nil
58 } 63 }
59 64
65 // Get file session store id
60 func (fs *FileSessionStore) SessionID() string { 66 func (fs *FileSessionStore) SessionID() string {
61 return fs.sid 67 return fs.sid
62 } 68 }
63 69
70 // Write file session to local file with Gob string
64 func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) { 71 func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) {
65 defer fs.f.Close() 72 defer fs.f.Close()
66 b, err := encodeGob(fs.values) 73 b, err := encodeGob(fs.values)
...@@ -72,17 +79,23 @@ func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) { ...@@ -72,17 +79,23 @@ func (fs *FileSessionStore) SessionRelease(w http.ResponseWriter) {
72 fs.f.Write(b) 79 fs.f.Write(b)
73 } 80 }
74 81
82 // File session provider
75 type FileProvider struct { 83 type FileProvider struct {
76 maxlifetime int64 84 maxlifetime int64
77 savePath string 85 savePath string
78 } 86 }
79 87
88 // Init file session provider.
89 // savePath sets the session files path.
80 func (fp *FileProvider) SessionInit(maxlifetime int64, savePath string) error { 90 func (fp *FileProvider) SessionInit(maxlifetime int64, savePath string) error {
81 fp.maxlifetime = maxlifetime 91 fp.maxlifetime = maxlifetime
82 fp.savePath = savePath 92 fp.savePath = savePath
83 return nil 93 return nil
84 } 94 }
85 95
96 // Read file session by sid.
97 // if file is not exist, create it.
98 // the file path is generated from sid string.
86 func (fp *FileProvider) SessionRead(sid string) (SessionStore, error) { 99 func (fp *FileProvider) SessionRead(sid string) (SessionStore, error) {
87 err := os.MkdirAll(path.Join(fp.savePath, string(sid[0]), string(sid[1])), 0777) 100 err := os.MkdirAll(path.Join(fp.savePath, string(sid[0]), string(sid[1])), 0777)
88 if err != nil { 101 if err != nil {
...@@ -117,6 +130,8 @@ func (fp *FileProvider) SessionRead(sid string) (SessionStore, error) { ...@@ -117,6 +130,8 @@ func (fp *FileProvider) SessionRead(sid string) (SessionStore, error) {
117 return ss, nil 130 return ss, nil
118 } 131 }
119 132
133 // Check file session exist.
134 // it checkes the file named from sid exist or not.
120 func (fp *FileProvider) SessionExist(sid string) bool { 135 func (fp *FileProvider) SessionExist(sid string) bool {
121 _, err := os.Stat(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid)) 136 _, err := os.Stat(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
122 if err == nil { 137 if err == nil {
...@@ -126,16 +141,20 @@ func (fp *FileProvider) SessionExist(sid string) bool { ...@@ -126,16 +141,20 @@ func (fp *FileProvider) SessionExist(sid string) bool {
126 } 141 }
127 } 142 }
128 143
144 // Remove all files in this save path
129 func (fp *FileProvider) SessionDestroy(sid string) error { 145 func (fp *FileProvider) SessionDestroy(sid string) error {
130 os.Remove(path.Join(fp.savePath)) 146 os.Remove(path.Join(fp.savePath))
131 return nil 147 return nil
132 } 148 }
133 149
150 // Recycle files in save path
134 func (fp *FileProvider) SessionGC() { 151 func (fp *FileProvider) SessionGC() {
135 gcmaxlifetime = fp.maxlifetime 152 gcmaxlifetime = fp.maxlifetime
136 filepath.Walk(fp.savePath, gcpath) 153 filepath.Walk(fp.savePath, gcpath)
137 } 154 }
138 155
156 // Get active file session number.
157 // it walks save path to count files.
139 func (fp *FileProvider) SessionAll() int { 158 func (fp *FileProvider) SessionAll() int {
140 a := &activeSession{} 159 a := &activeSession{}
141 err := filepath.Walk(fp.savePath, func(path string, f os.FileInfo, err error) error { 160 err := filepath.Walk(fp.savePath, func(path string, f os.FileInfo, err error) error {
...@@ -148,6 +167,8 @@ func (fp *FileProvider) SessionAll() int { ...@@ -148,6 +167,8 @@ func (fp *FileProvider) SessionAll() int {
148 return a.total 167 return a.total
149 } 168 }
150 169
170 // Generate new sid for file session.
171 // it delete old file and create new file named from new sid.
151 func (fp *FileProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) { 172 func (fp *FileProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) {
152 err := os.MkdirAll(path.Join(fp.savePath, string(oldsid[0]), string(oldsid[1])), 0777) 173 err := os.MkdirAll(path.Join(fp.savePath, string(oldsid[0]), string(oldsid[1])), 0777)
153 if err != nil { 174 if err != nil {
...@@ -197,6 +218,7 @@ func (fp *FileProvider) SessionRegenerate(oldsid, sid string) (SessionStore, err ...@@ -197,6 +218,7 @@ func (fp *FileProvider) SessionRegenerate(oldsid, sid string) (SessionStore, err
197 return ss, nil 218 return ss, nil
198 } 219 }
199 220
221 // remove file in save path if expired
200 func gcpath(path string, info os.FileInfo, err error) error { 222 func gcpath(path string, info os.FileInfo, err error) error {
201 if err != nil { 223 if err != nil {
202 return err 224 return err
......
...@@ -9,6 +9,8 @@ import ( ...@@ -9,6 +9,8 @@ import (
9 9
10 var mempder = &MemProvider{list: list.New(), sessions: make(map[string]*list.Element)} 10 var mempder = &MemProvider{list: list.New(), sessions: make(map[string]*list.Element)}
11 11
12 // memory session store.
13 // it saved sessions in a map in memory.
12 type MemSessionStore struct { 14 type MemSessionStore struct {
13 sid string //session id 15 sid string //session id
14 timeAccessed time.Time //last access time 16 timeAccessed time.Time //last access time
...@@ -16,6 +18,7 @@ type MemSessionStore struct { ...@@ -16,6 +18,7 @@ type MemSessionStore struct {
16 lock sync.RWMutex 18 lock sync.RWMutex
17 } 19 }
18 20
21 // set value to memory session
19 func (st *MemSessionStore) Set(key, value interface{}) error { 22 func (st *MemSessionStore) Set(key, value interface{}) error {
20 st.lock.Lock() 23 st.lock.Lock()
21 defer st.lock.Unlock() 24 defer st.lock.Unlock()
...@@ -23,6 +26,7 @@ func (st *MemSessionStore) Set(key, value interface{}) error { ...@@ -23,6 +26,7 @@ func (st *MemSessionStore) Set(key, value interface{}) error {
23 return nil 26 return nil
24 } 27 }
25 28
29 // get value from memory session by key
26 func (st *MemSessionStore) Get(key interface{}) interface{} { 30 func (st *MemSessionStore) Get(key interface{}) interface{} {
27 st.lock.RLock() 31 st.lock.RLock()
28 defer st.lock.RUnlock() 32 defer st.lock.RUnlock()
...@@ -34,6 +38,7 @@ func (st *MemSessionStore) Get(key interface{}) interface{} { ...@@ -34,6 +38,7 @@ func (st *MemSessionStore) Get(key interface{}) interface{} {
34 return nil 38 return nil
35 } 39 }
36 40
41 // delete in memory session by key
37 func (st *MemSessionStore) Delete(key interface{}) error { 42 func (st *MemSessionStore) Delete(key interface{}) error {
38 st.lock.Lock() 43 st.lock.Lock()
39 defer st.lock.Unlock() 44 defer st.lock.Unlock()
...@@ -41,6 +46,7 @@ func (st *MemSessionStore) Delete(key interface{}) error { ...@@ -41,6 +46,7 @@ func (st *MemSessionStore) Delete(key interface{}) error {
41 return nil 46 return nil
42 } 47 }
43 48
49 // clear all values in memory session
44 func (st *MemSessionStore) Flush() error { 50 func (st *MemSessionStore) Flush() error {
45 st.lock.Lock() 51 st.lock.Lock()
46 defer st.lock.Unlock() 52 defer st.lock.Unlock()
...@@ -48,27 +54,31 @@ func (st *MemSessionStore) Flush() error { ...@@ -48,27 +54,31 @@ func (st *MemSessionStore) Flush() error {
48 return nil 54 return nil
49 } 55 }
50 56
57 // get this id of memory session store
51 func (st *MemSessionStore) SessionID() string { 58 func (st *MemSessionStore) SessionID() string {
52 return st.sid 59 return st.sid
53 } 60 }
54 61
62 // Implement method, no used.
55 func (st *MemSessionStore) SessionRelease(w http.ResponseWriter) { 63 func (st *MemSessionStore) SessionRelease(w http.ResponseWriter) {
56 } 64 }
57 65
58 type MemProvider struct { 66 type MemProvider struct {
59 lock sync.RWMutex //用来锁 67 lock sync.RWMutex // locker
60 sessions map[string]*list.Element //用来存储在内存 68 sessions map[string]*list.Element // map in memory
61 list *list.List //用来做gc 69 list *list.List // for gc
62 maxlifetime int64 70 maxlifetime int64
63 savePath string 71 savePath string
64 } 72 }
65 73
74 // init memory session
66 func (pder *MemProvider) SessionInit(maxlifetime int64, savePath string) error { 75 func (pder *MemProvider) SessionInit(maxlifetime int64, savePath string) error {
67 pder.maxlifetime = maxlifetime 76 pder.maxlifetime = maxlifetime
68 pder.savePath = savePath 77 pder.savePath = savePath
69 return nil 78 return nil
70 } 79 }
71 80
81 // get memory session store by sid
72 func (pder *MemProvider) SessionRead(sid string) (SessionStore, error) { 82 func (pder *MemProvider) SessionRead(sid string) (SessionStore, error) {
73 pder.lock.RLock() 83 pder.lock.RLock()
74 if element, ok := pder.sessions[sid]; ok { 84 if element, ok := pder.sessions[sid]; ok {
...@@ -87,6 +97,7 @@ func (pder *MemProvider) SessionRead(sid string) (SessionStore, error) { ...@@ -87,6 +97,7 @@ func (pder *MemProvider) SessionRead(sid string) (SessionStore, error) {
87 return nil, nil 97 return nil, nil
88 } 98 }
89 99
100 // check session store exist in memory session by sid
90 func (pder *MemProvider) SessionExist(sid string) bool { 101 func (pder *MemProvider) SessionExist(sid string) bool {
91 pder.lock.RLock() 102 pder.lock.RLock()
92 defer pder.lock.RUnlock() 103 defer pder.lock.RUnlock()
...@@ -97,6 +108,7 @@ func (pder *MemProvider) SessionExist(sid string) bool { ...@@ -97,6 +108,7 @@ func (pder *MemProvider) SessionExist(sid string) bool {
97 } 108 }
98 } 109 }
99 110
111 // generate new sid for session store in memory session
100 func (pder *MemProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) { 112 func (pder *MemProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) {
101 pder.lock.RLock() 113 pder.lock.RLock()
102 if element, ok := pder.sessions[oldsid]; ok { 114 if element, ok := pder.sessions[oldsid]; ok {
...@@ -120,6 +132,7 @@ func (pder *MemProvider) SessionRegenerate(oldsid, sid string) (SessionStore, er ...@@ -120,6 +132,7 @@ func (pder *MemProvider) SessionRegenerate(oldsid, sid string) (SessionStore, er
120 return nil, nil 132 return nil, nil
121 } 133 }
122 134
135 // delete session store in memory session by id
123 func (pder *MemProvider) SessionDestroy(sid string) error { 136 func (pder *MemProvider) SessionDestroy(sid string) error {
124 pder.lock.Lock() 137 pder.lock.Lock()
125 defer pder.lock.Unlock() 138 defer pder.lock.Unlock()
...@@ -131,6 +144,7 @@ func (pder *MemProvider) SessionDestroy(sid string) error { ...@@ -131,6 +144,7 @@ func (pder *MemProvider) SessionDestroy(sid string) error {
131 return nil 144 return nil
132 } 145 }
133 146
147 // clean expired session stores in memory session
134 func (pder *MemProvider) SessionGC() { 148 func (pder *MemProvider) SessionGC() {
135 pder.lock.RLock() 149 pder.lock.RLock()
136 for { 150 for {
...@@ -152,10 +166,12 @@ func (pder *MemProvider) SessionGC() { ...@@ -152,10 +166,12 @@ func (pder *MemProvider) SessionGC() {
152 pder.lock.RUnlock() 166 pder.lock.RUnlock()
153 } 167 }
154 168
169 // get count number of memory session
155 func (pder *MemProvider) SessionAll() int { 170 func (pder *MemProvider) SessionAll() int {
156 return pder.list.Len() 171 return pder.list.Len()
157 } 172 }
158 173
174 // expand time of session store by id in memory session
159 func (pder *MemProvider) SessionUpdate(sid string) error { 175 func (pder *MemProvider) SessionUpdate(sid string) error {
160 pder.lock.Lock() 176 pder.lock.Lock()
161 defer pder.lock.Unlock() 177 defer pder.lock.Unlock()
......
1 package session 1 package session
2 2
3 //CREATE TABLE `session` ( 3 // mysql session support need create table as sql:
4 // CREATE TABLE `session` (
4 // `session_key` char(64) NOT NULL, 5 // `session_key` char(64) NOT NULL,
5 // `session_data` blob, 6 // session_data` blob,
6 // `session_expiry` int(11) unsigned NOT NULL, 7 // `session_expiry` int(11) unsigned NOT NULL,
7 // PRIMARY KEY (`session_key`) 8 // PRIMARY KEY (`session_key`)
8 //) ENGINE=MyISAM DEFAULT CHARSET=utf8; 9 // ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
9 10
10 import ( 11 import (
11 "database/sql" 12 "database/sql"
...@@ -18,6 +19,7 @@ import ( ...@@ -18,6 +19,7 @@ import (
18 19
19 var mysqlpder = &MysqlProvider{} 20 var mysqlpder = &MysqlProvider{}
20 21
22 // mysql session store
21 type MysqlSessionStore struct { 23 type MysqlSessionStore struct {
22 c *sql.DB 24 c *sql.DB
23 sid string 25 sid string
...@@ -25,6 +27,8 @@ type MysqlSessionStore struct { ...@@ -25,6 +27,8 @@ type MysqlSessionStore struct {
25 values map[interface{}]interface{} 27 values map[interface{}]interface{}
26 } 28 }
27 29
30 // set value in mysql session.
31 // it is temp value in map.
28 func (st *MysqlSessionStore) Set(key, value interface{}) error { 32 func (st *MysqlSessionStore) Set(key, value interface{}) error {
29 st.lock.Lock() 33 st.lock.Lock()
30 defer st.lock.Unlock() 34 defer st.lock.Unlock()
...@@ -32,6 +36,7 @@ func (st *MysqlSessionStore) Set(key, value interface{}) error { ...@@ -32,6 +36,7 @@ func (st *MysqlSessionStore) Set(key, value interface{}) error {
32 return nil 36 return nil
33 } 37 }
34 38
39 // get value from mysql session
35 func (st *MysqlSessionStore) Get(key interface{}) interface{} { 40 func (st *MysqlSessionStore) Get(key interface{}) interface{} {
36 st.lock.RLock() 41 st.lock.RLock()
37 defer st.lock.RUnlock() 42 defer st.lock.RUnlock()
...@@ -43,6 +48,7 @@ func (st *MysqlSessionStore) Get(key interface{}) interface{} { ...@@ -43,6 +48,7 @@ func (st *MysqlSessionStore) Get(key interface{}) interface{} {
43 return nil 48 return nil
44 } 49 }
45 50
51 // delete value in mysql session
46 func (st *MysqlSessionStore) Delete(key interface{}) error { 52 func (st *MysqlSessionStore) Delete(key interface{}) error {
47 st.lock.Lock() 53 st.lock.Lock()
48 defer st.lock.Unlock() 54 defer st.lock.Unlock()
...@@ -50,6 +56,7 @@ func (st *MysqlSessionStore) Delete(key interface{}) error { ...@@ -50,6 +56,7 @@ func (st *MysqlSessionStore) Delete(key interface{}) error {
50 return nil 56 return nil
51 } 57 }
52 58
59 // clear all values in mysql session
53 func (st *MysqlSessionStore) Flush() error { 60 func (st *MysqlSessionStore) Flush() error {
54 st.lock.Lock() 61 st.lock.Lock()
55 defer st.lock.Unlock() 62 defer st.lock.Unlock()
...@@ -57,10 +64,13 @@ func (st *MysqlSessionStore) Flush() error { ...@@ -57,10 +64,13 @@ func (st *MysqlSessionStore) Flush() error {
57 return nil 64 return nil
58 } 65 }
59 66
67 // get session id of this mysql session store
60 func (st *MysqlSessionStore) SessionID() string { 68 func (st *MysqlSessionStore) SessionID() string {
61 return st.sid 69 return st.sid
62 } 70 }
63 71
72 // save mysql session values to database.
73 // must call this method to save values to database.
64 func (st *MysqlSessionStore) SessionRelease(w http.ResponseWriter) { 74 func (st *MysqlSessionStore) SessionRelease(w http.ResponseWriter) {
65 defer st.c.Close() 75 defer st.c.Close()
66 b, err := encodeGob(st.values) 76 b, err := encodeGob(st.values)
...@@ -72,11 +82,13 @@ func (st *MysqlSessionStore) SessionRelease(w http.ResponseWriter) { ...@@ -72,11 +82,13 @@ func (st *MysqlSessionStore) SessionRelease(w http.ResponseWriter) {
72 82
73 } 83 }
74 84
85 // mysql session provider
75 type MysqlProvider struct { 86 type MysqlProvider struct {
76 maxlifetime int64 87 maxlifetime int64
77 savePath string 88 savePath string
78 } 89 }
79 90
91 // connect to mysql
80 func (mp *MysqlProvider) connectInit() *sql.DB { 92 func (mp *MysqlProvider) connectInit() *sql.DB {
81 db, e := sql.Open("mysql", mp.savePath) 93 db, e := sql.Open("mysql", mp.savePath)
82 if e != nil { 94 if e != nil {
...@@ -85,12 +97,15 @@ func (mp *MysqlProvider) connectInit() *sql.DB { ...@@ -85,12 +97,15 @@ func (mp *MysqlProvider) connectInit() *sql.DB {
85 return db 97 return db
86 } 98 }
87 99
100 // init mysql session.
101 // savepath is the connection string of mysql.
88 func (mp *MysqlProvider) SessionInit(maxlifetime int64, savePath string) error { 102 func (mp *MysqlProvider) SessionInit(maxlifetime int64, savePath string) error {
89 mp.maxlifetime = maxlifetime 103 mp.maxlifetime = maxlifetime
90 mp.savePath = savePath 104 mp.savePath = savePath
91 return nil 105 return nil
92 } 106 }
93 107
108 // get mysql session by sid
94 func (mp *MysqlProvider) SessionRead(sid string) (SessionStore, error) { 109 func (mp *MysqlProvider) SessionRead(sid string) (SessionStore, error) {
95 c := mp.connectInit() 110 c := mp.connectInit()
96 row := c.QueryRow("select session_data from session where session_key=?", sid) 111 row := c.QueryRow("select session_data from session where session_key=?", sid)
...@@ -113,6 +128,7 @@ func (mp *MysqlProvider) SessionRead(sid string) (SessionStore, error) { ...@@ -113,6 +128,7 @@ func (mp *MysqlProvider) SessionRead(sid string) (SessionStore, error) {
113 return rs, nil 128 return rs, nil
114 } 129 }
115 130
131 // check mysql session exist
116 func (mp *MysqlProvider) SessionExist(sid string) bool { 132 func (mp *MysqlProvider) SessionExist(sid string) bool {
117 c := mp.connectInit() 133 c := mp.connectInit()
118 defer c.Close() 134 defer c.Close()
...@@ -126,6 +142,7 @@ func (mp *MysqlProvider) SessionExist(sid string) bool { ...@@ -126,6 +142,7 @@ func (mp *MysqlProvider) SessionExist(sid string) bool {
126 } 142 }
127 } 143 }
128 144
145 // generate new sid for mysql session
129 func (mp *MysqlProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) { 146 func (mp *MysqlProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) {
130 c := mp.connectInit() 147 c := mp.connectInit()
131 row := c.QueryRow("select session_data from session where session_key=?", oldsid) 148 row := c.QueryRow("select session_data from session where session_key=?", oldsid)
...@@ -148,6 +165,7 @@ func (mp *MysqlProvider) SessionRegenerate(oldsid, sid string) (SessionStore, er ...@@ -148,6 +165,7 @@ func (mp *MysqlProvider) SessionRegenerate(oldsid, sid string) (SessionStore, er
148 return rs, nil 165 return rs, nil
149 } 166 }
150 167
168 // delete mysql session by sid
151 func (mp *MysqlProvider) SessionDestroy(sid string) error { 169 func (mp *MysqlProvider) SessionDestroy(sid string) error {
152 c := mp.connectInit() 170 c := mp.connectInit()
153 c.Exec("DELETE FROM session where session_key=?", sid) 171 c.Exec("DELETE FROM session where session_key=?", sid)
...@@ -155,6 +173,7 @@ func (mp *MysqlProvider) SessionDestroy(sid string) error { ...@@ -155,6 +173,7 @@ func (mp *MysqlProvider) SessionDestroy(sid string) error {
155 return nil 173 return nil
156 } 174 }
157 175
176 // delete expired values in mysql session
158 func (mp *MysqlProvider) SessionGC() { 177 func (mp *MysqlProvider) SessionGC() {
159 c := mp.connectInit() 178 c := mp.connectInit()
160 c.Exec("DELETE from session where session_expiry < ?", time.Now().Unix()-mp.maxlifetime) 179 c.Exec("DELETE from session where session_expiry < ?", time.Now().Unix()-mp.maxlifetime)
...@@ -162,6 +181,7 @@ func (mp *MysqlProvider) SessionGC() { ...@@ -162,6 +181,7 @@ func (mp *MysqlProvider) SessionGC() {
162 return 181 return
163 } 182 }
164 183
184 // count values in mysql session
165 func (mp *MysqlProvider) SessionAll() int { 185 func (mp *MysqlProvider) SessionAll() int {
166 c := mp.connectInit() 186 c := mp.connectInit()
167 defer c.Close() 187 defer c.Close()
......
...@@ -11,10 +11,12 @@ import ( ...@@ -11,10 +11,12 @@ import (
11 11
12 var redispder = &RedisProvider{} 12 var redispder = &RedisProvider{}
13 13
14 // redis max pool size
14 var MAX_POOL_SIZE = 100 15 var MAX_POOL_SIZE = 100
15 16
16 var redisPool chan redis.Conn 17 var redisPool chan redis.Conn
17 18
19 // redis session store
18 type RedisSessionStore struct { 20 type RedisSessionStore struct {
19 p *redis.Pool 21 p *redis.Pool
20 sid string 22 sid string
...@@ -23,6 +25,7 @@ type RedisSessionStore struct { ...@@ -23,6 +25,7 @@ type RedisSessionStore struct {
23 maxlifetime int64 25 maxlifetime int64
24 } 26 }
25 27
28 // set value in redis session
26 func (rs *RedisSessionStore) Set(key, value interface{}) error { 29 func (rs *RedisSessionStore) Set(key, value interface{}) error {
27 rs.lock.Lock() 30 rs.lock.Lock()
28 defer rs.lock.Unlock() 31 defer rs.lock.Unlock()
...@@ -30,6 +33,7 @@ func (rs *RedisSessionStore) Set(key, value interface{}) error { ...@@ -30,6 +33,7 @@ func (rs *RedisSessionStore) Set(key, value interface{}) error {
30 return nil 33 return nil
31 } 34 }
32 35
36 // get value in redis session
33 func (rs *RedisSessionStore) Get(key interface{}) interface{} { 37 func (rs *RedisSessionStore) Get(key interface{}) interface{} {
34 rs.lock.RLock() 38 rs.lock.RLock()
35 defer rs.lock.RUnlock() 39 defer rs.lock.RUnlock()
...@@ -41,6 +45,7 @@ func (rs *RedisSessionStore) Get(key interface{}) interface{} { ...@@ -41,6 +45,7 @@ func (rs *RedisSessionStore) Get(key interface{}) interface{} {
41 return nil 45 return nil
42 } 46 }
43 47
48 // delete value in redis session
44 func (rs *RedisSessionStore) Delete(key interface{}) error { 49 func (rs *RedisSessionStore) Delete(key interface{}) error {
45 rs.lock.Lock() 50 rs.lock.Lock()
46 defer rs.lock.Unlock() 51 defer rs.lock.Unlock()
...@@ -48,6 +53,7 @@ func (rs *RedisSessionStore) Delete(key interface{}) error { ...@@ -48,6 +53,7 @@ func (rs *RedisSessionStore) Delete(key interface{}) error {
48 return nil 53 return nil
49 } 54 }
50 55
56 // clear all values in redis session
51 func (rs *RedisSessionStore) Flush() error { 57 func (rs *RedisSessionStore) Flush() error {
52 rs.lock.Lock() 58 rs.lock.Lock()
53 defer rs.lock.Unlock() 59 defer rs.lock.Unlock()
...@@ -55,10 +61,12 @@ func (rs *RedisSessionStore) Flush() error { ...@@ -55,10 +61,12 @@ func (rs *RedisSessionStore) Flush() error {
55 return nil 61 return nil
56 } 62 }
57 63
64 // get redis session id
58 func (rs *RedisSessionStore) SessionID() string { 65 func (rs *RedisSessionStore) SessionID() string {
59 return rs.sid 66 return rs.sid
60 } 67 }
61 68
69 // save session values to redis
62 func (rs *RedisSessionStore) SessionRelease(w http.ResponseWriter) { 70 func (rs *RedisSessionStore) SessionRelease(w http.ResponseWriter) {
63 c := rs.p.Get() 71 c := rs.p.Get()
64 defer c.Close() 72 defer c.Close()
...@@ -77,6 +85,7 @@ func (rs *RedisSessionStore) SessionRelease(w http.ResponseWriter) { ...@@ -77,6 +85,7 @@ func (rs *RedisSessionStore) SessionRelease(w http.ResponseWriter) {
77 c.Do("SET", rs.sid, string(b), "EX", rs.maxlifetime) 85 c.Do("SET", rs.sid, string(b), "EX", rs.maxlifetime)
78 } 86 }
79 87
88 // redis session provider
80 type RedisProvider struct { 89 type RedisProvider struct {
81 maxlifetime int64 90 maxlifetime int64
82 savePath string 91 savePath string
...@@ -85,8 +94,9 @@ type RedisProvider struct { ...@@ -85,8 +94,9 @@ type RedisProvider struct {
85 poollist *redis.Pool 94 poollist *redis.Pool
86 } 95 }
87 96
88 //savepath like redisserveraddr,poolsize,password 97 // init redis session
89 //127.0.0.1:6379,100,astaxie 98 // savepath like redis server addr,pool size,password
99 // e.g. 127.0.0.1:6379,100,astaxie
90 func (rp *RedisProvider) SessionInit(maxlifetime int64, savePath string) error { 100 func (rp *RedisProvider) SessionInit(maxlifetime int64, savePath string) error {
91 rp.maxlifetime = maxlifetime 101 rp.maxlifetime = maxlifetime
92 configs := strings.Split(savePath, ",") 102 configs := strings.Split(savePath, ",")
...@@ -122,6 +132,7 @@ func (rp *RedisProvider) SessionInit(maxlifetime int64, savePath string) error { ...@@ -122,6 +132,7 @@ func (rp *RedisProvider) SessionInit(maxlifetime int64, savePath string) error {
122 return nil 132 return nil
123 } 133 }
124 134
135 // read redis session by sid
125 func (rp *RedisProvider) SessionRead(sid string) (SessionStore, error) { 136 func (rp *RedisProvider) SessionRead(sid string) (SessionStore, error) {
126 c := rp.poollist.Get() 137 c := rp.poollist.Get()
127 defer c.Close() 138 defer c.Close()
...@@ -141,6 +152,7 @@ func (rp *RedisProvider) SessionRead(sid string) (SessionStore, error) { ...@@ -141,6 +152,7 @@ func (rp *RedisProvider) SessionRead(sid string) (SessionStore, error) {
141 return rs, nil 152 return rs, nil
142 } 153 }
143 154
155 // check redis session exist by sid
144 func (rp *RedisProvider) SessionExist(sid string) bool { 156 func (rp *RedisProvider) SessionExist(sid string) bool {
145 c := rp.poollist.Get() 157 c := rp.poollist.Get()
146 defer c.Close() 158 defer c.Close()
...@@ -152,6 +164,7 @@ func (rp *RedisProvider) SessionExist(sid string) bool { ...@@ -152,6 +164,7 @@ func (rp *RedisProvider) SessionExist(sid string) bool {
152 } 164 }
153 } 165 }
154 166
167 // generate new sid for redis session
155 func (rp *RedisProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) { 168 func (rp *RedisProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) {
156 c := rp.poollist.Get() 169 c := rp.poollist.Get()
157 defer c.Close() 170 defer c.Close()
...@@ -181,6 +194,7 @@ func (rp *RedisProvider) SessionRegenerate(oldsid, sid string) (SessionStore, er ...@@ -181,6 +194,7 @@ func (rp *RedisProvider) SessionRegenerate(oldsid, sid string) (SessionStore, er
181 return rs, nil 194 return rs, nil
182 } 195 }
183 196
197 // delete redis session by id
184 func (rp *RedisProvider) SessionDestroy(sid string) error { 198 func (rp *RedisProvider) SessionDestroy(sid string) error {
185 c := rp.poollist.Get() 199 c := rp.poollist.Get()
186 defer c.Close() 200 defer c.Close()
...@@ -189,11 +203,12 @@ func (rp *RedisProvider) SessionDestroy(sid string) error { ...@@ -189,11 +203,12 @@ func (rp *RedisProvider) SessionDestroy(sid string) error {
189 return nil 203 return nil
190 } 204 }
191 205
206 // Impelment method, no used.
192 func (rp *RedisProvider) SessionGC() { 207 func (rp *RedisProvider) SessionGC() {
193 return 208 return
194 } 209 }
195 210
196 //@todo 211 // @todo
197 func (rp *RedisProvider) SessionAll() int { 212 func (rp *RedisProvider) SessionAll() int {
198 return 0 213 return 0
199 } 214 }
......
...@@ -14,6 +14,7 @@ import ( ...@@ -14,6 +14,7 @@ import (
14 "time" 14 "time"
15 ) 15 )
16 16
17 // SessionStore contains all data for one session process with specific id.
17 type SessionStore interface { 18 type SessionStore interface {
18 Set(key, value interface{}) error //set session value 19 Set(key, value interface{}) error //set session value
19 Get(key interface{}) interface{} //get session value 20 Get(key interface{}) interface{} //get session value
...@@ -23,6 +24,8 @@ type SessionStore interface { ...@@ -23,6 +24,8 @@ type SessionStore interface {
23 Flush() error //delete all data 24 Flush() error //delete all data
24 } 25 }
25 26
27 // Provider contains global session methods and saved SessionStores.
28 // it can operate a SessionStore by its id.
26 type Provider interface { 29 type Provider interface {
27 SessionInit(gclifetime int64, config string) error 30 SessionInit(gclifetime int64, config string) error
28 SessionRead(sid string) (SessionStore, error) 31 SessionRead(sid string) (SessionStore, error)
...@@ -61,16 +64,24 @@ type managerConfig struct { ...@@ -61,16 +64,24 @@ type managerConfig struct {
61 ProviderConfig string `json:"providerConfig"` 64 ProviderConfig string `json:"providerConfig"`
62 } 65 }
63 66
67 // Manager contains Provider and its configuration.
64 type Manager struct { 68 type Manager struct {
65 provider Provider 69 provider Provider
66 config *managerConfig 70 config *managerConfig
67 } 71 }
68 72
69 //options 73 // Create new Manager with provider name and json config string.
70 //1. is https default false 74 // provider name:
71 //2. hashfunc default sha1 75 // 1. cookie
72 //3. hashkey default beegosessionkey 76 // 2. file
73 //4. maxage default is none 77 // 3. memory
78 // 4. redis
79 // 5. mysql
80 // json config:
81 // 1. is https default false
82 // 2. hashfunc default sha1
83 // 3. hashkey default beegosessionkey
84 // 4. maxage default is none
74 func NewManager(provideName, config string) (*Manager, error) { 85 func NewManager(provideName, config string) (*Manager, error) {
75 provider, ok := provides[provideName] 86 provider, ok := provides[provideName]
76 if !ok { 87 if !ok {
...@@ -102,7 +113,8 @@ func NewManager(provideName, config string) (*Manager, error) { ...@@ -102,7 +113,8 @@ func NewManager(provideName, config string) (*Manager, error) {
102 }, nil 113 }, nil
103 } 114 }
104 115
105 //get Session 116 // Start session. generate or read the session id from http request.
117 // if session id exists, return SessionStore with this id.
106 func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (session SessionStore) { 118 func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (session SessionStore) {
107 cookie, err := r.Cookie(manager.config.CookieName) 119 cookie, err := r.Cookie(manager.config.CookieName)
108 if err != nil || cookie.Value == "" { 120 if err != nil || cookie.Value == "" {
...@@ -144,7 +156,7 @@ func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (se ...@@ -144,7 +156,7 @@ func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (se
144 return 156 return
145 } 157 }
146 158
147 //Destroy sessionid 159 // Destroy session by its id in http request cookie.
148 func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) { 160 func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) {
149 cookie, err := r.Cookie(manager.config.CookieName) 161 cookie, err := r.Cookie(manager.config.CookieName)
150 if err != nil || cookie.Value == "" { 162 if err != nil || cookie.Value == "" {
...@@ -161,16 +173,20 @@ func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) { ...@@ -161,16 +173,20 @@ func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) {
161 } 173 }
162 } 174 }
163 175
176 // Get SessionStore by its id.
164 func (manager *Manager) GetProvider(sid string) (sessions SessionStore, err error) { 177 func (manager *Manager) GetProvider(sid string) (sessions SessionStore, err error) {
165 sessions, err = manager.provider.SessionRead(sid) 178 sessions, err = manager.provider.SessionRead(sid)
166 return 179 return
167 } 180 }
168 181
182 // Start session gc process.
183 // it can do gc in times after gc lifetime.
169 func (manager *Manager) GC() { 184 func (manager *Manager) GC() {
170 manager.provider.SessionGC() 185 manager.provider.SessionGC()
171 time.AfterFunc(time.Duration(manager.config.Gclifetime)*time.Second, func() { manager.GC() }) 186 time.AfterFunc(time.Duration(manager.config.Gclifetime)*time.Second, func() { manager.GC() })
172 } 187 }
173 188
189 // Regenerate a session id for this SessionStore who's id is saving in http request.
174 func (manager *Manager) SessionRegenerateId(w http.ResponseWriter, r *http.Request) (session SessionStore) { 190 func (manager *Manager) SessionRegenerateId(w http.ResponseWriter, r *http.Request) (session SessionStore) {
175 sid := manager.sessionId(r) 191 sid := manager.sessionId(r)
176 cookie, err := r.Cookie(manager.config.CookieName) 192 cookie, err := r.Cookie(manager.config.CookieName)
...@@ -198,20 +214,23 @@ func (manager *Manager) SessionRegenerateId(w http.ResponseWriter, r *http.Reque ...@@ -198,20 +214,23 @@ func (manager *Manager) SessionRegenerateId(w http.ResponseWriter, r *http.Reque
198 return 214 return
199 } 215 }
200 216
217 // Get all active sessions count number.
201 func (manager *Manager) GetActiveSession() int { 218 func (manager *Manager) GetActiveSession() int {
202 return manager.provider.SessionAll() 219 return manager.provider.SessionAll()
203 } 220 }
204 221
222 // Set hash function for generating session id.
205 func (manager *Manager) SetHashFunc(hasfunc, hashkey string) { 223 func (manager *Manager) SetHashFunc(hasfunc, hashkey string) {
206 manager.config.SessionIDHashFunc = hasfunc 224 manager.config.SessionIDHashFunc = hasfunc
207 manager.config.SessionIDHashKey = hashkey 225 manager.config.SessionIDHashKey = hashkey
208 } 226 }
209 227
228 // Set cookie with https.
210 func (manager *Manager) SetSecure(secure bool) { 229 func (manager *Manager) SetSecure(secure bool) {
211 manager.config.Secure = secure 230 manager.config.Secure = secure
212 } 231 }
213 232
214 //remote_addr cruunixnano randdata 233 // generate session id with rand string, unix nano time, remote addr by hash function.
215 func (manager *Manager) sessionId(r *http.Request) (sid string) { 234 func (manager *Manager) sessionId(r *http.Request) (sid string) {
216 bs := make([]byte, 24) 235 bs := make([]byte, 24)
217 if _, err := io.ReadFull(rand.Reader, bs); err != nil { 236 if _, err := io.ReadFull(rand.Reader, bs); err != nil {
......
...@@ -29,16 +29,13 @@ type pointerInfo struct { ...@@ -29,16 +29,13 @@ type pointerInfo struct {
29 used []int 29 used []int
30 } 30 }
31 31
32 //
33 // print the data in console 32 // print the data in console
34 //
35 func Display(data ...interface{}) { 33 func Display(data ...interface{}) {
36 display(true, data...) 34 display(true, data...)
37 } 35 }
38 36
39 // 37
40 // return string 38 // return data print string
41 //
42 func GetDisplayString(data ...interface{}) string { 39 func GetDisplayString(data ...interface{}) string {
43 return display(false, data...) 40 return display(false, data...)
44 } 41 }
...@@ -67,9 +64,7 @@ func display(displayed bool, data ...interface{}) string { ...@@ -67,9 +64,7 @@ func display(displayed bool, data ...interface{}) string {
67 return buf.String() 64 return buf.String()
68 } 65 }
69 66
70 // 67 // return data dump and format bytes
71 // return fomateinfo
72 //
73 func fomateinfo(headlen int, data ...interface{}) []byte { 68 func fomateinfo(headlen int, data ...interface{}) []byte {
74 var buf = new(bytes.Buffer) 69 var buf = new(bytes.Buffer)
75 70
...@@ -108,6 +103,7 @@ func fomateinfo(headlen int, data ...interface{}) []byte { ...@@ -108,6 +103,7 @@ func fomateinfo(headlen int, data ...interface{}) []byte {
108 return buf.Bytes() 103 return buf.Bytes()
109 } 104 }
110 105
106 // check data is golang basic type
111 func isSimpleType(val reflect.Value, kind reflect.Kind, pointers **pointerInfo, interfaces *[]reflect.Value) bool { 107 func isSimpleType(val reflect.Value, kind reflect.Kind, pointers **pointerInfo, interfaces *[]reflect.Value) bool {
112 switch kind { 108 switch kind {
113 case reflect.Bool: 109 case reflect.Bool:
...@@ -158,6 +154,7 @@ func isSimpleType(val reflect.Value, kind reflect.Kind, pointers **pointerInfo, ...@@ -158,6 +154,7 @@ func isSimpleType(val reflect.Value, kind reflect.Kind, pointers **pointerInfo,
158 return false 154 return false
159 } 155 }
160 156
157 // dump value
161 func printKeyValue(buf *bytes.Buffer, val reflect.Value, pointers **pointerInfo, interfaces *[]reflect.Value, structFilter func(string, string) bool, formatOutput bool, indent string, level int) { 158 func printKeyValue(buf *bytes.Buffer, val reflect.Value, pointers **pointerInfo, interfaces *[]reflect.Value, structFilter func(string, string) bool, formatOutput bool, indent string, level int) {
162 var t = val.Kind() 159 var t = val.Kind()
163 160
...@@ -367,6 +364,7 @@ func printKeyValue(buf *bytes.Buffer, val reflect.Value, pointers **pointerInfo, ...@@ -367,6 +364,7 @@ func printKeyValue(buf *bytes.Buffer, val reflect.Value, pointers **pointerInfo,
367 } 364 }
368 } 365 }
369 366
367 // dump pointer value
370 func printPointerInfo(buf *bytes.Buffer, headlen int, pointers *pointerInfo) { 368 func printPointerInfo(buf *bytes.Buffer, headlen int, pointers *pointerInfo) {
371 var anyused = false 369 var anyused = false
372 var pointerNum = 0 370 var pointerNum = 0
...@@ -434,9 +432,7 @@ func printPointerInfo(buf *bytes.Buffer, headlen int, pointers *pointerInfo) { ...@@ -434,9 +432,7 @@ func printPointerInfo(buf *bytes.Buffer, headlen int, pointers *pointerInfo) {
434 } 432 }
435 } 433 }
436 434
437 // 435 // get stack bytes
438 // get stack info
439 //
440 func stack(skip int, indent string) []byte { 436 func stack(skip int, indent string) []byte {
441 var buf = new(bytes.Buffer) 437 var buf = new(bytes.Buffer)
442 438
...@@ -455,7 +451,7 @@ func stack(skip int, indent string) []byte { ...@@ -455,7 +451,7 @@ func stack(skip int, indent string) []byte {
455 return buf.Bytes() 451 return buf.Bytes()
456 } 452 }
457 453
458 // function returns, if possible, the name of the function containing the PC. 454 // return the name of the function containing the PC if possible,
459 func function(pc uintptr) []byte { 455 func function(pc uintptr) []byte {
460 fn := runtime.FuncForPC(pc) 456 fn := runtime.FuncForPC(pc)
461 if fn == nil { 457 if fn == nil {
......
...@@ -13,12 +13,15 @@ package toolbox ...@@ -13,12 +13,15 @@ package toolbox
13 13
14 //AddHealthCheck("database",&DatabaseCheck{}) 14 //AddHealthCheck("database",&DatabaseCheck{})
15 15
16 // health checker map
16 var AdminCheckList map[string]HealthChecker 17 var AdminCheckList map[string]HealthChecker
17 18
19 // health checker interface
18 type HealthChecker interface { 20 type HealthChecker interface {
19 Check() error 21 Check() error
20 } 22 }
21 23
24 // add health checker with name string
22 func AddHealthCheck(name string, hc HealthChecker) { 25 func AddHealthCheck(name string, hc HealthChecker) {
23 AdminCheckList[name] = hc 26 AdminCheckList[name] = hc
24 } 27 }
......
...@@ -19,6 +19,7 @@ func init() { ...@@ -19,6 +19,7 @@ func init() {
19 pid = os.Getpid() 19 pid = os.Getpid()
20 } 20 }
21 21
22 // parse input command string
22 func ProcessInput(input string, w io.Writer) { 23 func ProcessInput(input string, w io.Writer) {
23 switch input { 24 switch input {
24 case "lookup goroutine": 25 case "lookup goroutine":
...@@ -44,6 +45,7 @@ func ProcessInput(input string, w io.Writer) { ...@@ -44,6 +45,7 @@ func ProcessInput(input string, w io.Writer) {
44 } 45 }
45 } 46 }
46 47
48 // record memory profile in pprof
47 func MemProf() { 49 func MemProf() {
48 if f, err := os.Create("mem-" + strconv.Itoa(pid) + ".memprof"); err != nil { 50 if f, err := os.Create("mem-" + strconv.Itoa(pid) + ".memprof"); err != nil {
49 log.Fatal("record memory profile failed: %v", err) 51 log.Fatal("record memory profile failed: %v", err)
...@@ -54,6 +56,7 @@ func MemProf() { ...@@ -54,6 +56,7 @@ func MemProf() {
54 } 56 }
55 } 57 }
56 58
59 // start cpu profile monitor
57 func StartCPUProfile() { 60 func StartCPUProfile() {
58 f, err := os.Create("cpu-" + strconv.Itoa(pid) + ".pprof") 61 f, err := os.Create("cpu-" + strconv.Itoa(pid) + ".pprof")
59 if err != nil { 62 if err != nil {
...@@ -62,10 +65,12 @@ func StartCPUProfile() { ...@@ -62,10 +65,12 @@ func StartCPUProfile() {
62 pprof.StartCPUProfile(f) 65 pprof.StartCPUProfile(f)
63 } 66 }
64 67
68 // stop cpu profile monitor
65 func StopCPUProfile() { 69 func StopCPUProfile() {
66 pprof.StopCPUProfile() 70 pprof.StopCPUProfile()
67 } 71 }
68 72
73 // print gc information to io.Writer
69 func PrintGCSummary(w io.Writer) { 74 func PrintGCSummary(w io.Writer) {
70 memStats := &runtime.MemStats{} 75 memStats := &runtime.MemStats{}
71 runtime.ReadMemStats(memStats) 76 runtime.ReadMemStats(memStats)
...@@ -114,7 +119,7 @@ func avg(items []time.Duration) time.Duration { ...@@ -114,7 +119,7 @@ func avg(items []time.Duration) time.Duration {
114 return time.Duration(int64(sum) / int64(len(items))) 119 return time.Duration(int64(sum) / int64(len(items)))
115 } 120 }
116 121
117 // human readable format 122 // format bytes number friendly
118 func toH(bytes uint64) string { 123 func toH(bytes uint64) string {
119 switch { 124 switch {
120 case bytes < 1024: 125 case bytes < 1024:
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
7 "time" 7 "time"
8 ) 8 )
9 9
10 // Statistics struct
10 type Statistics struct { 11 type Statistics struct {
11 RequestUrl string 12 RequestUrl string
12 RequestController string 13 RequestController string
...@@ -16,12 +17,15 @@ type Statistics struct { ...@@ -16,12 +17,15 @@ type Statistics struct {
16 TotalTime time.Duration 17 TotalTime time.Duration
17 } 18 }
18 19
20 // UrlMap contains several statistics struct to log different data
19 type UrlMap struct { 21 type UrlMap struct {
20 lock sync.RWMutex 22 lock sync.RWMutex
21 LengthLimit int //limit the urlmap's length if it's equal to 0 there's no limit 23 LengthLimit int //limit the urlmap's length if it's equal to 0 there's no limit
22 urlmap map[string]map[string]*Statistics 24 urlmap map[string]map[string]*Statistics
23 } 25 }
24 26
27 // add statistics task.
28 // it needs request method, request url, request controller and statistics time duration
25 func (m *UrlMap) AddStatistics(requestMethod, requestUrl, requestController string, requesttime time.Duration) { 29 func (m *UrlMap) AddStatistics(requestMethod, requestUrl, requestController string, requesttime time.Duration) {
26 m.lock.Lock() 30 m.lock.Lock()
27 defer m.lock.Unlock() 31 defer m.lock.Unlock()
...@@ -65,6 +69,7 @@ func (m *UrlMap) AddStatistics(requestMethod, requestUrl, requestController stri ...@@ -65,6 +69,7 @@ func (m *UrlMap) AddStatistics(requestMethod, requestUrl, requestController stri
65 } 69 }
66 } 70 }
67 71
72 // put url statistics result in io.Writer
68 func (m *UrlMap) GetMap(rw io.Writer) { 73 func (m *UrlMap) GetMap(rw io.Writer) {
69 m.lock.RLock() 74 m.lock.RLock()
70 defer m.lock.RUnlock() 75 defer m.lock.RUnlock()
...@@ -78,6 +83,7 @@ func (m *UrlMap) GetMap(rw io.Writer) { ...@@ -78,6 +83,7 @@ func (m *UrlMap) GetMap(rw io.Writer) {
78 } 83 }
79 } 84 }
80 85
86 // global statistics data map
81 var StatisticsMap *UrlMap 87 var StatisticsMap *UrlMap
82 88
83 func init() { 89 func init() {
......
...@@ -53,6 +53,7 @@ const ( ...@@ -53,6 +53,7 @@ const (
53 starBit = 1 << 63 53 starBit = 1 << 63
54 ) 54 )
55 55
56 // time taks schedule
56 type Schedule struct { 57 type Schedule struct {
57 Second uint64 58 Second uint64
58 Minute uint64 59 Minute uint64
...@@ -62,8 +63,10 @@ type Schedule struct { ...@@ -62,8 +63,10 @@ type Schedule struct {
62 Week uint64 63 Week uint64
63 } 64 }
64 65
66 // task func type
65 type TaskFunc func() error 67 type TaskFunc func() error
66 68
69 // task interface
67 type Tasker interface { 70 type Tasker interface {
68 GetStatus() string 71 GetStatus() string
69 Run() error 72 Run() error
...@@ -73,21 +76,24 @@ type Tasker interface { ...@@ -73,21 +76,24 @@ type Tasker interface {
73 GetPrev() time.Time 76 GetPrev() time.Time
74 } 77 }
75 78
79 // task error
76 type taskerr struct { 80 type taskerr struct {
77 t time.Time 81 t time.Time
78 errinfo string 82 errinfo string
79 } 83 }
80 84
85 // task struct
81 type Task struct { 86 type Task struct {
82 Taskname string 87 Taskname string
83 Spec *Schedule 88 Spec *Schedule
84 DoFunc TaskFunc 89 DoFunc TaskFunc
85 Prev time.Time 90 Prev time.Time
86 Next time.Time 91 Next time.Time
87 Errlist []*taskerr //errtime:errinfo 92 Errlist []*taskerr // like errtime:errinfo
88 ErrLimit int //max length for the errlist 0 stand for there' no limit 93 ErrLimit int // max length for the errlist, 0 stand for no limit
89 } 94 }
90 95
96 // add new task with name, time and func
91 func NewTask(tname string, spec string, f TaskFunc) *Task { 97 func NewTask(tname string, spec string, f TaskFunc) *Task {
92 98
93 task := &Task{ 99 task := &Task{
...@@ -99,6 +105,7 @@ func NewTask(tname string, spec string, f TaskFunc) *Task { ...@@ -99,6 +105,7 @@ func NewTask(tname string, spec string, f TaskFunc) *Task {
99 return task 105 return task
100 } 106 }
101 107
108 // get current task status
102 func (tk *Task) GetStatus() string { 109 func (tk *Task) GetStatus() string {
103 var str string 110 var str string
104 for _, v := range tk.Errlist { 111 for _, v := range tk.Errlist {
...@@ -107,6 +114,7 @@ func (tk *Task) GetStatus() string { ...@@ -107,6 +114,7 @@ func (tk *Task) GetStatus() string {
107 return str 114 return str
108 } 115 }
109 116
117 // run task
110 func (tk *Task) Run() error { 118 func (tk *Task) Run() error {
111 err := tk.DoFunc() 119 err := tk.DoFunc()
112 if err != nil { 120 if err != nil {
...@@ -117,53 +125,58 @@ func (tk *Task) Run() error { ...@@ -117,53 +125,58 @@ func (tk *Task) Run() error {
117 return err 125 return err
118 } 126 }
119 127
128 // set next time for this task
120 func (tk *Task) SetNext(now time.Time) { 129 func (tk *Task) SetNext(now time.Time) {
121 tk.Next = tk.Spec.Next(now) 130 tk.Next = tk.Spec.Next(now)
122 } 131 }
123 132
133 // get the next call time of this task
124 func (tk *Task) GetNext() time.Time { 134 func (tk *Task) GetNext() time.Time {
125 return tk.Next 135 return tk.Next
126 } 136 }
137
138 // set prev time of this task
127 func (tk *Task) SetPrev(now time.Time) { 139 func (tk *Task) SetPrev(now time.Time) {
128 tk.Prev = now 140 tk.Prev = now
129 } 141 }
130 142
143 // get prev time of this task
131 func (tk *Task) GetPrev() time.Time { 144 func (tk *Task) GetPrev() time.Time {
132 return tk.Prev 145 return tk.Prev
133 } 146 }
134 147
135 //前6个字段分别表示 148 // six columns mean
136 // 秒钟:0-59 149 // second:0-59
137 // 分钟:0-59 150 // minute:0-59
138 // 小时:1-23 151 // hour:1-23
139 // 日期:1-31 152 // day:1-31
140 // 月份:1-12 153 // month:1-12
141 // 星期:0-6(0表示周日 154 // week:0-6(0 means Sunday
142 155
143 //还可以用一些特殊符号 156 // some signals
144 // *: 表示任何时刻 157 // *: any time
145 // ,: 表示分割,如第三段里:2,4,表示2点和4点执行 158 // ,:  separate signal
146 //   -:表示一个段,如第三端里: 1-5,就表示1到5点 159 //   -:duration
147 // /n : 表示每个n的单位执行一次,如第三段里,*/1, 就表示每隔1个小时执行一次命令。也可以写成1-23/1. 160 // /n : do as n times of time duration
148 ///////////////////////////////////////////////////////// 161 /////////////////////////////////////////////////////////
149 // 0/30 * * * * * 每30秒 执行 162 // 0/30 * * * * * every 30s
150 // 0 43 21 * * * 21:43 执行 163 // 0 43 21 * * * 21:43
151 // 0 15 05 * * *    05:15 执行 164 // 0 15 05 * * *    05:15
152 // 0 0 17 * * * 17:00 执行 165 // 0 0 17 * * * 17:00
153 // 0 0 17 * * 1 每周一的 17:00 执行 166 // 0 0 17 * * 1 17:00 in every Monday
154 // 0 0,10 17 * * 0,2,3 每周日,周二,周三的 17:00和 17:10 执行 167 // 0 0,10 17 * * 0,2,3 17:00 and 17:10 in every Sunday, Tuesday and Wednesday
155 // 0 0-10 17 1 * * 毎月1日从 17:00到7:10 毎隔1分钟 执行 168 // 0 0-10 17 1 * * 17:00 to 17:10 in 1 min duration each time on the first day of month
156 // 0 0 0 1,15 * 1 毎月1日和 15日和 一日的 0:00 执行 169 // 0 0 0 1,15 * 1 0:00 on the 1st day and 15th day of month
157 // 0 42 4 1 * *     毎月1日的 4:42分 执行 170 // 0 42 4 1 * *     4:42 on the 1st day of month
158 // 0 0 21 * * 1-6   周一到周六 21:00 执行 171 // 0 0 21 * * 1-6   21:00 from Monday to Saturday
159 // 0 0,10,20,30,40,50 * * * *  每隔10分 执行 172 // 0 0,10,20,30,40,50 * * * *  every 10 min duration
160 // 0 */10 * * * *        每隔10分 执行 173 // 0 */10 * * * *        every 10 min duration
161 // 0 * 1 * * *         从1:0到1:59 每隔1分钟 执行 174 // 0 * 1 * * *         1:00 to 1:59 in 1 min duration each time
162 // 0 0 1 * * *         1:00 执行 175 // 0 0 1 * * *         1:00
163 // 0 0 */1 * * *        毎时0分 每隔1小时 执行 176 // 0 0 */1 * * *        0 min of hour in 1 hour duration
164 // 0 0 * * * *         毎时0分 每隔1小时 执行 177 // 0 0 * * * *         0 min of hour in 1 hour duration
165 // 0 2 8-20/3 * * *       8:02,11:02,14:02,17:02,20:02 执行 178 // 0 2 8-20/3 * * *       8:02, 11:02, 14:02, 17:02, 20:02
166 // 0 30 5 1,15 * *       1日 和 15日的 5:30 执行 179 // 0 30 5 1,15 * *       5:30 on the 1st day and 15th day of month
167 func (t *Task) SetCron(spec string) { 180 func (t *Task) SetCron(spec string) {
168 t.Spec = t.parse(spec) 181 t.Spec = t.parse(spec)
169 } 182 }
...@@ -252,6 +265,7 @@ func (t *Task) parseSpec(spec string) *Schedule { ...@@ -252,6 +265,7 @@ func (t *Task) parseSpec(spec string) *Schedule {
252 return nil 265 return nil
253 } 266 }
254 267
268 // set schedule to next time
255 func (s *Schedule) Next(t time.Time) time.Time { 269 func (s *Schedule) Next(t time.Time) time.Time {
256 270
257 // Start at the earliest possible time (the upcoming second). 271 // Start at the earliest possible time (the upcoming second).
...@@ -349,6 +363,7 @@ func dayMatches(s *Schedule, t time.Time) bool { ...@@ -349,6 +363,7 @@ func dayMatches(s *Schedule, t time.Time) bool {
349 return domMatch || dowMatch 363 return domMatch || dowMatch
350 } 364 }
351 365
366 // start all tasks
352 func StartTask() { 367 func StartTask() {
353 go run() 368 go run()
354 } 369 }
...@@ -388,20 +403,23 @@ func run() { ...@@ -388,20 +403,23 @@ func run() {
388 } 403 }
389 } 404 }
390 405
406 // start all tasks
391 func StopTask() { 407 func StopTask() {
392 stop <- true 408 stop <- true
393 } 409 }
394 410
411 // add task with name
395 func AddTask(taskname string, t Tasker) { 412 func AddTask(taskname string, t Tasker) {
396 AdminTaskList[taskname] = t 413 AdminTaskList[taskname] = t
397 } 414 }
398 415
399 //sort map for tasker 416 // sort map for tasker
400 type MapSorter struct { 417 type MapSorter struct {
401 Keys []string 418 Keys []string
402 Vals []Tasker 419 Vals []Tasker
403 } 420 }
404 421
422 // create new tasker map
405 func NewMapSorter(m map[string]Tasker) *MapSorter { 423 func NewMapSorter(m map[string]Tasker) *MapSorter {
406 ms := &MapSorter{ 424 ms := &MapSorter{
407 Keys: make([]string, 0, len(m)), 425 Keys: make([]string, 0, len(m)),
...@@ -414,6 +432,7 @@ func NewMapSorter(m map[string]Tasker) *MapSorter { ...@@ -414,6 +432,7 @@ func NewMapSorter(m map[string]Tasker) *MapSorter {
414 return ms 432 return ms
415 } 433 }
416 434
435 // sort tasker map
417 func (ms *MapSorter) Sort() { 436 func (ms *MapSorter) Sort() {
418 sort.Sort(ms) 437 sort.Sort(ms)
419 } 438 }
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!