summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@mongodb.com>2015-09-25 13:09:08 +1000
committerMichael Cahill <michael.cahill@mongodb.com>2015-09-29 17:19:02 +1000
commit126467ed7e6b3ad4a9b2566fe6b66dae0b763a91 (patch)
treefe435dfd5c79240adb2427544f45296a8019d32d /src
parent4b6157e191d644603e6c0642aed1e9f07eee596d (diff)
downloadmongo-126467ed7e6b3ad4a9b2566fe6b66dae0b763a91.tar.gz
WT-2126: page split locking
Merge pull request #2210 from wiredtiger/wt2126 (cherry picked from commit 87c52d446eba66ef686b2144afe3d925c95297c1)
Diffstat (limited to 'src')
-rw-r--r--src/btree/bt_split.c137
-rw-r--r--src/include/extern.h2
2 files changed, 107 insertions, 32 deletions
diff --git a/src/btree/bt_split.c b/src/btree/bt_split.c
index 7d7e88db918..be7dc27c8b0 100644
--- a/src/btree/bt_split.c
+++ b/src/btree/bt_split.c
@@ -787,30 +787,22 @@ __wt_multi_to_ref(WT_SESSION_IMPL *session,
}
/*
- * __split_parent --
- * Resolve a multi-page split, inserting new information into the parent.
+ * __split_parent_lock --
+ * Lock the parent page.
*/
static int
-__split_parent(WT_SESSION_IMPL *session, WT_REF *ref,
- WT_REF **ref_new, uint32_t new_entries, size_t parent_incr, bool closing)
+__split_parent_lock(
+ WT_SESSION_IMPL *session, WT_REF *ref, WT_PAGE **parentp, bool *hazardp)
{
WT_DECL_RET;
- WT_IKEY *ikey;
WT_PAGE *parent;
- WT_PAGE_INDEX *alloc_index, *pindex;
- WT_REF **alloc_refp, *next_ref, *parent_ref;
- size_t parent_decr, size;
- uint64_t split_gen;
- uint32_t children, i, j;
- uint32_t deleted_entries, parent_entries, result_entries;
- bool complete, hazard;
+ WT_REF *parent_ref;
parent = NULL; /* -Wconditional-uninitialized */
- alloc_index = pindex = NULL;
parent_ref = NULL;
- parent_decr = 0;
- parent_entries = 0;
- complete = hazard = false;
+
+ *hazardp = false;
+ *parentp = NULL;
/*
* Get a page-level lock on the parent to single-thread splits into the
@@ -850,9 +842,63 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref,
*/
if (!__wt_ref_is_root(parent_ref = parent->pg_intl_parent_ref)) {
WT_ERR(__wt_page_in(session, parent_ref, WT_READ_NO_EVICT));
- hazard = true;
+ *hazardp = true;
}
+ *parentp = parent;
+ return (0);
+
+err: F_CLR_ATOMIC(parent, WT_PAGE_SPLIT_LOCKED);
+ return (ret);
+}
+
+/*
+ * __split_parent_unlock --
+ * Unlock the parent page.
+ */
+static int
+__split_parent_unlock(WT_SESSION_IMPL *session, WT_PAGE *parent, bool hazard)
+{
+ WT_DECL_RET;
+
+ if (hazard)
+ ret = __wt_hazard_clear(session, parent);
+
+ F_CLR_ATOMIC(parent, WT_PAGE_SPLIT_LOCKED);
+ return (ret);
+}
+
+/*
+ * __split_parent --
+ * Resolve a multi-page split, inserting new information into the parent.
+ */
+static int
+__split_parent(WT_SESSION_IMPL *session, WT_REF *ref,
+ WT_REF **ref_new, uint32_t new_entries, size_t parent_incr, bool closing)
+{
+ WT_DECL_RET;
+ WT_IKEY *ikey;
+ WT_PAGE *parent;
+ WT_PAGE_INDEX *alloc_index, *pindex;
+ WT_REF **alloc_refp, *next_ref, *parent_ref;
+ size_t parent_decr, size;
+ uint64_t split_gen;
+ uint32_t i, j;
+ uint32_t children, deleted_entries, parent_entries, result_entries;
+ bool complete;
+
+ parent = ref->home;
+ parent_ref = parent->pg_intl_parent_ref;
+
+ alloc_index = pindex = NULL;
+ parent_decr = 0;
+ parent_entries = 0;
+ complete = false;
+
+ /*
+ * We've locked the parent, which means it cannot split (which is the
+ * only reason to worry about split generation values).
+ */
pindex = WT_INTL_INDEX_GET_SAFE(parent);
parent_entries = pindex->entries;
@@ -1043,10 +1089,6 @@ err: if (!complete)
if (next_ref->state == WT_REF_SPLIT)
next_ref->state = WT_REF_DELETED;
}
- F_CLR_ATOMIC(parent, WT_PAGE_SPLIT_LOCKED);
-
- if (hazard)
- WT_TRET(__wt_hazard_clear(session, parent));
__wt_free_ref_index(session, NULL, alloc_index, false);
@@ -1062,12 +1104,11 @@ err: if (!complete)
}
/*
- * __wt_split_insert --
- * Check for pages with append-only workloads and split their last insert
- * list into a separate page.
+ * __split_insert --
+ * Split a page's last insert list entries into a separate page.
*/
-int
-__wt_split_insert(WT_SESSION_IMPL *session, WT_REF *ref)
+static int
+__split_insert(WT_SESSION_IMPL *session, WT_REF *ref)
{
WT_DECL_RET;
WT_DECL_ITEM(key);
@@ -1333,8 +1374,25 @@ err: if (split_ref[0] != NULL) {
}
/*
+ * __wt_split_insert --
+ * Lock, then split.
+ */
+int
+__wt_split_insert(WT_SESSION_IMPL *session, WT_REF *ref)
+{
+ WT_DECL_RET;
+ WT_PAGE *parent;
+ bool hazard;
+
+ WT_RET(__split_parent_lock(session, ref, &parent, &hazard));
+ ret = __split_insert(session, ref);
+ WT_TRET(__split_parent_unlock(session, parent, hazard));
+ return (ret);
+}
+
+/*
* __wt_split_rewrite --
- * Resolve a failed reconciliation by replacing a page with a new version.
+ * Rewrite an in-memory page with a new version.
*/
int
__wt_split_rewrite(WT_SESSION_IMPL *session, WT_REF *ref)
@@ -1377,11 +1435,11 @@ __wt_split_rewrite(WT_SESSION_IMPL *session, WT_REF *ref)
}
/*
- * __wt_split_multi --
- * Resolve a page split.
+ * __split_multi --
+ * Split a page into multiple pages.
*/
-int
-__wt_split_multi(WT_SESSION_IMPL *session, WT_REF *ref, bool closing)
+static int
+__split_multi(WT_SESSION_IMPL *session, WT_REF *ref, bool closing)
{
WT_DECL_RET;
WT_PAGE *page;
@@ -1445,3 +1503,20 @@ err: /*
__wt_free(session, ref_new);
return (ret);
}
+
+/*
+ * __wt_split_multi --
+ * Lock, then split.
+ */
+int
+__wt_split_multi(WT_SESSION_IMPL *session, WT_REF *ref, int closing)
+{
+ WT_DECL_RET;
+ WT_PAGE *parent;
+ bool hazard;
+
+ WT_RET(__split_parent_lock(session, ref, &parent, &hazard));
+ ret = __split_multi(session, ref, closing);
+ WT_TRET(__split_parent_unlock(session, parent, hazard));
+ return (ret);
+}
diff --git a/src/include/extern.h b/src/include/extern.h
index 58963bc8c42..4b341a6adaa 100644
--- a/src/include/extern.h
+++ b/src/include/extern.h
@@ -154,7 +154,7 @@ extern void __wt_split_stash_discard_all( WT_SESSION_IMPL *session_safe, WT_SESS
extern int __wt_multi_to_ref(WT_SESSION_IMPL *session, WT_PAGE *page, WT_MULTI *multi, WT_REF **refp, size_t *incrp);
extern int __wt_split_insert(WT_SESSION_IMPL *session, WT_REF *ref);
extern int __wt_split_rewrite(WT_SESSION_IMPL *session, WT_REF *ref);
-extern int __wt_split_multi(WT_SESSION_IMPL *session, WT_REF *ref, bool closing);
+extern int __wt_split_multi(WT_SESSION_IMPL *session, WT_REF *ref, int closing);
extern int __wt_btree_stat_init(WT_SESSION_IMPL *session, WT_CURSOR_STAT *cst);
extern int __wt_cache_op(WT_SESSION_IMPL *session, WT_CKPT *ckptbase, int op);
extern int __wt_upgrade(WT_SESSION_IMPL *session, const char *cfg[]);