summaryrefslogtreecommitdiff
path: root/src/support
diff options
context:
space:
mode:
Diffstat (limited to 'src/support')
-rw-r--r--src/support/cond_auto.c80
-rw-r--r--src/support/crypto.c1
-rw-r--r--src/support/err.c119
-rw-r--r--src/support/mtx_rw.c93
-rw-r--r--src/support/rand.c12
-rw-r--r--src/support/scratch.c9
-rw-r--r--src/support/stat.c48
-rw-r--r--src/support/thread_group.c85
8 files changed, 215 insertions, 232 deletions
diff --git a/src/support/cond_auto.c b/src/support/cond_auto.c
index a3ae67f5baa..600e5eab0ff 100644
--- a/src/support/cond_auto.c
+++ b/src/support/cond_auto.c
@@ -1,29 +1,9 @@
/*-
- * Public Domain 2014-2016 MongoDB, Inc.
- * Public Domain 2008-2014 WiredTiger, Inc.
+ * Copyright (c) 2014-2016 MongoDB, Inc.
+ * Copyright (c) 2008-2014 WiredTiger, Inc.
+ * All rights reserved.
*
- * This is free and unencumbered software released into the public domain.
- *
- * Anyone is free to copy, modify, publish, use, compile, sell, or
- * distribute this software, either in source code form or as a compiled
- * binary, for any purpose, commercial or non-commercial, and by any
- * means.
- *
- * In jurisdictions that recognize copyright laws, the author or authors
- * of this software dedicate any and all copyright interest in the
- * software to the public domain. We make this dedication for the benefit
- * of the public at large and to the detriment of our heirs and
- * successors. We intend this dedication to be an overt act of
- * relinquishment in perpetuity of all present and future rights to this
- * software under copyright law.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * See the file LICENSE for redistribution information.
*/
#include "wt_internal.h"
@@ -38,13 +18,12 @@
* Allocate and initialize an automatically adjusting condition variable.
*/
int
-__wt_cond_auto_alloc(
- WT_SESSION_IMPL *session, const char *name,
- bool is_signalled, uint64_t min, uint64_t max, WT_CONDVAR **condp)
+__wt_cond_auto_alloc(WT_SESSION_IMPL *session,
+ const char *name, uint64_t min, uint64_t max, WT_CONDVAR **condp)
{
WT_CONDVAR *cond;
- WT_RET(__wt_cond_alloc(session, name, is_signalled, condp));
+ WT_RET(__wt_cond_alloc(session, name, condp));
cond = *condp;
cond->min_wait = min;
@@ -55,33 +34,19 @@ __wt_cond_auto_alloc(
}
/*
- * __wt_cond_auto_signal --
- * Signal a condition variable.
- */
-void
-__wt_cond_auto_signal(WT_SESSION_IMPL *session, WT_CONDVAR *cond)
-{
-
- WT_ASSERT(session, cond->min_wait != 0);
- __wt_cond_signal(session, cond);
-}
-
-/*
* __wt_cond_auto_wait_signal --
* Wait on a mutex, optionally timing out. If we get it before the time
* out period expires, let the caller know.
- * TODO: Can this version of the API be removed, now that we have the
- * auto adjusting condition variables?
*/
void
-__wt_cond_auto_wait_signal(
- WT_SESSION_IMPL *session, WT_CONDVAR *cond, bool progress, bool *signalled)
+__wt_cond_auto_wait_signal(WT_SESSION_IMPL *session, WT_CONDVAR *cond,
+ bool progress, bool (*run_func)(WT_SESSION_IMPL *), bool *signalled)
{
uint64_t delta;
/*
* Catch cases where this function is called with a condition variable
- * that was initialized non-auto.
+ * that wasn't initialized to do automatic adjustments.
*/
WT_ASSERT(session, cond->min_wait != 0);
@@ -94,7 +59,8 @@ __wt_cond_auto_wait_signal(
cond->max_wait, cond->prev_wait + delta);
}
- __wt_cond_wait_signal(session, cond, cond->prev_wait, signalled);
+ __wt_cond_wait_signal(
+ session, cond, cond->prev_wait, run_func, signalled);
if (progress || *signalled)
WT_STAT_CONN_INCR(session, cond_auto_wait_reset);
@@ -108,24 +74,10 @@ __wt_cond_auto_wait_signal(
* out period expires, let the caller know.
*/
void
-__wt_cond_auto_wait(
- WT_SESSION_IMPL *session, WT_CONDVAR *cond, bool progress)
+__wt_cond_auto_wait(WT_SESSION_IMPL *session,
+ WT_CONDVAR *cond, bool progress, bool (*run_func)(WT_SESSION_IMPL *))
{
- bool signalled;
-
- /*
- * Call the signal version so the wait period is reset if the
- * condition is woken explicitly.
- */
- __wt_cond_auto_wait_signal(session, cond, progress, &signalled);
-}
+ bool notused;
-/*
- * __wt_cond_auto_destroy --
- * Destroy a condition variable.
- */
-int
-__wt_cond_auto_destroy(WT_SESSION_IMPL *session, WT_CONDVAR **condp)
-{
- return (__wt_cond_destroy(session, condp));
+ __wt_cond_auto_wait_signal(session, cond, progress, run_func, &notused);
}
diff --git a/src/support/crypto.c b/src/support/crypto.c
index ab94ec2c829..cce0d228832 100644
--- a/src/support/crypto.c
+++ b/src/support/crypto.c
@@ -133,5 +133,4 @@ __wt_encrypt_size(WT_SESSION_IMPL *session,
return;
*sizep = incoming_size + kencryptor->size_const + WT_ENCRYPT_LEN_SIZE;
- return;
}
diff --git a/src/support/err.c b/src/support/err.c
index 369997d38c0..57efde72b23 100644
--- a/src/support/err.c
+++ b/src/support/err.c
@@ -102,9 +102,10 @@ __handler_failure(WT_SESSION_IMPL *session,
*/
char s[256];
- (void)snprintf(s, sizeof(s),
+ if (__wt_snprintf(s, sizeof(s),
"application %s event handler failed: %s",
- which, __wt_strerror(session, error, NULL, 0));
+ which, __wt_strerror(session, error, NULL, 0)) != 0)
+ return;
/*
* Use the error handler to report the failure, unless it was the error
@@ -148,6 +149,23 @@ __wt_event_handler_set(WT_SESSION_IMPL *session, WT_EVENT_HANDLER *handler)
session->event_handler = handler;
}
+#define WT_ERROR_APPEND(p, remain, ...) do { \
+ size_t __len; \
+ WT_ERR(__wt_snprintf_len_set(p, remain, &__len, __VA_ARGS__)); \
+ if (__len > remain) \
+ __len = remain; \
+ p += __len; \
+ remain -= __len; \
+} while (0)
+#define WT_ERROR_APPEND_AP(p, remain, ...) do { \
+ size_t __len; \
+ WT_ERR(__wt_vsnprintf_len_set(p, remain, &__len, __VA_ARGS__)); \
+ if (__len > remain) \
+ __len = remain; \
+ p += __len; \
+ remain -= __len; \
+} while (0)
+
/*
* __wt_eventv --
* Report a message to an event handler.
@@ -161,9 +179,9 @@ __wt_eventv(WT_SESSION_IMPL *session, bool msg_event, int error,
WT_DECL_RET;
WT_SESSION *wt_session;
struct timespec ts;
- size_t len, remain, wlen;
+ size_t len, remain;
const char *err, *prefix;
- char *end, *p, tid[128];
+ char *p, tid[128];
/*
* We're using a stack buffer because we want error messages no matter
@@ -174,6 +192,8 @@ __wt_eventv(WT_SESSION_IMPL *session, bool msg_event, int error,
* Buffer placed at the end of the stack in case snprintf overflows.
*/
char s[2048];
+ p = s;
+ remain = sizeof(s);
/*
* !!!
@@ -185,24 +205,8 @@ __wt_eventv(WT_SESSION_IMPL *session, bool msg_event, int error,
* first session, but if the allocation of the first session fails, for
* example, we can end up here without a session.)
*/
- if (session == NULL) {
- if (fprintf(stderr,
- "WiredTiger Error%s%s: ",
- error == 0 ? "" : ": ",
- error == 0 ? "" :
- __wt_strerror(session, error, NULL, 0)) < 0)
- ret = EIO;
- if (vfprintf(stderr, fmt, ap) < 0)
- ret = EIO;
- if (fprintf(stderr, "\n") < 0)
- ret = EIO;
- if (fflush(stderr) != 0)
- ret = EIO;
- return (ret);
- }
-
- p = s;
- end = s + sizeof(s);
+ if (session == NULL)
+ goto err;
/*
* We have several prefixes for the error message: a timestamp and the
@@ -211,42 +215,24 @@ __wt_eventv(WT_SESSION_IMPL *session, bool msg_event, int error,
* followed by a colon.
*/
__wt_epoch(session, &ts);
- __wt_thread_id(tid, sizeof(tid));
- remain = WT_PTRDIFF(end, p);
- wlen = (size_t)snprintf(p, remain, "[%" PRIuMAX ":%" PRIuMAX "][%s]",
+ WT_ERR(__wt_thread_id(tid, sizeof(tid)));
+ WT_ERROR_APPEND(p, remain,
+ "[%" PRIuMAX ":%" PRIuMAX "][%s]",
(uintmax_t)ts.tv_sec, (uintmax_t)ts.tv_nsec / WT_THOUSAND, tid);
- p = wlen >= remain ? end : p + wlen;
- if ((prefix = S2C(session)->error_prefix) != NULL) {
- remain = WT_PTRDIFF(end, p);
- wlen = (size_t)snprintf(p, remain, ", %s", prefix);
- p = wlen >= remain ? end : p + wlen;
- }
+ if ((prefix = S2C(session)->error_prefix) != NULL)
+ WT_ERROR_APPEND(p, remain, ", %s", prefix);
prefix = session->dhandle == NULL ? NULL : session->dhandle->name;
- if (prefix != NULL) {
- remain = WT_PTRDIFF(end, p);
- wlen = (size_t)snprintf(p, remain, ", %s", prefix);
- p = wlen >= remain ? end : p + wlen;
- }
- if ((prefix = session->name) != NULL) {
- remain = WT_PTRDIFF(end, p);
- wlen = (size_t)snprintf(p, remain, ", %s", prefix);
- p = wlen >= remain ? end : p + wlen;
- }
- remain = WT_PTRDIFF(end, p);
- wlen = (size_t)snprintf(p, remain, ": ");
- p = wlen >= remain ? end : p + wlen;
-
- if (file_name != NULL) {
- remain = WT_PTRDIFF(end, p);
- wlen = (size_t)
- snprintf(p, remain, "%s, %d: ", file_name, line_number);
- p = wlen >= remain ? end : p + wlen;
- }
+ if (prefix != NULL)
+ WT_ERROR_APPEND(p, remain, ", %s", prefix);
+ if ((prefix = session->name) != NULL)
+ WT_ERROR_APPEND(p, remain, ", %s", prefix);
+ WT_ERROR_APPEND(p, remain, ": ");
+
+ if (file_name != NULL)
+ WT_ERROR_APPEND(p, remain, "%s, %d: ", file_name, line_number);
- remain = WT_PTRDIFF(end, p);
- wlen = (size_t)vsnprintf(p, remain, fmt, ap);
- p = wlen >= remain ? end : p + wlen;
+ WT_ERROR_APPEND_AP(p, remain, fmt, ap);
if (error != 0) {
/*
@@ -261,10 +247,8 @@ __wt_eventv(WT_SESSION_IMPL *session, bool msg_event, int error,
*/
err = __wt_strerror(session, error, NULL, 0);
len = strlen(err);
- if (WT_PTRDIFF(p, s) < len || strcmp(p - len, err) != 0) {
- remain = WT_PTRDIFF(end, p);
- (void)snprintf(p, remain, ": %s", err);
- }
+ if (WT_PTRDIFF(p, s) < len || strcmp(p - len, err) != 0)
+ WT_ERROR_APPEND(p, remain, ": %s", err);
}
/*
@@ -279,7 +263,7 @@ __wt_eventv(WT_SESSION_IMPL *session, bool msg_event, int error,
*
* If an application-specified error message handler fails, complain
* using the default error handler. If the default error handler fails,
- * there's nothing to do.
+ * fallback to stderr.
*/
wt_session = (WT_SESSION *)session;
handler = session->event_handler;
@@ -293,6 +277,21 @@ __wt_eventv(WT_SESSION_IMPL *session, bool msg_event, int error,
__handler_failure(session, ret, "error", true);
}
+ if (ret != 0) {
+err: if (fprintf(stderr,
+ "WiredTiger Error%s%s: ",
+ error == 0 ? "" : ": ",
+ error == 0 ? "" :
+ __wt_strerror(session, error, NULL, 0)) < 0)
+ WT_TRET(EIO);
+ if (vfprintf(stderr, fmt, ap) < 0)
+ WT_TRET(EIO);
+ if (fprintf(stderr, "\n") < 0)
+ WT_TRET(EIO);
+ if (fflush(stderr) != 0)
+ WT_TRET(EIO);
+ }
+
return (ret);
}
@@ -376,7 +375,7 @@ info_msg(WT_SESSION_IMPL *session, const char *fmt, va_list ap)
*/
char s[2048];
- (void)vsnprintf(s, sizeof(s), fmt, ap);
+ WT_RET(__wt_vsnprintf(s, sizeof(s), fmt, ap));
wt_session = (WT_SESSION *)session;
handler = session->event_handler;
diff --git a/src/support/mtx_rw.c b/src/support/mtx_rw.c
index ea18f556257..35ad5da23f2 100644
--- a/src/support/mtx_rw.c
+++ b/src/support/mtx_rw.c
@@ -115,23 +115,27 @@
#include "wt_internal.h"
/*
- * __wt_rwlock_alloc --
- * Allocate and initialize a read/write lock.
+ * __wt_rwlock_init --
+ * Initialize a read/write lock.
*/
-int
-__wt_rwlock_alloc(
- WT_SESSION_IMPL *session, WT_RWLOCK **rwlockp, const char *name)
+void
+__wt_rwlock_init(WT_SESSION_IMPL *session, WT_RWLOCK *l)
{
- WT_RWLOCK *rwlock;
-
- __wt_verbose(session, WT_VERB_MUTEX, "rwlock: alloc %s", name);
+ WT_UNUSED(session);
- WT_RET(__wt_calloc_one(session, &rwlock));
+ l->u = 0;
+}
- rwlock->name = name;
+/*
+ * __wt_rwlock_destroy --
+ * Destroy a read/write lock.
+ */
+void
+__wt_rwlock_destroy(WT_SESSION_IMPL *session, WT_RWLOCK *l)
+{
+ WT_UNUSED(session);
- *rwlockp = rwlock;
- return (0);
+ l->u = 0;
}
/*
@@ -139,13 +143,12 @@ __wt_rwlock_alloc(
* Try to get a shared lock, fail immediately if unavailable.
*/
int
-__wt_try_readlock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
+__wt_try_readlock(WT_SESSION_IMPL *session, WT_RWLOCK *l)
{
- wt_rwlock_t *l, new, old;
+ WT_RWLOCK new, old;
WT_STAT_CONN_INCR(session, rwlock_read);
- l = &rwlock->rwlock;
new = old = *l;
/*
@@ -172,19 +175,15 @@ __wt_try_readlock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
* exclusive.
*/
void
-__wt_readlock_spin(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
+__wt_readlock_spin(WT_SESSION_IMPL *session, WT_RWLOCK *l)
{
- wt_rwlock_t *l;
-
- l = &rwlock->rwlock;
-
/*
* Try to get the lock in a single operation if it is available to
* readers. This avoids the situation where multiple readers arrive
* concurrently and have to line up in order to enter the lock. For
* read-heavy workloads it can make a significant difference.
*/
- while (__wt_try_readlock(session, rwlock) != 0) {
+ while (__wt_try_readlock(session, l) != 0) {
if (l->s.writers_active > 0)
__wt_yield();
else
@@ -197,9 +196,8 @@ __wt_readlock_spin(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
* Get a shared lock.
*/
void
-__wt_readlock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
+__wt_readlock(WT_SESSION_IMPL *session, WT_RWLOCK *l)
{
- wt_rwlock_t *l;
uint16_t ticket;
int pause_cnt;
@@ -207,8 +205,6 @@ __wt_readlock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
WT_DIAGNOSTIC_YIELD;
- l = &rwlock->rwlock;
-
/*
* Possibly wrap: if we have more than 64K lockers waiting, the ticket
* value will wrap and two lockers will simultaneously be granted the
@@ -246,14 +242,10 @@ __wt_readlock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
* Release a shared lock.
*/
void
-__wt_readunlock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
+__wt_readunlock(WT_SESSION_IMPL *session, WT_RWLOCK *l)
{
- wt_rwlock_t *l;
-
WT_UNUSED(session);
- l = &rwlock->rwlock;
-
/*
* Increment the writers value (other readers are doing the same, make
* sure we don't race).
@@ -266,13 +258,12 @@ __wt_readunlock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
* Try to get an exclusive lock, fail immediately if unavailable.
*/
int
-__wt_try_writelock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
+__wt_try_writelock(WT_SESSION_IMPL *session, WT_RWLOCK *l)
{
- wt_rwlock_t *l, new, old;
+ WT_RWLOCK new, old;
WT_STAT_CONN_INCR(session, rwlock_write);
- l = &rwlock->rwlock;
old = new = *l;
/*
@@ -296,16 +287,13 @@ __wt_try_writelock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
* Wait to get an exclusive lock.
*/
void
-__wt_writelock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
+__wt_writelock(WT_SESSION_IMPL *session, WT_RWLOCK *l)
{
- wt_rwlock_t *l;
uint16_t ticket;
int pause_cnt;
WT_STAT_CONN_INCR(session, rwlock_write);
- l = &rwlock->rwlock;
-
/*
* Possibly wrap: if we have more than 64K lockers waiting, the ticket
* value will wrap and two lockers will simultaneously be granted the
@@ -338,13 +326,12 @@ __wt_writelock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
* Release an exclusive lock.
*/
void
-__wt_writeunlock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
+__wt_writeunlock(WT_SESSION_IMPL *session, WT_RWLOCK *l)
{
- wt_rwlock_t *l, new;
+ WT_RWLOCK new;
WT_UNUSED(session);
- l = &rwlock->rwlock;
(void)__wt_atomic_sub16(&l->s.writers_active, 1);
/*
@@ -368,40 +355,16 @@ __wt_writeunlock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
WT_DIAGNOSTIC_YIELD;
}
-/*
- * __wt_rwlock_destroy --
- * Destroy a read/write lock.
- */
-void
-__wt_rwlock_destroy(WT_SESSION_IMPL *session, WT_RWLOCK **rwlockp)
-{
- WT_RWLOCK *rwlock;
-
- rwlock = *rwlockp; /* Clear our caller's reference. */
- if (rwlock == NULL)
- return;
- *rwlockp = NULL;
-
- __wt_verbose(
- session, WT_VERB_MUTEX, "rwlock: destroy %s", rwlock->name);
-
- __wt_free(session, rwlock);
-}
-
#ifdef HAVE_DIAGNOSTIC
/*
* __wt_rwlock_islocked --
* Return if a read/write lock is currently locked for reading or writing.
*/
bool
-__wt_rwlock_islocked(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
+__wt_rwlock_islocked(WT_SESSION_IMPL *session, WT_RWLOCK *l)
{
- wt_rwlock_t *l;
-
WT_UNUSED(session);
- l = &rwlock->rwlock;
-
return (l->s.writers != l->s.next || l->s.readers != l->s.next);
}
#endif
diff --git a/src/support/rand.c b/src/support/rand.c
index a5b229b9abc..4fae43edc8e 100644
--- a/src/support/rand.c
+++ b/src/support/rand.c
@@ -120,3 +120,15 @@ __wt_random(WT_RAND_STATE volatile * rnd_state)
return ((z << 16) + (w & 65535));
}
+
+/*
+ * __wt_random64 --
+ * Return a 64-bit pseudo-random number.
+ */
+uint64_t
+__wt_random64(WT_RAND_STATE volatile * rnd_state)
+ WT_GCC_FUNC_ATTRIBUTE((visibility("default")))
+{
+ return (((uint64_t)__wt_random(rnd_state) << 32) +
+ __wt_random(rnd_state));
+}
diff --git a/src/support/scratch.c b/src/support/scratch.c
index 69987ebc852..485cea90e89 100644
--- a/src/support/scratch.c
+++ b/src/support/scratch.c
@@ -69,13 +69,16 @@ int
__wt_buf_fmt(WT_SESSION_IMPL *session, WT_ITEM *buf, const char *fmt, ...)
WT_GCC_FUNC_ATTRIBUTE((format (printf, 3, 4)))
{
+ WT_DECL_RET;
va_list ap;
size_t len;
for (;;) {
va_start(ap, fmt);
- len = (size_t)vsnprintf(buf->mem, buf->memsize, fmt, ap);
+ ret = __wt_vsnprintf_len_set(
+ buf->mem, buf->memsize, &len, fmt, ap);
va_end(ap);
+ WT_RET(ret);
/* Check if there was enough space. */
if (len < buf->memsize) {
@@ -100,6 +103,7 @@ int
__wt_buf_catfmt(WT_SESSION_IMPL *session, WT_ITEM *buf, const char *fmt, ...)
WT_GCC_FUNC_ATTRIBUTE((format (printf, 3, 4)))
{
+ WT_DECL_RET;
va_list ap;
size_t len, space;
char *p;
@@ -117,8 +121,9 @@ __wt_buf_catfmt(WT_SESSION_IMPL *session, WT_ITEM *buf, const char *fmt, ...)
p = (char *)((uint8_t *)buf->mem + buf->size);
WT_ASSERT(session, buf->memsize >= buf->size);
space = buf->memsize - buf->size;
- len = (size_t)vsnprintf(p, space, fmt, ap);
+ ret = __wt_vsnprintf_len_set(p, space, &len, fmt, ap);
va_end(ap);
+ WT_RET(ret);
/* Check if there was enough space. */
if (len < space) {
diff --git a/src/support/stat.c b/src/support/stat.c
index a9c0b24ef29..2c2217f8c20 100644
--- a/src/support/stat.c
+++ b/src/support/stat.c
@@ -64,6 +64,7 @@ static const char * const __stats_dsrc_desc[] = {
"cache: pages requested from the cache",
"cache: pages written from cache",
"cache: pages written requiring in-memory restoration",
+ "cache: tracked dirty bytes in the cache",
"cache: unmodified pages evicted",
"cache_walk: Average difference between current eviction generation when the page was last considered",
"cache_walk: Average on-disk page image size seen",
@@ -225,6 +226,7 @@ __wt_stat_dsrc_clear_single(WT_DSRC_STATS *stats)
stats->cache_pages_requested = 0;
stats->cache_write = 0;
stats->cache_write_restore = 0;
+ /* not clearing cache_bytes_dirty */
stats->cache_eviction_clean = 0;
/* not clearing cache_state_gen_avg_gap */
/* not clearing cache_state_avg_written_size */
@@ -372,6 +374,7 @@ __wt_stat_dsrc_aggregate_single(
to->cache_pages_requested += from->cache_pages_requested;
to->cache_write += from->cache_write;
to->cache_write_restore += from->cache_write_restore;
+ to->cache_bytes_dirty += from->cache_bytes_dirty;
to->cache_eviction_clean += from->cache_eviction_clean;
to->cache_state_gen_avg_gap += from->cache_state_gen_avg_gap;
to->cache_state_avg_written_size +=
@@ -535,6 +538,7 @@ __wt_stat_dsrc_aggregate(
WT_STAT_READ(from, cache_pages_requested);
to->cache_write += WT_STAT_READ(from, cache_write);
to->cache_write_restore += WT_STAT_READ(from, cache_write_restore);
+ to->cache_bytes_dirty += WT_STAT_READ(from, cache_bytes_dirty);
to->cache_eviction_clean += WT_STAT_READ(from, cache_eviction_clean);
to->cache_state_gen_avg_gap +=
WT_STAT_READ(from, cache_state_gen_avg_gap);
@@ -673,10 +677,15 @@ static const char * const __stats_connection_desc[] = {
"cache: eviction server unable to reach eviction goal",
"cache: eviction state",
"cache: eviction walks abandoned",
+ "cache: eviction worker thread active",
+ "cache: eviction worker thread created",
"cache: eviction worker thread evicting pages",
+ "cache: eviction worker thread removed",
+ "cache: eviction worker thread stable number",
"cache: failed eviction of pages that exceeded the in-memory maximum",
"cache: files with active eviction walks",
"cache: files with new eviction walks started",
+ "cache: force re-tuning of eviction workers once in a while",
"cache: hazard pointer blocked page eviction",
"cache: hazard pointer check calls",
"cache: hazard pointer check entries walked",
@@ -751,9 +760,7 @@ static const char * const __stats_connection_desc[] = {
"lock: checkpoint lock acquisitions",
"lock: checkpoint lock application thread wait time (usecs)",
"lock: checkpoint lock internal thread wait time (usecs)",
- "lock: handle-list lock acquisitions",
- "lock: handle-list lock application thread wait time (usecs)",
- "lock: handle-list lock internal thread wait time (usecs)",
+ "lock: handle-list lock eviction thread wait time (usecs)",
"lock: metadata lock acquisitions",
"lock: metadata lock application thread wait time (usecs)",
"lock: metadata lock internal thread wait time (usecs)",
@@ -765,9 +772,11 @@ static const char * const __stats_connection_desc[] = {
"lock: table lock internal thread time waiting for the table lock (usecs)",
"log: busy returns attempting to switch slots",
"log: consolidated slot closures",
+ "log: consolidated slot join active slot closed",
"log: consolidated slot join races",
"log: consolidated slot join transitions",
"log: consolidated slot joins",
+ "log: consolidated slot transitions unable to find free slot",
"log: consolidated slot unbuffered writes",
"log: log bytes of payload data",
"log: log bytes written",
@@ -954,10 +963,15 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats)
stats->cache_eviction_slow = 0;
/* not clearing cache_eviction_state */
stats->cache_eviction_walks_abandoned = 0;
+ /* not clearing cache_eviction_active_workers */
+ stats->cache_eviction_worker_created = 0;
stats->cache_eviction_worker_evicting = 0;
+ stats->cache_eviction_worker_removed = 0;
+ /* not clearing cache_eviction_stable_state_workers */
stats->cache_eviction_force_fail = 0;
/* not clearing cache_eviction_walks_active */
stats->cache_eviction_walks_started = 0;
+ stats->cache_eviction_force_retune = 0;
stats->cache_eviction_hazard = 0;
stats->cache_hazard_checks = 0;
stats->cache_hazard_walks = 0;
@@ -1032,9 +1046,7 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats)
stats->lock_checkpoint_count = 0;
stats->lock_checkpoint_wait_application = 0;
stats->lock_checkpoint_wait_internal = 0;
- stats->lock_handle_list_count = 0;
- stats->lock_handle_list_wait_application = 0;
- stats->lock_handle_list_wait_internal = 0;
+ stats->lock_handle_list_wait_eviction = 0;
stats->lock_metadata_count = 0;
stats->lock_metadata_wait_application = 0;
stats->lock_metadata_wait_internal = 0;
@@ -1046,9 +1058,11 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats)
stats->lock_table_wait_internal = 0;
stats->log_slot_switch_busy = 0;
stats->log_slot_closes = 0;
+ stats->log_slot_active_closed = 0;
stats->log_slot_races = 0;
stats->log_slot_transitions = 0;
stats->log_slot_joins = 0;
+ stats->log_slot_no_free_slots = 0;
stats->log_slot_unbuffered = 0;
stats->log_bytes_payload = 0;
stats->log_bytes_written = 0;
@@ -1228,14 +1242,24 @@ __wt_stat_connection_aggregate(
to->cache_eviction_state += WT_STAT_READ(from, cache_eviction_state);
to->cache_eviction_walks_abandoned +=
WT_STAT_READ(from, cache_eviction_walks_abandoned);
+ to->cache_eviction_active_workers +=
+ WT_STAT_READ(from, cache_eviction_active_workers);
+ to->cache_eviction_worker_created +=
+ WT_STAT_READ(from, cache_eviction_worker_created);
to->cache_eviction_worker_evicting +=
WT_STAT_READ(from, cache_eviction_worker_evicting);
+ to->cache_eviction_worker_removed +=
+ WT_STAT_READ(from, cache_eviction_worker_removed);
+ to->cache_eviction_stable_state_workers +=
+ WT_STAT_READ(from, cache_eviction_stable_state_workers);
to->cache_eviction_force_fail +=
WT_STAT_READ(from, cache_eviction_force_fail);
to->cache_eviction_walks_active +=
WT_STAT_READ(from, cache_eviction_walks_active);
to->cache_eviction_walks_started +=
WT_STAT_READ(from, cache_eviction_walks_started);
+ to->cache_eviction_force_retune +=
+ WT_STAT_READ(from, cache_eviction_force_retune);
to->cache_eviction_hazard +=
WT_STAT_READ(from, cache_eviction_hazard);
to->cache_hazard_checks += WT_STAT_READ(from, cache_hazard_checks);
@@ -1331,12 +1355,8 @@ __wt_stat_connection_aggregate(
WT_STAT_READ(from, lock_checkpoint_wait_application);
to->lock_checkpoint_wait_internal +=
WT_STAT_READ(from, lock_checkpoint_wait_internal);
- to->lock_handle_list_count +=
- WT_STAT_READ(from, lock_handle_list_count);
- to->lock_handle_list_wait_application +=
- WT_STAT_READ(from, lock_handle_list_wait_application);
- to->lock_handle_list_wait_internal +=
- WT_STAT_READ(from, lock_handle_list_wait_internal);
+ to->lock_handle_list_wait_eviction +=
+ WT_STAT_READ(from, lock_handle_list_wait_eviction);
to->lock_metadata_count += WT_STAT_READ(from, lock_metadata_count);
to->lock_metadata_wait_application +=
WT_STAT_READ(from, lock_metadata_wait_application);
@@ -1354,9 +1374,13 @@ __wt_stat_connection_aggregate(
WT_STAT_READ(from, lock_table_wait_internal);
to->log_slot_switch_busy += WT_STAT_READ(from, log_slot_switch_busy);
to->log_slot_closes += WT_STAT_READ(from, log_slot_closes);
+ to->log_slot_active_closed +=
+ WT_STAT_READ(from, log_slot_active_closed);
to->log_slot_races += WT_STAT_READ(from, log_slot_races);
to->log_slot_transitions += WT_STAT_READ(from, log_slot_transitions);
to->log_slot_joins += WT_STAT_READ(from, log_slot_joins);
+ to->log_slot_no_free_slots +=
+ WT_STAT_READ(from, log_slot_no_free_slots);
to->log_slot_unbuffered += WT_STAT_READ(from, log_slot_unbuffered);
to->log_bytes_payload += WT_STAT_READ(from, log_bytes_payload);
to->log_bytes_written += WT_STAT_READ(from, log_bytes_written);
diff --git a/src/support/thread_group.c b/src/support/thread_group.c
index a866d2d01c5..2b4b7ad4e61 100644
--- a/src/support/thread_group.c
+++ b/src/support/thread_group.c
@@ -50,8 +50,7 @@ __thread_group_grow(
{
WT_THREAD *thread;
- WT_ASSERT(session,
- __wt_rwlock_islocked(session, group->lock));
+ WT_ASSERT(session, __wt_rwlock_islocked(session, &group->lock));
/*
* Any bounds checking is done by the caller so we know that
@@ -72,20 +71,19 @@ __thread_group_grow(
/*
* __thread_group_shrink --
- * Decrease the number of running threads in the group, and free any
+ * Decrease the number of running threads in the group. Optionally free any
* memory associated with slots larger than the new count.
*/
static int
__thread_group_shrink(WT_SESSION_IMPL *session,
- WT_THREAD_GROUP *group, uint32_t new_count)
+ WT_THREAD_GROUP *group, uint32_t new_count, bool free_thread)
{
WT_DECL_RET;
WT_SESSION *wt_session;
WT_THREAD *thread;
uint32_t current_slot;
- WT_ASSERT(session,
- __wt_rwlock_islocked(session, group->lock));
+ WT_ASSERT(session, __wt_rwlock_islocked(session, &group->lock));
for (current_slot = group->alloc; current_slot > new_count; ) {
/*
@@ -107,14 +105,15 @@ __thread_group_shrink(WT_SESSION_IMPL *session,
WT_TRET(__wt_thread_join(session, thread->tid));
thread->tid = 0;
}
-
- if (thread->session != NULL) {
- wt_session = (WT_SESSION *)thread->session;
- WT_TRET(wt_session->close(wt_session, NULL));
- thread->session = NULL;
+ if (free_thread) {
+ if (thread->session != NULL) {
+ wt_session = (WT_SESSION *)thread->session;
+ WT_TRET(wt_session->close(wt_session, NULL));
+ thread->session = NULL;
+ }
+ __wt_free(session, thread);
+ group->threads[current_slot] = NULL;
}
- __wt_free(session, thread);
- group->threads[current_slot] = NULL;
}
/* Update the thread group state to match our changes */
@@ -142,16 +141,19 @@ __thread_group_resize(
WT_ASSERT(session,
group->current_threads <= group->alloc &&
- __wt_rwlock_islocked(session, group->lock));
+ __wt_rwlock_islocked(session, &group->lock));
if (new_min == group->min && new_max == group->max)
return (0);
+ if (new_min > new_max)
+ return (EINVAL);
+
/*
- * Coll shrink to reduce the number of thread structures and running
+ * Call shrink to reduce the number of thread structures and running
* threads if required by the change in group size.
*/
- WT_RET(__thread_group_shrink(session, group, new_max));
+ WT_RET(__thread_group_shrink(session, group, new_max, true));
/*
* Only reallocate the thread array if it is the largest ever, since
@@ -227,9 +229,9 @@ __wt_thread_group_resize(
" from max: %" PRIu32 " -> %" PRIu32,
(void *)group, group->min, new_min, group->max, new_max);
- __wt_writelock(session, group->lock);
+ __wt_writelock(session, &group->lock);
WT_TRET(__thread_group_resize(session, group, new_min, new_max, flags));
- __wt_writeunlock(session, group->lock);
+ __wt_writeunlock(session, &group->lock);
return (ret);
}
@@ -255,17 +257,17 @@ __wt_thread_group_create(
__wt_verbose(session, WT_VERB_THREAD_GROUP,
"Creating thread group: %p", (void *)group);
- WT_RET(__wt_rwlock_alloc(session, &group->lock, "Thread group"));
+ __wt_rwlock_init(session, &group->lock);
WT_ERR(__wt_cond_alloc(
- session, "Thread group cond", false, &group->wait_cond));
+ session, "thread group cond", &group->wait_cond));
cond_alloced = true;
- __wt_writelock(session, group->lock);
+ __wt_writelock(session, &group->lock);
group->run_func = run_func;
group->name = name;
WT_TRET(__thread_group_resize(session, group, min, max, flags));
- __wt_writeunlock(session, group->lock);
+ __wt_writeunlock(session, &group->lock);
/* Cleanup on error to avoid leaking resources */
err: if (ret != 0) {
@@ -288,10 +290,10 @@ __wt_thread_group_destroy(WT_SESSION_IMPL *session, WT_THREAD_GROUP *group)
__wt_verbose(session, WT_VERB_THREAD_GROUP,
"Destroying thread group: %p", (void *)group);
- WT_ASSERT(session, __wt_rwlock_islocked(session, group->lock));
+ WT_ASSERT(session, __wt_rwlock_islocked(session, &group->lock));
/* Shut down all threads and free associated resources. */
- WT_TRET(__thread_group_shrink(session, group, 0));
+ WT_TRET(__thread_group_shrink(session, group, 0, true));
__wt_free(session, group->threads);
@@ -322,15 +324,42 @@ __wt_thread_group_start_one(
return (0);
if (wait)
- __wt_writelock(session, group->lock);
- else if (__wt_try_writelock(session, group->lock) != 0)
- return (0);
+ __wt_writelock(session, &group->lock);
+ else
+ WT_RET(__wt_try_writelock(session, &group->lock));
/* Recheck the bounds now that we hold the lock */
if (group->current_threads < group->max)
WT_TRET(__thread_group_grow(
session, group, group->current_threads + 1));
- __wt_writeunlock(session, group->lock);
+ __wt_writeunlock(session, &group->lock);
+
+ return (ret);
+}
+
+/*
+ * __wt_thread_group_stop_one --
+ * Stop one thread if possible.
+ */
+int
+__wt_thread_group_stop_one(
+ WT_SESSION_IMPL *session, WT_THREAD_GROUP *group, bool wait)
+{
+ WT_DECL_RET;
+
+ if (group->current_threads <= group->min)
+ return (0);
+
+ if (wait)
+ __wt_writelock(session, &group->lock);
+ else
+ WT_RET(__wt_try_writelock(session, &group->lock));
+
+ /* Recheck the bounds now that we hold the lock */
+ if (group->current_threads > group->min)
+ WT_TRET(__thread_group_shrink(
+ session, group, group->current_threads - 1, false));
+ __wt_writeunlock(session, &group->lock);
return (ret);
}