annotate mercurial/lock.py @ 27015:341cb90ffd18

util: disable floating point stat times (issue4836) Alternate fix for this issue which avoids putting extra function calls and exception handling in the fast path. For almost all purposes, integer timestamps are preferable to Mercurial. It stores integer timestamps in the dirstate and would thus like to avoid doing any float/int comparisons or conversions. We will continue to have to deal with 1-second granularity on filesystems for quite some time, so this won't significantly hinder our capabilities. This has some impact on our file cache validation code in that it lowers timestamp resolution. But as we still have to deal with low-resolution filesystems, we're not relying on this anyway. An alternate approach is to use stat[ST_MTIME], which is guaranteed to be an integer. But since this support isn't already in our extension, we can't depend on it being available without adding a hard Python->C API dependency that's painful for people like yours truly who have bisect regularly and people without compilers.
author Matt Mackall <mpm@selenic.com>
date Thu, 19 Nov 2015 13:21:24 -0600
parents e8564e04382d
children 054abf2377e8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
9309
cfdcb7a465af localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents: 8312
diff changeset
1 # lock.py - simple advisory locking scheme for mercurial
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
2 #
2859
345bac2bc4ec update copyrights.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2579
diff changeset
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
4 #
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8113
diff changeset
5 # This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9858
diff changeset
6 # GNU General Public License version 2 or any later version.
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
7
25956
8cd30e9277ae lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
8 from __future__ import absolute_import
8cd30e9277ae lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
9
26473
5f94e64f182c lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents: 26387
diff changeset
10 import contextlib
25956
8cd30e9277ae lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
11 import errno
8cd30e9277ae lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
12 import os
8cd30e9277ae lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
13 import socket
8cd30e9277ae lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
14 import time
8113
87a1605979e4 add a deprecation warning for gc based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 8108
diff changeset
15 import warnings
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
16
25956
8cd30e9277ae lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
17 from . import (
8cd30e9277ae lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
18 error,
8cd30e9277ae lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
19 util,
8cd30e9277ae lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
20 )
8cd30e9277ae lock: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
21
1559
59b3639df0a9 Convert all classes to new-style classes by deriving them from object.
Eric Hopper <hopper@omnifarious.org>
parents: 1530
diff changeset
22 class lock(object):
9309
cfdcb7a465af localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents: 8312
diff changeset
23 '''An advisory lock held by one process to control access to a set
cfdcb7a465af localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents: 8312
diff changeset
24 of files. Non-cooperating processes or incorrectly written scripts
cfdcb7a465af localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents: 8312
diff changeset
25 can ignore Mercurial's locking scheme and stomp all over the
cfdcb7a465af localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents: 8312
diff changeset
26 repository, so don't do that.
cfdcb7a465af localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents: 8312
diff changeset
27
cfdcb7a465af localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents: 8312
diff changeset
28 Typically used via localrepository.lock() to lock the repository
cfdcb7a465af localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents: 8312
diff changeset
29 store (.hg/store/) or localrepository.wlock() to lock everything
cfdcb7a465af localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents: 8312
diff changeset
30 else under .hg/.'''
cfdcb7a465af localrepo: document the locking scheme a little better
Greg Ward <greg-hg@gerg.ca>
parents: 8312
diff changeset
31
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
32 # lock is symlink on platforms that support it, file on others.
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
33
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
34 # symlink is used because create of directory entry and contents
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
35 # are atomic even over nfs.
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
36
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
37 # old-style lock: symlink to pid
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
38 # new-style lock: symlink to hostname:pid
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
39
4947
3e25a6eb5c9a lock.py: cache hostname, but not pid, in case we fork
Bryan O'Sullivan <bos@serpentine.com>
parents: 3877
diff changeset
40 _host = None
3e25a6eb5c9a lock.py: cache hostname, but not pid, in case we fork
Bryan O'Sullivan <bos@serpentine.com>
parents: 3877
diff changeset
41
26321
db4c192cb9b3 lock: move acquirefn call to inside the lock
Siddharth Agarwal <sid0@fb.com>
parents: 26291
diff changeset
42 def __init__(self, vfs, file, timeout=-1, releasefn=None, acquirefn=None,
26498
e8564e04382d lock: add a way to prevent locks from being inherited
Siddharth Agarwal <sid0@fb.com>
parents: 26474
diff changeset
43 desc=None, inheritchecker=None, parentlock=None):
20091
abfe6a8e619b lock: take both vfs and lock file path relative to vfs to access via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19927
diff changeset
44 self.vfs = vfs
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
45 self.f = file
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
46 self.held = 0
1787
e431344e604c add a timeout when a lock is held (default 1024 sec)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1753
diff changeset
47 self.timeout = timeout
1530
abfab59fce79 add a releasefn keyword to lock.lock
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1062
diff changeset
48 self.releasefn = releasefn
26321
db4c192cb9b3 lock: move acquirefn call to inside the lock
Siddharth Agarwal <sid0@fb.com>
parents: 26291
diff changeset
49 self.acquirefn = acquirefn
2016
ff5c9a92f556 fix backtrace printed when cannot get lock.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1877
diff changeset
50 self.desc = desc
26498
e8564e04382d lock: add a way to prevent locks from being inherited
Siddharth Agarwal <sid0@fb.com>
parents: 26474
diff changeset
51 self._inheritchecker = inheritchecker
26356
927fa07a2ba4 lock: introduce state to keep track of inheritance
Siddharth Agarwal <sid0@fb.com>
parents: 26321
diff changeset
52 self.parentlock = parentlock
927fa07a2ba4 lock: introduce state to keep track of inheritance
Siddharth Agarwal <sid0@fb.com>
parents: 26321
diff changeset
53 self._parentheld = False
927fa07a2ba4 lock: introduce state to keep track of inheritance
Siddharth Agarwal <sid0@fb.com>
parents: 26321
diff changeset
54 self._inherited = False
15589
cc24e4ed3e0c lock: change name of release chain
Matt Mackall <mpm@selenic.com>
parents: 15583
diff changeset
55 self.postrelease = []
26383
0fceb34806e1 lock: add a wrapper to os.getpid() to make testing easier
Siddharth Agarwal <sid0@fb.com>
parents: 26359
diff changeset
56 self.pid = self._getpid()
20380
c697b70f295f localrepo: give a sigh of relief when getting lock after waiting for it
Mads Kiilerich <madski@unity3d.com>
parents: 20091
diff changeset
57 self.delay = self.lock()
26321
db4c192cb9b3 lock: move acquirefn call to inside the lock
Siddharth Agarwal <sid0@fb.com>
parents: 26291
diff changeset
58 if self.acquirefn:
db4c192cb9b3 lock: move acquirefn call to inside the lock
Siddharth Agarwal <sid0@fb.com>
parents: 26291
diff changeset
59 self.acquirefn()
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
60
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
61 def __del__(self):
8108
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
62 if self.held:
8113
87a1605979e4 add a deprecation warning for gc based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 8108
diff changeset
63 warnings.warn("use lock.release instead of del lock",
87a1605979e4 add a deprecation warning for gc based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 8108
diff changeset
64 category=DeprecationWarning,
87a1605979e4 add a deprecation warning for gc based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 8108
diff changeset
65 stacklevel=2)
87a1605979e4 add a deprecation warning for gc based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 8108
diff changeset
66
8108
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
67 # ensure the lock will be removed
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
68 # even if recursive locking did occur
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
69 self.held = 1
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
70
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
71 self.release()
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
72
26383
0fceb34806e1 lock: add a wrapper to os.getpid() to make testing easier
Siddharth Agarwal <sid0@fb.com>
parents: 26359
diff changeset
73 def _getpid(self):
0fceb34806e1 lock: add a wrapper to os.getpid() to make testing easier
Siddharth Agarwal <sid0@fb.com>
parents: 26359
diff changeset
74 # wrapper around os.getpid() to make testing easier
0fceb34806e1 lock: add a wrapper to os.getpid() to make testing easier
Siddharth Agarwal <sid0@fb.com>
parents: 26359
diff changeset
75 return os.getpid()
0fceb34806e1 lock: add a wrapper to os.getpid() to make testing easier
Siddharth Agarwal <sid0@fb.com>
parents: 26359
diff changeset
76
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
77 def lock(self):
1787
e431344e604c add a timeout when a lock is held (default 1024 sec)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1753
diff changeset
78 timeout = self.timeout
14494
1ffeeb91c55d check-code: flag 0/1 used as constant Boolean expression
Martin Geisler <mg@lazybytes.net>
parents: 13281
diff changeset
79 while True:
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
80 try:
26082
b188f60bd955 lock: make trylock private
Matt Mackall <mpm@selenic.com>
parents: 26081
diff changeset
81 self._trylock()
20380
c697b70f295f localrepo: give a sigh of relief when getting lock after waiting for it
Mads Kiilerich <madski@unity3d.com>
parents: 20091
diff changeset
82 return self.timeout - timeout
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23032
diff changeset
83 except error.LockHeld as inst:
1787
e431344e604c add a timeout when a lock is held (default 1024 sec)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1753
diff changeset
84 if timeout != 0:
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
85 time.sleep(1)
1787
e431344e604c add a timeout when a lock is held (default 1024 sec)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1753
diff changeset
86 if timeout > 0:
e431344e604c add a timeout when a lock is held (default 1024 sec)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 1753
diff changeset
87 timeout -= 1
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
88 continue
7640
7197812e8d44 error: move lock errors
Matt Mackall <mpm@selenic.com>
parents: 4959
diff changeset
89 raise error.LockHeld(errno.ETIMEDOUT, inst.filename, self.desc,
7197812e8d44 error: move lock errors
Matt Mackall <mpm@selenic.com>
parents: 4959
diff changeset
90 inst.locker)
515
03f27b1381f9 Whitespace cleanups
mpm@selenic.com
parents: 503
diff changeset
91
26082
b188f60bd955 lock: make trylock private
Matt Mackall <mpm@selenic.com>
parents: 26081
diff changeset
92 def _trylock(self):
8108
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
93 if self.held:
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
94 self.held += 1
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
95 return
4947
3e25a6eb5c9a lock.py: cache hostname, but not pid, in case we fork
Bryan O'Sullivan <bos@serpentine.com>
parents: 3877
diff changeset
96 if lock._host is None:
3e25a6eb5c9a lock.py: cache hostname, but not pid, in case we fork
Bryan O'Sullivan <bos@serpentine.com>
parents: 3877
diff changeset
97 lock._host = socket.gethostname()
18907
af9fa8d4c939 lock: if we fork, ensure that only the parent releases
Bryan O'Sullivan <bryano@fb.com>
parents: 17683
diff changeset
98 lockname = '%s:%s' % (lock._host, self.pid)
26081
3b6e5914edd8 lock: loop a finite number of times in trylock (issue4787)
Matt Mackall <mpm@selenic.com>
parents: 25956
diff changeset
99 retry = 5
3b6e5914edd8 lock: loop a finite number of times in trylock (issue4787)
Matt Mackall <mpm@selenic.com>
parents: 25956
diff changeset
100 while not self.held and retry:
3b6e5914edd8 lock: loop a finite number of times in trylock (issue4787)
Matt Mackall <mpm@selenic.com>
parents: 25956
diff changeset
101 retry -= 1
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
102 try:
20091
abfe6a8e619b lock: take both vfs and lock file path relative to vfs to access via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19927
diff changeset
103 self.vfs.makelock(lockname, self.f)
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
104 self.held = 1
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23032
diff changeset
105 except (OSError, IOError) as why:
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
106 if why.errno == errno.EEXIST:
26387
e16f80f89a29 lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents: 26383
diff changeset
107 locker = self._readlock()
e16f80f89a29 lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents: 26383
diff changeset
108 # special case where a parent process holds the lock -- this
e16f80f89a29 lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents: 26383
diff changeset
109 # is different from the pid being different because we do
e16f80f89a29 lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents: 26383
diff changeset
110 # want the unlock and postrelease functions to be called,
e16f80f89a29 lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents: 26383
diff changeset
111 # but the lockfile to not be removed.
e16f80f89a29 lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents: 26383
diff changeset
112 if locker == self.parentlock:
e16f80f89a29 lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents: 26383
diff changeset
113 self._parentheld = True
e16f80f89a29 lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents: 26383
diff changeset
114 self.held = 1
e16f80f89a29 lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents: 26383
diff changeset
115 return
e16f80f89a29 lock: recognize parent locks while acquiring
Siddharth Agarwal <sid0@fb.com>
parents: 26383
diff changeset
116 locker = self._testlock(locker)
3686
4308f4cdc07b Don't step into an endless loop when lock file is empty.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2859
diff changeset
117 if locker is not None:
20091
abfe6a8e619b lock: take both vfs and lock file path relative to vfs to access via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19927
diff changeset
118 raise error.LockHeld(errno.EAGAIN,
abfe6a8e619b lock: take both vfs and lock file path relative to vfs to access via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19927
diff changeset
119 self.vfs.join(self.f), self.desc,
7640
7197812e8d44 error: move lock errors
Matt Mackall <mpm@selenic.com>
parents: 4959
diff changeset
120 locker)
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
121 else:
7640
7197812e8d44 error: move lock errors
Matt Mackall <mpm@selenic.com>
parents: 4959
diff changeset
122 raise error.LockUnavailable(why.errno, why.strerror,
7197812e8d44 error: move lock errors
Matt Mackall <mpm@selenic.com>
parents: 4959
diff changeset
123 why.filename, self.desc)
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
124
26290
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
125 def _readlock(self):
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
126 """read lock and return its value
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
127
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
128 Returns None if no lock exists, pid for old-style locks, and host:pid
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
129 for new-style locks.
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
130 """
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
131 try:
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
132 return self.vfs.readlock(self.f)
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
133 except (OSError, IOError) as why:
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
134 if why.errno == errno.ENOENT:
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
135 return None
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
136 raise
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
137
26291
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
138 def _testlock(self, locker):
26290
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
139 if locker is None:
9664d32bd6cb lock: factor code to read lock into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26082
diff changeset
140 return None
2579
0875cda033fd use __contains__, index or split instead of str.find
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2016
diff changeset
141 try:
0875cda033fd use __contains__, index or split instead of str.find
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2016
diff changeset
142 host, pid = locker.split(":", 1)
0875cda033fd use __contains__, index or split instead of str.find
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2016
diff changeset
143 except ValueError:
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
144 return locker
4947
3e25a6eb5c9a lock.py: cache hostname, but not pid, in case we fork
Bryan O'Sullivan <bos@serpentine.com>
parents: 3877
diff changeset
145 if host != lock._host:
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
146 return locker
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
147 try:
2579
0875cda033fd use __contains__, index or split instead of str.find
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2016
diff changeset
148 pid = int(pid)
9685
a820cd39d415 lock: catch specific exceptions
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9680
diff changeset
149 except ValueError:
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
150 return locker
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
151 if util.testpid(pid):
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
152 return locker
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
153 # if locker dead, break lock. must do this with another lock
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
154 # held, or can race and break valid lock.
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
155 try:
20091
abfe6a8e619b lock: take both vfs and lock file path relative to vfs to access via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19927
diff changeset
156 l = lock(self.vfs, self.f + '.break', timeout=0)
abfe6a8e619b lock: take both vfs and lock file path relative to vfs to access via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19927
diff changeset
157 self.vfs.unlink(self.f)
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
158 l.release()
7640
7197812e8d44 error: move lock errors
Matt Mackall <mpm@selenic.com>
parents: 4959
diff changeset
159 except error.LockError:
1877
d314a89fa4f1 change lock format to let us detect and break stale locks.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 1836
diff changeset
160 return locker
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
161
26291
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
162 def testlock(self):
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
163 """return id of locker if lock is valid, else None.
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
164
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
165 If old-style lock, we cannot tell what machine locker is on.
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
166 with new-style lock, if locker is on this machine, we can
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
167 see if locker is alive. If locker is on this machine but
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
168 not alive, we can safely break lock.
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
169
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
170 The lock file is only deleted when None is returned.
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
171
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
172 """
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
173 locker = self._readlock()
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
174 return self._testlock(locker)
1d33842c5b3e lock: factor out lock testing into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 26290
diff changeset
175
26473
5f94e64f182c lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents: 26387
diff changeset
176 @contextlib.contextmanager
5f94e64f182c lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents: 26387
diff changeset
177 def inherit(self):
5f94e64f182c lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents: 26387
diff changeset
178 """context for the lock to be inherited by a Mercurial subprocess.
26357
6979a1369185 lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents: 26356
diff changeset
179
26473
5f94e64f182c lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents: 26387
diff changeset
180 Yields a string that will be recognized by the lock in the subprocess.
5f94e64f182c lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents: 26387
diff changeset
181 Communicating this string to the subprocess needs to be done separately
5f94e64f182c lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents: 26387
diff changeset
182 -- typically by an environment variable.
26357
6979a1369185 lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents: 26356
diff changeset
183 """
6979a1369185 lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents: 26356
diff changeset
184 if not self.held:
6979a1369185 lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents: 26356
diff changeset
185 raise error.LockInheritanceContractViolation(
26473
5f94e64f182c lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents: 26387
diff changeset
186 'inherit can only be called while lock is held')
26357
6979a1369185 lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents: 26356
diff changeset
187 if self._inherited:
6979a1369185 lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents: 26356
diff changeset
188 raise error.LockInheritanceContractViolation(
26473
5f94e64f182c lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents: 26387
diff changeset
189 'inherit cannot be called while lock is already inherited')
26498
e8564e04382d lock: add a way to prevent locks from being inherited
Siddharth Agarwal <sid0@fb.com>
parents: 26474
diff changeset
190 if self._inheritchecker is not None:
e8564e04382d lock: add a way to prevent locks from being inherited
Siddharth Agarwal <sid0@fb.com>
parents: 26474
diff changeset
191 self._inheritchecker()
26357
6979a1369185 lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents: 26356
diff changeset
192 if self.releasefn:
6979a1369185 lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents: 26356
diff changeset
193 self.releasefn()
6979a1369185 lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents: 26356
diff changeset
194 if self._parentheld:
6979a1369185 lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents: 26356
diff changeset
195 lockname = self.parentlock
6979a1369185 lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents: 26356
diff changeset
196 else:
6979a1369185 lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents: 26356
diff changeset
197 lockname = '%s:%s' % (lock._host, self.pid)
6979a1369185 lock: add a method to prepare the lock for inheritance
Siddharth Agarwal <sid0@fb.com>
parents: 26356
diff changeset
198 self._inherited = True
26473
5f94e64f182c lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents: 26387
diff changeset
199 try:
5f94e64f182c lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents: 26387
diff changeset
200 yield lockname
5f94e64f182c lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents: 26387
diff changeset
201 finally:
5f94e64f182c lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents: 26387
diff changeset
202 if self.acquirefn:
5f94e64f182c lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents: 26387
diff changeset
203 self.acquirefn()
5f94e64f182c lock: turn prepinherit/reacquire into a single context manager
Siddharth Agarwal <sid0@fb.com>
parents: 26387
diff changeset
204 self._inherited = False
26358
de5a52e5eb9e lock: add a method to reacquire the lock after subprocesses exit
Siddharth Agarwal <sid0@fb.com>
parents: 26357
diff changeset
205
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
206 def release(self):
15583
926a06f7a353 lock: add mechanism to register post release callback
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 14494
diff changeset
207 """release the lock and execute callback function if any
926a06f7a353 lock: add mechanism to register post release callback
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 14494
diff changeset
208
17537
31f32a96e1e3 Merge spelling fixes
Bryan O'Sullivan <bryano@fb.com>
parents: 17427 17510
diff changeset
209 If the lock has been acquired multiple times, the actual release is
17510
7c44b703657b spelling: release
timeless@mozdev.org
parents: 15589
diff changeset
210 delayed to the last release call."""
8108
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
211 if self.held > 1:
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
212 self.held -= 1
9680
8cea86d73887 lock: use '==' instead of 'is' for integer equality ('is' may not work)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9309
diff changeset
213 elif self.held == 1:
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
214 self.held = 0
26383
0fceb34806e1 lock: add a wrapper to os.getpid() to make testing easier
Siddharth Agarwal <sid0@fb.com>
parents: 26359
diff changeset
215 if self._getpid() != self.pid:
18907
af9fa8d4c939 lock: if we fork, ensure that only the parent releases
Bryan O'Sullivan <bryano@fb.com>
parents: 17683
diff changeset
216 # we forked, and are not the parent
af9fa8d4c939 lock: if we fork, ensure that only the parent releases
Bryan O'Sullivan <bryano@fb.com>
parents: 17683
diff changeset
217 return
503
c6a2e41c8c60 Fix troubles with clone and exception handling
mpm@selenic.com
parents: 429
diff changeset
218 try:
23032
f484be02bd35 lock: while releasing, unlink lockfile even if the release function throws
Siddharth Agarwal <sid0@fb.com>
parents: 20380
diff changeset
219 if self.releasefn:
f484be02bd35 lock: while releasing, unlink lockfile even if the release function throws
Siddharth Agarwal <sid0@fb.com>
parents: 20380
diff changeset
220 self.releasefn()
f484be02bd35 lock: while releasing, unlink lockfile even if the release function throws
Siddharth Agarwal <sid0@fb.com>
parents: 20380
diff changeset
221 finally:
26359
c545d51c901e lock.release: do not unlink inherited locks
Siddharth Agarwal <sid0@fb.com>
parents: 26358
diff changeset
222 if not self._parentheld:
c545d51c901e lock.release: do not unlink inherited locks
Siddharth Agarwal <sid0@fb.com>
parents: 26358
diff changeset
223 try:
c545d51c901e lock.release: do not unlink inherited locks
Siddharth Agarwal <sid0@fb.com>
parents: 26358
diff changeset
224 self.vfs.unlink(self.f)
c545d51c901e lock.release: do not unlink inherited locks
Siddharth Agarwal <sid0@fb.com>
parents: 26358
diff changeset
225 except OSError:
c545d51c901e lock.release: do not unlink inherited locks
Siddharth Agarwal <sid0@fb.com>
parents: 26358
diff changeset
226 pass
26474
431094a3b21f lock.release: don't call postrelease functions for inherited locks
Siddharth Agarwal <sid0@fb.com>
parents: 26473
diff changeset
227 # The postrelease functions typically assume the lock is not held
431094a3b21f lock.release: don't call postrelease functions for inherited locks
Siddharth Agarwal <sid0@fb.com>
parents: 26473
diff changeset
228 # at all.
431094a3b21f lock.release: don't call postrelease functions for inherited locks
Siddharth Agarwal <sid0@fb.com>
parents: 26473
diff changeset
229 if not self._parentheld:
431094a3b21f lock.release: don't call postrelease functions for inherited locks
Siddharth Agarwal <sid0@fb.com>
parents: 26473
diff changeset
230 for callback in self.postrelease:
431094a3b21f lock.release: don't call postrelease functions for inherited locks
Siddharth Agarwal <sid0@fb.com>
parents: 26473
diff changeset
231 callback()
161
0b4c5cb953d9 Simply repository locking
mpm@selenic.com
parents:
diff changeset
232
8108
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
233 def release(*locks):
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
234 for lock in locks:
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
235 if lock is not None:
a26d33749bd8 made repo locks recursive and deprecate refcounting based lock releasing
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 7640
diff changeset
236 lock.release()