summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@wiredtiger.com>2013-05-24 11:40:36 +1000
committerMichael Cahill <michael.cahill@wiredtiger.com>2013-05-24 11:40:36 +1000
commit1441654cebff4f46ba2f3448a0b41963276e9d24 (patch)
treea96647ef8a7a7501e74b12c16577d14e99d7ce37
parent7af5ca6253426a88e97ae6825e8084c75f5f22b2 (diff)
downloadmongo-1441654cebff4f46ba2f3448a0b41963276e9d24.tar.gz
Yet another rearrangement of the forced eviction code. Now check the first time we read a page in a transaction. That way, it shouldn't contain updates from the current transaction that prevent eviction.
-rw-r--r--src/btree/bt_page.c16
-rw-r--r--src/include/btree.i7
-rw-r--r--src/include/extern.h4
-rw-r--r--src/include/txn.h5
-rw-r--r--src/txn/txn.c12
5 files changed, 28 insertions, 16 deletions
diff --git a/src/btree/bt_page.c b/src/btree/bt_page.c
index ace833f8e26..5e43c53d6cd 100644
--- a/src/btree/bt_page.c
+++ b/src/btree/bt_page.c
@@ -30,8 +30,12 @@ __wt_page_in_func(
{
WT_DECL_RET;
WT_PAGE *page;
+ WT_PAGE_MODIFY *mod;
+ WT_TXN *txn;
int busy, oldgen;
+ txn = &session->txn;
+
for (oldgen = 0;;) {
switch (ref->state) {
case WT_REF_DISK:
@@ -79,9 +83,17 @@ __wt_page_in_func(
* updates. This should be extremely unlikely in real
* applications, wait for eviction of the page to avoid
* the issue.
+ *
+ * Also, make sure the page isn't too big. Only do
+ * this check once per transaction: it is not a common
+ * case, and we don't want to get stuck if it isn't
+ * possible to evict the page.
*/
- if (page->modify != NULL &&
- __wt_txn_ancient(session, page->modify->first_id)) {
+ if ((mod = page->modify) != NULL &&
+ (__wt_txn_ancient(session, mod->first_id) ||
+ (!F_ISSET(txn, TXN_FORCE_EVICT) &&
+ __wt_eviction_page_force(session, page)))) {
+ F_SET(txn, TXN_FORCE_EVICT);
page->read_gen = WT_READ_GEN_OLDEST;
WT_RET(__wt_page_release(session, page));
break;
diff --git a/src/include/btree.i b/src/include/btree.i
index ed3031471bc..3d49972043f 100644
--- a/src/include/btree.i
+++ b/src/include/btree.i
@@ -445,11 +445,10 @@ __wt_page_release(WT_SESSION_IMPL *session, WT_PAGE *page)
return (0);
/*
- * Try to immediately evict pages if they require forced eviction or
- * have the special "oldest" read generation.
+ * Try to immediately evict pages if they have the special "oldest"
+ * read generation.
*/
- if ((page->read_gen == WT_READ_GEN_OLDEST ||
- __wt_eviction_page_force(session, page)) &&
+ if (page->read_gen == WT_READ_GEN_OLDEST &&
WT_ATOMIC_CAS(page->ref->state, WT_REF_MEM, WT_REF_LOCKED)) {
if ((ret = __wt_hazard_clear(session, page)) != 0) {
page->ref->state = WT_REF_MEM;
diff --git a/src/include/extern.h b/src/include/extern.h
index ce7a96efb76..f9d4d5d3bbe 100644
--- a/src/include/extern.h
+++ b/src/include/extern.h
@@ -1239,10 +1239,10 @@ extern void __wt_stat_clear_connection_stats(void *stats_arg);
extern int __wt_txnid_cmp(const void *v1, const void *v2);
extern void __wt_txn_release_snapshot(WT_SESSION_IMPL *session);
extern void __wt_txn_get_oldest(WT_SESSION_IMPL *session);
-extern void __wt_txn_get_snapshot( WT_SESSION_IMPL *session,
+extern void __wt_txn_get_snapshot(WT_SESSION_IMPL *session,
wt_txnid_t my_id,
wt_txnid_t max_id,
- int force);
+ int committing);
extern void __wt_txn_get_evict_snapshot(WT_SESSION_IMPL *session);
extern int __wt_txn_begin(WT_SESSION_IMPL *session, const char *cfg[]);
extern void __wt_txn_release(WT_SESSION_IMPL *session);
diff --git a/src/include/txn.h b/src/include/txn.h
index 80e0a05668a..6d022c2d078 100644
--- a/src/include/txn.h
+++ b/src/include/txn.h
@@ -98,7 +98,8 @@ struct __wt_txn {
#define TXN_AUTOCOMMIT 0x01
#define TXN_ERROR 0x02
-#define TXN_OLDEST 0x04
-#define TXN_RUNNING 0x08
+#define TXN_FORCE_EVICT 0x04
+#define TXN_OLDEST 0x08
+#define TXN_RUNNING 0x10
uint32_t flags;
};
diff --git a/src/txn/txn.c b/src/txn/txn.c
index 70c7bd2bdfb..6bc860d7329 100644
--- a/src/txn/txn.c
+++ b/src/txn/txn.c
@@ -116,8 +116,8 @@ __wt_txn_get_oldest(WT_SESSION_IMPL *session)
* Set up a snapshot in the current transaction, without allocating an ID.
*/
void
-__wt_txn_get_snapshot(
- WT_SESSION_IMPL *session, wt_txnid_t my_id, wt_txnid_t max_id, int force)
+__wt_txn_get_snapshot(WT_SESSION_IMPL *session,
+ wt_txnid_t my_id, wt_txnid_t max_id, int committing)
{
WT_CONNECTION_IMPL *conn;
WT_TXN *txn;
@@ -132,7 +132,7 @@ __wt_txn_get_snapshot(
txn_state = &txn_global->states[session->id];
/* If nothing has changed since last time, we're done. */
- if (!force && txn->last_id == txn_global->current &&
+ if (!committing && txn->last_id == txn_global->current &&
txn->last_gen == txn_global->gen) {
WT_ASSERT(session,
TXNID_LE(txn->oldest_snap_min, txn->snap_min));
@@ -151,7 +151,7 @@ __wt_txn_get_snapshot(
for (i = n = 0, s = txn_global->states;
i < session_cnt;
i++, s++) {
- if ((id = s->id) != WT_TXN_NONE &&
+ if (!committing && (id = s->id) != WT_TXN_NONE &&
TXNID_LT(id, oldest_snap_min))
oldest_snap_min = id;
/*
@@ -182,7 +182,7 @@ __wt_txn_get_snapshot(
oldest_snap_min);
id = (my_id == WT_TXN_NONE || TXNID_LT(txn->snap_min, my_id)) ?
txn->snap_min : my_id;
- WT_ASSERT(session, TXNID_LE(oldest_snap_min, id));
+ WT_ASSERT(session, committing || TXNID_LE(oldest_snap_min, id));
txn_state->snap_min = id;
}
@@ -340,7 +340,7 @@ __wt_txn_release(WT_SESSION_IMPL *session)
if (session->ncursors == 0)
__wt_txn_release_snapshot(session);
txn->isolation = session->isolation;
- F_CLR(txn, TXN_ERROR | TXN_OLDEST | TXN_RUNNING);
+ F_CLR(txn, TXN_ERROR | TXN_FORCE_EVICT | TXN_OLDEST | TXN_RUNNING);
/* Update the global generation number. */
++txn_global->gen;