Files
mayan-edms/mayan/apps/lock_manager/backends/file_lock.py
Roberto Rosario 09edab5027 Update lock managet app
Add keyword arguments. Sort imports. Move settings and test
literals to their own module.

Signed-off-by: Roberto Rosario <Roberto.Rosario@mayan-edms.com>
2019-01-21 02:50:34 -04:00

126 lines
3.7 KiB
Python

from __future__ import unicode_literals
import hashlib
import json
import logging
import os
import threading
import time
import uuid
from django.conf import settings
from django.core.files import locks
from django.utils.encoding import force_bytes, force_text
from mayan.apps.common.settings import setting_temporary_directory
from ..exceptions import LockError
from ..settings import setting_default_lock_timeout
from .base import LockingBackend
lock = threading.Lock()
logger = logging.getLogger(__name__)
lock_file = os.path.join(
setting_temporary_directory.value, hashlib.sha256(
force_bytes(settings.SECRET_KEY)
).hexdigest()
)
open(lock_file, 'a').close()
logger.debug('lock_file: %s', lock_file)
class FileLock(LockingBackend):
lock_file = lock_file
@classmethod
def acquire_lock(cls, name, timeout=None):
super(FileLock, cls).acquire_lock(name=name, timeout=timeout)
instance = FileLock(
name=name, timeout=timeout or setting_default_lock_timeout.value
)
return instance
@classmethod
def purge_locks(cls):
super(FileLock, cls).purge_locks()
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 = {
'expiration': time.time() + self.timeout,
'uuid': self.uuid
}
else:
result = {
'expiration': 0,
'uuid': self.uuid
}
return result
def __init__(self, name, timeout=None):
self.name = name
self.timeout = timeout or setting_default_lock_timeout.value
self.uuid = force_text(uuid.uuid4())
lock.acquire()
with open(self.__class__.lock_file, 'r+') as file_object:
locks.lock(f=file_object, flags=locks.LOCK_EX)
data = file_object.read()
if data:
file_locks = json.loads(s=data)
else:
file_locks = {}
if name in file_locks:
# Someone already got this lock, check to see if it is expired
if file_locks[name]['expiration'] and time.time() > file_locks[name]['expiration']:
# It expires and has expired, we re-acquired it
file_locks[name] = self._get_lock_dictionary()
else:
lock.release()
raise LockError
else:
file_locks[name] = self._get_lock_dictionary()
file_object.seek(0)
file_object.truncate()
file_object.write(json.dumps(file_locks))
lock.release()
def release(self):
super(FileLock, self).release()
lock.acquire()
with open(self.__class__.lock_file, 'r+') as file_object:
locks.lock(f=file_object, flags=locks.LOCK_EX)
try:
file_locks = json.loads(s=file_object.read())
except EOFError:
file_locks = {}
if self.name in file_locks:
if file_locks[self.name]['uuid'] == self.uuid:
file_locks.pop(self.name)
else:
# Lock expired and someone else acquired it
pass
else:
# Lock expired and someone else released it
pass
file_object.seek(0)
file_object.truncate()
file_object.write(json.dumps(file_locks))
lock.release()