~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/lock.py

NEWS section template into a separate file

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 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
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
 
17
 
17
18
"""Locking using OS file locks or file existence.
18
19
 
19
20
Note: This method of locking is generally deprecated in favour of LockDir, but
33
34
unlock() method.
34
35
"""
35
36
 
36
 
from __future__ import absolute_import
37
 
 
38
 
import contextlib
39
37
import errno
40
38
import os
41
39
import sys
47
45
    osutils,
48
46
    trace,
49
47
    )
50
 
from bzrlib.hooks import Hooks
51
 
from bzrlib.i18n import gettext
 
48
from bzrlib.hooks import HookPoint, Hooks
 
49
 
52
50
 
53
51
class LockHooks(Hooks):
54
52
 
55
53
    def __init__(self):
56
 
        Hooks.__init__(self, "bzrlib.lock", "Lock.hooks")
57
 
        self.add_hook('lock_acquired',
58
 
            "Called with a bzrlib.lock.LockResult when a physical lock is "
59
 
            "acquired.", (1, 8))
60
 
        self.add_hook('lock_released',
61
 
            "Called with a bzrlib.lock.LockResult when a physical lock is "
62
 
            "released.", (1, 8))
63
 
        self.add_hook('lock_broken',
64
 
            "Called with a bzrlib.lock.LockResult when a physical lock is "
65
 
            "broken.", (1, 15))
 
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))
66
64
 
67
65
 
68
66
class Lock(object):
86
84
        return self.lock_url == other.lock_url and self.details == other.details
87
85
 
88
86
    def __repr__(self):
89
 
        return '%s(%s, %s)' % (self.__class__.__name__,
 
87
        return '%s(%s%s)' % (self.__class__.__name__,
90
88
                             self.lock_url, self.details)
91
89
 
92
90
 
93
 
class LogicalLockResult(object):
94
 
    """The result of a lock_read/lock_write/lock_tree_write call on lockables.
95
 
 
96
 
    :ivar unlock: A callable which will unlock the lock.
97
 
    """
98
 
 
99
 
    def __init__(self, unlock):
100
 
        self.unlock = unlock
101
 
 
102
 
    def __repr__(self):
103
 
        return "LogicalLockResult(%s)" % (self.unlock)
104
 
 
105
 
 
106
 
 
107
91
def cant_unlock_not_held(locked_object):
108
92
    """An attempt to unlock failed because the object was not locked.
109
93
 
173
157
            self.f.close()
174
158
            self.f = None
175
159
 
 
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
 
176
166
    def unlock(self):
177
167
        raise NotImplementedError()
178
168
 
210
200
 
211
201
            self._open(self.filename, 'rb+')
212
202
            # reserve a slot for this lock - even if the lockf call fails,
213
 
            # at this point unlock() will be called, because self.f is set.
 
203
            # at thisi point unlock() will be called, because self.f is set.
214
204
            # TODO: make this fully threadsafe, if we decide we care.
215
205
            _fcntl_WriteLock._open_locks.add(self.filename)
216
206
            try:
528
518
# We default to using the first available lock class.
529
519
_lock_type, WriteLock, ReadLock = _lock_classes[0]
530
520
 
531
 
 
532
 
class _RelockDebugMixin(object):
533
 
    """Mixin support for -Drelock flag.
534
 
 
535
 
    Add this as a base class then call self._note_lock with 'r' or 'w' when
536
 
    acquiring a read- or write-lock.  If this object was previously locked (and
537
 
    locked the same way), and -Drelock is set, then this will trace.note a
538
 
    message about it.
539
 
    """
540
 
 
541
 
    _prev_lock = None
542
 
 
543
 
    def _note_lock(self, lock_type):
544
 
        if 'relock' in debug.debug_flags and self._prev_lock == lock_type:
545
 
            if lock_type == 'r':
546
 
                type_name = 'read'
547
 
            else:
548
 
                type_name = 'write'
549
 
            trace.note(gettext('{0!r} was {1} locked again'), self, type_name)
550
 
        self._prev_lock = lock_type
551
 
 
552
 
@contextlib.contextmanager
553
 
def write_locked(lockable):
554
 
    lockable.lock_write()
555
 
    try:
556
 
        yield lockable
557
 
    finally:
558
 
        lockable.unlock()