summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEtienne Petrel <etienne.petrel@mongodb.com>2021-11-18 14:43:46 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-11-18 15:39:41 +0000
commit63639d4b9348c7a9943ab38121c5701b8dc09892 (patch)
tree5047ac77eb656f166da75860f144aad4f405aa94 /src
parent041cb777961858638cbb834015d24d6bc2f2fd08 (diff)
downloadmongo-63639d4b9348c7a9943ab38121c5701b8dc09892.tar.gz
Import wiredtiger: 73e6a5f9733205d2b0c1d58a78480fc2f5b08085 from branch mongodb-master
ref: 76bac330da..73e6a5f973 for: 5.2.0 WT-8303 Implement weak hazard pointers
Diffstat (limited to 'src')
-rw-r--r--src/third_party/wiredtiger/.clang-format1
-rw-r--r--src/third_party/wiredtiger/dist/filelist1
-rwxr-xr-x[-rw-r--r--]src/third_party/wiredtiger/dist/s_clang-scan0
-rw-r--r--src/third_party/wiredtiger/import.data2
-rw-r--r--src/third_party/wiredtiger/src/conn/conn_open.c1
-rw-r--r--src/third_party/wiredtiger/src/evict/evict_page.c8
-rw-r--r--src/third_party/wiredtiger/src/include/extern.h7
-rw-r--r--src/third_party/wiredtiger/src/include/session.h24
-rw-r--r--src/third_party/wiredtiger/src/include/txn.h2
-rw-r--r--src/third_party/wiredtiger/src/include/wt_internal.h4
-rw-r--r--src/third_party/wiredtiger/src/session/session_api.c14
-rw-r--r--src/third_party/wiredtiger/src/support/hazard.c13
-rw-r--r--src/third_party/wiredtiger/src/support/hazard_weak.c280
-rw-r--r--src/third_party/wiredtiger/src/txn/txn.c24
-rw-r--r--src/third_party/wiredtiger/src/txn/txn_log.c23
15 files changed, 393 insertions, 11 deletions
diff --git a/src/third_party/wiredtiger/.clang-format b/src/third_party/wiredtiger/.clang-format
index ad0583e71e0..b5595a1f863 100644
--- a/src/third_party/wiredtiger/.clang-format
+++ b/src/third_party/wiredtiger/.clang-format
@@ -78,6 +78,7 @@ ForEachMacros:
- WT_COL_FOREACH
- WT_EXT_FOREACH
- WT_EXT_FOREACH_OFF
+ - WT_HAZARD_WEAK_FORALL
- WT_INTL_FOREACH_BEGIN
- WT_INTL_FOREACH_REVERSE_BEGIN
- WT_MODIFY_FOREACH_BEGIN
diff --git a/src/third_party/wiredtiger/dist/filelist b/src/third_party/wiredtiger/dist/filelist
index a37d0e116e0..a50ec3d667c 100644
--- a/src/third_party/wiredtiger/dist/filelist
+++ b/src/third_party/wiredtiger/dist/filelist
@@ -200,6 +200,7 @@ src/support/global.c
src/support/hash_city.c
src/support/hash_fnv.c
src/support/hazard.c
+src/support/hazard_weak.c
src/support/hex.c
src/support/huffman.c
src/support/lock_ext.c
diff --git a/src/third_party/wiredtiger/dist/s_clang-scan b/src/third_party/wiredtiger/dist/s_clang-scan
index 9a5ee3d4587..9a5ee3d4587 100644..100755
--- a/src/third_party/wiredtiger/dist/s_clang-scan
+++ b/src/third_party/wiredtiger/dist/s_clang-scan
diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data
index 4b0d980b99e..d84cebd36d1 100644
--- a/src/third_party/wiredtiger/import.data
+++ b/src/third_party/wiredtiger/import.data
@@ -2,5 +2,5 @@
"vendor": "wiredtiger",
"github": "wiredtiger/wiredtiger.git",
"branch": "mongodb-master",
- "commit": "76bac330dabda8d508cc57ed7e00ee68b08f6ec2"
+ "commit": "73e6a5f9733205d2b0c1d58a78480fc2f5b08085"
}
diff --git a/src/third_party/wiredtiger/src/conn/conn_open.c b/src/third_party/wiredtiger/src/conn/conn_open.c
index 5d01264502d..d7fe6368fe1 100644
--- a/src/third_party/wiredtiger/src/conn/conn_open.c
+++ b/src/third_party/wiredtiger/src/conn/conn_open.c
@@ -178,6 +178,7 @@ __wt_connection_close(WT_CONNECTION_IMPL *conn)
__wt_free(session, s->dhhash);
__wt_stash_discard_all(session, s);
__wt_free(session, s->hazard);
+ __wt_hazard_weak_destroy(session, s);
}
/* Destroy the file-system configuration. */
diff --git a/src/third_party/wiredtiger/src/evict/evict_page.c b/src/third_party/wiredtiger/src/evict/evict_page.c
index de249ec4a4b..a0e7314c0cc 100644
--- a/src/third_party/wiredtiger/src/evict/evict_page.c
+++ b/src/third_party/wiredtiger/src/evict/evict_page.c
@@ -152,6 +152,14 @@ __wt_evict(WT_SESSION_IMPL *session, WT_REF *ref, uint8_t previous_state, uint32
}
/*
+ * We have exclusive access, invalidate any weak hazard pointers. Note: In the future we will
+ * investigate a better place to invalidate the weak hazard pointers. Ideally, we want to delay
+ * invalidation as long as possible so that if eviction of this page were to fail, we would not
+ * have invalidated the weak hazard pointers unnecessarily.
+ */
+ __wt_hazard_weak_invalidate(session, ref);
+
+ /*
* Review the page for conditions that would block its eviction. If the check fails (for
* example, we find a page with active children), quit. Make this check for clean pages, too:
* while unlikely eviction would choose an internal page with children, it's not disallowed.
diff --git a/src/third_party/wiredtiger/src/include/extern.h b/src/third_party/wiredtiger/src/include/extern.h
index 9d0be1b7016..3558d2dfe7e 100644
--- a/src/third_party/wiredtiger/src/include/extern.h
+++ b/src/third_party/wiredtiger/src/include/extern.h
@@ -782,6 +782,10 @@ extern int __wt_hazard_set_func(WT_SESSION_IMPL *session, WT_REF *ref, bool *bus
const char *func, int line
#endif
) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+extern int __wt_hazard_weak_clear(WT_SESSION_IMPL *session, WT_TXN_OP *op)
+ WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+extern int __wt_hazard_weak_set(WT_SESSION_IMPL *session, WT_REF *ref, WT_TXN_OP *op)
+ WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_hex2byte(const u_char *from, u_char *to)
WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_hex_to_raw(WT_SESSION_IMPL *session, const char *from, WT_ITEM *to)
@@ -1786,6 +1790,9 @@ extern void __wt_gen_init(WT_SESSION_IMPL *session);
extern void __wt_gen_next(WT_SESSION_IMPL *session, int which, uint64_t *genp);
extern void __wt_gen_next_drain(WT_SESSION_IMPL *session, int which);
extern void __wt_hazard_close(WT_SESSION_IMPL *session);
+extern void __wt_hazard_weak_close(WT_SESSION_IMPL *session);
+extern void __wt_hazard_weak_destroy(WT_SESSION_IMPL *session_safe, WT_SESSION_IMPL *s);
+extern void __wt_hazard_weak_invalidate(WT_SESSION_IMPL *session, WT_REF *ref);
extern void __wt_hs_close(WT_SESSION_IMPL *session);
extern void __wt_hs_upd_time_window(WT_CURSOR *hs_cursor, WT_TIME_WINDOW **twp);
extern void __wt_huffman_close(WT_SESSION_IMPL *session, void *huffman_arg);
diff --git a/src/third_party/wiredtiger/src/include/session.h b/src/third_party/wiredtiger/src/include/session.h
index 85690b57fbd..5273e1234b4 100644
--- a/src/third_party/wiredtiger/src/include/session.h
+++ b/src/third_party/wiredtiger/src/include/session.h
@@ -30,6 +30,28 @@ struct __wt_hazard {
#endif
};
+/*
+ * WT_HAZARD_WEAK --
+ * A weak hazard pointer.
+ */
+struct __wt_hazard_weak {
+ WT_REF *ref; /* Page reference */
+ bool valid; /* Is the weak hazard pointer still valid? */
+};
+
+/*
+ * WT_HAZARD_WEAK_ARRAY --
+ * A per-session array of weak hazard pointers. These are grown by adding a new array, and are
+ * only freed when the session is closed.
+ */
+struct __wt_hazard_weak_array {
+ uint32_t hazard_size; /* Weak hazard pointer array slots */
+ uint32_t hazard_inuse; /* Weak hazard pointer array slots in-use */
+ uint32_t nhazard; /* Count of active weak hazard pointers */
+ WT_HAZARD_WEAK_ARRAY *next;
+ WT_HAZARD_WEAK hazard[0]; /* Weak hazard pointer array */
+};
+
/* Get the connection implementation for a session */
#define S2C(session) ((WT_CONNECTION_IMPL *)(session)->iface.connection)
@@ -279,6 +301,8 @@ struct __wt_session_impl {
uint32_t nhazard; /* Count of active hazard pointers */
WT_HAZARD *hazard; /* Hazard pointer array */
+ WT_HAZARD_WEAK_ARRAY *hazard_weak;
+
/*
* Operation tracking.
*/
diff --git a/src/third_party/wiredtiger/src/include/txn.h b/src/third_party/wiredtiger/src/include/txn.h
index cb433664094..b1c2b50a743 100644
--- a/src/third_party/wiredtiger/src/include/txn.h
+++ b/src/third_party/wiredtiger/src/include/txn.h
@@ -196,6 +196,8 @@ typedef enum {
struct __wt_txn_op {
WT_BTREE *btree;
WT_TXN_TYPE type;
+ WT_HAZARD_WEAK *whp;
+
union {
/* WT_TXN_OP_BASIC_ROW, WT_TXN_OP_INMEM_ROW */
struct {
diff --git a/src/third_party/wiredtiger/src/include/wt_internal.h b/src/third_party/wiredtiger/src/include/wt_internal.h
index 429c1c92c40..0d6319d6ec2 100644
--- a/src/third_party/wiredtiger/src/include/wt_internal.h
+++ b/src/third_party/wiredtiger/src/include/wt_internal.h
@@ -211,6 +211,10 @@ struct __wt_fstream;
typedef struct __wt_fstream WT_FSTREAM;
struct __wt_hazard;
typedef struct __wt_hazard WT_HAZARD;
+struct __wt_hazard_weak;
+typedef struct __wt_hazard_weak WT_HAZARD_WEAK;
+struct __wt_hazard_weak_array;
+typedef struct __wt_hazard_weak_array WT_HAZARD_WEAK_ARRAY;
struct __wt_ikey;
typedef struct __wt_ikey WT_IKEY;
struct __wt_index;
diff --git a/src/third_party/wiredtiger/src/session/session_api.c b/src/third_party/wiredtiger/src/session/session_api.c
index 74e2cdab612..ca4762298e2 100644
--- a/src/third_party/wiredtiger/src/session/session_api.c
+++ b/src/third_party/wiredtiger/src/session/session_api.c
@@ -191,6 +191,8 @@ __wt_session_release_resources(WT_SESSION_IMPL *session)
static void
__session_clear(WT_SESSION_IMPL *session)
{
+ WT_HAZARD_WEAK_ARRAY *wha;
+
/*
* There's no serialization support around the review of the hazard array, which means threads
* checking for hazard pointers first check the active field (which may be 0) and then use the
@@ -205,6 +207,11 @@ __session_clear(WT_SESSION_IMPL *session)
session->hazard_inuse = 0;
session->nhazard = 0;
+
+ for (wha = session->hazard_weak; wha != NULL; wha = wha->next) {
+ wha->hazard_inuse = 0;
+ wha->nhazard = 0;
+ }
}
/*
@@ -2064,6 +2071,13 @@ __open_session(WT_CONNECTION_IMPL *conn, WT_EVENT_HANDLER *event_handler, const
session_ret->hazard_size = WT_SESSION_INITIAL_HAZARD_SLOTS;
session_ret->hazard_inuse = 0;
session_ret->nhazard = 0;
+
+ WT_ERR(__wt_calloc(session, 1,
+ sizeof(WT_HAZARD_WEAK_ARRAY) + WT_SESSION_INITIAL_HAZARD_SLOTS * sizeof(WT_HAZARD_WEAK),
+ &session_ret->hazard_weak));
+ session_ret->hazard_weak->hazard_size = WT_SESSION_INITIAL_HAZARD_SLOTS;
+ session_ret->hazard_weak->hazard_inuse = 0;
+ session_ret->hazard_weak->nhazard = 0;
}
/*
diff --git a/src/third_party/wiredtiger/src/support/hazard.c b/src/third_party/wiredtiger/src/support/hazard.c
index 0470f441cd5..1eaf46992ff 100644
--- a/src/third_party/wiredtiger/src/support/hazard.c
+++ b/src/third_party/wiredtiger/src/support/hazard.c
@@ -7,7 +7,6 @@
*/
#include "wt_internal.h"
-
#ifdef HAVE_DIAGNOSTIC
static void __hazard_dump(WT_SESSION_IMPL *);
#endif
@@ -51,7 +50,8 @@ hazard_grow(WT_SESSION_IMPL *session)
* leak the memory.
*/
__wt_gen_next(session, WT_GEN_HAZARD, &hazard_gen);
- WT_IGNORE_RET(__wt_stash_add(session, WT_GEN_HAZARD, hazard_gen, ohazard, 0));
+ WT_IGNORE_RET(
+ __wt_stash_add(session, WT_GEN_HAZARD, hazard_gen, ohazard, size * sizeof(WT_HAZARD)));
return (0);
}
@@ -237,7 +237,7 @@ __wt_hazard_close(WT_SESSION_IMPL *session)
break;
}
if (session->nhazard == 0 && !found)
- return;
+ goto weak;
__wt_errx(session, "session %p: close hazard pointer table: table not empty", (void *)session);
@@ -263,6 +263,10 @@ __wt_hazard_close(WT_SESSION_IMPL *session)
if (session->nhazard != 0)
__wt_errx(session, "session %p: close hazard pointer table: count didn't match entries",
(void *)session);
+
+weak:
+ /* Same for weak hazard pointers. */
+ __wt_hazard_weak_close(session);
}
/*
@@ -361,7 +365,8 @@ __wt_hazard_count(WT_SESSION_IMPL *session, WT_REF *ref)
uint32_t i, hazard_inuse;
u_int count;
- hazard_get_reference(session, &hp, &hazard_inuse);
+ hp = session->hazard;
+ hazard_inuse = session->hazard_inuse;
for (count = 0, i = 0; i < hazard_inuse; ++hp, ++i)
if (hp->ref == ref)
diff --git a/src/third_party/wiredtiger/src/support/hazard_weak.c b/src/third_party/wiredtiger/src/support/hazard_weak.c
new file mode 100644
index 00000000000..463a8afe097
--- /dev/null
+++ b/src/third_party/wiredtiger/src/support/hazard_weak.c
@@ -0,0 +1,280 @@
+/*-
+ * Copyright (c) 2014-present MongoDB, Inc.
+ * Copyright (c) 2008-2014 WiredTiger, Inc.
+ * All rights reserved.
+ *
+ * See the file LICENSE for redistribution information.
+ */
+
+#include "wt_internal.h"
+
+#define WT_HAZARD_WEAK_FORALL(s, wha, whp) \
+ for (wha = (s)->hazard_weak; wha != NULL; wha = wha->next) \
+ for (whp = wha->hazard; whp < wha->hazard + wha->hazard_inuse; whp++)
+
+#define WT_HAZARD_WEAK_FORALL_BARRIER(s, wha, whp) \
+ for (wha = (s)->hazard_weak; wha != NULL; wha = wha->next) { \
+ uint32_t __hazard_inuse; \
+ WT_ORDERED_READ(__hazard_inuse, wha->hazard_inuse); \
+ for (whp = wha->hazard; whp < wha->hazard + __hazard_inuse; whp++)
+
+#define WT_HAZARD_WEAK_FORALL_BARRIER_END }
+
+/*
+ * __wt_hazard_weak_close --
+ * Verify that no weak hazard pointers are set.
+ */
+void
+__wt_hazard_weak_close(WT_SESSION_IMPL *session)
+{
+ WT_HAZARD_WEAK *whp;
+ WT_HAZARD_WEAK_ARRAY *wha;
+ uint32_t nhazard_weak;
+ bool found;
+
+ /*
+ * Check for a set weak hazard pointer and complain if we find one. We could just check the
+ * session's weak hazard pointer count, but this is a useful diagnostic.
+ */
+ for (found = false, nhazard_weak = 0, wha = session->hazard_weak; wha != NULL;
+ nhazard_weak += wha->nhazard, wha = wha->next)
+ for (whp = wha->hazard; whp < wha->hazard + wha->hazard_inuse; whp++)
+ if (whp->ref != NULL) {
+ found = true;
+ break;
+ }
+
+ if (nhazard_weak == 0 && !found)
+ return;
+
+ __wt_errx(
+ session, "session %p: close weak hazard pointer table: table not empty", (void *)session);
+
+ WT_HAZARD_WEAK_FORALL (session, wha, whp)
+ if (whp->ref != NULL) {
+ whp->ref = NULL;
+ --wha->nhazard;
+ --nhazard_weak;
+ }
+
+ if (nhazard_weak != 0)
+ __wt_errx(session,
+ "session %p: close weak hazard pointer table: count didn't match entries",
+ (void *)session);
+}
+
+/*
+ * hazard_weak_grow --
+ * Grow a weak hazard pointer array. What we have is a list of arrays doubling in size, with the
+ * largest array being at the head of the list. The array at the head of the list is the only
+ * one we actively use to set the new weak hazard pointers. The older arrays get emptied as the
+ * sessions using them resolve their transactions, eventually leaving them all empty.
+ */
+static int
+hazard_weak_grow(WT_SESSION_IMPL *session)
+{
+ WT_HAZARD_WEAK_ARRAY *wha;
+ size_t size;
+
+ /*
+ * Allocate a new, larger hazard pointer array and link it into place.
+ */
+ size = session->hazard_weak->hazard_size;
+ WT_RET(__wt_calloc(
+ session, sizeof(WT_HAZARD_WEAK_ARRAY) + 2 * size * sizeof(WT_HAZARD_WEAK), 1, &wha));
+ wha->next = session->hazard_weak;
+ wha->hazard_size = (uint32_t)(size * 2);
+
+ /*
+ * Swap the new hazard pointer array into place after initialization is complete (initialization
+ * must complete before eviction can see the new hazard pointer array).
+ */
+ WT_PUBLISH(session->hazard_weak, wha);
+
+ return (0);
+}
+
+/*
+ * __wt_hazard_weak_destroy --
+ * Free all memory associated with weak hazard pointers
+ */
+void
+__wt_hazard_weak_destroy(WT_SESSION_IMPL *session_safe, WT_SESSION_IMPL *s)
+{
+ WT_HAZARD_WEAK_ARRAY *wha, *next;
+
+ for (wha = s->hazard_weak; wha != NULL; wha = next) {
+ next = wha->next;
+ __wt_free(session_safe, wha);
+ }
+}
+
+/*
+ * __wt_hazard_weak_set --
+ * Set a weak hazard pointer. A hazard pointer must be held on the ref.
+ */
+int
+__wt_hazard_weak_set(WT_SESSION_IMPL *session, WT_REF *ref, WT_TXN_OP *op)
+{
+ WT_HAZARD_WEAK *whp;
+ WT_HAZARD_WEAK_ARRAY *wha;
+
+ WT_ASSERT(session, ref != NULL);
+ WT_ASSERT(session, op->whp == NULL);
+
+ /* If a file can never be evicted, hazard pointers aren't required. */
+ if (F_ISSET(op->btree, WT_BTREE_IN_MEMORY))
+ return (0);
+
+ /* If we have filled the current hazard pointer array, grow it. */
+ for (wha = session->hazard_weak; wha != NULL && wha->nhazard >= wha->hazard_size;
+ wha = wha->next)
+ WT_ASSERT(
+ session, wha->nhazard == wha->hazard_size && wha->hazard_inuse == wha->hazard_size);
+
+ if (wha == NULL) {
+ WT_RET(hazard_weak_grow(session));
+ wha = session->hazard_weak;
+ }
+
+ /*
+ * If there are no available hazard pointer slots, make another one visible.
+ */
+ if (wha->nhazard >= wha->hazard_inuse) {
+ WT_ASSERT(
+ session, wha->nhazard == wha->hazard_inuse && wha->hazard_inuse < wha->hazard_size);
+ whp = &wha->hazard[wha->hazard_inuse++];
+ } else {
+ WT_ASSERT(
+ session, wha->nhazard < wha->hazard_inuse && wha->hazard_inuse <= wha->hazard_size);
+
+ /*
+ * There must be an empty slot in the array, find it. Skip most of the active slots by
+ * starting after the active count slot; there may be a free slot before there, but checking
+ * is expensive. If we reach the end of the array, continue the search from the beginning of
+ * the array.
+ */
+ for (whp = wha->hazard + wha->nhazard;; ++whp) {
+ if (whp >= wha->hazard + wha->hazard_inuse)
+ whp = wha->hazard;
+ if (whp->ref == NULL)
+ break;
+ }
+ }
+
+ ++wha->nhazard;
+
+ WT_ASSERT(session, whp->ref == NULL);
+
+ /*
+ * We rely on a hazard pointer protecting the ref, so for weak hazard pointers this is much
+ * simpler than the regular hazard pointer case.
+ */
+ whp->ref = ref;
+ whp->valid = true;
+
+ op->whp = whp;
+ return (0);
+}
+
+/*
+ * __wt_hazard_weak_clear --
+ * Clear a weak hazard pointer, given a modify operation.
+ */
+int
+__wt_hazard_weak_clear(WT_SESSION_IMPL *session, WT_TXN_OP *op)
+{
+ WT_HAZARD_WEAK *whp;
+ WT_HAZARD_WEAK_ARRAY *wha;
+
+ /* If a file can never be evicted, hazard pointers aren't required. */
+ if (F_ISSET(op->btree, WT_BTREE_IN_MEMORY))
+ return (0);
+
+ whp = op->whp;
+ /*
+ * An empty slot reflects a serious error, we should always find the weak hazard pointer. Panic,
+ * because we messed up in and it could imply corruption.
+ */
+ if (whp == NULL || whp->ref == NULL)
+ WT_RET_PANIC(session, WT_PANIC,
+ "session %p: could not find the weak hazard pointer for a modify operation",
+ (void *)session);
+
+ /*
+ * We don't publish the weak hazard pointer clear as we only clear while holding the hazard
+ * pointer to the page, preventing eviction from looking for this weak pointer.
+ */
+ whp->ref = NULL;
+
+ /*
+ * Find the array this hazard pointer belongs to, and do the accounting for using one less slot.
+ */
+ for (wha = session->hazard_weak; wha != NULL; wha = wha->next) {
+ if (whp >= wha->hazard && whp < wha->hazard + wha->hazard_size) {
+ if (wha->nhazard == 0)
+ WT_RET_PANIC(session, EINVAL,
+ "session %p: While clearing weak hazard pointer, the count of the pointers "
+ "went negative for the relevant array.",
+ (void *)session);
+ if (--wha->nhazard == 0)
+ WT_PUBLISH(wha->hazard_inuse, 0);
+ break;
+ }
+ }
+ /*
+ * We should always be able to find the array. Panic, because we messed up and it could imply
+ * corruption.
+ */
+ if (wha == NULL)
+ WT_RET_PANIC(session, EINVAL,
+ "session %p: While clearing weak hazard pointer could not find the array.",
+ (void *)session);
+
+ /* Clear the hazard stored in the modify operation. */
+ op->whp = NULL;
+
+ return (0);
+}
+
+/*
+ * __wt_hazard_weak_invalidate --
+ * Invalidate any weak hazard pointers on a page that is locked for eviction.
+ */
+void
+__wt_hazard_weak_invalidate(WT_SESSION_IMPL *session, WT_REF *ref)
+{
+ WT_CONNECTION_IMPL *conn;
+ WT_HAZARD_WEAK *whp;
+ WT_HAZARD_WEAK_ARRAY *wha;
+ WT_SESSION_IMPL *s;
+ uint32_t i, session_cnt, walk_cnt;
+
+ /* If a file can never be evicted, hazard pointers aren't required. */
+ if (F_ISSET(S2BT(session), WT_BTREE_IN_MEMORY))
+ return;
+
+ conn = S2C(session);
+
+ /*
+ * No lock is required because the session array is fixed size, but it may contain inactive
+ * entries. We must review any active session that might contain a hazard pointer, so insert a
+ * read barrier after reading the active session count. That way, no matter what sessions come
+ * or go, we'll check the slots for all of the sessions that could have been active when we
+ * started our check.
+ */
+ WT_ORDERED_READ(session_cnt, conn->session_cnt);
+ for (s = conn->sessions, i = walk_cnt = 0; i < session_cnt; ++s, ++i) {
+ if (!s->active)
+ continue;
+
+ WT_HAZARD_WEAK_FORALL_BARRIER(s, wha, whp)
+ {
+ ++walk_cnt;
+ if (whp->ref == ref)
+ whp->valid = false;
+ }
+ WT_HAZARD_WEAK_FORALL_BARRIER_END
+ }
+ WT_STAT_CONN_INCRV(session, cache_hazard_walks, walk_cnt);
+}
diff --git a/src/third_party/wiredtiger/src/txn/txn.c b/src/third_party/wiredtiger/src/txn/txn.c
index bddfbe26ac7..7930ba85341 100644
--- a/src/third_party/wiredtiger/src/txn/txn.c
+++ b/src/third_party/wiredtiger/src/txn/txn.c
@@ -1780,6 +1780,14 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[])
}
/*
+ * For now just confirm that each operation has a weak hazard pointer and clear it
+ * before proceeding.
+ */
+ if ((op->type == WT_TXN_OP_BASIC_ROW || op->type == WT_TXN_OP_INMEM_ROW) &&
+ !WT_IS_METADATA(op->btree->dhandle) && upd->type != WT_UPDATE_RESERVE)
+ WT_ERR(__wt_hazard_weak_clear(session, op));
+
+ /*
* Don't reset the timestamp of the history store records with history store
* transaction timestamp. Those records should already have the original time window
* when they are inserted into the history store.
@@ -2022,6 +2030,14 @@ __wt_txn_prepare(WT_SESSION_IMPL *session, const char *cfg[])
break;
}
+ /*
+ * For now just confirm that each operation has a weak hazard pointer and clear it
+ * before proceeding.
+ */
+ if ((op->type == WT_TXN_OP_BASIC_ROW || op->type == WT_TXN_OP_INMEM_ROW) &&
+ !WT_IS_METADATA(op->btree->dhandle) && upd->type != WT_UPDATE_RESERVE)
+ WT_RET(__wt_hazard_weak_clear(session, op));
+
++prepared_updates;
/* Set prepare timestamp. */
@@ -2146,6 +2162,14 @@ __wt_txn_rollback(WT_SESSION_IMPL *session, const char *cfg[])
upd = op->u.op_upd;
if (!prepare) {
+ /*
+ * For now just confirm that each operation has a weak hazard pointer and clear it
+ * before proceeding.
+ */
+ if ((op->type == WT_TXN_OP_BASIC_ROW || op->type == WT_TXN_OP_INMEM_ROW) &&
+ !WT_IS_METADATA(op->btree->dhandle) && upd->type != WT_UPDATE_RESERVE)
+ WT_TRET(__wt_hazard_weak_clear(session, op));
+
if (S2C(session)->cache->hs_fileid != 0 &&
op->btree->id == S2C(session)->cache->hs_fileid)
break;
diff --git a/src/third_party/wiredtiger/src/txn/txn_log.c b/src/third_party/wiredtiger/src/txn/txn_log.c
index 192dfc09cf2..cbed44285bc 100644
--- a/src/third_party/wiredtiger/src/txn/txn_log.c
+++ b/src/third_party/wiredtiger/src/txn/txn_log.c
@@ -162,6 +162,9 @@ __txn_oplist_printlog(
void
__wt_txn_op_free(WT_SESSION_IMPL *session, WT_TXN_OP *op)
{
+ /* The weak pointer should have already been freed. */
+ WT_ASSERT(session, op->whp == NULL);
+
switch (op->type) {
case WT_TXN_OP_NONE:
/*
@@ -257,12 +260,6 @@ __wt_txn_log_op(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt)
conn = S2C(session);
txn = session->txn;
- if (!FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED) ||
- F_ISSET(session, WT_SESSION_NO_LOGGING) ||
- (F_ISSET(S2BT(session), WT_BTREE_NO_LOGGING) &&
- !FLD_ISSET(conn->log_flags, WT_CONN_LOG_DEBUG_MODE)))
- return (0);
-
/* We'd better have a transaction. */
WT_ASSERT(session, F_ISSET(txn, WT_TXN_RUNNING) && F_ISSET(txn, WT_TXN_HAS_ID));
@@ -270,6 +267,20 @@ __wt_txn_log_op(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt)
op = txn->mod + txn->mod_count - 1;
fileid = op->btree->id;
+ /* Set the weak hazard pointer for this update. */
+ if ((op->type == WT_TXN_OP_BASIC_ROW || op->type == WT_TXN_OP_INMEM_ROW)) {
+ if (!WT_IS_METADATA(op->btree->dhandle)) {
+ WT_ASSERT(session, cbt != NULL);
+ WT_RET(__wt_hazard_weak_set(session, cbt->ref, op));
+ }
+ }
+
+ if (!FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED) ||
+ F_ISSET(session, WT_SESSION_NO_LOGGING) ||
+ (F_ISSET(S2BT(session), WT_BTREE_NO_LOGGING) &&
+ !FLD_ISSET(conn->log_flags, WT_CONN_LOG_DEBUG_MODE)))
+ return (0);
+
/*
* If this operation is diagnostic only, set the ignore bit on the fileid so that recovery can
* skip it.