diff options
author | agorrod <alexg@wiredtiger.com> | 2012-09-28 00:17:44 -0700 |
---|---|---|
committer | agorrod <alexg@wiredtiger.com> | 2012-09-28 00:17:44 -0700 |
commit | c8a4341d852d323d0029b0b0a1e48a58ab2f23b6 (patch) | |
tree | 56ba57223b3b07466f22c4491684fde522d9d9b2 /src | |
parent | 1b70668459116f1100da075cf2d0532efdc5ae6e (diff) | |
parent | abd79f526b7ef5334c2863fc84b6d9638eb8cad7 (diff) | |
download | mongo-c8a4341d852d323d0029b0b0a1e48a58ab2f23b6.tar.gz |
Merge pull request #343 from wiredtiger/evict-fail
If no space can be allocated in the cache, abort transactions.
Diffstat (limited to 'src')
-rw-r--r-- | src/btree/bt_curnext.c | 2 | ||||
-rw-r--r-- | src/btree/bt_curprev.c | 1 | ||||
-rw-r--r-- | src/btree/bt_cursor.c | 1 | ||||
-rw-r--r-- | src/btree/bt_evict.c | 10 | ||||
-rw-r--r-- | src/btree/rec_evict.c | 6 | ||||
-rw-r--r-- | src/docs/cursor-ops.dox | 10 | ||||
-rw-r--r-- | src/docs/transactions.dox | 5 | ||||
-rw-r--r-- | src/include/api.h | 8 | ||||
-rw-r--r-- | src/include/cursor.i | 13 |
9 files changed, 39 insertions, 17 deletions
diff --git a/src/btree/bt_curnext.c b/src/btree/bt_curnext.c index 3c7b8d21a33..98ebc3c622b 100644 --- a/src/btree/bt_curnext.c +++ b/src/btree/bt_curnext.c @@ -403,6 +403,7 @@ __wt_btcur_next(WT_CURSOR_BTREE *cbt, int discard) LF_SET(WT_TREE_DISCARD); __cursor_func_init(cbt, 0); + __cursor_position_clear(cbt); /* * If we aren't already iterating in the right direction, there's @@ -507,6 +508,7 @@ __wt_btcur_next_random(WT_CURSOR_BTREE *cbt) WT_BSTAT_INCR(session, cursor_read_next); __cursor_func_init(cbt, 1); + __cursor_position_clear(cbt); /* * Only supports row-store: applications can trivially select a random diff --git a/src/btree/bt_curprev.c b/src/btree/bt_curprev.c index 76a847ea61a..e7f9a37b742 100644 --- a/src/btree/bt_curprev.c +++ b/src/btree/bt_curprev.c @@ -491,6 +491,7 @@ __wt_btcur_prev(WT_CURSOR_BTREE *cbt, int discard) LF_SET(WT_TREE_DISCARD); __cursor_func_init(cbt, 0); + __cursor_position_clear(cbt); /* * If we aren't already iterating in the right direction, there's diff --git a/src/btree/bt_cursor.c b/src/btree/bt_cursor.c index b72c4a12fd0..4515063d8be 100644 --- a/src/btree/bt_cursor.c +++ b/src/btree/bt_cursor.c @@ -112,6 +112,7 @@ __wt_btcur_reset(WT_CURSOR_BTREE *cbt) __cursor_leave(cbt); __cursor_search_clear(cbt); + __cursor_position_clear(cbt); return (0); } diff --git a/src/btree/bt_evict.c b/src/btree/bt_evict.c index c834fd2c17f..f03a986cae3 100644 --- a/src/btree/bt_evict.c +++ b/src/btree/bt_evict.c @@ -940,6 +940,7 @@ int __wt_evict_lru_page(WT_SESSION_IMPL *session, int is_app) { WT_BTREE *btree, *saved_btree; + WT_DECL_RET; WT_PAGE *page; __evict_get_page(session, is_app, &btree, &page); @@ -952,19 +953,14 @@ __wt_evict_lru_page(WT_SESSION_IMPL *session, int is_app) saved_btree = session->btree; WT_SET_BTREE_IN_SESSION(session, btree); - /* - * We don't care why eviction failed (maybe the page was dirty and - * we're out of disk space, or the page had an in-memory subtree - * already being evicted). - */ - (void)__evict_page(session, page); + ret = __evict_page(session, page); (void)WT_ATOMIC_SUB(btree->lru_count, 1); WT_CLEAR_BTREE_IN_SESSION(session); session->btree = saved_btree; - return (0); + return (ret); } /* diff --git a/src/btree/rec_evict.c b/src/btree/rec_evict.c index 9ff11cf5900..780ad8f1976 100644 --- a/src/btree/rec_evict.c +++ b/src/btree/rec_evict.c @@ -339,10 +339,10 @@ __rec_review(WT_SESSION_IMPL *session, } /* - * If no pages are referenced, there are no consistency - * issues: try to bump our snapshot. + * If there aren't multiple cursors active, there + * are no consistency issues: try to bump our snapshot. */ - if (session->nhazard == 0) { + if (session->ncursors <= 1) { __wt_txn_read_last(session); __wt_txn_read_first(session); } diff --git a/src/docs/cursor-ops.dox b/src/docs/cursor-ops.dox index 84d089446cb..54a174a09c2 100644 --- a/src/docs/cursor-ops.dox +++ b/src/docs/cursor-ops.dox @@ -101,8 +101,14 @@ To remove existing data using a cursor, use the WT_CURSOR::remove method: @section cursor_error Cursor position after error After any cursor handle method failure, the cursor's position is -undetermined. Applications that cannot re-position the cursor after -failure must duplicate the cursor before calling a cursor method that will +undetermined. For cursor operations that expect a key to be set before the +operation begins (including WT_CURSOR::search, WT_CURSOR::insert, +WT_CURSOR::update and WT_CURSOR::remove), the application's key and value +will not be cleared by an error. + +Applications that cannot re-position the cursor after failure must +duplicate the cursor by calling WT_SESSION::open_cursor and passing the +cursor as the \c to_dup parameter before calling a cursor method that will attempt to re-position the cursor. */ diff --git a/src/docs/transactions.dox b/src/docs/transactions.dox index efc5934f9aa..4bc745858b8 100644 --- a/src/docs/transactions.dox +++ b/src/docs/transactions.dox @@ -72,6 +72,11 @@ updating the same value will fail with ::WT_DEADLOCK. Some applications may benefit from application-level synchronization to avoid repeated attempts to rollback and update the same value. +Operations in transactions may also fail with the ::WT_DEADLOCK error if +some resource cannot be allocated after repeated attempts. For example, if +the cache is not large enough to hold the updates required to satisfy +transactional readers, an operation may fail and return ::WT_DEADLOCK. + @section transaction_isolation Isolation levels WiredTiger supports <code>read-uncommitted</code>, diff --git a/src/include/api.h b/src/include/api.h index 47129ee8291..11ba9656cc7 100644 --- a/src/include/api.h +++ b/src/include/api.h @@ -331,14 +331,18 @@ struct __wt_connection_impl { } \ ret = __wt_txn_commit((s), NULL); \ } else { \ - WT_TRET(WT_DEADLOCK); \ (void)__wt_txn_rollback((s), NULL); \ + if (ret == 0 || ret == WT_DEADLOCK) { \ + ret = 0; \ + continue; \ + } \ } \ } else if ((ret) != 0 && \ (ret) != WT_NOTFOUND && \ (ret) != WT_DUPLICATE_KEY) \ F_SET(&(s)->txn, TXN_ERROR); \ -} while (0) + break; \ +} while (1) /* * If a session or connection method is about to return WT_NOTFOUND (some diff --git a/src/include/cursor.i b/src/include/cursor.i index e9a3240684c..aa0d3ef436f 100644 --- a/src/include/cursor.i +++ b/src/include/cursor.i @@ -17,6 +17,16 @@ __cursor_set_recno(WT_CURSOR_BTREE *cbt, uint64_t v) } /* + * __cursor_position_clear -- + * Forget the current key and value in a cursor. + */ +static inline void +__cursor_position_clear(WT_CURSOR_BTREE *cbt) +{ + F_CLR(&cbt->iface, WT_CURSTD_KEY_SET | WT_CURSTD_VALUE_SET); +} + +/* * __cursor_search_clear -- * Reset the cursor's state for a search. */ @@ -60,9 +70,6 @@ __cursor_leave(WT_CURSOR_BTREE *cbt) __wt_stack_release(session, cbt->page); cbt->page = NULL; - /* Reset the returned key/value state. */ - F_CLR(cursor, WT_CURSTD_KEY_SET | WT_CURSTD_VALUE_SET); - if (F_ISSET(cbt, WT_CBT_ACTIVE)) { WT_ASSERT(session, session->ncursors > 0); if (--session->ncursors == 0) |