~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/lockdir.py

  • Committer: Matt Nordhoff
  • Date: 2009-04-04 02:50:01 UTC
  • mfrom: (4253 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4256.
  • Revision ID: mnordhoff@mattnordhoff.com-20090404025001-z1403k0tatmc8l91
Merge bzr.dev, fixing conflicts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""On-disk mutex protecting a resource
18
18
 
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:
125
125
        ResourceBusy,
126
126
        TransportError,
127
127
        )
128
 
from bzrlib.hooks import Hooks
129
128
from bzrlib.trace import mutter, note
130
129
from bzrlib.osutils import format_delta, rand_chars, get_host_name
131
130
import bzrlib.ui
167
166
 
168
167
        :param transport: Transport which will contain the lock
169
168
 
170
 
        :param path: Path to the lock within the base directory of the 
 
169
        :param path: Path to the lock within the base directory of the
171
170
            transport.
172
171
        """
173
172
        self.transport = transport
192
191
    def create(self, mode=None):
193
192
        """Create the on-disk lock.
194
193
 
195
 
        This is typically only called when the object/directory containing the 
 
194
        This is typically only called when the object/directory containing the
196
195
        directory is first created.  The lock is not held when it's created.
197
196
        """
198
197
        self._trace("create lock directory")
204
203
 
205
204
    def _attempt_lock(self):
206
205
        """Make the pending directory and attempt to rename into place.
207
 
        
 
206
 
208
207
        If the rename succeeds, we read back the info file to check that we
209
208
        really got the lock.
210
209
 
255
254
    def _remove_pending_dir(self, tmpname):
256
255
        """Remove the pending directory
257
256
 
258
 
        This is called if we failed to rename into place, so that the pending 
 
257
        This is called if we failed to rename into place, so that the pending
259
258
        dirs don't clutter up the lockdir.
260
259
        """
261
260
        self._trace("remove %s", tmpname)
343
342
            lock_info = '\n'.join(self._format_lock_info(holder_info))
344
343
            if bzrlib.ui.ui_factory.get_boolean("Break %s" % lock_info):
345
344
                self.force_break(holder_info)
346
 
        
 
345
 
347
346
    def force_break(self, dead_holder_info):
348
347
        """Release a lock held by another process.
349
348
 
357
356
        LockBreakMismatch is raised.
358
357
 
359
358
        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 
 
359
        It is possible that another process may sneak in and take the
361
360
        lock before the breaking process acquires it.
362
361
        """
363
362
        if not isinstance(dead_holder_info, dict):
372
371
        tmpname = '%s/broken.%s.tmp' % (self.path, rand_chars(20))
373
372
        self.transport.rename(self._held_dir, tmpname)
374
373
        # check that we actually broke the right lock, not someone else;
375
 
        # there's a small race window between checking it and doing the 
 
374
        # there's a small race window between checking it and doing the
376
375
        # rename.
377
376
        broken_info_path = tmpname + self.__INFO_NAME
378
377
        broken_info = self._read_info_file(broken_info_path)
393
392
        or if the lock has been affected by a bug.
394
393
 
395
394
        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 
 
395
        the lock is thought to be held but has been broken, raises
397
396
        LockBroken.
398
397
        """
399
398
        if not self._lock_held:
405
404
        if info.get('nonce') != self.nonce:
406
405
            # there is a lock, but not ours
407
406
            raise LockBroken(self)
408
 
        
 
407
 
409
408
    def _read_info_file(self, path):
410
409
        """Read one given info file.
411
410
 
415
414
 
416
415
    def peek(self):
417
416
        """Check if the lock is held by anyone.
418
 
        
 
417
 
419
418
        If it is held, this returns the lock info structure as a rio Stanza,
420
419
        which contains some information about the current lock holder.
421
420
        Otherwise returns None.
449
448
 
450
449
    def attempt_lock(self):
451
450
        """Take the lock; fail if it's already held.
452
 
        
 
451
 
453
452
        If you wish to block until the lock can be obtained, call wait_lock()
454
453
        instead.
455
454
 
476
475
 
477
476
        :param timeout: Approximate maximum amount of time to wait for the
478
477
        lock, in seconds.
479
 
         
 
478
 
480
479
        :param poll: Delay in seconds between retrying the lock.
481
480
 
482
481
        :param max_attempts: Maximum number of times to try to lock.
542
541
            else:
543
542
                self._trace("timeout after waiting %ss", timeout)
544
543
                raise LockContention(self)
545
 
    
 
544
 
546
545
    def leave_in_place(self):
547
546
        self._locked_via_token = True
548
547
 
551
550
 
552
551
    def lock_write(self, token=None):
553
552
        """Wait for and acquire the lock.
554
 
        
 
553
 
555
554
        :param token: if this is already locked, then lock_write will fail
556
555
            unless the token matches the existing lock.
557
556
        :returns: a token if this instance supports tokens, otherwise None.
563
562
        A token should be passed in if you know that you have locked the object
564
563
        some other way, and need to synchronise this object's state with that
565
564
        fact.
566
 
         
 
565
 
567
566
        XXX: docstring duplicated from LockableFiles.lock_write.
568
567
        """
569
568
        if token is not None:
578
577
    def lock_read(self):
579
578
        """Compatibility-mode shared lock.
580
579
 
581
 
        LockDir doesn't support shared read-only locks, so this 
 
580
        LockDir doesn't support shared read-only locks, so this
582
581
        just pretends that the lock is taken but really does nothing.
583
582
        """
584
 
        # At the moment Branches are commonly locked for read, but 
 
583
        # At the moment Branches are commonly locked for read, but
585
584
        # we can't rely on that remotely.  Once this is cleaned up,
586
 
        # reenable this warning to prevent it coming back in 
 
585
        # reenable this warning to prevent it coming back in
587
586
        # -- mbp 20060303
588
587
        ## warn("LockDir.lock_read falls back to write lock")
589
588
        if self._lock_held or self._fake_read_lock: