~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/lockdir.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-02-23 17:00:36 UTC
  • mfrom: (4032.1.4 jam-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20090223170036-3q1v68ewdt8i0to5
(Marius Kruger) Remove all trailing whitespace and add tests to
        enforce this.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
internal locks (such as flock etc) because they can be seen across all
22
22
transports, including http.
23
23
 
24
 
Objects can be read if there is only physical read access; therefore 
 
24
Objects can be read if there is only physical read access; therefore
25
25
readers can never be required to create a lock, though they will
26
26
check whether a writer is using the lock.  Writers can't detect
27
27
whether anyone else is reading from the resource as they write.
56
56
 
57
57
The desired characteristics are:
58
58
 
59
 
* Locks are not reentrant.  (That is, a client that tries to take a 
 
59
* Locks are not reentrant.  (That is, a client that tries to take a
60
60
  lock it already holds may deadlock or fail.)
61
61
* Stale locks can be guessed at by a heuristic
62
62
* Lost locks can be broken by any client
78
78
and deadlocks will likely occur if the locks are aliased.
79
79
 
80
80
In the future we may add a "freshen" method which can be called
81
 
by a lock holder to check that their lock has not been broken, and to 
 
81
by a lock holder to check that their lock has not been broken, and to
82
82
update the timestamp within it.
83
83
 
84
84
Example usage:
167
167
 
168
168
        :param transport: Transport which will contain the lock
169
169
 
170
 
        :param path: Path to the lock within the base directory of the 
 
170
        :param path: Path to the lock within the base directory of the
171
171
            transport.
172
172
        """
173
173
        self.transport = transport
192
192
    def create(self, mode=None):
193
193
        """Create the on-disk lock.
194
194
 
195
 
        This is typically only called when the object/directory containing the 
 
195
        This is typically only called when the object/directory containing the
196
196
        directory is first created.  The lock is not held when it's created.
197
197
        """
198
198
        self._trace("create lock directory")
204
204
 
205
205
    def _attempt_lock(self):
206
206
        """Make the pending directory and attempt to rename into place.
207
 
        
 
207
 
208
208
        If the rename succeeds, we read back the info file to check that we
209
209
        really got the lock.
210
210
 
255
255
    def _remove_pending_dir(self, tmpname):
256
256
        """Remove the pending directory
257
257
 
258
 
        This is called if we failed to rename into place, so that the pending 
 
258
        This is called if we failed to rename into place, so that the pending
259
259
        dirs don't clutter up the lockdir.
260
260
        """
261
261
        self._trace("remove %s", tmpname)
343
343
            lock_info = '\n'.join(self._format_lock_info(holder_info))
344
344
            if bzrlib.ui.ui_factory.get_boolean("Break %s" % lock_info):
345
345
                self.force_break(holder_info)
346
 
        
 
346
 
347
347
    def force_break(self, dead_holder_info):
348
348
        """Release a lock held by another process.
349
349
 
357
357
        LockBreakMismatch is raised.
358
358
 
359
359
        After the lock is broken it will not be held by any process.
360
 
        It is possible that another process may sneak in and take the 
 
360
        It is possible that another process may sneak in and take the
361
361
        lock before the breaking process acquires it.
362
362
        """
363
363
        if not isinstance(dead_holder_info, dict):
372
372
        tmpname = '%s/broken.%s.tmp' % (self.path, rand_chars(20))
373
373
        self.transport.rename(self._held_dir, tmpname)
374
374
        # check that we actually broke the right lock, not someone else;
375
 
        # there's a small race window between checking it and doing the 
 
375
        # there's a small race window between checking it and doing the
376
376
        # rename.
377
377
        broken_info_path = tmpname + self.__INFO_NAME
378
378
        broken_info = self._read_info_file(broken_info_path)
393
393
        or if the lock has been affected by a bug.
394
394
 
395
395
        If the lock is not thought to be held, raises LockNotHeld.  If
396
 
        the lock is thought to be held but has been broken, raises 
 
396
        the lock is thought to be held but has been broken, raises
397
397
        LockBroken.
398
398
        """
399
399
        if not self._lock_held:
405
405
        if info.get('nonce') != self.nonce:
406
406
            # there is a lock, but not ours
407
407
            raise LockBroken(self)
408
 
        
 
408
 
409
409
    def _read_info_file(self, path):
410
410
        """Read one given info file.
411
411
 
415
415
 
416
416
    def peek(self):
417
417
        """Check if the lock is held by anyone.
418
 
        
 
418
 
419
419
        If it is held, this returns the lock info structure as a rio Stanza,
420
420
        which contains some information about the current lock holder.
421
421
        Otherwise returns None.
449
449
 
450
450
    def attempt_lock(self):
451
451
        """Take the lock; fail if it's already held.
452
 
        
 
452
 
453
453
        If you wish to block until the lock can be obtained, call wait_lock()
454
454
        instead.
455
455
 
476
476
 
477
477
        :param timeout: Approximate maximum amount of time to wait for the
478
478
        lock, in seconds.
479
 
         
 
479
 
480
480
        :param poll: Delay in seconds between retrying the lock.
481
481
 
482
482
        :param max_attempts: Maximum number of times to try to lock.
542
542
            else:
543
543
                self._trace("timeout after waiting %ss", timeout)
544
544
                raise LockContention(self)
545
 
    
 
545
 
546
546
    def leave_in_place(self):
547
547
        self._locked_via_token = True
548
548
 
551
551
 
552
552
    def lock_write(self, token=None):
553
553
        """Wait for and acquire the lock.
554
 
        
 
554
 
555
555
        :param token: if this is already locked, then lock_write will fail
556
556
            unless the token matches the existing lock.
557
557
        :returns: a token if this instance supports tokens, otherwise None.
563
563
        A token should be passed in if you know that you have locked the object
564
564
        some other way, and need to synchronise this object's state with that
565
565
        fact.
566
 
         
 
566
 
567
567
        XXX: docstring duplicated from LockableFiles.lock_write.
568
568
        """
569
569
        if token is not None:
578
578
    def lock_read(self):
579
579
        """Compatibility-mode shared lock.
580
580
 
581
 
        LockDir doesn't support shared read-only locks, so this 
 
581
        LockDir doesn't support shared read-only locks, so this
582
582
        just pretends that the lock is taken but really does nothing.
583
583
        """
584
 
        # At the moment Branches are commonly locked for read, but 
 
584
        # At the moment Branches are commonly locked for read, but
585
585
        # we can't rely on that remotely.  Once this is cleaned up,
586
 
        # reenable this warning to prevent it coming back in 
 
586
        # reenable this warning to prevent it coming back in
587
587
        # -- mbp 20060303
588
588
        ## warn("LockDir.lock_read falls back to write lock")
589
589
        if self._lock_held or self._fake_read_lock: