##// END OF EJS Templates
copies: no longer cache the ChangedFiles during copy tracing...
copies: no longer cache the ChangedFiles during copy tracing Now that the copies information for both parents are processed all at once, we no longer needs to cache this information, so we simplify the code. The simpler code is also a (tiny) bit faster overall. Repo Case Source-Rev Dest-Rev # of revisions old time new time Difference Factor time per rev --------------------------------------------------------------------------------------------------------------------------------------------------------------- mercurial x_revs_x_added_0_copies ad6b123de1c7 39cfcef4f463 : 1 revs, 0.000041 s, 0.000041 s, +0.000000 s, × 1.0000, 41 µs/rev mercurial x_revs_x_added_x_copies 2b1c78674230 0c1d10351869 : 6 revs, 0.000102 s, 0.000096 s, -0.000006 s, × 0.9412, 16 µs/rev mercurial x000_revs_x000_added_x_copies 81f8ff2a9bf2 dd3267698d84 : 1032 revs, 0.004254 s, 0.004039 s, -0.000215 s, × 0.9495, 3 µs/rev pypy x_revs_x_added_0_copies aed021ee8ae8 099ed31b181b : 9 revs, 0.000282 s, 0.000189 s, -0.000093 s, × 0.6702, 21 µs/rev pypy x_revs_x000_added_0_copies 4aa4e1f8e19a 359343b9ac0e : 1 revs, 0.000048 s, 0.000047 s, -0.000001 s, × 0.9792, 47 µs/rev pypy x_revs_x_added_x_copies ac52eb7bbbb0 72e022663155 : 7 revs, 0.000211 s, 0.000103 s, -0.000108 s, × 0.4882, 14 µs/rev pypy x_revs_x00_added_x_copies c3b14617fbd7 ace7255d9a26 : 1 revs, 0.000375 s, 0.000286 s, -0.000089 s, × 0.7627, 286 µs/rev pypy x_revs_x000_added_x000_copies df6f7a526b60 a83dc6a2d56f : 6 revs, 0.010574 s, 0.010436 s, -0.000138 s, × 0.9869, 1739 µs/rev pypy x000_revs_xx00_added_0_copies 89a76aede314 2f22446ff07e : 4785 revs, 0.049974 s, 0.047465 s, -0.002509 s, × 0.9498, 9 µs/rev pypy x000_revs_x000_added_x_copies 8a3b5bfd266e 2c68e87c3efe : 6780 revs, 0.084300 s, 0.082351 s, -0.001949 s, × 0.9769, 12 µs/rev pypy x000_revs_x000_added_x000_copies 89a76aede314 7b3dda341c84 : 5441 revs, 0.060128 s, 0.058757 s, -0.001371 s, × 0.9772, 10 µs/rev pypy x0000_revs_x_added_0_copies d1defd0dc478 c9cb1334cc78 : 43645 revs, 0.686542 s, 0.674129 s, -0.012413 s, × 0.9819, 15 µs/rev pypy x0000_revs_xx000_added_0_copies bf2c629d0071 4ffed77c095c : 2 revs, 0.009277 s, 0.009434 s, +0.000157 s, × 1.0169, 4717 µs/rev pypy x0000_revs_xx000_added_x000_copies 08ea3258278e d9fa043f30c0 : 11316 revs, 0.114733 s, 0.111935 s, -0.002798 s, × 0.9756, 9 µs/rev netbeans x_revs_x_added_0_copies fb0955ffcbcd a01e9239f9e7 : 2 revs, 0.000081 s, 0.000078 s, -0.000003 s, × 0.9630, 39 µs/rev netbeans x_revs_x000_added_0_copies 6f360122949f 20eb231cc7d0 : 2 revs, 0.000107 s, 0.000106 s, -0.000001 s, × 0.9907, 53 µs/rev netbeans x_revs_x_added_x_copies 1ada3faf6fb6 5a39d12eecf4 : 3 revs, 0.000173 s, 0.000162 s, -0.000011 s, × 0.9364, 54 µs/rev netbeans x_revs_x00_added_x_copies 35be93ba1e2c 9eec5e90c05f : 9 revs, 0.000698 s, 0.000695 s, -0.000003 s, × 0.9957, 77 µs/rev netbeans x000_revs_xx00_added_0_copies eac3045b4fdd 51d4ae7f1290 : 1421 revs, 0.009248 s, 0.008901 s, -0.000347 s, × 0.9625, 6 µs/rev netbeans x000_revs_x000_added_x_copies e2063d266acd 6081d72689dc : 1533 revs, 0.015446 s, 0.014333 s, -0.001113 s, × 0.9279, 9 µs/rev netbeans x000_revs_x000_added_x000_copies ff453e9fee32 411350406ec2 : 5750 revs, 0.074373 s, 0.071998 s, -0.002375 s, × 0.9681, 12 µs/rev netbeans x0000_revs_xx000_added_x000_copies 588c2d1ced70 1aad62e59ddd : 66949 revs, 0.639870 s, 0.615346 s, -0.024524 s, × 0.9617, 9 µs/rev mozilla-central x_revs_x_added_0_copies 3697f962bb7b 7015fcdd43a2 : 2 revs, 0.000088 s, 0.000085 s, -0.000003 s, × 0.9659, 42 µs/rev mozilla-central x_revs_x000_added_0_copies dd390860c6c9 40d0c5bed75d : 8 revs, 0.000199 s, 0.000199 s, +0.000000 s, × 1.0000, 24 µs/rev mozilla-central x_revs_x_added_x_copies 8d198483ae3b 14207ffc2b2f : 9 revs, 0.000171 s, 0.000169 s, -0.000002 s, × 0.9883, 18 µs/rev mozilla-central x_revs_x00_added_x_copies 98cbc58cc6bc 446a150332c3 : 7 revs, 0.000592 s, 0.000590 s, -0.000002 s, × 0.9966, 84 µs/rev mozilla-central x_revs_x000_added_x000_copies 3c684b4b8f68 0a5e72d1b479 : 3 revs, 0.003151 s, 0.003122 s, -0.000029 s, × 0.9908, 1040 µs/rev mozilla-central x_revs_x0000_added_x0000_copies effb563bb7e5 c07a39dc4e80 : 6 revs, 0.061612 s, 0.061192 s, -0.000420 s, × 0.9932, 10198 µs/rev mozilla-central x000_revs_xx00_added_0_copies 6100d773079a 04a55431795e : 1593 revs, 0.005381 s, 0.005137 s, -0.000244 s, × 0.9547, 3 µs/rev mozilla-central x000_revs_x000_added_x_copies 9f17a6fc04f9 2d37b966abed : 41 revs, 0.003742 s, 0.003585 s, -0.000157 s, × 0.9580, 87 µs/rev mozilla-central x000_revs_x000_added_x000_copies 7c97034feb78 4407bd0c6330 : 7839 revs, 0.061983 s, 0.060592 s, -0.001391 s, × 0.9776, 7 µs/rev mozilla-central x0000_revs_xx000_added_0_copies 9eec5917337d 67118cc6dcad : 615 revs, 0.019861 s, 0.019596 s, -0.000265 s, × 0.9867, 31 µs/rev mozilla-central x0000_revs_xx000_added_x000_copies f78c615a656c 96a38b690156 : 30263 revs, 0.188101 s, 0.183558 s, -0.004543 s, × 0.9758, 6 µs/rev mozilla-central x00000_revs_x0000_added_x0000_copies 6832ae71433c 4c222a1d9a00 : 153721 revs, 1.806696 s, 1.758083 s, -0.048613 s, × 0.9731, 11 µs/rev mozilla-central x00000_revs_x00000_added_x000_copies 76caed42cf7c 1daa622bbe42 : 204976 revs, 2.682987 s, 2.592955 s, -0.090032 s, × 0.9664, 12 µs/rev mozilla-try x_revs_x_added_0_copies aaf6dde0deb8 9790f499805a : 2 revs, 0.000852 s, 0.000844 s, -0.000008 s, × 0.9906, 422 µs/rev mozilla-try x_revs_x000_added_0_copies d8d0222927b4 5bb8ce8c7450 : 2 revs, 0.000859 s, 0.000861 s, +0.000002 s, × 1.0023, 430 µs/rev mozilla-try x_revs_x_added_x_copies 092fcca11bdb 936255a0384a : 4 revs, 0.000150 s, 0.000150 s, +0.000000 s, × 1.0000, 37 µs/rev mozilla-try x_revs_x00_added_x_copies b53d2fadbdb5 017afae788ec : 2 revs, 0.001158 s, 0.001166 s, +0.000008 s, × 1.0069, 583 µs/rev mozilla-try x_revs_x000_added_x000_copies 20408ad61ce5 6f0ee96e21ad : 1 revs, 0.027240 s, 0.027359 s, +0.000119 s, × 1.0044, 27359 µs/rev mozilla-try x_revs_x0000_added_x0000_copies effb563bb7e5 c07a39dc4e80 : 6 revs, 0.062824 s, 0.061848 s, -0.000976 s, × 0.9845, 10308 µs/rev mozilla-try x000_revs_xx00_added_0_copies 6100d773079a 04a55431795e : 1593 revs, 0.005463 s, 0.005110 s, -0.000353 s, × 0.9354, 3 µs/rev mozilla-try x000_revs_x000_added_x_copies 9f17a6fc04f9 2d37b966abed : 41 revs, 0.004238 s, 0.004168 s, -0.000070 s, × 0.9835, 101 µs/rev mozilla-try x000_revs_x000_added_x000_copies 1346fd0130e4 4c65cbdabc1f : 6657 revs, 0.064113 s, 0.063414 s, -0.000699 s, × 0.9891, 9 µs/rev mozilla-try x0000_revs_x_added_0_copies 63519bfd42ee a36a2a865d92 : 40314 revs, 0.294063 s, 0.288301 s, -0.005762 s, × 0.9804, 7 µs/rev mozilla-try x0000_revs_x_added_x_copies 9fe69ff0762d bcabf2a78927 : 38690 revs, 0.281493 s, 0.275798 s, -0.005695 s, × 0.9798, 7 µs/rev mozilla-try x0000_revs_xx000_added_x_copies 156f6e2674f2 4d0f2c178e66 : 8598 revs, 0.076323 s, 0.074640 s, -0.001683 s, × 0.9779, 8 µs/rev mozilla-try x0000_revs_xx000_added_0_copies 9eec5917337d 67118cc6dcad : 615 revs, 0.020390 s, 0.020327 s, -0.000063 s, × 0.9969, 33 µs/rev mozilla-try x0000_revs_xx000_added_x000_copies 89294cd501d9 7ccb2fc7ccb5 : 97052 revs, 3.023879 s, 2.970385 s, -0.053494 s, × 0.9823, 30 µs/rev mozilla-try x0000_revs_x0000_added_x0000_copies e928c65095ed e951f4ad123a : 52031 revs, 0.735549 s, 0.719432 s, -0.016117 s, × 0.9781, 13 µs/rev mozilla-try x00000_revs_x_added_0_copies 6a320851d377 1ebb79acd503 : 363753 revs, 18.568900 s, 18.165143 s, -0.403757 s, × 0.9783, 49 µs/rev mozilla-try x00000_revs_x00000_added_0_copies dc8a3ca7010e d16fde900c9c : 34414 revs, 0.502584 s, 0.486769 s, -0.015815 s, × 0.9685, 14 µs/rev mozilla-try x00000_revs_x_added_x_copies 5173c4b6f97c 95d83ee7242d : 362229 revs, 18.356645 s, 17.913924 s, -0.442721 s, × 0.9759, 49 µs/rev mozilla-try x00000_revs_x000_added_x_copies 9126823d0e9c ca82787bb23c : 359344 revs, 18.250393 s, 17.660113 s, -0.590280 s, × 0.9677, 49 µs/rev mozilla-try x00000_revs_x0000_added_x0000_copies 8d3fafa80d4b eb884023b810 : 192665 revs, 2.792459 s, 2.709446 s, -0.083013 s, × 0.9703, 14 µs/rev mozilla-try x00000_revs_x00000_added_x0000_copies 1b661134e2ca 1ae03d022d6d : 228985 revs, 107.697264 s, 107.796891 s, +0.099627 s, × 1.0009, 470 µs/rev mozilla-try x00000_revs_x00000_added_x000_copies 9b2a99adc05e 8e29777b48e6 : 382065 revs, 63.961040 s, 63.575217 s, -0.385823 s, × 0.9940, 166 µs/rev Differential Revision: https://phab.mercurial-scm.org/D9423

File last commit:

r46554:89a2afe3 default
r46765:a132aa59 default
Show More
lock.py
397 lines | 11.9 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
Gregory Szorc
lock: use absolute_import
r25956 from __future__ import absolute_import
Siddharth Agarwal
lock: turn prepinherit/reacquire into a single context manager...
r26473 import contextlib
Gregory Szorc
lock: use absolute_import
r25956 import errno
Jun Wu
lock: include Linux pid namespace identifier in prefix...
r30921 import os
Yuya Nishihara
lock: block signal interrupt while making a lock file...
r36717 import signal
Gregory Szorc
lock: use absolute_import
r25956 import socket
import time
Ronny Pfannschmidt
add a deprecation warning for gc based lock releasing
r8113 import warnings
mpm@selenic.com
Simply repository locking...
r161
Boris Feld
lock: add a trylock method handling the timeout and messaging logic...
r35209 from .i18n import _
Gregory Szorc
py3: manually import getattr where it is needed...
r43359 from .pycompat import getattr
Boris Feld
lock: add a trylock method handling the timeout and messaging logic...
r35209
Gregory Szorc
lock: use absolute_import
r25956 from . import (
Augie Fackler
lock: encode result of gethostname into a bytestring
r31375 encoding,
Gregory Szorc
lock: use absolute_import
r25956 error,
Jun Wu
lock: include Linux pid namespace identifier in prefix...
r30921 pycompat,
Yuya Nishihara
lock: add internal config to not replace signal handlers while locking...
r38157 util,
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 )
Augie Fackler
formatting: blacken the codebase...
r43346 from .utils import procutil
Gregory Szorc
lock: use absolute_import
r25956
Jun Wu
lock: move lock._host calculation to a function...
r30920 def _getlockprefix():
"""Return a string which is used to differentiate pid namespaces
It's useful to detect "dead" processes and remove stale locks with
Jun Wu
lock: include Linux pid namespace identifier in prefix...
r30921 confidence. Typically it's just hostname. On modern linux, we include an
extra Linux-specific pid namespace identifier.
Jun Wu
lock: move lock._host calculation to a function...
r30920 """
Yuya Nishihara
py3: replace "if ispy3" by encoding.strtolocal()
r35915 result = encoding.strtolocal(socket.gethostname())
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if pycompat.sysplatform.startswith(b'linux'):
Jun Wu
lock: include Linux pid namespace identifier in prefix...
r30921 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 result += b'/%x' % os.stat(b'/proc/self/ns/pid').st_ino
Jun Wu
lock: include Linux pid namespace identifier in prefix...
r30921 except OSError as ex:
if ex.errno not in (errno.ENOENT, errno.EACCES, errno.ENOTDIR):
raise
return result
Jun Wu
lock: move lock._host calculation to a function...
r30920
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
lock: block signal interrupt while making a lock file...
r36717 @contextlib.contextmanager
def _delayedinterrupt():
"""Block signal interrupt while doing something critical
This makes sure that the code block wrapped by this context manager won't
be interrupted.
For Windows developers: It appears not possible to guard time.sleep()
from CTRL_C_EVENT, so please don't use time.sleep() to test if this is
working.
"""
assertedsigs = []
blocked = False
orighandlers = {}
def raiseinterrupt(num):
Augie Fackler
formatting: blacken the codebase...
r43346 if num == getattr(signal, 'SIGINT', None) or num == getattr(
signal, 'CTRL_C_EVENT', None
):
Yuya Nishihara
lock: block signal interrupt while making a lock file...
r36717 raise KeyboardInterrupt
else:
raise error.SignalInterrupt
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
lock: block signal interrupt while making a lock file...
r36717 def catchterm(num, frame):
if blocked:
assertedsigs.append(num)
else:
raiseinterrupt(num)
try:
# save handlers first so they can be restored even if a setup is
# interrupted between signal.signal() and orighandlers[] =.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for name in [
b'CTRL_C_EVENT',
b'SIGINT',
b'SIGBREAK',
b'SIGHUP',
b'SIGTERM',
]:
Yuya Nishihara
lock: block signal interrupt while making a lock file...
r36717 num = getattr(signal, name, None)
if num and num not in orighandlers:
orighandlers[num] = signal.getsignal(num)
try:
for num in orighandlers:
signal.signal(num, catchterm)
except ValueError:
Augie Fackler
formatting: blacken the codebase...
r43346 pass # in a thread? no luck
Yuya Nishihara
lock: block signal interrupt while making a lock file...
r36717
blocked = True
yield
finally:
# no simple way to reliably restore all signal handlers because
# any loops, recursive function calls, except blocks, etc. can be
# interrupted. so instead, make catchterm() raise interrupt.
blocked = False
try:
for num, handler in orighandlers.items():
signal.signal(num, handler)
except ValueError:
Augie Fackler
formatting: blacken the codebase...
r43346 pass # in a thread?
Yuya Nishihara
lock: block signal interrupt while making a lock file...
r36717
# re-raise interrupt exception if any, which may be shadowed by a new
# interrupt occurred while re-raising the first one
if assertedsigs:
raiseinterrupt(assertedsigs[0])
Augie Fackler
formatting: blacken the codebase...
r43346
Boris Feld
lock: allow to configure when the lock messages are displayed...
r35210 def trylock(ui, vfs, lockname, timeout, warntimeout, *args, **kwargs):
Boris Feld
lock: add a trylock method handling the timeout and messaging logic...
r35209 """return an acquired lock or raise an a LockHeld exception
Boris Feld
lock: allow to configure when the lock messages are displayed...
r35210 This function is responsible to issue warnings and or debug messages about
the held lock while trying to acquires it."""
Boris Feld
lock: add a trylock method handling the timeout and messaging logic...
r35209
def printwarning(printer, locker):
"""issue the usual "waiting on lock" message through any channel"""
# show more details for new-style locks
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b':' in locker:
host, pid = locker.split(b":", 1)
Augie Fackler
formatting: blacken the codebase...
r43346 msg = _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"waiting for lock on %s held by process %r on host %r\n"
Augie Fackler
formatting: blacken the codebase...
r43346 ) % (
pycompat.bytestr(l.desc),
pycompat.bytestr(pid),
pycompat.bytestr(host),
)
Boris Feld
lock: add a trylock method handling the timeout and messaging logic...
r35209 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = _(b"waiting for lock on %s held by %r\n") % (
Augie Fackler
formatting: blacken the codebase...
r43346 l.desc,
pycompat.bytestr(locker),
)
Boris Feld
lock: add a trylock method handling the timeout and messaging logic...
r35209 printer(msg)
l = lock(vfs, lockname, 0, *args, dolock=False, **kwargs)
Boris Feld
lock: allow to configure when the lock messages are displayed...
r35210 debugidx = 0 if (warntimeout and timeout) else -1
Boris Feld
lock: add a trylock method handling the timeout and messaging logic...
r35209 warningidx = 0
if not timeout:
warningidx = -1
Boris Feld
lock: allow to configure when the lock messages are displayed...
r35210 elif warntimeout:
warningidx = warntimeout
Boris Feld
lock: add a trylock method handling the timeout and messaging logic...
r35209
delay = 0
while True:
try:
l._trylock()
break
except error.LockHeld as inst:
Boris Feld
lock: allow to configure when the lock messages are displayed...
r35210 if delay == debugidx:
printwarning(ui.debug, inst.locker)
Boris Feld
lock: add a trylock method handling the timeout and messaging logic...
r35209 if delay == warningidx:
printwarning(ui.warn, inst.locker)
if timeout <= delay:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.LockHeld(
errno.ETIMEDOUT, inst.filename, l.desc, inst.locker
)
Boris Feld
lock: add a trylock method handling the timeout and messaging logic...
r35209 time.sleep(1)
delay += 1
l.delay = delay
if l.delay:
Boris Feld
lock: allow to configure when the lock messages are displayed...
r35210 if 0 <= warningidx <= l.delay:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.warn(_(b"got lock after %d seconds\n") % l.delay)
Boris Feld
lock: allow to configure when the lock messages are displayed...
r35210 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.debug(b"got lock after %d seconds\n" % l.delay)
Boris Feld
lock: add a trylock method handling the timeout and messaging logic...
r35209 if l.acquirefn:
l.acquirefn()
return l
Augie Fackler
formatting: blacken the codebase...
r43346
Eric Hopper
Convert all classes to new-style classes by deriving them from object.
r1559 class lock(object):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """An advisory lock held by one process to control access to a set
Greg Ward
localrepo: document the locking scheme a little better...
r9309 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
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 else under .hg/."""
Greg Ward
localrepo: document the locking scheme a little better...
r9309
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
Augie Fackler
formatting: blacken the codebase...
r43346 def __init__(
self,
vfs,
fname,
timeout=-1,
releasefn=None,
acquirefn=None,
desc=None,
signalsafe=True,
dolock=True,
):
FUJIWARA Katsunori
lock: take both vfs and lock file path relative to vfs to access via vfs...
r20091 self.vfs = vfs
Pulkit Goyal
lock: don't use 'file' as a variable name...
r37677 self.f = fname
mpm@selenic.com
Simply repository locking...
r161 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
Siddharth Agarwal
lock: move acquirefn call to inside the lock...
r26321 self.acquirefn = acquirefn
Vadim Gelfer
fix backtrace printed when cannot get lock....
r2016 self.desc = desc
Yuya Nishihara
lock: add internal config to not replace signal handlers while locking...
r38157 if signalsafe:
self._maybedelayedinterrupt = _delayedinterrupt
else:
self._maybedelayedinterrupt = util.nullcontextmanager
Augie Fackler
formatting: blacken the codebase...
r43346 self.postrelease = []
Siddharth Agarwal
lock: add a wrapper to os.getpid() to make testing easier...
r26383 self.pid = self._getpid()
Boris Feld
lock: add a trylock method handling the timeout and messaging logic...
r35209 if dolock:
self.delay = self.lock()
if self.acquirefn:
self.acquirefn()
mpm@selenic.com
Simply repository locking...
r161
Bryan O'Sullivan
lock: turn a lock into a Python context manager...
r27797 def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, exc_tb):
Kyle Lippincott
lock: pass "success" boolean to _afterlock callbacks...
r44217 success = all(a is None for a in (exc_type, exc_value, exc_tb))
self.release(success=success)
Bryan O'Sullivan
lock: turn a lock into a Python context manager...
r27797
mpm@selenic.com
Simply repository locking...
r161 def __del__(self):
Ronny Pfannschmidt
made repo locks recursive and deprecate refcounting based lock releasing...
r8108 if self.held:
Augie Fackler
formatting: blacken the codebase...
r43346 warnings.warn(
Augie Fackler
cleanup: remove pointless r-prefixes on double-quoted strings...
r43809 "use lock.release instead of del lock",
Augie Fackler
formatting: blacken the codebase...
r43346 category=DeprecationWarning,
stacklevel=2,
)
Ronny Pfannschmidt
add a deprecation warning for gc based lock releasing
r8113
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()
Siddharth Agarwal
lock: add a wrapper to os.getpid() to make testing easier...
r26383 def _getpid(self):
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 # wrapper around procutil.getpid() to make testing easier
return procutil.getpid()
Siddharth Agarwal
lock: add a wrapper to os.getpid() to make testing easier...
r26383
mpm@selenic.com
Simply repository locking...
r161 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:
Matt Mackall
lock: make trylock private
r26082 self._trylock()
Mads Kiilerich
localrepo: give a sigh of relief when getting lock after waiting for it...
r20380 return self.timeout - timeout
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.LockHeld as 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
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.LockHeld(
errno.ETIMEDOUT, inst.filename, self.desc, inst.locker
)
mpm@selenic.com
Whitespace cleanups...
r515
Matt Mackall
lock: make trylock private
r26082 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:
Jun Wu
lock: move lock._host calculation to a function...
r30920 lock._host = _getlockprefix()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lockname = b'%s:%d' % (lock._host, self.pid)
Matt Mackall
lock: loop a finite number of times in trylock (issue4787)...
r26081 retry = 5
while not self.held and retry:
retry -= 1
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 try:
Yuya Nishihara
lock: add internal config to not replace signal handlers while locking...
r38157 with self._maybedelayedinterrupt():
Yuya Nishihara
lock: block signal interrupt while making a lock file...
r36717 self.vfs.makelock(lockname, self.f)
self.held = 1
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except (OSError, IOError) as why:
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 if why.errno == errno.EEXIST:
Siddharth Agarwal
lock: recognize parent locks while acquiring...
r26387 locker = self._readlock()
FUJIWARA Katsunori
lock: avoid unintentional lock acquisition at failure of readlock...
r32088 if locker is None:
continue
Siddharth Agarwal
lock: recognize parent locks while acquiring...
r26387 locker = self._testlock(locker)
Thomas Arendsen Hein
Don't step into an endless loop when lock file is empty.
r3686 if locker is not None:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.LockHeld(
errno.EAGAIN,
self.vfs.join(self.f),
self.desc,
locker,
)
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 else:
Augie Fackler
formatting: blacken the codebase...
r43346 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
FUJIWARA Katsunori
lock: avoid unintentional lock acquisition at failure of readlock...
r32089 if not self.held:
# use empty locker to mean "busy for frequent lock/unlock
# by many processes"
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.LockHeld(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 errno.EAGAIN, self.vfs.join(self.f), self.desc, b""
Augie Fackler
formatting: blacken the codebase...
r43346 )
FUJIWARA Katsunori
lock: avoid unintentional lock acquisition at failure of readlock...
r32089
Siddharth Agarwal
lock: factor code to read lock into a separate function...
r26290 def _readlock(self):
"""read lock and return its value
Returns None if no lock exists, pid for old-style locks, and host:pid
for new-style locks.
"""
try:
return self.vfs.readlock(self.f)
except (OSError, IOError) as why:
if why.errno == errno.ENOENT:
return None
raise
Valentin Gatien-Baron
lock: refactor in preparation for next commit...
r44107 def _lockshouldbebroken(self, locker):
Siddharth Agarwal
lock: factor code to read lock into a separate function...
r26290 if locker is None:
Valentin Gatien-Baron
lock: refactor in preparation for next commit...
r44107 return False
Benoit Boissinot
use __contains__, index or split instead of str.find...
r2579 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 host, pid = locker.split(b":", 1)
Benoit Boissinot
use __contains__, index or split instead of str.find...
r2579 except ValueError:
Valentin Gatien-Baron
lock: refactor in preparation for next commit...
r44107 return False
Bryan O'Sullivan
lock.py: cache hostname, but not pid, in case we fork
r4947 if host != lock._host:
Valentin Gatien-Baron
lock: refactor in preparation for next commit...
r44107 return False
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:
Valentin Gatien-Baron
lock: refactor in preparation for next commit...
r44107 return False
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 if procutil.testpid(pid):
Valentin Gatien-Baron
lock: refactor in preparation for next commit...
r44107 return False
return True
def _testlock(self, locker):
if not self._lockshouldbebroken(locker):
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 return locker
Valentin Gatien-Baron
lock: refactor in preparation for next commit...
r44107
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 # if locker dead, break lock. must do this with another lock
# held, or can race and break valid lock.
try:
Valentin Gatien-Baron
lock: refactor in preparation for next commit...
r44107 with lock(self.vfs, self.f + b'.break', timeout=0):
Valentin Gatien-Baron
lock: fix race in lock-breaking code...
r44108 locker = self._readlock()
if not self._lockshouldbebroken(locker):
return locker
Valentin Gatien-Baron
lock: refactor in preparation for next commit...
r44107 self.vfs.unlink(self.f)
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
Siddharth Agarwal
lock: factor out lock testing into a separate function...
r26291 def testlock(self):
"""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.
"""
locker = self._readlock()
return self._testlock(locker)
Kyle Lippincott
lock: pass "success" boolean to _afterlock callbacks...
r44217 def release(self, success=True):
Pierre-Yves David
lock: add mechanism to register post release callback
r15583 """release the lock and execute callback function if any
Bryan O'Sullivan
Merge spelling fixes
r17537 If the lock has been acquired multiple times, the actual release is
timeless@mozdev.org
spelling: release
r17510 delayed to the last release 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
Siddharth Agarwal
lock: add a wrapper to os.getpid() to make testing easier...
r26383 if self._getpid() != self.pid:
Bryan O'Sullivan
lock: if we fork, ensure that only the parent releases...
r18907 # we forked, and are not the parent
return
mpm@selenic.com
Fix troubles with clone and exception handling...
r503 try:
Siddharth Agarwal
lock: while releasing, unlink lockfile even if the release function throws...
r23032 if self.releasefn:
self.releasefn()
finally:
Martin von Zweigbergk
locking: remove support for inheriting locks in subprocess...
r46092 try:
self.vfs.unlink(self.f)
except OSError:
pass
Siddharth Agarwal
lock.release: don't call postrelease functions for inherited locks...
r26474 # The postrelease functions typically assume the lock is not held
# at all.
Martin von Zweigbergk
locking: remove support for inheriting locks in subprocess...
r46092 for callback in self.postrelease:
callback(success)
# Prevent double usage and help clear cycles.
self.postrelease = None
mpm@selenic.com
Simply repository locking...
r161
Augie Fackler
formatting: blacken the codebase...
r43346
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()