~ubuntu-branches/debian/sid/bzr/sid-201308041036

« back to all changes in this revision

Viewing changes to bzrlib/lockable_files.py

  • Committer: Bazaar Package Importer
  • Author(s): Jelmer Vernooij, Jelmer Vernooij, Max Bowsher
  • Date: 2011-07-14 15:35:42 UTC
  • mfrom: (1.5.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20110714153542-7m3m8jpt6c167g2a
Tags: 2.4.0~beta5-1
[ Jelmer Vernooij ]
* Fix typo in package description. Thanks Paul Stewart.
* Mark python-bzrlib as breaking with older versions of bzr that
  predate python-bzrlib. LP: #803362

[ Max Bowsher ]
* New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
    )
34
34
 
35
35
 
36
 
# XXX: The tracking here of lock counts and whether the lock is held is
37
 
# somewhat redundant with what's done in LockDir; the main difference is that
38
 
# LockableFiles permits reentrancy.
39
 
 
40
 
class _LockWarner(object):
41
 
    """Hold a counter for a lock and warn if GCed while the count is >= 1.
42
 
 
43
 
    This is separate from LockableFiles because putting a __del__ on
44
 
    LockableFiles can result in uncollectable cycles.
45
 
    """
46
 
 
47
 
    def __init__(self, repr):
48
 
        self.lock_count = 0
49
 
        self.repr = repr
50
 
 
51
 
    def __del__(self):
52
 
        if self.lock_count >= 1:
53
 
            # There should have been a try/finally to unlock this.
54
 
            warnings.warn("%r was gc'd while locked" % self.repr)
55
 
 
56
 
 
57
36
class LockableFiles(object):
58
37
    """Object representing a set of related files locked within the same scope.
59
38
 
68
47
    This class is now deprecated; code should move to using the Transport
69
48
    directly for file operations and using the lock or CountedLock for
70
49
    locking.
71
 
    
 
50
 
72
51
    :ivar _lock: The real underlying lock (e.g. a LockDir)
73
 
    :ivar _counted_lock: A lock decorated with a semaphore, so that it 
74
 
        can be re-entered.
 
52
    :ivar _lock_count: If _lock_mode is true, a positive count of the number
 
53
        of times the lock has been taken (and not yet released) *by this
 
54
        process*, through this particular object instance.
 
55
    :ivar _lock_mode: None, or 'r' or 'w'
75
56
    """
76
57
 
77
 
    # _lock_mode: None, or 'r' or 'w'
78
 
 
79
 
    # _lock_count: If _lock_mode is true, a positive count of the number of
80
 
    # times the lock has been taken *by this process*.
81
 
 
82
58
    def __init__(self, transport, lock_name, lock_class):
83
59
        """Create a LockableFiles group
84
60
 
92
68
        self.lock_name = lock_name
93
69
        self._transaction = None
94
70
        self._lock_mode = None
95
 
        self._lock_warner = _LockWarner(repr(self))
 
71
        self._lock_count = 0
96
72
        self._find_modes()
97
73
        esc_name = self._escape(lock_name)
98
74
        self._lock = lock_class(transport, esc_name,
111
87
    def __repr__(self):
112
88
        return '%s(%r)' % (self.__class__.__name__,
113
89
                           self._transport)
 
90
 
114
91
    def __str__(self):
115
92
        return 'LockableFiles(%s, %s)' % (self.lock_name, self._transport.base)
116
93
 
174
151
        some other way, and need to synchronise this object's state with that
175
152
        fact.
176
153
        """
177
 
        # TODO: Upgrade locking to support using a Transport,
178
 
        # and potentially a remote locking protocol
179
154
        if self._lock_mode:
180
 
            if self._lock_mode != 'w' or not self.get_transaction().writeable():
 
155
            if (self._lock_mode != 'w'
 
156
                or not self.get_transaction().writeable()):
181
157
                raise errors.ReadOnlyError(self)
182
158
            self._lock.validate_token(token)
183
 
            self._lock_warner.lock_count += 1
 
159
            self._lock_count += 1
184
160
            return self._token_from_lock
185
161
        else:
186
162
            token_from_lock = self._lock.lock_write(token=token)
187
163
            #traceback.print_stack()
188
164
            self._lock_mode = 'w'
189
 
            self._lock_warner.lock_count = 1
 
165
            self._lock_count = 1
190
166
            self._set_write_transaction()
191
167
            self._token_from_lock = token_from_lock
192
168
            return token_from_lock
195
171
        if self._lock_mode:
196
172
            if self._lock_mode not in ('r', 'w'):
197
173
                raise ValueError("invalid lock mode %r" % (self._lock_mode,))
198
 
            self._lock_warner.lock_count += 1
 
174
            self._lock_count += 1
199
175
        else:
200
176
            self._lock.lock_read()
201
177
            #traceback.print_stack()
202
178
            self._lock_mode = 'r'
203
 
            self._lock_warner.lock_count = 1
 
179
            self._lock_count = 1
204
180
            self._set_read_transaction()
205
181
 
206
182
    def _set_read_transaction(self):
217
193
    def unlock(self):
218
194
        if not self._lock_mode:
219
195
            return lock.cant_unlock_not_held(self)
220
 
        if self._lock_warner.lock_count > 1:
221
 
            self._lock_warner.lock_count -= 1
 
196
        if self._lock_count > 1:
 
197
            self._lock_count -= 1
222
198
        else:
223
199
            #traceback.print_stack()
224
200
            self._finish_transaction()
225
201
            try:
226
202
                self._lock.unlock()
227
203
            finally:
228
 
                self._lock_mode = self._lock_warner.lock_count = None
229
 
 
230
 
    @property
231
 
    def _lock_count(self):
232
 
        return self._lock_warner.lock_count
 
204
                self._lock_mode = self._lock_count = None
233
205
 
234
206
    def is_locked(self):
235
207
        """Return true if this LockableFiles group is locked"""
236
 
        return self._lock_warner.lock_count >= 1
 
208
        return self._lock_count >= 1
237
209
 
238
210
    def get_physical_lock_status(self):
239
211
        """Return physical lock status.
325
297
    def validate_token(self, token):
326
298
        if token is not None:
327
299
            raise errors.TokenLockingNotSupported(self)
328