Mercurial > repos > melissacline > ucsc_xena_platform
comparison lockfile-0.10.2/lockfile/__init__.py @ 33:7ceb967147c3
start xena with no gui
add library files
author | jingchunzhu <jingchunzhu@gmail.com> |
---|---|
date | Wed, 22 Jul 2015 13:24:44 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
32:63b1ba1e3424 | 33:7ceb967147c3 |
---|---|
1 """ | |
2 lockfile.py - Platform-independent advisory file locks. | |
3 | |
4 Requires Python 2.5 unless you apply 2.4.diff | |
5 Locking is done on a per-thread basis instead of a per-process basis. | |
6 | |
7 Usage: | |
8 | |
9 >>> lock = LockFile('somefile') | |
10 >>> try: | |
11 ... lock.acquire() | |
12 ... except AlreadyLocked: | |
13 ... print 'somefile', 'is locked already.' | |
14 ... except LockFailed: | |
15 ... print 'somefile', 'can\\'t be locked.' | |
16 ... else: | |
17 ... print 'got lock' | |
18 got lock | |
19 >>> print lock.is_locked() | |
20 True | |
21 >>> lock.release() | |
22 | |
23 >>> lock = LockFile('somefile') | |
24 >>> print lock.is_locked() | |
25 False | |
26 >>> with lock: | |
27 ... print lock.is_locked() | |
28 True | |
29 >>> print lock.is_locked() | |
30 False | |
31 | |
32 >>> lock = LockFile('somefile') | |
33 >>> # It is okay to lock twice from the same thread... | |
34 >>> with lock: | |
35 ... lock.acquire() | |
36 ... | |
37 >>> # Though no counter is kept, so you can't unlock multiple times... | |
38 >>> print lock.is_locked() | |
39 False | |
40 | |
41 Exceptions: | |
42 | |
43 Error - base class for other exceptions | |
44 LockError - base class for all locking exceptions | |
45 AlreadyLocked - Another thread or process already holds the lock | |
46 LockFailed - Lock failed for some other reason | |
47 UnlockError - base class for all unlocking exceptions | |
48 AlreadyUnlocked - File was not locked. | |
49 NotMyLock - File was locked but not by the current thread/process | |
50 """ | |
51 | |
52 from __future__ import absolute_import | |
53 | |
54 import sys | |
55 import socket | |
56 import os | |
57 import threading | |
58 import time | |
59 import urllib | |
60 import warnings | |
61 import functools | |
62 | |
63 # Work with PEP8 and non-PEP8 versions of threading module. | |
64 if not hasattr(threading, "current_thread"): | |
65 threading.current_thread = threading.currentThread | |
66 if not hasattr(threading.Thread, "get_name"): | |
67 threading.Thread.get_name = threading.Thread.getName | |
68 | |
69 __all__ = ['Error', 'LockError', 'LockTimeout', 'AlreadyLocked', | |
70 'LockFailed', 'UnlockError', 'NotLocked', 'NotMyLock', | |
71 'LinkLockFile', 'MkdirLockFile', 'SQLiteLockFile', | |
72 'LockBase', 'locked'] | |
73 | |
74 class Error(Exception): | |
75 """ | |
76 Base class for other exceptions. | |
77 | |
78 >>> try: | |
79 ... raise Error | |
80 ... except Exception: | |
81 ... pass | |
82 """ | |
83 pass | |
84 | |
85 class LockError(Error): | |
86 """ | |
87 Base class for error arising from attempts to acquire the lock. | |
88 | |
89 >>> try: | |
90 ... raise LockError | |
91 ... except Error: | |
92 ... pass | |
93 """ | |
94 pass | |
95 | |
96 class LockTimeout(LockError): | |
97 """Raised when lock creation fails within a user-defined period of time. | |
98 | |
99 >>> try: | |
100 ... raise LockTimeout | |
101 ... except LockError: | |
102 ... pass | |
103 """ | |
104 pass | |
105 | |
106 class AlreadyLocked(LockError): | |
107 """Some other thread/process is locking the file. | |
108 | |
109 >>> try: | |
110 ... raise AlreadyLocked | |
111 ... except LockError: | |
112 ... pass | |
113 """ | |
114 pass | |
115 | |
116 class LockFailed(LockError): | |
117 """Lock file creation failed for some other reason. | |
118 | |
119 >>> try: | |
120 ... raise LockFailed | |
121 ... except LockError: | |
122 ... pass | |
123 """ | |
124 pass | |
125 | |
126 class UnlockError(Error): | |
127 """ | |
128 Base class for errors arising from attempts to release the lock. | |
129 | |
130 >>> try: | |
131 ... raise UnlockError | |
132 ... except Error: | |
133 ... pass | |
134 """ | |
135 pass | |
136 | |
137 class NotLocked(UnlockError): | |
138 """Raised when an attempt is made to unlock an unlocked file. | |
139 | |
140 >>> try: | |
141 ... raise NotLocked | |
142 ... except UnlockError: | |
143 ... pass | |
144 """ | |
145 pass | |
146 | |
147 class NotMyLock(UnlockError): | |
148 """Raised when an attempt is made to unlock a file someone else locked. | |
149 | |
150 >>> try: | |
151 ... raise NotMyLock | |
152 ... except UnlockError: | |
153 ... pass | |
154 """ | |
155 pass | |
156 | |
157 class LockBase: | |
158 """Base class for platform-specific lock classes.""" | |
159 def __init__(self, path, threaded=True, timeout=None): | |
160 """ | |
161 >>> lock = LockBase('somefile') | |
162 >>> lock = LockBase('somefile', threaded=False) | |
163 """ | |
164 self.path = path | |
165 self.lock_file = os.path.abspath(path) + ".lock" | |
166 self.hostname = socket.gethostname() | |
167 self.pid = os.getpid() | |
168 if threaded: | |
169 t = threading.current_thread() | |
170 # Thread objects in Python 2.4 and earlier do not have ident | |
171 # attrs. Worm around that. | |
172 ident = getattr(t, "ident", hash(t)) | |
173 self.tname = "-%x" % (ident & 0xffffffff) | |
174 else: | |
175 self.tname = "" | |
176 dirname = os.path.dirname(self.lock_file) | |
177 | |
178 # unique name is mostly about the current process, but must | |
179 # also contain the path -- otherwise, two adjacent locked | |
180 # files conflict (one file gets locked, creating lock-file and | |
181 # unique file, the other one gets locked, creating lock-file | |
182 # and overwriting the already existing lock-file, then one | |
183 # gets unlocked, deleting both lock-file and unique file, | |
184 # finally the last lock errors out upon releasing. | |
185 self.unique_name = os.path.join(dirname, | |
186 "%s%s.%s%s" % (self.hostname, | |
187 self.tname, | |
188 self.pid, | |
189 hash(self.path))) | |
190 self.timeout = timeout | |
191 | |
192 def acquire(self, timeout=None): | |
193 """ | |
194 Acquire the lock. | |
195 | |
196 * If timeout is omitted (or None), wait forever trying to lock the | |
197 file. | |
198 | |
199 * If timeout > 0, try to acquire the lock for that many seconds. If | |
200 the lock period expires and the file is still locked, raise | |
201 LockTimeout. | |
202 | |
203 * If timeout <= 0, raise AlreadyLocked immediately if the file is | |
204 already locked. | |
205 """ | |
206 raise NotImplemented("implement in subclass") | |
207 | |
208 def release(self): | |
209 """ | |
210 Release the lock. | |
211 | |
212 If the file is not locked, raise NotLocked. | |
213 """ | |
214 raise NotImplemented("implement in subclass") | |
215 | |
216 def is_locked(self): | |
217 """ | |
218 Tell whether or not the file is locked. | |
219 """ | |
220 raise NotImplemented("implement in subclass") | |
221 | |
222 def i_am_locking(self): | |
223 """ | |
224 Return True if this object is locking the file. | |
225 """ | |
226 raise NotImplemented("implement in subclass") | |
227 | |
228 def break_lock(self): | |
229 """ | |
230 Remove a lock. Useful if a locking thread failed to unlock. | |
231 """ | |
232 raise NotImplemented("implement in subclass") | |
233 | |
234 def __enter__(self): | |
235 """ | |
236 Context manager support. | |
237 """ | |
238 self.acquire() | |
239 return self | |
240 | |
241 def __exit__(self, *_exc): | |
242 """ | |
243 Context manager support. | |
244 """ | |
245 self.release() | |
246 | |
247 def __repr__(self): | |
248 return "<%s: %r -- %r>" % (self.__class__.__name__, self.unique_name, | |
249 self.path) | |
250 | |
251 def _fl_helper(cls, mod, *args, **kwds): | |
252 warnings.warn("Import from %s module instead of lockfile package" % mod, | |
253 DeprecationWarning, stacklevel=2) | |
254 # This is a bit funky, but it's only for awhile. The way the unit tests | |
255 # are constructed this function winds up as an unbound method, so it | |
256 # actually takes three args, not two. We want to toss out self. | |
257 if not isinstance(args[0], str): | |
258 # We are testing, avoid the first arg | |
259 args = args[1:] | |
260 if len(args) == 1 and not kwds: | |
261 kwds["threaded"] = True | |
262 return cls(*args, **kwds) | |
263 | |
264 def LinkFileLock(*args, **kwds): | |
265 """Factory function provided for backwards compatibility. | |
266 | |
267 Do not use in new code. Instead, import LinkLockFile from the | |
268 lockfile.linklockfile module. | |
269 """ | |
270 from . import linklockfile | |
271 return _fl_helper(linklockfile.LinkLockFile, "lockfile.linklockfile", | |
272 *args, **kwds) | |
273 | |
274 def MkdirFileLock(*args, **kwds): | |
275 """Factory function provided for backwards compatibility. | |
276 | |
277 Do not use in new code. Instead, import MkdirLockFile from the | |
278 lockfile.mkdirlockfile module. | |
279 """ | |
280 from . import mkdirlockfile | |
281 return _fl_helper(mkdirlockfile.MkdirLockFile, "lockfile.mkdirlockfile", | |
282 *args, **kwds) | |
283 | |
284 def SQLiteFileLock(*args, **kwds): | |
285 """Factory function provided for backwards compatibility. | |
286 | |
287 Do not use in new code. Instead, import SQLiteLockFile from the | |
288 lockfile.mkdirlockfile module. | |
289 """ | |
290 from . import sqlitelockfile | |
291 return _fl_helper(sqlitelockfile.SQLiteLockFile, "lockfile.sqlitelockfile", | |
292 *args, **kwds) | |
293 | |
294 def locked(path, timeout=None): | |
295 """Decorator which enables locks for decorated function. | |
296 | |
297 Arguments: | |
298 - path: path for lockfile. | |
299 - timeout (optional): Timeout for acquiring lock. | |
300 | |
301 Usage: | |
302 @locked('/var/run/myname', timeout=0) | |
303 def myname(...): | |
304 ... | |
305 """ | |
306 def decor(func): | |
307 @functools.wraps(func) | |
308 def wrapper(*args, **kwargs): | |
309 lock = FileLock(path, timeout=timeout) | |
310 lock.acquire() | |
311 try: | |
312 return func(*args, **kwargs) | |
313 finally: | |
314 lock.release() | |
315 return wrapper | |
316 return decor | |
317 | |
318 if hasattr(os, "link"): | |
319 from . import linklockfile as _llf | |
320 LockFile = _llf.LinkLockFile | |
321 else: | |
322 from . import mkdirlockfile as _mlf | |
323 LockFile = _mlf.MkdirLockFile | |
324 | |
325 FileLock = LockFile | |
326 |