summaryrefslogtreecommitdiff
path: root/src/support
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@wiredtiger.com>2012-06-04 17:05:36 +1000
committerMichael Cahill <michael.cahill@wiredtiger.com>2012-06-04 17:05:36 +1000
commit953b622700125746202c116452638e0181db9165 (patch)
treebc03d820966af3cc87a2181137df6374ab7faacc /src/support
parentd20711f22bad7fcd401367977d883cd1bba9c017 (diff)
parent97cb94c0ccdf8e4554e4b233271f9ba219fee811 (diff)
downloadmongo-953b622700125746202c116452638e0181db9165.tar.gz
Merge branch 'develop'
Diffstat (limited to 'src/support')
-rw-r--r--src/support/err.c294
-rw-r--r--src/support/global.c2
-rw-r--r--src/support/hazard.c65
-rw-r--r--src/support/hex.c34
-rw-r--r--src/support/huffman.c14
-rw-r--r--src/support/scratch.c62
-rw-r--r--src/support/sess_dump.c22
-rw-r--r--src/support/stat.c7
8 files changed, 362 insertions, 138 deletions
diff --git a/src/support/err.c b/src/support/err.c
index aac2f8ab3ea..53ff89829f2 100644
--- a/src/support/err.c
+++ b/src/support/err.c
@@ -8,19 +8,125 @@
#include "wt_internal.h"
/*
- * __wt_eventv --
- * Report a message to an event handler.
+ * __handle_error_default --
+ * Default WT_EVENT_HANDLER->handle_error implementation: send to stderr.
+ */
+static int
+__handle_error_default(WT_EVENT_HANDLER *handler, int error, const char *errmsg)
+{
+ WT_UNUSED(handler);
+ WT_UNUSED(error);
+
+ return (fprintf(stderr, "%s\n", errmsg) >= 0 ? 0 : EIO);
+}
+
+/*
+ * __handle_message_default --
+ * Default WT_EVENT_HANDLER->handle_message implementation: send to stdout.
+ */
+static int
+__handle_message_default(WT_EVENT_HANDLER *handler, const char *message)
+{
+ WT_UNUSED(handler);
+
+ return (printf("%s\n", message) >= 0 ? 0 : EIO);
+}
+
+/*
+ * __handle_progress_default --
+ * Default WT_EVENT_HANDLER->handle_progress implementation: ignore.
+ */
+static int
+__handle_progress_default(
+ WT_EVENT_HANDLER *handler, const char *operation, uint64_t progress)
+{
+ WT_UNUSED(handler);
+ WT_UNUSED(operation);
+ WT_UNUSED(progress);
+
+ return (0);
+}
+
+static WT_EVENT_HANDLER __event_handler_default = {
+ __handle_error_default,
+ __handle_message_default,
+ __handle_progress_default
+};
+
+/*
+ * __handler_failure --
+ * Report the failure of an application-configured event handler.
+ */
+static void
+__handler_failure(WT_SESSION_IMPL *session,
+ int error, const char *which, int error_handler_failed)
+{
+ WT_EVENT_HANDLER *handler;
+
+ /*
+ * !!!
+ * SECURITY:
+ * Buffer placed at the end of the stack in case snprintf overflows.
+ */
+ char s[256];
+
+ (void)snprintf(s, sizeof(s),
+ "application %s event handler failed: %s",
+ which, wiredtiger_strerror(error));
+
+ /*
+ * Use the error handler to report the failure, unless it was the error
+ * handler that failed. If it was the error handler that failed, or a
+ * call to the error handler fails, use the default error handler.
+ */
+ handler = session->event_handler;
+ if (!error_handler_failed &&
+ handler->handle_error != __handle_error_default &&
+ handler->handle_error(handler, error, s) == 0)
+ return;
+
+ (void)__handle_error_default(NULL, error, s);
+}
+
+/*
+ * __wt_event_handler_set --
+ * Set an event handler, fill in any NULL methods with the defaults.
*/
void
-__wt_eventv(WT_SESSION_IMPL *session, int msg_event,
- int error,
+__wt_event_handler_set(WT_SESSION_IMPL *session, WT_EVENT_HANDLER *handler)
+{
+ if (handler == NULL)
+ handler = &__event_handler_default;
+ else {
+ if (handler->handle_error == NULL)
+ handler->handle_error = __handle_error_default;
+ if (handler->handle_message == NULL)
+ handler->handle_message = __handle_message_default;
+ if (handler->handle_progress == NULL)
+ handler->handle_progress = __handle_progress_default;
+ }
+
+ session->event_handler = handler;
+}
+
+/*
+ * __eventv --
+ * Report a message to an event handler.
+ */
+static int
+__eventv(WT_SESSION_IMPL *session, int msg_event, int error,
const char *file_name, int line_number, const char *fmt, va_list ap)
{
WT_EVENT_HANDLER *handler;
- const char *prefix1, *prefix2;
+ WT_DECL_RET;
+ size_t len, remain, wlen;
+ const char *err, *prefix1, *prefix2;
char *end, *p;
/*
+ * We're using a stack buffer because we want error messages no matter
+ * what, and allocating a WT_ITEM, or the memory it needs, might fail.
+ *
* !!!
* SECURITY:
* Buffer placed at the end of the stack in case snprintf overflows.
@@ -33,27 +139,74 @@ __wt_eventv(WT_SESSION_IMPL *session, int msg_event,
prefix1 = (session->btree != NULL) ? session->btree->name : NULL;
prefix2 = session->name;
- if (prefix1 != NULL && prefix2 != NULL && p < end)
- p += snprintf(p, (size_t)(end - p),
- "%s [%s]: ", prefix1, prefix2);
- else if (prefix1 != NULL && p < end)
- p += snprintf(p, (size_t)(end - p), "%s: ", prefix1);
- else if (prefix2 != NULL && p < end)
- p += snprintf(p, (size_t)(end - p), "%s: ", prefix2);
- if (file_name != NULL && p < end)
- p += snprintf(p, (size_t)(end - p),
- "%s, %d: ", file_name, line_number);
- if (p < end)
- p += vsnprintf(p, (size_t)(end - p), fmt, ap);
- if (error != 0 && p < end)
- p += snprintf(p,
- (size_t)(end - p), ": %s", wiredtiger_strerror(error));
+ remain = WT_PTRDIFF(end, p);
+ if (prefix1 != NULL && prefix2 != NULL)
+ wlen =
+ (size_t)snprintf(p, remain, "%s [%s]: ", prefix1, prefix2);
+ else if (prefix1 != NULL)
+ wlen = (size_t)snprintf(p, remain, "%s: ", prefix1);
+ else if (prefix2 != NULL)
+ wlen = (size_t)snprintf(p, remain, "%s: ", prefix2);
+ else
+ wlen = 0;
+ 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;
+ }
+
+ remain = WT_PTRDIFF(end, p);
+ wlen = (size_t)vsnprintf(p, remain, fmt, ap);
+ p = wlen >= remain ? end : p + wlen;
+
+ if (error != 0) {
+ /*
+ * When the engine calls __wt_err on error, it often outputs an
+ * error message including the string associated with the error
+ * it's returning. We could change the calls to call __wt_errx,
+ * but it's simpler to not append an error string if all we are
+ * doing is duplicating an existing error string.
+ *
+ * Use strcmp to compare: both strings are nul-terminated, and
+ * we don't want to run past the end of the buffer.
+ */
+ err = wiredtiger_strerror(error);
+ 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 a handler fails, return the error status: if we're in the process
+ * of handling an error, any return value we provide will be ignored by
+ * our caller, our caller presumably already has an error value it will
+ * be returning.
+ *
+ * If an application-specified or default informational message handler
+ * fails, complain using the application-specified or default error
+ * handler.
+ *
+ * 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.
+ */
handler = session->event_handler;
- if (msg_event)
- (void)handler->handle_message(handler, s);
- else
- handler->handle_error(handler, error, s);
+ if (msg_event) {
+ ret = handler->handle_message(handler, s);
+ if (ret != 0)
+ __handler_failure(session, ret, "message", 0);
+ } else {
+ ret = handler->handle_error(handler, error, s);
+ if (ret != 0 && handler->handle_error != __handle_error_default)
+ __handler_failure(session, ret, "error", 1);
+ }
+
+ return (ret);
}
/*
@@ -66,8 +219,12 @@ __wt_err(WT_SESSION_IMPL *session, int error, const char *fmt, ...)
{
va_list ap;
+ /*
+ * Ignore error returns from underlying event handlers, we already have
+ * an error value to return.
+ */
va_start(ap, fmt);
- __wt_eventv(session, 0, error, NULL, 0, fmt, ap);
+ (void)__eventv(session, 0, error, NULL, 0, fmt, ap);
va_end(ap);
}
@@ -81,17 +238,48 @@ __wt_errx(WT_SESSION_IMPL *session, const char *fmt, ...)
{
va_list ap;
+ /*
+ * Ignore error returns from underlying event handlers, we already have
+ * an error value to return.
+ */
va_start(ap, fmt);
- __wt_eventv(session, 0, 0, NULL, 0, fmt, ap);
+ (void)__eventv(session, 0, 0, NULL, 0, fmt, ap);
va_end(ap);
}
/*
- * __wt_msg_call --
- * Pass a message to an event handler.
+ * __wt_verrx --
+ * Interface to support the extension API.
*/
-void
-__wt_msgv(WT_SESSION_IMPL *session, const char *fmt, va_list ap)
+int
+__wt_verrx(WT_SESSION_IMPL *session, const char *fmt, va_list ap)
+{
+ return (__eventv(session, 0, 0, NULL, 0, fmt, ap));
+}
+/*
+ * __wt_msg --
+ * Informational message.
+ */
+int
+__wt_msg(WT_SESSION_IMPL *session, const char *fmt, ...)
+ WT_GCC_FUNC_ATTRIBUTE((format (printf, 2, 3)))
+{
+ WT_DECL_RET;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = __wt_vmsg(session, fmt, ap);
+ va_end(ap);
+
+ return (ret);
+}
+
+/*
+ * __wt_vmsg --
+ * Informational message.
+ */
+int
+__wt_vmsg(WT_SESSION_IMPL *session, const char *fmt, va_list ap)
{
WT_EVENT_HANDLER *handler;
@@ -105,37 +293,42 @@ __wt_msgv(WT_SESSION_IMPL *session, const char *fmt, va_list ap)
(void)vsnprintf(s, sizeof(s), fmt, ap);
handler = session->event_handler;
- (void)handler->handle_message(handler, s);
+ return (handler->handle_message(handler, s));
}
/*
- * __wt_verbose --
- * Verbose message.
+ * __wt_progress --
+ * Progress message.
*/
-void
-__wt_verbose(WT_SESSION_IMPL *session, const char *fmt, ...)
- WT_GCC_FUNC_ATTRIBUTE((format (printf, 2, 3)))
+int
+__wt_progress(WT_SESSION_IMPL *session, const char *s, uint64_t v)
{
- va_list ap;
+ WT_DECL_RET;
+ WT_EVENT_HANDLER *handler;
- va_start(ap, fmt);
- __wt_eventv(session, 1, 0, NULL, 0, fmt, ap);
- va_end(ap);
+ handler = session->event_handler;
+ if (handler != NULL && handler->handle_progress != NULL)
+ if ((ret = handler->handle_progress(
+ handler, s == NULL ? session->name : s, v)) != 0)
+ __handler_failure(session, ret, "progress", 0);
+ return (0);
}
/*
- * __wt_msg --
- * Report a message.
+ * __wt_verbose --
+ * Verbose message.
*/
-void
-__wt_msg(WT_SESSION_IMPL *session, const char *fmt, ...)
+int
+__wt_verbose(WT_SESSION_IMPL *session, const char *fmt, ...)
WT_GCC_FUNC_ATTRIBUTE((format (printf, 2, 3)))
{
+ WT_DECL_RET;
va_list ap;
va_start(ap, fmt);
- __wt_msgv(session, fmt, ap);
+ ret = __eventv(session, 1, 0, NULL, 0, fmt, ap);
va_end(ap);
+ return (ret);
}
/*
@@ -143,7 +336,7 @@ __wt_msg(WT_SESSION_IMPL *session, const char *fmt, ...)
* Assert and other unexpected failures, includes file/line information
* for debugging.
*/
-int
+void
__wt_assert(WT_SESSION_IMPL *session,
int error, const char *file_name, int line_number, const char *fmt, ...)
WT_GCC_FUNC_ATTRIBUTE((format (printf, 5, 6)))
@@ -151,14 +344,13 @@ __wt_assert(WT_SESSION_IMPL *session,
va_list ap;
va_start(ap, fmt);
- __wt_eventv(session, 0, error, file_name, line_number, fmt, ap);
+ (void)__eventv(session, 0, error, file_name, line_number, fmt, ap);
va_end(ap);
#ifdef HAVE_DIAGNOSTIC
__wt_abort(session);
/* NOTREACHED */
#endif
- return (error);
}
/*
@@ -166,13 +358,15 @@ __wt_assert(WT_SESSION_IMPL *session,
* Print a standard error message when we detect an illegal value.
*/
int
-__wt_illegal_value(WT_SESSION_IMPL *session)
+__wt_illegal_value(WT_SESSION_IMPL *session, const char *name)
{
WT_RET_MSG(session, WT_ERROR,
+ "%s%s"
"encountered an illegal file format or internal value; restart "
"the system and verify the underlying files, if corruption is "
"detected use the WT_SESSION salvage method or the wt utility's "
- "salvage command to repair the file");
+ "salvage command to repair the file",
+ name == NULL ? "" : name, name == NULL ? "" : " ");
}
/*
diff --git a/src/support/global.c b/src/support/global.c
index 7f78b620006..4d6420e6d14 100644
--- a/src/support/global.c
+++ b/src/support/global.c
@@ -32,7 +32,7 @@ __wt_library_init(void)
{
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
static int first = 1;
- int ret;
+ WT_DECL_RET;
/*
* Do per-process initialization once, before anything else, but only
diff --git a/src/support/hazard.c b/src/support/hazard.c
index e22d25be3c2..3846889dce2 100644
--- a/src/support/hazard.c
+++ b/src/support/hazard.c
@@ -16,7 +16,7 @@ static void __hazard_dump(WT_SESSION_IMPL *);
* Set a hazard reference.
*/
int
-__wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref
+__wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref, int *busyp
#ifdef HAVE_DIAGNOSTIC
, const char *file, int line
#endif
@@ -26,6 +26,7 @@ __wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref
WT_HAZARD *hp;
conn = S2C(session);
+ *busyp = 0;
/*
* Do the dance:
@@ -60,7 +61,7 @@ __wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref
*/
if (ref->state == WT_REF_MEM ||
ref->state == WT_REF_EVICT_WALK) {
- WT_VERBOSE(session, hazard,
+ WT_VERBOSE_RET(session, hazard,
"session %p hazard %p: set", session, ref->page);
return (0);
}
@@ -78,7 +79,8 @@ __wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref
* again until it loops around through the tree.
*/
hp->page = NULL;
- return (EBUSY);
+ *busyp = 1;
+ return (0);
}
__wt_errx(session,
@@ -109,24 +111,39 @@ __wt_hazard_clear(WT_SESSION_IMPL *session, WT_PAGE *page)
*/
WT_ASSERT(session, page != NULL);
- WT_VERBOSE(session, hazard,
- "session %p hazard %p: clr", session, page);
-
/* Clear the caller's hazard pointer. */
for (hp = session->hazard;
hp < session->hazard + conn->hazard_size; ++hp)
if (hp->page == page) {
- hp->page = NULL;
/*
- * We don't have to flush memory here for correctness;
- * it would give the page server thread faster access
- * to the block were the block selected to be evicted,
- * but the generation number was just set which makes
- * it unlikely to be selected for eviction.
+ * Check to see if the page has grown too big and force
+ * eviction. We have to request eviction while holding
+ * a hazard reference (else the page might disappear out
+ * from under us), but we can't wake the eviction server
+ * until we've released our hazard reference because our
+ * hazard reference blocks the page eviction. A little
+ * dance: check the page, schedule the forced eviction,
+ * clear/publish the hazard reference, wake the eviction
+ * server.
+ *
+ * We don't publish the hazard reference clear in the
+ * general case. It's not required for correctness;
+ * it gives the page server thread faster access to the
+ * page were the page selected for eviction, but the
+ * generation number was just set, so it's unlikely the
+ * page will be selected for eviction.
*/
+ if (__wt_eviction_page_check(session, page)) {
+ __wt_evict_page_request(session, page);
+ WT_PUBLISH(hp->page, NULL);
+ __wt_evict_server_wake(session);
+ } else
+ hp->page = NULL;
return;
}
- __wt_errx(session, "hazard reference not found");
+ __wt_errx(session,
+ "clear hazard reference: session: %p reference %p: not found",
+ session, page);
}
/*
@@ -190,26 +207,4 @@ __hazard_dump(WT_SESSION_IMPL *session)
if (fail)
__wt_errx(session, "unexpected hazard reference");
}
-
-/*
- * __wt_hazard_validate --
- * Confirm that a page isn't on the hazard list.
- */
-void
-__wt_hazard_validate(WT_SESSION_IMPL *session, WT_PAGE *page)
-{
- WT_CONNECTION_IMPL *conn;
- WT_HAZARD *hp;
- uint32_t elem, i;
-
- conn = S2C(session);
-
- elem = conn->session_size * conn->hazard_size;
- for (i = 0, hp = conn->hazard; i < elem; ++i, ++hp)
- if (hp->page == page)
- __wt_errx(session,
- "discarded page has hazard reference: "
- "(%p: %s, line %d)",
- hp->page, hp->file, hp->line);
-}
#endif
diff --git a/src/support/hex.c b/src/support/hex.c
index e582e9576ef..d9ee135599b 100644
--- a/src/support/hex.c
+++ b/src/support/hex.c
@@ -11,11 +11,11 @@ static const char hex[] = "0123456789abcdef";
/*
* __wt_raw_to_hex --
- * Convert a chunk of data to a printable hex string.
+ * Convert a chunk of data to a nul-terminated printable hex string.
*/
int
-__wt_raw_to_hex(WT_SESSION_IMPL *session,
- const uint8_t *from, uint32_t size, WT_ITEM *to)
+__wt_raw_to_hex(
+ WT_SESSION_IMPL *session, const uint8_t *from, uint32_t size, WT_ITEM *to)
{
uint32_t i;
const uint8_t *p;
@@ -38,12 +38,12 @@ __wt_raw_to_hex(WT_SESSION_IMPL *session,
/*
* __wt_raw_to_esc_hex --
- * Convert a chunk of data to an printable string using escaped hex as
- * necessary.
+ * Convert a chunk of data to a nul-terminated printable string using
+ * escaped hex, as necessary.
*/
int
-__wt_raw_to_esc_hex(WT_SESSION_IMPL *session,
- const uint8_t *from, size_t size, WT_ITEM *to)
+__wt_raw_to_esc_hex(
+ WT_SESSION_IMPL *session, const uint8_t *from, size_t size, WT_ITEM *to)
{
size_t i;
const uint8_t *p;
@@ -136,22 +136,31 @@ __hex_fmterr(WT_SESSION_IMPL *session)
/*
* __wt_hex_to_raw --
- * Convert a printable hex string to a chunk of data.
+ * Convert a nul-terminated printable hex string to a chunk of data.
*/
int
__wt_hex_to_raw(WT_SESSION_IMPL *session, const char *from, WT_ITEM *to)
{
+ return (__wt_nhex_to_raw(session, from, strlen(from), to));
+}
+
+/*
+ * __wt_nhex_to_raw --
+ * Convert a printable hex string to a chunk of data.
+ */
+int
+__wt_nhex_to_raw(
+ WT_SESSION_IMPL *session, const char *from, size_t size, WT_ITEM *to)
+{
const char *p;
uint8_t *t;
- size_t size;
- size = strlen(from);
if (size % 2 != 0)
return (__hex_fmterr(session));
WT_RET(__wt_buf_init(session, to, size / 2));
- for (p = from, t = to->mem; *p != '\0'; p += 2, ++t)
+ for (p = from, t = to->mem; size > 0; p += 2, size -= 2, ++t)
if (hex2byte(p, t))
return (__hex_fmterr(session));
@@ -161,8 +170,7 @@ __wt_hex_to_raw(WT_SESSION_IMPL *session, const char *from, WT_ITEM *to)
/*
* __wt_esc_hex_to_raw --
- * Convert a printable string using escaped hex as necessary to a chunk
- * of data.
+ * Convert a printable string, encoded in escaped hex, to a chunk of data.
*/
int
__wt_esc_hex_to_raw(WT_SESSION_IMPL *session, const char *from, WT_ITEM *to)
diff --git a/src/support/huffman.c b/src/support/huffman.c
index 7b66b321b9c..fa1f1499cff 100644
--- a/src/support/huffman.c
+++ b/src/support/huffman.c
@@ -62,7 +62,6 @@ typedef struct __wt_huffman_obj {
* memory: code2symbol[1 << max_code_length]
*/
uint8_t *code2symbol;
-
} WT_HUFFMAN_OBJ;
/*
@@ -296,17 +295,16 @@ __wt_huffman_open(WT_SESSION_IMPL *session,
{
INDEXED_SYMBOL *indexed_freqs, *sym;
NODE_QUEUE *combined_nodes, *leaves;
+ WT_DECL_RET;
WT_FREQTREE_NODE *node, *node2, **refnode, *tempnode;
WT_HUFFMAN_OBJ *huffman;
uint64_t w1, w2;
uint16_t i;
- int ret;
indexed_freqs = symbol_frequency_array;
combined_nodes = leaves = NULL;
node = node2 = tempnode = NULL;
- ret = 0;
WT_RET(__wt_calloc_def(session, 1, &huffman));
@@ -337,12 +335,12 @@ __wt_huffman_open(WT_SESSION_IMPL *session,
if (i > 0 &&
indexed_freqs[i].symbol == indexed_freqs[i - 1].symbol)
WT_ERR_MSG(session, EINVAL,
- "duplicate symbol %" PRIx16
+ "duplicate symbol %" PRIx32
" specified in a huffman table",
indexed_freqs[i].symbol);
if (indexed_freqs[i].symbol > huffman->numSymbols)
WT_ERR_MSG(session, EINVAL,
- "illegal symbol %" PRIx16
+ "illegal symbol %" PRIx32
" specified in a huffman table",
indexed_freqs[i].symbol);
}
@@ -590,6 +588,7 @@ int
__wt_huffman_encode(WT_SESSION_IMPL *session, void *huffman_arg,
const uint8_t *from_arg, uint32_t from_len, WT_ITEM *to_buf)
{
+ WT_DECL_RET;
WT_HUFFMAN_CODE code;
WT_HUFFMAN_OBJ *huffman;
WT_ITEM *tmp;
@@ -597,7 +596,6 @@ __wt_huffman_encode(WT_SESSION_IMPL *session, void *huffman_arg,
uint32_t max_len, outlen, bytes;
const uint8_t *from;
uint8_t len, *out, padding_info, symbol;
- int ret;
/*
* Shift register to accumulate bits from input.
@@ -612,7 +610,6 @@ __wt_huffman_encode(WT_SESSION_IMPL *session, void *huffman_arg,
huffman = huffman_arg;
from = from_arg;
tmp = NULL;
- ret = 0;
/*
* We don't want to find all of our callers and ensure they don't pass
@@ -729,6 +726,7 @@ int
__wt_huffman_decode(WT_SESSION_IMPL *session, void *huffman_arg,
const uint8_t *from_arg, uint32_t from_len, WT_ITEM *to_buf)
{
+ WT_DECL_RET;
WT_ITEM *tmp;
WT_HUFFMAN_OBJ *huffman;
uint64_t from_len_bits;
@@ -736,12 +734,10 @@ __wt_huffman_decode(WT_SESSION_IMPL *session, void *huffman_arg,
uint16_t pattern;
const uint8_t *from;
uint8_t padding_info, symbol, *to, valid;
- int ret;
huffman = huffman_arg;
from = from_arg;
tmp = NULL;
- ret = 0;
/*
* We don't want to find all of our callers and ensure they don't pass
diff --git a/src/support/scratch.c b/src/support/scratch.c
index 03e3d3a8b78..57b779bd5c2 100644
--- a/src/support/scratch.c
+++ b/src/support/scratch.c
@@ -248,12 +248,17 @@ __wt_buf_catfmt(WT_SESSION_IMPL *session, WT_ITEM *buf, const char *fmt, ...)
* Scratch buffer allocation function.
*/
int
-__wt_scr_alloc(WT_SESSION_IMPL *session, uint32_t size, WT_ITEM **scratchp)
+__wt_scr_alloc_func(WT_SESSION_IMPL *session,
+ uint32_t size, WT_ITEM **scratchp
+#ifdef HAVE_DIAGNOSTIC
+ , const char *file, int line
+#endif
+ )
{
- WT_ITEM *buf, **p, *best, **slot;
+ WT_DECL_RET;
+ WT_ITEM *buf, **p, **best, **slot;
size_t allocated;
u_int i;
- int ret;
/* Don't risk the caller not catching the error. */
*scratchp = NULL;
@@ -267,7 +272,7 @@ __wt_scr_alloc(WT_SESSION_IMPL *session, uint32_t size, WT_ITEM **scratchp)
*
* Walk the array, looking for a buffer we can use.
*/
- for (i = 0, best = NULL, slot = NULL,
+ for (i = 0, best = slot = NULL,
p = session->scratch; i < session->scratch_alloc; ++i, ++p) {
/* If we find an empty slot, remember it. */
if ((buf = *p) == NULL) {
@@ -285,11 +290,13 @@ __wt_scr_alloc(WT_SESSION_IMPL *session, uint32_t size, WT_ITEM **scratchp)
* or the largest buffer if none are large enough.
*/
if (best == NULL ||
- (best->memsize < size && buf->memsize > best->memsize) ||
- (buf->memsize >= size && buf->memsize < best->memsize))
- best = buf;
+ ((*best)->memsize < size &&
+ buf->memsize > (*best)->memsize) ||
+ (buf->memsize >= size && buf->memsize < (*best)->memsize))
+ best = p;
+
/* If we find a perfect match, use it. */
- if (best->memsize == size)
+ if ((*best)->memsize == size)
break;
}
@@ -302,6 +309,12 @@ __wt_scr_alloc(WT_SESSION_IMPL *session, uint32_t size, WT_ITEM **scratchp)
WT_ERR(__wt_realloc(session, &allocated,
(session->scratch_alloc + 10) * sizeof(WT_ITEM *),
&session->scratch));
+#ifdef HAVE_DIAGNOSTIC
+ allocated = session->scratch_alloc * sizeof(WT_SCRATCH_TRACK);
+ WT_ERR(__wt_realloc(session, &allocated,
+ (session->scratch_alloc + 10) * sizeof(WT_SCRATCH_TRACK),
+ &session->scratch_track));
+#endif
slot = session->scratch + session->scratch_alloc;
session->scratch_alloc += 10;
}
@@ -312,17 +325,24 @@ __wt_scr_alloc(WT_SESSION_IMPL *session, uint32_t size, WT_ITEM **scratchp)
*/
if (best == NULL) {
WT_ASSERT(session, slot != NULL);
- WT_ERR(__wt_calloc_def(session, 1, slot));
- best = *slot;
+ best = slot;
+
+ WT_ERR(__wt_calloc_def(session, 1, best));
/* Scratch buffers must be aligned. */
- F_SET(best, WT_ITEM_ALIGNED);
+ F_SET(*best, WT_ITEM_ALIGNED);
}
/* Grow the buffer as necessary and return. */
- WT_ERR(__wt_buf_init(session, best, size));
- F_SET(best, WT_ITEM_INUSE);
- *scratchp = best;
+ WT_ERR(__wt_buf_init(session, *best, size));
+ F_SET(*best, WT_ITEM_INUSE);
+
+#ifdef HAVE_DIAGNOSTIC
+ session->scratch_track[best - session->scratch].file = file;
+ session->scratch_track[best - session->scratch].line = line;
+#endif
+
+ *scratchp = *best;
return (0);
err: WT_RET_MSG(session, ret,
@@ -356,16 +376,26 @@ __wt_scr_discard(WT_SESSION_IMPL *session)
bufp = session->scratch; i < session->scratch_alloc; ++i, ++bufp) {
if (*bufp == NULL)
continue;
-#if 0
if (F_ISSET(*bufp, WT_ITEM_INUSE))
__wt_errx(session,
- "scratch buffer allocated and never discarded");
+ "scratch buffer allocated and never discarded"
+#ifdef HAVE_DIAGNOSTIC
+ ": %s: %d",
+ session->
+ scratch_track[bufp - session->scratch].file,
+ session->
+ scratch_track[bufp - session->scratch].line
#endif
+ );
+
__wt_buf_free(session, *bufp);
__wt_free(session, *bufp);
}
__wt_free(session, session->scratch);
+#ifdef HAVE_DIAGNOSTIC
+ __wt_free(session, session->scratch_track);
+#endif
}
/*
diff --git a/src/support/sess_dump.c b/src/support/sess_dump.c
index 962f50c532f..5fa5deb2b74 100644
--- a/src/support/sess_dump.c
+++ b/src/support/sess_dump.c
@@ -15,13 +15,17 @@
void
__wt_session_dump_all(WT_SESSION_IMPL *session)
{
- WT_SESSION_IMPL **tp;
+ WT_CONNECTION_IMPL *conn;
+ WT_SESSION_IMPL *s;
+ uint32_t i;
if (session == NULL)
return;
- for (tp = S2C(session)->sessions; *tp != NULL; ++tp)
- __wt_session_dump(*tp);
+ conn = S2C(session);
+ for (s = conn->sessions, i = 0; i < conn->session_size; ++s, ++i)
+ if (s->active)
+ __wt_session_dump(s);
}
/*
@@ -38,15 +42,15 @@ __wt_session_dump(WT_SESSION_IMPL *session)
conn = S2C(session);
- __wt_msg(session, "session: %s%s%p",
+ (void)__wt_msg(session, "session: %s%s%p",
session->name == NULL ? "" : session->name,
session->name == NULL ? "" : " ", session);
first = 0;
TAILQ_FOREACH(cursor, &session->cursors, q) {
if (++first == 1)
- __wt_msg(session, "\tcursors:");
- __wt_msg(session, "\t\t%p", cursor);
+ (void)__wt_msg(session, "\tcursors:");
+ (void)__wt_msg(session, "\t\t%p", cursor);
}
first = 0;
@@ -55,12 +59,12 @@ __wt_session_dump(WT_SESSION_IMPL *session)
if (hp->page == NULL)
continue;
if (++first == 1)
- __wt_msg(session, "\thazard references:");
+ (void)__wt_msg(session, "\thazard references:");
#ifdef HAVE_DIAGNOSTIC
- __wt_msg(session,
+ (void)__wt_msg(session,
"\t\t%p (%s, line %d)", hp->page, hp->file, hp->line);
#else
- __wt_msg(session, "\t\t%p", hp->page);
+ (void)__wt_msg(session, "\t\t%p", hp->page);
#endif
}
}
diff --git a/src/support/stat.c b/src/support/stat.c
index bbd13b8b839..5741be441e8 100644
--- a/src/support/stat.c
+++ b/src/support/stat.c
@@ -28,9 +28,6 @@ __wt_stat_alloc_btree_stats(WT_SESSION_IMPL *session, WT_BTREE_STATS **statsp)
"column-store variable-size leaf pages";
stats->file_entries.desc = "total entries";
stats->file_fixed_len.desc = "fixed-record size";
- stats->file_freelist_bytes.desc = "number of bytes in the freelist";
- stats->file_freelist_entries.desc =
- "number of entries in the freelist";
stats->file_magic.desc = "magic number";
stats->file_major.desc = "major version number";
stats->file_maxintlitem.desc = "maximum internal page item size";
@@ -42,6 +39,7 @@ __wt_stat_alloc_btree_stats(WT_SESSION_IMPL *session, WT_BTREE_STATS **statsp)
stats->file_row_int_pages.desc = "row-store internal pages";
stats->file_row_leaf_pages.desc = "row-store leaf pages";
stats->file_size.desc = "file: size";
+ stats->file_write_conflicts.desc = "write generation conflicts";
stats->free.desc = "file: block frees";
stats->overflow_read.desc = "file: overflow pages read from the file";
stats->page_read.desc = "file: pages read from the file";
@@ -85,8 +83,6 @@ __wt_stat_clear_btree_stats(WT_STATS *stats_arg)
stats->file_col_var_pages.v = 0;
stats->file_entries.v = 0;
stats->file_fixed_len.v = 0;
- stats->file_freelist_bytes.v = 0;
- stats->file_freelist_entries.v = 0;
stats->file_magic.v = 0;
stats->file_major.v = 0;
stats->file_maxintlitem.v = 0;
@@ -98,6 +94,7 @@ __wt_stat_clear_btree_stats(WT_STATS *stats_arg)
stats->file_row_int_pages.v = 0;
stats->file_row_leaf_pages.v = 0;
stats->file_size.v = 0;
+ stats->file_write_conflicts.v = 0;
stats->free.v = 0;
stats->overflow_read.v = 0;
stats->page_read.v = 0;