# HG changeset patch # User paulb # Date 1132444839 0 # Node ID 26d9b08d05f5063a97551d1f96160680944d8bc9 # Parent 83fcc5d284e5b916236fcc1f519b3f17409e7583 [project @ 2005-11-20 00:00:39 by paulb] Added primitive locking to the DirectoryRepository implementation. diff -r 83fcc5d284e5 -r 26d9b08d05f5 WebStack/Repositories/Directory.py --- a/WebStack/Repositories/Directory.py Sat Nov 19 23:59:54 2005 +0000 +++ b/WebStack/Repositories/Directory.py Sun Nov 20 00:00:39 2005 +0000 @@ -26,7 +26,7 @@ "A directory repository providing session-like access to files." - def __init__(self, path, fsencoding=None): + def __init__(self, path, fsencoding=None, delay=1): """ Initialise the repository using the given 'path' to indicate the @@ -37,12 +37,17 @@ character encoding used by the filesystem to represent filenames. By default, the default encoding is detected (or Unicode objects are used if appropriate). + + The optional 'delay' argument specifies the time in seconds between each + poll of an opened repository file when that file is found to be locked + for editing. """ if not os.path.exists(path): os.mkdir(path) self.path = path self.fsencoding = fsencoding + self.delay = delay # Guess the filesystem encoding. @@ -71,7 +76,14 @@ return name def keys(self): - return map(self._convert_fsname, os.listdir(self.path)) + # NOTE: Special names converted using a simple rule. + l = [] + for name in os.listdir(self.path): + if name.endswith(".edit"): + l.append(name[:-5]) + else: + l.append(name) + return map(self._convert_fsname, l) def full_path(self, key): return os.path.join(self.path, self._convert_name(key)) @@ -93,23 +105,58 @@ results.append(self[key]) return results - def __getitem__(self, key): - f = open(os.path.join(self.path, self._convert_name(key)), "rb") - s = "" - try: - s = f.read() - finally: - f.close() - return s + def _wait_for_file(self, key): + filename = self.full_path(key) + if os.path.exists(filename) or os.path.exists(filename + ".edit"): + while 1: + try: + os.rename(filename, filename + ".edit") + except OSError: + time.sleep(self.delay) + else: + break + return filename, 1 + else: + return filename, 0 def __delitem__(self, key): - os.remove(os.path.join(self.path, self._convert_name(key))) + filename = self.full_path(key) + if os.path.exists(filename) or os.path.exists(filename + ".edit"): + while 1: + try: + os.remove(filename) + except OSError: + time.sleep(self.delay) + else: + break + else: + raise KeyError, key + + def __getitem__(self, key): + filename, exists = self._wait_for_file(key) + if not exists: + raise KeyError, key + try: + f = open(filename + ".edit", "rb") + s = "" + try: + s = f.read() + finally: + f.close() + finally: + os.rename(filename + ".edit", filename) + + return s def __setitem__(self, key, value): - f = open(os.path.join(self.path, self._convert_name(key)), "wb") + filename, exists = self._wait_for_file(key) try: - f.write(value) + f = open(filename + ".edit", "wb") + try: + f.write(value) + finally: + f.close() finally: - f.close() + os.rename(filename + ".edit", filename) # vim: tabstop=4 expandtab shiftwidth=4