~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/lock.py

  • Committer: Patch Queue Manager
  • Date: 2011-10-14 16:54:26 UTC
  • mfrom: (6216.1.1 remove-this-file)
  • Revision ID: pqm@pqm.ubuntu.com-20111014165426-tjix4e6idryf1r2z
(jelmer) Remove an accidentally committed .THIS file. (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
 
1
# Copyright (C) 2005-2010 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
45
45
    osutils,
46
46
    trace,
47
47
    )
48
 
from bzrlib.hooks import HookPoint, Hooks
49
 
 
 
48
from bzrlib.hooks import Hooks
 
49
from bzrlib.i18n import gettext
50
50
 
51
51
class LockHooks(Hooks):
52
52
 
53
53
    def __init__(self):
54
 
        Hooks.__init__(self)
55
 
        self.create_hook(HookPoint('lock_acquired',
56
 
            "Called with a bzrlib.lock.LockResult when a physical lock is "
57
 
            "acquired.", (1, 8), None))
58
 
        self.create_hook(HookPoint('lock_released',
59
 
            "Called with a bzrlib.lock.LockResult when a physical lock is "
60
 
            "released.", (1, 8), None))
61
 
        self.create_hook(HookPoint('lock_broken',
62
 
            "Called with a bzrlib.lock.LockResult when a physical lock is "
63
 
            "broken.", (1, 15), None))
 
54
        Hooks.__init__(self, "bzrlib.lock", "Lock.hooks")
 
55
        self.add_hook('lock_acquired',
 
56
            "Called with a bzrlib.lock.LockResult when a physical lock is "
 
57
            "acquired.", (1, 8))
 
58
        self.add_hook('lock_released',
 
59
            "Called with a bzrlib.lock.LockResult when a physical lock is "
 
60
            "released.", (1, 8))
 
61
        self.add_hook('lock_broken',
 
62
            "Called with a bzrlib.lock.LockResult when a physical lock is "
 
63
            "broken.", (1, 15))
64
64
 
65
65
 
66
66
class Lock(object):
84
84
        return self.lock_url == other.lock_url and self.details == other.details
85
85
 
86
86
    def __repr__(self):
87
 
        return '%s(%s%s)' % (self.__class__.__name__,
 
87
        return '%s(%s, %s)' % (self.__class__.__name__,
88
88
                             self.lock_url, self.details)
89
89
 
90
90
 
 
91
class LogicalLockResult(object):
 
92
    """The result of a lock_read/lock_write/lock_tree_write call on lockables.
 
93
 
 
94
    :ivar unlock: A callable which will unlock the lock.
 
95
    """
 
96
 
 
97
    def __init__(self, unlock):
 
98
        self.unlock = unlock
 
99
 
 
100
    def __repr__(self):
 
101
        return "LogicalLockResult(%s)" % (self.unlock)
 
102
 
 
103
 
 
104
 
91
105
def cant_unlock_not_held(locked_object):
92
106
    """An attempt to unlock failed because the object was not locked.
93
107
 
157
171
            self.f.close()
158
172
            self.f = None
159
173
 
160
 
    def __del__(self):
161
 
        if self.f:
162
 
            from warnings import warn
163
 
            warn("lock on %r not released" % self.f)
164
 
            self.unlock()
165
 
 
166
174
    def unlock(self):
167
175
        raise NotImplementedError()
168
176
 
190
198
            if self.filename in _fcntl_WriteLock._open_locks:
191
199
                self._clear_f()
192
200
                raise errors.LockContention(self.filename)
 
201
            if self.filename in _fcntl_ReadLock._open_locks:
 
202
                if 'strict_locks' in debug.debug_flags:
 
203
                    self._clear_f()
 
204
                    raise errors.LockContention(self.filename)
 
205
                else:
 
206
                    trace.mutter('Write lock taken w/ an open read lock on: %s'
 
207
                                 % (self.filename,))
193
208
 
194
209
            self._open(self.filename, 'rb+')
195
210
            # reserve a slot for this lock - even if the lockf call fails,
196
 
            # at thisi point unlock() will be called, because self.f is set.
 
211
            # at this point unlock() will be called, because self.f is set.
197
212
            # TODO: make this fully threadsafe, if we decide we care.
198
213
            _fcntl_WriteLock._open_locks.add(self.filename)
199
214
            try:
220
235
        def __init__(self, filename):
221
236
            super(_fcntl_ReadLock, self).__init__()
222
237
            self.filename = osutils.realpath(filename)
 
238
            if self.filename in _fcntl_WriteLock._open_locks:
 
239
                if 'strict_locks' in debug.debug_flags:
 
240
                    # We raise before calling _open so we don't need to
 
241
                    # _clear_f
 
242
                    raise errors.LockContention(self.filename)
 
243
                else:
 
244
                    trace.mutter('Read lock taken w/ an open write lock on: %s'
 
245
                                 % (self.filename,))
223
246
            _fcntl_ReadLock._open_locks.setdefault(self.filename, 0)
224
247
            _fcntl_ReadLock._open_locks[self.filename] += 1
225
248
            self._open(filename, 'rb')
418
441
            DWORD,                 # dwFlagsAndAttributes
419
442
            HANDLE                 # hTemplateFile
420
443
        )((_function_name, ctypes.windll.kernel32))
421
 
    
 
444
 
422
445
    INVALID_HANDLE_VALUE = -1
423
 
    
 
446
 
424
447
    GENERIC_READ = 0x80000000
425
448
    GENERIC_WRITE = 0x40000000
426
449
    FILE_SHARE_READ = 1
427
450
    OPEN_ALWAYS = 4
428
451
    FILE_ATTRIBUTE_NORMAL = 128
429
 
    
 
452
 
430
453
    ERROR_ACCESS_DENIED = 5
431
454
    ERROR_SHARING_VIOLATION = 32
432
455
 
503
526
# We default to using the first available lock class.
504
527
_lock_type, WriteLock, ReadLock = _lock_classes[0]
505
528
 
 
529
 
 
530
class _RelockDebugMixin(object):
 
531
    """Mixin support for -Drelock flag.
 
532
 
 
533
    Add this as a base class then call self._note_lock with 'r' or 'w' when
 
534
    acquiring a read- or write-lock.  If this object was previously locked (and
 
535
    locked the same way), and -Drelock is set, then this will trace.note a
 
536
    message about it.
 
537
    """
 
538
 
 
539
    _prev_lock = None
 
540
 
 
541
    def _note_lock(self, lock_type):
 
542
        if 'relock' in debug.debug_flags and self._prev_lock == lock_type:
 
543
            if lock_type == 'r':
 
544
                type_name = 'read'
 
545
            else:
 
546
                type_name = 'write'
 
547
            trace.note(gettext('{0!r} was {1} locked again'), self, type_name)
 
548
        self._prev_lock = lock_type
 
549