summaryrefslogtreecommitdiff
path: root/src/conn/conn_dhandle.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/conn/conn_dhandle.c')
-rw-r--r--src/conn/conn_dhandle.c196
1 files changed, 56 insertions, 140 deletions
diff --git a/src/conn/conn_dhandle.c b/src/conn/conn_dhandle.c
index 60136a71b99..5019ab59fe3 100644
--- a/src/conn/conn_dhandle.c
+++ b/src/conn/conn_dhandle.c
@@ -129,7 +129,7 @@ __wt_conn_btree_sync_and_close(WT_SESSION_IMPL *session, bool final, bool force)
WT_BTREE *btree;
WT_DATA_HANDLE *dhandle;
WT_DECL_RET;
- bool evict_reset, marked_dead, no_schema_lock;
+ bool marked_dead, no_schema_lock;
btree = S2BT(session);
bm = btree->bm;
@@ -139,8 +139,8 @@ __wt_conn_btree_sync_and_close(WT_SESSION_IMPL *session, bool final, bool force)
if (!F_ISSET(dhandle, WT_DHANDLE_OPEN))
return (0);
- /* Ensure that we aren't racing with the eviction server */
- WT_RET(__wt_evict_file_exclusive_on(session, &evict_reset));
+ /* Turn off eviction. */
+ WT_RET(__wt_evict_file_exclusive_on(session));
/*
* If we don't already have the schema lock, make it an error to try
@@ -176,23 +176,19 @@ __wt_conn_btree_sync_and_close(WT_SESSION_IMPL *session, bool final, bool force)
WT_BTREE_SALVAGE | WT_BTREE_UPGRADE | WT_BTREE_VERIFY)) {
if (force && (bm == NULL || !bm->is_mapped(bm, session))) {
F_SET(session->dhandle, WT_DHANDLE_DEAD);
+ marked_dead = true;
- /*
- * Reset the tree's eviction priority, and the tree is
- * evictable by definition.
- */
+ /* Reset the tree's eviction priority (if any). */
__wt_evict_priority_clear(session);
- F_CLR(S2BT(session), WT_BTREE_NO_EVICTION);
-
- marked_dead = true;
}
if (!marked_dead || final)
WT_ERR(__wt_checkpoint_close(session, final));
}
WT_TRET(__wt_btree_close(session));
+
/*
- * If we marked a handle as dead it will be closed by sweep, via
+ * If we marked a handle dead it will be closed by sweep, via
* another call to sync and close.
*/
if (!marked_dead) {
@@ -206,12 +202,11 @@ __wt_conn_btree_sync_and_close(WT_SESSION_IMPL *session, bool final, bool force)
err: __wt_spin_unlock(session, &dhandle->close_lock);
- if (evict_reset)
- __wt_evict_file_exclusive_off(session);
-
if (no_schema_lock)
F_CLR(session, WT_SESSION_NO_SCHEMA_LOCK);
+ __wt_evict_file_exclusive_off(session);
+
return (ret);
}
@@ -355,42 +350,52 @@ err: F_CLR(btree, WT_BTREE_SPECIAL_FLAGS);
/*
* __conn_btree_apply_internal --
- * Apply a function to the open btree handles.
+ * Apply a function to an open data handle.
*/
static int
__conn_btree_apply_internal(WT_SESSION_IMPL *session, WT_DATA_HANDLE *dhandle,
- int (*func)(WT_SESSION_IMPL *, const char *[]), const char *cfg[])
+ int (*file_func)(WT_SESSION_IMPL *, const char *[]),
+ int (*name_func)(WT_SESSION_IMPL *, const char *, bool *),
+ const char *cfg[])
{
WT_DECL_RET;
+ bool skip;
+
+ /* Always apply the name function, if supplied. */
+ skip = false;
+ if (name_func != NULL)
+ WT_RET(name_func(session, dhandle->name, &skip));
+
+ /* If there is no file function, don't bother locking the handle */
+ if (file_func == NULL || skip)
+ return (0);
/*
* We need to pull the handle into the session handle cache and make
* sure it's referenced to stop other internal code dropping the handle
* (e.g in LSM when cleaning up obsolete chunks).
*/
- ret = __wt_session_get_btree(session,
- dhandle->name, dhandle->checkpoint, NULL, 0);
- if (ret == 0) {
- WT_SAVE_DHANDLE(session,
- ret = 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));
- } else if (ret == EBUSY)
- ret = __wt_conn_btree_apply_single(session, dhandle->name,
- dhandle->checkpoint, func, cfg);
+ if ((ret = __wt_session_get_btree(session,
+ dhandle->name, dhandle->checkpoint, NULL, 0)) != 0)
+ 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));
return (ret);
}
/*
* __wt_conn_btree_apply --
- * Apply a function to all open btree handles apart from the metadata.
+ * Apply a function to all open btree handles with the given URI.
*/
int
-__wt_conn_btree_apply(WT_SESSION_IMPL *session,
- bool apply_checkpoints, const char *uri,
- int (*func)(WT_SESSION_IMPL *, const char *[]), const char *cfg[])
+__wt_conn_btree_apply(WT_SESSION_IMPL *session, const char *uri,
+ int (*file_func)(WT_SESSION_IMPL *, const char *[]),
+ int (*name_func)(WT_SESSION_IMPL *, const char *, bool *),
+ const char *cfg[])
{
WT_CONNECTION_IMPL *conn;
WT_DATA_HANDLE *dhandle;
@@ -407,116 +412,27 @@ __wt_conn_btree_apply(WT_SESSION_IMPL *session,
if (uri != NULL) {
bucket =
__wt_hash_city64(uri, strlen(uri)) % WT_HASH_ARRAY_SIZE;
- TAILQ_FOREACH(dhandle, &conn->dhhash[bucket], hashq)
- if (F_ISSET(dhandle, WT_DHANDLE_OPEN) &&
- !F_ISSET(dhandle, WT_DHANDLE_DEAD) &&
- strcmp(uri, dhandle->name) == 0 &&
- (apply_checkpoints || dhandle->checkpoint == NULL))
- WT_RET(__conn_btree_apply_internal(
- session, dhandle, func, cfg));
+ TAILQ_FOREACH(dhandle, &conn->dhhash[bucket], hashq) {
+ 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));
+ }
} else {
- TAILQ_FOREACH(dhandle, &conn->dhqh, q)
- if (F_ISSET(dhandle, WT_DHANDLE_OPEN) &&
- !F_ISSET(dhandle, WT_DHANDLE_DEAD) &&
- (apply_checkpoints ||
- dhandle->checkpoint == NULL) &&
- WT_PREFIX_MATCH(dhandle->name, "file:") &&
- !WT_IS_METADATA(session, dhandle))
- WT_RET(__conn_btree_apply_internal(
- session, dhandle, func, cfg));
- }
-
- return (0);
-}
-
-/*
- * __wt_conn_btree_apply_single_ckpt --
- * Decode any checkpoint information from the configuration string then
- * call btree apply single.
- */
-int
-__wt_conn_btree_apply_single_ckpt(WT_SESSION_IMPL *session,
- const char *uri,
- int (*func)(WT_SESSION_IMPL *, const char *[]), const char *cfg[])
-{
- WT_CONFIG_ITEM cval;
- WT_DECL_RET;
- const char *checkpoint;
-
- checkpoint = NULL;
-
- /*
- * This function exists to handle checkpoint configuration. Callers
- * that never open a checkpoint call the underlying function directly.
- */
- WT_RET_NOTFOUND_OK(
- __wt_config_gets_def(session, cfg, "checkpoint", 0, &cval));
- if (cval.len != 0) {
- /*
- * The internal checkpoint name is special, find the last
- * unnamed checkpoint of the object.
- */
- if (WT_STRING_MATCH(WT_CHECKPOINT, cval.str, cval.len)) {
- WT_RET(__wt_meta_checkpoint_last_name(
- session, uri, &checkpoint));
- } else
- WT_RET(__wt_strndup(
- session, cval.str, cval.len, &checkpoint));
- }
-
- ret = __wt_conn_btree_apply_single(session, uri, checkpoint, func, cfg);
-
- __wt_free(session, checkpoint);
-
- return (ret);
-}
-
-/*
- * __wt_conn_btree_apply_single --
- * Apply a function to a single btree handle that couldn't be locked
- * (attempting to get the handle returned EBUSY).
- */
-int
-__wt_conn_btree_apply_single(WT_SESSION_IMPL *session,
- const char *uri, const char *checkpoint,
- int (*func)(WT_SESSION_IMPL *, const char *[]), const char *cfg[])
-{
- WT_CONNECTION_IMPL *conn;
- WT_DATA_HANDLE *dhandle;
- WT_DECL_RET;
- uint64_t bucket, hash;
-
- conn = S2C(session);
-
- WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_HANDLE_LIST));
-
- hash = __wt_hash_city64(uri, strlen(uri));
- bucket = hash % WT_HASH_ARRAY_SIZE;
- TAILQ_FOREACH(dhandle, &conn->dhhash[bucket], hashq)
- if (F_ISSET(dhandle, WT_DHANDLE_OPEN) &&
- !F_ISSET(dhandle, WT_DHANDLE_DEAD) &&
- (hash == dhandle->name_hash &&
- strcmp(uri, dhandle->name) == 0) &&
- ((dhandle->checkpoint == NULL && checkpoint == NULL) ||
- (dhandle->checkpoint != NULL && checkpoint != NULL &&
- strcmp(dhandle->checkpoint, checkpoint) == 0))) {
- /*
- * We're holding the handle list lock which locks out
- * handle open (which might change the state of the
- * underlying object). However, closing a handle
- * doesn't require the handle list lock, lock out
- * closing the handle and then confirm the handle is
- * still open.
- */
- __wt_spin_lock(session, &dhandle->close_lock);
- if (F_ISSET(dhandle, WT_DHANDLE_OPEN) &&
- !F_ISSET(dhandle, WT_DHANDLE_DEAD)) {
- WT_WITH_DHANDLE(session, dhandle,
- ret = func(session, cfg));
- }
- __wt_spin_unlock(session, &dhandle->close_lock);
- WT_RET(ret);
+ TAILQ_FOREACH(dhandle, &conn->dhqh, q) {
+ 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(session, dhandle))
+ continue;
+ WT_RET(__conn_btree_apply_internal(
+ session, dhandle, file_func, name_func, cfg));
}
+ }
return (0);
}