diff --git a/HISTORY.rst b/HISTORY.rst index a37b952c1b..0412ef9235 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -8,7 +8,8 @@ XX (2017-XX-XX) - Fix role creation API endpoint not returning id. GitLab issue #390. - Make tags, metadata types and cabinets searchable via the dynamic search API. GitLab issue #344. - Add support for updating configuration options from environment variables. - +- Add purgelocks management command. GitLab issue #221. + 2.3 (2017-06-08) ================ - Allow for bigger indexing expression templates. diff --git a/mayan/apps/lock_manager/backends/base.py b/mayan/apps/lock_manager/backends/base.py new file mode 100644 index 0000000000..941e0d9ccf --- /dev/null +++ b/mayan/apps/lock_manager/backends/base.py @@ -0,0 +1,15 @@ +from __future__ import unicode_literals + + +class LockingBackend(object): + """ + Base class for the lock backends. Defines the base methods that each + subclass must define. + """ + @classmethod + def acquire_lock(cls, name, timeout=None): + raise NotImplementedError + + @classmethod + def purge_locks(cls): + raise NotImplementedError diff --git a/mayan/apps/lock_manager/backends/file_lock.py b/mayan/apps/lock_manager/backends/file_lock.py index 389d48d297..aae3b6c024 100644 --- a/mayan/apps/lock_manager/backends/file_lock.py +++ b/mayan/apps/lock_manager/backends/file_lock.py @@ -13,6 +13,8 @@ from common.settings import setting_temporary_directory from ..exceptions import LockError +from .base import LockingBackend + lock = threading.Lock() logger = logging.getLogger(__name__) @@ -23,7 +25,7 @@ open(lock_file, 'a').close() logger.debug('lock_file: %s', lock_file) -class FileLock(object): +class FileLock(LockingBackend): lock_file = lock_file @classmethod @@ -31,6 +33,15 @@ class FileLock(object): instance = FileLock(name=name, timeout=timeout) return instance + @classmethod + def purge_locks(cls): + lock.acquire() + with open(cls.lock_file, 'r+') as file_object: + locks.lock(f=file_object, flags=locks.LOCK_EX) + file_object.seek(0) + file_object.truncate() + lock.release() + def _get_lock_dictionary(self): if self.timeout: result = { diff --git a/mayan/apps/lock_manager/backends/model_lock.py b/mayan/apps/lock_manager/backends/model_lock.py index 30ba0afb1a..59b9415f8a 100644 --- a/mayan/apps/lock_manager/backends/model_lock.py +++ b/mayan/apps/lock_manager/backends/model_lock.py @@ -2,9 +2,16 @@ from __future__ import unicode_literals from django.apps import apps +from .base import LockingBackend -class ModelLock(object): + +class ModelLock(LockingBackend): @classmethod def acquire_lock(cls, name, timeout=None): Lock = apps.get_model(app_label='lock_manager', model_name='Lock') return Lock.objects.acquire_lock(name=name, timeout=timeout) + + @classmethod + def purge_locks(cls): + Lock = apps.get_model(app_label='lock_manager', model_name='Lock') + Lock.objects.select_for_update().delete() diff --git a/mayan/apps/lock_manager/management/__init__.py b/mayan/apps/lock_manager/management/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mayan/apps/lock_manager/management/commands/__init__.py b/mayan/apps/lock_manager/management/commands/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mayan/apps/lock_manager/management/commands/purgelocks.py b/mayan/apps/lock_manager/management/commands/purgelocks.py new file mode 100644 index 0000000000..561eeb342f --- /dev/null +++ b/mayan/apps/lock_manager/management/commands/purgelocks.py @@ -0,0 +1,12 @@ +from __future__ import unicode_literals + +from django.core import management + +from ...runtime import locking_backend + + +class Command(management.BaseCommand): + help = 'Erase all locks (acquired and stale).' + + def handle(self, *args, **options): + locking_backend.purge_locks()