def _get_unused_port(start, end=65536): """Get an unused port in the range [start, end) . Args: start (int) : port range start end (int): port range end """ process_lock = None unused_port = None try: for port in range(start, end): process_lock = InterProcessLock( path='/tmp/socialbot/{}.lock'.format(port)) if not process_lock.acquire(blocking=False): process_lock.lockfile.close() process_lock = None continue try: with contextlib.closing(socket.socket()) as sock: sock.bind(('', port)) unused_port = port break except socket.error: process_lock.release() process_lock = None if unused_port is None: raise socket.error("No unused port in [{}, {})".format(start, end)) yield unused_port finally: if process_lock is not None: process_lock.release()
class ComboLock: """ A combined process and thread lock. Arguments: path (str): path to the lockfile for the lock """ def __init__(self, path): self.path = path self.plock = InterProcessLock(self.path) self.tlock = Lock() def acquire(self, blocking=True): """ Acquire lock, locks thread and process lock. Arguments: blocking(bool): Set's blocking mode of acquire operation. Default True. Returns: True if lock succeeded otherwise False """ # Create lock file if it doesn't exist and set permissions for # all users to lock/unlock if not exists(self.path): f = open(self.path, 'w+') f.close() chmod(self.path, 0o777) if not blocking: # Lock thread tlocked = self.tlock.acquire(blocking=False) if not tlocked: return False # Lock process plocked = self.plock.acquire(blocking=False) if not plocked: # Release thread lock if process couldn't be locked self.tlock.release() return False else: # blocking, just wait and acquire ALL THE LOCKS!!! self.tlock.acquire() self.plock.acquire() return True def release(self): """ Release acquired lock. """ self.plock.release() self.tlock.release() def __enter__(self): """ Context handler, acquires lock in blocking mode. """ self.acquire() return self def __exit__(self, _type, value, traceback): """ Releases the lock. """ self.release()
class ComboLock: """ A combined process and thread lock. Arguments: path (str): path to the lockfile for the lock """ def __init__(self, path): # Create lock file if it doesn't exist and set permissions for # all users to lock/unlock if not exists(path): f = open(path, 'w+') f.close() chmod(path, 0o777) self.plock = InterProcessLock(path) self.tlock = Lock() def acquire(self, blocking=True): """ Acquire lock, locks thread and process lock. Arguments: blocking(bool): Set's blocking mode of acquire operation. Default True. Returns: True if lock succeeded otherwise False """ if not blocking: # Lock thread tlocked = self.tlock.acquire(blocking=False) if not tlocked: return False # Lock process plocked = self.plock.acquire(blocking=False) if not plocked: # Release thread lock if process couldn't be locked self.tlock.release() return False else: # blocking, just wait and acquire ALL THE LOCKS!!! self.tlock.acquire() self.plock.acquire() return True def release(self): """ Release acquired lock. """ self.plock.release() self.tlock.release() def __enter__(self): """ Context handler, acquires lock in blocking mode. """ self.acquire() return self def __exit__(self, _type, value, traceback): """ Releases the lock. """ self.release()
def get_next(self): a_lock = None locked = False try: a_lock = InterProcessLock(self.uid_pidlock_filepath) locked = a_lock.acquire(blocking=True) if locked: v = self.load_value() v_next = v + 1 self.save_value(v_next) return v_next finally: if locked and a_lock is not None: a_lock.release()
class ReducerStats(object): """ReducerStats holds stats for the Grizzly reducer. """ FILE = "reducer-stats.json" PATH = grz_tmp("status") __slots__ = ("_file", "_lock", "error", "failed", "passed") def __init__(self): self._file = pathjoin(self.PATH, self.FILE) self._lock = None self.error = 0 self.failed = 0 self.passed = 0 def __enter__(self): self._lock = InterProcessLock("%s.lock" % (self._file, )) self._lock.acquire() try: with open(self._file, "r") as in_fp: data = load(in_fp) self.error = data["error"] self.failed = data["failed"] self.passed = data["passed"] except KeyError: LOG.debug("invalid status data in %r", self._file) except OSError: LOG.debug("%r does not exist", self._file) except ValueError: LOG.debug("failed to load stats from %r", self._file) return self def __exit__(self, exc_type, exc_val, exc_tb): try: with open(self._file, "w") as out_fp: dump( { "error": self.error, "failed": self.failed, "passed": self.passed }, out_fp) finally: if self._lock: self._lock.release() self._lock = None