diff --git a/dvc/lock.py b/dvc/lock.py index 5063cd219..0fbff6160 100644 --- a/dvc/lock.py +++ b/dvc/lock.py @@ -1,5 +1,7 @@ import os -import fasteners +import time +import zc.lockfile + from dvc.exceptions import DvcException @@ -13,18 +15,30 @@ class Lock(object): def __init__(self, dvc_dir): self.lock_file = os.path.join(dvc_dir, self.LOCK_FILE) - self._lock = fasteners.InterProcessLock(self.lock_file) + self._lock = None @staticmethod def init(dvc_dir): return Lock(dvc_dir) - def lock(self): - if not self._lock.acquire(timeout=self.TIMEOUT): + def _do_lock(self): + try: + self._lock = zc.lockfile.LockFile(self.lock_file) + except zc.lockfile.LockError: raise LockError('Cannot perform the cmd since DVC is busy and locked. Please retry the cmd later.') + def lock(self): + try: + self._do_lock() + return + except LockError: + time.sleep(self.TIMEOUT) + + self._do_lock() + def unlock(self): - self._lock.release() + self._lock.close() + self._lock = None def __enter__(self): self.lock() diff --git a/requirements.txt b/requirements.txt index 8b540a23e..8e842dcc8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ boto>=2.46.1 google-compute-engine>=2.4.1 #required by boto configparser>=3.5.0 -fasteners>=0.14.1 +zc.lockfile>=1.2.1 future>=0.16.0 google-cloud>=0.24.0 PyInstaller>=3.2.1 diff --git a/setup.py b/setup.py index 112468f5f..e81e01655 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ install_requires = [ "boto>=2.46.1", "google-compute-engine>=2.4.1", #required by boto "configparser>=3.5.0", - "fasteners>=0.14.1", + "zc.lockfile>=1.2.1", "future>=0.16.0", "google-cloud>=0.24.0", "colorama>=0.3.9", diff --git a/tests/test_lock.py b/tests/test_lock.py index f0963ff0a..edf3f1967 100644 --- a/tests/test_lock.py +++ b/tests/test_lock.py @@ -1,19 +1,21 @@ +from dvc.lock import LockError +from dvc.main import main from dvc.lock import Lock from tests.basic_env import TestDvc class TestLock(TestDvc): - def test_lock(self): - lock = Lock(self.dvc.dvc_dir) - lock.lock() - self.assertTrue(lock._lock.exists()) - self.assertTrue(lock._lock.acquired) - lock.unlock() - self.assertFalse(lock._lock.acquired) - def test_with(self): lock = Lock(self.dvc.dvc_dir) with lock: - self.assertTrue(lock._lock.acquired) - self.assertFalse(lock._lock.acquired) + with self.assertRaises(LockError): + lock2 = Lock(self.dvc.dvc_dir) + with lock2: + self.assertTrue(False) + + def test_cli(self): + lock = Lock(self.dvc.dvc_dir) + with lock: + ret = main(['add', self.FOO]) + self.assertEqual(ret, 1)