[MERGE] new locks branch
Robert Collins
robertc at robertcollins.net
Wed Feb 22 05:39:14 GMT 2006
On Wed, 2006-02-22 at 16:13 +1100, Martin Pool wrote:
> === added file 'bzrlib/lockdir.py'
> --- /dev/null
> +++ bzrlib/lockdir.py
> @@ -0,0 +1,334 @@
> +# Copyright (C) 2006 Canonical Ltd
> +
> +# This program is free software; you can redistribute it and/or
> modify
> +# it under the terms of the GNU General Public License as published
> by
> +# the Free Software Foundation; either version 2 of the License, or
> +# (at your option) any later version.
> +
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
> 02111-1307 USA
It would be nice to standardise on either:
# comment
#
# continues
or
# comment
# continues
I find the former more clear that its a single comment rather than two.
> +"""lock file protecting a resource
> +
> +bzr objects are locked by the existence of a file with a particular
> name
perhaps 'persistent bzr object' ? Or 'bzr disk objects' ?
...
> +A lock is represented on disk by a directory of a particular name,
> +containing an information file. Taking a lock is done by renaming a
> +temporary directory into place. We use temporary directories because
> +for all known transports and filesystems we believe that exactly one
> +attempt to claim the lock will succeed and the others will fail.
> (Files
> +won't do because some filesystems or transports only have
> +rename-and-overwrite, making it hard to tell who won.)
The first paragraph and this one conflict on what the lock is
represented by ;)
> +The desired characteristics are:
> +
> +* Locks are not reentrant. (That is, a client that tries to take a
> + lock it already holds may deadlock or fail.)
> +* Stale locks can be guessed at by a heuristic
> +* Lost locks can be broken by any client
> +* Failed lock operations leave little or no mess
> +* Deadlocks are avoided by having a timeout always in use, clients
> + desiring indefinite waits can retry or set a silly big timeout.
> +
> +Storage formats use the locks, and also need to consider concurrency
> +issues underneath the lock. A format may choose not to use a lock
> +at all for some operations.
> +
> +LockDirs always operate over a Transport. The transport may be
> readonly, in
> +which case the lock can be queried but not acquired.
> +
> +Locks are identified by a path name, relative to a base transport.
> +
> +Calling code will typically want to make sure there is exactly one
> LockDir
> +object per actual lock on disk. This module does nothing to prevent
> aliasing
> +and deadlocks will likely occur if the locks are aliased.
> +
> +In the future we may add a "freshen" method which can be called
> +by a lock holder to check that their lock has not been broken, and
> to
> +update the timestamp within it.
> +
> +Example usage:
> +
> +>>> from bzrlib.transport.memory import MemoryTransport
> +>>> # typically will be obtained from a BzrDir, Branch, etc
> +>>> t = MemoryTransport()
> +>>> l = LockDir(t, 'sample-lock')
> +>>> l.wait_lock()
> +>>> # do something here
> +>>> l.unlock()
Perhaps the sample usage should be in 'bzrlib.doc.api.lockdir.txt' ?
> +# TODO: After renaming the directory, check the contents are what we
> +# expected. It's possible that the rename failed but the transport
> lost
> +# the failure indication.
For some reason I thought you do this already ?
> +
> +class LockDir(object):
> + """Write-lock guarding access to data.
> + """
PEP8:
class LockDir(object):
"""Write-lock guarding access to data."""
> + INFO_NAME = '/info'
Is this meant to be mutable and public? If not public may I suggest
__INFO_NAME = '/info'
And if not mutable, accessing it via LockDir.__INFO_NAME rather than
self.__INFO_NAME.
We had a thread on the use of class members to initialize instance
members a while back :).
...
> + def attempt_lock(self):
> + """Take the lock; fail if it's already held
missing full stop I think.
> + def unlock(self):
Docstring per favour ?
> + def wait(self, timeout=20, poll=0.5):
> + """Wait a certain period for a lock to be released.
> + """
PEP8 - same line for the closing '"""'.
> +
> +"""Tests for LockDir"""
> +
> +from threading import Thread
> +import time
> +
> +from bzrlib.errors import (
> + LockBreakMismatch,
> + LockContention, LockError, UnlockableTransport,
> + LockNotHeld, LockBroken
> + )
> +from bzrlib.lockdir import LockDir
> +from bzrlib.tests import TestCaseInTempDir, TestCaseWithTransport
Is TestCaseInTempDir used here ?
> ...
> - raise ReadOnlyError("can't upgrade to a write lock
> from %r" %
> - self._lock_mode)
> + raise ReadOnlyError()
I think its useful to specify the lock path here, otherwise figuring out
*which* branch is incorrectly locked will be a biatch.
+1 with the above resolved.
Rob
--
GPG key available at: <http://www.robertcollins.net/keys.txt>.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part
Url : https://lists.ubuntu.com/archives/bazaar/attachments/20060222/876b6aa5/attachment.pgp
More information about the bazaar
mailing list