Home | Trees | Indices | Help |
|
---|
|
1 """File locking for the cache system, to avoid problems 2 when multiple processes work with the same module. 3 Only works on UNIX systems. 4 5 Two python libraries can be used: 6 7 flufl.lock : A nfs safe which can be downloaded from: 8 9 https://launchpad.net/flufl.lock 10 11 fcntl : A builtin Python module which only works on posix machines 12 and it is does unfortunately not work on nfs 13 14 """ 15 16 __all__ = ["get_lock", "release_lock", "release_all_lock"] 17 18 import os.path 19 from .output import instant_error, instant_assert, instant_debug 20 from .paths import validate_cache_dir 21 22 try: 23 import flufl.lock 24 fcntl = None 25 except: 26 flufl = None 27 try: 28 import fcntl 29 except: 30 fcntl = None 31 32 # Keeping an overview of locks currently held, 33 # to avoid deadlocks within a single process. 34 _lock_names = {} # lock.fileno() -> lockname 35 _lock_files = {} # lockname -> lock 36 _lock_count = {} # lockname -> number of times this lock has been aquired and not yet released 37 38 if flufl:40 "Get a new file lock." 41 42 from flufl.lock import Lock 43 from datetime import timedelta 44 45 lockname = module_name + ".lock" 46 count = _lock_count.get(lockname, 0) 47 48 instant_debug("Acquiring lock %s, count is %d." % (lockname, count)) 49 50 cache_dir = validate_cache_dir(cache_dir) 51 lockname = os.path.join(cache_dir, lockname) 52 lock = Lock(lockname) 53 lock.lock() 54 55 return lock5658 "Release a lock currently held by Instant." 59 if lock.is_locked: 60 hostname, pid, lockname = lock.details 61 instant_debug("Releasing lock %s." % (lockname)) 62 lock.unlock()63 66 67 elif fcntl:69 "Get a new file lock." 70 global _lock_names, _lock_files, _lock_count 71 72 lockname = module_name + ".lock" 73 count = _lock_count.get(lockname, 0) 74 75 instant_debug("Acquiring lock %s, count is %d." % (lockname, count)) 76 77 if count == 0: 78 cache_dir = validate_cache_dir(cache_dir) 79 lock = open(os.path.join(cache_dir, lockname), "w") 80 fcntl.flock(lock.fileno(), fcntl.LOCK_EX) 81 _lock_names[lock.fileno()] = lockname 82 _lock_files[lockname] = lock 83 else: 84 lock = _lock_files[lockname] 85 86 _lock_count[lockname] = count + 1 87 return lock8890 "Release a lock currently held by Instant." 91 global _lock_names, _lock_files, _lock_count 92 93 lockname = _lock_names[lock.fileno()] 94 count = _lock_count[lockname] 95 96 instant_debug("Releasing lock %s, count is %d." % (lockname, count)) 97 98 instant_assert(count > 0, "Releasing lock that Instant is supposedly not holding.") 99 instant_assert(lock is _lock_files[lockname], "Lock mismatch, might be something wrong in locking logic.") 100 101 del _lock_files[lockname] 102 del _lock_names[lock.fileno()] 103 _lock_count[lockname] = count - 1 104 105 fcntl.flock(lock.fileno(), fcntl.LOCK_UN) 106 lock.close()107109 "Release all locks currently held by Instant." 110 locks = list(_lock_files.values()) 111 for lock in locks: 112 release_lock(lock) 113 instant_assert(all(_lock_count[lockname] == 0 for lockname in _lock_count), "Lock counts not zero after releasing all locks.")114 115 else: 116 # Windows systems have no fcntl, implement these otherwise if locking is needed on windows 119 122 125
Home | Trees | Indices | Help |
|
---|
Generated by Epydoc 3.0.1 on Wed Apr 10 07:12:38 2013 | http://epydoc.sourceforge.net |