27
27
different threads in a single process.
29
29
Eventually we may need to use some kind of lock representation that
30
will work on a dumb filesystem without actual locking primitives.
32
This defines two classes: ReadLock and WriteLock, which can be
33
implemented in different ways on different platforms. Both have an
41
from bzrlib.trace import mutter, note, warning
42
from bzrlib.errors import LockError
44
class _base_Lock(object):
45
def _open(self, filename, filemode):
48
self.f = open(filename, filemode)
51
if e.errno != errno.ENOENT:
54
# maybe this is an old branch (before may 2005)
55
mutter("trying to create missing branch lock %r" % filename)
57
self.f = open(filename, 'wb')
63
from warnings import warn
64
warn("lock on %r not released" % self.f)
69
raise NotImplementedError()
76
############################################################
30
will work on a dumb filesystem without actual locking primitives."""
36
from trace import mutter, note, warning
38
class LockError(Exception):
39
"""All exceptions from the lock/unlock functions should be from this exception class.
40
They will be translated as necessary. The original exception is available as e.original_error
42
def __init__(self, e=None):
43
self.original_error = e
45
Exception.__init__(self, e)
47
Exception.__init__(self)
83
class _fcntl_FileLock(_base_Lock):
87
fcntl.flock(self.f, fcntl.LOCK_UN)
92
class _fcntl_WriteLock(_fcntl_FileLock):
93
def __init__(self, filename):
95
fcntl.flock(self._open(filename, 'wb'), fcntl.LOCK_EX)
100
class _fcntl_ReadLock(_fcntl_FileLock):
101
def __init__(self, filename):
103
fcntl.flock(self._open(filename, 'rb'), fcntl.LOCK_SH)
107
WriteLock = _fcntl_WriteLock
108
ReadLock = _fcntl_ReadLock
51
LOCK_SH = fcntl.LOCK_SH
52
LOCK_EX = fcntl.LOCK_EX
53
LOCK_NB = fcntl.LOCK_NB
62
fcntl.flock(f, fcntl.LOCK_UN)
110
66
except ImportError:
112
68
import win32con, win32file, pywintypes
115
#LOCK_SH = 0 # the default
116
#LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
117
#LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
119
class _w32c_FileLock(_base_Lock):
120
def _lock(self, filename, openmode, lockmode):
122
self._open(filename, openmode)
123
self.hfile = win32file._get_osfhandle(self.f.fileno())
124
overlapped = pywintypes.OVERLAPPED()
125
win32file.LockFileEx(self.hfile, lockmode, 0, 0x7fff0000, overlapped)
131
overlapped = pywintypes.OVERLAPPED()
132
win32file.UnlockFileEx(self.hfile, 0, 0x7fff0000, overlapped)
140
class _w32c_ReadLock(_w32c_FileLock):
141
def __init__(self, filename):
142
_w32c_FileLock._lock(self, filename, 'rb', 0)
144
class _w32c_WriteLock(_w32c_FileLock):
145
def __init__(self, filename):
146
_w32c_FileLock._lock(self, filename, 'wb',
147
win32con.LOCKFILE_EXCLUSIVE_LOCK)
151
WriteLock = _w32c_WriteLock
152
ReadLock = _w32c_ReadLock
69
LOCK_SH = 0 # the default
70
LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
71
LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
76
hfile = win32file._get_osfhandle(f.fileno())
78
hfile = win32file._get_osfhandle(f)
79
overlapped = pywintypes.OVERLAPPED()
80
win32file.LockFileEx(hfile, flags, 0, 0x7fff0000, overlapped)
87
hfile = win32file._get_osfhandle(f.fileno())
89
hfile = win32file._get_osfhandle(f)
90
overlapped = pywintypes.OVERLAPPED()
91
win32file.UnlockFileEx(hfile, 0, 0x7fff0000, overlapped)
154
94
except ImportError:
159
97
# Unfortunately, msvcrt.locking() doesn't distinguish between
160
98
# read locks and write locks. Also, the way the combinations
161
99
# work to get non-blocking is not the same, so we
162
100
# have to write extra special functions here.
165
class _msvc_FileLock(_base_Lock):
173
class _msvc_ReadLock(_msvc_FileLock):
174
def __init__(self, filename):
175
_msvc_lock(self._open(filename, 'rb'), self.LOCK_SH)
178
class _msvc_WriteLock(_msvc_FileLock):
179
def __init__(self, filename):
180
_msvc_lock(self._open(filename, 'wb'), self.LOCK_EX)
184
def _msvc_lock(f, flags):
186
108
# Unfortunately, msvcrt.LK_RLCK is equivalent to msvcrt.LK_LOCK
187
109
# according to the comments, LK_RLCK is open the lock for writing.