[Pkg-bazaar-commits] ./bzr/unstable r577: - merge portable lock module from John
Martin Pool
mbp at sourcefrog.net
Fri Apr 10 08:18:55 UTC 2009
------------------------------------------------------------
revno: 577
committer: Martin Pool <mbp at sourcefrog.net>
timestamp: Fri 2005-05-27 15:10:23 +1000
message:
- merge portable lock module from John
added:
bzrlib/lock.py
modified:
bzrlib/branch.py
-------------- next part --------------
=== modified file 'bzrlib/branch.py'
--- a/bzrlib/branch.py 2005-05-27 04:09:30 +0000
+++ b/bzrlib/branch.py 2005-05-27 05:10:23 +0000
@@ -32,6 +32,8 @@
from errors import BzrError
from textui import show_status
+import lock
+
BZR_BRANCH_FORMAT = "Bazaar-NG branch, format 0.0.4\n"
## TODO: Maybe include checks for common corruption of newlines, etc?
@@ -117,6 +119,7 @@
['use "bzr init" to initialize a new working tree',
'current bzr can only operate from top-of-tree'])
self._check_format()
+ self._lockfile = None
self.lock(lock_mode)
self.text_store = ImmutableStore(self.controlfilename('text-store'))
=== added file 'bzrlib/lock.py'
--- a/bzrlib/lock.py 1970-01-01 00:00:00 +0000
+++ b/bzrlib/lock.py 2005-05-27 05:10:23 +0000
@@ -0,0 +1,169 @@
+# Copyright (C) 2005 Canonical Ltd
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+"""Locking wrappers.
+
+This only does local locking using OS locks for now.
+
+This module causes two methods, lock() and unlock() to be defined in
+any way that works on the current platform.
+
+It is not specified whether these locks are reentrant (i.e. can be
+taken repeatedly by a single process) or whether they exclude
+different threads in a single process.
+
+Eventually we may need to use some kind of lock representation that
+will work on a dumb filesystem without actual locking primitives."""
+
+
+import sys, os
+
+import bzrlib
+from trace import mutter, note, warning
+
+class LockError(Exception):
+ """All exceptions from the lock/unlock functions should be from this exception class.
+ They will be translated as necessary. The original exception is available as e.original_error
+ """
+ def __init__(self, e=None):
+ self.original_error = e
+ if e:
+ Exception.__init__(self, e)
+ else:
+ Exception.__init__(self)
+
+try:
+ import fcntl
+ LOCK_SH = fcntl.LOCK_SH
+ LOCK_EX = fcntl.LOCK_EX
+ LOCK_NB = fcntl.LOCK_NB
+ def lock(f, flags):
+ try:
+ fcntl.flock(f, flags)
+ except Exception, e:
+ raise LockError(e)
+
+ def unlock(f):
+ try:
+ fcntl.flock(f, fcntl.LOCK_UN)
+ except Exception, e:
+ raise LockError(e)
+
+except ImportError:
+ try:
+ import win32con, win32file, pywintypes
+ LOCK_SH = 0 # the default
+ LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
+ LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
+
+ def lock(f, flags):
+ try:
+ if type(f) == file:
+ hfile = win32file._get_osfhandle(f.fileno())
+ else:
+ hfile = win32file._get_osfhandle(f)
+ overlapped = pywintypes.OVERLAPPED()
+ win32file.LockFileEx(hfile, flags, 0, 0x7fff0000, overlapped)
+ except Exception, e:
+ raise LockError(e)
+
+ def unlock(f):
+ try:
+ if type(f) == file:
+ hfile = win32file._get_osfhandle(f.fileno())
+ else:
+ hfile = win32file._get_osfhandle(f)
+ overlapped = pywintypes.OVERLAPPED()
+ win32file.UnlockFileEx(hfile, 0, 0x7fff0000, overlapped)
+ except Exception, e:
+ raise LockError(e)
+ except ImportError:
+ try:
+ import msvcrt
+ # Unfortunately, msvcrt.locking() doesn't distinguish between
+ # read locks and write locks. Also, the way the combinations
+ # work to get non-blocking is not the same, so we
+ # have to write extra special functions here.
+
+ LOCK_SH = 1
+ LOCK_EX = 2
+ LOCK_NB = 4
+
+ def lock(f, flags):
+ try:
+ # Unfortunately, msvcrt.LK_RLCK is equivalent to msvcrt.LK_LOCK
+ # according to the comments, LK_RLCK is open the lock for writing.
+
+ # Unfortunately, msvcrt.locking() also has the side effect that it
+ # will only block for 10 seconds at most, and then it will throw an
+ # exception, this isn't terrible, though.
+ if type(f) == file:
+ fpos = f.tell()
+ fn = f.fileno()
+ f.seek(0)
+ else:
+ fn = f
+ fpos = os.lseek(fn, 0,0)
+ os.lseek(fn, 0,0)
+
+ if flags & LOCK_SH:
+ if flags & LOCK_NB:
+ lock_mode = msvcrt.LK_NBLCK
+ else:
+ lock_mode = msvcrt.LK_LOCK
+ elif flags & LOCK_EX:
+ if flags & LOCK_NB:
+ lock_mode = msvcrt.LK_NBRLCK
+ else:
+ lock_mode = msvcrt.LK_RLCK
+ else:
+ raise ValueError('Invalid lock mode: %r' % flags)
+ try:
+ msvcrt.locking(fn, lock_mode, -1)
+ finally:
+ os.lseek(fn, fpos, 0)
+ except Exception, e:
+ raise LockError(e)
+
+ def unlock(f):
+ try:
+ if type(f) == file:
+ fpos = f.tell()
+ fn = f.fileno()
+ f.seek(0)
+ else:
+ fn = f
+ fpos = os.lseek(fn, 0,0)
+ os.lseek(fn, 0,0)
+
+ try:
+ msvcrt.locking(fn, msvcrt.LK_UNLCK, -1)
+ finally:
+ os.lseek(fn, fpos, 0)
+ except Exception, e:
+ raise LockError(e)
+ except ImportError:
+ from warnings import Warning
+
+ warning("please write a locking method for platform %r" % sys.platform)
+
+ # Creating no-op lock/unlock for now
+ def lock(f, flags):
+ pass
+ def unlock(f):
+ pass
+
More information about the Pkg-bazaar-commits
mailing list