summaryrefslogtreecommitdiff
path: root/src/conn
diff options
context:
space:
mode:
Diffstat (limited to 'src/conn')
-rw-r--r--src/conn/conn_api.c45
-rw-r--r--src/conn/conn_cache.c9
-rw-r--r--src/conn/conn_cache_pool.c64
-rw-r--r--src/conn/conn_ckpt.c26
-rw-r--r--src/conn/conn_dhandle.c101
-rw-r--r--src/conn/conn_handle.c24
-rw-r--r--src/conn/conn_log.c82
-rw-r--r--src/conn/conn_open.c57
-rw-r--r--src/conn/conn_stat.c33
-rw-r--r--src/conn/conn_sweep.c36
10 files changed, 290 insertions, 187 deletions
diff --git a/src/conn/conn_api.c b/src/conn/conn_api.c
index 474b8bbad8a..68d45678965 100644
--- a/src/conn/conn_api.c
+++ b/src/conn/conn_api.c
@@ -1662,8 +1662,8 @@ __conn_single(WT_SESSION_IMPL *session, const char *cfg[])
WT_ERR_MSG(session, EINVAL,
"Creating a new database is incompatible with "
"read-only configuration");
- len = (size_t)snprintf(buf, sizeof(buf),
- "%s\n%s\n", WT_WIREDTIGER, WIREDTIGER_VERSION_STRING);
+ WT_ERR(__wt_snprintf_len_set(buf, sizeof(buf), &len,
+ "%s\n%s\n", WT_WIREDTIGER, WIREDTIGER_VERSION_STRING));
WT_ERR(__wt_write(session, fh, (wt_off_t)0, len, buf));
WT_ERR(__wt_fsync(session, fh, true));
} else {
@@ -1798,6 +1798,7 @@ __wt_verbose_config(WT_SESSION_IMPL *session, const char *cfg[])
{ "checkpoint", WT_VERB_CHECKPOINT },
{ "compact", WT_VERB_COMPACT },
{ "evict", WT_VERB_EVICT },
+ { "evict_stuck", WT_VERB_EVICT_STUCK },
{ "evictserver", WT_VERB_EVICTSERVER },
{ "fileops", WT_VERB_FILEOPS },
{ "handleops", WT_VERB_HANDLEOPS },
@@ -1811,6 +1812,7 @@ __wt_verbose_config(WT_SESSION_IMPL *session, const char *cfg[])
{ "rebalance", WT_VERB_REBALANCE },
{ "reconcile", WT_VERB_RECONCILE },
{ "recovery", WT_VERB_RECOVERY },
+ { "recovery_progress", WT_VERB_RECOVERY_PROGRESS },
{ "salvage", WT_VERB_SALVAGE },
{ "shared_cache", WT_VERB_SHARED_CACHE },
{ "split", WT_VERB_SPLIT },
@@ -1986,6 +1988,16 @@ __conn_set_file_system(
CONNECTION_API_CALL(conn, session, set_file_system, config, cfg);
WT_UNUSED(cfg);
+ /*
+ * You can only configure a file system once, and attempting to do it
+ * again probably means the extension argument didn't have early-load
+ * set and we've already configured the default file system.
+ */
+ if (conn->file_system != NULL)
+ WT_ERR_MSG(session, EPERM,
+ "filesystem already configured; custom filesystems should "
+ "enable \"early_load\" configuration");
+
conn->file_system = file_system;
err: API_END_RET(session, ret);
@@ -2174,6 +2186,15 @@ wiredtiger_open(const char *home, WT_EVENT_HANDLER *event_handler,
if (cval.val)
F_SET(conn, WT_CONN_READONLY);
+ /* Configure error messages so we get them right early. */
+ WT_ERR(__wt_config_gets(session, cfg, "error_prefix", &cval));
+ if (cval.len != 0)
+ WT_ERR(__wt_strndup(
+ session, cval.str, cval.len, &conn->error_prefix));
+
+ /* Set the database home so extensions have access to it. */
+ WT_ERR(__conn_home(session, home, cfg));
+
/*
* Load early extensions before doing further initialization (one early
* extension is to configure a file system).
@@ -2197,6 +2218,9 @@ wiredtiger_open(const char *home, WT_EVENT_HANDLER *event_handler,
WT_ERR(
__conn_chk_file_system(session, F_ISSET(conn, WT_CONN_READONLY)));
+ /* Make sure no other thread of control already owns this database. */
+ WT_ERR(__conn_single(session, cfg));
+
/*
* Capture the config_base setting file for later use. Again, if the
* application doesn't want us to read the base configuration file,
@@ -2206,18 +2230,6 @@ wiredtiger_open(const char *home, WT_EVENT_HANDLER *event_handler,
WT_ERR(__wt_config_gets(session, cfg, "config_base", &cval));
config_base_set = cval.val != 0;
- /* Configure error messages so we get them right early. */
- WT_ERR(__wt_config_gets(session, cfg, "error_prefix", &cval));
- if (cval.len != 0)
- WT_ERR(__wt_strndup(
- session, cval.str, cval.len, &conn->error_prefix));
-
- /* Get the database home. */
- WT_ERR(__conn_home(session, home, cfg));
-
- /* Make sure no other thread of control already owns this database. */
- WT_ERR(__conn_single(session, cfg));
-
/*
* Build the real configuration stack, in the following order (where
* later entries override earlier entries):
@@ -2238,10 +2250,9 @@ wiredtiger_open(const char *home, WT_EVENT_HANDLER *event_handler,
WT_ERR(__wt_scr_alloc(session, 0, &i3));
cfg[0] = WT_CONFIG_BASE(session, wiredtiger_open_all);
cfg[1] = NULL;
- WT_ERR_TEST(snprintf(version, sizeof(version),
+ WT_ERR(__wt_snprintf(version, sizeof(version),
"version=(major=%d,minor=%d)",
- WIREDTIGER_VERSION_MAJOR, WIREDTIGER_VERSION_MINOR) >=
- (int)sizeof(version), ENOMEM);
+ WIREDTIGER_VERSION_MAJOR, WIREDTIGER_VERSION_MINOR));
__conn_config_append(cfg, version);
/* Ignore the base_config file if config_base_set is false. */
diff --git a/src/conn/conn_cache.c b/src/conn/conn_cache.c
index fe5f94ea03d..28dd06332e0 100644
--- a/src/conn/conn_cache.c
+++ b/src/conn/conn_cache.c
@@ -143,7 +143,8 @@ __wt_cache_config(WT_SESSION_IMPL *session, bool reconfigure, const char *cfg[])
if (reconfigure)
WT_RET(__wt_thread_group_resize(
session, &conn->evict_threads,
- conn->evict_threads_min, conn->evict_threads_max,
+ conn->evict_threads_min,
+ conn->evict_threads_max,
WT_THREAD_CAN_WAIT | WT_THREAD_PANIC_FAIL));
return (0);
@@ -186,8 +187,8 @@ __wt_cache_create(WT_SESSION_IMPL *session, const char *cfg[])
WT_RET_MSG(session, EINVAL,
"eviction target must be lower than the eviction trigger");
- WT_RET(__wt_cond_auto_alloc(session, "cache eviction server",
- false, 10000, WT_MILLION, &cache->evict_cond));
+ WT_RET(__wt_cond_auto_alloc(session,
+ "cache eviction server", 10000, WT_MILLION, &cache->evict_cond));
WT_RET(__wt_spin_init(session, &cache->evict_pass_lock, "evict pass"));
WT_RET(__wt_spin_init(session,
&cache->evict_queue_lock, "cache eviction queue"));
@@ -311,7 +312,7 @@ __wt_cache_destroy(WT_SESSION_IMPL *session)
cache->bytes_dirty_intl + cache->bytes_dirty_leaf,
cache->pages_dirty_intl + cache->pages_dirty_leaf);
- WT_TRET(__wt_cond_auto_destroy(session, &cache->evict_cond));
+ WT_TRET(__wt_cond_destroy(session, &cache->evict_cond));
__wt_spin_destroy(session, &cache->evict_pass_lock);
__wt_spin_destroy(session, &cache->evict_queue_lock);
__wt_spin_destroy(session, &cache->evict_walk_lock);
diff --git a/src/conn/conn_cache_pool.c b/src/conn/conn_cache_pool.c
index 79c2fc23da5..ed078991581 100644
--- a/src/conn/conn_cache_pool.c
+++ b/src/conn/conn_cache_pool.c
@@ -32,7 +32,7 @@
*/
#define WT_CACHE_POOL_APP_EVICT_MULTIPLIER 3
#define WT_CACHE_POOL_APP_WAIT_MULTIPLIER 6
-#define WT_CACHE_POOL_READ_MULTIPLIER 1
+#define WT_CACHE_POOL_READ_MULTIPLIER 1
static void __cache_pool_adjust(
WT_SESSION_IMPL *, uint64_t, uint64_t, bool, bool *);
@@ -104,8 +104,8 @@ __wt_cache_pool_config(WT_SESSION_IMPL *session, const char **cfg)
TAILQ_INIT(&cp->cache_pool_qh);
WT_ERR(__wt_spin_init(
session, &cp->cache_pool_lock, "cache shared pool"));
- WT_ERR(__wt_cond_alloc(session,
- "cache pool server", false, &cp->cache_pool_cond));
+ WT_ERR(__wt_cond_alloc(
+ session, "cache pool server", &cp->cache_pool_cond));
__wt_process.cache_pool = cp;
__wt_verbose(session,
@@ -418,8 +418,9 @@ static void
__cache_pool_balance(WT_SESSION_IMPL *session, bool forward)
{
WT_CACHE_POOL *cp;
- bool adjusted;
uint64_t bump_threshold, highest;
+ int i;
+ bool adjusted;
cp = __wt_process.cache_pool;
adjusted = false;
@@ -438,11 +439,17 @@ __cache_pool_balance(WT_SESSION_IMPL *session, bool forward)
/*
* Actively attempt to:
- * - Reduce the amount allocated, if we are over the budget
+ * - Reduce the amount allocated, if we are over the budget.
* - Increase the amount used if there is capacity and any pressure.
+ * Don't keep trying indefinitely, if we aren't succeeding in reducing
+ * the cache in use re-assessing the participants' states is necessary.
+ * We are also holding a lock across this process, which can slow
+ * participant shutdown if we spend a long time balancing.
*/
- while (F_ISSET(cp, WT_CACHE_POOL_ACTIVE) &&
- F_ISSET(S2C(session)->cache, WT_CACHE_POOL_RUN)) {
+ for (i = 0;
+ i < 2 * WT_CACHE_POOL_BUMP_THRESHOLD &&
+ F_ISSET(cp, WT_CACHE_POOL_ACTIVE) &&
+ F_ISSET(S2C(session)->cache, WT_CACHE_POOL_RUN); i++) {
__cache_pool_adjust(
session, highest, bump_threshold, forward, &adjusted);
/*
@@ -565,7 +572,7 @@ __cache_pool_adjust(WT_SESSION_IMPL *session,
WT_CONNECTION_IMPL *entry;
uint64_t adjustment, highest_percentile, pressure, reserved, smallest;
u_int pct_full;
- bool busy, pool_full, grow;
+ bool busy, decrease_ok, grow, pool_full;
*adjustedp = false;
cp = __wt_process.cache_pool;
@@ -612,6 +619,34 @@ __cache_pool_adjust(WT_SESSION_IMPL *session,
continue;
/*
+ * The bump threshold decreases as we try longer to balance
+ * the pool. Adjust how aggressively we free space from
+ * participants depending on how long we have been trying.
+ */
+ decrease_ok = false;
+ /*
+ * Any participant is a candidate if we have been trying
+ * for long enough.
+ */
+ if (bump_threshold == 0)
+ decrease_ok = true;
+ /*
+ * Participants that aren't doing application eviction and
+ * are showing a reasonable amount of usage are excluded
+ * even if we have been trying for a while.
+ */
+ else if (bump_threshold < WT_CACHE_POOL_BUMP_THRESHOLD / 3 &&
+ (!busy && highest > 1))
+ decrease_ok = true;
+ /*
+ * Any participant that is proportionally less busy is a
+ * candidate from the first attempt.
+ */
+ else if (highest > 1 &&
+ pressure < WT_CACHE_POOL_REDUCE_THRESHOLD)
+ decrease_ok = true;
+
+ /*
* If the entry is currently allocated less than the reserved
* size, increase its allocation. This should only happen if:
* - it's the first time we've seen this member, or
@@ -624,17 +659,12 @@ __cache_pool_adjust(WT_SESSION_IMPL *session,
* Conditions for reducing the amount of resources for an
* entry:
* - the pool is full,
- * - application threads are not busy doing eviction already,
* - this entry has more than the minimum amount of space in
* use,
- * - the read pressure in this entry is below the threshold,
- * other entries need more cache, the entry has more than
- * the minimum space and there is no available space in the
- * pool.
+ * - it was determined that this slot is a good candidate
*/
- } else if (pool_full && !busy &&
- entry->cache_size > reserved &&
- pressure < WT_CACHE_POOL_REDUCE_THRESHOLD && highest > 1) {
+ } else if (pool_full &&
+ entry->cache_size > reserved && decrease_ok) {
grow = false;
/*
* Don't drop the size down too much - or it can
@@ -733,7 +763,7 @@ __wt_cache_pool_server(void *arg)
F_ISSET(cache, WT_CACHE_POOL_RUN)) {
if (cp->currently_used <= cp->size)
__wt_cond_wait(
- session, cp->cache_pool_cond, WT_MILLION);
+ session, cp->cache_pool_cond, WT_MILLION, NULL);
/*
* Re-check pool run flag - since we want to avoid getting the
diff --git a/src/conn/conn_ckpt.c b/src/conn/conn_ckpt.c
index 1d18c128c5b..d5a6faf7bd7 100644
--- a/src/conn/conn_ckpt.c
+++ b/src/conn/conn_ckpt.c
@@ -65,6 +65,16 @@ __ckpt_server_config(WT_SESSION_IMPL *session, const char **cfg, bool *startp)
}
/*
+ * __ckpt_server_run_chk --
+ * Check to decide if the checkpoint server should continue running.
+ */
+static bool
+__ckpt_server_run_chk(WT_SESSION_IMPL *session)
+{
+ return (F_ISSET(S2C(session), WT_CONN_SERVER_CHECKPOINT));
+}
+
+/*
* __ckpt_server --
* The checkpoint server thread.
*/
@@ -80,14 +90,18 @@ __ckpt_server(void *arg)
conn = S2C(session);
wt_session = (WT_SESSION *)session;
- while (F_ISSET(conn, WT_CONN_SERVER_RUN) &&
- F_ISSET(conn, WT_CONN_SERVER_CHECKPOINT)) {
+ for (;;) {
/*
* Wait...
* NOTE: If the user only configured logsize, then usecs
* will be 0 and this wait won't return until signalled.
*/
- __wt_cond_wait(session, conn->ckpt_cond, conn->ckpt_usecs);
+ __wt_cond_wait(session,
+ conn->ckpt_cond, conn->ckpt_usecs, __ckpt_server_run_chk);
+
+ /* Check if we're quitting or being reconfigured. */
+ if (!__ckpt_server_run_chk(session))
+ break;
/*
* Checkpoint the database if the connection is marked dirty.
@@ -115,7 +129,8 @@ __ckpt_server(void *arg)
* it so we don't do another checkpoint
* immediately.
*/
- __wt_cond_wait(session, conn->ckpt_cond, 1);
+ __wt_cond_wait(
+ session, conn->ckpt_cond, 1, NULL);
}
} else
WT_STAT_CONN_INCR(session, txn_checkpoint_skipped);
@@ -154,8 +169,7 @@ __ckpt_server_start(WT_CONNECTION_IMPL *conn)
"checkpoint-server", true, session_flags, &conn->ckpt_session));
session = conn->ckpt_session;
- WT_RET(__wt_cond_alloc(
- session, "checkpoint server", false, &conn->ckpt_cond));
+ WT_RET(__wt_cond_alloc(session, "checkpoint server", &conn->ckpt_cond));
/*
* Start the thread.
diff --git a/src/conn/conn_dhandle.c b/src/conn/conn_dhandle.c
index e9e3925c57e..657cdebf7ee 100644
--- a/src/conn/conn_dhandle.c
+++ b/src/conn/conn_dhandle.c
@@ -12,37 +12,47 @@
* __conn_dhandle_destroy --
* Destroy a data handle.
*/
-static void
+static int
__conn_dhandle_destroy(WT_SESSION_IMPL *session, WT_DATA_HANDLE *dhandle)
{
+ WT_DECL_RET;
+
+ WT_WITH_DHANDLE(session, dhandle, ret = __wt_btree_discard(session));
+
__wt_rwlock_destroy(session, &dhandle->rwlock);
__wt_free(session, dhandle->name);
__wt_free(session, dhandle->checkpoint);
- __wt_free(session, dhandle->handle);
__wt_spin_destroy(session, &dhandle->close_lock);
__wt_stat_dsrc_discard(session, dhandle);
__wt_overwrite_and_free(session, dhandle);
+ return (ret);
}
/*
- * __conn_dhandle_alloc --
+ * __wt_conn_dhandle_alloc --
* Allocate a new data handle and return it linked into the connection's
* list.
*/
-static int
-__conn_dhandle_alloc(WT_SESSION_IMPL *session,
- const char *uri, const char *checkpoint, WT_DATA_HANDLE **dhandlep)
+int
+__wt_conn_dhandle_alloc(
+ WT_SESSION_IMPL *session, const char *uri, const char *checkpoint)
{
WT_BTREE *btree;
WT_DATA_HANDLE *dhandle;
WT_DECL_RET;
uint64_t bucket;
- *dhandlep = NULL;
+ /*
+ * Ensure no one beat us to creating the handle now that we hold the
+ * write lock.
+ */
+ if ((ret =
+ __wt_conn_dhandle_find(session, uri, checkpoint)) != WT_NOTFOUND)
+ return (ret);
WT_RET(__wt_calloc_one(session, &dhandle));
- WT_ERR(__wt_rwlock_alloc(session, &dhandle->rwlock, "data handle"));
+ __wt_rwlock_init(session, &dhandle->rwlock);
dhandle->name_hash = __wt_hash_city64(uri, strlen(uri));
WT_ERR(__wt_strdup(session, uri, &dhandle->name));
WT_ERR(__wt_strdup(session, checkpoint, &dhandle->checkpoint));
@@ -75,10 +85,10 @@ __conn_dhandle_alloc(WT_SESSION_IMPL *session,
bucket = dhandle->name_hash % WT_HASH_ARRAY_SIZE;
WT_CONN_DHANDLE_INSERT(S2C(session), dhandle, bucket);
- *dhandlep = dhandle;
+ session->dhandle = dhandle;
return (0);
-err: __conn_dhandle_destroy(session, dhandle);
+err: WT_TRET(__conn_dhandle_destroy(session, dhandle));
return (ret);
}
@@ -122,10 +132,7 @@ __wt_conn_dhandle_find(
}
}
- WT_RET(__conn_dhandle_alloc(session, uri, checkpoint, &dhandle));
-
- session->dhandle = dhandle;
- return (0);
+ return (WT_NOTFOUND);
}
/*
@@ -153,11 +160,11 @@ __wt_conn_btree_sync_and_close(WT_SESSION_IMPL *session, bool final, bool force)
WT_RET(__wt_evict_file_exclusive_on(session));
/*
- * If we don't already have the schema lock, make it an error to try
- * to acquire it. The problem is that we are holding an exclusive
- * lock on the handle, and if we attempt to acquire the schema lock
- * we might deadlock with a thread that has the schema lock and wants
- * a handle lock (specifically, checkpoint).
+ * If we don't already have the schema lock, make it an error to try to
+ * acquire it. The problem is that we are holding an exclusive lock on
+ * the handle, and if we attempt to acquire the schema lock we might
+ * deadlock with a thread that has the schema lock and wants a handle
+ * lock.
*/
no_schema_lock = false;
if (!F_ISSET(session, WT_SESSION_LOCKED_SCHEMA)) {
@@ -197,6 +204,7 @@ __wt_conn_btree_sync_and_close(WT_SESSION_IMPL *session, bool final, bool force)
}
WT_TRET(__wt_btree_close(session));
+ F_CLR(btree, WT_BTREE_SPECIAL_FLAGS);
/*
* If we marked a handle dead it will be closed by sweep, via
@@ -306,7 +314,8 @@ __wt_conn_btree_open(
F_ISSET(dhandle, WT_DHANDLE_EXCLUSIVE) &&
!LF_ISSET(WT_DHANDLE_LOCK_ONLY));
- WT_ASSERT(session, !F_ISSET(S2C(session), WT_CONN_CLOSING));
+ WT_ASSERT(session,
+ !F_ISSET(S2C(session), WT_CONN_CLOSING_NO_MORE_OPENS));
/*
* If the handle is already open, it has to be closed so it can be
@@ -400,10 +409,7 @@ __conn_btree_apply_internal(WT_SESSION_IMPL *session, WT_DATA_HANDLE *dhandle,
return (ret == EBUSY ? 0 : ret);
WT_SAVE_DHANDLE(session, ret = file_func(session, cfg));
- if (WT_META_TRACKING(session))
- WT_TRET(__wt_meta_track_handle_lock(session, false));
- else
- WT_TRET(__wt_session_release_btree(session));
+ WT_TRET(__wt_session_release_btree(session));
return (ret);
}
@@ -419,12 +425,11 @@ __wt_conn_btree_apply(WT_SESSION_IMPL *session, const char *uri,
{
WT_CONNECTION_IMPL *conn;
WT_DATA_HANDLE *dhandle;
+ WT_DECL_RET;
uint64_t bucket;
conn = S2C(session);
- WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_HANDLE_LIST));
-
/*
* If we're given a URI, then we walk only the hash list for that
* name. If we don't have a URI we walk the entire dhandle list.
@@ -432,29 +437,42 @@ __wt_conn_btree_apply(WT_SESSION_IMPL *session, const char *uri,
if (uri != NULL) {
bucket =
__wt_hash_city64(uri, strlen(uri)) % WT_HASH_ARRAY_SIZE;
- TAILQ_FOREACH(dhandle, &conn->dhhash[bucket], hashq) {
+
+ for (dhandle = NULL;;) {
+ WT_WITH_HANDLE_LIST_READ_LOCK(session,
+ WT_DHANDLE_NEXT(session, dhandle,
+ &conn->dhhash[bucket], hashq));
+ if (dhandle == NULL)
+ return (0);
+
if (!F_ISSET(dhandle, WT_DHANDLE_OPEN) ||
F_ISSET(dhandle, WT_DHANDLE_DEAD) ||
dhandle->checkpoint != NULL ||
strcmp(uri, dhandle->name) != 0)
continue;
- WT_RET(__conn_btree_apply_internal(
- session, dhandle, file_func, name_func, cfg));
+ WT_ERR(__conn_btree_apply_internal(session,
+ dhandle, file_func, name_func, cfg));
}
} else {
- TAILQ_FOREACH(dhandle, &conn->dhqh, q) {
+ for (dhandle = NULL;;) {
+ WT_WITH_HANDLE_LIST_READ_LOCK(session,
+ WT_DHANDLE_NEXT(session, dhandle, &conn->dhqh, q));
+ if (dhandle == NULL)
+ return (0);
+
if (!F_ISSET(dhandle, WT_DHANDLE_OPEN) ||
F_ISSET(dhandle, WT_DHANDLE_DEAD) ||
dhandle->checkpoint != NULL ||
!WT_PREFIX_MATCH(dhandle->name, "file:") ||
WT_IS_METADATA(dhandle))
continue;
- WT_RET(__conn_btree_apply_internal(
- session, dhandle, file_func, name_func, cfg));
+ WT_ERR(__conn_btree_apply_internal(session,
+ dhandle, file_func, name_func, cfg));
}
}
- return (0);
+err: WT_DHANDLE_RELEASE(dhandle);
+ return (ret);
}
/*
@@ -473,7 +491,8 @@ __wt_conn_dhandle_close_all(
conn = S2C(session);
- WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_HANDLE_LIST));
+ WT_ASSERT(session,
+ F_ISSET(session, WT_SESSION_LOCKED_HANDLE_LIST_WRITE));
WT_ASSERT(session, session->dhandle == NULL);
bucket = __wt_hash_city64(uri, strlen(uri)) % WT_HASH_ARRAY_SIZE;
@@ -484,7 +503,12 @@ __wt_conn_dhandle_close_all(
session->dhandle = dhandle;
- /* Lock the handle exclusively. */
+ /*
+ * Lock the handle exclusively. If this is part of
+ * schema-changing operation (indicated by metadata tracking
+ * being enabled), hold the lock for the duration of the
+ * operation.
+ */
WT_ERR(__wt_session_get_btree(session,
dhandle->name, dhandle->checkpoint,
NULL, WT_DHANDLE_EXCLUSIVE | WT_DHANDLE_LOCK_ONLY));
@@ -534,7 +558,8 @@ __conn_dhandle_remove(WT_SESSION_IMPL *session, bool final)
dhandle = session->dhandle;
bucket = dhandle->name_hash % WT_HASH_ARRAY_SIZE;
- WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_HANDLE_LIST));
+ WT_ASSERT(session,
+ F_ISSET(session, WT_SESSION_LOCKED_HANDLE_LIST_WRITE));
WT_ASSERT(session, dhandle != conn->cache->evict_file_next);
/* Check if the handle was reacquired by a session while we waited. */
@@ -583,7 +608,7 @@ __wt_conn_dhandle_discard_single(
}
/* Try to remove the handle, protected by the data handle lock. */
- WT_WITH_HANDLE_LIST_LOCK(session,
+ WT_WITH_HANDLE_LIST_WRITE_LOCK(session,
tret = __conn_dhandle_remove(session, final));
if (set_pass_intr)
(void)__wt_atomic_subv32(&S2C(session)->cache->pass_intr, 1);
@@ -594,7 +619,7 @@ __wt_conn_dhandle_discard_single(
*/
if (ret == 0 || final) {
__conn_btree_config_clear(session);
- __conn_dhandle_destroy(session, dhandle);
+ WT_TRET(__conn_dhandle_destroy(session, dhandle));
session->dhandle = NULL;
}
diff --git a/src/conn/conn_handle.c b/src/conn/conn_handle.c
index 02182daa7dc..287e9ca7b99 100644
--- a/src/conn/conn_handle.c
+++ b/src/conn/conn_handle.c
@@ -53,19 +53,18 @@ __wt_connection_init(WT_CONNECTION_IMPL *conn)
/* Spinlocks. */
WT_RET(__wt_spin_init(session, &conn->api_lock, "api"));
WT_SPIN_INIT_TRACKED(session, &conn->checkpoint_lock, checkpoint);
- WT_SPIN_INIT_TRACKED(session, &conn->dhandle_lock, handle_list);
WT_RET(__wt_spin_init(session, &conn->encryptor_lock, "encryptor"));
WT_RET(__wt_spin_init(session, &conn->fh_lock, "file list"));
WT_RET(__wt_spin_init(session, &conn->las_lock, "lookaside table"));
WT_SPIN_INIT_TRACKED(session, &conn->metadata_lock, metadata);
WT_RET(__wt_spin_init(session, &conn->reconfig_lock, "reconfigure"));
WT_SPIN_INIT_TRACKED(session, &conn->schema_lock, schema);
- WT_SPIN_INIT_TRACKED(session, &conn->table_lock, table);
WT_RET(__wt_spin_init(session, &conn->turtle_lock, "turtle file"));
/* Read-write locks */
- WT_RET(__wt_rwlock_alloc(
- session, &conn->hot_backup_lock, "hot backup"));
+ __wt_rwlock_init(session, &conn->dhandle_lock);
+ __wt_rwlock_init(session, &conn->hot_backup_lock);
+ __wt_rwlock_init(session, &conn->table_lock);
WT_RET(__wt_calloc_def(session, WT_PAGE_LOCKS, &conn->page_lock));
for (i = 0; i < WT_PAGE_LOCKS; ++i)
@@ -80,7 +79,7 @@ __wt_connection_init(WT_CONNECTION_IMPL *conn)
WT_RET(__wt_spin_init(
session, &conn->lsm_manager.switch_lock, "LSM switch queue lock"));
WT_RET(__wt_cond_alloc(
- session, "LSM worker cond", false, &conn->lsm_manager.work_cond));
+ session, "LSM worker cond", &conn->lsm_manager.work_cond));
/*
* Generation numbers.
@@ -110,16 +109,15 @@ __wt_connection_init(WT_CONNECTION_IMPL *conn)
* __wt_connection_destroy --
* Destroy the connection's underlying WT_CONNECTION_IMPL structure.
*/
-int
+void
__wt_connection_destroy(WT_CONNECTION_IMPL *conn)
{
- WT_DECL_RET;
WT_SESSION_IMPL *session;
u_int i;
/* Check there's something to destroy. */
if (conn == NULL)
- return (0);
+ return;
session = conn->default_session;
@@ -136,7 +134,7 @@ __wt_connection_destroy(WT_CONNECTION_IMPL *conn)
__wt_spin_destroy(session, &conn->api_lock);
__wt_spin_destroy(session, &conn->block_lock);
__wt_spin_destroy(session, &conn->checkpoint_lock);
- __wt_spin_destroy(session, &conn->dhandle_lock);
+ __wt_rwlock_destroy(session, &conn->dhandle_lock);
__wt_spin_destroy(session, &conn->encryptor_lock);
__wt_spin_destroy(session, &conn->fh_lock);
__wt_rwlock_destroy(session, &conn->hot_backup_lock);
@@ -144,17 +142,12 @@ __wt_connection_destroy(WT_CONNECTION_IMPL *conn)
__wt_spin_destroy(session, &conn->metadata_lock);
__wt_spin_destroy(session, &conn->reconfig_lock);
__wt_spin_destroy(session, &conn->schema_lock);
- __wt_spin_destroy(session, &conn->table_lock);
+ __wt_rwlock_destroy(session, &conn->table_lock);
__wt_spin_destroy(session, &conn->turtle_lock);
for (i = 0; i < WT_PAGE_LOCKS; ++i)
__wt_spin_destroy(session, &conn->page_lock[i]);
__wt_free(session, conn->page_lock);
- /* Destroy the file-system configuration. */
- if (conn->file_system != NULL && conn->file_system->terminate != NULL)
- WT_TRET(conn->file_system->terminate(
- conn->file_system, (WT_SESSION *)session));
-
/* Free allocated memory. */
__wt_free(session, conn->cfg);
__wt_free(session, conn->home);
@@ -163,5 +156,4 @@ __wt_connection_destroy(WT_CONNECTION_IMPL *conn)
__wt_stat_connection_discard(session, conn);
__wt_free(NULL, conn);
- return (ret);
}
diff --git a/src/conn/conn_log.c b/src/conn/conn_log.c
index 8198b3a1a02..b8b5bd2a908 100644
--- a/src/conn/conn_log.c
+++ b/src/conn/conn_log.c
@@ -174,7 +174,7 @@ __logmgr_config(
WT_RET(__logmgr_sync_cfg(session, cfg));
if (conn->log_cond != NULL)
- __wt_cond_auto_signal(session, conn->log_cond);
+ __wt_cond_signal(session, conn->log_cond);
return (0);
}
@@ -237,7 +237,7 @@ __log_archive_once(WT_SESSION_IMPL *session, uint32_t backup_file)
* We can only archive files if a hot backup is not in progress or
* if we are the backup.
*/
- __wt_readlock(session, conn->hot_backup_lock);
+ __wt_readlock(session, &conn->hot_backup_lock);
locked = true;
if (!conn->hot_backup || backup_file != 0) {
for (i = 0; i < logcount; i++) {
@@ -248,7 +248,7 @@ __log_archive_once(WT_SESSION_IMPL *session, uint32_t backup_file)
session, WT_LOG_FILENAME, lognum));
}
}
- __wt_readunlock(session, conn->hot_backup_lock);
+ __wt_readunlock(session, &conn->hot_backup_lock);
locked = false;
/*
@@ -260,7 +260,7 @@ __log_archive_once(WT_SESSION_IMPL *session, uint32_t backup_file)
if (0)
err: __wt_err(session, ret, "log archive server error");
if (locked)
- __wt_readunlock(session, conn->hot_backup_lock);
+ __wt_readunlock(session, &conn->hot_backup_lock);
WT_TRET(__wt_fs_directory_list_free(session, &logfiles, logcount));
return (ret);
}
@@ -341,7 +341,7 @@ __wt_log_truncate_files(
conn = S2C(session);
if (!FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED))
return (0);
- if (F_ISSET(conn, WT_CONN_SERVER_RUN) &&
+ if (F_ISSET(conn, WT_CONN_SERVER_LOG) &&
FLD_ISSET(conn->log_flags, WT_CONN_LOG_ARCHIVE))
WT_RET_MSG(session, EINVAL,
"Attempt to archive manually while a server is running");
@@ -355,9 +355,9 @@ __wt_log_truncate_files(
__wt_verbose(session, WT_VERB_LOG,
"log_truncate_files: Archive once up to %" PRIu32, backup_file);
- __wt_writelock(session, log->log_archive_lock);
+ __wt_writelock(session, &log->log_archive_lock);
ret = __log_archive_once(session, backup_file);
- __wt_writeunlock(session, log->log_archive_lock);
+ __wt_writeunlock(session, &log->log_archive_lock);
return (ret);
}
@@ -382,7 +382,7 @@ __log_file_server(void *arg)
conn = S2C(session);
log = conn->log;
locked = false;
- while (F_ISSET(conn, WT_CONN_LOG_SERVER_RUN)) {
+ while (F_ISSET(conn, WT_CONN_SERVER_LOG)) {
/*
* If there is a log file to close, make sure any outstanding
* write operations have completed, then fsync and close it.
@@ -433,7 +433,7 @@ __log_file_server(void *arg)
*/
if (!conn->hot_backup) {
__wt_readlock(
- session, conn->hot_backup_lock);
+ session, &conn->hot_backup_lock);
if (!conn->hot_backup)
WT_ERR_ERROR_OK(
__wt_ftruncate(session,
@@ -441,7 +441,7 @@ __log_file_server(void *arg)
close_end_lsn.l.offset),
ENOTSUP);
__wt_readunlock(
- session, conn->hot_backup_lock);
+ session, &conn->hot_backup_lock);
}
WT_SET_LSN(&close_end_lsn,
close_end_lsn.l.file + 1, 0);
@@ -505,8 +505,7 @@ __log_file_server(void *arg)
locked = false;
__wt_spin_unlock(session, &log->log_sync_lock);
} else {
- __wt_cond_auto_signal(
- session, conn->log_wrlsn_cond);
+ __wt_cond_signal(session, conn->log_wrlsn_cond);
/*
* We do not want to wait potentially a second
* to process this. Yield to give the wrlsn
@@ -517,8 +516,9 @@ __log_file_server(void *arg)
continue;
}
}
+
/* Wait until the next event. */
- __wt_cond_wait(session, conn->log_file_cond, WT_MILLION / 10);
+ __wt_cond_wait(session, conn->log_file_cond, 100000, NULL);
}
if (0) {
@@ -708,7 +708,7 @@ __log_wrlsn_server(void *arg)
log = conn->log;
yield = 0;
WT_INIT_LSN(&prev);
- while (F_ISSET(conn, WT_CONN_LOG_SERVER_RUN)) {
+ while (F_ISSET(conn, WT_CONN_SERVER_LOG)) {
/*
* Write out any log record buffers if anything was done
* since last time. Only call the function to walk the
@@ -730,12 +730,8 @@ __log_wrlsn_server(void *arg)
if (yield++ < WT_THOUSAND)
__wt_yield();
else
- /*
- * Send in false because if we did any work we would
- * not be on this path.
- */
__wt_cond_auto_wait(
- session, conn->log_wrlsn_cond, did_work);
+ session, conn->log_wrlsn_cond, did_work, NULL);
}
/*
* On close we need to do this one more time because there could
@@ -787,7 +783,7 @@ __log_server(void *arg)
* takes to sync out an earlier file.
*/
did_work = true;
- while (F_ISSET(conn, WT_CONN_LOG_SERVER_RUN)) {
+ while (F_ISSET(conn, WT_CONN_SERVER_LOG)) {
/*
* Slots depend on future activity. Force out buffered
* writes in case we are idle. This cannot be part of the
@@ -814,10 +810,11 @@ __log_server(void *arg)
* agreed not to rename or remove any files in
* the database directory.
*/
- __wt_readlock(session, conn->hot_backup_lock);
+ __wt_readlock(session, &conn->hot_backup_lock);
if (!conn->hot_backup)
ret = __log_prealloc_once(session);
- __wt_readunlock(session, conn->hot_backup_lock);
+ __wt_readunlock(
+ session, &conn->hot_backup_lock);
WT_ERR(ret);
}
@@ -826,10 +823,10 @@ __log_server(void *arg)
*/
if (FLD_ISSET(conn->log_flags, WT_CONN_LOG_ARCHIVE)) {
if (__wt_try_writelock(
- session, log->log_archive_lock) == 0) {
+ session, &log->log_archive_lock) == 0) {
ret = __log_archive_once(session, 0);
__wt_writeunlock(
- session, log->log_archive_lock);
+ session, &log->log_archive_lock);
WT_ERR(ret);
} else
__wt_verbose(session, WT_VERB_LOG,
@@ -839,10 +836,9 @@ __log_server(void *arg)
}
/* Wait until the next event. */
-
__wt_epoch(session, &start);
- __wt_cond_auto_wait_signal(session,
- conn->log_cond, did_work, &signalled);
+ __wt_cond_auto_wait_signal(
+ session, conn->log_cond, did_work, NULL, &signalled);
__wt_epoch(session, &now);
timediff = WT_TIMEDIFF_MS(now, start);
}
@@ -884,8 +880,7 @@ __wt_logmgr_create(WT_SESSION_IMPL *session, const char *cfg[])
WT_RET(__wt_spin_init(session, &log->log_sync_lock, "log sync"));
WT_RET(__wt_spin_init(session, &log->log_writelsn_lock,
"log write LSN"));
- WT_RET(__wt_rwlock_alloc(session,
- &log->log_archive_lock, "log archive lock"));
+ __wt_rwlock_init(session, &log->log_archive_lock);
if (FLD_ISSET(conn->direct_io, WT_DIRECT_IO_LOG))
log->allocsize = (uint32_t)
WT_MAX(conn->buffer_alignment, WT_LOG_ALIGN);
@@ -904,10 +899,8 @@ __wt_logmgr_create(WT_SESSION_IMPL *session, const char *cfg[])
WT_INIT_LSN(&log->write_lsn);
WT_INIT_LSN(&log->write_start_lsn);
log->fileid = 0;
- WT_RET(__wt_cond_alloc(
- session, "log sync", false, &log->log_sync_cond));
- WT_RET(__wt_cond_alloc(
- session, "log write", false, &log->log_write_cond));
+ WT_RET(__wt_cond_alloc(session, "log sync", &log->log_sync_cond));
+ WT_RET(__wt_cond_alloc(session, "log write", &log->log_write_cond));
WT_RET(__wt_log_open(session));
WT_RET(__wt_log_slot_init(session));
@@ -930,6 +923,8 @@ __wt_logmgr_open(WT_SESSION_IMPL *session)
if (!FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED))
return (0);
+ F_SET(conn, WT_CONN_SERVER_LOG);
+
/*
* Start the log close thread. It is not configurable.
* If logging is enabled, this thread runs.
@@ -937,8 +932,8 @@ __wt_logmgr_open(WT_SESSION_IMPL *session)
session_flags = WT_SESSION_NO_DATA_HANDLES;
WT_RET(__wt_open_internal_session(conn,
"log-close-server", false, session_flags, &conn->log_file_session));
- WT_RET(__wt_cond_alloc(conn->log_file_session,
- "log close server", false, &conn->log_file_cond));
+ WT_RET(__wt_cond_alloc(
+ conn->log_file_session, "log close server", &conn->log_file_cond));
/*
* Start the log file close thread.
@@ -954,8 +949,7 @@ __wt_logmgr_open(WT_SESSION_IMPL *session)
WT_RET(__wt_open_internal_session(conn, "log-wrlsn-server",
false, session_flags, &conn->log_wrlsn_session));
WT_RET(__wt_cond_auto_alloc(conn->log_wrlsn_session,
- "log write lsn server", false, 10000, WT_MILLION,
- &conn->log_wrlsn_cond));
+ "log write lsn server", 10000, WT_MILLION, &conn->log_wrlsn_cond));
WT_RET(__wt_thread_create(conn->log_wrlsn_session,
&conn->log_wrlsn_tid, __log_wrlsn_server, conn->log_wrlsn_session));
conn->log_wrlsn_tid_set = true;
@@ -969,13 +963,13 @@ __wt_logmgr_open(WT_SESSION_IMPL *session)
if (conn->log_session != NULL) {
WT_ASSERT(session, conn->log_cond != NULL);
WT_ASSERT(session, conn->log_tid_set == true);
- __wt_cond_auto_signal(session, conn->log_cond);
+ __wt_cond_signal(session, conn->log_cond);
} else {
/* The log server gets its own session. */
WT_RET(__wt_open_internal_session(conn,
"log-server", false, session_flags, &conn->log_session));
WT_RET(__wt_cond_auto_alloc(conn->log_session,
- "log server", false, 50000, WT_MILLION, &conn->log_cond));
+ "log server", 50000, WT_MILLION, &conn->log_cond));
/*
* Start the thread.
@@ -1001,6 +995,8 @@ __wt_logmgr_destroy(WT_SESSION_IMPL *session)
conn = S2C(session);
+ F_CLR(conn, WT_CONN_SERVER_LOG);
+
if (!FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED)) {
/*
* We always set up the log_path so printlog can work without
@@ -1011,7 +1007,7 @@ __wt_logmgr_destroy(WT_SESSION_IMPL *session)
return (0);
}
if (conn->log_tid_set) {
- __wt_cond_auto_signal(session, conn->log_cond);
+ __wt_cond_signal(session, conn->log_cond);
WT_TRET(__wt_thread_join(session, conn->log_tid));
conn->log_tid_set = false;
}
@@ -1026,7 +1022,7 @@ __wt_logmgr_destroy(WT_SESSION_IMPL *session)
conn->log_file_session = NULL;
}
if (conn->log_wrlsn_tid_set) {
- __wt_cond_auto_signal(session, conn->log_wrlsn_cond);
+ __wt_cond_signal(session, conn->log_wrlsn_cond);
WT_TRET(__wt_thread_join(session, conn->log_wrlsn_tid));
conn->log_wrlsn_tid_set = false;
}
@@ -1047,9 +1043,9 @@ __wt_logmgr_destroy(WT_SESSION_IMPL *session)
}
/* Destroy the condition variables now that all threads are stopped */
- WT_TRET(__wt_cond_auto_destroy(session, &conn->log_cond));
+ WT_TRET(__wt_cond_destroy(session, &conn->log_cond));
WT_TRET(__wt_cond_destroy(session, &conn->log_file_cond));
- WT_TRET(__wt_cond_auto_destroy(session, &conn->log_wrlsn_cond));
+ WT_TRET(__wt_cond_destroy(session, &conn->log_wrlsn_cond));
WT_TRET(__wt_cond_destroy(session, &conn->log->log_sync_cond));
WT_TRET(__wt_cond_destroy(session, &conn->log->log_write_cond));
diff --git a/src/conn/conn_open.c b/src/conn/conn_open.c
index d4ace127bb2..eb3c79422a0 100644
--- a/src/conn/conn_open.c
+++ b/src/conn/conn_open.c
@@ -21,12 +21,6 @@ __wt_connection_open(WT_CONNECTION_IMPL *conn, const char *cfg[])
session = conn->default_session;
WT_ASSERT(session, session->iface.connection == &conn->iface);
- /*
- * Tell internal server threads to run: this must be set before opening
- * any sessions.
- */
- F_SET(conn, WT_CONN_SERVER_RUN | WT_CONN_LOG_SERVER_RUN);
-
/* WT_SESSION_IMPL array. */
WT_RET(__wt_calloc(session,
conn->session_size, sizeof(WT_SESSION_IMPL), &conn->sessions));
@@ -100,8 +94,16 @@ __wt_connection_close(WT_CONNECTION_IMPL *conn)
__wt_yield();
}
- /* Clear any pending async ops. */
+ /* Shut down the subsystems, ensuring workers see the state change. */
+ F_SET(conn, WT_CONN_CLOSING);
+ WT_FULL_BARRIER();
+
+ /*
+ * Clear any pending async operations and shut down the async worker
+ * threads and system before closing LSM.
+ */
WT_TRET(__wt_async_flush(session));
+ WT_TRET(__wt_async_destroy(session));
/*
* Shut down server threads other than the eviction server, which is
@@ -109,15 +111,20 @@ __wt_connection_close(WT_CONNECTION_IMPL *conn)
* btree handles, so take care in ordering shutdown to make sure they
* exit before files are closed.
*/
- F_CLR(conn, WT_CONN_SERVER_RUN);
- WT_TRET(__wt_async_destroy(session));
WT_TRET(__wt_lsm_manager_destroy(session));
- WT_TRET(__wt_sweep_destroy(session));
- F_SET(conn, WT_CONN_CLOSING);
+ /*
+ * Once the async and LSM threads exit, we shouldn't be opening any
+ * more files.
+ */
+ F_SET(conn, WT_CONN_CLOSING_NO_MORE_OPENS);
+ WT_FULL_BARRIER();
WT_TRET(__wt_checkpoint_server_destroy(session));
WT_TRET(__wt_statlog_destroy(session, true));
+ WT_TRET(__wt_sweep_destroy(session));
+
+ /* The eviction server is shut down last. */
WT_TRET(__wt_evict_destroy(session));
/* Shut down the lookaside table, after all eviction is complete. */
@@ -126,7 +133,7 @@ __wt_connection_close(WT_CONNECTION_IMPL *conn)
/* Close open data handles. */
WT_TRET(__wt_conn_dhandle_discard(session));
- /* Shut down metadata tracking, required before creating tables. */
+ /* Shut down metadata tracking. */
WT_TRET(__wt_meta_track_destroy(session));
/*
@@ -140,7 +147,6 @@ __wt_connection_close(WT_CONNECTION_IMPL *conn)
FLD_ISSET(conn->log_flags, WT_CONN_LOG_RECOVER_DONE))
WT_TRET(__wt_txn_checkpoint_log(
session, true, WT_TXN_LOG_CKPT_STOP, NULL));
- F_CLR(conn, WT_CONN_LOG_SERVER_RUN);
WT_TRET(__wt_logmgr_destroy(session));
/* Free memory for collators, compressors, data sources. */
@@ -159,15 +165,6 @@ __wt_connection_close(WT_CONNECTION_IMPL *conn)
/* Discard transaction state. */
__wt_txn_global_destroy(session);
- /* Close extensions, first calling any unload entry point. */
- while ((dlh = TAILQ_FIRST(&conn->dlhqh)) != NULL) {
- TAILQ_REMOVE(&conn->dlhqh, dlh, q);
-
- if (dlh->terminate != NULL)
- WT_TRET(dlh->terminate(wt_conn));
- WT_TRET(__wt_dlclose(session, dlh));
- }
-
/* Close the lock file, opening up the database to other connections. */
if (conn->lock_fh != NULL)
WT_TRET(__wt_close(session, &conn->lock_fh));
@@ -199,8 +196,22 @@ __wt_connection_close(WT_CONNECTION_IMPL *conn)
__wt_free(session, s->hazard);
}
+ /* Destroy the file-system configuration. */
+ if (conn->file_system != NULL && conn->file_system->terminate != NULL)
+ WT_TRET(conn->file_system->terminate(
+ conn->file_system, (WT_SESSION *)session));
+
+ /* Close extensions, first calling any unload entry point. */
+ while ((dlh = TAILQ_FIRST(&conn->dlhqh)) != NULL) {
+ TAILQ_REMOVE(&conn->dlhqh, dlh, q);
+
+ if (dlh->terminate != NULL)
+ WT_TRET(dlh->terminate(wt_conn));
+ WT_TRET(__wt_dlclose(session, dlh));
+ }
+
/* Destroy the handle. */
- WT_TRET(__wt_connection_destroy(conn));
+ __wt_connection_destroy(conn);
return (ret);
}
diff --git a/src/conn/conn_stat.c b/src/conn/conn_stat.c
index 3bcdfd7ecb1..d89392b66c6 100644
--- a/src/conn/conn_stat.c
+++ b/src/conn/conn_stat.c
@@ -409,7 +409,6 @@ __statlog_log_one(WT_SESSION_IMPL *session, WT_ITEM *path, WT_ITEM *tmp)
struct timespec ts;
struct tm *tm, _tm;
WT_CONNECTION_IMPL *conn;
- WT_DECL_RET;
WT_FSTREAM *log_stream;
conn = S2C(session);
@@ -446,12 +445,9 @@ __statlog_log_one(WT_SESSION_IMPL *session, WT_ITEM *path, WT_ITEM *tmp)
* Lock the schema and walk the list of open handles, dumping
* any that match the list of object sources.
*/
- if (conn->stat_sources != NULL) {
- WT_WITH_HANDLE_LIST_LOCK(session,
- ret = __wt_conn_btree_apply(
+ if (conn->stat_sources != NULL)
+ WT_RET(__wt_conn_btree_apply(
session, NULL, __statlog_apply, NULL, NULL));
- WT_RET(ret);
- }
/*
* Walk the list of open LSM trees, dumping any that match the
@@ -485,8 +481,7 @@ __statlog_on_close(WT_SESSION_IMPL *session)
if (!FLD_ISSET(conn->stat_flags, WT_STAT_ON_CLOSE))
return (0);
- if (F_ISSET(conn, WT_CONN_SERVER_RUN) &&
- F_ISSET(conn, WT_CONN_SERVER_STATISTICS))
+ if (F_ISSET(conn, WT_CONN_SERVER_STATISTICS))
WT_RET_MSG(session, EINVAL,
"Attempt to log statistics while a server is running");
@@ -498,6 +493,16 @@ err: __wt_scr_free(session, &tmp);
}
/*
+ * __statlog_server_run_chk --
+ * Check to decide if the statistics log server should continue running.
+ */
+static bool
+__statlog_server_run_chk(WT_SESSION_IMPL *session)
+{
+ return (F_ISSET(S2C(session), WT_CONN_SERVER_STATISTICS));
+}
+
+/*
* __statlog_server --
* The statistics server thread.
*/
@@ -525,10 +530,14 @@ __statlog_server(void *arg)
WT_ERR(__wt_buf_init(session, &path, strlen(conn->stat_path) + 128));
WT_ERR(__wt_buf_init(session, &tmp, strlen(conn->stat_path) + 128));
- while (F_ISSET(conn, WT_CONN_SERVER_RUN) &&
- F_ISSET(conn, WT_CONN_SERVER_STATISTICS)) {
+ for (;;) {
/* Wait until the next event. */
- __wt_cond_wait(session, conn->stat_cond, conn->stat_usecs);
+ __wt_cond_wait(session, conn->stat_cond,
+ conn->stat_usecs, __statlog_server_run_chk);
+
+ /* Check if we're quitting or being reconfigured. */
+ if (!__statlog_server_run_chk(session))
+ break;
if (WT_STAT_ENABLED(session))
WT_ERR(__statlog_log_one(session, &path, &tmp));
@@ -563,7 +572,7 @@ __statlog_start(WT_CONNECTION_IMPL *conn)
session = conn->stat_session;
WT_RET(__wt_cond_alloc(
- session, "statistics log server", false, &conn->stat_cond));
+ session, "statistics log server", &conn->stat_cond));
/*
* Start the thread.
diff --git a/src/conn/conn_sweep.c b/src/conn/conn_sweep.c
index d1254d8afcc..22d90b08438 100644
--- a/src/conn/conn_sweep.c
+++ b/src/conn/conn_sweep.c
@@ -10,7 +10,7 @@
#define WT_DHANDLE_CAN_DISCARD(dhandle) \
(!F_ISSET(dhandle, WT_DHANDLE_EXCLUSIVE | WT_DHANDLE_OPEN) && \
- dhandle->session_inuse == 0 && dhandle->session_ref == 0)
+ (dhandle)->session_inuse == 0 && (dhandle)->session_ref == 0)
/*
* __sweep_mark --
@@ -81,7 +81,7 @@ __sweep_expire_one(WT_SESSION_IMPL *session)
* handle list lock so that connection-level handle searches
* never need to retry.
*/
- WT_RET(__wt_try_writelock(session, dhandle->rwlock));
+ WT_RET(__wt_try_writelock(session, &dhandle->rwlock));
/* Only sweep clean trees where all updates are visible. */
if (btree->modified ||
@@ -95,7 +95,7 @@ __sweep_expire_one(WT_SESSION_IMPL *session)
*/
ret = __wt_conn_btree_sync_and_close(session, false, true);
-err: __wt_writeunlock(session, dhandle->rwlock);
+err: __wt_writeunlock(session, &dhandle->rwlock);
return (ret);
}
@@ -188,7 +188,7 @@ __sweep_remove_one(WT_SESSION_IMPL *session, WT_DATA_HANDLE *dhandle)
WT_DECL_RET;
/* Try to get exclusive access. */
- WT_RET(__wt_try_writelock(session, dhandle->rwlock));
+ WT_RET(__wt_try_writelock(session, &dhandle->rwlock));
/*
* If there are no longer any references to the handle in any
@@ -205,7 +205,7 @@ __sweep_remove_one(WT_SESSION_IMPL *session, WT_DATA_HANDLE *dhandle)
* don't retry the discard until it times out again.
*/
if (ret != 0) {
-err: __wt_writeunlock(session, dhandle->rwlock);
+err: __wt_writeunlock(session, &dhandle->rwlock);
}
return (ret);
@@ -233,7 +233,7 @@ __sweep_remove_handles(WT_SESSION_IMPL *session)
if (!WT_DHANDLE_CAN_DISCARD(dhandle))
continue;
- WT_WITH_HANDLE_LIST_LOCK(session,
+ WT_WITH_HANDLE_LIST_WRITE_LOCK(session,
ret = __sweep_remove_one(session, dhandle));
if (ret == 0)
WT_STAT_CONN_INCR(session, dh_sweep_remove);
@@ -246,6 +246,16 @@ __sweep_remove_handles(WT_SESSION_IMPL *session)
}
/*
+ * __sweep_server_run_chk --
+ * Check to decide if the checkpoint server should continue running.
+ */
+static bool
+__sweep_server_run_chk(WT_SESSION_IMPL *session)
+{
+ return (F_ISSET(S2C(session), WT_CONN_SERVER_SWEEP));
+}
+
+/*
* __sweep_server --
* The handle sweep server thread.
*/
@@ -266,11 +276,15 @@ __sweep_server(void *arg)
/*
* Sweep for dead and excess handles.
*/
- while (F_ISSET(conn, WT_CONN_SERVER_RUN) &&
- F_ISSET(conn, WT_CONN_SERVER_SWEEP)) {
+ for (;;) {
/* Wait until the next event. */
- __wt_cond_wait(session,
- conn->sweep_cond, conn->sweep_interval * WT_MILLION);
+ __wt_cond_wait(session, conn->sweep_cond,
+ conn->sweep_interval * WT_MILLION, __sweep_server_run_chk);
+
+ /* Check if we're quitting or being reconfigured. */
+ if (!__sweep_server_run_chk(session))
+ break;
+
__wt_seconds(session, &now);
WT_STAT_CONN_INCR(session, dh_sweeps);
@@ -390,7 +404,7 @@ __wt_sweep_create(WT_SESSION_IMPL *session)
session = conn->sweep_session;
WT_RET(__wt_cond_alloc(
- session, "handle sweep server", false, &conn->sweep_cond));
+ session, "handle sweep server", &conn->sweep_cond));
WT_RET(__wt_thread_create(
session, &conn->sweep_tid, __sweep_server, session));