Refuse to run a second eris instance on the same directory
flock on .eris/lock prevents two eris processes racing the cache, which previously produced a mixed-format summary (int-list pages) and crashed sync_with_filesystem. The lock is acquired before manage_cache, the lock file survives checksum-mismatch cleanup, and the holder's PID is written to the lock file so a refused instance can report it.
This commit is contained in:
parent
980ee7071c
commit
329f500c8e
2 changed files with 115 additions and 13 deletions
|
|
@ -201,5 +201,60 @@ class SummarySyncWithFilesystemTestCase(unittest.TestCase):
|
|||
id(self.summary._entries[3])) # zoo
|
||||
self.assertTrue(self.jobs_added_event.is_set())
|
||||
|
||||
class CacheLockTestCase(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.temp_dir = tempfile.mkdtemp()
|
||||
self.cache_path = os.path.join(self.temp_dir, tools.CACHE_PATH)
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.temp_dir)
|
||||
|
||||
def test_acquire_lock_conflict_and_release(self):
|
||||
lock_fd = __main__.acquire_lock(self.cache_path)
|
||||
lock_path = os.path.join(self.cache_path, "lock")
|
||||
self.assertTrue(os.path.exists(lock_path))
|
||||
with open(lock_path) as lock_file:
|
||||
self.assertEqual(lock_file.read(), str(os.getpid()))
|
||||
with self.assertRaises(__main__.LockError) as error:
|
||||
__main__.acquire_lock(self.cache_path)
|
||||
self.assertEqual(error.exception.holder_pid, str(os.getpid()))
|
||||
os.close(lock_fd)
|
||||
lock_fd = __main__.acquire_lock(self.cache_path)
|
||||
os.close(lock_fd)
|
||||
|
||||
def test_manage_cache_preserves_lock_on_checksum_mismatch(self):
|
||||
lock_fd = __main__.acquire_lock(self.cache_path)
|
||||
lock_path = os.path.join(self.cache_path, "lock")
|
||||
with open(os.path.join(self.cache_path, "source_checksum"), "w") as checksum_file:
|
||||
checksum_file.write("stale-checksum")
|
||||
stale_pickle = os.path.join(self.cache_path, "summary.pickle")
|
||||
stale_dir = os.path.join(self.cache_path, "summary_dir")
|
||||
_touch(stale_pickle)
|
||||
os.mkdir(stale_dir)
|
||||
original_checksum = __main__.source_checksum
|
||||
__main__.source_checksum = lambda: "new-checksum"
|
||||
try:
|
||||
__main__.manage_cache(self.temp_dir)
|
||||
finally:
|
||||
__main__.source_checksum = original_checksum
|
||||
os.close(lock_fd)
|
||||
self.assertTrue(os.path.exists(lock_path))
|
||||
self.assertFalse(os.path.exists(stale_pickle))
|
||||
self.assertFalse(os.path.exists(stale_dir))
|
||||
with open(os.path.join(self.cache_path, "source_checksum")) as checksum_file:
|
||||
self.assertEqual(checksum_file.read(), "new-checksum")
|
||||
self.assertTrue(os.path.exists(os.path.join(self.cache_path, ".gitignore")))
|
||||
|
||||
def test_manage_cache_first_run_keeps_lock(self):
|
||||
lock_fd = __main__.acquire_lock(self.cache_path)
|
||||
os.close(lock_fd)
|
||||
__main__.manage_cache(self.temp_dir)
|
||||
self.assertTrue(os.path.exists(os.path.join(self.cache_path, "lock")))
|
||||
with open(os.path.join(self.cache_path, "source_checksum")) as checksum_file:
|
||||
self.assertEqual(checksum_file.read(), __main__.source_checksum())
|
||||
self.assertTrue(os.path.exists(os.path.join(self.cache_path, ".gitignore")))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
golden.main()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue