Merge pull request #490 from fuxiaohei/develop
add comments for session and toolbox package
Showing
11 changed files
with
213 additions
and
67 deletions
| ... | @@ -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 | // `session_key` char(64) NOT NULL, | 4 | // CREATE TABLE `session` ( |
| 5 | // `session_data` blob, | 5 | // `session_key` char(64) NOT NULL, |
| 6 | // `session_expiry` int(11) unsigned NOT NULL, | 6 | // session_data` blob, |
| 7 | // PRIMARY KEY (`session_key`) | 7 | // `session_expiry` int(11) unsigned NOT NULL, |
| 8 | //) ENGINE=MyISAM DEFAULT CHARSET=utf8; | 8 | // PRIMARY KEY (`session_key`) |
| 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 | } | ... | ... |
-
Please register or sign in to post a comment