Fix race when creating storage lock

This commit is contained in:
Unrud 2018-04-29 21:36:01 +02:00
parent 3d2ffe0c8e
commit 5adcab77a3

View File

@ -114,6 +114,7 @@ def load(configuration, logger):
"""Collection copy, avoids overriding the original class attributes.""" """Collection copy, avoids overriding the original class attributes."""
CollectionCopy.configuration = configuration CollectionCopy.configuration = configuration
CollectionCopy.logger = logger CollectionCopy.logger = logger
CollectionCopy.static_init()
return CollectionCopy return CollectionCopy
@ -432,6 +433,11 @@ class BaseCollection:
""" """
path = "" path = ""
@classmethod
def static_init():
"""init collection copy"""
pass
@property @property
def owner(self): def owner(self):
"""The owner of the collection.""" """The owner of the collection."""
@ -739,6 +745,19 @@ ITEM_CACHE_VERSION = 1
class Collection(BaseCollection): class Collection(BaseCollection):
"""Collection stored in several files per calendar.""" """Collection stored in several files per calendar."""
@classmethod
def static_init(cls):
# init storage lock
folder = os.path.expanduser(cls.configuration.get(
"storage", "filesystem_folder"))
cls._makedirs_synced(folder)
lock_path = None
if cls.configuration.getboolean("storage", "filesystem_locking"):
lock_path = os.path.join(folder, ".Radicale.lock")
close_lock_file = cls.configuration.getboolean(
"storage", "filesystem_close_lock_file")
cls._lock = FileBackedRwLock(lock_path, close_lock_file)
def __init__(self, path, principal=None, folder=None, def __init__(self, path, principal=None, folder=None,
filesystem_path=None): filesystem_path=None):
# DEPRECATED: Remove principal and folder attributes # DEPRECATED: Remove principal and folder attributes
@ -1535,26 +1554,16 @@ class Collection(BaseCollection):
self._etag_cache = super().etag self._etag_cache = super().etag
return self._etag_cache return self._etag_cache
_lock = None
@classmethod @classmethod
@contextmanager @contextmanager
def acquire_lock(cls, mode, user=None): def acquire_lock(cls, mode, user=None):
folder = os.path.expanduser(cls.configuration.get(
"storage", "filesystem_folder"))
if not cls._lock:
cls._makedirs_synced(folder)
lock_path = None
if cls.configuration.getboolean("storage", "filesystem_locking"):
lock_path = os.path.join(folder, ".Radicale.lock")
close_lock_file = cls.configuration.getboolean(
"storage", "filesystem_close_lock_file")
cls._lock = FileBackedRwLock(lock_path, close_lock_file)
with cls._lock.acquire_lock(mode): with cls._lock.acquire_lock(mode):
yield yield
# execute hook # execute hook
hook = cls.configuration.get("storage", "hook") hook = cls.configuration.get("storage", "hook")
if mode == "w" and hook: if mode == "w" and hook:
folder = os.path.expanduser(cls.configuration.get(
"storage", "filesystem_folder"))
cls.logger.debug("Running hook") cls.logger.debug("Running hook")
debug = cls.logger.isEnabledFor(logging.DEBUG) debug = cls.logger.isEnabledFor(logging.DEBUG)
p = subprocess.Popen( p = subprocess.Popen(