summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Bostic <keith.bostic@mongodb.com>2015-08-05 06:54:07 -0400
committerMichael Cahill <michael.cahill@mongodb.com>2015-08-06 12:12:59 +1000
commitf9572e20ad2de5372bd9c47ea0611a0b95dd92e5 (patch)
tree096d529d779ea59a4dce4c686d7f6da5f855a151
parent0349d8aa5f07209fb9b53cfff8236abe8acedfa3 (diff)
downloadmongo-f9572e20ad2de5372bd9c47ea0611a0b95dd92e5.tar.gz
WT-2025 Assert that cursors are positioned for inserts
Merge pull request #2106 from wiredtiger/cursor-positioned (cherry picked from commit c5c9936fb240c5bb4ec925f683476b7f075cfc78)
-rw-r--r--src/btree/col_modify.c2
-rw-r--r--src/btree/row_modify.c2
-rw-r--r--src/include/cursor.i6
-rw-r--r--src/include/serial.i31
4 files changed, 23 insertions, 18 deletions
diff --git a/src/btree/col_modify.c b/src/btree/col_modify.c
index dda56c19636..01db31057fc 100644
--- a/src/btree/col_modify.c
+++ b/src/btree/col_modify.c
@@ -160,7 +160,7 @@ __wt_col_modify(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt,
* The serial mutex acts as our memory barrier to flush these
* writes before inserting them into the list.
*/
- if (WT_SKIP_FIRST(ins_head) == NULL || recno == 0)
+ if (cbt->ins_stack[0] == NULL || recno == 0)
for (i = 0; i < skipdepth; i++) {
cbt->ins_stack[i] = &ins_head->head[i];
ins->next[i] = cbt->next_stack[i] = NULL;
diff --git a/src/btree/row_modify.c b/src/btree/row_modify.c
index f0a10cdf528..2dd42de5900 100644
--- a/src/btree/row_modify.c
+++ b/src/btree/row_modify.c
@@ -192,7 +192,7 @@ __wt_row_modify(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt,
* The serial mutex acts as our memory barrier to flush these
* writes before inserting them into the list.
*/
- if (WT_SKIP_FIRST(ins_head) == NULL)
+ if (cbt->ins_stack[0] == NULL)
for (i = 0; i < skipdepth; i++) {
cbt->ins_stack[i] = &ins_head->head[i];
ins->next[i] = cbt->next_stack[i] = NULL;
diff --git a/src/include/cursor.i b/src/include/cursor.i
index 606fee53749..47b772377c0 100644
--- a/src/include/cursor.i
+++ b/src/include/cursor.i
@@ -187,6 +187,12 @@ __cursor_func_init(WT_CURSOR_BTREE *cbt, int reenter)
if (reenter)
WT_RET(__curfile_leave(cbt));
+ /*
+ * Any old insert position is now invalid. We rely on this being
+ * cleared to detect if a new skiplist is installed after a search.
+ */
+ cbt->ins_stack[0] = NULL;
+
/* If the transaction is idle, check that the cache isn't full. */
WT_RET(__wt_txn_idle_cache_check(session));
diff --git a/src/include/serial.i b/src/include/serial.i
index 9e5acde9616..5b290822a10 100644
--- a/src/include/serial.i
+++ b/src/include/serial.i
@@ -47,6 +47,10 @@ __insert_simple_func(WT_SESSION_IMPL *session,
* return success: the levels we updated are correct and sufficient.
* Even though we don't get the benefit of the memory we allocated,
* we can't roll back.
+ *
+ * All structure setup must be flushed before the structure is entered
+ * into the list. We need a write barrier here, our callers depend on
+ * it.
*/
for (i = 0; i < skipdepth; i++)
if (!WT_ATOMIC_CAS8(*ins_stack[i], new_ins->next[i], new_ins))
@@ -65,7 +69,8 @@ __insert_serial_func(WT_SESSION_IMPL *session, WT_INSERT_HEAD *ins_head,
{
u_int i;
- WT_UNUSED(session);
+ /* The cursor should be positioned. */
+ WT_ASSERT(session, ins_stack[0] != NULL);
/*
* Update the skiplist elements referencing the new WT_INSERT item.
@@ -75,6 +80,10 @@ __insert_serial_func(WT_SESSION_IMPL *session, WT_INSERT_HEAD *ins_head,
* upper levels in the skiplist, return success: the levels we updated
* are correct and sufficient. Even though we don't get the benefit of
* the memory we allocated, we can't roll back.
+ *
+ * All structure setup must be flushed before the structure is entered
+ * into the list. We need a write barrier here, our callers depend on
+ * it.
*/
for (i = 0; i < skipdepth; i++) {
if (!WT_ATOMIC_CAS8(*ins_stack[i], new_ins->next[i], new_ins))
@@ -143,13 +152,6 @@ __wt_col_append_serial(WT_SESSION_IMPL *session, WT_PAGE *page,
WT_INSERT *new_ins = *new_insp;
WT_DECL_RET;
- /* !!!
- * Test for an uninitialized cursor, ins_stack[0] is cleared as part of
- * initializing a cursor for a search.
- */
- if (ins_stack[0] == NULL)
- return (WT_RESTART);
-
/* Check for page write generation wrap. */
WT_RET(__page_write_gen_wrapped_check(page));
@@ -162,8 +164,8 @@ __wt_col_append_serial(WT_SESSION_IMPL *session, WT_PAGE *page,
session, ins_head, ins_stack, new_ins, recnop, skipdepth);
WT_PAGE_UNLOCK(session, page);
- /* Free unused memory on error. */
if (ret != 0) {
+ /* Free unused memory on error. */
__wt_free(session, new_ins);
return (ret);
}
@@ -196,13 +198,6 @@ __wt_insert_serial(WT_SESSION_IMPL *session, WT_PAGE *page,
int simple;
u_int i;
- /* !!!
- * Test for an uninitialized cursor, ins_stack[0] is cleared as part of
- * initializing a cursor for a search.
- */
- if (ins_stack[0] == NULL)
- return (WT_RESTART);
-
/* Check for page write generation wrap. */
WT_RET(__page_write_gen_wrapped_check(page));
@@ -262,6 +257,10 @@ __wt_update_serial(WT_SESSION_IMPL *session, WT_PAGE *page,
*updp = NULL;
/*
+ * All structure setup must be flushed before the structure is entered
+ * into the list. We need a write barrier here, our callers depend on
+ * it.
+ *
* Swap the update into place. If that fails, a new update was added
* after our search, we raced. Check if our update is still permitted.
*/