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
30
will work on a dumb filesystem without actual locking primitives."""
40
36
from trace import mutter, note, warning
41
from errors import LockError
43
class _base_Lock(object):
44
def _open(self, filename, filemode):
45
self.f = open(filename, filemode)
51
from warnings import warn
52
warn("lock on %r not released" % self.f)
56
raise NotImplementedError()
63
############################################################
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)
70
class _fcntl_FileLock(_base_Lock):
74
fcntl.flock(self.f, fcntl.LOCK_UN)
79
class _fcntl_WriteLock(_fcntl_FileLock):
80
def __init__(self, filename):
82
fcntl.flock(self._open(filename, 'wb'), fcntl.LOCK_EX)
87
class _fcntl_ReadLock(_fcntl_FileLock):
88
def __init__(self, filename):
90
fcntl.flock(self._open(filename, 'rb'), fcntl.LOCK_SH)
94
WriteLock = _fcntl_WriteLock
95
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)
97
66
except ImportError:
99
68
import win32con, win32file, pywintypes
102
#LOCK_SH = 0 # the default
103
#LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
104
#LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
106
class _w32c_FileLock(_base_Lock):
107
def _lock(self, filename, openmode, lockmode):
109
self._open(filename, openmode)
110
self.hfile = win32file._get_osfhandle(self.f.fileno())
111
overlapped = pywintypes.OVERLAPPED()
112
win32file.LockFileEx(self.hfile, lockmode, 0, 0x7fff0000, overlapped)
118
overlapped = pywintypes.OVERLAPPED()
119
win32file.UnlockFileEx(self.hfile, 0, 0x7fff0000, overlapped)
127
class _w32c_ReadLock(_w32c_FileLock):
128
def __init__(self, filename):
129
_w32c_FileLock._lock(self, filename, 'rb', 0)
131
class _w32c_WriteLock(_w32c_FileLock):
132
def __init__(self, filename):
133
_w32c_FileLock._lock(self, filename, 'wb',
134
win32con.LOCKFILE_EXCLUSIVE_LOCK)
138
WriteLock = _w32c_WriteLock
139
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)
141
94
except ImportError:
146
97
# Unfortunately, msvcrt.locking() doesn't distinguish between
147
98
# read locks and write locks. Also, the way the combinations
148
99
# work to get non-blocking is not the same, so we
149
100
# have to write extra special functions here.
152
class _msvc_FileLock(_base_Lock):
160
class _msvc_ReadLock(_msvc_FileLock):
161
def __init__(self, filename):
162
_msvc_lock(self._open(filename, 'rb'), self.LOCK_SH)
165
class _msvc_WriteLock(_msvc_FileLock):
166
def __init__(self, filename):
167
_msvc_lock(self._open(filename, 'wb'), self.LOCK_EX)
171
def _msvc_lock(f, flags):
173
108
# Unfortunately, msvcrt.LK_RLCK is equivalent to msvcrt.LK_LOCK
174
109
# according to the comments, LK_RLCK is open the lock for writing.