summaryrefslogtreecommitdiff
path: root/src/session
diff options
context:
space:
mode:
authorDavid Hows <david.hows@mongodb.com>2017-01-06 12:12:50 +1100
committerDavid Hows <david.hows@mongodb.com>2017-01-06 12:12:50 +1100
commitd48181f6f4db08761ed7b80b0332908b272ad0d0 (patch)
tree38929fdcc5415ee7b001b6f1a406bd5bd777b737 /src/session
parent040e3d6f764c0fb626cb47fede54469f57d0c6e0 (diff)
parent8d2324943364286056ae399043f70b8a937de312 (diff)
Merge branch 'mongodb-3.6' into mongodb-3.2mongodb-3.2.12
Diffstat (limited to 'src/session')
-rw-r--r--src/session/session_api.c169
-rw-r--r--src/session/session_compact.c246
-rw-r--r--src/session/session_dhandle.c2
3 files changed, 253 insertions, 164 deletions
diff --git a/src/session/session_api.c b/src/session/session_api.c
index 00c2852649f..fe1bf821d3b 100644
--- a/src/session/session_api.c
+++ b/src/session/session_api.c
@@ -58,7 +58,6 @@ int
__wt_session_copy_values(WT_SESSION_IMPL *session)
{
WT_CURSOR *cursor;
- WT_DECL_RET;
TAILQ_FOREACH(cursor, &session->cursors, q)
if (F_ISSET(cursor, WT_CURSTD_VALUE_INT)) {
@@ -80,7 +79,7 @@ __wt_session_copy_values(WT_SESSION_IMPL *session)
F_SET(cursor, WT_CURSTD_VALUE_EXT);
}
- return (ret);
+ return (0);
}
/*
@@ -130,9 +129,47 @@ __session_clear(WT_SESSION_IMPL *session)
* For these reasons, be careful when clearing the session structure.
*/
memset(session, 0, WT_SESSION_CLEAR_SIZE(session));
- session->hazard_size = 0;
- session->nhazard = 0;
+
WT_INIT_LSN(&session->bg_sync_lsn);
+
+ session->hazard_inuse = 0;
+ session->nhazard = 0;
+}
+
+/*
+ * __session_alter --
+ * Alter a table setting.
+ */
+static int
+__session_alter(WT_SESSION *wt_session, const char *uri, const char *config)
+{
+ WT_DECL_RET;
+ WT_SESSION_IMPL *session;
+
+ session = (WT_SESSION_IMPL *)wt_session;
+
+ SESSION_API_CALL(session, alter, config, cfg);
+
+ /* Disallow objects in the WiredTiger name space. */
+ WT_ERR(__wt_str_name_check(session, uri));
+
+ /*
+ * We replace the default configuration listing with the current
+ * configuration. Otherwise the defaults for values that can be
+ * altered would override settings used by the user in create.
+ */
+ cfg[0] = cfg[1];
+ cfg[1] = NULL;
+ WT_WITH_CHECKPOINT_LOCK(session,
+ WT_WITH_SCHEMA_LOCK(session,
+ WT_WITH_TABLE_LOCK(session,
+ ret = __wt_schema_alter(session, uri, cfg))));
+
+err: if (ret != 0)
+ WT_STAT_CONN_INCR(session, session_table_alter_fail);
+ else
+ WT_STAT_CONN_INCR(session, session_table_alter_success);
+ API_END_RET_NOTFOUND_MAP(session, ret);
}
/*
@@ -483,8 +520,8 @@ __wt_session_create(
{
WT_DECL_RET;
- WT_WITH_SCHEMA_LOCK(session, ret,
- WT_WITH_TABLE_LOCK(session, ret,
+ WT_WITH_SCHEMA_LOCK(session,
+ WT_WITH_TABLE_LOCK(session,
ret = __wt_schema_create(session, uri, config)));
return (ret);
}
@@ -677,8 +714,8 @@ __session_rebalance(WT_SESSION *wt_session, const char *uri, const char *config)
SESSION_API_CALL(session, rebalance, config, cfg);
/* Block out checkpoints to avoid spurious EBUSY errors. */
- WT_WITH_CHECKPOINT_LOCK(session, ret,
- WT_WITH_SCHEMA_LOCK(session, ret,
+ WT_WITH_CHECKPOINT_LOCK(session,
+ WT_WITH_SCHEMA_LOCK(session,
ret = __wt_schema_worker(session, uri, __wt_bt_rebalance,
NULL, cfg, WT_DHANDLE_EXCLUSIVE | WT_BTREE_REBALANCE)));
@@ -730,9 +767,9 @@ __session_rename(WT_SESSION *wt_session,
WT_ERR(__wt_str_name_check(session, uri));
WT_ERR(__wt_str_name_check(session, newuri));
- WT_WITH_CHECKPOINT_LOCK(session, ret,
- WT_WITH_SCHEMA_LOCK(session, ret,
- WT_WITH_TABLE_LOCK(session, ret,
+ WT_WITH_CHECKPOINT_LOCK(session,
+ WT_WITH_SCHEMA_LOCK(session,
+ WT_WITH_TABLE_LOCK(session,
ret = __wt_schema_rename(session, uri, newuri, cfg))));
err: if (ret != 0)
@@ -791,53 +828,16 @@ err: API_END_RET_NOTFOUND_MAP(session, ret);
}
/*
- * __wt_session_drop --
- * Internal version of WT_SESSION::drop.
- */
-int
-__wt_session_drop(WT_SESSION_IMPL *session, const char *uri, const char *cfg[])
-{
- WT_DECL_RET;
- WT_CONFIG_ITEM cval;
- bool checkpoint_wait, lock_wait;
-
- WT_RET(__wt_config_gets_def(session, cfg, "checkpoint_wait", 1, &cval));
- checkpoint_wait = cval.val != 0;
- WT_RET(__wt_config_gets_def(session, cfg, "lock_wait", 1, &cval));
- lock_wait = cval.val != 0 || F_ISSET(session, WT_SESSION_LOCK_NO_WAIT);
-
- if (!lock_wait)
- F_SET(session, WT_SESSION_LOCK_NO_WAIT);
-
- /*
- * Take the checkpoint lock if there is a need to prevent the drop
- * operation from failing with EBUSY due to an ongoing checkpoint.
- */
- if (checkpoint_wait)
- WT_WITH_CHECKPOINT_LOCK(session, ret,
- WT_WITH_SCHEMA_LOCK(session, ret,
- WT_WITH_TABLE_LOCK(session, ret,
- ret = __wt_schema_drop(session, uri, cfg))));
- else
- WT_WITH_SCHEMA_LOCK(session, ret,
- WT_WITH_TABLE_LOCK(session, ret,
- ret = __wt_schema_drop(session, uri, cfg)));
-
- if (!lock_wait)
- F_CLR(session, WT_SESSION_LOCK_NO_WAIT);
-
- return (ret);
-}
-
-/*
* __session_drop --
* WT_SESSION->drop method.
*/
static int
__session_drop(WT_SESSION *wt_session, const char *uri, const char *config)
{
+ WT_CONFIG_ITEM cval;
WT_DECL_RET;
WT_SESSION_IMPL *session;
+ bool checkpoint_wait, lock_wait;
session = (WT_SESSION_IMPL *)wt_session;
SESSION_API_CALL(session, drop, config, cfg);
@@ -845,7 +845,36 @@ __session_drop(WT_SESSION *wt_session, const char *uri, const char *config)
/* Disallow objects in the WiredTiger name space. */
WT_ERR(__wt_str_name_check(session, uri));
- ret = __wt_session_drop(session, uri, cfg);
+ WT_ERR(__wt_config_gets_def(session, cfg, "checkpoint_wait", 1, &cval));
+ checkpoint_wait = cval.val != 0;
+ WT_ERR(__wt_config_gets_def(session, cfg, "lock_wait", 1, &cval));
+ lock_wait = cval.val != 0;
+
+ /*
+ * Take the checkpoint lock if there is a need to prevent the drop
+ * operation from failing with EBUSY due to an ongoing checkpoint.
+ */
+ if (checkpoint_wait) {
+ if (lock_wait)
+ WT_WITH_CHECKPOINT_LOCK(session,
+ WT_WITH_SCHEMA_LOCK(session,
+ WT_WITH_TABLE_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_schema_drop(session, uri, cfg))));
+ } else {
+ if (lock_wait)
+ WT_WITH_SCHEMA_LOCK(session,
+ WT_WITH_TABLE_LOCK(session,
+ ret = __wt_schema_drop(session, uri, cfg)));
+ else
+ WT_WITH_SCHEMA_LOCK_NOWAIT(session, ret,
+ WT_WITH_TABLE_LOCK_NOWAIT(session, ret,
+ ret = __wt_schema_drop(session, uri, cfg)));
+ }
err: if (ret != 0)
WT_STAT_CONN_INCR(session, session_table_drop_fail);
@@ -1036,8 +1065,8 @@ __session_salvage(WT_SESSION *wt_session, const char *uri, const char *config)
"configurations");
/* Block out checkpoints to avoid spurious EBUSY errors. */
- WT_WITH_CHECKPOINT_LOCK(session, ret,
- WT_WITH_SCHEMA_LOCK(session, ret,
+ WT_WITH_CHECKPOINT_LOCK(session,
+ WT_WITH_SCHEMA_LOCK(session,
ret = __wt_schema_worker(session, uri, __wt_salvage,
NULL, cfg, WT_DHANDLE_EXCLUSIVE | WT_BTREE_SALVAGE)));
@@ -1237,8 +1266,8 @@ __session_truncate(WT_SESSION *wt_session,
session, uri, start, stop));
else
/* Wait for checkpoints to avoid EBUSY errors. */
- WT_WITH_CHECKPOINT_LOCK(session, ret,
- WT_WITH_SCHEMA_LOCK(session, ret,
+ WT_WITH_CHECKPOINT_LOCK(session,
+ WT_WITH_SCHEMA_LOCK(session,
ret = __wt_schema_truncate(session, uri, cfg)));
} else
WT_ERR(__wt_session_range_truncate(session, uri, start, stop));
@@ -1293,8 +1322,8 @@ __session_upgrade(WT_SESSION *wt_session, const char *uri, const char *config)
SESSION_API_CALL(session, upgrade, config, cfg);
/* Block out checkpoints to avoid spurious EBUSY errors. */
- WT_WITH_CHECKPOINT_LOCK(session, ret,
- WT_WITH_SCHEMA_LOCK(session, ret,
+ WT_WITH_CHECKPOINT_LOCK(session,
+ WT_WITH_SCHEMA_LOCK(session,
ret = __wt_schema_worker(session, uri, __wt_upgrade,
NULL, cfg, WT_DHANDLE_EXCLUSIVE | WT_BTREE_UPGRADE)));
@@ -1342,8 +1371,8 @@ __session_verify(WT_SESSION *wt_session, const char *uri, const char *config)
"configurations");
/* Block out checkpoints to avoid spurious EBUSY errors. */
- WT_WITH_CHECKPOINT_LOCK(session, ret,
- WT_WITH_SCHEMA_LOCK(session, ret,
+ WT_WITH_CHECKPOINT_LOCK(session,
+ WT_WITH_SCHEMA_LOCK(session,
ret = __wt_schema_worker(session, uri, __wt_verify,
NULL, cfg, WT_DHANDLE_EXCLUSIVE | WT_BTREE_VERIFY)));
@@ -1606,7 +1635,7 @@ __session_checkpoint(WT_SESSION *wt_session, const char *config)
WT_ERR_MSG(session, EINVAL,
"Checkpoint not permitted in a transaction");
- ret = __wt_txn_checkpoint(session, cfg);
+ ret = __wt_txn_checkpoint(session, cfg, true);
/*
* Release common session resources (for example, checkpoint may acquire
@@ -1698,6 +1727,7 @@ __open_session(WT_CONNECTION_IMPL *conn,
static const WT_SESSION stds = {
NULL,
NULL,
+ __session_alter,
__session_close,
__session_reconfigure,
__wt_session_strerror,
@@ -1725,6 +1755,7 @@ __open_session(WT_CONNECTION_IMPL *conn,
}, stds_readonly = {
NULL,
NULL,
+ __session_alter,
__session_close,
__session_reconfigure,
__wt_session_strerror,
@@ -1828,17 +1859,13 @@ __open_session(WT_CONNECTION_IMPL *conn,
* session close because access to it isn't serialized. Allocate the
* first time we open this session.
*/
- if (WT_SESSION_FIRST_USE(session_ret))
- WT_ERR(__wt_calloc_def(
- session, conn->hazard_max, &session_ret->hazard));
-
- /*
- * Set an initial size for the hazard array. It will be grown as
- * required up to hazard_max. The hazard_size is reset on close, since
- * __wt_hazard_close ensures the array is cleared - so it is safe to
- * reset the starting size on each open.
- */
- session_ret->hazard_size = 0;
+ if (WT_SESSION_FIRST_USE(session_ret)) {
+ WT_ERR(__wt_calloc_def(session,
+ WT_SESSION_INITIAL_HAZARD_SLOTS, &session_ret->hazard));
+ session_ret->hazard_size = WT_SESSION_INITIAL_HAZARD_SLOTS;
+ session_ret->hazard_inuse = 0;
+ session_ret->nhazard = 0;
+ }
/* Cache the offset of this session's statistics bucket. */
session_ret->stat_bucket = WT_STATS_SLOT_ID(session);
diff --git a/src/session/session_compact.c b/src/session/session_compact.c
index 66635007723..85214ae6d98 100644
--- a/src/session/session_compact.c
+++ b/src/session/session_compact.c
@@ -53,11 +53,14 @@
* blocks, it can't easily know this is the case, and so we'll waste a lot of
* effort trying to compact files that can't be compacted.
*
- * Now, to the actual process. First, we checkpoint the high-level object
- * (which is potentially composed of multiple files): there are potentially
- * many dirty blocks in the cache, and we want to write them out and then
- * discard previous checkpoints so we have as many blocks as possible on the
- * file's "available for reuse" list when we start compaction.
+ * Finally, compaction checkpoints are database-wide, otherwise we can corrupt
+ * file relationships, for example, an index checkpointed by compaction could
+ * be out of sync with the primary after a crash.
+ *
+ * Now, to the actual process. First, we checkpoint the database: there are
+ * potentially many dirty blocks in the cache, and we want to write them out
+ * and then discard previous checkpoints so we have as many blocks as possible
+ * on the file's "available for reuse" list when we start compaction.
*
* Then, we compact the high-level object.
*
@@ -97,29 +100,6 @@
*/
/*
- * __compact_uri_analyze --
- * Extract information relevant to deciding what work compact needs to
- * do from a URI that is part of a table schema.
- * Called via the schema_worker function.
- */
-static int
-__compact_uri_analyze(WT_SESSION_IMPL *session, const char *uri, bool *skipp)
-{
- /*
- * Add references to schema URI objects to the list of objects to be
- * compacted. Skip over LSM trees or we will get false positives on
- * the "file:" URIs for the chunks.
- */
- if (WT_PREFIX_MATCH(uri, "lsm:")) {
- session->compact->lsm_count++;
- *skipp = true;
- } else if (WT_PREFIX_MATCH(uri, "file:"))
- session->compact->file_count++;
-
- return (0);
-}
-
-/*
* __compact_start --
* Start object compaction.
*/
@@ -146,6 +126,29 @@ __compact_end(WT_SESSION_IMPL *session)
}
/*
+ * __compact_uri_analyze --
+ * Extract information relevant to deciding what work compact needs to
+ * do from a URI that is part of a table schema.
+ * Called via the schema_worker function.
+ */
+static int
+__compact_uri_analyze(WT_SESSION_IMPL *session, const char *uri, bool *skipp)
+{
+ /*
+ * Add references to schema URI objects to the list of objects to be
+ * compacted. Skip over LSM trees or we will get false positives on
+ * the "file:" URIs for the chunks.
+ */
+ if (WT_PREFIX_MATCH(uri, "lsm:")) {
+ session->compact->lsm_count++;
+ *skipp = true;
+ } else if (WT_PREFIX_MATCH(uri, "file:"))
+ session->compact->file_count++;
+
+ return (0);
+}
+
+/*
* __compact_handle_append --
* Gather a file handle to be compacted.
* Called via the schema_worker function.
@@ -157,10 +160,6 @@ __compact_handle_append(WT_SESSION_IMPL *session, const char *cfg[])
WT_UNUSED(cfg);
- /* Make sure there is space for the next entry. */
- WT_RET(__wt_realloc_def(session, &session->op_handle_allocated,
- session->op_handle_next + 1, &session->op_handle));
-
WT_RET(__wt_session_get_btree(
session, session->dhandle->name, NULL, NULL, 0));
@@ -170,16 +169,20 @@ __compact_handle_append(WT_SESSION_IMPL *session, const char *cfg[])
return (ret);
}
+ /* Make sure there is space for the next entry. */
+ WT_RET(__wt_realloc_def(session, &session->op_handle_allocated,
+ session->op_handle_next + 1, &session->op_handle));
+
session->op_handle[session->op_handle_next++] = session->dhandle;
return (0);
}
/*
- * __session_compact_check_timeout --
+ * __wt_session_compact_check_timeout --
* Check if the timeout has been exceeded.
*/
-static int
-__session_compact_check_timeout(WT_SESSION_IMPL *session, struct timespec begin)
+int
+__wt_session_compact_check_timeout(WT_SESSION_IMPL *session)
{
struct timespec end;
@@ -187,64 +190,116 @@ __session_compact_check_timeout(WT_SESSION_IMPL *session, struct timespec begin)
return (0);
__wt_epoch(session, &end);
- if (session->compact->max_time < WT_TIMEDIFF_SEC(end, begin))
- return (ETIMEDOUT);
- return (0);
+ return (session->compact->max_time >
+ WT_TIMEDIFF_SEC(end, session->compact->begin) ? 0 : ETIMEDOUT);
}
/*
- * __compact_file --
- * Function to alternate between checkpoints and compaction calls.
+ * __compact_checkpoint --
+ * Perform a checkpoint for compaction.
*/
static int
-__compact_file(WT_SESSION_IMPL *session, const char *cfg[])
+__compact_checkpoint(WT_SESSION_IMPL *session)
{
- struct timespec start_time;
- WT_DATA_HANDLE *dhandle;
- WT_DECL_ITEM(t);
+ WT_TXN_GLOBAL *txn_global;
WT_DECL_RET;
- int i;
+ uint64_t txn_gen;
+
+ /*
+ * Force compaction checkpoints: we don't want to skip it because the
+ * work we need to have done is done in the underlying block manager.
+ */
const char *checkpoint_cfg[] = {
- WT_CONFIG_BASE(session, WT_SESSION_checkpoint), NULL, 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));
+
+ if ((ret = __wt_txn_checkpoint(session, checkpoint_cfg, false)) == 0)
+ return (0);
+ WT_RET_BUSY_OK(ret);
+
+ /*
+ * If there's a checkpoint running, wait for it to complete, checking if
+ * we're out of time. If there's no checkpoint running or the checkpoint
+ * generation number changes, the checkpoint blocking us has completed.
+ */
+ txn_global = &S2C(session)->txn_global;
+ for (txn_gen = txn_global->checkpoint_gen;;) {
+ WT_READ_BARRIER();
+ if (!txn_global->checkpoint_running ||
+ txn_gen != txn_global->checkpoint_gen)
+ break;
+
+ WT_RET(__wt_session_compact_check_timeout(session));
+ __wt_sleep(2, 0);
+ }
+
+ return (0);
+}
- dhandle = session->dhandle;
+/*
+ * __compact_worker --
+ * Function to alternate between checkpoints and compaction calls.
+ */
+static int
+__compact_worker(WT_SESSION_IMPL *session)
+{
+ WT_DECL_RET;
+ u_int i, loop;
+ bool didwork;
/*
- * Force the checkpoint: we don't want to skip it because the work we
- * need to have done is done in the underlying block manager.
+ * Reset the handles' compaction skip flag (we don't bother setting
+ * or resetting it when we finish compaction, it's simpler to do it
+ * once, here).
*/
- WT_ERR(__wt_scr_alloc(session, 128, &t));
- WT_ERR(__wt_buf_fmt(
- session, t, "target=(\"%s\"),force=1", dhandle->name));
- checkpoint_cfg[1] = t->data;
+ for (i = 0; i < session->op_handle_next; ++i)
+ session->op_handle[i]->compact_skip = false;
- __wt_epoch(session, &start_time);
+ /*
+ * Perform an initial checkpoint (see this file's leading comment for
+ * details).
+ */
+ WT_ERR(__compact_checkpoint(session));
/*
- * We compact 10% of the file on each pass (but the overall size of the
+ * We compact 10% of a file on each pass (but the overall size of the
* file is decreasing each time, so we're not compacting 10% of the
* original file each time). Try 100 times (which is clearly more than
- * we need); quit if we make no progress and check for a timeout each
- * time through the loop.
+ * we need); quit if we make no progress.
*/
- for (i = 0; i < 100; ++i) {
- WT_ERR(__wt_txn_checkpoint(session, checkpoint_cfg));
-
- session->compact_state = WT_COMPACT_RUNNING;
- WT_WITH_DHANDLE(session, dhandle,
- ret = __wt_compact(session, cfg));
- WT_ERR(ret);
- if (session->compact_state != WT_COMPACT_SUCCESS)
+ for (loop = 0; loop < 100; ++loop) {
+ /* Step through the list of files being compacted. */
+ for (didwork = false, i = 0; i < session->op_handle_next; ++i) {
+ /* Skip objects where there's no more work. */
+ if (session->op_handle[i]->compact_skip)
+ continue;
+
+ session->compact_state = WT_COMPACT_RUNNING;
+ WT_WITH_DHANDLE(session,
+ session->op_handle[i], ret = __wt_compact(session));
+ WT_ERR(ret);
+
+ /* If we did no work, skip this file in the future. */
+ if (session->compact_state == WT_COMPACT_SUCCESS)
+ didwork = true;
+ else
+ session->op_handle[i]->compact_skip = true;
+ }
+ if (!didwork)
break;
- WT_ERR(__wt_txn_checkpoint(session, checkpoint_cfg));
- WT_ERR(__wt_txn_checkpoint(session, checkpoint_cfg));
- WT_ERR(__session_compact_check_timeout(session, start_time));
+ /*
+ * Perform two checkpoints (see this file's leading comment for
+ * details).
+ */
+ WT_ERR(__compact_checkpoint(session));
+ WT_ERR(__compact_checkpoint(session));
}
err: session->compact_state = WT_COMPACT_NONE;
- __wt_scr_free(session, &t);
return (ret);
}
@@ -256,8 +311,9 @@ int
__wt_session_compact(
WT_SESSION *wt_session, const char *uri, const char *config)
{
- WT_COMPACT compact;
+ WT_COMPACT_STATE compact;
WT_CONFIG_ITEM cval;
+ WT_DATA_SOURCE *dsrc;
WT_DECL_RET;
WT_SESSION_IMPL *session;
WT_TXN *txn;
@@ -270,6 +326,17 @@ __wt_session_compact(
if (F_ISSET(S2C(session), WT_CONN_IN_MEMORY))
goto err;
+ /*
+ * Non-LSM object compaction requires checkpoints, which are impossible
+ * in transactional contexts. Disallow in all contexts (there's no
+ * reason for LSM to allow this, possible or not), and check now so the
+ * error message isn't confusing.
+ */
+ txn = &session->txn;
+ if (F_ISSET(txn, WT_TXN_RUNNING))
+ WT_ERR_MSG(session, EINVAL,
+ "compaction not permitted in a transaction");
+
/* Disallow objects in the WiredTiger name space. */
WT_ERR(__wt_str_name_check(session, uri));
@@ -277,18 +344,28 @@ __wt_session_compact(
!WT_PREFIX_MATCH(uri, "file:") &&
!WT_PREFIX_MATCH(uri, "index:") &&
!WT_PREFIX_MATCH(uri, "lsm:") &&
- !WT_PREFIX_MATCH(uri, "table:"))
- WT_ERR(__wt_bad_object_type(session, uri));
+ !WT_PREFIX_MATCH(uri, "table:")) {
+ if ((dsrc = __wt_schema_get_source(session, uri)) != NULL)
+ ret = dsrc->compact == NULL ?
+ __wt_object_unsupported(session, uri) :
+ dsrc->compact(
+ dsrc, wt_session, uri, (WT_CONFIG_ARG *)cfg);
+ else
+ ret = __wt_bad_object_type(session, uri);
+ goto err;
+ }
- /* Setup the structure in the session handle */
- memset(&compact, 0, sizeof(WT_COMPACT));
+ /* Setup the session handle's compaction state structure. */
+ memset(&compact, 0, sizeof(WT_COMPACT_STATE));
session->compact = &compact;
+ /* Compaction can be time-limited. */
WT_ERR(__wt_config_gets(session, cfg, "timeout", &cval));
session->compact->max_time = (uint64_t)cval.val;
+ __wt_epoch(session, &session->compact->begin);
/* Find the types of data sources being compacted. */
- WT_WITH_SCHEMA_LOCK(session, ret,
+ WT_WITH_SCHEMA_LOCK(session,
ret = __wt_schema_worker(session, uri,
__compact_handle_append, __compact_uri_analyze, cfg, 0));
WT_ERR(ret);
@@ -296,23 +373,8 @@ __wt_session_compact(
if (session->compact->lsm_count != 0)
WT_ERR(__wt_schema_worker(
session, uri, NULL, __wt_lsm_compact, cfg, 0));
- if (session->compact->file_count != 0) {
- /*
- * File compaction requires checkpoints, which will fail in a
- * transactional context. Check now so the error message isn't
- * confusing.
- */
- txn = &session->txn;
- if (F_ISSET(txn, WT_TXN_RUNNING))
- WT_ERR_MSG(session, EINVAL,
- " File compaction not permitted in a transaction");
-
- for (i = 0; i < session->op_handle_next; ++i) {
- WT_WITH_DHANDLE(session, session->op_handle[i],
- ret = __compact_file(session, cfg));
- WT_ERR(ret);
- }
- }
+ if (session->compact->file_count != 0)
+ WT_ERR(__compact_worker(session));
err: session->compact = NULL;
diff --git a/src/session/session_dhandle.c b/src/session/session_dhandle.c
index 94326aebe46..732dc797b6d 100644
--- a/src/session/session_dhandle.c
+++ b/src/session/session_dhandle.c
@@ -511,7 +511,7 @@ __wt_session_get_btree(WT_SESSION_IMPL *session,
F_CLR(dhandle, WT_DHANDLE_EXCLUSIVE);
__wt_writeunlock(session, dhandle->rwlock);
- WT_WITH_SCHEMA_LOCK(session, ret,
+ WT_WITH_SCHEMA_LOCK(session,
WT_WITH_HANDLE_LIST_LOCK(session,
ret = __wt_session_get_btree(
session, uri, checkpoint, cfg, flags)));