summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Danjou <julien@danjou.info>2016-07-27 15:28:40 +0200
committerJulien Danjou <julien@danjou.info>2016-09-30 17:17:47 +0200
commitd48d8bc3fb0bb89de63346d553065f97fd6b3195 (patch)
tree5b138ff97a47cb716c56bb1ce759df2aabeb4c5a
parentadbb5bf466730803f62a25acd0e21fcbe3f82ce4 (diff)
downloadtooz-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.py16
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):