Ejemplo n.º 1
0
class AdaptiveLock:
    timeout = 600

    def __init__(self):
        self.method = "hard_links"

        self.lock_instance = None

    def lock(self, lock_file):
        if self.method == "hard_links":
            self.lock_instance = FluflLock(
                lock_file,
                lifetime=60)  # seconds after which the lock is broken

            try:
                self.lock_instance.lock(
                    timeout=self.timeout)  # try for a long time
                return
            except TimeoutError:
                pass
            except OSError:
                pass
            except PermissionError:
                pass

            logger.warning(
                "Unable to use hard link-based file locks. "
                "Trying fcntl-based file locks",
                exc_info=True)

            self.method = "fcntl"

        if self.method == "fcntl":
            self.lock_instance = FcntlLock(lock_file)

            acquired = self.lock_instance.acquire(timeout=self.timeout)

            if acquired:
                return

            logger.warning(
                "Unable to use fcntl-based file locks. "
                "Disabling file locks",
                exc_info=True)

            self.method = None
            self.delay = 10.0  # use a large delay to make write collisions unlikely

    def unlock(self):
        if self.method == "hard_links":
            self.lock_instance.unlock(
                unconditionally=True)  # do not raise errors in unlock
            self.lock_instance = None
        elif self.method == "fcntl":
            self.lock_instance.release()
Ejemplo n.º 2
0
class AdaptiveLock:
    def __init__(self, timeout: int = 180):
        self.timeout = timeout

        self.methods: List[str] = ["fcntl", "hard_links", "delay"]

        self.lock_instance = None

    def lock(self, lock_file):
        if self.methods[0] == "hard_links":
            self.lock_instance = FluflLock(
                lock_file, lifetime=self.timeout
            )  # seconds after which the lock is broken

            try:
                self.lock_instance.lock(
                    timeout=self.timeout)  # try for a long time
                return
            except (FluflLockError, TimeOutError):  # timeouts etc.
                pass
            except OSError:  # such as PermissionError
                pass

            logger.warning("Unable to use hard link-based file locks",
                           exc_info=True)

            self.methods.pop(0)
            self.lock(lock_file)

        elif self.methods[0] == "fcntl":
            self.lock_instance = FcntlLock(lock_file)

            acquired = self.lock_instance.acquire(timeout=self.timeout,
                                                  delay=1)

            if acquired:
                return

            logger.warning("Unable to use fcntl-based file locks",
                           exc_info=True)

            self.methods.pop(0)
            self.lock(lock_file)

        else:
            # use a random delay to make write collisions unlikely
            delay = gauss(20, 5)
            if delay > 0:
                sleep(delay)

    def unlock(self):
        if self.methods[0] == "hard_links":
            assert isinstance(self.lock_instance, FluflLock)

            self.lock_instance.unlock(
                unconditionally=True)  # do not raise errors in unlock
            self.lock_instance = None

        elif self.methods[0] == "fcntl":
            assert isinstance(self.lock_instance, FcntlLock)

            self.lock_instance.release()