Commit da536f0a authored by Barry Warsaw's avatar Barry Warsaw

Backport lock file changes from ZODB4. Specifically, implement an

unlock_file() call which awaits Tim's backport of
winlock.UnlockFile().  This is no-op on *nix.

Also, implement a better API for dealing with lock files.  Use the
LockFile class for clean acquisition and release of locks, and
unlinking of lock files.
parent 1b9c5718
...@@ -12,47 +12,63 @@ ...@@ -12,47 +12,63 @@
# #
############################################################################## ##############################################################################
from ZODB.POSException import StorageSystemError import os
import errno
# Try to create a function that creates Unix file locks.
try: try:
import fcntl import fcntl
except ImportError:
try:
from winlock import LockFile as _LockFile
from winlock import UnlockFile as _UnlockFile
except ImportError:
import zLOG
def lock_file(file):
zLOG.LOG('ZODB', zLOG.INFO,
'No file-locking support on this platform')
lock_file_FLAG = fcntl.LOCK_EX | fcntl.LOCK_NB # Windows
def lock_file(file):
# Lock just the first byte
_LockFile(file.fileno(), 0, 0, 1, 0)
def unlock_file(file):
_UnlockFile(file.fileno(), 0, 0, 1, 0)
else:
# Unix
_flags = fcntl.LOCK_EX | fcntl.LOCK_NB
def lock_file(file): def lock_file(file):
try: fcntl.flock(file.fileno(), _flags)
un = file.fileno()
except: def unlock_file(file):
return # don't care if not a real 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: try:
fcntl.flock(un, lock_file_FLAG) self._fp = open(path, 'r+')
except: except IOError, e:
raise StorageSystemError, ( if e.errno <> errno.ENOENT: raise
"Could not lock the database file. There must be\n" self._fp = open(path, 'w+')
"another process that has opened the file.\n" # Acquire the lock and piss on the hydrant
"<p>") lock_file(self._fp)
print >> self._fp, os.getpid()
except: self._fp.flush()
# Try windows-specific code:
try: def close(self):
from winlock import LockFile if self._fp is not None:
def lock_file(file): unlock_file(self._fp)
try: self._fp.close()
un=file.fileno() os.unlink(self._path)
except: self._fp = None
return # don't care if not a real file
def __del__(self):
try: self.close()
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"
"<p>")
except:
import zLOG
def lock_file(file):
zLOG.LOG("FS", zLOG.INFO,
"No file-locking support on this platform")
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment