[Zodb-checkins] CVS: Zope3/src/zodb - lockfile.py:1.4

Barry Warsaw barry@wooz.org
Thu, 27 Feb 2003 18:18:36 -0500


Update of /cvs-repository/Zope3/src/zodb
In directory cvs.zope.org:/tmp/cvs-serv14535

Modified Files:
	lockfile.py 
Log Message:
Improve the imports so that we're not just using bare excepts.  Add
support for unlock_file() so Windows has a chance of working
correctly (uses Tim's new UnlockFile() Windows function).

Implement a better API using a LockFile class, which has the semantics
wanted Berkeley storages and FileStorage.


=== Zope3/src/zodb/lockfile.py 1.3 => 1.4 ===
--- Zope3/src/zodb/lockfile.py:1.3	Wed Feb  5 18:28:34 2003
+++ Zope3/src/zodb/lockfile.py	Thu Feb 27 18:18:34 2003
@@ -12,44 +12,62 @@
 #
 ##############################################################################
 
-from zodb.storage.interfaces import StorageSystemError
+import os
+import errno
 
-# Try to create a function that creates Unix file locks.
 try:
     import fcntl
+except ImportError:
+    try:
+        from zodb.winlock import LockFile as _LockFile
+        from zodb.winlock import UnlockFile as _UnlockFile
+    except ImportError:
+        import logging
+        def lock_file(file):
+            logging.warn('ZODB: No file-locking support on this platform')
+            
+    # Windows
+    def lock_file(file):
+        # Lock just the first byte
+        _LockFile(file.fileno(), 0, 0, 1, 0)
 
-    lock_file_FLAG = fcntl.LOCK_EX | fcntl.LOCK_NB
+    def unlock_file(file):
+        _UnlockFile(file.fileno(), 0, 0, 1, 0)
+else:
+    # Unix
+    _flags = fcntl.LOCK_EX | fcntl.LOCK_NB
 
     def lock_file(file):
-        try:
-            un = file.fileno()
-        except:
-            return # don't care if not a real file
+        fcntl.flock(file.fileno(), _flags)
+
+    def unlock_file(file):
+        # File is automatically unlocked on close
+        pass
 
+
+
+# This is a better interface to use than the lockfile.lock_file() interface.
+# Creating the instance acquires the lock.  The file remains open.  Calling
+# close both closes and unlocks the lock file.
+class LockFile:
+    def __init__(self, path):
+        self._path = path
         try:
-            fcntl.flock(un, lock_file_FLAG)
-        except:
-            raise StorageSystemError, (
-                "Could not lock the database file.  There must be\n"
-                "another process that has opened the file.\n")
+            self._fp = open(path, 'r+')
+        except IOError, e:
+            if e.errno <> errno.ENOENT: raise
+            self._fp = open(path, 'w+')
+        # Acquire the lock and piss on the hydrant
+        lock_file(self._fp)
+        print >> self._fp, os.getpid()
+        self._fp.flush()
+
+    def close(self):
+        if self._fp is not None:
+            unlock_file(self._fp)
+            self._fp.close()
+            os.unlink(self._path)
+            self._fp = None
 
-except:
-    # Try windows-specific code:
-    try:
-        from zodb.winlock import LockFile
-        def lock_file(file):
-            try:
-                un=file.fileno()
-            except:
-                return # don't care if not a real file
-
-            try:
-                LockFile(un, 0, 0, 1, 0) # just lock the first byte, who cares
-            except:
-                raise StorageSystemError, (
-                    "Could not lock the database file.  There must be\n"
-                    "another process that has opened the file.\n")
-    except:
-        import logging
-        def lock_file(file):
-            logging.warn("FS: No file-locking support on this platform")
+    def __del__(self):
+        self.close()