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
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