summaryrefslogtreecommitdiff
path: root/src/session
diff options
context:
space:
mode:
Diffstat (limited to 'src/session')
-rw-r--r--src/session/session_api.c71
-rw-r--r--src/session/session_compact.c2
-rw-r--r--src/session/session_dhandle.c102
-rw-r--r--src/session/session_salvage.c2
4 files changed, 105 insertions, 72 deletions
diff --git a/src/session/session_api.c b/src/session/session_api.c
index fe1bf821d3b..b7daf0e2e02 100644
--- a/src/session/session_api.c
+++ b/src/session/session_api.c
@@ -128,7 +128,7 @@ __session_clear(WT_SESSION_IMPL *session)
*
* For these reasons, be careful when clearing the session structure.
*/
- memset(session, 0, WT_SESSION_CLEAR_SIZE(session));
+ memset(session, 0, WT_SESSION_CLEAR_SIZE);
WT_INIT_LSN(&session->bg_sync_lsn);
@@ -162,7 +162,7 @@ __session_alter(WT_SESSION *wt_session, const char *uri, const char *config)
cfg[1] = NULL;
WT_WITH_CHECKPOINT_LOCK(session,
WT_WITH_SCHEMA_LOCK(session,
- WT_WITH_TABLE_LOCK(session,
+ WT_WITH_TABLE_WRITE_LOCK(session,
ret = __wt_schema_alter(session, uri, cfg))));
err: if (ret != 0)
@@ -234,9 +234,6 @@ __session_close(WT_SESSION *wt_session, const char *config)
/* Release common session resources. */
WT_TRET(__wt_session_release_resources(session));
- /* Destroy the thread's mutex. */
- WT_TRET(__wt_cond_destroy(session, &session->cond));
-
/* The API lock protects opening and closing of sessions. */
__wt_spin_lock(session, &conn->api_lock);
@@ -521,7 +518,7 @@ __wt_session_create(
WT_DECL_RET;
WT_WITH_SCHEMA_LOCK(session,
- WT_WITH_TABLE_LOCK(session,
+ WT_WITH_TABLE_WRITE_LOCK(session,
ret = __wt_schema_create(session, uri, config)));
return (ret);
}
@@ -769,7 +766,7 @@ __session_rename(WT_SESSION *wt_session,
WT_WITH_CHECKPOINT_LOCK(session,
WT_WITH_SCHEMA_LOCK(session,
- WT_WITH_TABLE_LOCK(session,
+ WT_WITH_TABLE_WRITE_LOCK(session,
ret = __wt_schema_rename(session, uri, newuri, cfg))));
err: if (ret != 0)
@@ -858,21 +855,22 @@ __session_drop(WT_SESSION *wt_session, const char *uri, const char *config)
if (lock_wait)
WT_WITH_CHECKPOINT_LOCK(session,
WT_WITH_SCHEMA_LOCK(session,
- WT_WITH_TABLE_LOCK(session, ret =
+ WT_WITH_TABLE_WRITE_LOCK(session, ret =
__wt_schema_drop(session, uri, cfg))));
else
WT_WITH_CHECKPOINT_LOCK_NOWAIT(session, ret,
WT_WITH_SCHEMA_LOCK_NOWAIT(session, ret,
- WT_WITH_TABLE_LOCK_NOWAIT(session, ret, ret =
+ WT_WITH_TABLE_WRITE_LOCK_NOWAIT(session, ret,
+ ret =
__wt_schema_drop(session, uri, cfg))));
} else {
if (lock_wait)
WT_WITH_SCHEMA_LOCK(session,
- WT_WITH_TABLE_LOCK(session,
+ WT_WITH_TABLE_WRITE_LOCK(session,
ret = __wt_schema_drop(session, uri, cfg)));
else
WT_WITH_SCHEMA_LOCK_NOWAIT(session, ret,
- WT_WITH_TABLE_LOCK_NOWAIT(session, ret,
+ WT_WITH_TABLE_WRITE_LOCK_NOWAIT(session, ret,
ret = __wt_schema_drop(session, uri, cfg)));
}
@@ -1208,10 +1206,15 @@ __wt_session_range_truncate(WT_SESSION_IMPL *session,
done:
err: /*
- * Close any locally-opened start cursor.
+ * Close any locally-opened start cursor. Reset application cursors,
+ * they've possibly moved and the application cannot use them.
*/
if (local_start)
WT_TRET(start->close(start));
+ else
+ WT_TRET(start->reset(start));
+ if (stop != NULL)
+ WT_TRET(stop->reset(stop));
return (ret);
}
@@ -1489,6 +1492,20 @@ err: API_END_RET(session, ret);
}
/*
+ * __transaction_sync_run_chk --
+ * Check to decide if the transaction sync call should continue running.
+ */
+static bool
+__transaction_sync_run_chk(WT_SESSION_IMPL *session)
+{
+ WT_CONNECTION_IMPL *conn;
+
+ conn = S2C(session);
+
+ return (FLD_ISSET(conn->flags, WT_CONN_SERVER_LOG));
+}
+
+/*
* __session_transaction_sync --
* WT_SESSION->transaction_sync method.
*/
@@ -1502,7 +1519,7 @@ __session_transaction_sync(WT_SESSION *wt_session, const char *config)
WT_SESSION_IMPL *session;
WT_TXN *txn;
struct timespec now, start;
- uint64_t timeout_ms, waited_ms;
+ uint64_t remaining_usec, timeout_ms, waited_ms;
bool forever;
session = (WT_SESSION_IMPL *)wt_session;
@@ -1555,22 +1572,20 @@ __session_transaction_sync(WT_SESSION *wt_session, const char *config)
__wt_epoch(session, &start);
/*
* Keep checking the LSNs until we find it is stable or we reach
- * our timeout.
+ * our timeout, or there's some other reason to quit.
*/
while (__wt_log_cmp(&session->bg_sync_lsn, &log->sync_lsn) > 0) {
+ if (!__transaction_sync_run_chk(session))
+ WT_ERR(ETIMEDOUT);
+
__wt_cond_signal(session, conn->log_file_cond);
__wt_epoch(session, &now);
waited_ms = WT_TIMEDIFF_MS(now, start);
- if (forever || waited_ms < timeout_ms)
- /*
- * Note, we will wait an increasing amount of time
- * each iteration, likely doubling. Also note that
- * the function timeout value is in usecs (we are
- * computing the wait time in msecs and passing that
- * in, unchanged, as the usecs to wait).
- */
- __wt_cond_wait(session, log->log_sync_cond, waited_ms);
- else
+ if (forever || waited_ms < timeout_ms) {
+ remaining_usec = (timeout_ms - waited_ms) * WT_THOUSAND;
+ __wt_cond_wait(session, log->log_sync_cond,
+ remaining_usec, __transaction_sync_run_chk);
+ } else
WT_ERR(ETIMEDOUT);
}
@@ -1686,7 +1701,7 @@ __session_snapshot(WT_SESSION *wt_session, const char *config)
WT_ERR(__wt_txn_named_snapshot_config(
session, cfg, &has_create, &has_drop));
- __wt_writelock(session, txn_global->nsnap_rwlock);
+ __wt_writelock(session, &txn_global->nsnap_rwlock);
/* Drop any snapshots to be removed first. */
if (has_drop)
@@ -1696,7 +1711,7 @@ __session_snapshot(WT_SESSION *wt_session, const char *config)
if (has_create)
WT_ERR(__wt_txn_named_snapshot_begin(session, cfg));
-err: __wt_writeunlock(session, txn_global->nsnap_rwlock);
+err: __wt_writeunlock(session, &txn_global->nsnap_rwlock);
API_END_RET_NOTFOUND_MAP(session, ret);
}
@@ -1797,7 +1812,7 @@ __open_session(WT_CONNECTION_IMPL *conn,
* closes the connection. This is particularly intended to catch
* cases where server threads open sessions.
*/
- WT_ASSERT(session, F_ISSET(conn, WT_CONN_SERVER_RUN));
+ WT_ASSERT(session, !F_ISSET(conn, WT_CONN_CLOSING));
/* Find the first inactive session slot. */
for (session_ret = conn->sessions,
@@ -1825,8 +1840,6 @@ __open_session(WT_CONNECTION_IMPL *conn,
session_ret->name = NULL;
session_ret->id = i;
- WT_ERR(__wt_cond_alloc(session, "session", false, &session_ret->cond));
-
if (WT_SESSION_FIRST_USE(session_ret))
__wt_random_init(&session_ret->rnd);
diff --git a/src/session/session_compact.c b/src/session/session_compact.c
index 85214ae6d98..72c072e0fb8 100644
--- a/src/session/session_compact.c
+++ b/src/session/session_compact.c
@@ -210,7 +210,7 @@ __compact_checkpoint(WT_SESSION_IMPL *session)
* work we need to have done is done in the underlying block manager.
*/
const char *checkpoint_cfg[] = {
- WT_CONFIG_BASE(session, WT_SESSION_checkpoint), "force=1", NULL };
+ WT_CONFIG_BASE(session, WT_SESSION_checkpoint), "force=1", NULL };
/* Checkpoints take a lot of time, check if we've run out. */
WT_RET(__wt_session_compact_check_timeout(session));
diff --git a/src/session/session_dhandle.c b/src/session/session_dhandle.c
index 732dc797b6d..95fb6a6f90e 100644
--- a/src/session/session_dhandle.c
+++ b/src/session/session_dhandle.c
@@ -44,8 +44,7 @@ __session_discard_dhandle(
TAILQ_REMOVE(&session->dhandles, dhandle_cache, q);
TAILQ_REMOVE(&session->dhhash[bucket], dhandle_cache, hashq);
- (void)__wt_atomic_sub32(&dhandle_cache->dhandle->session_ref, 1);
-
+ WT_DHANDLE_RELEASE(dhandle_cache->dhandle);
__wt_overwrite_and_free(session, dhandle_cache);
}
@@ -181,17 +180,17 @@ __wt_session_lock_dhandle(
*/
if (F_ISSET(dhandle, WT_DHANDLE_OPEN) &&
(!want_exclusive || lock_busy)) {
- __wt_readlock(session, dhandle->rwlock);
+ __wt_readlock(session, &dhandle->rwlock);
if (F_ISSET(dhandle, WT_DHANDLE_DEAD)) {
*is_deadp = 1;
- __wt_readunlock(session, dhandle->rwlock);
+ __wt_readunlock(session, &dhandle->rwlock);
return (0);
}
is_open = F_ISSET(dhandle, WT_DHANDLE_OPEN);
if (is_open && !want_exclusive)
return (0);
- __wt_readunlock(session, dhandle->rwlock);
+ __wt_readunlock(session, &dhandle->rwlock);
} else
is_open = false;
@@ -201,10 +200,11 @@ __wt_session_lock_dhandle(
* with another thread that successfully opens the file, we
* don't want to block waiting to get exclusive access.
*/
- if ((ret = __wt_try_writelock(session, dhandle->rwlock)) == 0) {
+ if ((ret =
+ __wt_try_writelock(session, &dhandle->rwlock)) == 0) {
if (F_ISSET(dhandle, WT_DHANDLE_DEAD)) {
*is_deadp = 1;
- __wt_writeunlock(session, dhandle->rwlock);
+ __wt_writeunlock(session, &dhandle->rwlock);
return (0);
}
@@ -215,7 +215,7 @@ __wt_session_lock_dhandle(
if (F_ISSET(dhandle, WT_DHANDLE_OPEN) &&
!want_exclusive) {
lock_busy = false;
- __wt_writeunlock(session, dhandle->rwlock);
+ __wt_writeunlock(session, &dhandle->rwlock);
continue;
}
@@ -270,6 +270,16 @@ __wt_session_release_btree(WT_SESSION_IMPL *session)
if (F_ISSET(dhandle, WT_DHANDLE_DISCARD_FORCE)) {
ret = __wt_conn_btree_sync_and_close(session, false, true);
F_CLR(dhandle, WT_DHANDLE_DISCARD_FORCE);
+ } else if (F_ISSET(btree, WT_BTREE_BULK)) {
+ WT_ASSERT(session, F_ISSET(dhandle, WT_DHANDLE_EXCLUSIVE) &&
+ !F_ISSET(dhandle, WT_DHANDLE_DISCARD));
+ /*
+ * Acquire the schema lock while completing a bulk load. This
+ * avoids racing with a checkpoint while it gathers a set
+ * of handles.
+ */
+ WT_WITH_SCHEMA_LOCK(session, ret =
+ __wt_conn_btree_sync_and_close(session, false, false));
} else if (F_ISSET(dhandle, WT_DHANDLE_DISCARD) ||
F_ISSET(btree, WT_BTREE_SPECIAL_FLAGS)) {
WT_ASSERT(session, F_ISSET(dhandle, WT_DHANDLE_EXCLUSIVE));
@@ -286,9 +296,9 @@ __wt_session_release_btree(WT_SESSION_IMPL *session)
if (locked) {
if (write_locked) {
F_CLR(dhandle, WT_DHANDLE_EXCLUSIVE);
- __wt_writeunlock(session, dhandle->rwlock);
+ __wt_writeunlock(session, &dhandle->rwlock);
} else
- __wt_readunlock(session, dhandle->rwlock);
+ __wt_readunlock(session, &dhandle->rwlock);
}
session->dhandle = NULL;
@@ -411,17 +421,27 @@ __session_dhandle_sweep(WT_SESSION_IMPL *session)
/*
* __session_find_shared_dhandle --
* Search for a data handle in the connection and add it to a session's
- * cache. Since the data handle isn't locked, this must be called holding
- * the handle list lock, and we must increment the handle's reference
- * count before releasing it.
+ * cache. We must increment the handle's reference count while holding
+ * the handle list lock.
*/
static int
__session_find_shared_dhandle(
WT_SESSION_IMPL *session, const char *uri, const char *checkpoint)
{
- WT_RET(__wt_conn_dhandle_find(session, uri, checkpoint));
- (void)__wt_atomic_add32(&session->dhandle->session_ref, 1);
- return (0);
+ WT_DECL_RET;
+
+ WT_WITH_HANDLE_LIST_READ_LOCK(session,
+ if ((ret = __wt_conn_dhandle_find(session, uri, checkpoint)) == 0)
+ WT_DHANDLE_ACQUIRE(session->dhandle));
+
+ if (ret != WT_NOTFOUND)
+ return (ret);
+
+ WT_WITH_HANDLE_LIST_WRITE_LOCK(session,
+ if ((ret = __wt_conn_dhandle_alloc(session, uri, checkpoint)) == 0)
+ WT_DHANDLE_ACQUIRE(session->dhandle));
+
+ return (ret);
}
/*
@@ -449,16 +469,16 @@ __session_get_dhandle(
* We didn't find a match in the session cache, search the shared
* handle list and cache the handle we find.
*/
- WT_WITH_HANDLE_LIST_LOCK(session,
- ret = __session_find_shared_dhandle(session, uri, checkpoint));
- WT_RET(ret);
+ WT_RET(__session_find_shared_dhandle(session, uri, checkpoint));
/*
* Fixup the reference count on failure (we incremented the reference
* count while holding the handle-list lock).
*/
- if ((ret = __session_add_dhandle(session)) != 0)
- (void)__wt_atomic_sub32(&session->dhandle->session_ref, 1);
+ if ((ret = __session_add_dhandle(session)) != 0) {
+ WT_DHANDLE_RELEASE(session->dhandle);
+ session->dhandle = NULL;
+ }
return (ret);
}
@@ -504,17 +524,15 @@ __wt_session_get_btree(WT_SESSION_IMPL *session,
* reopen handles in the meantime. A combination of the schema
* and handle list locks are used to enforce this.
*/
- if (!F_ISSET(session, WT_SESSION_LOCKED_SCHEMA) ||
- !F_ISSET(session, WT_SESSION_LOCKED_HANDLE_LIST)) {
+ if (!F_ISSET(session, WT_SESSION_LOCKED_SCHEMA)) {
dhandle->excl_session = NULL;
dhandle->excl_ref = 0;
F_CLR(dhandle, WT_DHANDLE_EXCLUSIVE);
- __wt_writeunlock(session, dhandle->rwlock);
+ __wt_writeunlock(session, &dhandle->rwlock);
WT_WITH_SCHEMA_LOCK(session,
- WT_WITH_HANDLE_LIST_LOCK(session,
- ret = __wt_session_get_btree(
- session, uri, checkpoint, cfg, flags)));
+ ret = __wt_session_get_btree(
+ session, uri, checkpoint, cfg, flags));
return (ret);
}
@@ -531,7 +549,7 @@ __wt_session_get_btree(WT_SESSION_IMPL *session,
dhandle->excl_session = NULL;
dhandle->excl_ref = 0;
F_CLR(dhandle, WT_DHANDLE_EXCLUSIVE);
- __wt_writeunlock(session, dhandle->rwlock);
+ __wt_writeunlock(session, &dhandle->rwlock);
WT_RET(ret);
}
@@ -552,7 +570,7 @@ __wt_session_get_btree(WT_SESSION_IMPL *session,
int
__wt_session_lock_checkpoint(WT_SESSION_IMPL *session, const char *checkpoint)
{
- WT_DATA_HANDLE *dhandle, *saved_dhandle;
+ WT_DATA_HANDLE *saved_dhandle;
WT_DECL_RET;
WT_ASSERT(session, WT_META_TRACKING(session));
@@ -560,31 +578,33 @@ __wt_session_lock_checkpoint(WT_SESSION_IMPL *session, const char *checkpoint)
/*
* Get the checkpoint handle exclusive, so no one else can access it
- * while we are creating the new checkpoint.
+ * while we are creating the new checkpoint. Hold the lock until the
+ * checkpoint completes.
*/
WT_ERR(__wt_session_get_btree(session, saved_dhandle->name,
checkpoint, NULL, WT_DHANDLE_EXCLUSIVE | WT_DHANDLE_LOCK_ONLY));
+ if ((ret = __wt_meta_track_handle_lock(session, false)) != 0) {
+ WT_TRET(__wt_session_release_btree(session));
+ goto err;
+ }
/*
- * Flush any pages in this checkpoint from the cache (we are about to
- * re-write the checkpoint which will mean cached pages no longer have
- * valid contents). This is especially noticeable with memory mapped
- * files, since changes to the underlying file are visible to the in
- * memory pages.
+ * Get exclusive access to the handle and then flush any pages in this
+ * checkpoint from the cache (we are about to re-write the checkpoint
+ * which will mean cached pages no longer have valid contents). This
+ * is especially noticeable with memory mapped files, since changes to
+ * 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));
/*
* We lock checkpoint handles that we are overwriting, so the handle
* must be closed when we release it.
*/
- dhandle = session->dhandle;
- F_SET(dhandle, WT_DHANDLE_DISCARD);
-
- WT_ERR(__wt_meta_track_handle_lock(session, false));
+ F_SET(session->dhandle, WT_DHANDLE_DISCARD);
- /* Restore the original btree in the session. */
+ /* Restore the original data handle in the session. */
err: session->dhandle = saved_dhandle;
-
return (ret);
}
diff --git a/src/session/session_salvage.c b/src/session/session_salvage.c
index 983b28dd8ea..12ce71cdbb0 100644
--- a/src/session/session_salvage.c
+++ b/src/session/session_salvage.c
@@ -54,6 +54,6 @@ __wt_salvage(WT_SESSION_IMPL *session, const char *cfg[])
WT_ERR(__wt_meta_ckptlist_set(
session, dhandle->name, ckptbase, NULL));
-err: __wt_meta_ckptlist_free(session, ckptbase);
+err: __wt_meta_ckptlist_free(session, &ckptbase);
return (ret);
}