Hello Alan,
I was just wondering why you didn't use a .lock file for the ShelveSessionStore? (as you did with DiskSessionStore?) to resolve the concurrently accesses ?
For example I did a small FileLock? class with a decorator :
class FileLock(object):
def __init__(self, lock_file):
self._lock_file = lock_file
def acquireLock(self, timeout=LOCK_TIMEOUT):
for i in xrange(1, timeout*10):
try:
os.open(self._lock_file, os.O_WRONLY | os.O_CREAT | os.O_EXCL,
0660)
return True
except:
time.sleep(0.1)
continue
try:
self.isStale() and self.releaseLock()
except:
pass
return False
def isStale(self):
try:
return os.stat(self._lock_file).st_mtime < time.time() - 3600
except OSError:
return False
def releaseLock(self):
os.path.isfile(self._lock_file) and os.unlink(self._lock_file)
def withLock(self, fct):
if self.acquireLock():
try:
return fct()
finally:
self.releaseLock()
else:
raise IOError('Cannot acquire lock')
def with_lock(fct):
return lambda self: self.lock.withLock(lambda: fct(self))
and you can do something like :
class ShelveSession(BaseSession):
def __init__(...):
super(ShelveSession, self).__init__(...)
lock_file = os.path.join(os.path.dirname(self.session_file), '.lock')
self.lock = FileLock(lock_file)
@with_lock
def save(self):
f = shelve.open(self.session_file, 'c')
f[self.sid] = self.data
f.close()
@with_lock
def load(self):
f = shelve.open(self.session_file, 'r')
self.data = f.get(self.sid, None)
f.close()
@with_lock
def delete(self):
f = shelve.open(self.session_file, 'w')
try:
del f[self.sid]
except KeyError:
pass
f.close()
self.clear()
Any reason why to not use a lockfile with a shelve ?
Thanks !