Source code for infrahouse_toolkit.lock.system
"""
A system-wide Lock class.
Where the system is a server, computer, container, and/or file system.
"""
from fcntl import LOCK_EX, LOCK_NB, LOCK_UN, flock
from infrahouse_toolkit import DEFAULT_OPEN_ENCODING
from infrahouse_toolkit.lock.base import BaseLock
from infrahouse_toolkit.lock.exceptions import LockAcquireError
[docs]class SystemLock(BaseLock):
"""
Acquire a system-wide lock.
:param lockfile: Path to a file on the local filesystem.
:type lockfile: str
:param blocking: Whether the caller should wait for the lock or exception
should be raised. If blocking is True, the caller will wait.
:type blocking: bool
:raise LockAcquireError: If we tried to acquire the lock in a non-blocking mode
and the lock is taken by somebody else.
"""
def __init__(self, lockfile: str, blocking: bool = True):
self._lockfile = lockfile
self._blocking = blocking
self._f_desc = None
super().__init__()
self._name = f"{self.__class__.name}@{self._lockfile}"
def __enter__(self):
self._f_desc = open(self._lockfile, "a", encoding=DEFAULT_OPEN_ENCODING)
try:
flock(self._f_desc, LOCK_EX if self._blocking else LOCK_EX | LOCK_NB)
except BlockingIOError as exc:
raise LockAcquireError(f"Failed to get an exclusive lock on {self._lockfile}") from exc
def __exit__(self, exc_type, exc_val, exc_tb):
flock(self._f_desc, LOCK_UN)