github.com/astaxie/beego@v1.12.3/session/sess_mem.go (about)

     1  // Copyright 2014 beego Author. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package session
    16  
    17  import (
    18  	"container/list"
    19  	"net/http"
    20  	"sync"
    21  	"time"
    22  )
    23  
    24  var mempder = &MemProvider{list: list.New(), sessions: make(map[string]*list.Element)}
    25  
    26  // MemSessionStore memory session store.
    27  // it saved sessions in a map in memory.
    28  type MemSessionStore struct {
    29  	sid          string                      //session id
    30  	timeAccessed time.Time                   //last access time
    31  	value        map[interface{}]interface{} //session store
    32  	lock         sync.RWMutex
    33  }
    34  
    35  // Set value to memory session
    36  func (st *MemSessionStore) Set(key, value interface{}) error {
    37  	st.lock.Lock()
    38  	defer st.lock.Unlock()
    39  	st.value[key] = value
    40  	return nil
    41  }
    42  
    43  // Get value from memory session by key
    44  func (st *MemSessionStore) Get(key interface{}) interface{} {
    45  	st.lock.RLock()
    46  	defer st.lock.RUnlock()
    47  	if v, ok := st.value[key]; ok {
    48  		return v
    49  	}
    50  	return nil
    51  }
    52  
    53  // Delete in memory session by key
    54  func (st *MemSessionStore) Delete(key interface{}) error {
    55  	st.lock.Lock()
    56  	defer st.lock.Unlock()
    57  	delete(st.value, key)
    58  	return nil
    59  }
    60  
    61  // Flush clear all values in memory session
    62  func (st *MemSessionStore) Flush() error {
    63  	st.lock.Lock()
    64  	defer st.lock.Unlock()
    65  	st.value = make(map[interface{}]interface{})
    66  	return nil
    67  }
    68  
    69  // SessionID get this id of memory session store
    70  func (st *MemSessionStore) SessionID() string {
    71  	return st.sid
    72  }
    73  
    74  // SessionRelease Implement method, no used.
    75  func (st *MemSessionStore) SessionRelease(w http.ResponseWriter) {
    76  }
    77  
    78  // MemProvider Implement the provider interface
    79  type MemProvider struct {
    80  	lock        sync.RWMutex             // locker
    81  	sessions    map[string]*list.Element // map in memory
    82  	list        *list.List               // for gc
    83  	maxlifetime int64
    84  	savePath    string
    85  }
    86  
    87  // SessionInit init memory session
    88  func (pder *MemProvider) SessionInit(maxlifetime int64, savePath string) error {
    89  	pder.maxlifetime = maxlifetime
    90  	pder.savePath = savePath
    91  	return nil
    92  }
    93  
    94  // SessionRead get memory session store by sid
    95  func (pder *MemProvider) SessionRead(sid string) (Store, error) {
    96  	pder.lock.RLock()
    97  	if element, ok := pder.sessions[sid]; ok {
    98  		go pder.SessionUpdate(sid)
    99  		pder.lock.RUnlock()
   100  		return element.Value.(*MemSessionStore), nil
   101  	}
   102  	pder.lock.RUnlock()
   103  	pder.lock.Lock()
   104  	newsess := &MemSessionStore{sid: sid, timeAccessed: time.Now(), value: make(map[interface{}]interface{})}
   105  	element := pder.list.PushFront(newsess)
   106  	pder.sessions[sid] = element
   107  	pder.lock.Unlock()
   108  	return newsess, nil
   109  }
   110  
   111  // SessionExist check session store exist in memory session by sid
   112  func (pder *MemProvider) SessionExist(sid string) bool {
   113  	pder.lock.RLock()
   114  	defer pder.lock.RUnlock()
   115  	if _, ok := pder.sessions[sid]; ok {
   116  		return true
   117  	}
   118  	return false
   119  }
   120  
   121  // SessionRegenerate generate new sid for session store in memory session
   122  func (pder *MemProvider) SessionRegenerate(oldsid, sid string) (Store, error) {
   123  	pder.lock.RLock()
   124  	if element, ok := pder.sessions[oldsid]; ok {
   125  		go pder.SessionUpdate(oldsid)
   126  		pder.lock.RUnlock()
   127  		pder.lock.Lock()
   128  		element.Value.(*MemSessionStore).sid = sid
   129  		pder.sessions[sid] = element
   130  		delete(pder.sessions, oldsid)
   131  		pder.lock.Unlock()
   132  		return element.Value.(*MemSessionStore), nil
   133  	}
   134  	pder.lock.RUnlock()
   135  	pder.lock.Lock()
   136  	newsess := &MemSessionStore{sid: sid, timeAccessed: time.Now(), value: make(map[interface{}]interface{})}
   137  	element := pder.list.PushFront(newsess)
   138  	pder.sessions[sid] = element
   139  	pder.lock.Unlock()
   140  	return newsess, nil
   141  }
   142  
   143  // SessionDestroy delete session store in memory session by id
   144  func (pder *MemProvider) SessionDestroy(sid string) error {
   145  	pder.lock.Lock()
   146  	defer pder.lock.Unlock()
   147  	if element, ok := pder.sessions[sid]; ok {
   148  		delete(pder.sessions, sid)
   149  		pder.list.Remove(element)
   150  		return nil
   151  	}
   152  	return nil
   153  }
   154  
   155  // SessionGC clean expired session stores in memory session
   156  func (pder *MemProvider) SessionGC() {
   157  	pder.lock.RLock()
   158  	for {
   159  		element := pder.list.Back()
   160  		if element == nil {
   161  			break
   162  		}
   163  		if (element.Value.(*MemSessionStore).timeAccessed.Unix() + pder.maxlifetime) < time.Now().Unix() {
   164  			pder.lock.RUnlock()
   165  			pder.lock.Lock()
   166  			pder.list.Remove(element)
   167  			delete(pder.sessions, element.Value.(*MemSessionStore).sid)
   168  			pder.lock.Unlock()
   169  			pder.lock.RLock()
   170  		} else {
   171  			break
   172  		}
   173  	}
   174  	pder.lock.RUnlock()
   175  }
   176  
   177  // SessionAll get count number of memory session
   178  func (pder *MemProvider) SessionAll() int {
   179  	return pder.list.Len()
   180  }
   181  
   182  // SessionUpdate expand time of session store by id in memory session
   183  func (pder *MemProvider) SessionUpdate(sid string) error {
   184  	pder.lock.Lock()
   185  	defer pder.lock.Unlock()
   186  	if element, ok := pder.sessions[sid]; ok {
   187  		element.Value.(*MemSessionStore).timeAccessed = time.Now()
   188  		pder.list.MoveToFront(element)
   189  		return nil
   190  	}
   191  	return nil
   192  }
   193  
   194  func init() {
   195  	Register("memory", mempder)
   196  }