/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/lockable_files.py

  • Committer: Martin Pool
  • Date: 2009-03-12 02:45:17 UTC
  • mfrom: (4121 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4123.
  • Revision ID: mbp@sourcefrog.net-20090312024517-43rws5frloylav7b
merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
43
43
# somewhat redundant with what's done in LockDir; the main difference is that
44
44
# LockableFiles permits reentrancy.
45
45
 
 
46
class _LockWarner(object):
 
47
    """Hold a counter for a lock and warn if GCed while the count is >= 1.
 
48
 
 
49
    This is separate from LockableFiles because putting a __del__ on
 
50
    LockableFiles can result in uncollectable cycles.
 
51
    """
 
52
 
 
53
    def __init__(self, repr):
 
54
        self.lock_count = 0
 
55
        self.repr = repr
 
56
 
 
57
    def __del__(self):
 
58
        if self.lock_count >= 1:
 
59
            # There should have been a try/finally to unlock this.
 
60
            warnings.warn("%r was gc'd while locked" % self.repr)
 
61
 
 
62
 
46
63
class LockableFiles(object):
47
64
    """Object representing a set of related files locked within the same scope.
48
65
 
88
105
        self.lock_name = lock_name
89
106
        self._transaction = None
90
107
        self._lock_mode = None
91
 
        self._lock_count = 0
 
108
        self._lock_warner = _LockWarner(repr(self))
92
109
        self._find_modes()
93
110
        esc_name = self._escape(lock_name)
94
111
        self._lock = lock_class(transport, esc_name,
109
126
    def __str__(self):
110
127
        return 'LockableFiles(%s, %s)' % (self.lock_name, self._transport.base)
111
128
 
112
 
    def __del__(self):
113
 
        if self.is_locked():
114
 
            # do not automatically unlock; there should have been a
115
 
            # try/finally to unlock this.
116
 
            warnings.warn("%r was gc'd while locked" % self)
117
 
 
118
129
    def break_lock(self):
119
130
        """Break the lock of this lockable files group if it is held.
120
131
 
253
264
            if self._lock_mode != 'w' or not self.get_transaction().writeable():
254
265
                raise errors.ReadOnlyError(self)
255
266
            self._lock.validate_token(token)
256
 
            self._lock_count += 1
 
267
            self._lock_warner.lock_count += 1
257
268
            return self._token_from_lock
258
269
        else:
259
270
            token_from_lock = self._lock.lock_write(token=token)
260
271
            #traceback.print_stack()
261
272
            self._lock_mode = 'w'
262
 
            self._lock_count = 1
 
273
            self._lock_warner.lock_count = 1
263
274
            self._set_transaction(transactions.WriteTransaction())
264
275
            self._token_from_lock = token_from_lock
265
276
            return token_from_lock
268
279
        if self._lock_mode:
269
280
            if self._lock_mode not in ('r', 'w'):
270
281
                raise ValueError("invalid lock mode %r" % (self._lock_mode,))
271
 
            self._lock_count += 1
 
282
            self._lock_warner.lock_count += 1
272
283
        else:
273
284
            self._lock.lock_read()
274
285
            #traceback.print_stack()
275
286
            self._lock_mode = 'r'
276
 
            self._lock_count = 1
 
287
            self._lock_warner.lock_count = 1
277
288
            self._set_transaction(transactions.ReadOnlyTransaction())
278
289
            # 5K may be excessive, but hey, its a knob.
279
290
            self.get_transaction().set_cache_size(5000)
281
292
    def unlock(self):
282
293
        if not self._lock_mode:
283
294
            raise errors.LockNotHeld(self)
284
 
        if self._lock_count > 1:
285
 
            self._lock_count -= 1
 
295
        if self._lock_warner.lock_count > 1:
 
296
            self._lock_warner.lock_count -= 1
286
297
        else:
287
298
            #traceback.print_stack()
288
299
            self._finish_transaction()
289
300
            try:
290
301
                self._lock.unlock()
291
302
            finally:
292
 
                self._lock_mode = self._lock_count = None
 
303
                self._lock_mode = self._lock_warner.lock_count = None
 
304
 
 
305
    @property
 
306
    def _lock_count(self):
 
307
        return self._lock_warner.lock_count
293
308
 
294
309
    def is_locked(self):
295
310
        """Return true if this LockableFiles group is locked"""
296
 
        return self._lock_count >= 1
 
311
        return self._lock_warner.lock_count >= 1
297
312
 
298
313
    def get_physical_lock_status(self):
299
314
        """Return physical lock status.