summaryrefslogtreecommitdiff
path: root/src/support/filename.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/support/filename.c')
-rw-r--r--src/support/filename.c60
1 files changed, 45 insertions, 15 deletions
diff --git a/src/support/filename.c b/src/support/filename.c
index 02a83803e25..215f5b47997 100644
--- a/src/support/filename.c
+++ b/src/support/filename.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2014-2015 MongoDB, Inc.
+ * Copyright (c) 2014-2016 MongoDB, Inc.
* Copyright (c) 2008-2014 WiredTiger, Inc.
* All rights reserved.
*
@@ -65,11 +65,49 @@ __wt_remove_if_exists(WT_SESSION_IMPL *session, const char *name)
}
/*
- * __wt_sync_and_rename_fh --
+ * __wt_rename_and_sync_directory --
+ * Rename a file and sync the enclosing directory.
+ */
+int
+__wt_rename_and_sync_directory(
+ WT_SESSION_IMPL *session, const char *from, const char *to)
+{
+ const char *fp, *tp;
+ bool same_directory;
+
+ /* Rename the source file to the target. */
+ WT_RET(__wt_rename(session, from, to));
+
+ /*
+ * Flush the backing directory to guarantee the rename. My reading of
+ * POSIX 1003.1 is there's no guarantee flushing only one of the from
+ * or to directories, or flushing a common parent, is sufficient, and
+ * even if POSIX were to make that guarantee, existing filesystems are
+ * known to not provide the guarantee or only provide the guarantee
+ * with specific mount options. Flush both of the from/to directories
+ * until it's a performance problem.
+ */
+ WT_RET(__wt_directory_sync(session, from));
+
+ /*
+ * In almost all cases, we're going to be renaming files in the same
+ * directory, we can at least fast-path that.
+ */
+ fp = strrchr(from, '/');
+ tp = strrchr(to, '/');
+ same_directory = (fp == NULL && tp == NULL) ||
+ (fp != NULL && tp != NULL &&
+ fp - from == tp - to && memcmp(from, to, (size_t)(fp - from)) == 0);
+
+ return (same_directory ? 0 : __wt_directory_sync(session, to));
+}
+
+/*
+ * __wt_fh_sync_and_rename --
* Sync and close a file, and swap it into place.
*/
int
-__wt_sync_and_rename_fh(
+__wt_fh_sync_and_rename(
WT_SESSION_IMPL *session, WT_FH **fhp, const char *from, const char *to)
{
WT_DECL_RET;
@@ -83,19 +121,15 @@ __wt_sync_and_rename_fh(
WT_TRET(__wt_close(session, &fh));
WT_RET(ret);
- /* Rename the source file to the target. */
- WT_RET(__wt_rename(session, from, to));
-
- /* Flush the backing directory to guarantee the rename. */
- return (__wt_directory_sync(session, NULL));
+ return (__wt_rename_and_sync_directory(session, from, to));
}
/*
- * __wt_sync_and_rename_fp --
+ * __wt_sync_fp_and_rename --
* Sync and close a file, and swap it into place.
*/
int
-__wt_sync_and_rename_fp(
+__wt_sync_fp_and_rename(
WT_SESSION_IMPL *session, FILE **fpp, const char *from, const char *to)
{
FILE *fp;
@@ -106,9 +140,5 @@ __wt_sync_and_rename_fp(
/* Flush to disk and close the handle. */
WT_RET(__wt_fclose(&fp, WT_FHANDLE_WRITE));
- /* Rename the source file to the target. */
- WT_RET(__wt_rename(session, from, to));
-
- /* Flush the backing directory to guarantee the rename. */
- return (__wt_directory_sync(session, NULL));
+ return (__wt_rename_and_sync_directory(session, from, to));
}