summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Chen <luke.chen@mongodb.com>2018-04-12 10:58:59 +1000
committerLuke Chen <luke.chen@mongodb.com>2018-04-12 10:58:59 +1000
commit1e619e899f17520ddb04f3848b1bdd8b99f97787 (patch)
tree9c52101414de390988242d3888ff7a4e5cbcb3e7
parentd9bc77ee5021049248505dac91059ef20e4997c3 (diff)
downloadmongo-1e619e899f17520ddb04f3848b1bdd8b99f97787.tar.gz
Import wiredtiger: 4babae8093f7a3cb05226abe959e10e0bb6b2716 from branch mongodb-3.2
ref: 46c2f8fd9b..4babae8093 for: 3.2.20 WT-3994 Enhance WiredTiger Jenkins pull request tester for old branches
-rw-r--r--src/third_party/wiredtiger/build_posix/aclocal/strict.m423
-rw-r--r--src/third_party/wiredtiger/dist/s_string.ok1
-rw-r--r--src/third_party/wiredtiger/import.data2
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_cursor.c4
-rw-r--r--src/third_party/wiredtiger/src/btree/bt_handle.c35
-rw-r--r--src/third_party/wiredtiger/src/conn/conn_api.c35
-rw-r--r--src/third_party/wiredtiger/src/conn/conn_dhandle.c17
-rw-r--r--src/third_party/wiredtiger/src/conn/conn_open.c2
-rw-r--r--src/third_party/wiredtiger/src/evict/evict_lru.c30
-rw-r--r--src/third_party/wiredtiger/src/include/btree.h25
-rw-r--r--src/third_party/wiredtiger/src/session/session_dhandle.c4
-rw-r--r--src/third_party/wiredtiger/src/support/err.c13
-rw-r--r--src/third_party/wiredtiger/test/mciproject.yml14
-rw-r--r--src/third_party/wiredtiger/test/suite/test_bug018.py98
14 files changed, 250 insertions, 53 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 f3852d00ac8..99abc3e9ad1 100644
--- a/src/third_party/wiredtiger/dist/s_string.ok
+++ b/src/third_party/wiredtiger/dist/s_string.ok
@@ -1060,6 +1060,7 @@ rebalancing
recno
recnos
reconfig
+reconfigures
reconfiguring
recsize
rectype
diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data
index 8255b539a98..b613d8d45e1 100644
--- a/src/third_party/wiredtiger/import.data
+++ b/src/third_party/wiredtiger/import.data
@@ -1,5 +1,5 @@
{
- "commit": "46c2f8fd9b678f4e876bd4fbc888d0040b628045",
+ "commit": "4babae8093f7a3cb05226abe959e10e0bb6b2716",
"github": "wiredtiger/wiredtiger.git",
"vendor": "wiredtiger",
"branch": "mongodb-3.2"
diff --git a/src/third_party/wiredtiger/src/btree/bt_cursor.c b/src/third_party/wiredtiger/src/btree/bt_cursor.c
index f0aa632551b..95d817850ef 100644
--- a/src/third_party/wiredtiger/src/btree/bt_cursor.c
+++ b/src/third_party/wiredtiger/src/btree/bt_cursor.c
@@ -156,8 +156,10 @@ __cursor_disable_bulk(WT_SESSION_IMPL *session, WT_BTREE *btree)
* into a tree. Eviction is disabled when an empty tree is opened, and
* it must only be enabled once.
*/
- if (__wt_atomic_cas8(&btree->original, 1, 0))
+ if (__wt_atomic_cas8(&btree->original, 1, 0)) {
+ btree->evict_disabled_open = false;
__wt_evict_file_exclusive_off(session);
+ }
}
/*
diff --git a/src/third_party/wiredtiger/src/btree/bt_handle.c b/src/third_party/wiredtiger/src/btree/bt_handle.c
index a0da7df0998..1e6405272f7 100644
--- a/src/third_party/wiredtiger/src/btree/bt_handle.c
+++ b/src/third_party/wiredtiger/src/btree/bt_handle.c
@@ -66,7 +66,6 @@ __wt_btree_open(WT_SESSION_IMPL *session, const char *op_cfg[])
WT_DATA_HANDLE *dhandle;
WT_DECL_RET;
size_t root_addr_size;
- uint32_t mask;
uint8_t root_addr[WT_BTREE_MAX_ADDR_COOKIE];
const char *filename;
bool creation, forced_salvage, readonly;
@@ -75,15 +74,14 @@ __wt_btree_open(WT_SESSION_IMPL *session, const char *op_cfg[])
dhandle = session->dhandle;
/*
- * This may be a re-open of an underlying object and we have to clean
- * up. We can't clear the operation flags, however, they're set by the
- * connection handle software that called us.
+ * This may be a re-open, clean up the btree structure.
+ * Clear the fields that don't persist across a re-open.
+ * Clear all flags other than the operation flags (which are set by the
+ * connection handle software that called us).
*/
WT_RET(__btree_clear(session));
-
- mask = F_MASK(btree, WT_BTREE_SPECIAL_FLAGS);
- memset(btree, 0, sizeof(*btree));
- btree->flags = mask;
+ memset(btree, 0, WT_BTREE_CLEAR_SIZE);
+ F_CLR(btree, ~WT_BTREE_SPECIAL_FLAGS);
/* Set the data handle first, our called functions reasonably use it. */
btree->dhandle = dhandle;
@@ -185,13 +183,19 @@ __wt_btree_open(WT_SESSION_IMPL *session, const char *op_cfg[])
*
* Files that can still be bulk-loaded cannot be evicted.
* Permanently cache-resident files can never be evicted.
- * Special operations don't enable eviction. (The underlying commands
- * may turn on eviction, but it's their decision.)
+ * Special operations don't enable eviction. The underlying commands may
+ * turn on eviction (for example, verify turns on eviction while working
+ * a file to keep from consuming the cache), but it's their decision. If
+ * an underlying command reconfigures eviction, it must either clear the
+ * evict-disabled-open flag or restore the eviction configuration when
+ * finished so that handle close behaves correctly.
*/
if (btree->original ||
F_ISSET(btree, WT_BTREE_IN_MEMORY | WT_BTREE_REBALANCE |
- WT_BTREE_SALVAGE | WT_BTREE_UPGRADE | WT_BTREE_VERIFY))
+ WT_BTREE_SALVAGE | WT_BTREE_UPGRADE | WT_BTREE_VERIFY)) {
WT_ERR(__wt_evict_file_exclusive_on(session));
+ btree->evict_disabled_open = true;
+ }
if (0) {
err: WT_TRET(__wt_btree_close(session));
@@ -228,6 +232,15 @@ __wt_btree_close(WT_SESSION_IMPL *session)
return (0);
F_SET(btree, WT_BTREE_CLOSED);
+ /*
+ * If we turned eviction off and never turned it back on, do that now,
+ * otherwise the counter will be off.
+ */
+ if (btree->evict_disabled_open) {
+ btree->evict_disabled_open = false;
+ __wt_evict_file_exclusive_off(session);
+ }
+
/* Discard any underlying block manager resources. */
if ((bm = btree->bm) != NULL) {
btree->bm = NULL;
diff --git a/src/third_party/wiredtiger/src/conn/conn_api.c b/src/third_party/wiredtiger/src/conn/conn_api.c
index 68d45678965..00d559881dc 100644
--- a/src/third_party/wiredtiger/src/conn/conn_api.c
+++ b/src/third_party/wiredtiger/src/conn/conn_api.c
@@ -1086,6 +1086,41 @@ err: /*
WT_TRET(wt_session->close(wt_session, config));
}
+ /*
+ * Perform a system-wide checkpoint so that all tables are consistent
+ * with each other. Do this before shutting down all the subsystems.
+ * We have shut down all user sessions, but send in true for waiting
+ * for internal races.
+ */
+ if (!F_ISSET(conn, WT_CONN_IN_MEMORY | WT_CONN_READONLY)) {
+ s = NULL;
+ WT_TRET(__wt_open_internal_session(
+ conn, "close_ckpt", true, 0, &s));
+ if (s != NULL) {
+ const char *checkpoint_cfg[] = {
+ WT_CONFIG_BASE(session, WT_SESSION_checkpoint),
+ NULL
+ };
+ wt_session = &s->iface;
+ WT_TRET(__wt_txn_checkpoint(s, checkpoint_cfg, true));
+
+ /*
+ * Mark the metadata dirty so we flush it on close,
+ * allowing recovery to be skipped.
+ */
+ WT_WITH_DHANDLE(s, WT_SESSION_META_DHANDLE(s),
+ __wt_tree_modify_set(s));
+
+ WT_TRET(wt_session->close(wt_session, config));
+ }
+ }
+
+ if (ret != 0) {
+ __wt_err(session, ret,
+ "failure during close, disabling further writes");
+ F_SET(conn, WT_CONN_PANIC);
+ }
+
WT_TRET(__wt_connection_close(conn));
/* We no longer have a session, don't try to update it. */
diff --git a/src/third_party/wiredtiger/src/conn/conn_dhandle.c b/src/third_party/wiredtiger/src/conn/conn_dhandle.c
index 1816e66b0b7..a08a71c8c94 100644
--- a/src/third_party/wiredtiger/src/conn/conn_dhandle.c
+++ b/src/third_party/wiredtiger/src/conn/conn_dhandle.c
@@ -317,6 +317,9 @@ __wt_conn_btree_open(
WT_ASSERT(session,
!F_ISSET(S2C(session), WT_CONN_CLOSING_NO_MORE_OPENS));
+ /* Turn off eviction. */
+ WT_RET(__wt_evict_file_exclusive_on(session));
+
/*
* If the handle is already open, it has to be closed so it can be
* reopened with a new configuration.
@@ -330,11 +333,11 @@ __wt_conn_btree_open(
* in the tree that can block the close.
*/
if (F_ISSET(dhandle, WT_DHANDLE_OPEN))
- WT_RET(__wt_conn_btree_sync_and_close(session, false, false));
+ WT_ERR(__wt_conn_btree_sync_and_close(session, false, false));
/* Discard any previous configuration, set up the new configuration. */
__conn_btree_config_clear(session);
- WT_RET(__conn_btree_config_set(session));
+ WT_ERR(__conn_btree_config_set(session));
/* Set any special flags on the handle. */
F_SET(btree, LF_MASK(WT_BTREE_SPECIAL_FLAGS));
@@ -374,6 +377,8 @@ __wt_conn_btree_open(
err: F_CLR(btree, WT_BTREE_SPECIAL_FLAGS);
}
+ __wt_evict_file_exclusive_off(session);
+
return (ret);
}
@@ -673,8 +678,8 @@ restart:
continue;
WT_WITH_DHANDLE(session, dhandle,
- WT_TRET(__wt_conn_dhandle_discard_single(
- session, true, F_ISSET(conn, WT_CONN_IN_MEMORY))));
+ WT_TRET(__wt_conn_dhandle_discard_single(session, true,
+ F_ISSET(conn, WT_CONN_IN_MEMORY | WT_CONN_PANIC))));
goto restart;
}
@@ -699,8 +704,8 @@ restart:
/* Close the metadata file handle. */
while ((dhandle = TAILQ_FIRST(&conn->dhqh)) != NULL)
WT_WITH_DHANDLE(session, dhandle,
- WT_TRET(__wt_conn_dhandle_discard_single(
- session, true, F_ISSET(conn, WT_CONN_IN_MEMORY))));
+ WT_TRET(__wt_conn_dhandle_discard_single(session, true,
+ F_ISSET(conn, WT_CONN_IN_MEMORY | WT_CONN_PANIC))));
return (ret);
}
diff --git a/src/third_party/wiredtiger/src/conn/conn_open.c b/src/third_party/wiredtiger/src/conn/conn_open.c
index eb3c79422a0..0020c2cb735 100644
--- a/src/third_party/wiredtiger/src/conn/conn_open.c
+++ b/src/third_party/wiredtiger/src/conn/conn_open.c
@@ -143,7 +143,7 @@ __wt_connection_close(WT_CONNECTION_IMPL *conn)
* conditional because we allocate the log path so that printlog can
* run without running logging or recovery.
*/
- if (FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED) &&
+ if (ret == 0 && FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED) &&
FLD_ISSET(conn->log_flags, WT_CONN_LOG_RECOVER_DONE))
WT_TRET(__wt_txn_checkpoint_log(
session, true, WT_TXN_LOG_CKPT_STOP, NULL));
diff --git a/src/third_party/wiredtiger/src/evict/evict_lru.c b/src/third_party/wiredtiger/src/evict/evict_lru.c
index cc3c5a5c824..e1e2f82a6d0 100644
--- a/src/third_party/wiredtiger/src/evict/evict_lru.c
+++ b/src/third_party/wiredtiger/src/evict/evict_lru.c
@@ -1452,26 +1452,23 @@ retry: while (slot < max_entries) {
/*
* Re-check the "no eviction" flag, used to enforce exclusive
- * access when a handle is being closed. If not set, remember
- * the file to visit first, next loop.
+ * access when a handle is being closed.
*
* Only try to acquire the lock and simply continue if we fail;
* the lock is held while the thread turning off eviction clears
* the tree's current eviction point, and part of the process is
* waiting on this thread to acknowledge that action.
+ *
+ * If a handle is being discarded, it will still be marked open,
+ * but won't have a root page.
*/
if (btree->evict_disabled == 0 &&
!__wt_spin_trylock(session, &cache->evict_walk_lock)) {
- if (btree->evict_disabled == 0) {
+ if (btree->evict_disabled == 0 &&
+ btree->root.page != NULL) {
/*
- * Assert the handle has a root page: eviction
- * should have been locked out if the tree is
- * being discarded or the root page is changing.
- * As this has not always been the case, assert
- * to debug that change.
+ * Remember the file to visit first, next loop.
*/
- WT_ASSERT(session, btree->root.page != NULL);
-
cache->evict_file_next = dhandle;
WT_WITH_DHANDLE(session, dhandle,
ret = __evict_walk_file(
@@ -1870,6 +1867,10 @@ fast: /* If the page can't be evicted, give up. */
WT_STAT_CONN_INCRV(
session, cache_eviction_pages_queued, (u_int)(evict - start));
+ __wt_verbose(session, WT_VERB_EVICTSERVER,
+ "%s walk: seen %" PRIu64 ", queued %" PRIu64,
+ session->dhandle->name, pages_seen, pages_queued);
+
/*
* If we couldn't find the number of pages we were looking for, skip
* the tree next time.
@@ -2452,14 +2453,23 @@ __wt_verbose_dump_cache(WT_SESSION_IMPL *session)
WT_CONNECTION_IMPL *conn;
WT_DATA_HANDLE *dhandle;
WT_DECL_RET;
+ u_int pct;
uint64_t total_bytes, total_dirty_bytes;
conn = S2C(session);
total_bytes = total_dirty_bytes = 0;
+ pct = 0; /* [-Werror=uninitialized] */
WT_RET(__wt_msg(session, "%s", WT_DIVIDER));
WT_RET(__wt_msg(session, "cache dump"));
+ WT_RET(__wt_msg(session,
+ "cache full: %s", __wt_cache_full(session) ? "yes" : "no"));
+ WT_RET(__wt_msg(session, "cache clean check: %s (%u%%)",
+ __wt_eviction_clean_needed(session, &pct) ? "yes" : "no", pct));
+ WT_RET(__wt_msg(session, "cache dirty check: %s (%u%%)",
+ __wt_eviction_dirty_needed(session, &pct) ? "yes" : "no", pct));
+
for (dhandle = NULL;;) {
WT_WITH_HANDLE_LIST_READ_LOCK(session,
WT_DHANDLE_NEXT(session, dhandle, &conn->dhqh, q));
diff --git a/src/third_party/wiredtiger/src/include/btree.h b/src/third_party/wiredtiger/src/include/btree.h
index 28fe1b94b23..8712a404b13 100644
--- a/src/third_party/wiredtiger/src/include/btree.h
+++ b/src/third_party/wiredtiger/src/include/btree.h
@@ -142,12 +142,30 @@ struct __wt_btree {
uint64_t bytes_dirty_intl; /* Bytes in dirty internal pages. */
uint64_t bytes_dirty_leaf; /* Bytes in dirty leaf pages. */
+ /*
+ * We flush pages from the tree (in order to make checkpoint faster),
+ * without a high-level lock. To avoid multiple threads flushing at
+ * the same time, lock the tree.
+ */
+ WT_SPINLOCK flush_lock; /* Lock to flush the tree's pages */
+
+ /*
+ * All of the following fields live at the end of the structure so it's
+ * easier to clear everything but the fields that persist.
+ */
+#define WT_BTREE_CLEAR_SIZE (offsetof(WT_BTREE, evict_ref))
+
+ /*
+ * Eviction information is maintained in the btree handle, but owned by
+ * eviction, not the btree code.
+ */
WT_REF *evict_ref; /* Eviction thread's location */
uint64_t evict_priority; /* Relative priority of cached pages */
u_int evict_walk_period; /* Skip this many LRU walks */
u_int evict_walk_saved; /* Saved walk skips for checkpoints */
u_int evict_walk_skips; /* Number of walks skipped */
int evict_disabled; /* Eviction disabled count */
+ bool evict_disabled_open;/* Eviction disabled on open */
volatile uint32_t evict_busy; /* Count of threads in eviction */
int evict_start_type; /* Start position for eviction walk
(see WT_EVICT_WALK_START). */
@@ -155,13 +173,6 @@ struct __wt_btree {
WT_CKPT_OFF, WT_CKPT_PREPARE, WT_CKPT_RUNNING
} checkpointing; /* Checkpoint in progress */
- /*
- * We flush pages from the tree (in order to make checkpoint faster),
- * without a high-level lock. To avoid multiple threads flushing at
- * the same time, lock the tree.
- */
- WT_SPINLOCK flush_lock; /* Lock to flush the tree's pages */
-
/* Flags values up to 0xff are reserved for WT_DHANDLE_* */
#define WT_BTREE_ALLOW_SPLITS 0x000100 /* Allow splits, even with no evict */
#define WT_BTREE_BULK 0x000200 /* Bulk-load handle */
diff --git a/src/third_party/wiredtiger/src/session/session_dhandle.c b/src/third_party/wiredtiger/src/session/session_dhandle.c
index ffeb6137766..9fc769a1187 100644
--- a/src/third_party/wiredtiger/src/session/session_dhandle.c
+++ b/src/third_party/wiredtiger/src/session/session_dhandle.c
@@ -597,7 +597,9 @@ __wt_session_lock_checkpoint(WT_SESSION_IMPL *session, const char *checkpoint)
* the underlying file are visible to the in-memory pages.
*/
WT_ERR(__wt_evict_file_exclusive_on(session));
- WT_ERR(__wt_cache_op(session, WT_SYNC_DISCARD));
+ ret = __wt_cache_op(session, WT_SYNC_DISCARD);
+ __wt_evict_file_exclusive_off(session);
+ WT_ERR(ret);
/*
* We lock checkpoint handles that we are overwriting, so the handle
diff --git a/src/third_party/wiredtiger/src/support/err.c b/src/third_party/wiredtiger/src/support/err.c
index 57efde72b23..f98b1943449 100644
--- a/src/third_party/wiredtiger/src/support/err.c
+++ b/src/third_party/wiredtiger/src/support/err.c
@@ -494,7 +494,18 @@ __wt_panic(WT_SESSION_IMPL *session)
WT_GCC_FUNC_ATTRIBUTE((cold))
WT_GCC_FUNC_ATTRIBUTE((visibility("default")))
{
- F_SET(S2C(session), WT_CONN_PANIC);
+ WT_CONNECTION_IMPL *conn;
+
+ conn = S2C(session);
+
+ /*
+ * If the connection has already be marked for panic, just return the
+ * error.
+ */
+ if (F_ISSET(conn, WT_CONN_PANIC))
+ return (WT_PANIC);
+
+ F_SET(conn, WT_CONN_PANIC);
__wt_err(session, WT_PANIC, "the process must exit and restart");
#if defined(HAVE_DIAGNOSTIC)
diff --git a/src/third_party/wiredtiger/test/mciproject.yml b/src/third_party/wiredtiger/test/mciproject.yml
index 6456475aa00..50a910d9e58 100644
--- a/src/third_party/wiredtiger/test/mciproject.yml
+++ b/src/third_party/wiredtiger/test/mciproject.yml
@@ -157,20 +157,6 @@ buildvariants:
- name: unit-test
- name: fops
-- name: solaris
- display_name: Solaris
- run_on:
- - solaris
- expansions:
- make_command: PATH=/opt/mongodbtoolchain/bin:$PATH gmake
- test_env_vars: LD_LIBRARY_PATH=`pwd`/.libs
- smp_command: -j $(kstat cpu | sort -u | grep -c "^module")
- configure_env_vars: PATH=/opt/mongodbtoolchain/bin:$PATH CFLAGS="-m64"
- tasks:
- - name: compile
- - name: unit-test
- - name: fops
-
- name: windows-64
display_name: Windows 64-bit
run_on:
diff --git a/src/third_party/wiredtiger/test/suite/test_bug018.py b/src/third_party/wiredtiger/test/suite/test_bug018.py
index e69de29bb2d..7d20ebcaacb 100644
--- a/src/third_party/wiredtiger/test/suite/test_bug018.py
+++ b/src/third_party/wiredtiger/test/suite/test_bug018.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2017 MongoDB, Inc.
+# Public Domain 2008-2014 WiredTiger, Inc.
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+from helper import copy_wiredtiger_home
+import os
+import wiredtiger, wttest
+
+# test_bug018.py
+# JIRA WT-3590: if writing table data fails during close then tables
+# that were updated within the same transaction could get out of sync with
+# each other.
+class test_bug018(wttest.WiredTigerTestCase):
+ '''Test closing/reopening/recovering tables when writes fail'''
+
+ conn_config = 'log=(enabled)'
+
+ def setUp(self):
+ # This test uses Linux-specific code so skip on any other system.
+ if os.name != 'posix' or os.uname()[0] != 'Linux':
+ self.skipTest('Linux-specific test skipped on ' + os.name)
+ super(test_bug018, self).setUp()
+
+ def create_table(self, uri):
+ self.session.create(uri, 'key_format=S,value_format=S')
+ return self.session.open_cursor(uri)
+
+ def test_bug018(self):
+ '''Test closing multiple tables'''
+ basename = 'bug018.'
+ baseuri = 'file:' + basename
+ c1 = self.create_table(baseuri + '01.wt')
+ c2 = self.create_table(baseuri + '02.wt')
+
+ self.session.begin_transaction()
+ c1['key'] = 'value'
+ c2['key'] = 'value'
+ self.session.commit_transaction()
+
+ # Simulate a write failure by closing the file descriptor for the second
+ # table out from underneath WiredTiger. We do this right before
+ # closing the connection so that the write error happens during close
+ # when writing out the final data. Allow table 1 to succeed and force
+ # an erorr writing out table 2.
+ #
+ # This is Linux-specific code to figure out the file descriptor.
+ for f in os.listdir('/proc/self/fd'):
+ try:
+ if os.readlink('/proc/self/fd/' + f).endswith(basename + '02.wt'):
+ os.close(int(f))
+ except OSError:
+ pass
+
+ # Expect an error and messages, so turn off stderr checking.
+ with self.expectedStderrPattern(''):
+ try:
+ self.close_conn()
+ except wiredtiger.WiredTigerError:
+ self.conn = None
+
+ # Make a backup for forensics in case something goes wrong.
+ backup_dir = 'BACKUP'
+ copy_wiredtiger_home('.', backup_dir, True)
+
+ # After reopening and running recovery both tables should be in
+ # sync even though table 1 was successfully written and table 2
+ # had an error on close.
+ self.open_conn()
+ c1 = self.session.open_cursor(baseuri + '01.wt')
+ c2 = self.session.open_cursor(baseuri + '02.wt')
+ self.assertEqual(list(c1), list(c2))
+
+if __name__ == '__main__':
+ wttest.run()