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): def lock_file(file):
try: # Lock just the first byte
un = file.fileno() _LockFile(file.fileno(), 0, 0, 1, 0)
except:
return # don't care if not a real file def unlock_file(file):
_UnlockFile(file.fileno(), 0, 0, 1, 0)
else:
# Unix
_flags = fcntl.LOCK_EX | fcntl.LOCK_NB
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"
"<p>")
except:
# Try windows-specific code:
try:
from winlock import LockFile
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:
LockFile(un, 0, 0, 1, 0) # just lock the first byte, who cares 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)
except: print >> self._fp, os.getpid()
import zLOG self._fp.flush()
def lock_file(file):
zLOG.LOG("FS", zLOG.INFO, def close(self):
"No file-locking support on this platform") if self._fp is not None:
unlock_file(self._fp)
self._fp.close()
os.unlink(self._path)
self._fp = None
def __del__(self):
self.close()
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