Use context manager for locking

This commit is contained in:
Unrud 2016-05-22 08:47:19 +02:00
parent ff3b31fed6
commit bca6cec6b3
2 changed files with 31 additions and 38 deletions

View File

@ -282,45 +282,37 @@ class Application:
is_authenticated = self.is_authenticated(user, password) is_authenticated = self.is_authenticated(user, password)
is_valid_user = is_authenticated or not user is_valid_user = is_authenticated or not user
lock = None # Get content
try: content_length = int(environ.get("CONTENT_LENGTH") or 0)
if is_valid_user: if content_length:
if function in (self.do_GET, self.do_HEAD, content = self.decode(
self.do_OPTIONS, self.do_PROPFIND, environ["wsgi.input"].read(content_length), environ)
self.do_REPORT): self.logger.debug("Request content:\n%s" % content)
lock_mode = "r" else:
else: content = None
lock_mode = "w"
lock = self.Collection.acquire_lock(lock_mode)
if is_valid_user:
if function in (self.do_GET, self.do_HEAD,
self.do_OPTIONS, self.do_PROPFIND,
self.do_REPORT):
lock_mode = "r"
else:
lock_mode = "w"
with self.Collection.acquire_lock(lock_mode):
items = self.Collection.discover( items = self.Collection.discover(
path, environ.get("HTTP_DEPTH", "0")) path, environ.get("HTTP_DEPTH", "0"))
read_allowed_items, write_allowed_items = ( read_allowed_items, write_allowed_items = (
self.collect_allowed_items(items, user)) self.collect_allowed_items(items, user))
else: if (read_allowed_items or write_allowed_items or
read_allowed_items, write_allowed_items = None, None is_authenticated and function == self.do_PROPFIND or
function == self.do_OPTIONS):
# Get content status, headers, answer = function(
content_length = int(environ.get("CONTENT_LENGTH") or 0) environ, read_allowed_items, write_allowed_items,
if content_length: content, user)
content = self.decode( else:
environ["wsgi.input"].read(content_length), environ) status, headers, answer = NOT_ALLOWED
self.logger.debug("Request content:\n%s" % content) else:
else: status, headers, answer = NOT_ALLOWED
content = None
if is_valid_user and (
(read_allowed_items or write_allowed_items) or
(is_authenticated and function == self.do_PROPFIND) or
function == self.do_OPTIONS):
status, headers, answer = function(
environ, read_allowed_items, write_allowed_items, content,
user)
else:
status, headers, answer = NOT_ALLOWED
finally:
if lock:
lock.release()
if (status, headers, answer) == NOT_ALLOWED and not is_authenticated: if (status, headers, answer) == NOT_ALLOWED and not is_authenticated:
# Unknown or unauthorized user # Unknown or unauthorized user

View File

@ -277,14 +277,13 @@ class BaseCollection:
raise NotImplementedError raise NotImplementedError
@classmethod @classmethod
@contextmanager
def acquire_lock(cls, mode): def acquire_lock(cls, mode):
"""Lock the whole storage. """Set a context manager to lock the whole storage.
``mode`` must either be "r" for shared access or "w" for exclusive ``mode`` must either be "r" for shared access or "w" for exclusive
access. access.
Returns an object which has a method ``release``.
""" """
raise NotImplementedError raise NotImplementedError
@ -521,6 +520,7 @@ class Collection(BaseCollection):
_lock = threading.Lock() _lock = threading.Lock()
@classmethod @classmethod
@contextmanager
def acquire_lock(cls, mode): def acquire_lock(cls, mode):
class Lock: class Lock:
def __init__(self, release_method): def __init__(self, release_method):
@ -574,4 +574,5 @@ class Collection(BaseCollection):
# TODO: use readerswriter lock # TODO: use readerswriter lock
cls._lock.acquire() cls._lock.acquire()
lock = Lock(cls._lock.release) lock = Lock(cls._lock.release)
return lock yield
lock.release()