##// END OF EJS Templates
Merge with stable
Merge with stable

File last commit:

r15589:cc24e4ed default
r17331:ef8d612b merge default
Show More
lock.py
143 lines | 4.5 KiB | text/x-python | PythonLexer
Greg Ward
localrepo: document the locking scheme a little better...
r9309 # lock.py - simple advisory locking scheme for mercurial
mpm@selenic.com
Simply repository locking...
r161 #
Vadim Gelfer
update copyrights.
r2859 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
mpm@selenic.com
Simply repository locking...
r161 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
mpm@selenic.com
Simply repository locking...
r161
Simon Heimberg
separate import lines from mercurial and general python modules
r8312 import util, error
import errno, os, socket, time
Ronny Pfannschmidt
add a deprecation warning for gc based lock releasing
r8113 import warnings
mpm@selenic.com
Simply repository locking...
r161
Eric Hopper
Convert all classes to new-style classes by deriving them from object.
r1559 class lock(object):
Greg Ward
localrepo: document the locking scheme a little better...
r9309 '''An advisory lock held by one process to control access to a set
of files. Non-cooperating processes or incorrectly written scripts
can ignore Mercurial's locking scheme and stomp all over the
repository, so don't do that.
Typically used via localrepository.lock() to lock the repository
store (.hg/store/) or localrepository.wlock() to lock everything
else under .hg/.'''
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 # lock is symlink on platforms that support it, file on others.
# symlink is used because create of directory entry and contents
# are atomic even over nfs.
# old-style lock: symlink to pid
# new-style lock: symlink to hostname:pid
Bryan O'Sullivan
lock.py: cache hostname, but not pid, in case we fork
r4947 _host = None
Vadim Gelfer
fix backtrace printed when cannot get lock....
r2016 def __init__(self, file, timeout=-1, releasefn=None, desc=None):
mpm@selenic.com
Simply repository locking...
r161 self.f = file
self.held = 0
Benoit Boissinot
add a timeout when a lock is held (default 1024 sec)...
r1787 self.timeout = timeout
Benoit Boissinot
add a releasefn keyword to lock.lock...
r1530 self.releasefn = releasefn
Vadim Gelfer
fix backtrace printed when cannot get lock....
r2016 self.desc = desc
Matt Mackall
lock: change name of release chain
r15589 self.postrelease = []
mpm@selenic.com
Simply repository locking...
r161 self.lock()
def __del__(self):
Ronny Pfannschmidt
made repo locks recursive and deprecate refcounting based lock releasing...
r8108 if self.held:
Ronny Pfannschmidt
add a deprecation warning for gc based lock releasing
r8113 warnings.warn("use lock.release instead of del lock",
category=DeprecationWarning,
stacklevel=2)
Ronny Pfannschmidt
made repo locks recursive and deprecate refcounting based lock releasing...
r8108 # ensure the lock will be removed
# even if recursive locking did occur
self.held = 1
mpm@selenic.com
Simply repository locking...
r161 self.release()
def lock(self):
Benoit Boissinot
add a timeout when a lock is held (default 1024 sec)...
r1787 timeout = self.timeout
Martin Geisler
check-code: flag 0/1 used as constant Boolean expression
r14494 while True:
mpm@selenic.com
Simply repository locking...
r161 try:
self.trylock()
return 1
Matt Mackall
error: move lock errors...
r7640 except error.LockHeld, inst:
Benoit Boissinot
add a timeout when a lock is held (default 1024 sec)...
r1787 if timeout != 0:
mpm@selenic.com
Simply repository locking...
r161 time.sleep(1)
Benoit Boissinot
add a timeout when a lock is held (default 1024 sec)...
r1787 if timeout > 0:
timeout -= 1
mpm@selenic.com
Simply repository locking...
r161 continue
Matt Mackall
error: move lock errors...
r7640 raise error.LockHeld(errno.ETIMEDOUT, inst.filename, self.desc,
inst.locker)
mpm@selenic.com
Whitespace cleanups...
r515
mpm@selenic.com
Simply repository locking...
r161 def trylock(self):
Ronny Pfannschmidt
made repo locks recursive and deprecate refcounting based lock releasing...
r8108 if self.held:
self.held += 1
return
Bryan O'Sullivan
lock.py: cache hostname, but not pid, in case we fork
r4947 if lock._host is None:
lock._host = socket.gethostname()
Thomas Arendsen Hein
Use format string for lockname again (was changed by 3e25a6eb5c9a)
r4959 lockname = '%s:%s' % (lock._host, os.getpid())
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 while not self.held:
try:
Bryan O'Sullivan
lock.py: cache hostname, but not pid, in case we fork
r4947 util.makelock(lockname, self.f)
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 self.held = 1
except (OSError, IOError), why:
if why.errno == errno.EEXIST:
locker = self.testlock()
Thomas Arendsen Hein
Don't step into an endless loop when lock file is empty.
r3686 if locker is not None:
Matt Mackall
error: move lock errors...
r7640 raise error.LockHeld(errno.EAGAIN, self.f, self.desc,
locker)
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 else:
Matt Mackall
error: move lock errors...
r7640 raise error.LockUnavailable(why.errno, why.strerror,
why.filename, self.desc)
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877
def testlock(self):
Thomas Arendsen Hein
Don't step into an endless loop when lock file is empty.
r3686 """return id of locker if lock is valid, else None.
If old-style lock, we cannot tell what machine locker is on.
with new-style lock, if locker is on this machine, we can
see if locker is alive. If locker is on this machine but
not alive, we can safely break lock.
The lock file is only deleted when None is returned.
"""
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 locker = util.readlock(self.f)
Benoit Boissinot
use __contains__, index or split instead of str.find...
r2579 try:
host, pid = locker.split(":", 1)
except ValueError:
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 return locker
Bryan O'Sullivan
lock.py: cache hostname, but not pid, in case we fork
r4947 if host != lock._host:
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 return locker
mpm@selenic.com
Simply repository locking...
r161 try:
Benoit Boissinot
use __contains__, index or split instead of str.find...
r2579 pid = int(pid)
Benoit Boissinot
lock: catch specific exceptions
r9685 except ValueError:
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 return locker
if util.testpid(pid):
return locker
# if locker dead, break lock. must do this with another lock
# held, or can race and break valid lock.
try:
Benoit Boissinot
lock: the correct way to do a trylock() is to use a timeout of 0
r9858 l = lock(self.f + '.break', timeout=0)
Adrian Buehlmann
lock: use util.unlink (issue2537)
r13281 util.unlink(self.f)
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 l.release()
Matt Mackall
error: move lock errors...
r7640 except error.LockError:
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 return locker
mpm@selenic.com
Simply repository locking...
r161
def release(self):
Pierre-Yves David
lock: add mechanism to register post release callback
r15583 """release the lock and execute callback function if any
If the lock have been aquired multiple time, the actual release is
delayed to the last relase call."""
Ronny Pfannschmidt
made repo locks recursive and deprecate refcounting based lock releasing...
r8108 if self.held > 1:
self.held -= 1
Benoit Boissinot
lock: use '==' instead of 'is' for integer equality ('is' may not work)
r9680 elif self.held == 1:
mpm@selenic.com
Simply repository locking...
r161 self.held = 0
Benoit Boissinot
add a releasefn keyword to lock.lock...
r1530 if self.releasefn:
self.releasefn()
mpm@selenic.com
Fix troubles with clone and exception handling...
r503 try:
Adrian Buehlmann
lock: use util.unlink (issue2537)
r13281 util.unlink(self.f)
Benoit Boissinot
lock: catch specific exceptions
r9685 except OSError:
pass
Matt Mackall
lock: change name of release chain
r15589 for callback in self.postrelease:
Pierre-Yves David
lock: add mechanism to register post release callback
r15583 callback()
mpm@selenic.com
Simply repository locking...
r161
Ronny Pfannschmidt
made repo locks recursive and deprecate refcounting based lock releasing...
r8108 def release(*locks):
for lock in locks:
if lock is not None:
lock.release()