summaryrefslogtreecommitdiff
path: root/src/include/btree.i
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/btree.i')
-rw-r--r--src/include/btree.i135
1 files changed, 113 insertions, 22 deletions
diff --git a/src/include/btree.i b/src/include/btree.i
index 43418d65b96..5ddab20dfd6 100644
--- a/src/include/btree.i
+++ b/src/include/btree.i
@@ -517,6 +517,70 @@ __wt_ref_key_clear(WT_REF *ref)
}
/*
+ * __wt_row_leaf_direct --
+ * Return an encoded row-store leaf page key.
+ */
+static inline void
+__wt_row_leaf_direct(WT_PAGE *page, void *ripkey, WT_ITEM *key)
+{
+ uintptr_t v;
+
+ /*
+ * A row-store leaf page key is in one of two places: if instantiated,
+ * the WT_ROW pointer references a WT_IKEY structure, otherwise, it
+ * references an on-page location. However, on-page keys are in one of
+ * two states and the reference is in one of two forms: if a row-store
+ * doesn't configure prefix compression or Huffman encoding, and there
+ * were no overflow keys found when reading the page into memory (all
+ * of which is likely, those are the default configurations), the key's
+ * location and size was encoded in the pointer and a page flag was set.
+ * If we found overflow keys or one of those features is configured, the
+ * reference is to the key's on-page cell, which we'll unpack (we're
+ * trying to avoid that cell unpack per key read in the fast path).
+ * The test is if the page flag is set, we're done, it's an encoding;
+ * otherwise, if the pointer is off-page it's an instantiated key, else
+ * an on-page cell.
+ *
+ * This function cracks an encoded key and returns a real pointer. The
+ * encoding magic is simpler than internal page key encoding because we
+ * are using the page's flag rather than per-key information to decide
+ * if the key is encoded. The key's page offset is the bottom 4B, and
+ * the key size is the top 4B.
+ */
+ v = (uintptr_t)ripkey;
+ key->data = WT_PAGE_REF_OFFSET(page, (v & 0xFFFFFFFF));
+ key->size = v >> 32;
+}
+
+/*
+ * __wt_row_leaf_key_onpage_set --
+ * Set a WT_ROW to reference an on-page key.
+ */
+static inline void
+__wt_row_leaf_key_onpage_set(WT_PAGE *page, WT_ROW *rip, WT_CELL_UNPACK *unpack)
+{
+ uintptr_t v;
+
+ /*
+ * See the comment in __wt_row_leaf_direct for an explanation of the
+ * magic.
+ */
+ v = (uintptr_t)unpack->size << 32 |
+ (uint32_t)WT_PAGE_DISK_OFFSET(page, unpack->data);
+ WT_ROW_KEY_SET(rip, v);
+}
+
+/*
+ * __wt_row_leaf_key_onpage_set_cell --
+ * Set a WT_ROW to reference an on-page key's cell.
+ */
+static inline void
+__wt_row_leaf_key_onpage_set_cell(WT_ROW *rip, WT_CELL *cell)
+{
+ WT_ROW_KEY_SET(rip, cell);
+}
+
+/*
* __wt_row_leaf_key --
* Set a buffer to reference a row-store leaf page key as cheaply as
* possible.
@@ -526,32 +590,39 @@ __wt_row_leaf_key(WT_SESSION_IMPL *session,
WT_PAGE *page, WT_ROW *rip, WT_ITEM *key, int instantiate)
{
WT_BTREE *btree;
- WT_IKEY *ikey;
WT_CELL_UNPACK unpack;
+ WT_IKEY *ikey;
+ void *copy;
btree = S2BT(session);
/*
- * A subset of __wt_row_leaf_key_work, that is, calling that function
- * should give you the same results as calling this one; this function
- * exists to inline fast-path checks for already instantiated keys and
- * on-page uncompressed keys.
+ * A front-end for __wt_row_leaf_key_work, here to inline fast paths.
+ *
+ * The row-store key can change underfoot; explicitly take a copy.
*/
- ikey = WT_ROW_KEY_COPY(rip);
+ copy = WT_ROW_KEY_COPY(rip);
- /*
- * Key copied.
- * If the key has been instantiated for any reason, off-page, use it.
- */
- if (__wt_off_page(page, ikey)) {
+ /* First, check for an encoded key. */
+ if (F_ISSET_ATOMIC(page, WT_PAGE_DIRECT_KEY)) {
+ __wt_row_leaf_direct(page, copy, key);
+ return (0);
+ }
+
+ /* Second, check for an instantiated key. */
+ if (__wt_off_page(page, copy)) {
+ ikey = copy;
key->data = WT_IKEY_DATA(ikey);
key->size = ikey->size;
return (0);
}
- /* If the key isn't compressed or an overflow, take it from the page. */
+ /*
+ * Third, if the key isn't compressed or an overflow, unpack the cell
+ * and take it from the page.
+ */
if (btree->huffman_key == NULL) {
- __wt_cell_unpack((WT_CELL *)ikey, &unpack);
+ __wt_cell_unpack(copy, &unpack);
if (unpack.type == WT_CELL_KEY && unpack.prefix == 0) {
key->data = unpack.data;
key->size = unpack.size;
@@ -603,23 +674,43 @@ __wt_row_leaf_value(WT_PAGE *page, WT_ROW *rip)
{
WT_CELL *cell;
WT_CELL_UNPACK unpack;
+ WT_IKEY *ikey;
+ void *copy;
+ uintptr_t v;
- cell = WT_ROW_KEY_COPY(rip);
+ /*
+ * The row-store key can change underfoot; explicitly take a copy.
+ */
+ copy = WT_ROW_KEY_COPY(rip);
/*
- * Key copied.
- *
- * Cell now either references a WT_IKEY structure with a cell offset,
- * or references the on-page key WT_CELL. Both can be processed
- * regardless of what other threads are doing. If it's the former,
- * use it to get the latter.
+ * See the comment in __wt_row_leaf_direct for an explanation of the
+ * magic; we know where the key is, step past it to the value's cell.
*/
- if (__wt_off_page(page, cell))
- cell = WT_PAGE_REF_OFFSET(page, ((WT_IKEY *)cell)->cell_offset);
+ if (F_ISSET_ATOMIC(page, WT_PAGE_DIRECT_KEY)) {
+ v = (uintptr_t)copy;
+ cell = (WT_CELL *)
+ ((uint8_t *)WT_PAGE_REF_OFFSET(page, (v & 0xFFFFFFFF)) +
+ (v >> 32));
+ return (__wt_cell_leaf_value_parse(page, cell));
+ }
+
+ /*
+ * Cell now either references a WT_IKEY structure with a cell offset, or
+ * references the on-page key WT_CELL. Both can be processed no matter
+ * what other threads are doing. If it's the former, use it to get the
+ * latter.
+ */
+ if (__wt_off_page(page, copy)) {
+ ikey = copy;
+ cell = WT_PAGE_REF_OFFSET(page, ikey->cell_offset);
+ } else
+ cell = copy;
/* Unpack the key cell, then return its associated value cell. */
__wt_cell_unpack(cell, &unpack);
cell = (WT_CELL *)((uint8_t *)cell + __wt_cell_total_len(&unpack));
+
return (__wt_cell_leaf_value_parse(page, cell));
}