~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/lock.py

  • Committer: Vincent Ladeuil
  • Date: 2009-06-22 12:52:39 UTC
  • mto: (4471.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 4472.
  • Revision ID: v.ladeuil+lp@free.fr-20090622125239-kabo9smxt9c3vnir
Use a consistent scheme for naming pyrex source files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
 
18
18
"""Locking using OS file locks or file existence.
42
42
    osutils,
43
43
    trace,
44
44
    )
 
45
from bzrlib.hooks import HookPoint, Hooks
 
46
 
 
47
 
 
48
class LockHooks(Hooks):
 
49
 
 
50
    def __init__(self):
 
51
        Hooks.__init__(self)
 
52
        self.create_hook(HookPoint('lock_acquired',
 
53
            "Called with a bzrlib.lock.LockResult when a physical lock is "
 
54
            "acquired.", (1, 8), None))
 
55
        self.create_hook(HookPoint('lock_released',
 
56
            "Called with a bzrlib.lock.LockResult when a physical lock is "
 
57
            "released.", (1, 8), None))
 
58
        self.create_hook(HookPoint('lock_broken',
 
59
            "Called with a bzrlib.lock.LockResult when a physical lock is "
 
60
            "broken.", (1, 15), None))
 
61
 
 
62
 
 
63
class Lock(object):
 
64
    """Base class for locks.
 
65
 
 
66
    :cvar hooks: Hook dictionary for operations on locks.
 
67
    """
 
68
 
 
69
    hooks = LockHooks()
 
70
 
 
71
 
 
72
class LockResult(object):
 
73
    """Result of an operation on a lock; passed to a hook"""
 
74
 
 
75
    def __init__(self, lock_url, details=None):
 
76
        """Create a lock result for lock with optional details about the lock."""
 
77
        self.lock_url = lock_url
 
78
        self.details = details
 
79
 
 
80
    def __eq__(self, other):
 
81
        return self.lock_url == other.lock_url and self.details == other.details
 
82
 
 
83
    def __repr__(self):
 
84
        return '%s(%s%s)' % (self.__class__.__name__,
 
85
                             self.lock_url, self.details)
 
86
 
 
87
 
 
88
try:
 
89
    import fcntl
 
90
    have_fcntl = True
 
91
except ImportError:
 
92
    have_fcntl = False
 
93
 
 
94
have_pywin32 = False
 
95
have_ctypes_win32 = False
 
96
if sys.platform == 'win32':
 
97
    import msvcrt
 
98
    try:
 
99
        import win32con, win32file, pywintypes, winerror
 
100
        have_pywin32 = True
 
101
    except ImportError:
 
102
        pass
 
103
 
 
104
    try:
 
105
        import ctypes
 
106
        have_ctypes_win32 = True
 
107
    except ImportError:
 
108
        pass
45
109
 
46
110
 
47
111
class _OSLock(object):
83
147
        raise NotImplementedError()
84
148
 
85
149
 
86
 
try:
87
 
    import fcntl
88
 
    have_fcntl = True
89
 
except ImportError:
90
 
    have_fcntl = False
91
 
try:
92
 
    import win32con, win32file, pywintypes, winerror, msvcrt
93
 
    have_pywin32 = True
94
 
except ImportError:
95
 
    have_pywin32 = False
96
 
try:
97
 
    import ctypes, msvcrt
98
 
    have_ctypes = True
99
 
except ImportError:
100
 
    have_ctypes = False
101
 
 
102
 
 
103
150
_lock_classes = []
104
151
 
105
152
 
143
190
                    self.unlock()
144
191
                # we should be more precise about whats a locking
145
192
                # error and whats a random-other error
146
 
                raise errors.LockContention(e)
 
193
                raise errors.LockContention(self.filename, e)
147
194
 
148
195
        def unlock(self):
149
196
            _fcntl_WriteLock._open_locks.remove(self.filename)
167
214
            except IOError, e:
168
215
                # we should be more precise about whats a locking
169
216
                # error and whats a random-other error
170
 
                raise errors.LockContention(e)
 
217
                raise errors.LockContention(self.filename, e)
171
218
 
172
219
        def unlock(self):
173
220
            count = _fcntl_ReadLock._open_locks[self.filename]
235
282
                fcntl.lockf(new_f, fcntl.LOCK_EX | fcntl.LOCK_NB)
236
283
            except IOError, e:
237
284
                # TODO: Raise a more specific error based on the type of error
238
 
                raise errors.LockContention(e)
 
285
                raise errors.LockContention(self.filename, e)
239
286
            _fcntl_WriteLock._open_locks.add(self.filename)
240
287
 
241
288
            self.f = new_f
280
327
                raise
281
328
            except Exception, e:
282
329
                self._clear_f()
283
 
                raise errors.LockContention(e)
 
330
                raise errors.LockContention(filename, e)
284
331
 
285
332
        def unlock(self):
286
333
            overlapped = pywintypes.OVERLAPPED()
288
335
                win32file.UnlockFileEx(self.hfile, 0, 0x7fff0000, overlapped)
289
336
                self._clear_f()
290
337
            except Exception, e:
291
 
                raise errors.LockContention(e)
 
338
                raise errors.LockContention(self.filename, e)
292
339
 
293
340
 
294
341
    class _w32c_ReadLock(_w32c_FileLock):
332
379
    _lock_classes.append(('pywin32', _w32c_WriteLock, _w32c_ReadLock))
333
380
 
334
381
 
335
 
if have_ctypes and sys.platform == 'win32':
 
382
if have_ctypes_win32:
336
383
    # These constants were copied from the win32con.py module.
337
384
    LOCKFILE_FAIL_IMMEDIATELY = 1
338
385
    LOCKFILE_EXCLUSIVE_LOCK = 2
344
391
    LOCK_NB = LOCKFILE_FAIL_IMMEDIATELY
345
392
    _LockFileEx = ctypes.windll.kernel32.LockFileEx
346
393
    _UnlockFileEx = ctypes.windll.kernel32.UnlockFileEx
347
 
    _GetLastError = ctypes.windll.kernel32.GetLastError
348
394
 
349
395
    ### Define the OVERLAPPED structure.
350
396
    #   http://msdn2.microsoft.com/en-us/library/ms684342.aspx
393
439
                                 ctypes.byref(overlapped), # lpOverlapped
394
440
                                )
395
441
            if result == 0:
 
442
                last_err = ctypes.GetLastError()
396
443
                self._clear_f()
397
 
                last_err = _GetLastError()
398
444
                if last_err in (ERROR_LOCK_VIOLATION,):
399
445
                    raise errors.LockContention(filename)
400
 
                raise errors.LockContention('Unknown locking error: %s'
401
 
                                            % (last_err,))
 
446
                raise errors.LockContention(filename,
 
447
                    'Unknown locking error: %s' % (last_err,))
402
448
 
403
449
        def unlock(self):
404
450
            overlapped = OVERLAPPED()
408
454
                                   0x00000000, # DWORD nNumberOfBytesToLockHigh
409
455
                                   ctypes.byref(overlapped), # lpOverlapped
410
456
                                  )
411
 
            self._clear_f()
412
457
            if result == 0:
 
458
                last_err = ctypes.GetLastError()
413
459
                self._clear_f()
414
 
                last_err = _GetLastError()
415
 
                raise errors.LockContention('Unknown unlocking error: %s'
416
 
                                            % (last_err,))
 
460
                raise errors.LockContention(self.filename,
 
461
                    'Unknown unlocking error: %s' % (last_err,))
 
462
            self._clear_f()
417
463
 
418
464
 
419
465
    class _ctypes_ReadLock(_ctypes_FileLock):