1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-04-13 07:47:14 +03:00

Re-factor JournalLock.obtain_lock() for 'ALREADY_LOCKED' test.

This splits the code for opening the lockfile away from that for
actually obtaining the lock.  It enables a test for trying to lock again
with the same file handle.
This commit is contained in:
Athanasius 2021-03-19 19:16:45 +00:00
parent 70bdc5e0e9
commit cfdf9fbf20
2 changed files with 40 additions and 10 deletions

View File

@ -53,16 +53,9 @@ class JournalLock:
except Exception:
logger.exception("Couldn't make pathlib.Path from journal_dir")
def obtain_lock(self) -> JournalLockResult:
"""
Attempt to obtain a lock on the journal directory.
:return: LockResult - See the class Enum definition
"""
if self.journal_dir_path is None:
return JournalLockResult.JOURNALDIR_IS_NONE
self.journal_dir_lockfile_name = self.journal_dir_path / 'edmc-journal-lock.txt'
def open_journal_dir_lockfile(self) -> bool:
"""Open journal_dir lockfile ready for locking."""
self.journal_dir_lockfile_name = self.journal_dir_path / 'edmc-journal-lock.txt' # type: ignore
logger.trace(f'journal_dir_lockfile_name = {self.journal_dir_lockfile_name!r}')
try:
self.journal_dir_lockfile = open(self.journal_dir_lockfile_name, mode='w+', encoding='utf-8')
@ -72,8 +65,35 @@ class JournalLock:
except Exception as e: # For remote FS this could be any of a wide range of exceptions
logger.warning(f"Couldn't open \"{self.journal_dir_lockfile_name}\" for \"w+\""
f" Aborting duplicate process checks: {e!r}")
return False
return True
def obtain_lock(self) -> JournalLockResult:
"""
Attempt to obtain a lock on the journal directory.
:return: LockResult - See the class Enum definition
"""
if self.journal_dir_path is None:
return JournalLockResult.JOURNALDIR_IS_NONE
if not self.open_journal_dir_lockfile():
return JournalLockResult.JOURNALDIR_READONLY
return self._obtain_lock()
def _obtain_lock(self) -> JournalLockResult:
"""
Actual code for obtaining a lock.
This is split out so tests can call *just* it, without the attempt
at opening the file. If we call open_journal_dir_lockfile() we
re-use self.journal_dir_lockfile and in the process close the
previous handle stored in it and thus release the lock.
:return: LockResult - See the class Enum definition
"""
if platform == 'win32':
logger.trace('win32, using msvcrt')
# win32 doesn't have fcntl, so we have to use msvcrt

View File

@ -182,3 +182,13 @@ class TestJournalLock:
os.chmod(tmpdir, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
assert locked == JournalLockResult.JOURNALDIR_READONLY
def test_obtain_lock_already_locked(self, mock_journaldir: py_path_local_LocalPath):
"""Test JournalLock.obtain_lock() with tmpdir."""
jlock = JournalLock()
locked = jlock.obtain_lock()
assert locked == JournalLockResult.LOCKED
# Now attempt to lock again, but only that.
second_attempt = jlock._obtain_lock()
assert second_attempt == JournalLockResult.ALREADY_LOCKED