diff options
| author | Julien Danjou <julien@danjou.info> | 2016-07-27 15:28:40 +0200 |
|---|---|---|
| committer | Julien Danjou <julien@danjou.info> | 2016-09-30 17:17:47 +0200 |
| commit | d48d8bc3fb0bb89de63346d553065f97fd6b3195 (patch) | |
| tree | 5b138ff97a47cb716c56bb1ce759df2aabeb4c5a | |
| parent | adbb5bf466730803f62a25acd0e21fcbe3f82ce4 (diff) | |
| download | tooz-d48d8bc3fb0bb89de63346d553065f97fd6b3195.tar.gz | |
file: update .metadata atomically
This change the method writing the .metadata file for each group to do
it in an atomic fashion. This avoids the need to lock the whole driver
to read/write the group information.
Change-Id: Id615145b936463f13eb4d45717cd88f2ab34b105
| -rw-r--r-- | tooz/drivers/file.py | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/tooz/drivers/file.py b/tooz/drivers/file.py index fa68e28..c1fc12d 100644 --- a/tooz/drivers/file.py +++ b/tooz/drivers/file.py @@ -23,6 +23,7 @@ import os import re import shutil import sys +import tempfile import threading import weakref @@ -210,10 +211,11 @@ class FileDriver(coordination._RunWatchersMixin, self._dir = self._normalize_path(parsed_url.path) self._executor = utils.ProxyExecutor.build("File", options) self._group_dir = os.path.join(self._dir, 'groups') + self._tmpdir = os.path.join(self._dir, 'tmp') self._driver_lock_path = os.path.join(self._dir, '.driver_lock') self._driver_lock = self._get_raw_lock(self._driver_lock_path, self._member_id) - self._reserved_dirs = [self._dir, self._group_dir] + self._reserved_dirs = [self._dir, self._group_dir, self._tmpdir] self._reserved_paths = list(self._reserved_dirs) self._reserved_paths.append(self._driver_lock_path) self._joined_groups = set() @@ -269,17 +271,18 @@ class FileDriver(coordination._RunWatchersMixin, } details[u'encoded'] = details[u"group_id"] != group_id details_blob = utils.dumps(details) - with open(path, "wb") as fh: + fd, name = tempfile.mkstemp("tooz", dir=self._tmpdir) + with os.fdopen(fd, "wb") as fh: fh.write(details_blob) + os.rename(name, path) def create_group(self, group_id): safe_group_id = self._make_filesystem_safe(group_id) group_dir = os.path.join(self._group_dir, safe_group_id) group_meta_path = os.path.join(group_dir, '.metadata') - @_lock_me(self._driver_lock) def _do_create_group(): - if os.path.isdir(group_dir): + if os.path.exists(os.path.join(group_dir, ".metadata")): # NOTE(sileht): We update the group metadata even # they are already good, so ensure dict key are convert # to unicode in case of the file have been written with @@ -299,7 +302,7 @@ class FileDriver(coordination._RunWatchersMixin, @_lock_me(self._driver_lock) def _do_join_group(): - if not os.path.isdir(group_dir): + if not os.path.exists(os.path.join(group_dir, ".metadata")): raise coordination.GroupNotCreated(group_id) if os.path.isfile(me_path): raise coordination.MemberAlreadyExist(group_id, @@ -326,7 +329,7 @@ class FileDriver(coordination._RunWatchersMixin, @_lock_me(self._driver_lock) def _do_leave_group(): - if not os.path.isdir(group_dir): + if not os.path.exists(os.path.join(group_dir, ".metadata")): raise coordination.GroupNotCreated(group_id) try: os.unlink(me_path) @@ -465,7 +468,6 @@ class FileDriver(coordination._RunWatchersMixin, def get_groups(self): - @_lock_me(self._driver_lock) def _do_get_groups(): groups = [] for entry in os.listdir(self._group_dir): |
