summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Chen <luke.chen@mongodb.com>2018-05-16 14:48:23 +1000
committerLuke Chen <luke.chen@mongodb.com>2018-05-16 14:48:23 +1000
commit081ec07c4807774227a6bded19aa7b001666d281 (patch)
tree5518d943c453ed92d489f961a9106daeaf492480
parent19d3fb3948496052313221e53438b1b90f6a7ae5 (diff)
downloadmongo-081ec07c4807774227a6bded19aa7b001666d281.tar.gz
Import wiredtiger: 65d96ccb972b239c8af5aa24a03d215eb143b0e4 from branch mongodb-3.4
ref: e99ab771b2..65d96ccb97 for: 3.4.16 WT-3557 Make test/format ignore unknown keywords WT-3710 Fix a race condition between concurrent page splits WT-3994 Enhance WiredTiger Jenkins pull request tester for old branches WT-4032 parent pages can be evicted while being split. WT-4037 WT_REF structures freed while still in use WT-4045 Don't retry fsync calls after EIO failure
-rw-r--r--src/third_party/wiredtiger/build_posix/aclocal/strict.m423
-rw-r--r--src/third_party/wiredtiger/dist/s_string.ok3
-rw-r--r--src/third_party/wiredtiger/import.data2
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_split.c166
-rw-r--r--src/third_party/wiredtiger/src/os_posix/os_fs.c78
-rw-r--r--src/third_party/wiredtiger/test/format/config.c55
6 files changed, 233 insertions, 94 deletions
diff --git a/src/third_party/wiredtiger/build_posix/aclocal/strict.m4 b/src/third_party/wiredtiger/build_posix/aclocal/strict.m4
index 659867fa69e..b671c45e26e 100644
--- a/src/third_party/wiredtiger/build_posix/aclocal/strict.m4
+++ b/src/third_party/wiredtiger/build_posix/aclocal/strict.m4
@@ -45,6 +45,26 @@ AC_DEFUN([AM_GCC_WARNINGS], [
[*6.[0-9].[0-9]*]) # gcc6.X
w="$w -Wduplicated-cond"
w="$w -Wmisleading-indentation";;
+ [*7.[0-9].[0-9]*]) # gcc7.X
+ w="$w -Walloca"
+ w="$w -Walloc-zero"
+ w="$w -Wduplicated-branches"
+ w="$w -Wduplicated-cond"
+ w="$w -Wformat-overflow=2"
+ w="$w -Wformat-signedness"
+ w="$w -Wformat-truncation=2"
+ w="$w -Wno-error=format-truncation"
+ w="$w -Wno-error=format"
+ w="$w -Wno-error=implicit-fallthrough"
+ w="$w -Wno-error=maybe-uninitialized"
+ w="$w -Wno-error=unsafe-loop-optimizations"
+ w="$w -Wjump-misses-init"
+ w="$w -Wlogical-op"
+ w="$w -Wredundant-decls"
+ w="$w -Wrestrict"
+ w="$w -Wunused-const-variable=2"
+ w="$w -Wunused-macros"
+ w="$w -Wvariadic-macros";;
esac
wt_cv_strict_warnings="$w"
@@ -67,6 +87,9 @@ AC_DEFUN([AM_CLANG_WARNINGS], [
# w="$w -Wno-error=cast-qual"
w="$w -Wno-cast-qual"
+ # Turn off clang unreachable-code error
+ w="$w -Wno-error=unreachable-code"
+
# On Centos 7.3.1611, system header files aren't compatible with
# -Wdisabled-macro-expansion.
w="$w -Wno-disabled-macro-expansion"
diff --git a/src/third_party/wiredtiger/dist/s_string.ok b/src/third_party/wiredtiger/dist/s_string.ok
index fad8c2f021a..0bfebbf8458 100644
--- a/src/third_party/wiredtiger/dist/s_string.ok
+++ b/src/third_party/wiredtiger/dist/s_string.ok
@@ -143,6 +143,7 @@ Fprintf
FreeBSD
FreeBSD's
FreeLibrary
+Fsync
Fuerst
GCC
GIDs
@@ -207,6 +208,7 @@ LSM
LSN
LSNs
LTE
+LWN
LZ
LZO
LeafGreen
@@ -285,6 +287,7 @@ Pandis
Phong
PlatformSDK
Posix
+PostgreSQL
PowerPC
Pre
Preload
diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data
index 04b716ec1c7..d7df48cee9a 100644
--- a/src/third_party/wiredtiger/import.data
+++ b/src/third_party/wiredtiger/import.data
@@ -1,5 +1,5 @@
{
- "commit": "e99ab771b2aa837199b72c2028569e7f5d3a7815",
+ "commit": "65d96ccb972b239c8af5aa24a03d215eb143b0e4",
"github": "wiredtiger/wiredtiger.git",
"vendor": "wiredtiger",
"branch": "mongodb-3.4"
diff --git a/src/third_party/wiredtiger/src/btree/bt_split.c b/src/third_party/wiredtiger/src/btree/bt_split.c
index 92be2125b88..355bc09871b 100644
--- a/src/third_party/wiredtiger/src/btree/bt_split.c
+++ b/src/third_party/wiredtiger/src/btree/bt_split.c
@@ -440,17 +440,49 @@ __split_ref_move(WT_SESSION_IMPL *session, WT_PAGE *from_home,
}
/*
+ * __split_ref_final --
+ * Finalize the WT_REF move.
+ */
+static void
+__split_ref_final(WT_SESSION_IMPL *session, WT_PAGE ***lockedp)
+{
+ WT_PAGE **locked;
+ size_t i;
+
+ /* The parent page's page index has been updated. */
+ WT_WRITE_BARRIER();
+
+ if ((locked = *lockedp) == NULL)
+ return;
+ *lockedp = NULL;
+
+ /*
+ * The moved child pages are locked to prevent them from splitting
+ * before the parent move completes, unlock them as the final step.
+ */
+ for (i = 0; locked[i] != NULL; ++i)
+ WT_PAGE_UNLOCK(session, locked[i]);
+ __wt_free(session, locked);
+}
+
+/*
* __split_ref_prepare --
* Prepare a set of WT_REFs for a move.
*/
-static void
+static int
__split_ref_prepare(WT_SESSION_IMPL *session,
- WT_PAGE_INDEX *pindex, uint64_t split_gen, bool skip_first)
+ WT_PAGE_INDEX *pindex, WT_PAGE ***lockedp, bool skip_first)
{
- WT_PAGE *child;
+ WT_DECL_RET;
+ WT_PAGE *child, **locked;
WT_REF *child_ref, *ref;
+ size_t alloc, cnt;
uint32_t i, j;
+ *lockedp = NULL;
+
+ locked = NULL;
+
/* The newly created subtree is complete. */
WT_WRITE_BARRIER();
@@ -462,51 +494,44 @@ __split_ref_prepare(WT_SESSION_IMPL *session,
* ascend into the created children, but eventually fail as that parent
* page won't yet know about the created children pages. That's OK, we
* spin there until the parent's page index is updated.
- */
+ *
+ * Lock the newly created page to ensure none of its children can split.
+ * First, to ensure all of the child pages are updated before any pages
+ * can split. Second, to ensure the original split completes before any
+ * of the children can split. The latter involves split generations:
+ * the original split page has references to these children. If they
+ * split immediately, they could free WT_REF structures based on split
+ * generations earlier than the split generation we'll eventually choose
+ * to protect the original split page's previous page index.
+ */
+ alloc = cnt = 0;
for (i = skip_first ? 1 : 0; i < pindex->entries; ++i) {
ref = pindex->index[i];
child = ref->page;
- /*
- * Block eviction in newly created pages.
- *
- * Once the split is live, newly created internal pages might be
- * evicted and their WT_REF structures freed. If that happened
- * before all threads exit the index of the page that previously
- * "owned" the WT_REF, a thread might see a freed WT_REF. To
- * ensure that doesn't happen, the newly created page contains
- * the current split generation and can't be evicted until
- * all readers have left the old generation.
- *
- * Historic, we also blocked splits in newly created pages
- * because we didn't update the WT_REF.home field until after
- * the split was live, so the WT_REF.home fields being updated
- * could split again before the update, there's a race between
- * splits as to which would update them first. The current code
- * updates the WT_REF.home fields before going live (in this
- * function), this isn't an issue.
- */
- child->pg_intl_split_gen = split_gen;
+ WT_PAGE_LOCK(session, child);
- /*
- * We use a page flag to prevent the child from splitting from
- * underneath us, but the split-generation error checks don't
- * know about that flag; use the standard macros to ensure that
- * reading the child's page index structure is safe.
- */
+ /* Track the locked pages for cleanup. */
+ WT_ERR(__wt_realloc_def(session, &alloc, cnt + 2, &locked));
+ locked[cnt++] = child;
+
+ /* Switch the WT_REF's to their new page. */
j = 0;
- WT_ENTER_PAGE_INDEX(session);
WT_INTL_FOREACH_BEGIN(session, child, child_ref) {
child_ref->home = child;
child_ref->pindex_hint = j++;
} WT_INTL_FOREACH_END;
- WT_LEAVE_PAGE_INDEX(session);
#ifdef HAVE_DIAGNOSTIC
WT_WITH_PAGE_INDEX(session,
__split_verify_intl_key_order(session, child));
#endif
}
+ *lockedp = locked;
+ return (0);
+
+err: __split_ref_final(session, &locked);
+ return (ret);
}
/*
@@ -518,10 +543,9 @@ __split_root(WT_SESSION_IMPL *session, WT_PAGE *root)
{
WT_BTREE *btree;
WT_DECL_RET;
- WT_PAGE *child;
+ WT_PAGE *child, **locked;
WT_PAGE_INDEX *alloc_index, *child_pindex, *pindex;
- WT_REF **alloc_refp;
- WT_REF **child_refp, *ref, **root_refp;
+ WT_REF **alloc_refp, **child_refp, *ref, **root_refp;
WT_SPLIT_ERROR_PHASE complete;
size_t child_incr, root_decr, root_incr, size;
uint64_t split_gen;
@@ -536,11 +560,13 @@ __split_root(WT_SESSION_IMPL *session, WT_PAGE *root)
btree = S2BT(session);
alloc_index = NULL;
+ locked = NULL;
root_decr = root_incr = 0;
complete = WT_ERR_RETURN;
- /* The root page will be marked dirty, make sure that will succeed. */
+ /* Mark the root page dirty. */
WT_RET(__wt_page_modify_init(session, root));
+ __wt_page_modify_set(session, root);
/*
* Our caller is holding the root page locked to single-thread splits,
@@ -583,6 +609,17 @@ __split_root(WT_SESSION_IMPL *session, WT_PAGE *root)
WT_ERR(__wt_calloc_one(session, alloc_refp));
root_incr += children * sizeof(WT_REF);
+ /*
+ * Once the split is live, newly created internal pages might be evicted
+ * and their WT_REF structures freed. If that happens before all threads
+ * exit the index of the page that previously "owned" the WT_REF, a
+ * thread might see a freed WT_REF. To ensure that doesn't happen, the
+ * created pages are set to the current split generation and so can't be
+ * evicted until all readers have left the old generation.
+ */
+ split_gen = __wt_atomic_addv64(&S2C(session)->split_gen, 1);
+ WT_ASSERT(session, root->pg_intl_split_gen < split_gen);
+
/* Allocate child pages, and connect them into the new page index. */
for (root_refp = pindex->index,
alloc_refp = alloc_index->index, i = 0; i < children; ++i) {
@@ -609,6 +646,7 @@ __split_root(WT_SESSION_IMPL *session, WT_PAGE *root)
/* Initialize the child page. */
child->pg_intl_parent_ref = ref;
+ child->pg_intl_split_gen = split_gen;
/* Mark it dirty. */
WT_ERR(__wt_page_modify_init(session, child));
@@ -640,12 +678,9 @@ __split_root(WT_SESSION_IMPL *session, WT_PAGE *root)
/* Start making real changes to the tree, errors are fatal. */
complete = WT_ERR_PANIC;
- /*
- * Prepare the WT_REFs for the move: this requires a stable split
- * generation to block splits in newly created pages, so get one.
- */
+ /* Prepare the WT_REFs for the move. */
WT_ENTER_PAGE_INDEX(session);
- __split_ref_prepare(session, alloc_index, session->split_gen, false);
+ WT_ERR(__split_ref_prepare(session, alloc_index, &locked, false));
/*
* Confirm the root page's index hasn't moved, then update it, which
@@ -665,6 +700,9 @@ __split_root(WT_SESSION_IMPL *session, WT_PAGE *root)
split_gen = __wt_atomic_addv64(&S2C(session)->split_gen, 1);
root->pg_intl_split_gen = split_gen;
+ /* Finalize the WT_REF move. */
+ __split_ref_final(session, &locked);
+
#ifdef HAVE_DIAGNOSTIC
WT_WITH_PAGE_INDEX(session,
ret = __split_verify_root(session, root));
@@ -688,12 +726,13 @@ __split_root(WT_SESSION_IMPL *session, WT_PAGE *root)
WT_TRET(__split_safe_free(session, split_gen, false, pindex, size));
root_decr += size;
- /* Adjust the root's memory footprint and mark it dirty. */
+ /* Adjust the root's memory footprint. */
__wt_cache_page_inmem_incr(session, root, root_incr);
__wt_cache_page_inmem_decr(session, root, root_decr);
- __wt_page_modify_set(session, root);
-err: switch (complete) {
+err: __split_ref_final(session, &locked);
+
+ switch (complete) {
case WT_ERR_RETURN:
__wt_free_ref_index(session, root, alloc_index, true);
break;
@@ -743,8 +782,9 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new,
empty_parent = false;
complete = WT_ERR_RETURN;
- /* The parent page will be marked dirty, make sure that will succeed. */
+ /* Mark the page dirty. */
WT_RET(__wt_page_modify_init(session, parent));
+ __wt_page_modify_set(session, parent);
/*
* We've locked the parent, which means it cannot split (which is the
@@ -972,10 +1012,9 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new,
WT_TRET(__split_safe_free(session, split_gen, exclusive, pindex, size));
parent_decr += size;
- /* Adjust the parent's memory footprint and mark it dirty. */
+ /* Adjust the parent's memory footprint. */
__wt_cache_page_inmem_incr(session, parent, parent_incr);
__wt_cache_page_inmem_decr(session, parent, parent_decr);
- __wt_page_modify_set(session, parent);
err: __wt_scr_free(session, &scr);
/*
@@ -1025,10 +1064,9 @@ __split_internal(WT_SESSION_IMPL *session, WT_PAGE *parent, WT_PAGE *page)
{
WT_BTREE *btree;
WT_DECL_RET;
- WT_PAGE *child;
+ WT_PAGE *child, **locked;
WT_PAGE_INDEX *alloc_index, *child_pindex, *pindex, *replace_index;
- WT_REF **alloc_refp;
- WT_REF **child_refp, *page_ref, **page_refp, *ref;
+ WT_REF **alloc_refp, **child_refp, *page_ref, **page_refp, *ref;
WT_SPLIT_ERROR_PHASE complete;
size_t child_incr, page_decr, page_incr, parent_incr, size;
uint64_t split_gen;
@@ -1039,12 +1077,14 @@ __split_internal(WT_SESSION_IMPL *session, WT_PAGE *parent, WT_PAGE *page)
WT_STAT_CONN_INCR(session, cache_eviction_split_internal);
WT_STAT_DATA_INCR(session, cache_eviction_split_internal);
- /* The page will be marked dirty, make sure that will succeed. */
+ /* Mark the page dirty. */
WT_RET(__wt_page_modify_init(session, page));
+ __wt_page_modify_set(session, page);
btree = S2BT(session);
alloc_index = replace_index = NULL;
page_ref = page->pg_intl_parent_ref;
+ locked = NULL;
page_decr = page_incr = parent_incr = 0;
complete = WT_ERR_RETURN;
@@ -1111,6 +1151,17 @@ __split_internal(WT_SESSION_IMPL *session, WT_PAGE *parent, WT_PAGE *page)
WT_ERR(__wt_calloc_one(session, alloc_refp));
parent_incr += children * sizeof(WT_REF);
+ /*
+ * Once the split is live, newly created internal pages might be evicted
+ * and their WT_REF structures freed. If that happens before all threads
+ * exit the index of the page that previously "owned" the WT_REF, a
+ * thread might see a freed WT_REF. To ensure that doesn't happen, the
+ * created pages are set to the current split generation and so can't be
+ * evicted until all readers have left the old generation.
+ */
+ split_gen = __wt_atomic_addv64(&S2C(session)->split_gen, 1);
+ WT_ASSERT(session, page->pg_intl_split_gen < split_gen);
+
/* Allocate child pages, and connect them into the new page index. */
WT_ASSERT(session, page_refp == pindex->index + chunk);
for (alloc_refp = alloc_index->index + 1, i = 1; i < children; ++i) {
@@ -1137,6 +1188,7 @@ __split_internal(WT_SESSION_IMPL *session, WT_PAGE *parent, WT_PAGE *page)
/* Initialize the child page. */
child->pg_intl_parent_ref = ref;
+ child->pg_intl_split_gen = split_gen;
/* Mark it dirty. */
WT_ERR(__wt_page_modify_init(session, child));
@@ -1173,7 +1225,7 @@ __split_internal(WT_SESSION_IMPL *session, WT_PAGE *parent, WT_PAGE *page)
* generation to block splits in newly created pages, so get one.
*/
WT_ENTER_PAGE_INDEX(session);
- __split_ref_prepare(session, alloc_index, session->split_gen, true);
+ WT_ERR(__split_ref_prepare(session, alloc_index, &locked, true));
/* Split into the parent. */
if ((ret = __split_parent(session, page_ref, alloc_index->index,
@@ -1197,6 +1249,9 @@ __split_internal(WT_SESSION_IMPL *session, WT_PAGE *parent, WT_PAGE *page)
split_gen = __wt_atomic_addv64(&S2C(session)->split_gen, 1);
page->pg_intl_split_gen = split_gen;
+ /* Finalize the WT_REF move. */
+ __split_ref_final(session, &locked);
+
#ifdef HAVE_DIAGNOSTIC
WT_WITH_PAGE_INDEX(session,
__split_verify_intl_key_order(session, parent));
@@ -1228,12 +1283,13 @@ __split_internal(WT_SESSION_IMPL *session, WT_PAGE *parent, WT_PAGE *page)
WT_TRET(__split_safe_free(session, split_gen, false, pindex, size));
page_decr += size;
- /* Adjust the page's memory footprint, and mark it dirty. */
+ /* Adjust the page's memory footprint. */
__wt_cache_page_inmem_incr(session, page, page_incr);
__wt_cache_page_inmem_decr(session, page, page_decr);
- __wt_page_modify_set(session, page);
-err: switch (complete) {
+err: __split_ref_final(session, &locked);
+
+ switch (complete) {
case WT_ERR_RETURN:
__wt_free_ref_index(session, page, alloc_index, true);
__wt_free_ref_index(session, page, replace_index, false);
diff --git a/src/third_party/wiredtiger/src/os_posix/os_fs.c b/src/third_party/wiredtiger/src/os_posix/os_fs.c
index bc8cbf67025..3c90183caf2 100644
--- a/src/third_party/wiredtiger/src/os_posix/os_fs.c
+++ b/src/third_party/wiredtiger/src/os_posix/os_fs.c
@@ -31,6 +31,23 @@
/*
* __posix_sync --
* Underlying support function to flush a file descriptor.
+ *
+ * Fsync calls (or fsync-style calls, for example, fdatasync) are not retried
+ * on failure, and failure halts the system.
+ *
+ * Excerpted from the LWN.net article https://lwn.net/Articles/752063/:
+ * In short, PostgreSQL assumes that a successful call to fsync() indicates
+ * that all data written since the last successful call made it safely to
+ * persistent storage. But that is not what the kernel actually does. When
+ * a buffered I/O write fails due to a hardware-level error, filesystems
+ * will respond differently, but that behavior usually includes discarding
+ * the data in the affected pages and marking them as being clean. So a read
+ * of the blocks that were just written will likely return something other
+ * than the data that was written.
+ *
+ * Given the shared history of UNIX filesystems, and the difficulty of knowing
+ * what specific error will be returned under specific circumstances, we don't
+ * retry fsync-style calls and panic if a flush operation fails.
*/
static int
__posix_sync(
@@ -52,25 +69,49 @@ __posix_sync(
* OS X F_FULLFSYNC fcntl documentation:
* "This is currently implemented on HFS, MS-DOS (FAT), and Universal
* Disk Format (UDF) file systems."
+ *
+ * See comment in __posix_sync(): sync cannot be retried or fail.
*/
- WT_SYSCALL_RETRY(fcntl(fd, F_FULLFSYNC, 0) == -1 ? -1 : 0, ret);
- if (ret == 0)
- return (0);
- /*
- * Assume F_FULLFSYNC failed because the file system doesn't support it
- * and fallback to fsync.
- */
+ static enum { FF_NOTSET, FF_IGNORE, FF_OK } ff_status = FF_NOTSET;
+ switch (ff_status) {
+ case FF_NOTSET:
+ WT_SYSCALL(fcntl(fd, F_FULLFSYNC, 0) == -1 ? -1 : 0, ret);
+ if (ret == 0) {
+ ff_status = FF_OK;
+ return (0);
+ }
+
+ /*
+ * If the first F_FULLFSYNC fails, assume the file system
+ * doesn't support it and fallback to fdatasync or fsync.
+ */
+ ff_status = FF_IGNORE;
+ __wt_err(session, ret,
+ "fcntl(F_FULLFSYNC) failed, falling back to fdatasync "
+ "or fsync");
+ break;
+ case FF_IGNORE:
+ break;
+ case FF_OK:
+ WT_SYSCALL(fcntl(fd, F_FULLFSYNC, 0) == -1 ? -1 : 0, ret);
+ if (ret == 0)
+ return (0);
+ WT_PANIC_RET(session,
+ ret, "%s: %s: fcntl(F_FULLFSYNC)", name, func);
+ }
#endif
#if defined(HAVE_FDATASYNC)
- WT_SYSCALL_RETRY(fdatasync(fd), ret);
+ /* See comment in __posix_sync(): sync cannot be retried or fail. */
+ WT_SYSCALL(fdatasync(fd), ret);
if (ret == 0)
return (0);
- WT_RET_MSG(session, ret, "%s: %s: fdatasync", name, func);
+ WT_PANIC_RET(session, ret, "%s: %s: fdatasync", name, func);
#else
- WT_SYSCALL_RETRY(fsync(fd), ret);
+ /* See comment in __posix_sync(): sync cannot be retried or fail. */
+ WT_SYSCALL(fsync(fd), ret);
if (ret == 0)
return (0);
- WT_RET_MSG(session, ret, "%s: %s: fsync", name, func);
+ WT_PANIC_RET(session, ret, "%s: %s: fsync", name, func);
#endif
}
@@ -108,12 +149,15 @@ __posix_directory_sync(WT_SESSION_IMPL *session, const char *path)
WT_SYSCALL(close(fd), tret);
if (tret != 0) {
__wt_err(session, tret, "%s: directory-sync: close", dir);
- if (ret == 0)
- ret = tret;
+ WT_TRET(tret);
}
err: __wt_scr_free(session, &tmp);
- return (ret);
+ if (ret == 0)
+ return (ret);
+
+ /* See comment in __posix_sync(): sync cannot be retried or fail. */
+ WT_PANIC_RET(session, ret, "%s: directory-sync", path);
}
#endif
@@ -460,11 +504,13 @@ __posix_file_sync_nowait(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session)
session = (WT_SESSION_IMPL *)wt_session;
pfh = (WT_FILE_HANDLE_POSIX *)file_handle;
- WT_SYSCALL_RETRY(sync_file_range(pfh->fd,
+ /* See comment in __posix_sync(): sync cannot be retried or fail. */
+ WT_SYSCALL(sync_file_range(pfh->fd,
(off64_t)0, (off64_t)0, SYNC_FILE_RANGE_WRITE), ret);
if (ret == 0)
return (0);
- WT_RET_MSG(session, ret,
+
+ WT_PANIC_RET(session, ret,
"%s: handle-sync-nowait: sync_file_range", file_handle->name);
}
#endif
diff --git a/src/third_party/wiredtiger/test/format/config.c b/src/third_party/wiredtiger/test/format/config.c
index 22b40f7164d..146861e2adc 100644
--- a/src/third_party/wiredtiger/test/format/config.c
+++ b/src/third_party/wiredtiger/test/format/config.c
@@ -33,7 +33,6 @@ static void config_checksum(void);
static void config_compression(const char *);
static void config_encryption(void);
static const char *config_file_type(u_int);
-static CONFIG *config_find(const char *, size_t);
static void config_in_memory(void);
static void config_in_memory_check(void);
static int config_is_perm(const char *);
@@ -672,6 +671,35 @@ config_reset(void)
}
/*
+ * config_find
+ * Find a specific configuration entry.
+ */
+static CONFIG *
+config_find(const char *s, size_t len, bool fatal)
+{
+ CONFIG *cp;
+
+ for (cp = c; cp->name != NULL; ++cp)
+ if (strncmp(s, cp->name, len) == 0 && cp->name[len] == '\0')
+ return (cp);
+
+ /*
+ * Optionally ignore unknown keywords, it makes it easier to run old
+ * CONFIG files.
+ */
+ if (fatal) {
+ fprintf(stderr,
+ "%s: %s: unknown required configuration keyword\n",
+ progname, s);
+ exit(EXIT_FAILURE);
+ }
+ fprintf(stderr,
+ "%s: %s: WARNING, ignoring unknown configuration keyword\n",
+ progname, s);
+ return (NULL);
+}
+
+/*
* config_single --
* Set a single configuration structure value.
*/
@@ -690,7 +718,9 @@ config_single(const char *s, int perm)
exit(EXIT_FAILURE);
}
- cp = config_find(s, (size_t)(ep - s));
+ if ((cp = config_find(s, (size_t)(ep - s), false)) == NULL)
+ return;
+
F_SET(cp, perm ? C_PERM : C_TEMP);
++ep;
@@ -876,25 +906,6 @@ config_map_isolation(const char *s, u_int *vp)
}
/*
- * config_find
- * Find a specific configuration entry.
- */
-static CONFIG *
-config_find(const char *s, size_t len)
-{
- CONFIG *cp;
-
- for (cp = c; cp->name != NULL; ++cp)
- if (strncmp(s, cp->name, len) == 0 && cp->name[len] == '\0')
- return (cp);
-
- fprintf(stderr,
- "%s: %s: unknown configuration keyword\n", progname, s);
- config_error();
- exit(EXIT_FAILURE);
-}
-
-/*
* config_is_perm
* Return if a specific configuration entry was permanently set.
*/
@@ -903,7 +914,7 @@ config_is_perm(const char *s)
{
CONFIG *cp;
- cp = config_find(s, strlen(s));
+ cp = config_find(s, strlen(s), true);
return (F_ISSET(cp, C_PERM) ? 1 : 0);
}