diff options
Diffstat (limited to 'src/third_party/wiredtiger/src/support/filename.c')
-rw-r--r-- | src/third_party/wiredtiger/src/support/filename.c | 60 |
1 files changed, 45 insertions, 15 deletions
diff --git a/src/third_party/wiredtiger/src/support/filename.c b/src/third_party/wiredtiger/src/support/filename.c index 02a83803e25..215f5b47997 100644 --- a/src/third_party/wiredtiger/src/support/filename.c +++ b/src/third_party/wiredtiger/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)); } |