1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """
17 Contains locking classes.
18 """
19
20 import os
21 import re
22 import time
23 import fcntl
24 from threading import RLock
25
26
29
32
33
35 """
36 File based locking.
37 @ivar path: The absolute path to the lock file.
38 @type path: str
39 @ivar __fp: The I{file pointer} to the lock file.
40 @type __fp: I{file-like} pointer.
41 """
42
44 """
45 @param path: The absolute path to the lock file.
46 @type path: str
47 """
48 self.path = path
49 self.__fp = None
50 self.__mkdir(path)
51
53 """
54 Acquire the lockfile.
55 @param blocking: Wait for the lock.
56 @type blocking: bool
57 @return: self
58 @rtype: L{LockFile}
59 """
60 fp = open(self.path, 'w')
61 if not blocking:
62 try:
63 fcntl.flock(fp.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB)
64 except IOError:
65 fp.close()
66 raise LockFailed(self.path)
67 else:
68 fcntl.flock(fp.fileno(), fcntl.LOCK_EX)
69 self.__fp = fp
70 self.setpid()
71 return self
72
74 """
75 Release the lockfile.
76 """
77 try:
78 if self.__fp.closed:
79 return
80 fd = self.__fp.fileno()
81 self.__fp.close()
82 except:
83 pass
84
86 """
87 Get the process id.
88 @return: The pid in the lock file, else the current pid.
89 @rtype: int
90 """
91 pid = 0
92 fp = open(self.path)
93 content = fp.read()
94 if content:
95 pid = int(content)
96 return pid
97
99 """
100 Write our procecss id and flush.
101 @param pid: The process ID.
102 @type pid: int
103 """
104 self.__fp.seek(0)
105 self.__fp.write(str(pid))
106 self.__fp.flush()
107
109 dir = os.path.dirname(path)
110 if not os.path.exists(dir):
111 os.makedirs(dir)
112
113
115 """
116 File backed Reentrant lock.
117 """
118
120 self.__depth = 0
121 self.__mutex = RLock()
122 self.__lockf = LockFile(path)
123
125 """
126 Acquire the lock.
127 Acquire the mutex; acquire the lockfile.
128 @param blocking: Wait for the lock.
129 @type blocking: bool
130 @return: self
131 @rtype: L{Lock}
132 """
133 self.__lock(blocking)
134 if self.__push() == 1:
135 try:
136 self.__lockf.acquire(blocking)
137 except:
138 self.__pop()
139 raise
140 return self
141
143 """
144 Release the lock.
145 Release the lockfile; release the mutex.
146 """
147 if self.__pop() == 0:
148 self.__lockf.release()
149 self.__unlock()
150 return self
151
153 """
154 Write our procecss id and flush.
155 @param pid: The process ID.
156 @type pid: int
157 """
158 self.__lock()
159 try:
160 self.__lockf.setpid(pid)
161 finally:
162 self.__unlock()
163
165 """
166 Increment the lock depth.
167 @return: The incremented depth
168 @rtype: int
169 """
170 self.__lock()
171 try:
172 self.__depth += 1
173 return self.__depth
174 finally:
175 self.__unlock()
176
178 """
179 Decrement the lock depth.
180 @return: The decremented depth
181 @rtype: int
182 """
183 self.__lock()
184 try:
185 if self.__depth > 0:
186 self.__depth -= 1
187 return self.__depth
188 finally:
189 self.__unlock()
190
191 - def __lock(self, blocking=1):
194
197