Ticket #1: locking-shelves.diff

File locking-shelves.diff, 4.0 kB (added by asaddi, 5 years ago)

LockingShelveSessionStore? patch. Complete, but with issues (see comment)

  • session.py

    old new  
    4545           'SessionStore', 
    4646           'MemorySessionStore', 
    4747           'ShelveSessionStore', 
     48           'LockingShelveSessionStore', 
    4849           'DiskSessionStore', 
    4950           'SessionMiddleware'] 
    5051 
     
    395396    def _shutdown(self): 
    396397        self._secondaryStore.close() 
    397398 
     399# LockingShelveSessionStore contributed by Julian Cigar <jcigar@ulb.ac.be> 
     400 
     401LOCK_TIMEOUT = 60 
     402 
     403class FileLock(object): 
     404 
     405    def __init__(self, lock_file): 
     406        self._lock_file = lock_file 
     407 
     408    def acquireLock(self, timeout=LOCK_TIMEOUT): 
     409 
     410        for i in xrange(1, timeout*10): 
     411            try: 
     412                os.open(self._lock_file, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 
     413                        0660) 
     414                return True 
     415            except: 
     416                time.sleep(0.1) 
     417                continue 
     418 
     419        try: 
     420            self.isStale() and self.releaseLock() 
     421        except: 
     422            pass 
     423 
     424        return False 
     425     
     426    def isStale(self): 
     427        try: 
     428            return os.stat(self._lock_file).st_mtime < time.time() - 3600 
     429        except OSError: 
     430            return False 
     431 
     432    def releaseLock(self): 
     433        os.path.isfile(self._lock_file) and os.unlink(self._lock_file) 
     434 
     435    def withLock(self, self_, fct, args): 
     436        if self.acquireLock(): 
     437            try: 
     438                return fct(self_, *args) 
     439            finally: 
     440                self.releaseLock() 
     441        else: 
     442            raise IOError('Cannot acquire lock') 
     443 
     444def with_lock(fct): 
     445    return lambda self, *args: self.lock.withLock(self, fct, args) 
     446 
     447class LockingShelveSessionStore(SessionStore): 
     448    def __init__(self, storeFile='sessions', *a, **kw): 
     449        super(LockingShelveSessionStore, self).__init__(*a, **kw) 
     450 
     451        self.storeFile = storeFile 
     452        lock_file = os.path.join(os.path.dirname(self.storeFile), '.lock') 
     453        self.lock = FileLock(lock_file) 
     454 
     455    def _createSession(self, identifier): 
     456        secondaryStore = shelve.open(self.storeFile) 
     457        try: 
     458            if secondaryStore.has_key(identifier): 
     459                return None 
     460            sess = self._sessionClass(identifier) 
     461            secondaryStore[sess.identifier] = sess 
     462            return sess 
     463        finally: 
     464            secondaryStore.close() 
     465    _createSession = with_lock(_createSession) 
     466 
     467    def _loadSession(self, identifier): 
     468        secondaryStore = shelve.open(self.storeFile) 
     469        try: 
     470            return secondaryStore.get(identifier, None) 
     471        finally: 
     472            secondaryStore.close() 
     473    _loadSession = with_lock(_loadSession) 
     474 
     475    def _saveSession(self, session): 
     476        secondaryStore = shelve.open(self.storeFile) 
     477        try: 
     478            secondaryStore[session.identifier] = session 
     479        finally: 
     480            secondaryStore.close() 
     481    _saveSession = with_lock(_saveSession) 
     482 
     483    def _deleteSession(self, identifier): 
     484        secondaryStore = shelve.open(self.storeFile) 
     485        try: 
     486            if secondaryStore.has_key(identifier): 
     487                del secondaryStore[identifier] 
     488        finally: 
     489            secondaryStore.close() 
     490    _deleteSession = with_lock(_deleteSession) 
     491 
     492    def _periodic(self): 
     493        secondaryStore = shelve.open(self.storeFile) 
     494        try: 
     495            now = time.time() 
     496            for key,sess in secondaryStore.items(): 
     497                if self._isSessionTimedout(sess, now): 
     498                    del secondaryStore[key] 
     499        finally: 
     500            secondaryStore.close() 
     501    _periodic = with_lock(_periodic) 
     502 
     503    def _shutdown(self): 
     504        pass 
     505 
    398506class DiskSessionStore(SessionStore): 
    399507    """ 
    400508    Disk-based session store that stores each session as its own file 
     
    766874 
    767875if __name__ == '__main__': 
    768876    mss = MemorySessionStore(timeout=5) 
     877    sss = LockingShelveSessionStore(timeout=5) 
    769878#    sss = ShelveSessionStore(timeout=5) 
    770     dss = DiskSessionStore(timeout=5) 
     879#    dss = DiskSessionStore(timeout=5)