Changeset 575
- Timestamp:
- 08/29/05 12:26:47
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/lib/filter/sessionfilter/baseadaptor.py
r568 r575 31 31 import cherrypy 32 32 33 import mrow 34 33 35 class BaseAdaptor(object): 34 36 """ … … 60 62 def newSession(self): 61 63 """ Return a new sessiondict instance """ 62 attributes = { 63 'timestamp' : int(time.time()), 64 'timeout' : cherrypy.config.get('sessionFilter.timeout'), 65 'lastAccess' : int(time.time()), 66 'key' : self.generateSessionKey() 67 } 64 attributes = self.getDefaultAttributes() 68 65 return SessionDict(sessionAttributes = attributes) 69 66 70 67 # there should never be a reason to modify the remaining functions, they are used 71 68 # internally by the sessionFilter 72 69 70 def getDefaultAttributes(self): 71 """ return the default attributes as a dict""" 72 return { 73 'timestamp' : int(time.time()), 74 'timeout' : cherrypy.config.get('sessionFilter.timeout'), 75 'lastAccess' : int(time.time()), 76 'key' : self.generateSessionKey() 77 } 78 73 79 def __init__(self): 74 80 """ … … 79 85 80 86 self.__sessionCache = {} 87 self.__sessionLocks = {} 81 88 82 89 #set the path … … 100 107 # look for the session in the cache 101 108 session = self.__sessionCache[sessionKey] 102 session.threadCount += 1 109 session.lock_write() 110 try: 111 session.threadCount += 1 112 finally: 113 session.unlock_write() 103 114 except KeyError: 104 # look in the primary storage 105 session = self._getSessionDict(sessionKey) 106 session.threadCount += 1 107 self.__sessionCache[sessionKey] = session 108 115 lock = self.__sessionLocks.setdefault(sessionKey, mrow.MROWLock()) 116 lock.lock_write() 117 try: 118 # look in the primary storage 119 session = self._getSessionDict(sessionKey) 120 121 # make the session use same lock the internally 122 session.setLock(self.__sessionLocks[sessionKey]) 123 124 session.threadCount += 1 125 self.__sessionCache[sessionKey] = session 126 finally: 127 lock.unlock_write() 109 128 return session 110 129 … … 114 133 session.lastAccess = time.time() 115 134 116 #setattr(cherrypy.session, 'default', session)117 135 cherrypy.session._setDict(session) 118 136 … … 129 147 try: 130 148 session = self.__sessionCache[sessionKey] 131 session.threadCount = 0 132 self.saveSessionDict(session) 149 session.threadCount -= 1 150 try: 151 session.lock_write() 152 153 self.saveSessionDict(session) 133 154 134 cacheTimeout = cherrypy.config.get('sessionFilter.cacheTimeout')155 cacheTimeout = cherrypy.config.get('sessionFilter.cacheTimeout') 135 156 136 if session.threadCount == 0 and (self.noCache or not cacheTimeout): 137 del self.__sessionCache[sessionKey] 157 if session.threadCount == 0 and (self.noCache or not cacheTimeout): 158 del self.__sessionCache[sessionKey] 159 del self.__sessionLocks[sessionKey] 160 finally: 161 session.unlock_write() 138 162 except KeyError: 139 # i don't think this should happen but it does 140 # this is probably the result of two thread calling commitCache 141 # but nothing bad should happen 163 # another thread beat us to the delete 142 164 pass 143 165 … … 155 177 if session.threadCount == 0 and expired: 156 178 deleteList.append(session) 179 157 180 for session in deleteList: 158 181 self.commitCache(session.key) 159 del self.__sessionCache[session.key]160 182 161 183 def _cacheSize(self): trunk/cherrypy/lib/filter/sessionfilter/fileadaptor.py
r568 r575 75 75 filePath = os.path.join(storagePath, fileName) 76 76 77 self.__fileLock.lock_write()77 #self.__fileLock.lock_write() 78 78 try: 79 79 f = open(filePath,"wb") … … 81 81 f.close() 82 82 finally: 83 self.__fileLock.unlock_write() 83 pass 84 #self.__fileLock.unlock_write() 84 85 85 86 def _cleanUpOldSessions(self): trunk/cherrypy/lib/filter/sessionfilter/mrow.py
r566 r575 13 13 self.readers = [] # list of all reader Events. when clear, they are reading. must wait() for all of these to be sure no one is reading 14 14 self.readerslock = threading.RLock() # lock for readers list so it is not changed while looping 15 15 16 def lock_read(self): 16 17 if not hasattr(self.local, "reader"): … … 20 21 self.readers.append(self.local.reader) 21 22 self.readerslock.release() 22 self.writing.wait() # wait for any writes to finish 23 24 # only wait if the writing thread is not the thread same which is requesting a read lock 25 if not hasattr(self.local, 'writing'): 26 self.writing.wait() # wait for any writes to finish 27 23 28 # tell everyone we are reading 24 29 self.local.reader.clear() 30 25 31 def lock_write(self): 26 self.writing.wait() # wait for any writes to finish (this is a bit redundant with the next line) 32 # we set the writing attribute so we know if 33 # lock_write is being called by the same thread 34 if not hasattr(self.local, 'writing'): 35 self.local.writing = True 36 self.writing.wait() # wait for any writes to finish (this is a bit redundant with the next line) 37 27 38 self.writelock.acquire() 28 39 self.writing.clear() # lock out everyone reading from this dict … … 32 43 self.readerslock.release() 33 44 # at this point, all systems go 45 34 46 def unlock_read(self): 35 47 if hasattr(self.local, "reader"): 36 48 self.local.reader.set() 49 37 50 def unlock_write(self): 38 51 self.writing.set() # wake everyone else up. TODO: what if one thread has the lock, and another calls this method? 39 52 self.writelock.release() 53 40 54 41 55 class MROWDict(dict): … … 46 60 self._auto_lock = auto_lock # automatically acquire locks for getitem setitem (BAD IDEA) 47 61 self._auto_lock_safe = auto_lock_safe # when autolocking, lock the whole dict (GOOD IDEA) 62 48 63 def _init_lock(self, key): 49 64 self._lockslock.acquire() … … 51 66 self._locks[key] = MROWLock() 52 67 self._lockslock.release() 68 53 69 def lock_read(self, key = "__me__"): 54 70 self._init_lock(key) 55 71 return self._locks[key].lock_read() 72 56 73 def lock_write(self, key = "__me__"): 57 74 self._init_lock(key) 58 75 return self._locks[key].lock_write() 76 59 77 def unlock_read(self, key = "__me__"): 60 78 return self._locks[key].unlock_read() 79 61 80 def unlock_write(self, key = "__me__"): 62 81 return self._locks[key].unlock_write() 82 63 83 def __delitem__(self, key): 64 84 if key in self._locks: … … 67 87 del self._locks[key] 68 88 dict.__delitem__(self, key) 89 69 90 def __getitem__(self, key): 70 91 if self._auto_lock: … … 74 95 self.lock_read(key) 75 96 return dict.__getitem__(self, key) 97 76 98 def __setitem__(self, key, value): 77 99 if self._auto_lock: … … 81 103 self.lock_write(key) 82 104 dict.__setitem__(self, key, value) 105 106 def get(self, key): 107 if self._auto_lock: 108 if self._auto_lock_safe: 109 self.lock_read() 110 else: 111 self.lock_read(key) 112 return dict.get(self, key) 113 114 def setdefault(self, key, value): 115 if self._auto_lock: 116 if self._auto_lock_safe: 117 self.lock_write() 118 else: 119 self.lock_write(key) 120 dict.setdefault(self, key, value) 83 121 122 def update(self, values): 123 if self._auto_lock: 124 if self._auto_lock_safe: 125 self.lock_write() 126 else: 127 self.lock_write(key) 128 dict.update(self, values) 129 130 ''' 84 131 # test code 85 '''86 132 import time, thread 87 133 trunk/cherrypy/lib/filter/sessionfilter/sessiondict.py
r548 r575 31 31 from sessionerrors import SessionImmutableError 32 32 33 def locker(function):33 def readLocker(function): 34 34 def _inner(self, *args, **kwds): 35 self._lock. acquire()35 self._lock.lock_read() 36 36 try: 37 37 return function(self, *args, **kwds) 38 38 finally: 39 self._lock.release() 39 self._lock.unlock_read() 40 return _inner 41 42 def writeLocker(function): 43 def _inner(self, *args, **kwds): 44 self._lock.lock_write() 45 try: 46 return function(self, *args, **kwds) 47 finally: 48 self._lock.unlock_write() 40 49 return _inner 41 50 42 51 import threading 43 52 53 import mrow 54 44 55 class SessionDict(dict): 45 56 46 57 def __init__(self, sessionData = {}, sessionAttributes = {}): 47 self._lock = threading.RLock()58 self._lock = mrow.MROWLock() 48 59 self.threadCount = 0 49 60 … … 51 62 self.__sessionAttributes = sessionAttributes 52 63 53 get=locker(dict.get) 54 setdefault=locker(dict.setdefault) 64 get=readLocker(dict.get) 65 setdefault=writeLocker(dict.setdefault) 66 67 def setLock(self, lockObject): 68 """ set the lock object """ 69 self._lock = lockObject 70 71 def lock_write(self): 72 self._lock.lock_write() 55 73 74 def unlock_write(self): 75 self._lock.unlock_write() 76 77 def lock_read(self): 78 self._lock.lock_read() 79 80 def unlock_read(self): 81 self._lock.unlock_read() 82 56 83 def __getattr__(self, attr): 57 84 try: … … 59 86 except KeyError: 60 87 return object.__getattribute__(self, attr) 61 __getattr__= locker(__getattr__)88 __getattr__=readLocker(__getattr__) 62 89 63 90 # this function we lock the hard way … … 68 95 return 69 96 70 self._lock.acquire() 97 self._lock.lock_read() 98 try: 71 99 72 if attr in ['timeout', 'lastAccess' ]:73 self.__sessionAttributes[attr] = value74 elif attr in ['timestamp', 'key']:75 raise AttributeError('%s is immutable' % attr)76 else:77 object.__setattr__(self, attr, value)78 79 self._lock.release()100 if attr in ['timeout', 'lastAccess' ]: 101 self.__sessionAttributes[attr] = value 102 elif attr in ['timestamp', 'key']: 103 raise AttributeError('%s is immutable' % attr) 104 else: 105 object.__setattr__(self, attr, value) 106 finally: 107 self._lock.unlock_read() 80 108 81 109 def expired(self): 82 110 now = time.time() 83 111 return (now - self.lastAccess) > self.timeout 84 expired = locker(expired)112 expired = readLocker(expired) 85 113 86 114 def __getstate__(self): … … 90 118 stateDict.pop('_lock') 91 119 return stateDict 92 __getstate__ = locker(__getstate__)120 __getstate__ = readLocker(__getstate__) 93 121 94 122 def __setstate__(self, stateDict): 95 123 """ create a new lock object """ 96 self.__dict__['_lock'] = threading.RLock()124 self.__dict__['_lock'] = mrow.MROWLock() 97 125 self.__dict__.update(stateDict) 98 126

