Mercurial > hg > mercurial-crew-with-dirclash
comparison mercurial/lock.py @ 2016:ff5c9a92f556
fix backtrace printed when cannot get lock.
change lock error handling code so exceptions have useful info and
exception handling in one place.
add test case for when cannot get lock.
author | Vadim Gelfer <vadim.gelfer@gmail.com> |
---|---|
date | Tue, 28 Mar 2006 09:01:07 -0800 |
parents | d314a89fa4f1 |
children | 0875cda033fd |
comparison
equal
deleted
inserted
replaced
2009:182f500805db | 2016:ff5c9a92f556 |
---|---|
6 # of the GNU General Public License, incorporated herein by reference. | 6 # of the GNU General Public License, incorporated herein by reference. |
7 | 7 |
8 from demandload import * | 8 from demandload import * |
9 demandload(globals(), 'errno os socket time util') | 9 demandload(globals(), 'errno os socket time util') |
10 | 10 |
11 class LockException(Exception): | 11 class LockException(IOError): |
12 pass | 12 def __init__(self, errno, strerror, filename, desc): |
13 IOError.__init__(self, errno, strerror, filename) | |
14 self.desc = desc | |
15 | |
13 class LockHeld(LockException): | 16 class LockHeld(LockException): |
14 pass | 17 def __init__(self, errno, filename, desc, locker): |
18 LockException.__init__(self, errno, 'Lock held', filename, desc) | |
19 self.locker = locker | |
20 | |
15 class LockUnavailable(LockException): | 21 class LockUnavailable(LockException): |
16 pass | 22 pass |
17 | 23 |
18 class lock(object): | 24 class lock(object): |
19 # lock is symlink on platforms that support it, file on others. | 25 # lock is symlink on platforms that support it, file on others. |
22 # are atomic even over nfs. | 28 # are atomic even over nfs. |
23 | 29 |
24 # old-style lock: symlink to pid | 30 # old-style lock: symlink to pid |
25 # new-style lock: symlink to hostname:pid | 31 # new-style lock: symlink to hostname:pid |
26 | 32 |
27 def __init__(self, file, timeout=-1, releasefn=None): | 33 def __init__(self, file, timeout=-1, releasefn=None, desc=None): |
28 self.f = file | 34 self.f = file |
29 self.held = 0 | 35 self.held = 0 |
30 self.timeout = timeout | 36 self.timeout = timeout |
31 self.releasefn = releasefn | 37 self.releasefn = releasefn |
32 self.id = None | 38 self.id = None |
33 self.host = None | 39 self.host = None |
34 self.pid = None | 40 self.pid = None |
41 self.desc = desc | |
35 self.lock() | 42 self.lock() |
36 | 43 |
37 def __del__(self): | 44 def __del__(self): |
38 self.release() | 45 self.release() |
39 | 46 |
47 if timeout != 0: | 54 if timeout != 0: |
48 time.sleep(1) | 55 time.sleep(1) |
49 if timeout > 0: | 56 if timeout > 0: |
50 timeout -= 1 | 57 timeout -= 1 |
51 continue | 58 continue |
52 raise inst | 59 raise LockHeld(errno.ETIMEDOUT, inst.filename, self.desc, |
60 inst.locker) | |
53 | 61 |
54 def trylock(self): | 62 def trylock(self): |
55 if self.id is None: | 63 if self.id is None: |
56 self.host = socket.gethostname() | 64 self.host = socket.gethostname() |
57 self.pid = os.getpid() | 65 self.pid = os.getpid() |
62 self.held = 1 | 70 self.held = 1 |
63 except (OSError, IOError), why: | 71 except (OSError, IOError), why: |
64 if why.errno == errno.EEXIST: | 72 if why.errno == errno.EEXIST: |
65 locker = self.testlock() | 73 locker = self.testlock() |
66 if locker: | 74 if locker: |
67 raise LockHeld(locker) | 75 raise LockHeld(errno.EAGAIN, self.f, self.desc, |
76 locker) | |
68 else: | 77 else: |
69 raise LockUnavailable(why) | 78 raise LockUnavailable(why.errno, why.strerror, |
79 why.filename, self.desc) | |
70 | 80 |
71 def testlock(self): | 81 def testlock(self): |
72 '''return id of locker if lock is valid, else None.''' | 82 '''return id of locker if lock is valid, else None.''' |
73 # if old-style lock, we cannot tell what machine locker is on. | 83 # if old-style lock, we cannot tell what machine locker is on. |
74 # with new-style lock, if locker is on this machine, we can | 84 # with new-style lock, if locker is on this machine, we can |