summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/async/async_worker.c5
-rw-r--r--src/block/block_ckpt.c5
-rw-r--r--src/block/block_compact.c4
-rw-r--r--src/block/block_ext.c84
-rw-r--r--src/block/block_open.c2
-rw-r--r--src/block/block_vrfy.c36
-rw-r--r--src/btree/bt_cursor.c12
-rw-r--r--src/btree/bt_debug.c23
-rw-r--r--src/btree/bt_discard.c2
-rw-r--r--src/btree/bt_handle.c9
-rw-r--r--src/btree/bt_io.c2
-rw-r--r--src/btree/bt_misc.c16
-rw-r--r--src/btree/bt_read.c2
-rw-r--r--src/btree/bt_split.c13
-rw-r--r--src/btree/bt_sync.c13
-rw-r--r--src/btree/bt_vrfy.c47
-rw-r--r--src/btree/bt_vrfy_dsk.c9
-rw-r--r--src/btree/row_srch.c5
-rw-r--r--src/checksum/checksum.c2
-rw-r--r--src/checksum/power8/crc32_wrapper.c5
-rw-r--r--src/config/config_def.c47
-rw-r--r--src/conn/api_strerror.c2
-rw-r--r--src/conn/conn_api.c32
-rw-r--r--src/conn/conn_cache.c18
-rw-r--r--src/conn/conn_cache_pool.c1
-rw-r--r--src/conn/conn_dhandle.c10
-rw-r--r--src/conn/conn_log.c2
-rw-r--r--src/conn/conn_open.c3
-rw-r--r--src/cursor/cur_bulk.c1
-rw-r--r--src/cursor/cur_dump.c2
-rw-r--r--src/cursor/cur_join.c12
-rw-r--r--src/cursor/cur_json.c37
-rw-r--r--src/cursor/cur_std.c4
-rw-r--r--src/cursor/cur_table.c3
-rw-r--r--src/docs/custom-file-systems.dox9
-rw-r--r--src/evict/evict_file.c6
-rw-r--r--src/evict/evict_lru.c380
-rw-r--r--src/evict/evict_page.c3
-rw-r--r--src/include/block.h1
-rw-r--r--src/include/btree_cmp.i20
-rw-r--r--src/include/cache.h23
-rw-r--r--src/include/cell.i26
-rw-r--r--src/include/ctype.i69
-rw-r--r--src/include/extern.h102
-rw-r--r--src/include/extern_posix.h31
-rw-r--r--src/include/extern_win.h32
-rw-r--r--src/include/flags.h27
-rw-r--r--src/include/log.h5
-rw-r--r--src/include/misc.h8
-rw-r--r--src/include/os.h43
-rw-r--r--src/include/os_fhandle.i33
-rw-r--r--src/include/packing.i4
-rw-r--r--src/include/serial.i2
-rw-r--r--src/include/stat.h40
-rw-r--r--src/include/wiredtiger.in323
-rw-r--r--src/include/wiredtiger_ext.h13
-rw-r--r--src/include/wt_internal.h7
-rw-r--r--src/log/log.c55
-rw-r--r--src/log/log_auto.c2
-rw-r--r--src/log/log_slot.c11
-rw-r--r--src/lsm/lsm_work_unit.c3
-rw-r--r--src/meta/meta_track.c2
-rw-r--r--src/os_common/os_errno.c (renamed from src/os_posix/os_errno.c)43
-rw-r--r--src/os_common/os_fhandle.c5
-rw-r--r--src/os_common/os_fs_inmemory.c52
-rw-r--r--src/os_posix/os_dir.c12
-rw-r--r--src/os_posix/os_fs.c20
-rw-r--r--src/os_posix/os_map.c4
-rw-r--r--src/os_posix/os_thread.c2
-rw-r--r--src/os_posix/os_time.c4
-rw-r--r--src/os_win/os_dir.c22
-rw-r--r--src/os_win/os_dlopen.c28
-rw-r--r--src/os_win/os_errno.c151
-rw-r--r--src/os_win/os_fs.c184
-rw-r--r--src/os_win/os_getenv.c20
-rw-r--r--src/os_win/os_map.c44
-rw-r--r--src/os_win/os_mtx_cond.c32
-rw-r--r--src/os_win/os_path.c2
-rw-r--r--src/os_win/os_thread.c25
-rw-r--r--src/os_win/os_winerr.c130
-rw-r--r--src/reconcile/rec_write.c10
-rw-r--r--src/schema/schema_create.c2
-rw-r--r--src/schema/schema_list.c2
-rw-r--r--src/schema/schema_project.c6
-rw-r--r--src/support/err.c19
-rw-r--r--src/support/global.c4
-rw-r--r--src/support/hash_city.c2
-rw-r--r--src/support/hazard.c14
-rw-r--r--src/support/hex.c2
-rw-r--r--src/support/huffman.c25
-rw-r--r--src/support/scratch.c58
-rw-r--r--src/support/stat.c77
-rw-r--r--src/txn/txn.c17
-rw-r--r--src/txn/txn_ckpt.c20
-rw-r--r--src/txn/txn_log.c20
-rw-r--r--src/txn/txn_recover.c2
-rw-r--r--src/utilities/util_dump.c5
-rw-r--r--src/utilities/util_load.c2
-rw-r--r--src/utilities/util_load_json.c14
-rw-r--r--src/utilities/util_misc.c2
-rw-r--r--src/utilities/util_verify.c20
101 files changed, 1752 insertions, 1101 deletions
diff --git a/src/async/async_worker.c b/src/async/async_worker.c
index e692bc619a9..90dac557e36 100644
--- a/src/async/async_worker.c
+++ b/src/async/async_worker.c
@@ -216,9 +216,8 @@ __async_worker_execop(WT_SESSION_IMPL *session, WT_ASYNC_OP_IMPL *op,
__wt_cursor_set_raw_value(&asyncop->c, &val);
break;
case WT_AOP_NONE:
- default:
- WT_RET_MSG(session, EINVAL, "Unknown async optype %d\n",
- op->optype);
+ WT_RET_MSG(session, EINVAL,
+ "Unknown async optype %d\n", op->optype);
}
return (0);
}
diff --git a/src/block/block_ckpt.c b/src/block/block_ckpt.c
index 716121faa06..b9f0ec25d53 100644
--- a/src/block/block_ckpt.c
+++ b/src/block/block_ckpt.c
@@ -63,6 +63,7 @@ __wt_block_checkpoint_load(WT_SESSION_IMPL *session, WT_BLOCK *block,
*/
*root_addr_sizep = 0;
+#ifdef HAVE_VERBOSE
if (WT_VERBOSE_ISSET(session, WT_VERB_CHECKPOINT)) {
if (addr != NULL) {
WT_ERR(__wt_scr_alloc(session, 0, &tmp));
@@ -72,6 +73,7 @@ __wt_block_checkpoint_load(WT_SESSION_IMPL *session, WT_BLOCK *block,
"%s: load-checkpoint: %s", block->name,
addr == NULL ? "[Empty]" : (const char *)tmp->data));
}
+#endif
/*
* There's a single checkpoint in the file that can be written, all of
@@ -507,6 +509,7 @@ __ckpt_process(WT_SESSION_IMPL *session, WT_BLOCK *block, WT_CKPT *ckptbase)
!F_ISSET(ckpt, WT_CKPT_DELETE))
continue;
+#ifdef HAVE_VERBOSE
if (WT_VERBOSE_ISSET(session, WT_VERB_CHECKPOINT)) {
if (tmp == NULL)
WT_ERR(__wt_scr_alloc(session, 0, &tmp));
@@ -516,7 +519,7 @@ __ckpt_process(WT_SESSION_IMPL *session, WT_BLOCK *block, WT_CKPT *ckptbase)
"%s: delete-checkpoint: %s: %s",
block->name, ckpt->name, (const char *)tmp->data));
}
-
+#endif
/*
* Find the checkpoint into which we'll roll this checkpoint's
* blocks: it's the next real checkpoint in the list, and it
diff --git a/src/block/block_compact.c b/src/block/block_compact.c
index 24ca6632311..02862ea842f 100644
--- a/src/block/block_compact.c
+++ b/src/block/block_compact.c
@@ -39,12 +39,14 @@ __wt_block_compact_end(WT_SESSION_IMPL *session, WT_BLOCK *block)
/* Restore the original allocation plan. */
__wt_block_configure_first_fit(block, false);
+#ifdef HAVE_VERBOSE
/* Dump the results of the compaction pass. */
if (WT_VERBOSE_ISSET(session, WT_VERB_COMPACT)) {
__wt_spin_lock(session, &block->live_lock);
ret = __block_dump_avail(session, block, false);
__wt_spin_unlock(session, &block->live_lock);
}
+#endif
return (ret);
}
@@ -188,6 +190,7 @@ __wt_block_compact_page_skip(WT_SESSION_IMPL *session,
}
__wt_spin_unlock(session, &block->live_lock);
+#ifdef HAVE_VERBOSE
if (WT_VERBOSE_ISSET(session, WT_VERB_COMPACT)) {
++block->compact_pages_reviewed;
if (*skipp)
@@ -195,6 +198,7 @@ __wt_block_compact_page_skip(WT_SESSION_IMPL *session,
else
++block->compact_pages_written;
}
+#endif
return (ret);
}
diff --git a/src/block/block_ext.c b/src/block/block_ext.c
index 6d67a66be5f..0d3e7b54f17 100644
--- a/src/block/block_ext.c
+++ b/src/block/block_ext.c
@@ -24,7 +24,7 @@ static int __block_append(WT_SESSION_IMPL *,
static int __block_ext_overlap(WT_SESSION_IMPL *,
WT_BLOCK *, WT_EXTLIST *, WT_EXT **, WT_EXTLIST *, WT_EXT **);
static int __block_extlist_dump(
- WT_SESSION_IMPL *, const char *, WT_EXTLIST *, bool);
+ WT_SESSION_IMPL *, WT_BLOCK *, WT_EXTLIST *, const char *);
static int __block_merge(WT_SESSION_IMPL *,
WT_BLOCK *, WT_EXTLIST *, wt_off_t, wt_off_t);
@@ -1227,8 +1227,7 @@ corrupted: __wt_scr_free(session, &tmp);
WT_ERR(func(session, block, el, off, size));
}
- if (WT_VERBOSE_ISSET(session, WT_VERB_BLOCK))
- WT_ERR(__block_extlist_dump(session, "read extlist", el, 0));
+ WT_ERR(__block_extlist_dump(session, block, el, "read"));
err: __wt_scr_free(session, &tmp);
return (ret);
@@ -1250,8 +1249,7 @@ __wt_block_extlist_write(WT_SESSION_IMPL *session,
uint32_t entries;
uint8_t *p;
- if (WT_VERBOSE_ISSET(session, WT_VERB_BLOCK))
- WT_RET(__block_extlist_dump(session, "write extlist", el, 0));
+ WT_RET(__block_extlist_dump(session, block, el, "write"));
/*
* Figure out how many entries we're writing -- if there aren't any
@@ -1427,38 +1425,62 @@ __wt_block_extlist_free(WT_SESSION_IMPL *session, WT_EXTLIST *el)
*/
static int
__block_extlist_dump(
- WT_SESSION_IMPL *session, const char *tag, WT_EXTLIST *el, bool show_size)
+ WT_SESSION_IMPL *session, WT_BLOCK *block, WT_EXTLIST *el, const char *tag)
{
+ WT_DECL_ITEM(t1);
+ WT_DECL_ITEM(t2);
+ WT_DECL_RET;
WT_EXT *ext;
- WT_SIZE *szp;
+ uint64_t pow, sizes[64];
+ u_int i;
+ const char *sep;
- WT_RET(__wt_verbose(session, WT_VERB_BLOCK,
- "%s: %s: %" PRIu64 " bytes, by offset:%s",
- tag, el->name, el->bytes, el->entries == 0 ? " [Empty]" : ""));
- if (el->entries == 0)
+ if (!block->verify_layout && !WT_VERBOSE_ISSET(session, WT_VERB_BLOCK))
return (0);
- WT_EXT_FOREACH(ext, el->off)
- WT_RET(__wt_verbose(session, WT_VERB_BLOCK,
- "\t{%" PRIuMAX "/%" PRIuMAX "}",
- (uintmax_t)ext->off, (uintmax_t)ext->size));
+ WT_ERR(__wt_scr_alloc(session, 0, &t1));
+ if (block->verify_layout)
+ WT_ERR(__wt_msg(session,
+ "%s extent list %s, %" PRIu32 " entries, %s bytes",
+ tag, el->name, el->entries,
+ __wt_buf_set_size(session, el->bytes, true, t1)));
+ else
+ WT_ERR(__wt_verbose(session, WT_VERB_BLOCK,
+ "%s extent list %s, %" PRIu32 " entries, %s bytes",
+ tag, el->name, el->entries,
+ __wt_buf_set_size(session, el->bytes, true, t1)));
- if (!show_size)
- return (0);
+ if (ret != 0 || el->entries == 0)
+ goto done;
- WT_RET(__wt_verbose(session, WT_VERB_BLOCK,
- "%s: %s: by size:%s",
- tag, el->name, el->entries == 0 ? " [Empty]" : ""));
- if (el->entries == 0)
- return (0);
+ memset(sizes, 0, sizeof(sizes));
+ WT_EXT_FOREACH(ext, el->off)
+ for (i = 9, pow = 512;; ++i, pow *= 2)
+ if (ext->size <= (wt_off_t)pow) {
+ ++sizes[i];
+ break;
+ }
+ sep = "extents by bucket:";
+ t1->size = 0;
+ WT_ERR(__wt_scr_alloc(session, 0, &t2));
+ for (i = 9, pow = 512; i < WT_ELEMENTS(sizes); ++i, pow *= 2)
+ if (sizes[i] != 0) {
+ WT_ERR(__wt_buf_catfmt(session, t1,
+ "%s {%s: %" PRIu64 "}",
+ sep,
+ __wt_buf_set_size(session, pow, false, t2),
+ sizes[i]));
+ sep = ",";
+ }
- WT_EXT_FOREACH(szp, el->sz) {
- WT_RET(__wt_verbose(session, WT_VERB_BLOCK,
- "\t{%" PRIuMAX "}", (uintmax_t)szp->size));
- WT_EXT_FOREACH_OFF(ext, szp->off)
- WT_RET(__wt_verbose(session, WT_VERB_BLOCK,
- "\t\t{%" PRIuMAX "/%" PRIuMAX "}",
- (uintmax_t)ext->off, (uintmax_t)ext->size));
- }
- return (0);
+ if (block->verify_layout)
+ WT_ERR(__wt_msg(session, "%s", (char *)t1->data));
+ else
+ WT_ERR(__wt_verbose(
+ session, WT_VERB_BLOCK, "%s", (char *)t1->data));
+
+done: err:
+ __wt_scr_free(session, &t1);
+ __wt_scr_free(session, &t2);
+ return (ret);
}
diff --git a/src/block/block_open.c b/src/block/block_open.c
index e58bef30a6d..1603b1574e7 100644
--- a/src/block/block_open.c
+++ b/src/block/block_open.c
@@ -59,7 +59,7 @@ __wt_block_manager_create(
session, filename, tmp->data));
WT_ERR(__wt_msg(session,
"unexpected file %s found, renamed to %s",
- filename, (char *)tmp->data));
+ filename, (const char *)tmp->data));
break;
}
}
diff --git a/src/block/block_vrfy.c b/src/block/block_vrfy.c
index a8e59ad0af7..af58864b9dc 100644
--- a/src/block/block_vrfy.c
+++ b/src/block/block_vrfy.c
@@ -20,8 +20,10 @@ static int __verify_set_file_size(WT_SESSION_IMPL *, WT_BLOCK *, WT_CKPT *);
/* The bit list ignores the first block: convert to/from a frag/offset. */
#define WT_wt_off_TO_FRAG(block, off) \
((off) / (block)->allocsize - 1)
+#ifdef HAVE_VERBOSE
#define WT_FRAG_TO_OFF(block, frag) \
(((wt_off_t)(frag + 1)) * (block)->allocsize)
+#endif
/*
* __wt_block_verify_start --
@@ -35,6 +37,14 @@ __wt_block_verify_start(WT_SESSION_IMPL *session,
WT_CONFIG_ITEM cval;
wt_off_t size;
+ /* Configuration: strict behavior on any error. */
+ WT_RET(__wt_config_gets(session, cfg, "strict", &cval));
+ block->verify_strict = cval.val != 0;
+
+ /* Configuration: dump the file's layout. */
+ WT_RET(__wt_config_gets(session, cfg, "dump_layout", &cval));
+ block->verify_layout = cval.val != 0;
+
/*
* Find the last checkpoint in the list: if there are none, or the only
* checkpoint we have is fake, there's no work to do. Don't complain,
@@ -105,9 +115,6 @@ __wt_block_verify_start(WT_SESSION_IMPL *session,
*/
WT_RET(__verify_last_avail(session, block, ckpt));
- /* Configuration: strict behavior on any error. */
- WT_RET(__wt_config_gets(session, cfg, "strict", &cval));
- block->verify_strict = cval.val != 0;
return (0);
}
@@ -152,11 +159,23 @@ __verify_set_file_size(WT_SESSION_IMPL *session, WT_BLOCK *block, WT_CKPT *ckpt)
{
WT_BLOCK_CKPT *ci, _ci;
WT_DECL_RET;
+ WT_DECL_ITEM(tmp);
ci = &_ci;
WT_RET(__wt_block_ckpt_init(session, ci, ckpt->name));
WT_ERR(__wt_block_buffer_to_ckpt(session, block, ckpt->raw.data, ci));
+ if (block->verify_layout) {
+ WT_ERR(__wt_scr_alloc(session, 0, &tmp));
+ WT_ERR(__wt_msg(session, "%s: physical size %s", block->name,
+ __wt_buf_set_size(
+ session, (uint64_t)block->size, true, tmp)));
+ WT_ERR(
+ __wt_msg(session, "%s: correcting to %s checkpoint size %s",
+ block->name, ckpt->name, __wt_buf_set_size(
+ session, (uint64_t)ci->file_size, true, tmp)));
+ }
+
/*
* Verify is read-only. Set the block's file size information as if we
* truncated the file during checkpoint load, so references to blocks
@@ -165,6 +184,7 @@ __verify_set_file_size(WT_SESSION_IMPL *session, WT_BLOCK *block, WT_CKPT *ckpt)
block->size = block->extend_size = ci->file_size;
err: __wt_block_ckpt_destroy(session, ci);
+ __wt_scr_free(session, &tmp);
return (ret);
}
@@ -253,9 +273,9 @@ __wt_verify_ckpt_load(
}
/*
- * We don't need to list of blocks on a checkpoint's avail list, but we
- * read it to ensure it wasn't corrupted. We could confirm correctness
- * of intermediate avail lists (that is, if they're logically the result
+ * We don't need the blocks on a checkpoint's avail list, but we read it
+ * to ensure it wasn't corrupted. We could confirm correctness of the
+ * intermediate avail lists (that is, if they're logically the result
* of the allocations and discards to this point). We don't because the
* only avail list ever used is the one for the last checkpoint, which
* is separately verified by checking it against all of the blocks found
@@ -443,6 +463,7 @@ __verify_filefrag_chk(WT_SESSION_IMPL *session, WT_BLOCK *block)
__bit_set(block->fragfile, last);
}
+#ifdef HAVE_VERBOSE
if (!WT_VERBOSE_ISSET(session, WT_VERB_VERIFY))
continue;
@@ -450,6 +471,7 @@ __verify_filefrag_chk(WT_SESSION_IMPL *session, WT_BLOCK *block)
"file range %" PRIuMAX "-%" PRIuMAX " never verified",
(uintmax_t)WT_FRAG_TO_OFF(block, first),
(uintmax_t)WT_FRAG_TO_OFF(block, last));
+#endif
}
if (count == 0)
return (0);
@@ -534,6 +556,7 @@ __verify_ckptfrag_chk(WT_SESSION_IMPL *session, WT_BLOCK *block)
__bit_clear(block->fragckpt, last);
}
+#ifdef HAVE_VERBOSE
if (!WT_VERBOSE_ISSET(session, WT_VERB_VERIFY))
continue;
@@ -541,6 +564,7 @@ __verify_ckptfrag_chk(WT_SESSION_IMPL *session, WT_BLOCK *block)
"checkpoint range %" PRIuMAX "-%" PRIuMAX " never verified",
(uintmax_t)WT_FRAG_TO_OFF(block, first),
(uintmax_t)WT_FRAG_TO_OFF(block, last));
+#endif
}
if (count == 0)
diff --git a/src/btree/bt_cursor.c b/src/btree/bt_cursor.c
index 4b73b76c8c8..9a57759570a 100644
--- a/src/btree/bt_cursor.c
+++ b/src/btree/bt_cursor.c
@@ -559,7 +559,6 @@ retry: WT_RET(__cursor_func_init(cbt, true));
ret = __cursor_row_modify(session, cbt, false);
break;
- WT_ILLEGAL_VALUE_ERR(session);
}
err: if (ret == WT_RESTART) {
@@ -640,7 +639,8 @@ retry: WT_RET(__cursor_func_init(cbt, true));
break;
case BTREE_COL_FIX:
case BTREE_COL_VAR:
- WT_ILLEGAL_VALUE_ERR(session);
+ WT_ERR(__wt_illegal_value(session, NULL));
+ break;
}
err: if (ret == WT_RESTART) {
@@ -718,7 +718,6 @@ retry: WT_RET(__cursor_func_init(cbt, true));
ret = __cursor_row_modify(session, cbt, true);
break;
- WT_ILLEGAL_VALUE_ERR(session);
}
err: if (ret == WT_RESTART) {
@@ -809,7 +808,6 @@ retry: WT_RET(__cursor_func_init(cbt, true));
}
ret = __cursor_row_modify(session, cbt, false);
break;
- WT_ILLEGAL_VALUE_ERR(session);
}
err: if (ret == WT_RESTART) {
@@ -976,7 +974,6 @@ __wt_btcur_compare(WT_CURSOR_BTREE *a_arg, WT_CURSOR_BTREE *b_arg, int *cmpp)
WT_RET(__wt_compare(
session, a_arg->btree->collator, &a->key, &b->key, cmpp));
break;
- WT_ILLEGAL_VALUE(session);
}
return (0);
}
@@ -1027,6 +1024,7 @@ __wt_btcur_equals(WT_CURSOR_BTREE *a_arg, WT_CURSOR_BTREE *b_arg, int *equalp)
a = (WT_CURSOR *)a_arg;
b = (WT_CURSOR *)b_arg;
+ cmp = 0;
session = (WT_SESSION_IMPL *)a->session;
/* Confirm both cursors reference the same object. */
@@ -1114,7 +1112,7 @@ __cursor_truncate_fix(WT_SESSION_IMPL *session,
int (*rmfunc)(WT_SESSION_IMPL *, WT_CURSOR_BTREE *, bool))
{
WT_DECL_RET;
- uint8_t *value;
+ const uint8_t *value;
/*
* Handle fixed-length column-store objects separately: for row-store
@@ -1143,7 +1141,7 @@ retry: WT_RET(__wt_btcur_remove(start));
if ((ret = __wt_btcur_next(start, true)) != 0)
break;
start->compare = 0; /* Exact match */
- value = (uint8_t *)start->iface.value.data;
+ value = (const uint8_t *)start->iface.value.data;
if (*value != 0 &&
(ret = rmfunc(session, start, 1)) != 0)
break;
diff --git a/src/btree/bt_debug.c b/src/btree/bt_debug.c
index bd5970ecf86..b1579d25dc6 100644
--- a/src/btree/bt_debug.c
+++ b/src/btree/bt_debug.c
@@ -431,12 +431,12 @@ __debug_tree_shape_info(WT_PAGE *page)
v = page->memory_footprint;
if (v >= WT_GIGABYTE)
snprintf(buf, sizeof(buf),
- "(%p %" PRIu64 "G)", page, v / WT_GIGABYTE);
+ "(%p %" PRIu64 "G)", (void *)page, v / WT_GIGABYTE);
else if (v >= WT_MEGABYTE)
snprintf(buf, sizeof(buf),
- "(%p %" PRIu64 "M)", page, v / WT_MEGABYTE);
+ "(%p %" PRIu64 "M)", (void *)page, v / WT_MEGABYTE);
else
- snprintf(buf, sizeof(buf), "(%p %" PRIu64 ")", page, v);
+ snprintf(buf, sizeof(buf), "(%p %" PRIu64 ")", (void *)page, v);
return (buf);
}
@@ -636,7 +636,7 @@ __debug_page_metadata(WT_DBG *ds, WT_REF *ref)
page = ref->page;
mod = page->modify;
- __dmsg(ds, "%p", page);
+ __dmsg(ds, "%p", (void *)page);
switch (page->type) {
case WT_PAGE_COL_INT:
@@ -663,7 +663,8 @@ __debug_page_metadata(WT_DBG *ds, WT_REF *ref)
}
__dmsg(ds, ": %s\n", __wt_page_type_string(page->type));
- __dmsg(ds, "\t" "disk %p, entries %" PRIu32, page->dsk, entries);
+ __dmsg(ds,
+ "\t" "disk %p, entries %" PRIu32, (void *)page->dsk, entries);
__dmsg(ds, ", %s", __wt_page_is_modified(page) ? "dirty" : "clean");
__dmsg(ds, ", %s", __wt_fair_islocked(
session, &page->page_lock) ? "locked" : "unlocked");
@@ -894,7 +895,7 @@ __debug_page_row_leaf(WT_DBG *ds, WT_PAGE *page)
/* Dump the page's K/V pairs. */
WT_ROW_FOREACH(page, rip, i) {
- WT_RET(__wt_row_leaf_key(session, page, rip, key, false));
+ WT_ERR(__wt_row_leaf_key(session, page, rip, key, false));
__debug_item(ds, "K", key->data, key->size);
if ((cell = __wt_row_leaf_value_cell(page, rip, NULL)) == NULL)
@@ -990,10 +991,10 @@ __debug_ref(WT_DBG *ds, WT_REF *ref)
__dmsg(ds, "deleted");
break;
case WT_REF_LOCKED:
- __dmsg(ds, "locked %p", ref->page);
+ __dmsg(ds, "locked %p", (void *)ref->page);
break;
case WT_REF_MEM:
- __dmsg(ds, "memory %p", ref->page);
+ __dmsg(ds, "memory %p", (void *)ref->page);
break;
case WT_REF_READING:
__dmsg(ds, "reading");
@@ -1155,14 +1156,14 @@ static void
__debug_item(WT_DBG *ds, const char *tag, const void *data_arg, size_t size)
{
size_t i;
- int ch;
+ u_char ch;
const uint8_t *data;
__dmsg(ds, "\t%s%s{", tag == NULL ? "" : tag, tag == NULL ? "" : " ");
for (data = data_arg, i = 0; i < size; ++i, ++data) {
ch = data[0];
- if (isprint(ch))
- __dmsg(ds, "%c", ch);
+ if (__wt_isprint(ch))
+ __dmsg(ds, "%c", (int)ch);
else
__debug_hex_byte(ds, data[0]);
}
diff --git a/src/btree/bt_discard.c b/src/btree/bt_discard.c
index 9807d5bc88f..a00bb7dc2b5 100644
--- a/src/btree/bt_discard.c
+++ b/src/btree/bt_discard.c
@@ -82,7 +82,7 @@ __wt_page_out(WT_SESSION_IMPL *session, WT_PAGE **pagep)
if (hp != NULL)
__wt_errx(session,
"discarded page has hazard pointer: (%p: %s, line %d)",
- hp->page, hp->file, hp->line);
+ (void *)hp->page, hp->file, hp->line);
WT_ASSERT(session, hp == NULL);
}
#endif
diff --git a/src/btree/bt_handle.c b/src/btree/bt_handle.c
index 118195779e9..c97e05d74a7 100644
--- a/src/btree/bt_handle.c
+++ b/src/btree/bt_handle.c
@@ -519,7 +519,6 @@ __btree_tree_open_empty(WT_SESSION_IMPL *session, bool creation)
ref->state = WT_REF_DELETED;
WT_ERR(__wt_row_ikey_incr(session, root, 0, "", 1, ref));
break;
- WT_ILLEGAL_VALUE_ERR(session);
}
/* Bulk loads require a leaf page for reconciliation: create it now. */
@@ -567,7 +566,6 @@ __wt_btree_new_leaf_page(WT_SESSION_IMPL *session, WT_PAGE **pagep)
WT_RET(__wt_page_alloc(
session, WT_PAGE_ROW_LEAF, 0, false, pagep));
break;
- WT_ILLEGAL_VALUE(session);
}
return (0);
}
@@ -689,10 +687,9 @@ __btree_page_sizes(WT_SESSION_IMPL *session)
"size (%" PRIu32 "B)", btree->allocsize);
/*
- * Don't let pages grow larger than a quarter of the cache, with too-
- * small caches, we can end up in a situation where nothing can be
- * evicted. Take care getting the cache size: with a shared cache,
- * it may not have been set.
+ * Don't let pages grow large compared to the cache size or we can end
+ * up in a situation where nothing can be evicted. Take care getting
+ * the cache size: with a shared cache, it may not have been set.
*/
WT_RET(__wt_config_gets(session, cfg, "memory_page_max", &cval));
btree->maxmempage = (uint64_t)cval.val;
diff --git a/src/btree/bt_io.c b/src/btree/bt_io.c
index aaf906ca785..4339de6f25c 100644
--- a/src/btree/bt_io.c
+++ b/src/btree/bt_io.c
@@ -343,6 +343,7 @@ __wt_bt_write(WT_SESSION_IMPL *session, WT_ITEM *buf,
* Checksum the data if the buffer isn't compressed or checksums are
* configured.
*/
+ data_cksum = true; /* -Werror=maybe-uninitialized */
switch (btree->checksum) {
case CKSUM_ON:
data_cksum = true;
@@ -351,7 +352,6 @@ __wt_bt_write(WT_SESSION_IMPL *session, WT_ITEM *buf,
data_cksum = false;
break;
case CKSUM_UNCOMPRESSED:
- default:
data_cksum = !compressed;
break;
}
diff --git a/src/btree/bt_misc.c b/src/btree/bt_misc.c
index 7f188502a0a..b6e2cc07f5a 100644
--- a/src/btree/bt_misc.c
+++ b/src/btree/bt_misc.c
@@ -129,19 +129,3 @@ __wt_addr_string(WT_SESSION_IMPL *session,
}
return (buf->data);
}
-
-/*
- * __wt_buf_set_printable --
- * Set the contents of the buffer to a printable representation of a
- * byte string.
- */
-const char *
-__wt_buf_set_printable(
- WT_SESSION_IMPL *session, const void *p, size_t size, WT_ITEM *buf)
-{
- if (__wt_raw_to_esc_hex(session, p, size, buf)) {
- buf->data = "[Error]";
- buf->size = strlen("[Error]");
- }
- return (buf->data);
-}
diff --git a/src/btree/bt_read.c b/src/btree/bt_read.c
index 89d16a3f827..086500c8b2f 100644
--- a/src/btree/bt_read.c
+++ b/src/btree/bt_read.c
@@ -326,7 +326,7 @@ __evict_force_check(WT_SESSION_IMPL *session, WT_REF *ref)
__wt_page_evict_soon(page);
/* Bump the oldest ID, we're about to do some visibility checks. */
- WT_RET(__wt_txn_update_oldest(session, false));
+ WT_RET(__wt_txn_update_oldest(session, 0));
/* If eviction cannot succeed, don't try. */
return (__wt_page_can_evict(session, ref, NULL));
diff --git a/src/btree/bt_split.c b/src/btree/bt_split.c
index 2d7b0a0030f..7a05a883f83 100644
--- a/src/btree/bt_split.c
+++ b/src/btree/bt_split.c
@@ -1841,8 +1841,11 @@ __split_insert(WT_SESSION_IMPL *session, WT_REF *ref)
*/
for (i = 0; i < WT_SKIP_MAXDEPTH && ins_head->tail[i] == moved_ins; ++i)
;
- WT_MEM_TRANSFER(page_decr, right_incr, sizeof(WT_INSERT) +
- (size_t)i * sizeof(WT_INSERT *) + WT_INSERT_KEY_SIZE(moved_ins));
+ WT_MEM_TRANSFER(page_decr, right_incr,
+ sizeof(WT_INSERT) + (size_t)i * sizeof(WT_INSERT *));
+ if (type == WT_PAGE_ROW_LEAF)
+ WT_MEM_TRANSFER(
+ page_decr, right_incr, WT_INSERT_KEY_SIZE(moved_ins));
WT_MEM_TRANSFER(
page_decr, right_incr, __wt_update_list_memsize(moved_ins->upd));
@@ -1951,9 +1954,6 @@ __split_insert(WT_SESSION_IMPL *session, WT_REF *ref)
/*
* Update the page accounting.
- *
- * XXX
- * If we fail to split the parent, the page's accounting will be wrong.
*/
__wt_cache_page_inmem_decr(session, page, page_decr);
__wt_cache_page_inmem_incr(session, right, right_incr);
@@ -1999,6 +1999,9 @@ __split_insert(WT_SESSION_IMPL *session, WT_REF *ref)
ins_head->tail[0]->next[0] = moved_ins;
ins_head->tail[0] = moved_ins;
+ /* Fix up accounting for the page size. */
+ __wt_cache_page_inmem_incr(session, page, page_decr);
+
err: if (split_ref[0] != NULL) {
/*
* The address was moved to the replacement WT_REF, restore it.
diff --git a/src/btree/bt_sync.c b/src/btree/bt_sync.c
index 4404069e507..da6c53aa316 100644
--- a/src/btree/bt_sync.c
+++ b/src/btree/bt_sync.c
@@ -188,7 +188,8 @@ __sync_file(WT_SESSION_IMPL *session, WT_CACHE_OP syncop)
break;
case WT_SYNC_CLOSE:
case WT_SYNC_DISCARD:
- WT_ILLEGAL_VALUE_ERR(session);
+ WT_ERR(__wt_illegal_value(session, NULL));
+ break;
}
if (WT_VERBOSE_ISSET(session, WT_VERB_CHECKPOINT)) {
@@ -273,6 +274,8 @@ err: /* On error, clear any left-over tree walk. */
int
__wt_cache_op(WT_SESSION_IMPL *session, WT_CACHE_OP op)
{
+ WT_DECL_RET;
+
switch (op) {
case WT_SYNC_CHECKPOINT:
case WT_SYNC_CLOSE:
@@ -292,10 +295,12 @@ __wt_cache_op(WT_SESSION_IMPL *session, WT_CACHE_OP op)
switch (op) {
case WT_SYNC_CHECKPOINT:
case WT_SYNC_WRITE_LEAVES:
- return (__sync_file(session, op));
+ ret = __sync_file(session, op);
+ break;
case WT_SYNC_CLOSE:
case WT_SYNC_DISCARD:
- return (__wt_evict_file(session, op));
- WT_ILLEGAL_VALUE(session);
+ ret = __wt_evict_file(session, op);
+ break;
}
+ return (ret);
}
diff --git a/src/btree/bt_vrfy.c b/src/btree/bt_vrfy.c
index 531a0dc125a..0a04c387a0f 100644
--- a/src/btree/bt_vrfy.c
+++ b/src/btree/bt_vrfy.c
@@ -22,13 +22,13 @@ typedef struct {
#define WT_VRFY_DUMP(vs) \
((vs)->dump_address || \
- (vs)->dump_blocks || (vs)->dump_pages || (vs)->dump_shape)
+ (vs)->dump_blocks || (vs)->dump_layout || (vs)->dump_pages)
bool dump_address; /* Configure: dump special */
bool dump_blocks;
+ bool dump_layout;
bool dump_pages;
- bool dump_shape;
-
- u_int depth, depth_internal[100], depth_leaf[100];
+ /* Page layout information */
+ uint64_t depth, depth_internal[100], depth_leaf[100];
WT_ITEM *tmp1, *tmp2, *tmp3, *tmp4; /* Temporary buffers */
} WT_VSTUFF;
@@ -59,12 +59,12 @@ __verify_config(WT_SESSION_IMPL *session, const char *cfg[], WT_VSTUFF *vs)
WT_RET(__wt_config_gets(session, cfg, "dump_blocks", &cval));
vs->dump_blocks = cval.val != 0;
+ WT_RET(__wt_config_gets(session, cfg, "dump_layout", &cval));
+ vs->dump_layout = cval.val != 0;
+
WT_RET(__wt_config_gets(session, cfg, "dump_pages", &cval));
vs->dump_pages = cval.val != 0;
- WT_RET(__wt_config_gets(session, cfg, "dump_shape", &cval));
- vs->dump_shape = cval.val != 0;
-
#if !defined(HAVE_DIAGNOSTIC)
if (vs->dump_blocks || vs->dump_pages)
WT_RET_MSG(session, ENOTSUP,
@@ -112,33 +112,38 @@ __verify_config_offsets(
}
/*
- * __verify_tree_shape --
+ * __verify_layout --
* Dump the tree shape.
*/
static int
-__verify_tree_shape(WT_SESSION_IMPL *session, WT_VSTUFF *vs)
+__verify_layout(WT_SESSION_IMPL *session, WT_VSTUFF *vs)
{
- uint32_t total;
+ uint64_t total;
size_t i;
for (i = 0, total = 0; i < WT_ELEMENTS(vs->depth_internal); ++i)
total += vs->depth_internal[i];
WT_RET(__wt_msg(
- session, "Internal page tree-depth (total %" PRIu32 "):", total));
+ session, "Internal page tree-depth (total %" PRIu64 "):", total));
for (i = 0; i < WT_ELEMENTS(vs->depth_internal); ++i)
- if (vs->depth_internal[i] != 0)
+ if (vs->depth_internal[i] != 0) {
WT_RET(__wt_msg(session,
- "\t%03zu: %u", i, vs->depth_internal[i]));
+ "\t%03" WT_SIZET_FMT ": %" PRIu64,
+ i, vs->depth_internal[i]));
+ vs->depth_internal[i] = 0;
+ }
for (i = 0, total = 0; i < WT_ELEMENTS(vs->depth_leaf); ++i)
total += vs->depth_leaf[i];
WT_RET(__wt_msg(
- session, "Leaf page tree-depth (total %" PRIu32 "):", total));
+ session, "Leaf page tree-depth (total %" PRIu64 "):", total));
for (i = 0; i < WT_ELEMENTS(vs->depth_leaf); ++i)
- if (vs->depth_leaf[i] != 0)
+ if (vs->depth_leaf[i] != 0) {
WT_RET(__wt_msg(session,
- "\t%03zu: %u", i, vs->depth_leaf[i]));
-
+ "\t%03" WT_SIZET_FMT ": %" PRIu64,
+ i, vs->depth_leaf[i]));
+ vs->depth_leaf[i] = 0;
+ }
return (0);
}
@@ -200,9 +205,11 @@ __wt_verify(WT_SESSION_IMPL *session, const char *cfg[])
/* House-keeping between checkpoints. */
__verify_checkpoint_reset(vs);
- if (WT_VRFY_DUMP(vs))
+ if (WT_VRFY_DUMP(vs)) {
+ WT_ERR(__wt_msg(session, "%s", WT_DIVIDER));
WT_ERR(__wt_msg(session, "%s: checkpoint %s",
btree->dhandle->name, ckpt->name));
+ }
/* Load the checkpoint. */
WT_ERR(bm->checkpoint_load(bm, session,
@@ -234,8 +241,8 @@ __wt_verify(WT_SESSION_IMPL *session, const char *cfg[])
WT_ERR(ret);
/* Display the tree shape. */
- if (vs->dump_shape)
- WT_ERR(__verify_tree_shape(session, vs));
+ if (vs->dump_layout)
+ WT_ERR(__verify_layout(session, vs));
}
done:
diff --git a/src/btree/bt_vrfy_dsk.c b/src/btree/bt_vrfy_dsk.c
index 5480a25b5ec..3a6fd8261ba 100644
--- a/src/btree/bt_vrfy_dsk.c
+++ b/src/btree/bt_vrfy_dsk.c
@@ -298,14 +298,11 @@ __verify_dsk_row(
case WT_CELL_ADDR_LEAF_NO:
case WT_CELL_KEY_OVFL:
case WT_CELL_VALUE_OVFL:
- ret = bm->addr_invalid(
- bm, session, unpack->data, unpack->size);
- WT_RET_ERROR_OK(ret, EINVAL);
- if (ret == EINVAL) {
+ if ((ret = bm->addr_invalid(
+ bm, session, unpack->data, unpack->size)) == EINVAL)
ret = __err_cell_corrupt_or_eof(
session, cell_num, tag);
- goto err;
- }
+ WT_ERR(ret);
break;
}
diff --git a/src/btree/row_srch.c b/src/btree/row_srch.c
index a631764be7e..4afcd74520f 100644
--- a/src/btree/row_srch.c
+++ b/src/btree/row_srch.c
@@ -639,10 +639,11 @@ __wt_row_random_leaf(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt)
int level;
page = cbt->ref->page;
-
start = stop = NULL; /* [-Wconditional-uninitialized] */
entries = 0; /* [-Wconditional-uninitialized] */
+ __cursor_pos_clear(cbt);
+
/* If the page has disk-based entries, select from them. */
if (page->pg_row_entries != 0) {
cbt->compare = 0;
@@ -795,8 +796,6 @@ __wt_row_random_descent(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt)
btree = S2BT(session);
current = NULL;
- __cursor_pos_clear(cbt);
-
if (0) {
restart: /*
* Discard the currently held page and restart the search from
diff --git a/src/checksum/checksum.c b/src/checksum/checksum.c
index 0b086753406..b6a76dacfd8 100644
--- a/src/checksum/checksum.c
+++ b/src/checksum/checksum.c
@@ -1103,6 +1103,7 @@ static const uint32_t g_crc_slicing[8][256] = {
#endif
};
+#if !defined(__powerpc64__)
/*
* __wt_cksum_sw --
* Return a checksum for a chunk of memory, computed in software.
@@ -1171,6 +1172,7 @@ __wt_cksum_sw(const void *chunk, size_t len)
#endif
return (~crc);
}
+#endif
#if (defined(__amd64) || defined(__x86_64))
/*
diff --git a/src/checksum/power8/crc32_wrapper.c b/src/checksum/power8/crc32_wrapper.c
index 34ac4150338..62bd3e64f5c 100644
--- a/src/checksum/power8/crc32_wrapper.c
+++ b/src/checksum/power8/crc32_wrapper.c
@@ -2,7 +2,7 @@
#define CRC_TABLE
#include "crc32_constants.h"
-#define VMX_ALIGN 16
+#define VMX_ALIGN 16U
#define VMX_ALIGN_MASK (VMX_ALIGN-1)
#ifdef REFLECT
@@ -26,6 +26,9 @@ static unsigned int crc32_align(unsigned int crc, unsigned char *p,
unsigned int __crc32_vpmsum(unsigned int crc, unsigned char *p,
unsigned long len);
+/* -Werror=missing-prototypes */
+unsigned int crc32_vpmsum(unsigned int crc, unsigned char *p,
+ unsigned long len);
unsigned int crc32_vpmsum(unsigned int crc, unsigned char *p,
unsigned long len)
{
diff --git a/src/config/config_def.c b/src/config/config_def.c
index 7a75db8857d..1b656c5a0aa 100644
--- a/src/config/config_def.c
+++ b/src/config/config_def.c
@@ -380,9 +380,9 @@ static const WT_CONFIG_CHECK confchk_WT_SESSION_transaction_sync[] = {
static const WT_CONFIG_CHECK confchk_WT_SESSION_verify[] = {
{ "dump_address", "boolean", NULL, NULL, NULL, 0 },
{ "dump_blocks", "boolean", NULL, NULL, NULL, 0 },
+ { "dump_layout", "boolean", NULL, NULL, NULL, 0 },
{ "dump_offsets", "list", NULL, NULL, NULL, 0 },
{ "dump_pages", "boolean", NULL, NULL, NULL, 0 },
- { "dump_shape", "boolean", NULL, NULL, NULL, 0 },
{ "strict", "boolean", NULL, NULL, NULL, 0 },
{ NULL, NULL, NULL, NULL, NULL, 0 }
};
@@ -976,7 +976,7 @@ static const WT_CONFIG_ENTRY config_entries[] = {
"eviction_dirty_trigger=95,eviction_target=80,eviction_trigger=95"
",file_manager=(close_handle_minimum=250,close_idle_time=30,"
"close_scan_interval=10),log=(archive=,compressor=,enabled=0,"
- "file_max=100MB,path=,prealloc=,recover=on,zero_fill=0),"
+ "file_max=100MB,path=\".\",prealloc=,recover=on,zero_fill=0),"
"lsm_manager=(merge=,worker_thread_max=4),lsm_merge=,"
"shared_cache=(chunk=10MB,name=,quota=0,reserve=0,size=500MB),"
"statistics=none,statistics_log=(json=0,on_close=0,"
@@ -1102,8 +1102,8 @@ static const WT_CONFIG_ENTRY config_entries[] = {
NULL, 0
},
{ "WT_SESSION.verify",
- "dump_address=0,dump_blocks=0,dump_offsets=,dump_pages=0,"
- "dump_shape=0,strict=0",
+ "dump_address=0,dump_blocks=0,dump_layout=0,dump_offsets=,"
+ "dump_pages=0,strict=0",
confchk_WT_SESSION_verify, 6
},
{ "colgroup.meta",
@@ -1177,14 +1177,15 @@ static const WT_CONFIG_ENTRY config_entries[] = {
"file_extend=,file_manager=(close_handle_minimum=250,"
"close_idle_time=30,close_scan_interval=10),hazard_max=1000,"
"in_memory=0,log=(archive=,compressor=,enabled=0,file_max=100MB,"
- "path=,prealloc=,recover=on,zero_fill=0),lsm_manager=(merge=,"
- "worker_thread_max=4),lsm_merge=,mmap=,multiprocess=0,readonly=0,"
- "session_max=100,session_scratch_max=2MB,shared_cache=(chunk=10MB"
- ",name=,quota=0,reserve=0,size=500MB),statistics=none,"
- "statistics_log=(json=0,on_close=0,path=\"WiredTigerStat.%d.%H\","
- "sources=,timestamp=\"%b %d %H:%M:%S\",wait=0),"
- "transaction_sync=(enabled=0,method=fsync),use_environment=,"
- "use_environment_priv=0,verbose=,write_through=",
+ "path=\".\",prealloc=,recover=on,zero_fill=0),lsm_manager=(merge="
+ ",worker_thread_max=4),lsm_merge=,mmap=,multiprocess=0,readonly=0"
+ ",session_max=100,session_scratch_max=2MB,"
+ "shared_cache=(chunk=10MB,name=,quota=0,reserve=0,size=500MB),"
+ "statistics=none,statistics_log=(json=0,on_close=0,"
+ "path=\"WiredTigerStat.%d.%H\",sources=,"
+ "timestamp=\"%b %d %H:%M:%S\",wait=0),transaction_sync=(enabled=0"
+ ",method=fsync),use_environment=,use_environment_priv=0,verbose=,"
+ "write_through=",
confchk_wiredtiger_open, 38
},
{ "wiredtiger_open_all",
@@ -1198,15 +1199,15 @@ static const WT_CONFIG_ENTRY config_entries[] = {
"file_extend=,file_manager=(close_handle_minimum=250,"
"close_idle_time=30,close_scan_interval=10),hazard_max=1000,"
"in_memory=0,log=(archive=,compressor=,enabled=0,file_max=100MB,"
- "path=,prealloc=,recover=on,zero_fill=0),lsm_manager=(merge=,"
- "worker_thread_max=4),lsm_merge=,mmap=,multiprocess=0,readonly=0,"
- "session_max=100,session_scratch_max=2MB,shared_cache=(chunk=10MB"
- ",name=,quota=0,reserve=0,size=500MB),statistics=none,"
- "statistics_log=(json=0,on_close=0,path=\"WiredTigerStat.%d.%H\","
- "sources=,timestamp=\"%b %d %H:%M:%S\",wait=0),"
- "transaction_sync=(enabled=0,method=fsync),use_environment=,"
- "use_environment_priv=0,verbose=,version=(major=0,minor=0),"
- "write_through=",
+ "path=\".\",prealloc=,recover=on,zero_fill=0),lsm_manager=(merge="
+ ",worker_thread_max=4),lsm_merge=,mmap=,multiprocess=0,readonly=0"
+ ",session_max=100,session_scratch_max=2MB,"
+ "shared_cache=(chunk=10MB,name=,quota=0,reserve=0,size=500MB),"
+ "statistics=none,statistics_log=(json=0,on_close=0,"
+ "path=\"WiredTigerStat.%d.%H\",sources=,"
+ "timestamp=\"%b %d %H:%M:%S\",wait=0),transaction_sync=(enabled=0"
+ ",method=fsync),use_environment=,use_environment_priv=0,verbose=,"
+ "version=(major=0,minor=0),write_through=",
confchk_wiredtiger_open_all, 39
},
{ "wiredtiger_open_basecfg",
@@ -1218,7 +1219,7 @@ static const WT_CONFIG_ENTRY config_entries[] = {
"eviction_dirty_trigger=95,eviction_target=80,eviction_trigger=95"
",extensions=,file_extend=,file_manager=(close_handle_minimum=250"
",close_idle_time=30,close_scan_interval=10),hazard_max=1000,"
- "log=(archive=,compressor=,enabled=0,file_max=100MB,path=,"
+ "log=(archive=,compressor=,enabled=0,file_max=100MB,path=\".\","
"prealloc=,recover=on,zero_fill=0),lsm_manager=(merge=,"
"worker_thread_max=4),lsm_merge=,mmap=,multiprocess=0,readonly=0,"
"session_max=100,session_scratch_max=2MB,shared_cache=(chunk=10MB"
@@ -1238,7 +1239,7 @@ static const WT_CONFIG_ENTRY config_entries[] = {
"eviction_dirty_trigger=95,eviction_target=80,eviction_trigger=95"
",extensions=,file_extend=,file_manager=(close_handle_minimum=250"
",close_idle_time=30,close_scan_interval=10),hazard_max=1000,"
- "log=(archive=,compressor=,enabled=0,file_max=100MB,path=,"
+ "log=(archive=,compressor=,enabled=0,file_max=100MB,path=\".\","
"prealloc=,recover=on,zero_fill=0),lsm_manager=(merge=,"
"worker_thread_max=4),lsm_merge=,mmap=,multiprocess=0,readonly=0,"
"session_max=100,session_scratch_max=2MB,shared_cache=(chunk=10MB"
diff --git a/src/conn/api_strerror.c b/src/conn/api_strerror.c
index 87864f7f4b0..edb11957556 100644
--- a/src/conn/api_strerror.c
+++ b/src/conn/api_strerror.c
@@ -40,8 +40,6 @@ __wt_wiredtiger_error(int error)
return ("WT_RUN_RECOVERY: recovery must be run to continue");
case WT_CACHE_FULL:
return ("WT_CACHE_FULL: operation would overflow cache");
- case WT_PERM_DENIED:
- return ("WT_PERM_DENIED: permission denied (internal)");
}
/*
diff --git a/src/conn/conn_api.c b/src/conn/conn_api.c
index dde3fb6930e..98267eeeb2c 100644
--- a/src/conn/conn_api.c
+++ b/src/conn/conn_api.c
@@ -751,6 +751,7 @@ __conn_get_extension_api(WT_CONNECTION *wt_conn)
conn->extension_api.err_printf = __wt_ext_err_printf;
conn->extension_api.msg_printf = __wt_ext_msg_printf;
conn->extension_api.strerror = __wt_ext_strerror;
+ conn->extension_api.map_windows_error = __wt_ext_map_windows_error;
conn->extension_api.scr_alloc = __wt_ext_scr_alloc;
conn->extension_api.scr_free = __wt_ext_scr_free;
conn->extension_api.collator_config = ext_collator_config;
@@ -1298,7 +1299,8 @@ __conn_config_file(WT_SESSION_IMPL *session,
* the next character is a hash mark, skip to the next newline.
*/
for (;;) {
- for (*t++ = ','; --len > 0 && isspace(*++p);)
+ for (*t++ = ',';
+ --len > 0 && __wt_isspace((u_char)*++p);)
;
if (len == 0)
break;
@@ -1517,17 +1519,14 @@ __conn_single(WT_SESSION_IMPL *session, const char *cfg[])
* if the file does not exist. If so, then ignore the error.
* XXX Ignoring the error does allow multiple read-only
* connections to exist at the same time on a read-only directory.
+ *
+ * If we got an expected permission or non-existence error then skip
+ * the byte lock.
*/
- if (F_ISSET(conn, WT_CONN_READONLY)) {
- /*
- * If we got an expected permission or non-existence error
- * then skip the byte lock.
- */
- ret = __wt_map_error_rdonly(ret);
- if (ret == WT_NOTFOUND || ret == WT_PERM_DENIED) {
- bytelock = false;
- ret = 0;
- }
+ if (F_ISSET(conn, WT_CONN_READONLY) &&
+ (ret == EACCES || ret == ENOENT)) {
+ bytelock = false;
+ ret = 0;
}
WT_ERR(ret);
if (bytelock) {
@@ -1567,19 +1566,16 @@ __conn_single(WT_SESSION_IMPL *session, const char *cfg[])
WT_OPEN_FILE_TYPE_REGULAR, is_create ? WT_OPEN_CREATE : 0, &fh);
/*
- * If we're read-only, check for success as well as handled errors.
- * Even if we're able to open the WiredTiger file successfully, we
- * do not try to lock it. The lock file test above is the only
- * one we do for read-only.
+ * If we're read-only, check for handled errors. Even if able to open
+ * the WiredTiger file successfully, we do not try to lock it. The
+ * lock file test above is the only one we do for read-only.
*/
if (F_ISSET(conn, WT_CONN_READONLY)) {
- ret = __wt_map_error_rdonly(ret);
- if (ret == 0 || ret == WT_NOTFOUND || ret == WT_PERM_DENIED)
+ if (ret == EACCES || ret == ENOENT)
ret = 0;
WT_ERR(ret);
} else {
WT_ERR(ret);
-
/*
* Lock the WiredTiger file (for backward compatibility reasons
* as described above). Immediately release the lock, it's
diff --git a/src/conn/conn_cache.c b/src/conn/conn_cache.c
index 4d33ac608bb..9f15db5382b 100644
--- a/src/conn/conn_cache.c
+++ b/src/conn/conn_cache.c
@@ -158,9 +158,14 @@ __wt_cache_create(WT_SESSION_IMPL *session, const char *cfg[])
false, 10000, WT_MILLION, &cache->evict_cond));
WT_ERR(__wt_cond_alloc(session,
"eviction waiters", false, &cache->evict_waiter_cond));
+ WT_ERR(__wt_spin_init(session, &cache->evict_pass_lock, "evict pass"));
WT_ERR(__wt_spin_init(session,
&cache->evict_queue_lock, "cache eviction queue"));
WT_ERR(__wt_spin_init(session, &cache->evict_walk_lock, "cache walk"));
+ if ((ret = __wt_open_internal_session(conn, "evict pass",
+ false, WT_SESSION_NO_DATA_HANDLES, &cache->walk_session)) != 0)
+ WT_ERR_MSG(NULL, ret,
+ "Failed to create session for eviction walks");
/* Allocate the LRU eviction queue. */
cache->evict_slots = WT_EVICT_WALK_BASE + WT_EVICT_WALK_INCR;
@@ -223,6 +228,14 @@ __wt_cache_stats_update(WT_SESSION_IMPL *session)
WT_STAT_SET(
session, stats, cache_bytes_overflow, cache->bytes_overflow);
WT_STAT_SET(session, stats, cache_bytes_leaf, leaf);
+
+ /*
+ * The number of files with active walks ~= number of hazard pointers
+ * in the walk session. Note: reading without locking.
+ */
+ if (conn->evict_session != NULL)
+ WT_STAT_SET(session, stats, cache_eviction_walks_active,
+ conn->evict_session->nhazard);
}
/*
@@ -235,6 +248,7 @@ __wt_cache_destroy(WT_SESSION_IMPL *session)
WT_CACHE *cache;
WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
+ WT_SESSION *wt_session;
int i;
conn = S2C(session);
@@ -261,8 +275,12 @@ __wt_cache_destroy(WT_SESSION_IMPL *session)
WT_TRET(__wt_cond_auto_destroy(session, &cache->evict_cond));
WT_TRET(__wt_cond_destroy(session, &cache->evict_waiter_cond));
+ __wt_spin_destroy(session, &cache->evict_pass_lock);
__wt_spin_destroy(session, &cache->evict_queue_lock);
__wt_spin_destroy(session, &cache->evict_walk_lock);
+ wt_session = &cache->walk_session->iface;
+ if (wt_session != NULL)
+ WT_TRET(wt_session->close(wt_session, NULL));
for (i = 0; i < WT_EVICT_QUEUE_MAX; ++i) {
__wt_spin_destroy(session, &cache->evict_queues[i].evict_lock);
diff --git a/src/conn/conn_cache_pool.c b/src/conn/conn_cache_pool.c
index 898bd09ece9..75ecb6b3b4a 100644
--- a/src/conn/conn_cache_pool.c
+++ b/src/conn/conn_cache_pool.c
@@ -309,6 +309,7 @@ __wt_conn_cache_pool_destroy(WT_SESSION_IMPL *session)
if (!F_ISSET(conn, WT_CONN_CACHE_POOL))
return (0);
+ F_CLR(conn, WT_CONN_CACHE_POOL);
__wt_spin_lock(session, &cp->cache_pool_lock);
cp_locked = true;
diff --git a/src/conn/conn_dhandle.c b/src/conn/conn_dhandle.c
index 4c2cf9a8dc2..08fb2b24468 100644
--- a/src/conn/conn_dhandle.c
+++ b/src/conn/conn_dhandle.c
@@ -544,6 +544,7 @@ __wt_conn_dhandle_discard_single(
WT_DATA_HANDLE *dhandle;
WT_DECL_RET;
int tret;
+ bool set_pass_intr;
dhandle = session->dhandle;
@@ -562,12 +563,17 @@ __wt_conn_dhandle_discard_single(
* Kludge: interrupt the eviction server in case it is holding the
* handle list lock.
*/
- if (!F_ISSET(session, WT_SESSION_LOCKED_HANDLE_LIST))
- F_SET(S2C(session)->cache, WT_CACHE_CLEAR_WALKS);
+ set_pass_intr = false;
+ if (!F_ISSET(session, WT_SESSION_LOCKED_HANDLE_LIST)) {
+ set_pass_intr = true;
+ (void)__wt_atomic_add32(&S2C(session)->cache->pass_intr, 1);
+ }
/* Try to remove the handle, protected by the data handle lock. */
WT_WITH_HANDLE_LIST_LOCK(session,
tret = __conn_dhandle_remove(session, final));
+ if (set_pass_intr)
+ (void)__wt_atomic_sub32(&S2C(session)->cache->pass_intr, 1);
WT_TRET(tret);
/*
diff --git a/src/conn/conn_log.c b/src/conn/conn_log.c
index 5397962bc4f..1ae370ef2fa 100644
--- a/src/conn/conn_log.c
+++ b/src/conn/conn_log.c
@@ -544,8 +544,6 @@ restart:
while (i < WT_SLOT_POOL) {
save_i = i;
slot = &log->slot_pool[i++];
- WT_ASSERT(session, slot->slot_state != 0 ||
- slot->slot_release_lsn.l.file >= log->write_lsn.l.file);
if (slot->slot_state != WT_LOG_SLOT_WRITTEN)
continue;
written[written_i].slot_index = save_i;
diff --git a/src/conn/conn_open.c b/src/conn/conn_open.c
index f5722d343f7..9c978fed843 100644
--- a/src/conn/conn_open.c
+++ b/src/conn/conn_open.c
@@ -93,7 +93,8 @@ __wt_connection_close(WT_CONNECTION_IMPL *conn)
* transaction ID will catch up with the current ID.
*/
for (;;) {
- WT_TRET(__wt_txn_update_oldest(session, true));
+ WT_TRET(__wt_txn_update_oldest(session,
+ WT_TXN_OLDEST_STRICT | WT_TXN_OLDEST_WAIT));
if (txn_global->oldest_id == txn_global->current)
break;
__wt_yield();
diff --git a/src/cursor/cur_bulk.c b/src/cursor/cur_bulk.c
index c013383fa61..d1a53057650 100644
--- a/src/cursor/cur_bulk.c
+++ b/src/cursor/cur_bulk.c
@@ -328,7 +328,6 @@ __wt_curbulk_init(WT_SESSION_IMPL *session,
c->insert = skip_sort_check ?
__curbulk_insert_row_skip_check : __curbulk_insert_row;
break;
- WT_ILLEGAL_VALUE(session);
}
cbulk->first_insert = true;
diff --git a/src/cursor/cur_dump.c b/src/cursor/cur_dump.c
index 32353e0a28d..595915df7b7 100644
--- a/src/cursor/cur_dump.c
+++ b/src/cursor/cur_dump.c
@@ -128,7 +128,7 @@ str2recno(WT_SESSION_IMPL *session, const char *p, uint64_t *recnop)
* forth -- none of them are OK with us. Check the string starts with
* digit, that turns off the special processing.
*/
- if (!isdigit(p[0]))
+ if (!__wt_isdigit((u_char)p[0]))
goto format;
errno = 0;
diff --git a/src/cursor/cur_join.c b/src/cursor/cur_join.c
index b35558e04b3..0760a07a3aa 100644
--- a/src/cursor/cur_join.c
+++ b/src/cursor/cur_join.c
@@ -170,7 +170,7 @@ __curjoin_iter_set_entry(WT_CURSOR_JOIN_ITER *iter, u_int entry_pos)
iter->entry_count = 1;
WT_ASSERT(iter->session, iter->entry_pos < iter->entry_count);
- entry->stats.actual_count = 0;
+ entry->stats.iterated = 0;
if (entry->subjoin == NULL) {
for (topjoin = iter->cjoin; topjoin->parent != NULL;
@@ -303,8 +303,7 @@ again:
cursor, iter->cursor, iter->entry->repack_format,
iter->entry->index != NULL));
iter->curkey = &cursor->key;
- iter->entry->stats.actual_count++;
- iter->entry->stats.accesses++;
+ iter->entry->stats.iterated++;
return (0);
}
@@ -608,7 +607,7 @@ __curjoin_entry_member(WT_SESSION_IMPL *session, WT_CURSOR_JOIN_ENTRY *entry,
F_ISSET(entry, WT_CURJOIN_ENTRY_DISJUNCTION))))
return (0); /* no checks to make */
- entry->stats.accesses++;
+ entry->stats.membership_check++;
bloom_found = false;
if (entry->bloom != NULL) {
@@ -652,6 +651,7 @@ __curjoin_entry_member(WT_SESSION_IMPL *session, WT_CURSOR_JOIN_ENTRY *entry,
memset(&v, 0, sizeof(v)); /* Keep lint quiet. */
c = entry->main;
c->set_key(c, key);
+ entry->stats.main_access++;
if ((ret = c->search(c)) == 0)
ret = c->get_value(c, &v);
else if (ret == WT_NOTFOUND)
@@ -801,6 +801,7 @@ __curjoin_init_bloom(WT_SESSION_IMPL *session, WT_CURSOR_JOIN *cjoin,
collator = (entry->index == NULL) ? NULL : entry->index->collator;
while (ret == 0) {
WT_ERR(c->get_key(c, &curkey));
+ entry->stats.iterated++;
if (entry->index != NULL) {
/*
* Repack so it's comparable to the
@@ -875,7 +876,7 @@ insert:
else
WT_ERR(c->get_key(c, &curvalue));
WT_ERR(__wt_bloom_insert(bloom, &curvalue));
- entry->stats.actual_count++;
+ entry->stats.bloom_insert++;
advance:
if ((ret = c->next(c)) == WT_NOTFOUND)
break;
@@ -1107,6 +1108,7 @@ __curjoin_next(WT_CURSOR *cursor)
* A failed search is not expected, convert WT_NOTFOUND into a
* generic error.
*/
+ iter->entry->stats.main_access++;
if ((ret = c->search(c)) == WT_NOTFOUND)
ret = WT_ERROR;
WT_ERR(ret);
diff --git a/src/cursor/cur_json.c b/src/cursor/cur_json.c
index 133b7b9ac9b..f0fa0d8aec2 100644
--- a/src/cursor/cur_json.c
+++ b/src/cursor/cur_json.c
@@ -66,7 +66,7 @@ __json_unpack_put(WT_SESSION_IMPL *session, void *voidpv,
u_char *buf, size_t bufsz, WT_CONFIG_ITEM *name)
{
WT_PACK_VALUE *pv;
- const char *p, *end;
+ const u_char *p, *end;
size_t s, n;
pv = (WT_PACK_VALUE *)voidpv;
@@ -86,7 +86,7 @@ __json_unpack_put(WT_SESSION_IMPL *session, void *voidpv,
case 'S':
/* Account for '"' quote in front and back. */
s += 2;
- p = (const char *)pv->u.s;
+ p = (const u_char *)pv->u.s;
if (bufsz > 0) {
*buf++ = '"';
bufsz--;
@@ -122,7 +122,7 @@ __json_unpack_put(WT_SESSION_IMPL *session, void *voidpv,
case 'U':
case 'u':
s += 2;
- p = (const char *)pv->u.item.data;
+ p = (const u_char *)pv->u.item.data;
end = p + pv->u.item.size;
if (bufsz > 0) {
*buf++ = '"';
@@ -314,14 +314,14 @@ __wt_json_close(WT_SESSION_IMPL *session, WT_CURSOR *cursor)
* Can be called with null buf for sizing.
*/
size_t
-__wt_json_unpack_char(char ch, u_char *buf, size_t bufsz, bool force_unicode)
+__wt_json_unpack_char(u_char ch, u_char *buf, size_t bufsz, bool force_unicode)
{
- char abbrev;
+ u_char abbrev;
if (!force_unicode) {
- if (isprint(ch) && ch != '\\' && ch != '"') {
+ if (__wt_isprint(ch) && ch != '\\' && ch != '"') {
if (bufsz >= 1)
- *buf = (u_char)ch;
+ *buf = ch;
return (1);
} else {
abbrev = '\0';
@@ -346,7 +346,7 @@ __wt_json_unpack_char(char ch, u_char *buf, size_t bufsz, bool force_unicode)
if (abbrev != '\0') {
if (bufsz >= 2) {
*buf++ = '\\';
- *buf = (u_char)abbrev;
+ *buf = abbrev;
}
return (2);
}
@@ -390,7 +390,7 @@ __wt_json_column_init(WT_CURSOR *cursor, const char *keyformat,
}
for (nkeys = 0; *keyformat; keyformat++)
- if (!isdigit(*keyformat))
+ if (!__wt_isdigit((u_char)*keyformat))
nkeys++;
p = beginkey;
@@ -413,12 +413,13 @@ __wt_json_column_init(WT_CURSOR *cursor, const char *keyformat,
#define MATCH_KEYWORD(session, in, result, keyword, matchval) do { \
size_t _kwlen = strlen(keyword); \
- if (strncmp(in, keyword, _kwlen) == 0 && !isalnum(in[_kwlen])) { \
+ if (strncmp(in, keyword, _kwlen) == 0 && \
+ !__wt_isalnum((u_char)in[_kwlen])) { \
in += _kwlen; \
result = matchval; \
} else { \
const char *_bad = in; \
- while (isalnum(*in)) \
+ while (__wt_isalnum((u_char)*in)) \
in++; \
__wt_errx(session, "unknown keyword \"%.*s\" in JSON", \
(int)(in - _bad), _bad); \
@@ -460,7 +461,7 @@ __wt_json_token(WT_SESSION *wt_session, const char *src, int *toktype,
result = -1;
session = (WT_SESSION_IMPL *)wt_session;
- while (isspace(*src))
+ while (__wt_isspace((u_char)*src))
src++;
*tokstart = src;
@@ -520,13 +521,12 @@ __wt_json_token(WT_SESSION *wt_session, const char *src, int *toktype,
isfloat = false;
if (*src == '-')
src++;
- while ((ch = *src) != '\0' && isdigit(ch))
+ while ((ch = *src) != '\0' && __wt_isdigit((u_char)ch))
src++;
if (*src == '.') {
isfloat = true;
src++;
- while ((ch = *src) != '\0' &&
- isdigit(ch))
+ while ((ch = *src) != '\0' && __wt_isdigit((u_char)ch))
src++;
}
if (*src == 'e' || *src == 'E') {
@@ -534,8 +534,7 @@ __wt_json_token(WT_SESSION *wt_session, const char *src, int *toktype,
src++;
if (*src == '+' || *src == '-')
src++;
- while ((ch = *src) != '\0' &&
- isdigit(ch))
+ while ((ch = *src) != '\0' && __wt_isdigit((u_char)ch))
src++;
}
result = isfloat ? 'f' : 'i';
@@ -560,10 +559,10 @@ __wt_json_token(WT_SESSION *wt_session, const char *src, int *toktype,
default:
/* An illegal token, move past it anyway */
bad = src;
- isalph = isalnum(*src);
+ isalph = __wt_isalnum((u_char)*src);
src++;
if (isalph)
- while (*src != '\0' && isalnum(*src))
+ while (*src != '\0' && __wt_isalnum((u_char)*src))
src++;
__wt_errx(session, "unknown token \"%.*s\" in JSON",
(int)(src - bad), bad);
diff --git a/src/cursor/cur_std.c b/src/cursor/cur_std.c
index 7f220a3faa2..8bb8931f36f 100644
--- a/src/cursor/cur_std.c
+++ b/src/cursor/cur_std.c
@@ -435,7 +435,7 @@ __wt_cursor_get_valuev(WT_CURSOR *cursor, va_list ap)
} else if (WT_STREQ(fmt, "S"))
*va_arg(ap, const char **) = cursor->value.data;
else if (WT_STREQ(fmt, "t") ||
- (isdigit(fmt[0]) && WT_STREQ(fmt + 1, "t")))
+ (__wt_isdigit((u_char)fmt[0]) && WT_STREQ(fmt + 1, "t")))
*va_arg(ap, uint8_t *) = *(uint8_t *)cursor->value.data;
else
ret = __wt_struct_unpackv(session,
@@ -496,7 +496,7 @@ __wt_cursor_set_valuev(WT_CURSOR *cursor, va_list ap)
sz = strlen(str) + 1;
buf->data = str;
} else if (WT_STREQ(fmt, "t") ||
- (isdigit(fmt[0]) && WT_STREQ(fmt + 1, "t"))) {
+ (__wt_isdigit((u_char)fmt[0]) && WT_STREQ(fmt + 1, "t"))) {
sz = 1;
WT_ERR(__wt_buf_initsize(session, buf, sz));
*(uint8_t *)buf->mem = (uint8_t)va_arg(ap, int);
diff --git a/src/cursor/cur_table.c b/src/cursor/cur_table.c
index 9eb88ec6fcd..6d50523043a 100644
--- a/src/cursor/cur_table.c
+++ b/src/cursor/cur_table.c
@@ -972,7 +972,8 @@ __wt_curtable_open(WT_SESSION_IMPL *session,
if (0) {
err: if (*cursorp != NULL) {
- WT_TRET(__wt_cursor_close(*cursorp));
+ if (*cursorp != cursor)
+ WT_TRET(__wt_cursor_close(*cursorp));
*cursorp = NULL;
}
WT_TRET(__curtable_close(cursor));
diff --git a/src/docs/custom-file-systems.dox b/src/docs/custom-file-systems.dox
index cddec0e4258..d496002b0fb 100644
--- a/src/docs/custom-file-systems.dox
+++ b/src/docs/custom-file-systems.dox
@@ -17,6 +17,12 @@ allocation is attempted. See the WiredTiger POSIX file system
implementation for an example of how the fallocate method might be
changed after initialization.
+WT_FILE_SYSTEM and WT_FILE_HANDLE methods are expected to return POSIX
+1003.1 or ANSI C standard error codes on failure. Custom file systems
+on Windows systems can use the WT_EXTENSION_API::map_windows_error
+method to translate Windows system errors into POSIX system errors for
+return to WiredTiger.
+
WT_FILE_SYSTEM and WT_FILE_HANDLE methods which fail but not fatally
(for example, a WT_FILE_HANDLE::truncate method call which fails because
the file is currently mapped into memory), should return EBUSY.
@@ -25,6 +31,9 @@ WT_FILE_SYSTEM and WT_FILE_HANDLE methods which fail fatally, but not
in all cases (for example, a WT_FILE_HANDLE::fadvise method call which
only supports ::WT_FILE_HANDLE_WILLNEED), should return ENOTSUP.
+Additionally, custom file system functions may return ::WT_PANIC to
+shut down the system.
+
Unless explicitly stated otherwise, WiredTiger may invoke methods on the
WT_FILE_SYSTEM and WT_FILE_HANDLE interfaces from multiple threads
concurrently. It is the responsibility of the implementation to protect
diff --git a/src/evict/evict_file.c b/src/evict/evict_file.c
index ffd48afd1a7..b0cd50cc655 100644
--- a/src/evict/evict_file.c
+++ b/src/evict/evict_file.c
@@ -26,7 +26,8 @@ __wt_evict_file(WT_SESSION_IMPL *session, WT_CACHE_OP syncop)
WT_RET(__wt_evict_file_exclusive_on(session));
/* Make sure the oldest transaction ID is up-to-date. */
- WT_RET(__wt_txn_update_oldest(session, true));
+ WT_RET(__wt_txn_update_oldest(
+ session, WT_TXN_OLDEST_STRICT | WT_TXN_OLDEST_WAIT));
/* Walk the tree, discarding pages. */
next_ref = NULL;
@@ -88,7 +89,8 @@ __wt_evict_file(WT_SESSION_IMPL *session, WT_CACHE_OP syncop)
break;
case WT_SYNC_CHECKPOINT:
case WT_SYNC_WRITE_LEAVES:
- WT_ILLEGAL_VALUE_ERR(session);
+ WT_ERR(__wt_illegal_value(session, NULL));
+ break;
}
}
diff --git a/src/evict/evict_lru.c b/src/evict/evict_lru.c
index f5a6c33e50f..8ea487bbf83 100644
--- a/src/evict/evict_lru.c
+++ b/src/evict/evict_lru.c
@@ -9,15 +9,15 @@
#include "wt_internal.h"
static int __evict_clear_all_walks(WT_SESSION_IMPL *);
-static int __evict_clear_walks(WT_SESSION_IMPL *);
+static int __evict_helper(WT_SESSION_IMPL *);
static int WT_CDECL __evict_lru_cmp(const void *, const void *);
static int __evict_lru_pages(WT_SESSION_IMPL *, bool);
static int __evict_lru_walk(WT_SESSION_IMPL *);
static int __evict_page(WT_SESSION_IMPL *, bool);
static int __evict_pass(WT_SESSION_IMPL *);
+static int __evict_server(WT_SESSION_IMPL *, bool *);
static int __evict_walk(WT_SESSION_IMPL *, uint32_t);
static int __evict_walk_file(WT_SESSION_IMPL *, uint32_t, u_int *);
-static WT_THREAD_RET __evict_worker(void *);
/*
* __evict_read_gen --
@@ -152,6 +152,7 @@ __wt_evict_server_wake(WT_SESSION_IMPL *session)
conn = S2C(session);
cache = conn->cache;
+#ifdef HAVE_VERBOSE
if (WT_VERBOSE_ISSET(session, WT_VERB_EVICTSERVER)) {
uint64_t bytes_inuse, bytes_max;
@@ -165,107 +166,159 @@ __wt_evict_server_wake(WT_SESSION_IMPL *session)
bytes_inuse <= bytes_max ? "<=" : ">",
bytes_max / WT_MEGABYTE));
}
+#endif
return (__wt_cond_auto_signal(session, cache->evict_cond));
}
/*
- * __evict_server --
- * Thread to evict pages from the cache.
+ * __evict_thread_run --
+ * General wrapper for any eviction thread.
*/
static WT_THREAD_RET
-__evict_server(void *arg)
+__evict_thread_run(void *arg)
{
WT_CACHE *cache;
WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
WT_SESSION_IMPL *session;
-#ifdef HAVE_DIAGNOSTIC
- struct timespec now, stuck_ts;
-#endif
- uint64_t pages_evicted = 0;
- u_int spins;
+ bool did_work;
session = arg;
conn = S2C(session);
cache = conn->cache;
#ifdef HAVE_DIAGNOSTIC
- WT_ERR(__wt_epoch(session, &stuck_ts)); /* -Wuninitialized */
+ if (session == conn->evict_session)
+ WT_ERR(__wt_epoch(
+ session, &cache->stuck_ts)); /* -Wuninitialized */
#endif
while (F_ISSET(conn, WT_CONN_EVICTION_RUN)) {
- /* Evict pages from the cache as needed. */
- WT_ERR(__evict_pass(session));
-
- if (!F_ISSET(conn, WT_CONN_EVICTION_RUN))
- break;
-
- /*
- * Clear the walks so we don't pin pages while asleep,
- * otherwise we can block applications evicting large pages.
- */
- if (!F_ISSET(cache, WT_CACHE_STUCK)) {
- for (spins = 0; (ret = __wt_spin_trylock(
- session, &conn->dhandle_lock)) == EBUSY &&
- !F_ISSET(cache, WT_CACHE_CLEAR_WALKS);
- spins++) {
- if (spins < WT_THOUSAND)
- __wt_yield();
- else
- __wt_sleep(0, WT_THOUSAND);
- }
+ if (conn->evict_tid_set &&
+ __wt_spin_trylock(session, &cache->evict_pass_lock) == 0) {
/*
- * If we gave up acquiring the lock, that indicates a
- * session is waiting for us to clear walks. Do that
- * as part of a normal pass (without the handle list
- * lock) to avoid deadlock.
+ * Cannot use WT_WITH_PASS_LOCK because this is a try
+ * lock. Fix when that is supported. We set the flag
+ * on both sessions because we may call clear_walk when
+ * we are walking with the walk session, locked.
*/
- if (ret == EBUSY)
- continue;
- WT_ERR(ret);
- ret = __evict_clear_all_walks(session);
- __wt_spin_unlock(session, &conn->dhandle_lock);
+ F_SET(session, WT_SESSION_LOCKED_PASS);
+ F_SET(cache->walk_session, WT_SESSION_LOCKED_PASS);
+ ret = __evict_server(session, &did_work);
+ F_CLR(cache->walk_session, WT_SESSION_LOCKED_PASS);
+ F_CLR(session, WT_SESSION_LOCKED_PASS);
+ __wt_spin_unlock(session, &cache->evict_pass_lock);
WT_ERR(ret);
+ WT_ERR(__wt_verbose(
+ session, WT_VERB_EVICTSERVER, "sleeping"));
+ /* Don't rely on signals: check periodically. */
+ WT_ERR(__wt_cond_auto_wait(
+ session, cache->evict_cond, did_work));
+ WT_ERR(__wt_verbose(
+ session, WT_VERB_EVICTSERVER, "waking"));
+ } else
+ WT_ERR(__evict_helper(session));
+ }
- /* Next time we wake up, reverse the sweep direction. */
- cache->flags ^= WT_CACHE_WALK_REVERSE;
- pages_evicted = 0;
- } else if (pages_evicted != cache->pages_evict) {
- pages_evicted = cache->pages_evict;
+ if (session == conn->evict_session) {
+ /*
+ * The eviction server is shutting down: in case any trees are
+ * still open, clear all walks now so that they can be closed.
+ */
+ WT_WITH_PASS_LOCK(session, ret,
+ ret = __evict_clear_all_walks(session));
+ WT_ERR(ret);
+ }
+ WT_ERR(__wt_verbose(
+ session, WT_VERB_EVICTSERVER, "cache eviction thread exiting"));
+
+ /*
+ * The only two cases when eviction workers are expected to stop are
+ * when recovery is finished or when the connection is closing. Check
+ * otherwise fewer eviction worker threads may be running than
+ * expected.
+ */
+ WT_ASSERT(session, F_ISSET(conn, WT_CONN_CLOSING | WT_CONN_RECOVERING));
+ if (0) {
+err: WT_PANIC_MSG(session, ret, "cache eviction thread error");
+ }
+ return (WT_THREAD_RET_VALUE);
+}
+
+/*
+ * __evict_server --
+ * Thread to evict pages from the cache.
+ */
+static int
+__evict_server(WT_SESSION_IMPL *session, bool *did_work)
+{
+ WT_CACHE *cache;
+ WT_CONNECTION_IMPL *conn;
+ WT_DECL_RET;
#ifdef HAVE_DIAGNOSTIC
- WT_ERR(__wt_epoch(session, &stuck_ts));
- } else {
- /* After being stuck for 5 minutes, give up. */
- WT_ERR(__wt_epoch(session, &now));
- if (WT_TIMEDIFF_SEC(now, stuck_ts) > 300) {
- __wt_err(session, ETIMEDOUT,
- "Cache stuck for too long, giving up");
- (void)__wt_cache_dump(session, NULL);
- WT_ERR(ETIMEDOUT);
- }
+ struct timespec now;
#endif
- }
+ uint64_t orig_pages_evicted;
+ u_int spins;
- WT_ERR(__wt_verbose(session, WT_VERB_EVICTSERVER, "sleeping"));
- /* Don't rely on signals: check periodically. */
- WT_ERR(__wt_cond_auto_wait(
- session, cache->evict_cond, pages_evicted != 0));
- WT_ERR(__wt_verbose(session, WT_VERB_EVICTSERVER, "waking"));
- }
+ conn = S2C(session);
+ cache = conn->cache;
+ WT_ASSERT(session, did_work != NULL);
+ *did_work = false;
+ orig_pages_evicted = cache->pages_evicted;
+
+ /* Evict pages from the cache as needed. */
+ WT_RET(__evict_pass(session));
+
+ if (!F_ISSET(conn, WT_CONN_EVICTION_RUN))
+ return (0);
/*
- * The eviction server is shutting down: in case any trees are still
- * open, clear all walks now so that they can be closed.
+ * Clear the walks so we don't pin pages while asleep,
+ * otherwise we can block applications evicting large pages.
*/
- WT_ERR(__evict_clear_all_walks(session));
-
- WT_ERR(__wt_verbose(
- session, WT_VERB_EVICTSERVER, "cache eviction server exiting"));
+ if (!F_ISSET(cache, WT_CACHE_STUCK)) {
+ for (spins = 0; (ret = __wt_spin_trylock(
+ session, &conn->dhandle_lock)) == EBUSY &&
+ cache->pass_intr == 0; spins++) {
+ if (spins < WT_THOUSAND)
+ __wt_yield();
+ else
+ __wt_sleep(0, WT_THOUSAND);
+ }
+ /*
+ * If we gave up acquiring the lock, that indicates a
+ * session is waiting for us to clear walks. Do that
+ * as part of a normal pass (without the handle list
+ * lock) to avoid deadlock.
+ */
+ if (ret == EBUSY)
+ return (0);
+ WT_RET(ret);
+ ret = __evict_clear_all_walks(session);
+ __wt_spin_unlock(session, &conn->dhandle_lock);
+ WT_RET(ret);
- if (0) {
-err: WT_PANIC_MSG(session, ret, "cache eviction server error");
+ /* Next time we wake up, reverse the sweep direction. */
+ cache->flags ^= WT_CACHE_WALK_REVERSE;
+ cache->pages_evicted = 0;
+ } else if (cache->pages_evicted != cache->pages_evict) {
+ cache->pages_evicted = cache->pages_evict;
+#ifdef HAVE_DIAGNOSTIC
+ WT_RET(__wt_epoch(session, &cache->stuck_ts));
+ } else {
+ /* After being stuck for 5 minutes, give up. */
+ WT_RET(__wt_epoch(session, &now));
+ if (WT_TIMEDIFF_SEC(now, cache->stuck_ts) > 300) {
+ __wt_err(session, ETIMEDOUT,
+ "Cache stuck for too long, giving up");
+ (void)__wt_cache_dump(session, NULL);
+ WT_RET(ETIMEDOUT);
+ }
+#endif
}
- return (WT_THREAD_RET_VALUE);
+ *did_work = cache->pages_evicted != orig_pages_evicted;
+ return (0);
}
/*
@@ -284,6 +337,7 @@ __evict_workers_resize(WT_SESSION_IMPL *session)
uint32_t i, session_flags;
conn = S2C(session);
+ workers = NULL; /* -Wconditional-uninitialized */
if (conn->evict_workers_alloc < conn->evict_workers_max) {
alloc = conn->evict_workers_alloc * sizeof(*workers);
@@ -315,7 +369,8 @@ __evict_workers_resize(WT_SESSION_IMPL *session)
++conn->evict_workers;
F_SET(&workers[i], WT_EVICT_WORKER_RUN);
WT_ERR(__wt_thread_create(workers[i].session,
- &workers[i].tid, __evict_worker, &workers[i]));
+ &workers[i].tid, __evict_thread_run,
+ workers[i].session));
}
}
@@ -369,7 +424,7 @@ __wt_evict_create(WT_SESSION_IMPL *session)
* the worker's sessions are created.
*/
WT_RET(__wt_thread_create(
- session, &conn->evict_tid, __evict_server, session));
+ session, &conn->evict_tid, __evict_thread_run, session));
conn->evict_tid_set = true;
return (0);
@@ -439,39 +494,22 @@ __wt_evict_destroy(WT_SESSION_IMPL *session)
}
/*
- * __evict_worker --
+ * __evict_helper --
* Thread to help evict pages from the cache.
*/
-static WT_THREAD_RET
-__evict_worker(void *arg)
+static int
+__evict_helper(WT_SESSION_IMPL *session)
{
WT_CACHE *cache;
- WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
- WT_EVICT_WORKER *worker;
- WT_SESSION_IMPL *session;
- worker = arg;
- session = worker->session;
- conn = S2C(session);
- cache = conn->cache;
-
- while (F_ISSET(conn, WT_CONN_EVICTION_RUN) &&
- F_ISSET(worker, WT_EVICT_WORKER_RUN)) {
- /* Don't spin in a busy loop if there is no work to do */
- if ((ret = __evict_lru_pages(session, false)) == WT_NOTFOUND)
- WT_ERR(__wt_cond_wait(
- session, cache->evict_waiter_cond, 10000));
- else
- WT_ERR(ret);
- }
- WT_ERR(__wt_verbose(
- session, WT_VERB_EVICTSERVER, "cache eviction worker exiting"));
-
- if (0) {
-err: WT_PANIC_MSG(session, ret, "cache eviction worker error");
- }
- return (WT_THREAD_RET_VALUE);
+ cache = S2C(session)->cache;
+ if ((ret = __evict_lru_pages(session, false)) == WT_NOTFOUND)
+ WT_RET(__wt_cond_wait(
+ session, cache->evict_waiter_cond, 10000));
+ else
+ WT_RET(ret);
+ return (0);
}
/*
@@ -579,12 +617,8 @@ __evict_pass(WT_SESSION_IMPL *session)
* If there is a request to clear eviction walks, do that now,
* before checking if the cache is full.
*/
- if (F_ISSET(cache, WT_CACHE_CLEAR_WALKS)) {
- F_CLR(cache, WT_CACHE_CLEAR_WALKS);
- WT_RET(__evict_clear_walks(session));
- WT_RET(__wt_cond_signal(
- session, cache->evict_waiter_cond));
- }
+ if (cache->pass_intr != 0)
+ break;
/*
* Increment the shared read generation. Do this occasionally
@@ -602,9 +636,10 @@ __evict_pass(WT_SESSION_IMPL *session)
*
* Do this every time the eviction server wakes up, regardless
* of whether the cache is full, to prevent the oldest ID
- * falling too far behind.
+ * falling too far behind. Don't wait to lock the table: with
+ * highly threaded workloads, that creates a bottleneck.
*/
- WT_RET(__wt_txn_update_oldest(session, loop > 0));
+ WT_RET(__wt_txn_update_oldest(session, WT_TXN_OLDEST_STRICT));
if (!__evict_update_work(session))
break;
@@ -630,7 +665,7 @@ __evict_pass(WT_SESSION_IMPL *session)
worker = &conn->evict_workctx[conn->evict_workers++];
F_SET(worker, WT_EVICT_WORKER_RUN);
WT_RET(__wt_thread_create(session,
- &worker->tid, __evict_worker, worker));
+ &worker->tid, __evict_thread_run, worker->session));
}
WT_RET(__wt_verbose(session, WT_VERB_EVICTSERVER,
@@ -648,7 +683,7 @@ __evict_pass(WT_SESSION_IMPL *session)
*/
if (pages_evicted == cache->pages_evict) {
WT_STAT_FAST_CONN_INCR(session,
- cache_eviction_server_slept);
+ cache_eviction_server_slept);
/*
* Back off if we aren't making progress: walks hold
* the handle list lock, which blocks other operations
@@ -689,11 +724,13 @@ __evict_clear_walk(WT_SESSION_IMPL *session)
{
WT_BTREE *btree;
WT_CACHE *cache;
+ WT_DECL_RET;
WT_REF *ref;
btree = S2BT(session);
cache = S2C(session)->cache;
+ WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_PASS));
if (session->dhandle == cache->evict_file_next)
cache->evict_file_next = NULL;
@@ -705,30 +742,9 @@ __evict_clear_walk(WT_SESSION_IMPL *session)
* assert we never try to evict the current eviction walk point).
*/
btree->evict_ref = NULL;
- return (__wt_page_release(session, ref, WT_READ_NO_EVICT));
-}
-
-/*
- * __evict_clear_walks --
- * Clear the eviction walk points for any file a session is waiting on.
- */
-static int
-__evict_clear_walks(WT_SESSION_IMPL *session)
-{
- WT_CONNECTION_IMPL *conn;
- WT_DECL_RET;
- WT_SESSION_IMPL *s;
- u_int i, session_cnt;
-
- conn = S2C(session);
-
- WT_ORDERED_READ(session_cnt, conn->session_cnt);
- for (s = conn->sessions, i = 0; i < session_cnt; ++s, ++i) {
- if (!s->active || !F_ISSET(s, WT_SESSION_CLEAR_EVICT_WALK))
- continue;
- WT_WITH_DHANDLE(
- session, s->dhandle, WT_TRET(__evict_clear_walk(session)));
- }
+ WT_WITH_DHANDLE(cache->walk_session, session->dhandle,
+ (ret = __wt_page_release(cache->walk_session,
+ ref, WT_READ_NO_EVICT)));
return (ret);
}
@@ -753,39 +769,6 @@ __evict_clear_all_walks(WT_SESSION_IMPL *session)
}
/*
- * __evict_request_clear_walk --
- * Request that the eviction server clear the tree's current eviction
- * point.
- */
-static int
-__evict_request_clear_walk(WT_SESSION_IMPL *session)
-{
- WT_BTREE *btree;
- WT_CACHE *cache;
- WT_DECL_RET;
-
- btree = S2BT(session);
- cache = S2C(session)->cache;
-
- F_SET(session, WT_SESSION_CLEAR_EVICT_WALK);
-
- while (ret == 0 && (btree->evict_ref != NULL ||
- cache->evict_file_next == session->dhandle)) {
- F_SET(cache, WT_CACHE_CLEAR_WALKS);
- ret = __wt_cond_wait(
- session, cache->evict_waiter_cond, 100000);
- }
-
- F_CLR(session, WT_SESSION_CLEAR_EVICT_WALK);
-
- /* An error is unexpected - flag the failure. */
- if (ret != 0)
- __wt_err(session, ret, "Failed to clear eviction walk point");
-
- return (ret);
-}
-
-/*
* __wt_evict_file_exclusive_on --
* Get exclusive eviction access to a file and discard any of the file's
* blocks queued for eviction.
@@ -822,10 +805,14 @@ __wt_evict_file_exclusive_on(WT_SESSION_IMPL *session)
* this point.
*/
F_SET(btree, WT_BTREE_NO_EVICTION);
+ (void)__wt_atomic_add32(&cache->pass_intr, 1);
WT_FULL_BARRIER();
/* Clear any existing LRU eviction walk for the file. */
- WT_ERR(__evict_request_clear_walk(session));
+ WT_WITH_PASS_LOCK(session, ret,
+ ret = __evict_clear_walk(session));
+ (void)__wt_atomic_sub32(&cache->pass_intr, 1);
+ WT_ERR(ret);
/*
* The eviction candidate list might reference pages from the file,
@@ -949,7 +936,7 @@ __evict_lru_walk(WT_SESSION_IMPL *session)
queue_index = cache->evict_queue_fill++ % WT_EVICT_QUEUE_MAX;
evict_queue = &cache->evict_queues[queue_index];
/* Get some more pages to consider for eviction. */
- if ((ret = __evict_walk(session, queue_index)) != 0)
+ if ((ret = __evict_walk(cache->walk_session, queue_index)) != 0)
return (ret == EBUSY ? 0 : ret);
/* Sort the list into LRU order and restart. */
@@ -1063,8 +1050,8 @@ __evict_lru_walk(WT_SESSION_IMPL *session)
__wt_spin_unlock(session, &cache->evict_queue_lock);
/*
- * The eviction server thread doesn't do any actual eviction if there
- * are multiple eviction workers running.
+ * Signal any application or helper threads that may be waiting
+ * to help with eviction.
*/
WT_RET(__wt_cond_signal(session, cache->evict_waiter_cond));
@@ -1108,7 +1095,7 @@ retry: while (slot < max_entries && ret == 0) {
* If another thread is waiting on the eviction server to clear
* the walk point in a tree, give up.
*/
- if (F_ISSET(cache, WT_CACHE_CLEAR_WALKS))
+ if (cache->pass_intr != 0)
break;
/*
@@ -1118,7 +1105,7 @@ retry: while (slot < max_entries && ret == 0) {
if (!dhandle_locked) {
for (spins = 0; (ret = __wt_spin_trylock(
session, &conn->dhandle_lock)) == EBUSY &&
- !F_ISSET(cache, WT_CACHE_CLEAR_WALKS);
+ cache->pass_intr == 0;
spins++) {
if (spins < WT_THOUSAND)
__wt_yield();
@@ -1244,7 +1231,7 @@ retry: while (slot < max_entries && ret == 0) {
* Try two passes through all the files, give up when we have some
* candidates and we aren't finding more.
*/
- if (!F_ISSET(cache, WT_CACHE_CLEAR_WALKS) && ret == 0 &&
+ if (cache->pass_intr == 0 && ret == 0 &&
slot < max_entries && (retries < 2 ||
(retries < 10 &&
!FLD_ISSET(cache->state, WT_EVICT_PASS_WOULD_BLOCK) &&
@@ -1298,7 +1285,7 @@ __evict_walk_file(WT_SESSION_IMPL *session, uint32_t queue_index, u_int *slotp)
WT_PAGE *page;
WT_PAGE_MODIFY *mod;
WT_REF *ref;
- uint64_t pages_walked;
+ uint64_t pages_seen, refs_walked;
uint32_t walk_flags;
int internal_pages, restarts;
bool enough, modified;
@@ -1333,17 +1320,21 @@ __evict_walk_file(WT_SESSION_IMPL *session, uint32_t queue_index, u_int *slotp)
* Once we hit the page limit, do one more step through the walk in
* case we are appending and only the last page in the file is live.
*/
- for (evict = start, pages_walked = 0;
+ for (evict = start, pages_seen = refs_walked = 0;
evict < end && !enough && (ret == 0 || ret == WT_NOTFOUND);
ret = __wt_tree_walk_count(
- session, &btree->evict_ref, &pages_walked, walk_flags)) {
- enough = pages_walked > cache->evict_max_refs_per_file;
+ session, &btree->evict_ref, &refs_walked, walk_flags)) {
+ enough = refs_walked > cache->evict_max_refs_per_file;
if ((ref = btree->evict_ref) == NULL) {
if (++restarts == 2 || enough)
break;
+ WT_STAT_FAST_CONN_INCR(
+ session, cache_eviction_walks_started);
continue;
}
+ ++pages_seen;
+
/* Ignore root pages entirely. */
if (__wt_ref_is_root(ref))
continue;
@@ -1371,9 +1362,13 @@ __evict_walk_file(WT_SESSION_IMPL *session, uint32_t queue_index, u_int *slotp)
}
/* Pages we no longer need (clean or dirty), are found money. */
+ if (page->read_gen == WT_READGEN_OLDEST) {
+ WT_STAT_FAST_CONN_INCR(
+ session, cache_eviction_pages_queued_oldest);
+ goto fast;
+ }
if (__wt_page_is_empty(page) ||
- F_ISSET(session->dhandle, WT_DHANDLE_DEAD) ||
- page->read_gen == WT_READGEN_OLDEST)
+ F_ISSET(session->dhandle, WT_DHANDLE_DEAD))
goto fast;
/* Skip clean pages if appropriate. */
@@ -1439,24 +1434,31 @@ fast: /* If the page can't be evicted, give up. */
WT_RET_NOTFOUND_OK(ret);
*slotp += (u_int)(evict - start);
+ WT_STAT_FAST_CONN_INCRV(
+ session, cache_eviction_pages_queued, (u_int)(evict - start));
/*
* If we happen to end up on the root page, clear it. We have to track
* hazard pointers, and the root page complicates that calculation.
*
+ * Likewise if we found no new candidates during the walk: there is no
+ * point keeping a page pinned, since it may be the only candidate in an
+ * idle tree.
+ *
* If we land on a page requiring forced eviction, move on to the next
* page: we want this page evicted as quickly as possible.
*/
if ((ref = btree->evict_ref) != NULL) {
- if (__wt_ref_is_root(ref))
+ if (__wt_ref_is_root(ref) || evict == start)
WT_RET(__evict_clear_walk(session));
else if (ref->page->read_gen == WT_READGEN_OLDEST)
WT_RET_NOTFOUND_OK(__wt_tree_walk_count(
session, &btree->evict_ref,
- &pages_walked, walk_flags));
+ &refs_walked, walk_flags));
}
- WT_STAT_FAST_CONN_INCRV(session, cache_eviction_walk, pages_walked);
+ WT_STAT_FAST_CONN_INCRV(session, cache_eviction_walk, refs_walked);
+ WT_STAT_FAST_CONN_INCRV(session, cache_eviction_pages_seen, pages_seen);
return (0);
}
@@ -1541,6 +1543,10 @@ __evict_get_ref(
for (;;) {
if (__wt_spin_trylock(session, &evict_queue->evict_lock) == 0)
break;
+ if (!F_ISSET(session, WT_SESSION_INTERNAL)) {
+ __wt_spin_unlock(session, &cache->evict_queue_lock);
+ return (WT_NOTFOUND);
+ }
__wt_yield();
}
/*
@@ -1638,6 +1644,9 @@ __evict_page(WT_SESSION_IMPL *session, bool is_server)
cache->worker_evicts++;
}
} else {
+ if (__wt_page_is_modified(ref->page))
+ WT_STAT_FAST_CONN_INCR(
+ session, cache_eviction_app_dirty);
WT_STAT_FAST_CONN_INCR(session, cache_eviction_app);
cache->app_evicts++;
}
@@ -1727,8 +1736,9 @@ __wt_cache_eviction_worker(WT_SESSION_IMPL *session, bool busy, u_int pct_full)
}
/* See if eviction is still needed. */
- if (!__wt_eviction_needed(session, NULL) ||
- cache->pages_evict > init_evict_count + max_pages_evicted)
+ if (!__wt_eviction_needed(session, &pct_full) ||
+ (pct_full < 100 &&
+ cache->pages_evict > init_evict_count + max_pages_evicted))
return (0);
/* Evict a page. */
diff --git a/src/evict/evict_page.c b/src/evict/evict_page.c
index 2d20f53e9ae..305b81fe69e 100644
--- a/src/evict/evict_page.c
+++ b/src/evict/evict_page.c
@@ -420,7 +420,8 @@ __evict_review(
* fallen behind current.
*/
if (modified)
- WT_RET(__wt_txn_update_oldest(session, false));
+ WT_RET(__wt_txn_update_oldest(
+ session, WT_TXN_OLDEST_STRICT));
if (!__wt_page_can_evict(session, ref, inmem_splitp))
return (EBUSY);
diff --git a/src/include/block.h b/src/include/block.h
index 9f652ceddb9..a8080c1651c 100644
--- a/src/include/block.h
+++ b/src/include/block.h
@@ -261,6 +261,7 @@ struct __wt_block {
/* Verification support */
bool verify; /* If performing verification */
+ bool verify_layout; /* Print out file layout information */
bool verify_strict; /* Fail hard on any error */
wt_off_t verify_size; /* Checkpoint's file size */
WT_EXTLIST verify_alloc; /* Verification allocation list */
diff --git a/src/include/btree_cmp.i b/src/include/btree_cmp.i
index 1993c1be293..23a462e4e50 100644
--- a/src/include/btree_cmp.i
+++ b/src/include/btree_cmp.i
@@ -52,8 +52,8 @@ __wt_lex_compare(const WT_ITEM *user_item, const WT_ITEM *tree_item)
for (; len > 0;
len -= WT_VECTOR_SIZE,
userp += WT_VECTOR_SIZE, treep += WT_VECTOR_SIZE) {
- u = _mm_load_si128((__m128i *)userp);
- t = _mm_load_si128((__m128i *)treep);
+ u = _mm_load_si128((const __m128i *)userp);
+ t = _mm_load_si128((const __m128i *)treep);
res_eq = _mm_cmpeq_epi8(u, t);
if (_mm_movemask_epi8(res_eq) != 65535)
break;
@@ -62,8 +62,8 @@ __wt_lex_compare(const WT_ITEM *user_item, const WT_ITEM *tree_item)
for (; len > 0;
len -= WT_VECTOR_SIZE,
userp += WT_VECTOR_SIZE, treep += WT_VECTOR_SIZE) {
- u = _mm_loadu_si128((__m128i *)userp);
- t = _mm_loadu_si128((__m128i *)treep);
+ u = _mm_loadu_si128((const __m128i *)userp);
+ t = _mm_loadu_si128((const __m128i *)treep);
res_eq = _mm_cmpeq_epi8(u, t);
if (_mm_movemask_epi8(res_eq) != 65535)
break;
@@ -123,8 +123,8 @@ __wt_lex_compare_skip(
tsz = tree_item->size;
len = WT_MIN(usz, tsz) - *matchp;
- userp = (uint8_t *)user_item->data + *matchp;
- treep = (uint8_t *)tree_item->data + *matchp;
+ userp = (const uint8_t *)user_item->data + *matchp;
+ treep = (const uint8_t *)tree_item->data + *matchp;
#ifdef HAVE_X86INTRIN_H
/* Use vector instructions if we'll execute at least 2 of them. */
@@ -139,8 +139,8 @@ __wt_lex_compare_skip(
len -= WT_VECTOR_SIZE,
userp += WT_VECTOR_SIZE, treep += WT_VECTOR_SIZE,
*matchp += WT_VECTOR_SIZE) {
- u = _mm_load_si128((__m128i *)userp);
- t = _mm_load_si128((__m128i *)treep);
+ u = _mm_load_si128((const __m128i *)userp);
+ t = _mm_load_si128((const __m128i *)treep);
res_eq = _mm_cmpeq_epi8(u, t);
if (_mm_movemask_epi8(res_eq) != 65535)
break;
@@ -150,8 +150,8 @@ __wt_lex_compare_skip(
len -= WT_VECTOR_SIZE,
userp += WT_VECTOR_SIZE, treep += WT_VECTOR_SIZE,
*matchp += WT_VECTOR_SIZE) {
- u = _mm_loadu_si128((__m128i *)userp);
- t = _mm_loadu_si128((__m128i *)treep);
+ u = _mm_loadu_si128((const __m128i *)userp);
+ t = _mm_loadu_si128((const __m128i *)treep);
res_eq = _mm_cmpeq_epi8(u, t);
if (_mm_movemask_epi8(res_eq) != 65535)
break;
diff --git a/src/include/cache.h b/src/include/cache.h
index 4f7981a5df9..f4a35de7201 100644
--- a/src/include/cache.h
+++ b/src/include/cache.h
@@ -76,6 +76,7 @@ struct __wt_cache {
uint64_t bytes_overflow; /* Bytes of overflow pages */
uint64_t bytes_evict; /* Bytes/pages discarded by eviction */
uint64_t pages_evict;
+ uint64_t pages_evicted; /* Pages evicted during a pass */
uint64_t bytes_dirty; /* Bytes/pages currently dirty */
uint64_t pages_dirty;
uint64_t bytes_read; /* Bytes read into memory */
@@ -86,6 +87,9 @@ struct __wt_cache {
uint64_t worker_evicts; /* Pages evicted by worker threads */
uint64_t evict_max_page_size; /* Largest page seen at eviction */
+#ifdef HAVE_DIAGNOSTIC
+ struct timespec stuck_ts; /* Stuck timestamp */
+#endif
/*
* Read information.
@@ -112,6 +116,8 @@ struct __wt_cache {
/*
* LRU eviction list information.
*/
+ WT_SPINLOCK evict_pass_lock; /* Eviction pass lock */
+ WT_SESSION_IMPL *walk_session; /* Eviction pass session */
WT_SPINLOCK evict_queue_lock; /* Eviction current queue lock */
WT_EVICT_QUEUE evict_queues[WT_EVICT_QUEUE_MAX];
WT_EVICT_QUEUE *evict_current_queue;/* LRU current queue in use */
@@ -144,19 +150,28 @@ struct __wt_cache {
#define WT_EVICT_PASS_DIRTY 0x04
#define WT_EVICT_PASS_WOULD_BLOCK 0x08
uint32_t state;
+ /*
+ * Pass interrupt counter.
+ */
+ uint32_t pass_intr; /* Interrupt eviction pass. */
/*
* Flags.
*/
#define WT_CACHE_POOL_MANAGER 0x01 /* The active cache pool manager */
#define WT_CACHE_POOL_RUN 0x02 /* Cache pool thread running */
-#define WT_CACHE_CLEAR_WALKS 0x04 /* Clear eviction walks */
-#define WT_CACHE_STUCK 0x08 /* Eviction server is stuck */
-#define WT_CACHE_WALK_REVERSE 0x10 /* Scan backwards for candidates */
-#define WT_CACHE_WOULD_BLOCK 0x20 /* Pages that would block apps */
+#define WT_CACHE_STUCK 0x04 /* Eviction server is stuck */
+#define WT_CACHE_WALK_REVERSE 0x08 /* Scan backwards for candidates */
+#define WT_CACHE_WOULD_BLOCK 0x10 /* Pages that would block apps */
uint32_t flags;
};
+#define WT_WITH_PASS_LOCK(session, ret, op) do { \
+ WT_ASSERT(session, !F_ISSET(session, WT_SESSION_LOCKED_PASS)); \
+ WT_WITH_LOCK(session, ret, \
+ &cache->evict_pass_lock, WT_SESSION_LOCKED_PASS, op); \
+} while (0)
+
/*
* WT_CACHE_POOL --
* A structure that represents a shared cache.
diff --git a/src/include/cell.i b/src/include/cell.i
index 481d2a29764..c130768e595 100644
--- a/src/include/cell.i
+++ b/src/include/cell.i
@@ -183,9 +183,9 @@ __wt_cell_pack_addr(WT_CELL *cell, u_int cell_type, uint64_t recno, size_t size)
p = cell->__chunk + 1;
if (recno == WT_RECNO_OOB)
- cell->__chunk[0] = cell_type; /* Type */
+ cell->__chunk[0] = (uint8_t)cell_type; /* Type */
else {
- cell->__chunk[0] = cell_type | WT_CELL_64V;
+ cell->__chunk[0] = (uint8_t)(cell_type | WT_CELL_64V);
(void)__wt_vpack_uint(&p, 0, recno); /* Record number */
}
(void)__wt_vpack_uint(&p, 0, (uint64_t)size); /* Length */
@@ -207,8 +207,8 @@ __wt_cell_pack_data(WT_CELL *cell, uint64_t rle, size_t size)
*/
if (rle < 2 && size <= WT_CELL_SHORT_MAX) {
byte = (uint8_t)size; /* Type + length */
- cell->__chunk[0] =
- (byte << WT_CELL_SHORT_SHIFT) | WT_CELL_VALUE_SHORT;
+ cell->__chunk[0] = (uint8_t)
+ ((byte << WT_CELL_SHORT_SHIFT) | WT_CELL_VALUE_SHORT);
return (1);
}
@@ -331,8 +331,8 @@ __wt_cell_pack_int_key(WT_CELL *cell, size_t size)
/* Short keys have 6 bits of data length in the descriptor byte. */
if (size <= WT_CELL_SHORT_MAX) {
byte = (uint8_t)size;
- cell->__chunk[0] =
- (byte << WT_CELL_SHORT_SHIFT) | WT_CELL_KEY_SHORT;
+ cell->__chunk[0] = (uint8_t)
+ ((byte << WT_CELL_SHORT_SHIFT) | WT_CELL_KEY_SHORT);
return (1);
}
@@ -358,14 +358,14 @@ __wt_cell_pack_leaf_key(WT_CELL *cell, uint8_t prefix, size_t size)
if (size <= WT_CELL_SHORT_MAX) {
if (prefix == 0) {
byte = (uint8_t)size; /* Type + length */
- cell->__chunk[0] =
- (byte << WT_CELL_SHORT_SHIFT) | WT_CELL_KEY_SHORT;
+ cell->__chunk[0] = (uint8_t)
+ ((byte << WT_CELL_SHORT_SHIFT) | WT_CELL_KEY_SHORT);
return (1);
} else {
byte = (uint8_t)size; /* Type + length */
- cell->__chunk[0] =
- (byte << WT_CELL_SHORT_SHIFT) |
- WT_CELL_KEY_SHORT_PFX;
+ cell->__chunk[0] = (uint8_t)
+ ((byte << WT_CELL_SHORT_SHIFT) |
+ WT_CELL_KEY_SHORT_PFX);
cell->__chunk[1] = prefix; /* Prefix */
return (2);
}
@@ -585,8 +585,8 @@ restart:
WT_CELL_LEN_CHK(cell, 0);
unpack->cell = cell;
unpack->v = 0;
- unpack->raw = __wt_cell_type_raw(cell);
- unpack->type = __wt_cell_type(cell);
+ unpack->raw = (uint8_t)__wt_cell_type_raw(cell);
+ unpack->type = (uint8_t)__wt_cell_type(cell);
unpack->ovfl = 0;
/*
diff --git a/src/include/ctype.i b/src/include/ctype.i
new file mode 100644
index 00000000000..b4a1ad9f318
--- /dev/null
+++ b/src/include/ctype.i
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 2014-2016 MongoDB, Inc.
+ * Copyright (c) 2008-2014 WiredTiger, Inc.
+ * All rights reserved.
+ *
+ * See the file LICENSE for redistribution information.
+ */
+
+#include <ctype.h>
+
+/*
+ * __wt_isalnum --
+ * Wrap the ctype function without sign extension.
+ */
+static inline bool
+__wt_isalnum(u_char c)
+{
+ return (isalnum(c) != 0);
+}
+
+/*
+ * __wt_isalpha --
+ * Wrap the ctype function without sign extension.
+ */
+static inline bool
+__wt_isalpha(u_char c)
+{
+ return (isalpha(c) != 0);
+}
+
+/*
+ * __wt_isdigit --
+ * Wrap the ctype function without sign extension.
+ */
+static inline bool
+__wt_isdigit(u_char c)
+{
+ return (isdigit(c) != 0);
+}
+
+/*
+ * __wt_isprint --
+ * Wrap the ctype function without sign extension.
+ */
+static inline bool
+__wt_isprint(u_char c)
+{
+ return (isprint(c) != 0);
+}
+
+/*
+ * __wt_isspace --
+ * Wrap the ctype function without sign extension.
+ */
+static inline bool
+__wt_isspace(u_char c)
+{
+ return (isspace(c) != 0);
+}
+
+/*
+ * __wt_tolower --
+ * Wrap the ctype function without sign extension.
+ */
+static inline u_char
+__wt_tolower(u_char c)
+{
+ return ((u_char)tolower(c));
+}
diff --git a/src/include/extern.h b/src/include/extern.h
index 4ca5c8461a0..b0c0f6eccad 100644
--- a/src/include/extern.h
+++ b/src/include/extern.h
@@ -144,7 +144,6 @@ extern const char *__wt_page_type_string(u_int type);
extern const char *__wt_cell_type_string(uint8_t type);
extern const char *__wt_page_addr_string(WT_SESSION_IMPL *session, WT_REF *ref, WT_ITEM *buf);
extern const char *__wt_addr_string(WT_SESSION_IMPL *session, const uint8_t *addr, size_t addr_size, WT_ITEM *buf);
-extern const char *__wt_buf_set_printable( WT_SESSION_IMPL *session, const void *p, size_t size, WT_ITEM *buf);
extern int __wt_ovfl_read(WT_SESSION_IMPL *session, WT_PAGE *page, WT_CELL_UNPACK *unpack, WT_ITEM *store);
extern int __wt_ovfl_cache(WT_SESSION_IMPL *session, WT_PAGE *page, void *cookie, WT_CELL_UNPACK *vpack);
extern int __wt_ovfl_discard(WT_SESSION_IMPL *session, WT_CELL *cell);
@@ -291,7 +290,7 @@ extern int __wt_curjoin_open(WT_SESSION_IMPL *session, const char *uri, WT_CURSO
extern int __wt_curjoin_join(WT_SESSION_IMPL *session, WT_CURSOR_JOIN *cjoin, WT_INDEX *idx, WT_CURSOR *ref_cursor, uint8_t flags, uint8_t range, uint64_t count, uint32_t bloom_bit_count, uint32_t bloom_hash_count);
extern int __wt_json_alloc_unpack(WT_SESSION_IMPL *session, const void *buffer, size_t size, const char *fmt, WT_CURSOR_JSON *json, bool iskey, va_list ap);
extern void __wt_json_close(WT_SESSION_IMPL *session, WT_CURSOR *cursor);
-extern size_t __wt_json_unpack_char(char ch, u_char *buf, size_t bufsz, bool force_unicode);
+extern size_t __wt_json_unpack_char(u_char ch, u_char *buf, size_t bufsz, bool force_unicode);
extern int __wt_json_column_init(WT_CURSOR *cursor, const char *keyformat, const WT_CONFIG_ITEM *idxconf, const WT_CONFIG_ITEM *colconf);
extern int __wt_json_token(WT_SESSION *wt_session, const char *src, int *toktype, const char **tokstart, size_t *toklen);
extern const char *__wt_json_tokname(int toktype);
@@ -484,6 +483,31 @@ extern int __wt_meta_track_destroy(WT_SESSION_IMPL *session);
extern int __wt_turtle_init(WT_SESSION_IMPL *session);
extern int __wt_turtle_read(WT_SESSION_IMPL *session, const char *key, char **valuep);
extern int __wt_turtle_update(WT_SESSION_IMPL *session, const char *key, const char *value);
+extern int __wt_filename(WT_SESSION_IMPL *session, const char *name, char **path);
+extern int __wt_nfilename( WT_SESSION_IMPL *session, const char *name, size_t namelen, char **path);
+extern int __wt_remove_if_exists(WT_SESSION_IMPL *session, const char *name);
+extern int __wt_rename_and_sync_directory( WT_SESSION_IMPL *session, const char *from, const char *to);
+extern int __wt_copy_and_sync(WT_SESSION *wt_session, const char *from, const char *to);
+extern void __wt_abort(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((noreturn));
+extern int __wt_calloc(WT_SESSION_IMPL *session, size_t number, size_t size, void *retp);
+extern int __wt_malloc(WT_SESSION_IMPL *session, size_t bytes_to_allocate, void *retp);
+extern int __wt_realloc(WT_SESSION_IMPL *session, size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp);
+extern int __wt_realloc_noclear(WT_SESSION_IMPL *session, size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp);
+extern int __wt_realloc_aligned(WT_SESSION_IMPL *session, size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp);
+extern int __wt_strndup(WT_SESSION_IMPL *session, const void *str, size_t len, void *retp);
+extern void __wt_free_int(WT_SESSION_IMPL *session, const void *p_arg);
+extern int __wt_errno(void);
+extern const char *__wt_strerror(WT_SESSION_IMPL *session, int error, char *errbuf, size_t errlen);
+extern int __wt_ext_map_windows_error( WT_EXTENSION_API *wt_api, WT_SESSION *wt_session, uint32_t windows_error);
+extern bool __wt_handle_is_open(WT_SESSION_IMPL *session, const char *name);
+extern int __wt_open(WT_SESSION_IMPL *session, const char *name, WT_OPEN_FILE_TYPE file_type, u_int flags, WT_FH **fhp);
+extern int __wt_close(WT_SESSION_IMPL *session, WT_FH **fhp);
+extern int __wt_close_connection_close(WT_SESSION_IMPL *session);
+extern int __wt_os_inmemory(WT_SESSION_IMPL *session);
+extern int __wt_fopen(WT_SESSION_IMPL *session, const char *name, uint32_t open_flags, uint32_t flags, WT_FSTREAM **fstrp);
+extern int __wt_os_stdio(WT_SESSION_IMPL *session);
+extern int __wt_getopt( const char *progname, int nargc, char *const *nargv, const char *ostr);
+extern uint64_t __wt_strtouq(const char *nptr, char **endptr, int base);
extern int __wt_ext_struct_pack(WT_EXTENSION_API *wt_api, WT_SESSION *wt_session, void *buffer, size_t size, const char *fmt, ...);
extern int __wt_ext_struct_size(WT_EXTENSION_API *wt_api, WT_SESSION *wt_session, size_t *sizep, const char *fmt, ...);
extern int __wt_ext_struct_unpack(WT_EXTENSION_API *wt_api, WT_SESSION *wt_session, const void *buffer, size_t size, const char *fmt, ...);
@@ -598,7 +622,14 @@ extern int __wt_msg(WT_SESSION_IMPL *session, const char *fmt, ...) WT_GCC_FUNC_
extern int __wt_ext_msg_printf( WT_EXTENSION_API *wt_api, WT_SESSION *wt_session, const char *fmt, ...) WT_GCC_FUNC_DECL_ATTRIBUTE((format (printf, 3, 4)));
extern const char *__wt_ext_strerror(WT_EXTENSION_API *wt_api, WT_SESSION *wt_session, int error);
extern int __wt_progress(WT_SESSION_IMPL *session, const char *s, uint64_t v);
-extern void __wt_assert(WT_SESSION_IMPL *session, int error, const char *file_name, int line_number, const char *fmt, ...) WT_GCC_FUNC_DECL_ATTRIBUTE((format (printf, 5, 6)));
+extern void
+__wt_assert(WT_SESSION_IMPL *session,
+ int error, const char *file_name, int line_number, const char *fmt, ...)
+ WT_GCC_FUNC_DECL_ATTRIBUTE((format (printf, 5, 6)))
+#ifdef HAVE_DIAGNOSTIC
+ WT_GCC_FUNC_DECL_ATTRIBUTE((noreturn))
+#endif
+;
extern int __wt_panic(WT_SESSION_IMPL *session);
extern int __wt_illegal_value(WT_SESSION_IMPL *session, const char *name);
extern int __wt_object_unsupported(WT_SESSION_IMPL *session, const char *uri);
@@ -647,6 +678,8 @@ extern uint32_t __wt_random(WT_RAND_STATE volatile *rnd_state);
extern int __wt_buf_grow_worker(WT_SESSION_IMPL *session, WT_ITEM *buf, size_t size);
extern int __wt_buf_fmt(WT_SESSION_IMPL *session, WT_ITEM *buf, const char *fmt, ...) WT_GCC_FUNC_DECL_ATTRIBUTE((format (printf, 3, 4)));
extern int __wt_buf_catfmt(WT_SESSION_IMPL *session, WT_ITEM *buf, const char *fmt, ...) WT_GCC_FUNC_DECL_ATTRIBUTE((format (printf, 3, 4)));
+extern const char *__wt_buf_set_printable( WT_SESSION_IMPL *session, const void *p, size_t size, WT_ITEM *buf);
+extern const char *__wt_buf_set_size( WT_SESSION_IMPL *session, uint64_t size, bool exact, WT_ITEM *buf);
extern int
__wt_scr_alloc_func(WT_SESSION_IMPL *session, size_t size, WT_ITEM **scratchp
#ifdef HAVE_DIAGNOSTIC
@@ -676,7 +709,7 @@ extern void __wt_stat_join_clear_all(WT_JOIN_STATS **stats);
extern void __wt_stat_join_aggregate( WT_JOIN_STATS **from, WT_JOIN_STATS *to);
extern void __wt_txn_release_snapshot(WT_SESSION_IMPL *session);
extern int __wt_txn_get_snapshot(WT_SESSION_IMPL *session);
-extern int __wt_txn_update_oldest(WT_SESSION_IMPL *session, bool force);
+extern int __wt_txn_update_oldest(WT_SESSION_IMPL *session, uint32_t flags);
extern int __wt_txn_config(WT_SESSION_IMPL *session, const char *cfg[]);
extern void __wt_txn_release(WT_SESSION_IMPL *session);
extern int __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[]);
@@ -711,64 +744,3 @@ extern int __wt_txn_named_snapshot_get(WT_SESSION_IMPL *session, WT_CONFIG_ITEM
extern int __wt_txn_named_snapshot_config(WT_SESSION_IMPL *session, const char *cfg[], bool *has_create, bool *has_drops);
extern int __wt_txn_named_snapshot_destroy(WT_SESSION_IMPL *session);
extern int __wt_txn_recover(WT_SESSION_IMPL *session);
-extern bool __wt_absolute_path(const char *path);
-extern bool __wt_handle_is_open(WT_SESSION_IMPL *session, const char *name);
-extern bool __wt_has_priv(void);
-extern const char *__wt_path_separator(void);
-extern const char *__wt_strerror(WT_SESSION_IMPL *session, int error, char *errbuf, size_t errlen);
-extern int __wt_calloc(WT_SESSION_IMPL *session, size_t number, size_t size, void *retp);
-extern int __wt_close(WT_SESSION_IMPL *session, WT_FH **fhp);
-extern int __wt_close_connection_close(WT_SESSION_IMPL *session);
-extern int __wt_cond_alloc(WT_SESSION_IMPL *session, const char *name, bool is_signalled, WT_CONDVAR **condp);
-extern int __wt_cond_destroy(WT_SESSION_IMPL *session, WT_CONDVAR **condp);
-extern int __wt_cond_signal(WT_SESSION_IMPL *session, WT_CONDVAR *cond);
-extern int __wt_cond_wait_signal( WT_SESSION_IMPL *session, WT_CONDVAR *cond, uint64_t usecs, bool *signalled);
-extern int __wt_copy_and_sync(WT_SESSION *wt_session, const char *from, const char *to);
-extern int __wt_dlclose(WT_SESSION_IMPL *session, WT_DLH *dlh);
-extern int __wt_dlopen(WT_SESSION_IMPL *session, const char *path, WT_DLH **dlhp);
-extern int __wt_dlsym(WT_SESSION_IMPL *session, WT_DLH *dlh, const char *name, bool fail, void *sym_ret);
-extern int __wt_epoch(WT_SESSION_IMPL *session, struct timespec *tsp);
-extern int __wt_errno(void);
-extern int __wt_filename(WT_SESSION_IMPL *session, const char *name, char **path);
-extern int __wt_fopen(WT_SESSION_IMPL *session, const char *name, uint32_t open_flags, uint32_t flags, WT_FSTREAM **fstrp);
-extern int __wt_get_vm_pagesize(void);
-extern int __wt_getenv(WT_SESSION_IMPL *session, const char *variable, const char **envp);
-extern int __wt_getlasterror(void);
-extern int __wt_getopt( const char *progname, int nargc, char *const *nargv, const char *ostr);
-extern int __wt_malloc(WT_SESSION_IMPL *session, size_t bytes_to_allocate, void *retp);
-extern int __wt_map_error_rdonly(int error);
-extern int __wt_nfilename( WT_SESSION_IMPL *session, const char *name, size_t namelen, char **path);
-extern int __wt_once(void (*init_routine)(void));
-extern int __wt_open(WT_SESSION_IMPL *session, const char *name, WT_OPEN_FILE_TYPE file_type, u_int flags, WT_FH **fhp);
-extern int __wt_os_inmemory(WT_SESSION_IMPL *session);
-extern int __wt_os_posix(WT_SESSION_IMPL *session);
-extern int __wt_os_stdio(WT_SESSION_IMPL *session);
-extern int __wt_os_win(WT_SESSION_IMPL *session);
-extern int __wt_posix_directory_list(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *directory, const char *prefix, char ***dirlistp, uint32_t *countp);
-extern int __wt_posix_directory_list_free(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, char **dirlist, uint32_t count);
-extern int __wt_posix_file_fallocate(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, wt_off_t offset, wt_off_t len);
-extern int __wt_posix_map(WT_FILE_HANDLE *fh, WT_SESSION *wt_session, void *mapped_regionp, size_t *lenp, void *mapped_cookiep);
-extern int __wt_posix_map_discard(WT_FILE_HANDLE *fh, WT_SESSION *wt_session, void *map, size_t length, void *mapped_cookie);
-extern int __wt_posix_map_preload(WT_FILE_HANDLE *fh, WT_SESSION *wt_session, const void *map, size_t length, void *mapped_cookie);
-extern int __wt_posix_unmap(WT_FILE_HANDLE *fh, WT_SESSION *wt_session, void *mapped_region, size_t len, void *mapped_cookie);
-extern int __wt_realloc(WT_SESSION_IMPL *session, size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp);
-extern int __wt_realloc_aligned(WT_SESSION_IMPL *session, size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp);
-extern int __wt_realloc_noclear(WT_SESSION_IMPL *session, size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp);
-extern int __wt_remove_if_exists(WT_SESSION_IMPL *session, const char *name);
-extern int __wt_rename_and_sync_directory( WT_SESSION_IMPL *session, const char *from, const char *to);
-extern int __wt_strndup(WT_SESSION_IMPL *session, const void *str, size_t len, void *retp);
-extern int __wt_thread_create(WT_SESSION_IMPL *session, wt_thread_t *tidret, WT_THREAD_CALLBACK(*func)(void *), void *arg);
-extern int __wt_thread_join(WT_SESSION_IMPL *session, wt_thread_t tid);
-extern int __wt_win_directory_list(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *directory, const char *prefix, char ***dirlistp, uint32_t *countp);
-extern int __wt_win_directory_list_free(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, char **dirlist, uint32_t count);
-extern int __wt_win_fs_size(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *name, wt_off_t *sizep);
-extern int __wt_win_map(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, void *mapped_regionp, size_t *lenp, void *mapped_cookiep);
-extern int __wt_win_unmap(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, void *mapped_region, size_t length, void *mapped_cookie);
-extern uint64_t __wt_strtouq(const char *nptr, char **endptr, int base);
-extern void __wt_abort(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((noreturn));
-extern void __wt_free_int(WT_SESSION_IMPL *session, const void *p_arg);
-extern void __wt_sleep(uint64_t seconds, uint64_t micro_seconds);
-extern void __wt_stream_set_line_buffer(FILE *fp);
-extern void __wt_stream_set_no_buffer(FILE *fp);
-extern void __wt_thread_id(char *buf, size_t buflen);
-extern void __wt_yield(void);
diff --git a/src/include/extern_posix.h b/src/include/extern_posix.h
new file mode 100644
index 00000000000..6fde537f36b
--- /dev/null
+++ b/src/include/extern_posix.h
@@ -0,0 +1,31 @@
+/* DO NOT EDIT: automatically built by dist/s_prototypes. */
+
+extern int __wt_posix_directory_list(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *directory, const char *prefix, char ***dirlistp, uint32_t *countp);
+extern int __wt_posix_directory_list_free(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, char **dirlist, uint32_t count);
+extern int __wt_dlopen(WT_SESSION_IMPL *session, const char *path, WT_DLH **dlhp);
+extern int __wt_dlsym(WT_SESSION_IMPL *session, WT_DLH *dlh, const char *name, bool fail, void *sym_ret);
+extern int __wt_dlclose(WT_SESSION_IMPL *session, WT_DLH *dlh);
+extern int __wt_posix_file_fallocate(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, wt_off_t offset, wt_off_t len);
+extern int __wt_os_posix(WT_SESSION_IMPL *session);
+extern int __wt_getenv(WT_SESSION_IMPL *session, const char *variable, const char **envp);
+extern int __wt_posix_map(WT_FILE_HANDLE *fh, WT_SESSION *wt_session, void *mapped_regionp, size_t *lenp, void *mapped_cookiep);
+extern int __wt_posix_map_preload(WT_FILE_HANDLE *fh, WT_SESSION *wt_session, const void *map, size_t length, void *mapped_cookie);
+extern int __wt_posix_map_discard(WT_FILE_HANDLE *fh, WT_SESSION *wt_session, void *map, size_t length, void *mapped_cookie);
+extern int __wt_posix_unmap(WT_FILE_HANDLE *fh, WT_SESSION *wt_session, void *mapped_region, size_t len, void *mapped_cookie);
+extern int __wt_cond_alloc(WT_SESSION_IMPL *session, const char *name, bool is_signalled, WT_CONDVAR **condp);
+extern int __wt_cond_wait_signal( WT_SESSION_IMPL *session, WT_CONDVAR *cond, uint64_t usecs, bool *signalled);
+extern int __wt_cond_signal(WT_SESSION_IMPL *session, WT_CONDVAR *cond);
+extern int __wt_cond_destroy(WT_SESSION_IMPL *session, WT_CONDVAR **condp);
+extern int __wt_once(void (*init_routine)(void));
+extern int __wt_get_vm_pagesize(void);
+extern bool __wt_absolute_path(const char *path);
+extern const char *__wt_path_separator(void);
+extern bool __wt_has_priv(void);
+extern void __wt_stream_set_line_buffer(FILE *fp);
+extern void __wt_stream_set_no_buffer(FILE *fp);
+extern void __wt_sleep(uint64_t seconds, uint64_t micro_seconds);
+extern int __wt_thread_create(WT_SESSION_IMPL *session, wt_thread_t *tidret, WT_THREAD_CALLBACK(*func)(void *), void *arg);
+extern int __wt_thread_join(WT_SESSION_IMPL *session, wt_thread_t tid);
+extern void __wt_thread_id(char *buf, size_t buflen);
+extern int __wt_epoch(WT_SESSION_IMPL *session, struct timespec *tsp);
+extern void __wt_yield(void);
diff --git a/src/include/extern_win.h b/src/include/extern_win.h
new file mode 100644
index 00000000000..c5c2624db2c
--- /dev/null
+++ b/src/include/extern_win.h
@@ -0,0 +1,32 @@
+/* DO NOT EDIT: automatically built by dist/s_prototypes. */
+
+extern int __wt_win_directory_list(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *directory, const char *prefix, char ***dirlistp, uint32_t *countp);
+extern int __wt_win_directory_list_free(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, char **dirlist, uint32_t count);
+extern int __wt_dlopen(WT_SESSION_IMPL *session, const char *path, WT_DLH **dlhp);
+extern int __wt_dlsym(WT_SESSION_IMPL *session, WT_DLH *dlh, const char *name, bool fail, void *sym_ret);
+extern int __wt_dlclose(WT_SESSION_IMPL *session, WT_DLH *dlh);
+extern int __wt_win_fs_size(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *name, wt_off_t *sizep);
+extern int __wt_os_win(WT_SESSION_IMPL *session);
+extern int __wt_getenv(WT_SESSION_IMPL *session, const char *variable, const char **envp);
+extern int __wt_win_map(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, void *mapped_regionp, size_t *lenp, void *mapped_cookiep);
+extern int __wt_win_unmap(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, void *mapped_region, size_t length, void *mapped_cookie);
+extern int __wt_cond_alloc(WT_SESSION_IMPL *session, const char *name, bool is_signalled, WT_CONDVAR **condp);
+extern int __wt_cond_wait_signal( WT_SESSION_IMPL *session, WT_CONDVAR *cond, uint64_t usecs, bool *signalled);
+extern int __wt_cond_signal(WT_SESSION_IMPL *session, WT_CONDVAR *cond);
+extern int __wt_cond_destroy(WT_SESSION_IMPL *session, WT_CONDVAR **condp);
+extern int __wt_once(void (*init_routine)(void));
+extern int __wt_get_vm_pagesize(void);
+extern bool __wt_absolute_path(const char *path);
+extern const char *__wt_path_separator(void);
+extern bool __wt_has_priv(void);
+extern void __wt_stream_set_line_buffer(FILE *fp);
+extern void __wt_stream_set_no_buffer(FILE *fp);
+extern void __wt_sleep(uint64_t seconds, uint64_t micro_seconds);
+extern int __wt_thread_create(WT_SESSION_IMPL *session, wt_thread_t *tidret, WT_THREAD_CALLBACK(*func)(void *), void *arg);
+extern int __wt_thread_join(WT_SESSION_IMPL *session, wt_thread_t tid);
+extern void __wt_thread_id(char *buf, size_t buflen);
+extern int __wt_epoch(WT_SESSION_IMPL *session, struct timespec *tsp);
+extern DWORD __wt_getlasterror(void);
+extern int __wt_map_windows_error(DWORD windows_error);
+extern const char *__wt_formatmessage(WT_SESSION_IMPL *session, DWORD windows_error);
+extern void __wt_yield(void);
diff --git a/src/include/flags.h b/src/include/flags.h
index da7aee7b059..f134af69d29 100644
--- a/src/include/flags.h
+++ b/src/include/flags.h
@@ -13,13 +13,14 @@
#define WT_CONN_LSM_MERGE 0x00000100
#define WT_CONN_PANIC 0x00000200
#define WT_CONN_READONLY 0x00000400
-#define WT_CONN_SERVER_ASYNC 0x00000800
-#define WT_CONN_SERVER_CHECKPOINT 0x00001000
-#define WT_CONN_SERVER_LSM 0x00002000
-#define WT_CONN_SERVER_RUN 0x00004000
-#define WT_CONN_SERVER_STATISTICS 0x00008000
-#define WT_CONN_SERVER_SWEEP 0x00010000
-#define WT_CONN_WAS_BACKUP 0x00020000
+#define WT_CONN_RECOVERING 0x00000800
+#define WT_CONN_SERVER_ASYNC 0x00001000
+#define WT_CONN_SERVER_CHECKPOINT 0x00002000
+#define WT_CONN_SERVER_LSM 0x00004000
+#define WT_CONN_SERVER_RUN 0x00008000
+#define WT_CONN_SERVER_STATISTICS 0x00010000
+#define WT_CONN_SERVER_SWEEP 0x00020000
+#define WT_CONN_WAS_BACKUP 0x00040000
#define WT_EVICTING 0x00000001
#define WT_EVICT_IN_MEMORY 0x00000002
#define WT_EVICT_LOOKASIDE 0x00000004
@@ -47,11 +48,11 @@
#define WT_READ_TRUNCATE 0x00000800
#define WT_READ_WONT_NEED 0x00001000
#define WT_SESSION_CAN_WAIT 0x00000001
-#define WT_SESSION_CLEAR_EVICT_WALK 0x00000002
-#define WT_SESSION_INTERNAL 0x00000004
-#define WT_SESSION_LOCKED_CHECKPOINT 0x00000008
-#define WT_SESSION_LOCKED_HANDLE_LIST 0x00000010
-#define WT_SESSION_LOCKED_METADATA 0x00000020
+#define WT_SESSION_INTERNAL 0x00000002
+#define WT_SESSION_LOCKED_CHECKPOINT 0x00000004
+#define WT_SESSION_LOCKED_HANDLE_LIST 0x00000008
+#define WT_SESSION_LOCKED_METADATA 0x00000010
+#define WT_SESSION_LOCKED_PASS 0x00000020
#define WT_SESSION_LOCKED_SCHEMA 0x00000040
#define WT_SESSION_LOCKED_SLOT 0x00000080
#define WT_SESSION_LOCKED_TABLE 0x00000100
@@ -71,6 +72,8 @@
#define WT_TXN_LOG_CKPT_START 0x00000004
#define WT_TXN_LOG_CKPT_STOP 0x00000008
#define WT_TXN_LOG_CKPT_SYNC 0x00000010
+#define WT_TXN_OLDEST_STRICT 0x00000001
+#define WT_TXN_OLDEST_WAIT 0x00000002
#define WT_VERB_API 0x00000001
#define WT_VERB_BLOCK 0x00000002
#define WT_VERB_CHECKPOINT 0x00000004
diff --git a/src/include/log.h b/src/include/log.h
index 7655cfbb3e9..870c046252c 100644
--- a/src/include/log.h
+++ b/src/include/log.h
@@ -256,9 +256,8 @@ struct __wt_log {
#ifdef HAVE_DIAGNOSTIC
uint64_t write_calls; /* Calls to log_write */
#endif
-
-#define WT_LOG_NOT_VERIFIED 0x1 /* Log just started */
- uint32_t flags;
+#define WT_LOG_OPENED 0x01 /* Log subsystem successfully open */
+ uint32_t flags;
};
struct __wt_log_record {
diff --git a/src/include/misc.h b/src/include/misc.h
index 4c7c9572905..1121b7dfa75 100644
--- a/src/include/misc.h
+++ b/src/include/misc.h
@@ -12,6 +12,8 @@
*/
#define WT_UNUSED(var) (void)(var)
+#define WT_DIVIDER "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
+
/* Basic constants. */
#define WT_THOUSAND (1000)
#define WT_MILLION (1000000)
@@ -31,12 +33,12 @@
*/
#define WT_STORE_SIZE(s) ((uint32_t)(s))
#define WT_PTRDIFF(end, begin) \
- ((size_t)((uint8_t *)(end) - (uint8_t *)(begin)))
+ ((size_t)((const uint8_t *)(end) - (const uint8_t *)(begin)))
#define WT_PTRDIFF32(end, begin) \
WT_STORE_SIZE(WT_PTRDIFF((end), (begin)))
#define WT_BLOCK_FITS(p, len, begin, maxlen) \
- ((uint8_t *)(p) >= (uint8_t *)(begin) && \
- ((uint8_t *)(p) + (len) <= (uint8_t *)(begin) + (maxlen)))
+ ((const uint8_t *)(p) >= (const uint8_t *)(begin) && \
+ ((const uint8_t *)(p) + (len) <= (const uint8_t *)(begin) + (maxlen)))
#define WT_PTR_IN_RANGE(p, begin, maxlen) \
WT_BLOCK_FITS((p), 1, (begin), (maxlen))
diff --git a/src/include/os.h b/src/include/os.h
index dd9b96f73a8..7a8e47ed81f 100644
--- a/src/include/os.h
+++ b/src/include/os.h
@@ -6,28 +6,32 @@
* See the file LICENSE for redistribution information.
*/
+#define WT_SYSCALL(call, ret) do { \
+ /* \
+ * A call returning 0 indicates success; any call where \
+ * 0 is not the only successful return must provide an \
+ * expression evaluating to 0 in all successful cases. \
+ */ \
+ if (((ret) = (call)) == 0) \
+ break; \
+ /* \
+ * The call's error was either returned by the call or \
+ * is in errno, and there are cases where it depends on \
+ * the software release as to which it is (for example, \
+ * posix_fadvise on FreeBSD and OS X). Failing calls \
+ * must either return a non-zero error value, or -1 if \
+ * the error value is in errno. (The WiredTiger errno \
+ * function returns WT_ERROR if errno is 0, which isn't \
+ * ideal but won't discard the failure.) \
+ */ \
+ if ((ret) == -1) \
+ (ret) = __wt_errno(); \
+} while (0)
+
#define WT_SYSCALL_RETRY(call, ret) do { \
int __retry; \
for (__retry = 0; __retry < 10; ++__retry) { \
- /* \
- * A call returning 0 indicates success; any call where \
- * 0 is not the only successful return must provide an \
- * expression evaluating to 0 in all successful cases. \
- */ \
- if (((ret) = (call)) == 0) \
- break; \
- /* \
- * The call's error was either returned by the call or \
- * is in errno, and there are cases where it depends on \
- * the software release as to which it is (for example, \
- * posix_fadvise on FreeBSD and OS X). Failing calls \
- * must either return a non-zero error value, or -1 if \
- * the error value is in errno. (The WiredTiger errno \
- * function returns WT_ERROR if errno is 0, which isn't \
- * ideal but won't discard the failure.) \
- */ \
- if ((ret) == -1) \
- (ret) = __wt_errno(); \
+ WT_SYSCALL(call, ret); \
switch (ret) { \
case EAGAIN: \
case EBUSY: \
@@ -132,7 +136,6 @@ struct __wt_file_handle_inmem {
TAILQ_ENTRY(__wt_file_handle_inmem) q; /* internal queue, hash queue */
TAILQ_ENTRY(__wt_file_handle_inmem) hashq;
- size_t off; /* Read/write offset */
WT_ITEM buf; /* Data */
u_int ref; /* Reference count */
};
diff --git a/src/include/os_fhandle.i b/src/include/os_fhandle.i
index cf790d6bc4d..313bf8eca3f 100644
--- a/src/include/os_fhandle.i
+++ b/src/include/os_fhandle.i
@@ -13,6 +13,7 @@
static inline int
__wt_fsync(WT_SESSION_IMPL *session, WT_FH *fh, bool block)
{
+ WT_DECL_RET;
WT_FILE_HANDLE *handle;
WT_ASSERT(session, !F_ISSET(S2C(session), WT_CONN_READONLY));
@@ -21,12 +22,20 @@ __wt_fsync(WT_SESSION_IMPL *session, WT_FH *fh, bool block)
session, WT_VERB_HANDLEOPS, "%s: handle-sync", fh->handle->name));
handle = fh->handle;
+ /*
+ * There is no way to check when the non-blocking sync-file-range is
+ * complete, but we track the time taken in the call for completeness.
+ */
+ WT_STAT_FAST_CONN_INCR_ATOMIC(session, fsync_active);
+ WT_STAT_FAST_CONN_INCR(session, fsync_io);
if (block)
- return (handle->fh_sync == NULL ? 0 :
+ ret = (handle->fh_sync == NULL ? 0 :
handle->fh_sync(handle, (WT_SESSION *)session));
else
- return (handle->fh_sync_nowait == NULL ? 0 :
+ ret = (handle->fh_sync_nowait == NULL ? 0 :
handle->fh_sync_nowait(handle, (WT_SESSION *)session));
+ WT_STAT_FAST_CONN_DECR_ATOMIC(session, fsync_active);
+ return (ret);
}
/*
@@ -92,14 +101,20 @@ static inline int
__wt_read(
WT_SESSION_IMPL *session, WT_FH *fh, wt_off_t offset, size_t len, void *buf)
{
+ WT_DECL_RET;
+
WT_RET(__wt_verbose(session, WT_VERB_HANDLEOPS,
"%s: handle-read: %" WT_SIZET_FMT " at %" PRIuMAX,
fh->handle->name, len, (uintmax_t)offset));
+ WT_STAT_FAST_CONN_INCR_ATOMIC(session, read_active);
WT_STAT_FAST_CONN_INCR(session, read_io);
- return (fh->handle->fh_read(
- fh->handle, (WT_SESSION *)session, offset, len, buf));
+ ret = fh->handle->fh_read(
+ fh->handle, (WT_SESSION *)session, offset, len, buf);
+
+ WT_STAT_FAST_CONN_DECR_ATOMIC(session, read_active);
+ return (ret);
}
/*
@@ -140,6 +155,8 @@ static inline int
__wt_write(WT_SESSION_IMPL *session,
WT_FH *fh, wt_off_t offset, size_t len, const void *buf)
{
+ WT_DECL_RET;
+
WT_ASSERT(session, !F_ISSET(S2C(session), WT_CONN_READONLY) ||
WT_STRING_MATCH(fh->name,
WT_SINGLETHREAD, strlen(WT_SINGLETHREAD)));
@@ -148,8 +165,12 @@ __wt_write(WT_SESSION_IMPL *session,
"%s: handle-write: %" WT_SIZET_FMT " at %" PRIuMAX,
fh->handle->name, len, (uintmax_t)offset));
+ WT_STAT_FAST_CONN_INCR_ATOMIC(session, write_active);
WT_STAT_FAST_CONN_INCR(session, write_io);
- return (fh->handle->fh_write(
- fh->handle, (WT_SESSION *)session, offset, len, buf));
+ ret = fh->handle->fh_write(
+ fh->handle, (WT_SESSION *)session, offset, len, buf);
+
+ WT_STAT_FAST_CONN_DECR_ATOMIC(session, write_active);
+ return (ret);
}
diff --git a/src/include/packing.i b/src/include/packing.i
index 9d5971ed99f..d662c60d221 100644
--- a/src/include/packing.i
+++ b/src/include/packing.i
@@ -138,7 +138,7 @@ __pack_next(WT_PACK *pack, WT_PACK_VALUE *pv)
next: if (pack->cur == pack->end)
return (WT_NOTFOUND);
- if (isdigit(*pack->cur)) {
+ if (__wt_isdigit((u_char)*pack->cur)) {
pv->havesize = 1;
pv->size = WT_STORE_SIZE(strtoul(pack->cur, &endsize, 10));
pack->cur = endsize;
@@ -540,7 +540,7 @@ __unpack_read(WT_SESSION_IMPL *session,
break;
case 'R':
WT_SIZE_CHECK_UNPACK(sizeof(uint64_t), maxlen);
- pv->u.u = *(uint64_t *)*pp;
+ pv->u.u = *(const uint64_t *)*pp;
*pp += sizeof(uint64_t);
break;
default:
diff --git a/src/include/serial.i b/src/include/serial.i
index c0cd9c85ee9..67edc1c9ce1 100644
--- a/src/include/serial.i
+++ b/src/include/serial.i
@@ -306,7 +306,7 @@ __wt_update_serial(WT_SESSION_IMPL *session, WT_PAGE *page,
if ((txn = page->modify->obsolete_check_txn) != WT_TXN_NONE) {
if (!__wt_txn_visible_all(session, txn)) {
/* Try to move the oldest ID forward and re-check. */
- WT_RET(__wt_txn_update_oldest(session, false));
+ WT_RET(__wt_txn_update_oldest(session, 0));
if (!__wt_txn_visible_all(session, txn))
return (0);
diff --git a/src/include/stat.h b/src/include/stat.h
index a71e0fa208e..57126af8aa4 100644
--- a/src/include/stat.h
+++ b/src/include/stat.h
@@ -144,10 +144,16 @@ __wt_stats_clear(void *stats_arg, int slot)
#define WT_STAT_DECRV(session, stats, fld, value) \
(stats)[WT_STATS_SLOT_ID(session)]->fld -= (int64_t)(value)
+#define WT_STAT_DECRV_ATOMIC(session, stats, fld, value) \
+ __wt_atomic_addi64( \
+ &(stats)[WT_STATS_SLOT_ID(session)]->fld, (int64_t)(value))
#define WT_STAT_DECR(session, stats, fld) \
WT_STAT_DECRV(session, stats, fld, 1)
#define WT_STAT_INCRV(session, stats, fld, value) \
(stats)[WT_STATS_SLOT_ID(session)]->fld += (int64_t)(value)
+#define WT_STAT_INCRV_ATOMIC(session, stats, fld, value) \
+ __wt_atomic_subi64( \
+ &(stats)[WT_STATS_SLOT_ID(session)]->fld, (int64_t)(value))
#define WT_STAT_INCR(session, stats, fld) \
WT_STAT_INCRV(session, stats, fld, 1)
#define WT_STAT_SET(session, stats, fld, value) do { \
@@ -164,12 +170,20 @@ __wt_stats_clear(void *stats_arg, int slot)
} while (0)
#define WT_STAT_FAST_DECR(session, stats, fld) \
WT_STAT_FAST_DECRV(session, stats, fld, 1)
+#define WT_STAT_FAST_DECRV_ATOMIC(session, stats, fld, value) do { \
+ if (FLD_ISSET(S2C(session)->stat_flags, WT_CONN_STAT_FAST)) \
+ WT_STAT_DECRV_ATOMIC(session, stats, fld, value); \
+} while (0)
#define WT_STAT_FAST_INCRV(session, stats, fld, value) do { \
if (FLD_ISSET(S2C(session)->stat_flags, WT_CONN_STAT_FAST)) \
WT_STAT_INCRV(session, stats, fld, value); \
} while (0)
#define WT_STAT_FAST_INCR(session, stats, fld) \
WT_STAT_FAST_INCRV(session, stats, fld, 1)
+#define WT_STAT_FAST_INCRV_ATOMIC(session, stats, fld, value) do { \
+ if (FLD_ISSET(S2C(session)->stat_flags, WT_CONN_STAT_FAST)) \
+ WT_STAT_INCRV_ATOMIC(session, stats, fld, value); \
+} while (0)
#define WT_STAT_FAST_SET(session, stats, fld, value) do { \
if (FLD_ISSET(S2C(session)->stat_flags, WT_CONN_STAT_FAST)) \
WT_STAT_SET(session, stats, fld, value); \
@@ -180,10 +194,14 @@ __wt_stats_clear(void *stats_arg, int slot)
*/
#define WT_STAT_FAST_CONN_DECR(session, fld) \
WT_STAT_FAST_DECR(session, S2C(session)->stats, fld)
+#define WT_STAT_FAST_CONN_DECR_ATOMIC(session, fld) \
+ WT_STAT_FAST_DECRV_ATOMIC(session, S2C(session)->stats, fld, 1)
#define WT_STAT_FAST_CONN_DECRV(session, fld, value) \
WT_STAT_FAST_DECRV(session, S2C(session)->stats, fld, value)
#define WT_STAT_FAST_CONN_INCR(session, fld) \
WT_STAT_FAST_INCR(session, S2C(session)->stats, fld)
+#define WT_STAT_FAST_CONN_INCR_ATOMIC(session, fld) \
+ WT_STAT_FAST_INCRV_ATOMIC(session, S2C(session)->stats, fld, 1)
#define WT_STAT_FAST_CONN_INCRV(session, fld, value) \
WT_STAT_FAST_INCRV(session, S2C(session)->stats, fld, value)
#define WT_STAT_FAST_CONN_SET(session, fld, value) \
@@ -274,6 +292,8 @@ struct __wt_connection_stats {
int64_t cache_eviction_slow;
int64_t cache_eviction_worker_evicting;
int64_t cache_eviction_force_fail;
+ int64_t cache_eviction_walks_active;
+ int64_t cache_eviction_walks_started;
int64_t cache_eviction_hazard;
int64_t cache_hazard_checks;
int64_t cache_hazard_walks;
@@ -288,15 +308,19 @@ struct __wt_connection_stats {
int64_t cache_bytes_max;
int64_t cache_eviction_maximum_page_size;
int64_t cache_eviction_dirty;
+ int64_t cache_eviction_app_dirty;
int64_t cache_eviction_deepen;
int64_t cache_write_lookaside;
int64_t cache_pages_inuse;
int64_t cache_eviction_force;
int64_t cache_eviction_force_delete;
int64_t cache_eviction_app;
+ int64_t cache_eviction_pages_queued;
+ int64_t cache_eviction_pages_queued_oldest;
int64_t cache_read;
int64_t cache_read_lookaside;
int64_t cache_pages_requested;
+ int64_t cache_eviction_pages_seen;
int64_t cache_eviction_fail;
int64_t cache_eviction_walk;
int64_t cache_write;
@@ -317,6 +341,7 @@ struct __wt_connection_stats {
int64_t cond_wait;
int64_t rwlock_read;
int64_t rwlock_write;
+ int64_t fsync_io;
int64_t read_io;
int64_t write_io;
int64_t cursor_create;
@@ -359,7 +384,9 @@ struct __wt_connection_stats {
int64_t log_write_lsn;
int64_t log_write_lsn_skip;
int64_t log_sync;
+ int64_t log_sync_duration;
int64_t log_sync_dir;
+ int64_t log_sync_dir_duration;
int64_t log_writes;
int64_t log_slot_consolidated;
int64_t log_max_filesize;
@@ -381,6 +408,9 @@ struct __wt_connection_stats {
int64_t rec_split_stashed_objects;
int64_t session_cursor_open;
int64_t session_open;
+ int64_t fsync_active;
+ int64_t read_active;
+ int64_t write_active;
int64_t page_busy_blocked;
int64_t page_forcible_evict_blocked;
int64_t page_locked_blocked;
@@ -397,6 +427,10 @@ struct __wt_connection_stats {
int64_t txn_checkpoint_time_total;
int64_t txn_checkpoint;
int64_t txn_fail_cache;
+ int64_t txn_checkpoint_fsync_post;
+ int64_t txn_checkpoint_fsync_pre;
+ int64_t txn_checkpoint_fsync_post_duration;
+ int64_t txn_checkpoint_fsync_pre_duration;
int64_t txn_pinned_range;
int64_t txn_pinned_checkpoint_range;
int64_t txn_pinned_snapshot_range;
@@ -517,9 +551,11 @@ struct __wt_dsrc_stats {
*/
#define WT_JOIN_STATS_BASE 3000
struct __wt_join_stats {
- int64_t accesses;
- int64_t actual_count;
+ int64_t main_access;
int64_t bloom_false_positive;
+ int64_t membership_check;
+ int64_t bloom_insert;
+ int64_t iterated;
};
/* Statistics section: END */
diff --git a/src/include/wiredtiger.in b/src/include/wiredtiger.in
index 6de92b72051..f578f4e6c08 100644
--- a/src/include/wiredtiger.in
+++ b/src/include/wiredtiger.in
@@ -1466,15 +1466,16 @@ struct __wt_session {
* @config{dump_blocks, Display the contents of on-disk blocks as they
* are verified\, using the application's message handler\, intended for
* debugging., a boolean flag; default \c false.}
+ * @config{dump_layout, Display the layout of the files as they are
+ * verified\, using the application's message handler\, intended for
+ * debugging; requires optional support from the block manager., a
+ * boolean flag; default \c false.}
* @config{dump_offsets, Display the contents of specific on-disk
* blocks\, using the application's message handler\, intended for
* debugging., a list of strings; default empty.}
* @config{dump_pages, Display the contents of in-memory pages as they
* are verified\, using the application's message handler\, intended for
* debugging., a boolean flag; default \c false.}
- * @config{dump_shape, Display the shape of the tree after
- * verification\, using the application's message handler\, intended for
- * debugging., a boolean flag; default \c false.}
* @config{strict, Treat any verification problem as an error; by
* default\, verify will warn\, but not fail\, in the case of errors
* that won't affect future behavior (for example\, a leaked block)., a
@@ -1848,7 +1849,7 @@ struct __wt_connection {
* @config{&nbsp;&nbsp;&nbsp;&nbsp;path, the path to a directory into
* which the log files are written. If the value is not an absolute
* path name\, the files are created relative to the database home., a
- * string; default empty.}
+ * string; default \c ".".}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;prealloc,
* pre-allocate log files., a boolean flag; default \c true.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;recover, run recovery or error if
@@ -2344,7 +2345,7 @@ struct __wt_connection {
* integer between 100KB and 2GB; default \c 100MB.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;path, the path to a directory into which the
* log files are written. If the value is not an absolute path name\, the files
- * are created relative to the database home., a string; default empty.}
+ * are created relative to the database home., a string; default \c ".".}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;prealloc, pre-allocate log files., a boolean
* flag; default \c true.}
* @config{&nbsp;&nbsp;&nbsp;&nbsp;recover, run recovery
@@ -3050,10 +3051,6 @@ const char *wiredtiger_version(int *majorp, int *minorp, int *patchp);
* transaction.
*/
#define WT_CACHE_FULL -31807
-/*! @cond internal */
-/*! Permission denied (internal). */
-#define WT_PERM_DENIED -31808
-/*! @endcond */
/*
* Error return section: END
* DO NOT EDIT: automatically built by dist/api_err.py.
@@ -4298,265 +4295,301 @@ extern int wiredtiger_extension_terminate(WT_CONNECTION *connection);
#define WT_STAT_CONN_CACHE_EVICTION_WORKER_EVICTING 1045
/*! cache: failed eviction of pages that exceeded the in-memory maximum */
#define WT_STAT_CONN_CACHE_EVICTION_FORCE_FAIL 1046
+/*! cache: files with active eviction walks */
+#define WT_STAT_CONN_CACHE_EVICTION_WALKS_ACTIVE 1047
+/*! cache: files with new eviction walks started */
+#define WT_STAT_CONN_CACHE_EVICTION_WALKS_STARTED 1048
/*! cache: hazard pointer blocked page eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_HAZARD 1047
+#define WT_STAT_CONN_CACHE_EVICTION_HAZARD 1049
/*! cache: hazard pointer check calls */
-#define WT_STAT_CONN_CACHE_HAZARD_CHECKS 1048
+#define WT_STAT_CONN_CACHE_HAZARD_CHECKS 1050
/*! cache: hazard pointer check entries walked */
-#define WT_STAT_CONN_CACHE_HAZARD_WALKS 1049
+#define WT_STAT_CONN_CACHE_HAZARD_WALKS 1051
/*! cache: hazard pointer maximum array length */
-#define WT_STAT_CONN_CACHE_HAZARD_MAX 1050
+#define WT_STAT_CONN_CACHE_HAZARD_MAX 1052
/*! cache: in-memory page passed criteria to be split */
-#define WT_STAT_CONN_CACHE_INMEM_SPLITTABLE 1051
+#define WT_STAT_CONN_CACHE_INMEM_SPLITTABLE 1053
/*! cache: in-memory page splits */
-#define WT_STAT_CONN_CACHE_INMEM_SPLIT 1052
+#define WT_STAT_CONN_CACHE_INMEM_SPLIT 1054
/*! cache: internal pages evicted */
-#define WT_STAT_CONN_CACHE_EVICTION_INTERNAL 1053
+#define WT_STAT_CONN_CACHE_EVICTION_INTERNAL 1055
/*! cache: internal pages split during eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_INTERNAL 1054
+#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_INTERNAL 1056
/*! cache: leaf pages split during eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_LEAF 1055
+#define WT_STAT_CONN_CACHE_EVICTION_SPLIT_LEAF 1057
/*! cache: lookaside table insert calls */
-#define WT_STAT_CONN_CACHE_LOOKASIDE_INSERT 1056
+#define WT_STAT_CONN_CACHE_LOOKASIDE_INSERT 1058
/*! cache: lookaside table remove calls */
-#define WT_STAT_CONN_CACHE_LOOKASIDE_REMOVE 1057
+#define WT_STAT_CONN_CACHE_LOOKASIDE_REMOVE 1059
/*! cache: maximum bytes configured */
-#define WT_STAT_CONN_CACHE_BYTES_MAX 1058
+#define WT_STAT_CONN_CACHE_BYTES_MAX 1060
/*! cache: maximum page size at eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_MAXIMUM_PAGE_SIZE 1059
+#define WT_STAT_CONN_CACHE_EVICTION_MAXIMUM_PAGE_SIZE 1061
/*! cache: modified pages evicted */
-#define WT_STAT_CONN_CACHE_EVICTION_DIRTY 1060
+#define WT_STAT_CONN_CACHE_EVICTION_DIRTY 1062
+/*! cache: modified pages evicted by application threads */
+#define WT_STAT_CONN_CACHE_EVICTION_APP_DIRTY 1063
/*! cache: page split during eviction deepened the tree */
-#define WT_STAT_CONN_CACHE_EVICTION_DEEPEN 1061
+#define WT_STAT_CONN_CACHE_EVICTION_DEEPEN 1064
/*! cache: page written requiring lookaside records */
-#define WT_STAT_CONN_CACHE_WRITE_LOOKASIDE 1062
+#define WT_STAT_CONN_CACHE_WRITE_LOOKASIDE 1065
/*! cache: pages currently held in the cache */
-#define WT_STAT_CONN_CACHE_PAGES_INUSE 1063
+#define WT_STAT_CONN_CACHE_PAGES_INUSE 1066
/*! cache: pages evicted because they exceeded the in-memory maximum */
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE 1064
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE 1067
/*! cache: pages evicted because they had chains of deleted items */
-#define WT_STAT_CONN_CACHE_EVICTION_FORCE_DELETE 1065
+#define WT_STAT_CONN_CACHE_EVICTION_FORCE_DELETE 1068
/*! cache: pages evicted by application threads */
-#define WT_STAT_CONN_CACHE_EVICTION_APP 1066
+#define WT_STAT_CONN_CACHE_EVICTION_APP 1069
+/*! cache: pages queued for eviction */
+#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED 1070
+/*! cache: pages queued for urgent eviction */
+#define WT_STAT_CONN_CACHE_EVICTION_PAGES_QUEUED_OLDEST 1071
/*! cache: pages read into cache */
-#define WT_STAT_CONN_CACHE_READ 1067
+#define WT_STAT_CONN_CACHE_READ 1072
/*! cache: pages read into cache requiring lookaside entries */
-#define WT_STAT_CONN_CACHE_READ_LOOKASIDE 1068
+#define WT_STAT_CONN_CACHE_READ_LOOKASIDE 1073
/*! cache: pages requested from the cache */
-#define WT_STAT_CONN_CACHE_PAGES_REQUESTED 1069
+#define WT_STAT_CONN_CACHE_PAGES_REQUESTED 1074
+/*! cache: pages seen by eviction walk */
+#define WT_STAT_CONN_CACHE_EVICTION_PAGES_SEEN 1075
/*! cache: pages selected for eviction unable to be evicted */
-#define WT_STAT_CONN_CACHE_EVICTION_FAIL 1070
+#define WT_STAT_CONN_CACHE_EVICTION_FAIL 1076
/*! cache: pages walked for eviction */
-#define WT_STAT_CONN_CACHE_EVICTION_WALK 1071
+#define WT_STAT_CONN_CACHE_EVICTION_WALK 1077
/*! cache: pages written from cache */
-#define WT_STAT_CONN_CACHE_WRITE 1072
+#define WT_STAT_CONN_CACHE_WRITE 1078
/*! cache: pages written requiring in-memory restoration */
-#define WT_STAT_CONN_CACHE_WRITE_RESTORE 1073
+#define WT_STAT_CONN_CACHE_WRITE_RESTORE 1079
/*! cache: percentage overhead */
-#define WT_STAT_CONN_CACHE_OVERHEAD 1074
+#define WT_STAT_CONN_CACHE_OVERHEAD 1080
/*! cache: tracked bytes belonging to internal pages in the cache */
-#define WT_STAT_CONN_CACHE_BYTES_INTERNAL 1075
+#define WT_STAT_CONN_CACHE_BYTES_INTERNAL 1081
/*! cache: tracked bytes belonging to leaf pages in the cache */
-#define WT_STAT_CONN_CACHE_BYTES_LEAF 1076
+#define WT_STAT_CONN_CACHE_BYTES_LEAF 1082
/*! cache: tracked bytes belonging to overflow pages in the cache */
-#define WT_STAT_CONN_CACHE_BYTES_OVERFLOW 1077
+#define WT_STAT_CONN_CACHE_BYTES_OVERFLOW 1083
/*! cache: tracked dirty bytes in the cache */
-#define WT_STAT_CONN_CACHE_BYTES_DIRTY 1078
+#define WT_STAT_CONN_CACHE_BYTES_DIRTY 1084
/*! cache: tracked dirty pages in the cache */
-#define WT_STAT_CONN_CACHE_PAGES_DIRTY 1079
+#define WT_STAT_CONN_CACHE_PAGES_DIRTY 1085
/*! cache: unmodified pages evicted */
-#define WT_STAT_CONN_CACHE_EVICTION_CLEAN 1080
+#define WT_STAT_CONN_CACHE_EVICTION_CLEAN 1086
/*! connection: auto adjusting condition resets */
-#define WT_STAT_CONN_COND_AUTO_WAIT_RESET 1081
+#define WT_STAT_CONN_COND_AUTO_WAIT_RESET 1087
/*! connection: auto adjusting condition wait calls */
-#define WT_STAT_CONN_COND_AUTO_WAIT 1082
+#define WT_STAT_CONN_COND_AUTO_WAIT 1088
/*! connection: files currently open */
-#define WT_STAT_CONN_FILE_OPEN 1083
+#define WT_STAT_CONN_FILE_OPEN 1089
/*! connection: memory allocations */
-#define WT_STAT_CONN_MEMORY_ALLOCATION 1084
+#define WT_STAT_CONN_MEMORY_ALLOCATION 1090
/*! connection: memory frees */
-#define WT_STAT_CONN_MEMORY_FREE 1085
+#define WT_STAT_CONN_MEMORY_FREE 1091
/*! connection: memory re-allocations */
-#define WT_STAT_CONN_MEMORY_GROW 1086
+#define WT_STAT_CONN_MEMORY_GROW 1092
/*! connection: pthread mutex condition wait calls */
-#define WT_STAT_CONN_COND_WAIT 1087
+#define WT_STAT_CONN_COND_WAIT 1093
/*! connection: pthread mutex shared lock read-lock calls */
-#define WT_STAT_CONN_RWLOCK_READ 1088
+#define WT_STAT_CONN_RWLOCK_READ 1094
/*! connection: pthread mutex shared lock write-lock calls */
-#define WT_STAT_CONN_RWLOCK_WRITE 1089
+#define WT_STAT_CONN_RWLOCK_WRITE 1095
+/*! connection: total fsync I/Os */
+#define WT_STAT_CONN_FSYNC_IO 1096
/*! connection: total read I/Os */
-#define WT_STAT_CONN_READ_IO 1090
+#define WT_STAT_CONN_READ_IO 1097
/*! connection: total write I/Os */
-#define WT_STAT_CONN_WRITE_IO 1091
+#define WT_STAT_CONN_WRITE_IO 1098
/*! cursor: cursor create calls */
-#define WT_STAT_CONN_CURSOR_CREATE 1092
+#define WT_STAT_CONN_CURSOR_CREATE 1099
/*! cursor: cursor insert calls */
-#define WT_STAT_CONN_CURSOR_INSERT 1093
+#define WT_STAT_CONN_CURSOR_INSERT 1100
/*! cursor: cursor next calls */
-#define WT_STAT_CONN_CURSOR_NEXT 1094
+#define WT_STAT_CONN_CURSOR_NEXT 1101
/*! cursor: cursor prev calls */
-#define WT_STAT_CONN_CURSOR_PREV 1095
+#define WT_STAT_CONN_CURSOR_PREV 1102
/*! cursor: cursor remove calls */
-#define WT_STAT_CONN_CURSOR_REMOVE 1096
+#define WT_STAT_CONN_CURSOR_REMOVE 1103
/*! cursor: cursor reset calls */
-#define WT_STAT_CONN_CURSOR_RESET 1097
+#define WT_STAT_CONN_CURSOR_RESET 1104
/*! cursor: cursor restarted searches */
-#define WT_STAT_CONN_CURSOR_RESTART 1098
+#define WT_STAT_CONN_CURSOR_RESTART 1105
/*! cursor: cursor search calls */
-#define WT_STAT_CONN_CURSOR_SEARCH 1099
+#define WT_STAT_CONN_CURSOR_SEARCH 1106
/*! cursor: cursor search near calls */
-#define WT_STAT_CONN_CURSOR_SEARCH_NEAR 1100
+#define WT_STAT_CONN_CURSOR_SEARCH_NEAR 1107
/*! cursor: cursor update calls */
-#define WT_STAT_CONN_CURSOR_UPDATE 1101
+#define WT_STAT_CONN_CURSOR_UPDATE 1108
/*! cursor: truncate calls */
-#define WT_STAT_CONN_CURSOR_TRUNCATE 1102
+#define WT_STAT_CONN_CURSOR_TRUNCATE 1109
/*! data-handle: connection data handles currently active */
-#define WT_STAT_CONN_DH_CONN_HANDLE_COUNT 1103
+#define WT_STAT_CONN_DH_CONN_HANDLE_COUNT 1110
/*! data-handle: connection sweep candidate became referenced */
-#define WT_STAT_CONN_DH_SWEEP_REF 1104
+#define WT_STAT_CONN_DH_SWEEP_REF 1111
/*! data-handle: connection sweep dhandles closed */
-#define WT_STAT_CONN_DH_SWEEP_CLOSE 1105
+#define WT_STAT_CONN_DH_SWEEP_CLOSE 1112
/*! data-handle: connection sweep dhandles removed from hash list */
-#define WT_STAT_CONN_DH_SWEEP_REMOVE 1106
+#define WT_STAT_CONN_DH_SWEEP_REMOVE 1113
/*! data-handle: connection sweep time-of-death sets */
-#define WT_STAT_CONN_DH_SWEEP_TOD 1107
+#define WT_STAT_CONN_DH_SWEEP_TOD 1114
/*! data-handle: connection sweeps */
-#define WT_STAT_CONN_DH_SWEEPS 1108
+#define WT_STAT_CONN_DH_SWEEPS 1115
/*! data-handle: session dhandles swept */
-#define WT_STAT_CONN_DH_SESSION_HANDLES 1109
+#define WT_STAT_CONN_DH_SESSION_HANDLES 1116
/*! data-handle: session sweep attempts */
-#define WT_STAT_CONN_DH_SESSION_SWEEPS 1110
+#define WT_STAT_CONN_DH_SESSION_SWEEPS 1117
/*! log: busy returns attempting to switch slots */
-#define WT_STAT_CONN_LOG_SLOT_SWITCH_BUSY 1111
+#define WT_STAT_CONN_LOG_SLOT_SWITCH_BUSY 1118
/*! log: consolidated slot closures */
-#define WT_STAT_CONN_LOG_SLOT_CLOSES 1112
+#define WT_STAT_CONN_LOG_SLOT_CLOSES 1119
/*! log: consolidated slot join races */
-#define WT_STAT_CONN_LOG_SLOT_RACES 1113
+#define WT_STAT_CONN_LOG_SLOT_RACES 1120
/*! log: consolidated slot join transitions */
-#define WT_STAT_CONN_LOG_SLOT_TRANSITIONS 1114
+#define WT_STAT_CONN_LOG_SLOT_TRANSITIONS 1121
/*! log: consolidated slot joins */
-#define WT_STAT_CONN_LOG_SLOT_JOINS 1115
+#define WT_STAT_CONN_LOG_SLOT_JOINS 1122
/*! log: consolidated slot unbuffered writes */
-#define WT_STAT_CONN_LOG_SLOT_UNBUFFERED 1116
+#define WT_STAT_CONN_LOG_SLOT_UNBUFFERED 1123
/*! log: log bytes of payload data */
-#define WT_STAT_CONN_LOG_BYTES_PAYLOAD 1117
+#define WT_STAT_CONN_LOG_BYTES_PAYLOAD 1124
/*! log: log bytes written */
-#define WT_STAT_CONN_LOG_BYTES_WRITTEN 1118
+#define WT_STAT_CONN_LOG_BYTES_WRITTEN 1125
/*! log: log files manually zero-filled */
-#define WT_STAT_CONN_LOG_ZERO_FILLS 1119
+#define WT_STAT_CONN_LOG_ZERO_FILLS 1126
/*! log: log flush operations */
-#define WT_STAT_CONN_LOG_FLUSH 1120
+#define WT_STAT_CONN_LOG_FLUSH 1127
/*! log: log force write operations */
-#define WT_STAT_CONN_LOG_FORCE_WRITE 1121
+#define WT_STAT_CONN_LOG_FORCE_WRITE 1128
/*! log: log force write operations skipped */
-#define WT_STAT_CONN_LOG_FORCE_WRITE_SKIP 1122
+#define WT_STAT_CONN_LOG_FORCE_WRITE_SKIP 1129
/*! log: log records compressed */
-#define WT_STAT_CONN_LOG_COMPRESS_WRITES 1123
+#define WT_STAT_CONN_LOG_COMPRESS_WRITES 1130
/*! log: log records not compressed */
-#define WT_STAT_CONN_LOG_COMPRESS_WRITE_FAILS 1124
+#define WT_STAT_CONN_LOG_COMPRESS_WRITE_FAILS 1131
/*! log: log records too small to compress */
-#define WT_STAT_CONN_LOG_COMPRESS_SMALL 1125
+#define WT_STAT_CONN_LOG_COMPRESS_SMALL 1132
/*! log: log release advances write LSN */
-#define WT_STAT_CONN_LOG_RELEASE_WRITE_LSN 1126
+#define WT_STAT_CONN_LOG_RELEASE_WRITE_LSN 1133
/*! log: log scan operations */
-#define WT_STAT_CONN_LOG_SCANS 1127
+#define WT_STAT_CONN_LOG_SCANS 1134
/*! log: log scan records requiring two reads */
-#define WT_STAT_CONN_LOG_SCAN_REREADS 1128
+#define WT_STAT_CONN_LOG_SCAN_REREADS 1135
/*! log: log server thread advances write LSN */
-#define WT_STAT_CONN_LOG_WRITE_LSN 1129
+#define WT_STAT_CONN_LOG_WRITE_LSN 1136
/*! log: log server thread write LSN walk skipped */
-#define WT_STAT_CONN_LOG_WRITE_LSN_SKIP 1130
+#define WT_STAT_CONN_LOG_WRITE_LSN_SKIP 1137
/*! log: log sync operations */
-#define WT_STAT_CONN_LOG_SYNC 1131
+#define WT_STAT_CONN_LOG_SYNC 1138
+/*! log: log sync time duration (usecs) */
+#define WT_STAT_CONN_LOG_SYNC_DURATION 1139
/*! log: log sync_dir operations */
-#define WT_STAT_CONN_LOG_SYNC_DIR 1132
+#define WT_STAT_CONN_LOG_SYNC_DIR 1140
+/*! log: log sync_dir time duration (usecs) */
+#define WT_STAT_CONN_LOG_SYNC_DIR_DURATION 1141
/*! log: log write operations */
-#define WT_STAT_CONN_LOG_WRITES 1133
+#define WT_STAT_CONN_LOG_WRITES 1142
/*! log: logging bytes consolidated */
-#define WT_STAT_CONN_LOG_SLOT_CONSOLIDATED 1134
+#define WT_STAT_CONN_LOG_SLOT_CONSOLIDATED 1143
/*! log: maximum log file size */
-#define WT_STAT_CONN_LOG_MAX_FILESIZE 1135
+#define WT_STAT_CONN_LOG_MAX_FILESIZE 1144
/*! log: number of pre-allocated log files to create */
-#define WT_STAT_CONN_LOG_PREALLOC_MAX 1136
+#define WT_STAT_CONN_LOG_PREALLOC_MAX 1145
/*! log: pre-allocated log files not ready and missed */
-#define WT_STAT_CONN_LOG_PREALLOC_MISSED 1137
+#define WT_STAT_CONN_LOG_PREALLOC_MISSED 1146
/*! log: pre-allocated log files prepared */
-#define WT_STAT_CONN_LOG_PREALLOC_FILES 1138
+#define WT_STAT_CONN_LOG_PREALLOC_FILES 1147
/*! log: pre-allocated log files used */
-#define WT_STAT_CONN_LOG_PREALLOC_USED 1139
+#define WT_STAT_CONN_LOG_PREALLOC_USED 1148
/*! log: records processed by log scan */
-#define WT_STAT_CONN_LOG_SCAN_RECORDS 1140
+#define WT_STAT_CONN_LOG_SCAN_RECORDS 1149
/*! log: total in-memory size of compressed records */
-#define WT_STAT_CONN_LOG_COMPRESS_MEM 1141
+#define WT_STAT_CONN_LOG_COMPRESS_MEM 1150
/*! log: total log buffer size */
-#define WT_STAT_CONN_LOG_BUFFER_SIZE 1142
+#define WT_STAT_CONN_LOG_BUFFER_SIZE 1151
/*! log: total size of compressed records */
-#define WT_STAT_CONN_LOG_COMPRESS_LEN 1143
+#define WT_STAT_CONN_LOG_COMPRESS_LEN 1152
/*! log: written slots coalesced */
-#define WT_STAT_CONN_LOG_SLOT_COALESCED 1144
+#define WT_STAT_CONN_LOG_SLOT_COALESCED 1153
/*! log: yields waiting for previous log file close */
-#define WT_STAT_CONN_LOG_CLOSE_YIELDS 1145
+#define WT_STAT_CONN_LOG_CLOSE_YIELDS 1154
/*! reconciliation: fast-path pages deleted */
-#define WT_STAT_CONN_REC_PAGE_DELETE_FAST 1146
+#define WT_STAT_CONN_REC_PAGE_DELETE_FAST 1155
/*! reconciliation: page reconciliation calls */
-#define WT_STAT_CONN_REC_PAGES 1147
+#define WT_STAT_CONN_REC_PAGES 1156
/*! reconciliation: page reconciliation calls for eviction */
-#define WT_STAT_CONN_REC_PAGES_EVICTION 1148
+#define WT_STAT_CONN_REC_PAGES_EVICTION 1157
/*! reconciliation: pages deleted */
-#define WT_STAT_CONN_REC_PAGE_DELETE 1149
+#define WT_STAT_CONN_REC_PAGE_DELETE 1158
/*! reconciliation: split bytes currently awaiting free */
-#define WT_STAT_CONN_REC_SPLIT_STASHED_BYTES 1150
+#define WT_STAT_CONN_REC_SPLIT_STASHED_BYTES 1159
/*! reconciliation: split objects currently awaiting free */
-#define WT_STAT_CONN_REC_SPLIT_STASHED_OBJECTS 1151
+#define WT_STAT_CONN_REC_SPLIT_STASHED_OBJECTS 1160
/*! session: open cursor count */
-#define WT_STAT_CONN_SESSION_CURSOR_OPEN 1152
+#define WT_STAT_CONN_SESSION_CURSOR_OPEN 1161
/*! session: open session count */
-#define WT_STAT_CONN_SESSION_OPEN 1153
+#define WT_STAT_CONN_SESSION_OPEN 1162
+/*! thread-state: active filesystem fsync calls */
+#define WT_STAT_CONN_FSYNC_ACTIVE 1163
+/*! thread-state: active filesystem read calls */
+#define WT_STAT_CONN_READ_ACTIVE 1164
+/*! thread-state: active filesystem write calls */
+#define WT_STAT_CONN_WRITE_ACTIVE 1165
/*! thread-yield: page acquire busy blocked */
-#define WT_STAT_CONN_PAGE_BUSY_BLOCKED 1154
+#define WT_STAT_CONN_PAGE_BUSY_BLOCKED 1166
/*! thread-yield: page acquire eviction blocked */
-#define WT_STAT_CONN_PAGE_FORCIBLE_EVICT_BLOCKED 1155
+#define WT_STAT_CONN_PAGE_FORCIBLE_EVICT_BLOCKED 1167
/*! thread-yield: page acquire locked blocked */
-#define WT_STAT_CONN_PAGE_LOCKED_BLOCKED 1156
+#define WT_STAT_CONN_PAGE_LOCKED_BLOCKED 1168
/*! thread-yield: page acquire read blocked */
-#define WT_STAT_CONN_PAGE_READ_BLOCKED 1157
+#define WT_STAT_CONN_PAGE_READ_BLOCKED 1169
/*! thread-yield: page acquire time sleeping (usecs) */
-#define WT_STAT_CONN_PAGE_SLEEP 1158
+#define WT_STAT_CONN_PAGE_SLEEP 1170
/*! transaction: number of named snapshots created */
-#define WT_STAT_CONN_TXN_SNAPSHOTS_CREATED 1159
+#define WT_STAT_CONN_TXN_SNAPSHOTS_CREATED 1171
/*! transaction: number of named snapshots dropped */
-#define WT_STAT_CONN_TXN_SNAPSHOTS_DROPPED 1160
+#define WT_STAT_CONN_TXN_SNAPSHOTS_DROPPED 1172
/*! transaction: transaction begins */
-#define WT_STAT_CONN_TXN_BEGIN 1161
+#define WT_STAT_CONN_TXN_BEGIN 1173
/*! transaction: transaction checkpoint currently running */
-#define WT_STAT_CONN_TXN_CHECKPOINT_RUNNING 1162
+#define WT_STAT_CONN_TXN_CHECKPOINT_RUNNING 1174
/*! transaction: transaction checkpoint generation */
-#define WT_STAT_CONN_TXN_CHECKPOINT_GENERATION 1163
+#define WT_STAT_CONN_TXN_CHECKPOINT_GENERATION 1175
/*! transaction: transaction checkpoint max time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MAX 1164
+#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MAX 1176
/*! transaction: transaction checkpoint min time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MIN 1165
+#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_MIN 1177
/*! transaction: transaction checkpoint most recent time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_RECENT 1166
+#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_RECENT 1178
/*! transaction: transaction checkpoint total time (msecs) */
-#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_TOTAL 1167
+#define WT_STAT_CONN_TXN_CHECKPOINT_TIME_TOTAL 1179
/*! transaction: transaction checkpoints */
-#define WT_STAT_CONN_TXN_CHECKPOINT 1168
+#define WT_STAT_CONN_TXN_CHECKPOINT 1180
/*! transaction: transaction failures due to cache overflow */
-#define WT_STAT_CONN_TXN_FAIL_CACHE 1169
+#define WT_STAT_CONN_TXN_FAIL_CACHE 1181
+/*! transaction: transaction fsync calls for checkpoint after allocating
+ * the transaction ID */
+#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_POST 1182
+/*! transaction: transaction fsync calls for checkpoint before allocating
+ * the transaction ID */
+#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_PRE 1183
+/*! transaction: transaction fsync duration for checkpoint after
+ * allocating the transaction ID (usecs) */
+#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_POST_DURATION 1184
+/*! transaction: transaction fsync duration for checkpoint before
+ * allocating the transaction ID (usecs) */
+#define WT_STAT_CONN_TXN_CHECKPOINT_FSYNC_PRE_DURATION 1185
/*! transaction: transaction range of IDs currently pinned */
-#define WT_STAT_CONN_TXN_PINNED_RANGE 1170
+#define WT_STAT_CONN_TXN_PINNED_RANGE 1186
/*! transaction: transaction range of IDs currently pinned by a checkpoint */
-#define WT_STAT_CONN_TXN_PINNED_CHECKPOINT_RANGE 1171
+#define WT_STAT_CONN_TXN_PINNED_CHECKPOINT_RANGE 1187
/*! transaction: transaction range of IDs currently pinned by named
* snapshots */
-#define WT_STAT_CONN_TXN_PINNED_SNAPSHOT_RANGE 1172
+#define WT_STAT_CONN_TXN_PINNED_SNAPSHOT_RANGE 1188
/*! transaction: transaction sync calls */
-#define WT_STAT_CONN_TXN_SYNC 1173
+#define WT_STAT_CONN_TXN_SYNC 1189
/*! transaction: transactions committed */
-#define WT_STAT_CONN_TXN_COMMIT 1174
+#define WT_STAT_CONN_TXN_COMMIT 1190
/*! transaction: transactions rolled back */
-#define WT_STAT_CONN_TXN_ROLLBACK 1175
+#define WT_STAT_CONN_TXN_ROLLBACK 1191
/*!
* @}
@@ -4773,12 +4806,16 @@ extern int wiredtiger_extension_terminate(WT_CONNECTION *connection);
* @anchor statistics_join
* @{
*/
-/*! : accesses */
-#define WT_STAT_JOIN_ACCESSES 3000
-/*! : actual count of items */
-#define WT_STAT_JOIN_ACTUAL_COUNT 3001
+/*! : accesses to the main table */
+#define WT_STAT_JOIN_MAIN_ACCESS 3000
/*! : bloom filter false positives */
-#define WT_STAT_JOIN_BLOOM_FALSE_POSITIVE 3002
+#define WT_STAT_JOIN_BLOOM_FALSE_POSITIVE 3001
+/*! : checks that conditions of membership are satisfied */
+#define WT_STAT_JOIN_MEMBERSHIP_CHECK 3002
+/*! : items inserted into a bloom filter */
+#define WT_STAT_JOIN_BLOOM_INSERT 3003
+/*! : items iterated */
+#define WT_STAT_JOIN_ITERATED 3004
/*! @} */
/*
* Statistics section: END
diff --git a/src/include/wiredtiger_ext.h b/src/include/wiredtiger_ext.h
index 7d97d97dcf5..3d65cd1fc24 100644
--- a/src/include/wiredtiger_ext.h
+++ b/src/include/wiredtiger_ext.h
@@ -131,6 +131,19 @@ struct __wt_extension_api {
WT_EXTENSION_API *, WT_SESSION *session, int error);
/*!
+ * Map a Windows system error code to a POSIX 1003.1/ANSI C error.
+ *
+ * @param wt_api the extension handle
+ * @param session the session handle (or NULL if none available)
+ * @param windows_error a Windows system error code
+ * @returns a string representation of the error
+ *
+ * @snippet ex_data_source.c WT_EXTENSION_API map_windows_error
+ */
+ int (*map_windows_error)(WT_EXTENSION_API *wt_api,
+ WT_SESSION *session, uint32_t windows_error);
+
+ /*!
* Allocate short-term use scratch memory.
*
* @param wt_api the extension handle
diff --git a/src/include/wt_internal.h b/src/include/wt_internal.h
index 0c8abf36cfe..c5337967f22 100644
--- a/src/include/wt_internal.h
+++ b/src/include/wt_internal.h
@@ -28,7 +28,6 @@ extern "C" {
#include <sys/time.h>
#include <sys/uio.h>
#endif
-#include <ctype.h>
#ifndef _WIN32
#include <dlfcn.h>
#endif
@@ -357,8 +356,14 @@ union __wt_rand_state;
#include "connection.h"
#include "extern.h"
+#ifdef _WIN32
+#include "extern_win.h"
+#else
+#include "extern_posix.h"
+#endif
#include "verify_build.h"
+#include "ctype.i" /* required by packing.i */
#include "intpack.i" /* required by cell.i, packing.i */
#include "buf.i" /* required by cell.i */
diff --git a/src/log/log.c b/src/log/log.c
index 56e9f65f914..bf83c280d8d 100644
--- a/src/log/log.c
+++ b/src/log/log.c
@@ -95,9 +95,11 @@ __wt_log_background(WT_SESSION_IMPL *session, WT_LSN *lsn)
int
__wt_log_force_sync(WT_SESSION_IMPL *session, WT_LSN *min_lsn)
{
+ struct timespec fsync_start, fsync_stop;
WT_DECL_RET;
WT_FH *log_fh;
WT_LOG *log;
+ uint64_t fsync_duration_usecs;
log = S2C(session)->log;
@@ -124,9 +126,14 @@ __wt_log_force_sync(WT_SESSION_IMPL *session, WT_LSN *min_lsn)
"log_force_sync: sync directory %s to LSN %" PRIu32
"/%" PRIu32,
log->log_dir_fh->name, min_lsn->l.file, min_lsn->l.offset));
+ WT_ERR(__wt_epoch(session, &fsync_start));
WT_ERR(__wt_fsync(session, log->log_dir_fh, true));
+ WT_ERR(__wt_epoch(session, &fsync_stop));
+ fsync_duration_usecs = WT_TIMEDIFF_US(fsync_stop, fsync_start);
log->sync_dir_lsn = *min_lsn;
WT_STAT_FAST_CONN_INCR(session, log_sync_dir);
+ WT_STAT_FAST_CONN_INCRV(session,
+ log_sync_dir_duration, fsync_duration_usecs);
}
/*
* Sync the log file if needed.
@@ -143,9 +150,14 @@ __wt_log_force_sync(WT_SESSION_IMPL *session, WT_LSN *min_lsn)
WT_ERR(__wt_verbose(session, WT_VERB_LOG,
"log_force_sync: sync %s to LSN %" PRIu32 "/%" PRIu32,
log_fh->name, min_lsn->l.file, min_lsn->l.offset));
+ WT_ERR(__wt_epoch(session, &fsync_start));
WT_ERR(__wt_fsync(session, log_fh, true));
+ WT_ERR(__wt_epoch(session, &fsync_stop));
+ fsync_duration_usecs = WT_TIMEDIFF_US(fsync_stop, fsync_start);
log->sync_lsn = *min_lsn;
WT_STAT_FAST_CONN_INCR(session, log_sync);
+ WT_STAT_FAST_CONN_INCRV(session,
+ log_sync_duration, fsync_duration_usecs);
WT_ERR(__wt_close(session, &log_fh));
WT_ERR(__wt_cond_signal(session, log->log_sync_cond));
}
@@ -447,12 +459,12 @@ __log_prealloc(WT_SESSION_IMPL *session, WT_FH *fh)
* writes happening concurrently, so there are no locking issues.
*/
if ((ret = __wt_fallocate(
- session, fh, WT_LOG_FIRST_RECORD, conn->log_file_max)) == 0)
+ session, fh, WT_LOG_FIRST_RECORD,
+ conn->log_file_max - WT_LOG_FIRST_RECORD)) == 0)
return (0);
WT_RET_ERROR_OK(ret, ENOTSUP);
- return (__wt_ftruncate(
- session, fh, WT_LOG_FIRST_RECORD + conn->log_file_max));
+ return (__wt_ftruncate(session, fh, conn->log_file_max));
}
/*
@@ -778,6 +790,7 @@ __log_newfile(WT_SESSION_IMPL *session, bool conn_open, bool *created)
{
WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
+ WT_FH *log_fh;
WT_LOG *log;
WT_LSN end_lsn;
int yield_cnt;
@@ -850,8 +863,15 @@ __log_newfile(WT_SESSION_IMPL *session, bool conn_open, bool *created)
WT_RET(__wt_log_allocfile(
session, log->fileid, WT_LOG_FILENAME));
}
+ /*
+ * Since the file system clears the output file handle pointer before
+ * searching the handle list and filling in the new file handle,
+ * we must pass in a local file handle. Otherwise there is a wide
+ * window where another thread could see a NULL log file handle.
+ */
WT_RET(__log_openfile(session,
- false, &log->log_fh, WT_LOG_FILENAME, log->fileid));
+ false, &log_fh, WT_LOG_FILENAME, log->fileid));
+ WT_PUBLISH(log->log_fh, log_fh);
/*
* We need to setup the LSNs. Set the end LSN and alloc LSN to
* the end of the header.
@@ -1029,7 +1049,6 @@ __wt_log_allocfile(
*/
WT_ERR(__log_openfile(session, true, &log_fh, WT_LOG_TMPNAME, tmp_id));
WT_ERR(__log_file_header(session, log_fh, NULL, true));
- WT_ERR(__wt_ftruncate(session, log_fh, WT_LOG_FIRST_RECORD));
WT_ERR(__log_prealloc(session, log_fh));
WT_ERR(__wt_fsync(session, log_fh, true));
WT_ERR(__wt_close(session, &log_fh));
@@ -1090,7 +1109,6 @@ __wt_log_open(WT_SESSION_IMPL *session)
logcount = 0;
lastlog = 0;
firstlog = UINT32_MAX;
- F_SET(log, WT_LOG_NOT_VERIFIED);
/*
* Open up a file handle to the log directory if we haven't.
@@ -1166,6 +1184,8 @@ __wt_log_open(WT_SESSION_IMPL *session)
}
err: WT_TRET(__wt_fs_directory_list_free(session, &logfiles, logcount));
+ if (ret == 0)
+ F_SET(log, WT_LOG_OPENED);
return (ret);
}
@@ -1205,6 +1225,7 @@ __wt_log_close(WT_SESSION_IMPL *session)
WT_RET(__wt_close(session, &log->log_dir_fh));
log->log_dir_fh = NULL;
}
+ F_CLR(log, WT_LOG_OPENED);
return (0);
}
@@ -1274,11 +1295,13 @@ err: __wt_free(session, buf);
int
__wt_log_release(WT_SESSION_IMPL *session, WT_LOGSLOT *slot, bool *freep)
{
+ struct timespec fsync_start, fsync_stop;
WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
WT_LOG *log;
WT_LSN sync_lsn;
int64_t release_buffered, release_bytes;
+ uint64_t fsync_duration_usecs;
int yield_count;
bool locked;
@@ -1408,9 +1431,15 @@ __wt_log_release(WT_SESSION_IMPL *session, WT_LOGSLOT *slot, bool *freep)
"/%" PRIu32,
log->log_dir_fh->name,
sync_lsn.l.file, sync_lsn.l.offset));
+ WT_ERR(__wt_epoch(session, &fsync_start));
WT_ERR(__wt_fsync(session, log->log_dir_fh, true));
+ WT_ERR(__wt_epoch(session, &fsync_stop));
+ fsync_duration_usecs =
+ WT_TIMEDIFF_US(fsync_stop, fsync_start);
log->sync_dir_lsn = sync_lsn;
WT_STAT_FAST_CONN_INCR(session, log_sync_dir);
+ WT_STAT_FAST_CONN_INCRV(session,
+ log_sync_dir_duration, fsync_duration_usecs);
}
/*
@@ -1424,7 +1453,13 @@ __wt_log_release(WT_SESSION_IMPL *session, WT_LOGSLOT *slot, bool *freep)
log->log_fh->name,
sync_lsn.l.file, sync_lsn.l.offset));
WT_STAT_FAST_CONN_INCR(session, log_sync);
+ WT_ERR(__wt_epoch(session, &fsync_start));
WT_ERR(__wt_fsync(session, log->log_fh, true));
+ WT_ERR(__wt_epoch(session, &fsync_stop));
+ fsync_duration_usecs =
+ WT_TIMEDIFF_US(fsync_stop, fsync_start);
+ WT_STAT_FAST_CONN_INCRV(session,
+ log_sync_duration, fsync_duration_usecs);
log->sync_lsn = sync_lsn;
WT_ERR(__wt_cond_signal(session, log->log_sync_cond));
}
@@ -1750,7 +1785,7 @@ err: WT_STAT_FAST_CONN_INCR(session, log_scans);
* an error recovery is likely going to fail. Try to provide
* a helpful failure message.
*/
- if (ret != 0 && F_ISSET(log, WT_LOG_NOT_VERIFIED)) {
+ if (ret != 0 && firstrecord) {
__wt_errx(session,
"WiredTiger is unable to read the recovery log.");
__wt_errx(session, "This may be due to the log"
@@ -1760,7 +1795,6 @@ err: WT_STAT_FAST_CONN_INCR(session, log_scans);
" opened the database with the correct options including"
" all encryption and compression options");
}
- F_CLR(log, WT_LOG_NOT_VERIFIED);
WT_TRET(__wt_fs_directory_list_free(session, &logfiles, logcount));
@@ -1832,9 +1866,10 @@ __wt_log_write(WT_SESSION_IMPL *session, WT_ITEM *record, WT_LSN *lsnp,
/*
* An error during opening the logging subsystem can result in it
* being enabled, but without an open log file. In that case,
- * just return.
+ * just return. We can also have logging opened for reading in a
+ * read-only database and attempt to write a record on close.
*/
- if (log->log_fh == NULL)
+ if (!F_ISSET(log, WT_LOG_OPENED) || F_ISSET(conn, WT_CONN_READONLY))
return (0);
ip = record;
if ((compressor = conn->log_compressor) != NULL &&
diff --git a/src/log/log_auto.c b/src/log/log_auto.c
index d4dab4e1a33..34bccd0ede4 100644
--- a/src/log/log_auto.c
+++ b/src/log/log_auto.c
@@ -44,7 +44,7 @@ __wt_logop_read(WT_SESSION_IMPL *session,
}
static size_t
-__logrec_json_unpack_str(char *dest, size_t destlen, const char *src,
+__logrec_json_unpack_str(char *dest, size_t destlen, const u_char *src,
size_t srclen)
{
size_t total;
diff --git a/src/log/log_slot.c b/src/log/log_slot.c
index b7efb1d9018..47071211450 100644
--- a/src/log/log_slot.c
+++ b/src/log/log_slot.c
@@ -94,6 +94,17 @@ retry:
if (WT_LOG_SLOT_DONE(new_state))
*releasep = 1;
slot->slot_end_lsn = slot->slot_start_lsn;
+ /*
+ * A thread setting the unbuffered flag sets the unbuffered size after
+ * setting the flag. There could be a delay between a thread setting
+ * the flag, a thread closing the slot, and the original thread setting
+ * that value. If the state is unbuffered, wait for the unbuffered
+ * size to be set.
+ */
+ while (WT_LOG_SLOT_UNBUFFERED_ISSET(old_state) &&
+ slot->slot_unbuffered == 0)
+ __wt_yield();
+
end_offset =
WT_LOG_SLOT_JOINED_BUFFERED(old_state) + slot->slot_unbuffered;
slot->slot_end_lsn.l.offset += (uint32_t)end_offset;
diff --git a/src/lsm/lsm_work_unit.c b/src/lsm/lsm_work_unit.c
index 821a996c38b..c19f42327be 100644
--- a/src/lsm/lsm_work_unit.c
+++ b/src/lsm/lsm_work_unit.c
@@ -289,7 +289,8 @@ __wt_lsm_checkpoint_chunk(WT_SESSION_IMPL *session,
}
/* Stop if a running transaction needs the chunk. */
- WT_RET(__wt_txn_update_oldest(session, true));
+ WT_RET(__wt_txn_update_oldest(
+ session, WT_TXN_OLDEST_STRICT | WT_TXN_OLDEST_WAIT));
if (chunk->switch_txn == WT_TXN_NONE ||
!__wt_txn_visible_all(session, chunk->switch_txn)) {
WT_RET(__wt_verbose(session, WT_VERB_LSM,
diff --git a/src/meta/meta_track.c b/src/meta/meta_track.c
index 4fe628e319b..eb06b2bed66 100644
--- a/src/meta/meta_track.c
+++ b/src/meta/meta_track.c
@@ -153,7 +153,6 @@ __meta_track_apply(WT_SESSION_IMPL *session, WT_META_TRACK *trk)
case WT_ST_REMOVE:
case WT_ST_SET:
break;
- WT_ILLEGAL_VALUE(session);
}
__meta_track_clear(session, trk);
@@ -215,7 +214,6 @@ __meta_track_unroll(WT_SESSION_IMPL *session, WT_META_TRACK *trk)
__wt_err(session, ret,
"metadata unroll update %s to %s", trk->a, trk->b);
break;
- WT_ILLEGAL_VALUE(session);
}
__meta_track_clear(session, trk);
diff --git a/src/os_posix/os_errno.c b/src/os_common/os_errno.c
index a0f1202c6ef..a8e56b7f1aa 100644
--- a/src/os_posix/os_errno.c
+++ b/src/os_common/os_errno.c
@@ -23,24 +23,8 @@ __wt_errno(void)
}
/*
- * __wt_map_error_rdonly --
- * Map an error into a WiredTiger error code specific for
- * read-only operation which intercepts based on certain types
- * of failures.
- */
-int
-__wt_map_error_rdonly(int error)
-{
- if (error == ENOENT)
- return (WT_NOTFOUND);
- else if (error == EACCES)
- return (WT_PERM_DENIED);
- return (error);
-}
-
-/*
* __wt_strerror --
- * POSIX implementation of WT_SESSION.strerror and wiredtiger_strerror.
+ * WT_SESSION.strerror and wiredtiger_strerror.
*/
const char *
__wt_strerror(WT_SESSION_IMPL *session, int error, char *errbuf, size_t errlen)
@@ -69,3 +53,28 @@ __wt_strerror(WT_SESSION_IMPL *session, int error, char *errbuf, size_t errlen)
/* Defeated. */
return ("Unable to return error string");
}
+
+/*
+ * __wt_ext_map_windows_error --
+ * Extension API call to map a Windows system error to a POSIX/ANSI error.
+ */
+int
+__wt_ext_map_windows_error(
+ WT_EXTENSION_API *wt_api, WT_SESSION *wt_session, uint32_t windows_error)
+{
+ WT_UNUSED(wt_api);
+ WT_UNUSED(wt_session);
+
+ /*
+ * This extension API only makes sense in Windows builds, but it's hard
+ * to exclude it otherwise (there's no way to return an error, anyway).
+ * Call an underlying function on Windows, else panic so callers figure
+ * out what they're doing wrong.
+ */
+#ifdef _WIN32
+ return (__wt_map_windows_error(windows_error));
+#else
+ WT_UNUSED(windows_error);
+ return (WT_PANIC);
+#endif
+}
diff --git a/src/os_common/os_fhandle.c b/src/os_common/os_fhandle.c
index 50404c8b354..81e4cc14ccb 100644
--- a/src/os_common/os_fhandle.c
+++ b/src/os_common/os_fhandle.c
@@ -27,14 +27,15 @@ __fhandle_method_finalize(
/* not required: fadvise */
/* not required: fallocate */
/* not required: fallocate_nolock */
- /* not required: lock */
+ WT_HANDLE_METHOD_REQ(fh_lock);
/* not required: map */
/* not required: map_discard */
/* not required: map_preload */
/* not required: map_unmap */
WT_HANDLE_METHOD_REQ(fh_read);
WT_HANDLE_METHOD_REQ(fh_size);
- /* not required: sync */
+ if (!readonly)
+ WT_HANDLE_METHOD_REQ(fh_sync);
/* not required: sync_nowait */
if (!readonly) {
WT_HANDLE_METHOD_REQ(fh_truncate);
diff --git a/src/os_common/os_fs_inmemory.c b/src/os_common/os_fs_inmemory.c
index 3e4fe628892..09c2e08db83 100644
--- a/src/os_common/os_fs_inmemory.c
+++ b/src/os_common/os_fs_inmemory.c
@@ -80,22 +80,6 @@ __im_handle_remove(WT_SESSION_IMPL *session,
}
/*
- * __im_handle_size --
- * Return the handle's data size.
- */
-static void
-__im_handle_size(WT_FILE_HANDLE_INMEM *im_fh, wt_off_t *sizep)
-{
- /*
- * XXX
- * This function exists as a place for this comment. MongoDB assumes
- * any file with content will have a non-zero size. In memory tables
- * generally are zero-sized, make MongoDB happy.
- */
- *sizep = im_fh->buf.size == 0 ? 1024 : (wt_off_t)im_fh->buf.size;
-}
-
-/*
* __im_fs_directory_list --
* Return the directory contents.
*/
@@ -284,7 +268,7 @@ __im_fs_size(WT_FILE_SYSTEM *file_system,
if ((im_fh = __im_handle_search(file_system, name)) == NULL)
ret = ENOENT;
else
- __im_handle_size(im_fh, sizep);
+ *sizep = (wt_off_t)im_fh->buf.size;
__wt_spin_unlock(session, &im_fs->lock);
@@ -316,6 +300,20 @@ __im_file_close(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session)
}
/*
+ * __im_file_lock --
+ * Lock/unlock a file.
+ */
+static int
+__im_file_lock(
+ WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, bool lock)
+{
+ WT_UNUSED(file_handle);
+ WT_UNUSED(wt_session);
+ WT_UNUSED(lock);
+ return (0);
+}
+
+/*
* __im_file_read --
* POSIX pread.
*/
@@ -339,7 +337,6 @@ __im_file_read(WT_FILE_HANDLE *file_handle,
if (off < im_fh->buf.size) {
len = WT_MIN(len, im_fh->buf.size - off);
memcpy(buf, (uint8_t *)im_fh->buf.mem + off, len);
- im_fh->off = off + len;
} else
ret = WT_ERROR;
@@ -370,7 +367,7 @@ __im_file_size(
__wt_spin_lock(session, &im_fs->lock);
- __im_handle_size(im_fh, sizep);
+ *sizep = (wt_off_t)im_fh->buf.size;
__wt_spin_unlock(session, &im_fs->lock);
@@ -378,6 +375,18 @@ __im_file_size(
}
/*
+ * __im_file_sync --
+ * In-memory sync.
+ */
+static int
+__im_file_sync(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session)
+{
+ WT_UNUSED(file_handle);
+ WT_UNUSED(wt_session);
+ return (0);
+}
+
+/*
* __im_file_truncate --
* POSIX ftruncate.
*/
@@ -438,7 +447,6 @@ __im_file_write(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session,
memcpy((uint8_t *)im_fh->buf.data + off, buf, len);
if (off + len > im_fh->buf.size)
im_fh->buf.size = off + len;
- im_fh->off = off + len;
err: __wt_spin_unlock(session, &im_fs->lock);
if (ret == 0)
@@ -486,7 +494,6 @@ __im_file_open(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
"%s: file-open: already open", name);
im_fh->ref = 1;
- im_fh->off = 0;
*file_handlep = (WT_FILE_HANDLE *)im_fh;
@@ -504,7 +511,6 @@ __im_file_open(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
/* Initialize private information. */
im_fh->ref = 1;
- im_fh->off = 0;
hash = __wt_hash_city64(name, strlen(name));
bucket = hash % WT_HASH_ARRAY_SIZE;
@@ -512,8 +518,10 @@ __im_file_open(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
WT_FILE_HANDLE_INSERT(im_fs, im_fh, bucket);
file_handle->close = __im_file_close;
+ file_handle->fh_lock = __im_file_lock;
file_handle->fh_read = __im_file_read;
file_handle->fh_size = __im_file_size;
+ file_handle->fh_sync = __im_file_sync;
file_handle->fh_truncate = __im_file_truncate;
file_handle->fh_write = __im_file_write;
diff --git a/src/os_posix/os_dir.c b/src/os_posix/os_dir.c
index ea0ca11fa54..768a1324cd8 100644
--- a/src/os_posix/os_dir.c
+++ b/src/os_posix/os_dir.c
@@ -25,6 +25,7 @@ __wt_posix_directory_list(WT_FILE_SYSTEM *file_system,
WT_SESSION_IMPL *session;
size_t dirallocsz;
uint32_t count;
+ int tret;
char **entries;
WT_UNUSED(file_system);
@@ -64,8 +65,15 @@ __wt_posix_directory_list(WT_FILE_SYSTEM *file_system,
*dirlistp = entries;
*countp = count;
-err: if (dirp != NULL)
- (void)closedir(dirp);
+err: if (dirp != NULL) {
+ WT_SYSCALL(closedir(dirp), tret);
+ if (tret != 0) {
+ __wt_err(session, tret,
+ "%s: directory-list: closedir", directory);
+ if (ret == 0)
+ ret = tret;
+ }
+ }
if (ret == 0)
return (0);
diff --git a/src/os_posix/os_fs.c b/src/os_posix/os_fs.c
index 1cfa8fd2d2d..86fa2e8f117 100644
--- a/src/os_posix/os_fs.c
+++ b/src/os_posix/os_fs.c
@@ -98,7 +98,7 @@ __posix_directory_sync(
ret = __posix_sync(session, fd, path, "directory-sync");
- WT_SYSCALL_RETRY(close(fd), tret);
+ WT_SYSCALL(close(fd), tret);
if (tret != 0) {
__wt_err(session, tret, "%s: directory-sync: close", path);
if (ret == 0)
@@ -124,7 +124,7 @@ __posix_fs_exist(WT_FILE_SYSTEM *file_system,
session = (WT_SESSION_IMPL *)wt_session;
- WT_SYSCALL_RETRY(stat(name, &sb), ret);
+ WT_SYSCALL(stat(name, &sb), ret);
if (ret == 0) {
*existp = true;
return (0);
@@ -158,7 +158,7 @@ __posix_fs_remove(
* where we're not doing any special checking for standards compliance,
* using unlink may be marginally safer.
*/
- WT_SYSCALL_RETRY(unlink(name), ret);
+ WT_SYSCALL(unlink(name), ret);
if (ret == 0)
return (0);
WT_RET_MSG(session, ret, "%s: file-remove: unlink", name);
@@ -186,7 +186,7 @@ __posix_fs_rename(WT_FILE_SYSTEM *file_system,
* with the wrong errno (if errno is garbage), or the generic WT_ERROR
* return (if errno is 0), but we've done the best we can.
*/
- WT_SYSCALL_RETRY(rename(from, to) != 0 ? -1 : 0, ret);
+ WT_SYSCALL(rename(from, to) != 0 ? -1 : 0, ret);
if (ret == 0)
return (0);
WT_RET_MSG(session, ret, "%s to %s: file-rename: rename", from, to);
@@ -208,7 +208,7 @@ __posix_fs_size(WT_FILE_SYSTEM *file_system,
session = (WT_SESSION_IMPL *)wt_session;
- WT_SYSCALL_RETRY(stat(name, &sb), ret);
+ WT_SYSCALL(stat(name, &sb), ret);
if (ret == 0) {
*sizep = sb.st_size;
return (0);
@@ -232,7 +232,7 @@ __posix_file_advise(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session,
session = (WT_SESSION_IMPL *)wt_session;
pfh = (WT_FILE_HANDLE_POSIX *)file_handle;
- WT_SYSCALL_RETRY(posix_fadvise(pfh->fd, offset, len, advice), ret);
+ WT_SYSCALL(posix_fadvise(pfh->fd, offset, len, advice), ret);
if (ret == 0)
return (0);
@@ -268,7 +268,7 @@ __posix_file_close(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session)
/* Close the file handle. */
if (pfh->fd != -1) {
- WT_SYSCALL_RETRY(close(pfh->fd), ret);
+ WT_SYSCALL(close(pfh->fd), ret);
if (ret != 0)
__wt_err(session, ret,
"%s: handle-close: close", file_handle->name);
@@ -309,7 +309,7 @@ __posix_file_lock(
fl.l_type = lock ? F_WRLCK : F_UNLCK;
fl.l_whence = SEEK_SET;
- WT_SYSCALL_RETRY(fcntl(pfh->fd, F_SETLK, &fl) == -1 ? -1 : 0, ret);
+ WT_SYSCALL(fcntl(pfh->fd, F_SETLK, &fl) == -1 ? -1 : 0, ret);
if (ret == 0)
return (0);
WT_RET_MSG(session, ret, "%s: handle-lock: fcntl", file_handle->name);
@@ -369,7 +369,7 @@ __posix_file_size(
session = (WT_SESSION_IMPL *)wt_session;
pfh = (WT_FILE_HANDLE_POSIX *)file_handle;
- WT_SYSCALL_RETRY(fstat(pfh->fd, &sb), ret);
+ WT_SYSCALL(fstat(pfh->fd, &sb), ret);
if (ret == 0) {
*sizep = sb.st_size;
return (0);
@@ -617,7 +617,7 @@ __posix_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
* interesting.
*/
if (!pfh->direct_io && file_type == WT_OPEN_FILE_TYPE_DATA) {
- WT_SYSCALL_RETRY(
+ WT_SYSCALL(
posix_fadvise(pfh->fd, 0, 0, POSIX_FADV_RANDOM), ret);
if (ret != 0)
WT_ERR_MSG(session, ret,
diff --git a/src/os_posix/os_map.c b/src/os_posix/os_map.c
index d89ba4d7c26..b33f6d82e34 100644
--- a/src/os_posix/os_map.c
+++ b/src/os_posix/os_map.c
@@ -105,7 +105,7 @@ __wt_posix_map_preload(WT_FILE_HANDLE *fh,
if (length <= (size_t)conn->page_size)
return (0);
- WT_SYSCALL_RETRY(posix_madvise(blk, length, POSIX_MADV_WILLNEED), ret);
+ WT_SYSCALL(posix_madvise(blk, length, POSIX_MADV_WILLNEED), ret);
if (ret == 0)
return (0);
@@ -138,7 +138,7 @@ __wt_posix_map_discard(WT_FILE_HANDLE *fh,
blk = (void *)((uintptr_t)map & ~(uintptr_t)(conn->page_size - 1));
length += WT_PTRDIFF(map, blk);
- WT_SYSCALL_RETRY(posix_madvise(blk, length, POSIX_MADV_DONTNEED), ret);
+ WT_SYSCALL(posix_madvise(blk, length, POSIX_MADV_DONTNEED), ret);
if (ret == 0)
return (0);
diff --git a/src/os_posix/os_thread.c b/src/os_posix/os_thread.c
index 35a23622ddc..e57a308c9b0 100644
--- a/src/os_posix/os_thread.c
+++ b/src/os_posix/os_thread.c
@@ -34,7 +34,7 @@ __wt_thread_join(WT_SESSION_IMPL *session, wt_thread_t tid)
{
WT_DECL_RET;
- WT_SYSCALL_RETRY(pthread_join(tid, NULL), ret);
+ WT_SYSCALL(pthread_join(tid, NULL), ret);
if (ret == 0)
return (0);
diff --git a/src/os_posix/os_time.c b/src/os_posix/os_time.c
index 0e5a1cdadfb..b1b22a8e684 100644
--- a/src/os_posix/os_time.c
+++ b/src/os_posix/os_time.c
@@ -18,14 +18,14 @@ __wt_epoch(WT_SESSION_IMPL *session, struct timespec *tsp)
WT_DECL_RET;
#if defined(HAVE_CLOCK_GETTIME)
- WT_SYSCALL_RETRY(clock_gettime(CLOCK_REALTIME, tsp), ret);
+ WT_SYSCALL(clock_gettime(CLOCK_REALTIME, tsp), ret);
if (ret == 0)
return (0);
WT_RET_MSG(session, ret, "clock_gettime");
#elif defined(HAVE_GETTIMEOFDAY)
struct timeval v;
- WT_SYSCALL_RETRY(gettimeofday(&v, NULL), ret);
+ WT_SYSCALL(gettimeofday(&v, NULL), ret);
if (ret == 0) {
tsp->tv_sec = v.tv_sec;
tsp->tv_nsec = v.tv_usec * WT_THOUSAND;
diff --git a/src/os_win/os_dir.c b/src/os_win/os_dir.c
index 6f796f6ef7d..dccacc1e446 100644
--- a/src/os_win/os_dir.c
+++ b/src/os_win/os_dir.c
@@ -17,6 +17,7 @@ __wt_win_directory_list(WT_FILE_SYSTEM *file_system,
WT_SESSION *wt_session, const char *directory,
const char *prefix, char ***dirlistp, uint32_t *countp)
{
+ DWORD windows_error;
HANDLE findhandle;
WIN32_FIND_DATA finddata;
WT_DECL_ITEM(pathbuf);
@@ -45,9 +46,13 @@ __wt_win_directory_list(WT_FILE_SYSTEM *file_system,
WT_ERR(__wt_buf_fmt(session, pathbuf, "%s\\*", dir_copy));
findhandle = FindFirstFileA(pathbuf->data, &finddata);
- if (findhandle == INVALID_HANDLE_VALUE)
- WT_ERR_MSG(session, __wt_getlasterror(),
- "%s: directory-list: FindFirstFile", pathbuf->data);
+ if (findhandle == INVALID_HANDLE_VALUE) {
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s: directory-list: FindFirstFile: %s",
+ pathbuf->data, __wt_formatmessage(session, windows_error));
+ WT_ERR(__wt_map_windows_error(windows_error));
+ }
count = 0;
do {
@@ -74,7 +79,16 @@ __wt_win_directory_list(WT_FILE_SYSTEM *file_system,
*countp = count;
err: if (findhandle != INVALID_HANDLE_VALUE)
- (void)FindClose(findhandle);
+ if (FindClose(findhandle) == 0) {
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s: directory-list: FindClose: %s",
+ pathbuf->data,
+ __wt_formatmessage(session, windows_error));
+ if (ret == 0)
+ ret = __wt_map_windows_error(windows_error);
+ }
+
__wt_free(session, dir_copy);
__wt_scr_free(session, &pathbuf);
diff --git a/src/os_win/os_dlopen.c b/src/os_win/os_dlopen.c
index 9289c8f6488..3da47bf23a3 100644
--- a/src/os_win/os_dlopen.c
+++ b/src/os_win/os_dlopen.c
@@ -15,6 +15,7 @@
int
__wt_dlopen(WT_SESSION_IMPL *session, const char *path, WT_DLH **dlhp)
{
+ DWORD windows_error;
WT_DECL_RET;
WT_DLH *dlh;
@@ -26,9 +27,11 @@ __wt_dlopen(WT_SESSION_IMPL *session, const char *path, WT_DLH **dlhp)
if (path == NULL) {
if (GetModuleHandleExA(
0, NULL, (HMODULE *)&dlh->handle) == FALSE) {
- ret = __wt_getlasterror();
- WT_ERR_MSG(session, ret,
- "GetModuleHandleEx(%s): %s", path, 0);
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "GetModuleHandleEx: %s: %s",
+ path, __wt_formatmessage(session, windows_error));
+ WT_ERR(__wt_map_windows_error(windows_error));
}
} else {
// TODO: load dll here
@@ -51,14 +54,20 @@ int
__wt_dlsym(WT_SESSION_IMPL *session,
WT_DLH *dlh, const char *name, bool fail, void *sym_ret)
{
+ DWORD windows_error;
void *sym;
*(void **)sym_ret = NULL;
sym = GetProcAddress(dlh->handle, name);
- if (sym == NULL && fail)
- WT_RET_MSG(session, __wt_getlasterror(),
- "GetProcAddress(%s in %s)", name, dlh->name);
+ if (sym == NULL && fail) {
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "GetProcAddress: %s in %s: %s",
+ name, dlh->name,
+ __wt_formatmessage(session, windows_error));
+ WT_RET(__wt_map_windows_error(windows_error));
+ }
*(void **)sym_ret = sym;
return (0);
@@ -71,11 +80,14 @@ __wt_dlsym(WT_SESSION_IMPL *session,
int
__wt_dlclose(WT_SESSION_IMPL *session, WT_DLH *dlh)
{
+ DWORD windows_error;
WT_DECL_RET;
if (FreeLibrary(dlh->handle) == FALSE) {
- ret = __wt_getlasterror();
- __wt_err(session, ret, "FreeLibrary: %s", dlh->name);
+ windows_error = __wt_getlasterror();
+ __wt_errx(session, "FreeLibrary: %s: %s",
+ dlh->name, __wt_formatmessage(session, windows_error));
+ ret = __wt_map_windows_error(windows_error);
}
__wt_free(session, dlh->name);
diff --git a/src/os_win/os_errno.c b/src/os_win/os_errno.c
deleted file mode 100644
index f3fffd5ef42..00000000000
--- a/src/os_win/os_errno.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*-
- * Copyright (c) 2014-2016 MongoDB, Inc.
- * Copyright (c) 2008-2014 WiredTiger, Inc.
- * All rights reserved.
- *
- * See the file LICENSE for redistribution information.
- */
-
-#include "wt_internal.h"
-
-static const int windows_error_offset = -29000;
-
-/*
- * __wt_map_error_to_windows_error --
- * Return a negative integer, an encoded Windows error
- * Standard C errors are positive integers from 0 - ~200
- * Windows errors are from 0 - 15999 according to the documentation
- */
-static DWORD
-__wt_map_error_to_windows_error(int error)
-{
- /*
- * Ensure we do not exceed the error range
- * Also validate we do not get any COM errors
- * (which are negative integers)
- */
- WT_ASSERT(NULL, error < 0);
-
- return (error + -(windows_error_offset));
-}
-
-/*
- * __wt_map_windows_error_to_error --
- * Return a positive integer, a decoded Windows error
- */
-static int
-__wt_map_windows_error_to_error(DWORD winerr)
-{
- return (winerr + windows_error_offset);
-}
-
-/*
- * __wt_map_error_rdonly --
- * Map an error into a WiredTiger error code specific for
- * read-only operation which intercepts based on certain types
- * of failures.
- */
-int
-__wt_map_error_rdonly(int error)
-{
- if (error == ERROR_FILE_NOT_FOUND)
- return (WT_NOTFOUND);
- else if (error == ERROR_ACCESS_DENIED)
- return (WT_PERM_DENIED);
- return (error);
-}
-
-/*
- * __wt_errno --
- * Return errno, or WT_ERROR if errno not set.
- */
-int
-__wt_errno(void)
-{
- /*
- * Check for 0:
- * It's easy to introduce a problem by calling the wrong error function,
- * for example, this function when the MSVC function set the C runtime
- * error value. Handle gracefully and always return an error.
- */
- return (errno == 0 ? WT_ERROR : errno);
-}
-
-/*
- * __wt_getlasterror --
- * Return GetLastError, or WT_ERROR if error not set.
- */
-int
-__wt_getlasterror(void)
-{
- /*
- * Called when we know an error occurred, and we want the system
- * error code.
- */
- DWORD err = GetLastError();
-
- /*
- * Check for ERROR_SUCCESS:
- * It's easy to introduce a problem by calling the wrong error function,
- * for example, this function when the MSVC function set the C runtime
- * error value. Handle gracefully and always return an error.
- */
- return (err == ERROR_SUCCESS ?
- WT_ERROR : __wt_map_windows_error_to_error(err));
-}
-
-/*
- * __wt_strerror --
- * Windows implementation of WT_SESSION.strerror and wiredtiger_strerror.
- */
-const char *
-__wt_strerror(WT_SESSION_IMPL *session, int error, char *errbuf, size_t errlen)
-{
- DWORD lasterror;
- const char *p;
- char buf[512];
-
- /*
- * Check for a WiredTiger or POSIX constant string, no buffer needed.
- */
- if ((p = __wt_wiredtiger_error(error)) != NULL)
- return (p);
-
- /*
- * When called from wiredtiger_strerror, write a passed-in buffer.
- * When called from WT_SESSION.strerror, write the session's buffer.
- *
- * Check for Windows errors.
- */
- if (error < 0) {
- error = __wt_map_error_to_windows_error(error);
-
- lasterror = FormatMessageA(
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- error,
- 0, /* let system choose the correct LANGID */
- buf,
- sizeof(buf),
- NULL);
-
- if (lasterror != 0 && session == NULL &&
- snprintf(errbuf, errlen, "%s", buf) > 0)
- return (errbuf);
- if (lasterror != 0 && session != NULL &&
- __wt_buf_fmt(session, &session->err, "%s", buf) == 0)
- return (session->err.data);
- }
-
- /* Fallback to a generic message. */
- if (session == NULL &&
- snprintf(errbuf, errlen, "error return: %d", error) > 0)
- return (errbuf);
- if (session != NULL && __wt_buf_fmt(
- session, &session->err, "error return: %d", error) == 0)
- return (session->err.data);
-
- /* Defeated. */
- return ("Unable to return error string");
-}
diff --git a/src/os_win/os_fs.c b/src/os_win/os_fs.c
index 4da60d5ffb0..5daba124e90 100644
--- a/src/os_win/os_fs.c
+++ b/src/os_win/os_fs.c
@@ -39,17 +39,20 @@ static int
__win_fs_remove(
WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *name)
{
- WT_DECL_RET;
+ DWORD windows_error;
WT_SESSION_IMPL *session;
WT_UNUSED(file_system);
session = (WT_SESSION_IMPL *)wt_session;
- if (DeleteFileA(name) == FALSE)
- WT_RET_MSG(session, __wt_getlasterror(),
- "%s: file-remove: DeleteFileA", name);
-
+ if (DeleteFileA(name) == FALSE) {
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s: file-remove: DeleteFileA: %s",
+ name, __wt_formatmessage(session, windows_error));
+ return (__wt_map_windows_error(windows_error));
+ }
return (0);
}
@@ -61,7 +64,7 @@ static int
__win_fs_rename(WT_FILE_SYSTEM *file_system,
WT_SESSION *wt_session, const char *from, const char *to)
{
- WT_DECL_RET;
+ DWORD windows_error;
WT_SESSION_IMPL *session;
WT_UNUSED(file_system);
@@ -73,13 +76,21 @@ __win_fs_rename(WT_FILE_SYSTEM *file_system,
* it exists.
*/
if (GetFileAttributesA(to) != INVALID_FILE_ATTRIBUTES)
- if (DeleteFileA(to) == FALSE)
- WT_RET_MSG(session, __wt_getlasterror(),
- "%s to %s: file-rename: rename", from, to);
+ if (DeleteFileA(to) == FALSE) {
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s: file-rename: DeleteFileA: %s",
+ to, __wt_formatmessage(session, windows_error));
+ return (__wt_map_windows_error(windows_error));
+ }
- if (MoveFileA(from, to) == FALSE)
- WT_RET_MSG(session, __wt_getlasterror(),
- "%s to %s: file-rename: rename", from, to);
+ if (MoveFileA(from, to) == FALSE) {
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s to %s: file-rename: MoveFileA: %s",
+ from, to, __wt_formatmessage(session, windows_error));
+ return (__wt_map_windows_error(windows_error));
+ }
return (0);
}
@@ -92,6 +103,7 @@ int
__wt_win_fs_size(WT_FILE_SYSTEM *file_system,
WT_SESSION *wt_session, const char *name, wt_off_t *sizep)
{
+ DWORD windows_error;
WIN32_FILE_ATTRIBUTE_DATA data;
WT_SESSION_IMPL *session;
@@ -105,8 +117,11 @@ __wt_win_fs_size(WT_FILE_SYSTEM *file_system,
return (0);
}
- WT_RET_MSG(session, __wt_getlasterror(),
- "%s: file-size: GetFileAttributesEx", name);
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s: file-size: GetFileAttributesEx: %s",
+ name, __wt_formatmessage(session, windows_error));
+ return (__wt_map_windows_error(windows_error));
}
/*
@@ -116,6 +131,7 @@ __wt_win_fs_size(WT_FILE_SYSTEM *file_system,
static int
__win_file_close(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session)
{
+ DWORD windows_error;
WT_DECL_RET;
WT_FILE_HANDLE_WIN *win_fh;
WT_SESSION_IMPL *session;
@@ -132,17 +148,22 @@ __win_file_close(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session)
*/
if (win_fh->filehandle != INVALID_HANDLE_VALUE &&
CloseHandle(win_fh->filehandle) == 0) {
- ret = __wt_getlasterror();
- __wt_err(session, ret,
- "%s: handle-close: CloseHandle", file_handle->name);
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s: handle-close: CloseHandle: %s",
+ file_handle->name,
+ __wt_formatmessage(session, windows_error));
+ ret = __wt_map_windows_error(windows_error);
}
if (win_fh->filehandle_secondary != INVALID_HANDLE_VALUE &&
CloseHandle(win_fh->filehandle_secondary) == 0) {
- ret = __wt_getlasterror();
- __wt_err(session, ret,
- "%s: handle-close: secondary: CloseHandle",
- file_handle->name);
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s: handle-close: secondary: CloseHandle: %s",
+ file_handle->name,
+ __wt_formatmessage(session, windows_error));
+ ret = __wt_map_windows_error(windows_error);
}
__wt_free(session, file_handle->name);
@@ -158,7 +179,7 @@ static int
__win_file_lock(
WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, bool lock)
{
- WT_DECL_RET;
+ DWORD windows_error;
WT_FILE_HANDLE_WIN *win_fh;
WT_SESSION_IMPL *session;
@@ -177,17 +198,23 @@ __win_file_lock(
*/
if (lock) {
if (LockFile(win_fh->filehandle, 0, 0, 1, 0) == FALSE) {
- ret = __wt_getlasterror();
- __wt_err(session, ret,
- "%s: handle-lock: LockFile", file_handle->name);
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s: handle-lock: LockFile: %s",
+ file_handle->name,
+ __wt_formatmessage(session, windows_error));
+ return (__wt_map_windows_error(windows_error));
}
} else
if (UnlockFile(win_fh->filehandle, 0, 0, 1, 0) == FALSE) {
- ret = __wt_getlasterror();
- __wt_err(session, ret,
- "%s: handle-lock: UnlockFile", file_handle->name);
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s: handle-lock: UnlockFile: %s",
+ file_handle->name,
+ __wt_formatmessage(session, windows_error));
+ return (__wt_map_windows_error(windows_error));
}
- return (ret);
+ return (0);
}
/*
@@ -198,7 +225,7 @@ static int
__win_file_read(WT_FILE_HANDLE *file_handle,
WT_SESSION *wt_session, wt_off_t offset, size_t len, void *buf)
{
- DWORD chunk, nr;
+ DWORD chunk, nr, windows_error;
uint8_t *addr;
OVERLAPPED overlapped = { 0 };
WT_FILE_HANDLE_WIN *win_fh;
@@ -225,12 +252,15 @@ __win_file_read(WT_FILE_HANDLE *file_handle,
overlapped.OffsetHigh = UINT32_MAX & (offset >> 32);
if (!ReadFile(
- win_fh->filehandle, addr, chunk, &nr, &overlapped))
- WT_RET_MSG(session,
- __wt_getlasterror(),
+ win_fh->filehandle, addr, chunk, &nr, &overlapped)) {
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
"%s: handle-read: ReadFile: failed to read %lu "
- "bytes at offset %" PRIuMAX,
- file_handle->name, chunk, (uintmax_t)offset);
+ "bytes at offset %" PRIuMAX ": %s",
+ file_handle->name, chunk, (uintmax_t)offset,
+ __wt_formatmessage(session, windows_error));
+ return (__wt_map_windows_error(windows_error));
+ }
}
return (0);
}
@@ -243,6 +273,7 @@ static int
__win_file_size(
WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, wt_off_t *sizep)
{
+ DWORD windows_error;
WT_FILE_HANDLE_WIN *win_fh;
WT_SESSION_IMPL *session;
LARGE_INTEGER size;
@@ -255,8 +286,11 @@ __win_file_size(
return (0);
}
- WT_RET_MSG(session, __wt_getlasterror(),
- "%s: handle-size: GetFileSizeEx", file_handle->name);
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s: handle-size: GetFileSizeEx: %s",
+ file_handle->name, __wt_formatmessage(session, windows_error));
+ return (__wt_map_windows_error(windows_error));
}
/*
@@ -266,7 +300,7 @@ __win_file_size(
static int
__win_file_sync(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session)
{
- WT_DECL_RET;
+ DWORD windows_error;
WT_FILE_HANDLE_WIN *win_fh;
WT_SESSION_IMPL *session;
@@ -283,10 +317,12 @@ __win_file_sync(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session)
return (0);
if (FlushFileBuffers(win_fh->filehandle) == FALSE) {
- ret = __wt_getlasterror();
- WT_RET_MSG(session, ret,
- "%s handle-sync: FlushFileBuffers error",
- file_handle->name);
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s handle-sync: FlushFileBuffers: %s",
+ file_handle->name,
+ __wt_formatmessage(session, windows_error));
+ return (__wt_map_windows_error(windows_error));
}
return (0);
}
@@ -299,7 +335,7 @@ static int
__win_file_truncate(
WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, wt_off_t len)
{
- WT_DECL_RET;
+ DWORD windows_error;
WT_FILE_HANDLE_WIN *win_fh;
WT_SESSION_IMPL *session;
LARGE_INTEGER largeint;
@@ -313,18 +349,25 @@ __win_file_truncate(
WT_RET_MSG(session, EINVAL,
"%s: handle-truncate: read-only", file_handle->name);
- if (SetFilePointerEx(
- win_fh->filehandle_secondary, largeint, NULL, FILE_BEGIN) == FALSE)
- WT_RET_MSG(session, __wt_getlasterror(),
- "%s: handle-truncate: SetFilePointerEx",
- file_handle->name);
+ if (SetFilePointerEx(win_fh->filehandle_secondary,
+ largeint, NULL, FILE_BEGIN) == FALSE) {
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s: handle-truncate: SetFilePointerEx: %s",
+ file_handle->name,
+ __wt_formatmessage(session, windows_error));
+ return (__wt_map_windows_error(windows_error));
+ }
if (SetEndOfFile(win_fh->filehandle_secondary) == FALSE) {
if (GetLastError() == ERROR_USER_MAPPED_FILE)
return (EBUSY);
- WT_RET_MSG(session, __wt_getlasterror(),
- "%s: handle-truncate: SetEndOfFile error",
- file_handle->name);
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s: handle-truncate: SetEndOfFile: %s",
+ file_handle->name,
+ __wt_formatmessage(session, windows_error));
+ return (__wt_map_windows_error(windows_error));
}
return (0);
}
@@ -337,8 +380,7 @@ static int
__win_file_write(WT_FILE_HANDLE *file_handle,
WT_SESSION *wt_session, wt_off_t offset, size_t len, const void *buf)
{
- DWORD chunk;
- DWORD nw;
+ DWORD chunk, nw, windows_error;
const uint8_t *addr;
OVERLAPPED overlapped = { 0 };
WT_FILE_HANDLE_WIN *win_fh;
@@ -365,11 +407,15 @@ __win_file_write(WT_FILE_HANDLE *file_handle,
overlapped.OffsetHigh = UINT32_MAX & (offset >> 32);
if (!WriteFile(
- win_fh->filehandle, addr, chunk, &nw, &overlapped))
- WT_RET_MSG(session, __wt_getlasterror(),
+ win_fh->filehandle, addr, chunk, &nw, &overlapped)) {
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
"%s: handle-write: WriteFile: failed to write %lu "
- "bytes at offset %" PRIuMAX,
- file_handle->name, chunk, (uintmax_t)offset);
+ "bytes at offset %" PRIuMAX ": %s",
+ file_handle->name, chunk, (uintmax_t)offset,
+ __wt_formatmessage(session, windows_error));
+ return (__wt_map_windows_error(windows_error));
+ }
}
return (0);
}
@@ -383,7 +429,7 @@ __win_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
const char *name, WT_OPEN_FILE_TYPE file_type, uint32_t flags,
WT_FILE_HANDLE **file_handlep)
{
- DWORD dwCreationDisposition;
+ DWORD dwCreationDisposition, windows_error;
WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
WT_FILE_HANDLE *file_handle;
@@ -464,13 +510,17 @@ __win_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
win_fh->filehandle = CreateFileA(name, desired_access,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, f, NULL);
- if (win_fh->filehandle == INVALID_HANDLE_VALUE)
- WT_ERR_MSG(session, __wt_getlasterror(),
+ if (win_fh->filehandle == INVALID_HANDLE_VALUE) {
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
win_fh->direct_io ?
"%s: handle-open: CreateFileA: failed with direct "
"I/O configured, some filesystem types do not "
- "support direct I/O" :
- "%s: handle-open: CreateFileA", name);
+ "support direct I/O: %s" :
+ "%s: handle-open: CreateFileA: %s",
+ name, __wt_formatmessage(session, windows_error));
+ WT_ERR(__wt_map_windows_error(windows_error));
+ }
}
/*
@@ -482,9 +532,13 @@ __win_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session,
win_fh->filehandle_secondary = CreateFileA(name, desired_access,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, f, NULL);
- if (win_fh->filehandle_secondary == INVALID_HANDLE_VALUE)
- WT_ERR_MSG(session, __wt_getlasterror(),
- "%s: handle-open: CreateFileA: secondary", name);
+ if (win_fh->filehandle_secondary == INVALID_HANDLE_VALUE) {
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s: handle-open: CreateFileA: secondary: %s",
+ name, __wt_formatmessage(session, windows_error));
+ WT_ERR(__wt_map_windows_error(windows_error));
+ }
}
directory_open:
diff --git a/src/os_win/os_getenv.c b/src/os_win/os_getenv.c
index 9b297ac3a74..fe228328ee6 100644
--- a/src/os_win/os_getenv.c
+++ b/src/os_win/os_getenv.c
@@ -15,22 +15,22 @@
int
__wt_getenv(WT_SESSION_IMPL *session, const char *variable, const char **envp)
{
- WT_DECL_RET;
- DWORD size;
+ DWORD size, windows_error;
*envp = NULL;
- size = GetEnvironmentVariableA(variable, NULL, 0);
- if (size <= 1)
+ if ((size = GetEnvironmentVariableA(variable, NULL, 0)) <= 1)
return (WT_NOTFOUND);
- WT_RET(__wt_calloc(session, 1, size, envp));
+ WT_RET(__wt_malloc(session, (size_t)size, envp));
- ret = GetEnvironmentVariableA(variable, *envp, size);
/* We expect the number of bytes not including nul terminator. */
- if ((ret + 1) != size)
- WT_RET_MSG(session, __wt_getlasterror(),
- "GetEnvironmentVariableA failed: %s", variable);
+ if (GetEnvironmentVariableA(variable, *envp, size) == size - 1)
+ return (0);
- return (0);
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "GetEnvironmentVariableA: %s: %s",
+ variable, __wt_formatmessage(session, windows_error));
+ return (__wt_map_windows_error(windows_error));
}
diff --git a/src/os_win/os_map.c b/src/os_win/os_map.c
index 488cbfb2ceb..8f5b289062d 100644
--- a/src/os_win/os_map.c
+++ b/src/os_win/os_map.c
@@ -16,7 +16,7 @@ int
__wt_win_map(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session,
void *mapped_regionp, size_t *lenp, void *mapped_cookiep)
{
- WT_DECL_RET;
+ DWORD windows_error;
WT_FILE_HANDLE_WIN *win_fh;
WT_SESSION_IMPL *session;
size_t len;
@@ -40,18 +40,27 @@ __wt_win_map(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session,
mapped_cookie = CreateFileMappingA(
win_fh->filehandle, NULL, PAGE_READONLY, 0, 0, NULL);
- if (mapped_cookie == NULL)
- WT_RET_MSG(session, __wt_getlasterror(),
- "%s: memory-map: CreateFileMappingA", file_handle->name);
+ if (mapped_cookie == NULL) {
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s: memory-map: CreateFileMappingA: %s",
+ file_handle->name,
+ __wt_formatmessage(session, windows_error));
+ return (__wt_map_windows_error(windows_error));
+ }
if ((map =
MapViewOfFile(mapped_cookie, FILE_MAP_READ, 0, 0, len)) == NULL) {
/* Retrieve the error before cleaning up. */
- ret = __wt_getlasterror();
- CloseHandle(mapped_cookie);
+ windows_error = __wt_getlasterror();
+
+ (void)CloseHandle(mapped_cookie);
- WT_RET_MSG(session, ret,
- "%s: memory-map: MapViewOfFile", file_handle->name);
+ __wt_errx(session,
+ "%s: memory-map: MapViewOfFile: %s",
+ file_handle->name,
+ __wt_formatmessage(session, windows_error));
+ return (__wt_map_windows_error(windows_error));
}
*(void **)mapped_cookiep = mapped_cookie;
@@ -68,6 +77,7 @@ int
__wt_win_unmap(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session,
void *mapped_region, size_t length, void *mapped_cookie)
{
+ DWORD windows_error;
WT_DECL_RET;
WT_FILE_HANDLE_WIN *win_fh;
WT_SESSION_IMPL *session;
@@ -80,15 +90,21 @@ __wt_win_unmap(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session,
file_handle->name, length);
if (UnmapViewOfFile(mapped_region) == 0) {
- ret = __wt_getlasterror();
- __wt_err(session, ret,
- "%s: memory-unmap: UnmapViewOfFile", file_handle->name);
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s: memory-unmap: UnmapViewOfFile: %s",
+ file_handle->name,
+ __wt_formatmessage(session, windows_error));
+ ret = __wt_map_windows_error(windows_error);
}
if (CloseHandle(*(void **)mapped_cookie) == 0) {
- ret = __wt_getlasterror();
- __wt_err(session, ret,
- "%s: memory-unmap: CloseHandle", file_handle->name);
+ windows_error = __wt_getlasterror();
+ __wt_errx(session,
+ "%s: memory-unmap: CloseHandle: %s",
+ file_handle->name,
+ __wt_formatmessage(session, windows_error));
+ ret = __wt_map_windows_error(windows_error);
}
return (ret);
diff --git a/src/os_win/os_mtx_cond.c b/src/os_win/os_mtx_cond.c
index af4a5035076..8645fdaccb3 100644
--- a/src/os_win/os_mtx_cond.c
+++ b/src/os_win/os_mtx_cond.c
@@ -45,10 +45,10 @@ int
__wt_cond_wait_signal(
WT_SESSION_IMPL *session, WT_CONDVAR *cond, uint64_t usecs, bool *signalled)
{
- DWORD err, milliseconds;
- WT_DECL_RET;
- uint64_t milliseconds64;
+ BOOL sleepret;
+ DWORD milliseconds, windows_error;
bool locked;
+ uint64_t milliseconds64;
locked = false;
@@ -88,33 +88,35 @@ __wt_cond_wait_signal(
if (milliseconds == 0)
milliseconds = 1;
- ret = SleepConditionVariableCS(
+ sleepret = SleepConditionVariableCS(
&cond->cond, &cond->mtx, milliseconds);
} else
- ret = SleepConditionVariableCS(
+ sleepret = SleepConditionVariableCS(
&cond->cond, &cond->mtx, INFINITE);
/*
* SleepConditionVariableCS returns non-zero on success, 0 on timeout
- * or failure. Check for timeout, else convert to a WiredTiger error
- * value and fail.
+ * or failure.
*/
- if (ret == 0) {
- if ((err = GetLastError()) == ERROR_TIMEOUT)
+ if (sleepret == 0) {
+ windows_error = __wt_getlasterror();
+ if (windows_error == ERROR_TIMEOUT) {
*signalled = false;
- else
- ret = __wt_getlasterror();
- } else
- ret = 0;
+ sleepret = 1;
+ }
+ }
(void)__wt_atomic_subi32(&cond->waiters, 1);
if (locked)
LeaveCriticalSection(&cond->mtx);
- if (ret == 0)
+ if (sleepret != 0)
return (0);
- WT_RET_MSG(session, ret, "SleepConditionVariableCS");
+
+ __wt_errx(session, "SleepConditionVariableCS: %s",
+ __wt_formatmessage(session, windows_error));
+ return (__wt_map_windows_error(windows_error));
}
/*
diff --git a/src/os_win/os_path.c b/src/os_win/os_path.c
index e9532de2b38..220752ce7a1 100644
--- a/src/os_win/os_path.c
+++ b/src/os_win/os_path.c
@@ -19,7 +19,7 @@ __wt_absolute_path(const char *path)
* Check for a drive name (for example, "D:"), allow both forward and
* backward slashes.
*/
- if (strlen(path) >= 3 && isalpha(path[0]) && path[1] == ':')
+ if (strlen(path) >= 3 && __wt_isalpha(path[0]) && path[1] == ':')
path += 2;
return (path[0] == '/' || path[0] == '\\');
}
diff --git a/src/os_win/os_thread.c b/src/os_win/os_thread.c
index 2b846216442..a34dff776b6 100644
--- a/src/os_win/os_thread.c
+++ b/src/os_win/os_thread.c
@@ -31,19 +31,24 @@ __wt_thread_create(WT_SESSION_IMPL *session,
int
__wt_thread_join(WT_SESSION_IMPL *session, wt_thread_t tid)
{
- WT_DECL_RET;
+ DWORD windows_error;
- if ((ret = WaitForSingleObject(tid, INFINITE)) != WAIT_OBJECT_0)
- /*
- * If we fail to wait, we will leak handles so do not continue
- */
- WT_PANIC_RET(session,
- ret == WAIT_FAILED ? __wt_getlasterror() : ret,
- "thread join: WaitForSingleObject");
+ if ((windows_error =
+ WaitForSingleObject(tid, INFINITE)) != WAIT_OBJECT_0) {
+ if (windows_error == WAIT_FAILED)
+ windows_error = __wt_getlasterror();
+ __wt_errx(session, "thread join: WaitForSingleObject: %s",
+ __wt_formatmessage(session, windows_error));
+
+ /* If we fail to wait, we will leak handles, do not continue. */
+ return (WT_PANIC);
+ }
if (CloseHandle(tid) == 0) {
- WT_RET_MSG(session,
- __wt_getlasterror(), "thread join: CloseHandle");
+ windows_error = __wt_getlasterror();
+ __wt_errx(session, "thread join: CloseHandle: %s",
+ __wt_formatmessage(session, windows_error));
+ return (__wt_map_windows_error(windows_error));
}
return (0);
diff --git a/src/os_win/os_winerr.c b/src/os_win/os_winerr.c
new file mode 100644
index 00000000000..70499580c48
--- /dev/null
+++ b/src/os_win/os_winerr.c
@@ -0,0 +1,130 @@
+/*-
+ * Copyright (c) 2014-2016 MongoDB, Inc.
+ * Copyright (c) 2008-2014 WiredTiger, Inc.
+ * All rights reserved.
+ *
+ * See the file LICENSE for redistribution information.
+ */
+
+#include "wt_internal.h"
+
+/*
+ * __wt_getlasterror --
+ * Return GetLastError, or a relatively generic Windows error if the system
+ * error code isn't set.
+ */
+DWORD
+__wt_getlasterror(void)
+{
+ DWORD windows_error;
+
+ /*
+ * Check for ERROR_SUCCESS:
+ * It's easy to introduce a problem by calling the wrong error function,
+ * for example, this function when the MSVC function set the C runtime
+ * error value. Handle gracefully and always return an error.
+ */
+ windows_error = GetLastError();
+ return (windows_error == ERROR_SUCCESS ?
+ ERROR_INVALID_PARAMETER : windows_error);
+}
+
+/*
+ * __wt_map_windows_error --
+ * Map Windows errors to POSIX/ANSI errors.
+ */
+int
+__wt_map_windows_error(DWORD windows_error)
+{
+ static const struct {
+ int windows_error;
+ int posix_error;
+ } list[] = {
+ { ERROR_ACCESS_DENIED, EACCES },
+ { ERROR_ALREADY_EXISTS, EEXIST },
+ { ERROR_ARENA_TRASHED, EFAULT },
+ { ERROR_BAD_COMMAND, EFAULT },
+ { ERROR_BAD_ENVIRONMENT, EFAULT },
+ { ERROR_BAD_FORMAT, EFAULT },
+ { ERROR_BAD_NETPATH, ENOENT },
+ { ERROR_BAD_NET_NAME, ENOENT },
+ { ERROR_BAD_PATHNAME, ENOENT },
+ { ERROR_BROKEN_PIPE, EPIPE },
+ { ERROR_CANNOT_MAKE, EACCES },
+ { ERROR_CHILD_NOT_COMPLETE, ECHILD },
+ { ERROR_CURRENT_DIRECTORY, EACCES },
+ { ERROR_DIRECT_ACCESS_HANDLE, EBADF },
+ { ERROR_DIR_NOT_EMPTY, ENOTEMPTY },
+ { ERROR_DISK_FULL, ENOSPC },
+ { ERROR_DRIVE_LOCKED, EACCES },
+ { ERROR_FAIL_I24, EACCES },
+ { ERROR_FILENAME_EXCED_RANGE, ENOENT },
+ { ERROR_FILE_EXISTS, EEXIST },
+ { ERROR_FILE_NOT_FOUND, ENOENT },
+ { ERROR_GEN_FAILURE, EFAULT },
+ { ERROR_INVALID_ACCESS, EACCES },
+ { ERROR_INVALID_BLOCK, EFAULT },
+ { ERROR_INVALID_DATA, EFAULT },
+ { ERROR_INVALID_DRIVE, ENOENT },
+ { ERROR_INVALID_FUNCTION, EINVAL },
+ { ERROR_INVALID_HANDLE, EBADF },
+ { ERROR_INVALID_PARAMETER, EINVAL },
+ { ERROR_INVALID_TARGET_HANDLE, EBADF },
+ { ERROR_LOCK_FAILED, EBUSY },
+ { ERROR_LOCK_VIOLATION, EBUSY },
+ { ERROR_MAX_THRDS_REACHED, EAGAIN },
+ { ERROR_NEGATIVE_SEEK, EINVAL },
+ { ERROR_NESTING_NOT_ALLOWED, EAGAIN },
+ { ERROR_NETWORK_ACCESS_DENIED, EACCES },
+ { ERROR_NOT_ENOUGH_MEMORY, ENOMEM },
+ { ERROR_NOT_ENOUGH_QUOTA, ENOMEM },
+ { ERROR_NOT_LOCKED, EACCES },
+ { ERROR_NOT_READY, EBUSY },
+ { ERROR_NOT_SAME_DEVICE, EXDEV },
+ { ERROR_NO_DATA, EPIPE },
+ { ERROR_NO_MORE_FILES, EMFILE },
+ { ERROR_NO_PROC_SLOTS, EAGAIN },
+ { ERROR_PATH_NOT_FOUND, ENOENT },
+ { ERROR_READ_FAULT, EFAULT },
+ { ERROR_RETRY, EINTR },
+ { ERROR_SEEK_ON_DEVICE, EACCES },
+ { ERROR_SHARING_VIOLATION, EBUSY },
+ { ERROR_TOO_MANY_OPEN_FILES, EMFILE },
+ { ERROR_WAIT_NO_CHILDREN, ECHILD },
+ { ERROR_WRITE_FAULT, EFAULT },
+ { ERROR_WRITE_PROTECT, EACCES },
+ };
+ int i;
+
+ for (i = 0; i < WT_ELEMENTS(list); ++i)
+ if (windows_error == list[i].windows_error)
+ return (list[i].posix_error);
+
+ /* Untranslatable error, go generic. */
+ return (WT_ERROR);
+}
+
+/*
+ * __wt_formatmessage --
+ * Windows error formatting.
+ */
+const char *
+__wt_formatmessage(WT_SESSION_IMPL *session, DWORD windows_error)
+{
+ /*
+ * !!!
+ * This function MUST handle a NULL session handle.
+ *
+ * Grow the session error buffer as necessary.
+ */
+ if (session != NULL &&
+ __wt_buf_initsize(session, &session->err, 512) == 0 &&
+ FormatMessageA(
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, windows_error,
+ 0, /* Let system choose the correct LANGID. */
+ session->err.mem, (DWORD)512, NULL) != 0)
+ return (session->err.data);
+
+ return ("Unable to format Windows error string");
+}
diff --git a/src/reconcile/rec_write.c b/src/reconcile/rec_write.c
index 6e406fc7180..b49946bb10e 100644
--- a/src/reconcile/rec_write.c
+++ b/src/reconcile/rec_write.c
@@ -1041,6 +1041,7 @@ __rec_txn_read(WT_SESSION_IMPL *session, WT_RECONCILE *r,
bool append_origv, skipped;
*updp = NULL;
+ append = NULL; /* -Wconditional-uninitialized */
btree = S2BT(session);
page = r->page;
@@ -2428,7 +2429,7 @@ __rec_split(WT_SESSION_IMPL *session, WT_RECONCILE *r, size_t next_len)
r->split_size - WT_PAGE_HEADER_BYTE_SIZE(btree);
break;
case SPLIT_TRACKING_RAW:
- WT_ILLEGAL_VALUE(session);
+ return (__wt_illegal_value(session, NULL));
}
/*
@@ -2959,7 +2960,6 @@ __rec_split_finish_std(WT_SESSION_IMPL *session, WT_RECONCILE *r)
* wrote anything, or there's a remaindered block of data.
*/
break;
- WT_ILLEGAL_VALUE(session);
}
/*
@@ -3330,6 +3330,8 @@ supd_check_complete:
}
bnd->entries = r->entries;
+
+#ifdef HAVE_VERBOSE
/* Output a verbose message if we create a page without many entries */
if (WT_VERBOSE_ISSET(session, WT_VERB_SPLIT) && r->entries < 6)
WT_ERR(__wt_verbose(session, WT_VERB_SPLIT,
@@ -3339,6 +3341,7 @@ supd_check_complete:
r->entries, r->page->memory_footprint, r->bnd_next,
F_ISSET(r, WT_EVICTING) ? "evict" : "checkpoint",
r->bnd_state));
+#endif
WT_ERR(__wt_bt_write(session,
buf, addr, &addr_size, false, bnd->already_compressed));
@@ -3527,6 +3530,7 @@ __wt_bulk_init(WT_SESSION_IMPL *session, WT_CURSOR_BULK *cbulk)
r = cbulk->reconcile;
r->is_bulk_load = true;
+ recno = WT_RECNO_OOB; /* -Werror=maybe-uninitialized */
switch (btree->type) {
case BTREE_COL_FIX:
case BTREE_COL_VAR:
@@ -3535,7 +3539,6 @@ __wt_bulk_init(WT_SESSION_IMPL *session, WT_CURSOR_BULK *cbulk)
case BTREE_ROW:
recno = WT_RECNO_OOB;
break;
- WT_ILLEGAL_VALUE(session);
}
return (__rec_split_init(
@@ -3569,7 +3572,6 @@ __wt_bulk_wrapup(WT_SESSION_IMPL *session, WT_CURSOR_BULK *cbulk)
break;
case BTREE_ROW:
break;
- WT_ILLEGAL_VALUE(session);
}
WT_RET(__rec_split_finish(session, r));
diff --git a/src/schema/schema_create.c b/src/schema/schema_create.c
index 67d64cf1c75..f250612d0ae 100644
--- a/src/schema/schema_create.c
+++ b/src/schema/schema_create.c
@@ -578,7 +578,7 @@ __create_table(WT_SESSION_IMPL *session,
WT_ERR(EEXIST);
exists = true;
}
- WT_RET_NOTFOUND_OK(ret);
+ WT_ERR_NOTFOUND_OK(ret);
WT_ERR(__wt_config_gets(session, cfg, "colgroups", &cval));
WT_ERR(__wt_config_subinit(session, &conf, &cval));
diff --git a/src/schema/schema_list.c b/src/schema/schema_list.c
index 5e9caf94b7a..79e3ef1da7c 100644
--- a/src/schema/schema_list.c
+++ b/src/schema/schema_list.c
@@ -20,6 +20,8 @@ __schema_add_table(WT_SESSION_IMPL *session,
WT_TABLE *table;
uint64_t bucket;
+ table = NULL; /* -Wconditional-uninitialized */
+
/* Make sure the metadata is open before getting other locks. */
WT_RET(__wt_metadata_cursor(session, NULL));
diff --git a/src/schema/schema_project.c b/src/schema/schema_project.c
index 4d29b2baa13..fd59539ae89 100644
--- a/src/schema/schema_project.c
+++ b/src/schema/schema_project.c
@@ -353,7 +353,8 @@ __wt_schema_project_slice(WT_SESSION_IMPL *session, WT_CURSOR **cp,
/* Make sure the types are compatible. */
WT_ASSERT(session,
- tolower(pv.type) == tolower(vpv.type));
+ __wt_tolower((u_char)pv.type) ==
+ __wt_tolower((u_char)vpv.type));
pv.u = vpv.u;
len = __pack_size(session, &pv);
@@ -459,7 +460,8 @@ __wt_schema_project_merge(WT_SESSION_IMPL *session,
WT_RET(__pack_next(&vpack, &vpv));
/* Make sure the types are compatible. */
WT_ASSERT(session,
- tolower(pv.type) == tolower(vpv.type));
+ __wt_tolower((u_char)pv.type) ==
+ __wt_tolower((u_char)vpv.type));
vpv.u = pv.u;
len = __pack_size(session, &vpv);
WT_RET(__wt_buf_grow(session,
diff --git a/src/support/err.c b/src/support/err.c
index 815b79c16db..93c0af37328 100644
--- a/src/support/err.c
+++ b/src/support/err.c
@@ -469,6 +469,9 @@ 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)))
+#ifdef HAVE_DIAGNOSTIC
+ WT_GCC_FUNC_ATTRIBUTE((noreturn))
+#endif
{
va_list ap;
@@ -493,7 +496,10 @@ __wt_panic(WT_SESSION_IMPL *session)
F_SET(S2C(session), WT_CONN_PANIC);
__wt_err(session, WT_PANIC, "the process must exit and restart");
-#if !defined(HAVE_DIAGNOSTIC)
+#if defined(HAVE_DIAGNOSTIC)
+ __wt_abort(session); /* Drop core if testing. */
+ /* NOTREACHED */
+#else
/*
* Chaos reigns within.
* Reflect, repent, and reboot.
@@ -501,9 +507,6 @@ __wt_panic(WT_SESSION_IMPL *session)
*/
return (WT_PANIC);
#endif
-
- __wt_abort(session); /* Drop core if testing. */
- /* NOTREACHED */
}
/*
@@ -517,12 +520,12 @@ __wt_illegal_value(WT_SESSION_IMPL *session, const char *name)
name == NULL ? "" : name, name == NULL ? "" : ": ",
"encountered an illegal file format or internal value");
-#if !defined(HAVE_DIAGNOSTIC)
- return (__wt_panic(session));
-#endif
-
+#if defined(HAVE_DIAGNOSTIC)
__wt_abort(session); /* Drop core if testing. */
/* NOTREACHED */
+#else
+ return (__wt_panic(session));
+#endif
}
/*
diff --git a/src/support/global.c b/src/support/global.c
index e0d5bafeaa8..eba88bf2b20 100644
--- a/src/support/global.c
+++ b/src/support/global.c
@@ -111,11 +111,13 @@ void
__wt_attach(WT_SESSION_IMPL *session)
{
#ifdef HAVE_ATTACH
+ u_int i;
+
__wt_errx(session, "process ID %" PRIdMAX
": waiting for debugger...", (intmax_t)getpid());
/* Sleep forever, the debugger will interrupt us when it attaches. */
- for (;;)
+ for (i = 0; i < WT_MILLION; ++i)
__wt_sleep(10, 0);
#else
WT_UNUSED(session);
diff --git a/src/support/hash_city.c b/src/support/hash_city.c
index 7a700aa809c..8354532e820 100644
--- a/src/support/hash_city.c
+++ b/src/support/hash_city.c
@@ -85,6 +85,7 @@ static uint32_t UNALIGNED_LOAD32(const char *p) {
return (result);
}
+#ifdef WORDS_BIGENDIAN
#ifdef _MSC_VER
#include <stdlib.h>
@@ -132,7 +133,6 @@ static uint32_t UNALIGNED_LOAD32(const char *p) {
#endif
-#ifdef WORDS_BIGENDIAN
#define uint32_in_expected_order(x) (bswap_32(x))
#define uint64_in_expected_order(x) (bswap_64(x))
#else
diff --git a/src/support/hazard.c b/src/support/hazard.c
index 13e0eb3b9ac..dee85586a4d 100644
--- a/src/support/hazard.c
+++ b/src/support/hazard.c
@@ -121,7 +121,8 @@ __wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref, bool *busyp
return (0);
}
- __wt_errx(session, "session %p: hazard pointer table full", session);
+ __wt_errx(session,
+ "session %p: hazard pointer table full", (void *)session);
#ifdef HAVE_DIAGNOSTIC
__hazard_dump(session);
#endif
@@ -176,7 +177,8 @@ __wt_hazard_clear(WT_SESSION_IMPL *session, WT_PAGE *page)
* because using a page we didn't have pinned down implies corruption.
*/
WT_PANIC_RET(session, EINVAL,
- "session %p: clear hazard pointer: %p: not found", session, page);
+ "session %p: clear hazard pointer: %p: not found",
+ (void *)session, (void *)page);
}
/*
@@ -204,7 +206,8 @@ __wt_hazard_close(WT_SESSION_IMPL *session)
return;
__wt_errx(session,
- "session %p: close hazard pointer table: table not empty", session);
+ "session %p: close hazard pointer table: table not empty",
+ (void *)session);
#ifdef HAVE_DIAGNOSTIC
__hazard_dump(session);
@@ -232,7 +235,7 @@ __wt_hazard_close(WT_SESSION_IMPL *session)
__wt_errx(session,
"session %p: close hazard pointer table: count didn't "
"match entries",
- session);
+ (void *)session);
}
#ifdef HAVE_DIAGNOSTIC
@@ -250,6 +253,7 @@ __hazard_dump(WT_SESSION_IMPL *session)
if (hp->page != NULL)
__wt_errx(session,
"session %p: hazard pointer %p: %s, line %d",
- session, hp->page, hp->file, hp->line);
+ (void *)session,
+ (void *)hp->page, hp->file, hp->line);
}
#endif
diff --git a/src/support/hex.c b/src/support/hex.c
index d42a84154ca..5c48ce8b74a 100644
--- a/src/support/hex.c
+++ b/src/support/hex.c
@@ -84,7 +84,7 @@ __wt_raw_to_esc_hex(
WT_RET(__wt_buf_init(session, to, size * 3 + 1));
for (p = from, t = to->mem, i = size; i > 0; --i, ++p)
- if (isprint((int)*p)) {
+ if (__wt_isprint((u_char)*p)) {
if (*p == '\\')
*t++ = '\\';
*t++ = *p;
diff --git a/src/support/huffman.c b/src/support/huffman.c
index 1e1aaeab5b5..05612cdbe80 100644
--- a/src/support/huffman.c
+++ b/src/support/huffman.c
@@ -230,19 +230,19 @@ set_codes(WT_FREQTREE_NODE *node,
* lower-order bits for consecutive numbering.
*/
if (len < MAX_CODE_LENGTH &&
- ((half = 1 << (remaining - 1)) < node->left->weight ||
- half < node->right->weight)) {
- pattern = pattern << remaining;
+ ((half = (uint16_t)(1 << (remaining - 1))) <
+ node->left->weight || half < node->right->weight)) {
+ pattern = (uint16_t)(pattern << remaining);
len = MAX_CODE_LENGTH;
}
if (len < MAX_CODE_LENGTH) {
- patternleft = (pattern << 1) | 0;
- patternright = (pattern << 1) | 1;
+ patternleft = (uint16_t)((pattern << 1) | 0);
+ patternright = (uint16_t)((pattern << 1) | 1);
len++;
} else { /* "low bit mode" */
patternleft = pattern;
- patternright = pattern + node->left->weight;
+ patternright = (uint16_t)(pattern + node->left->weight);
/* len unchanged */
}
@@ -284,12 +284,12 @@ make_table(WT_SESSION_IMPL *session, uint8_t *code2symbol,
* than necessary, we allocate (2 ^ max-code-length) of them.
*/
c = codes[i].pattern;
- shift = max_depth - len;
+ shift = (uint8_t)(max_depth - len);
c1 = (uint32_t)c << shift;
c2 = (uint32_t)(c + 1) << shift;
for (j = c1; j < c2; j++) {
WT_ASSERT(session, code2symbol[j] == 0);
- code2symbol[j] = i;
+ code2symbol[j] = (uint8_t)i;
}
}
}
@@ -694,7 +694,7 @@ __wt_huffman_encode(WT_SESSION_IMPL *session, void *huffman_arg,
* used in the last byte, unless they're 0, in which case there are 8
* bits used in the last byte.
*/
- padding_info = (bitpos % 8) << (8 - WT_HUFFMAN_HEADER);
+ padding_info = (uint8_t)((bitpos % 8) << (8 - WT_HUFFMAN_HEADER));
((uint8_t *)tmp->mem)[0] |= padding_info;
/* Copy result of exact known size into caller's buffer. */
@@ -808,11 +808,12 @@ __wt_huffman_decode(WT_SESSION_IMPL *session, void *huffman_arg,
valid += 8;
from_bytes--;
}
- pattern = valid >= max ? /* short patterns near end */
- (bits >> (valid - max)) : (bits << (max - valid));
+ pattern = (uint16_t)
+ (valid >= max ? /* short patterns near end */
+ (bits >> (valid - max)) : (bits << (max - valid)));
symbol = huffman->code2symbol[pattern & mask];
len = huffman->codes[symbol].length;
- valid -= len;
+ valid -= (uint8_t)len;
/*
* from_len_bits is the total number of input bits, reduced by
diff --git a/src/support/scratch.c b/src/support/scratch.c
index 1881f8ad5a5..69987ebc852 100644
--- a/src/support/scratch.c
+++ b/src/support/scratch.c
@@ -135,6 +135,64 @@ __wt_buf_catfmt(WT_SESSION_IMPL *session, WT_ITEM *buf, const char *fmt, ...)
}
/*
+ * __wt_buf_set_printable --
+ * Set the contents of the buffer to a printable representation of a
+ * byte string.
+ */
+const char *
+__wt_buf_set_printable(
+ WT_SESSION_IMPL *session, const void *p, size_t size, WT_ITEM *buf)
+{
+ if (__wt_raw_to_esc_hex(session, p, size, buf)) {
+ buf->data = "[Error]";
+ buf->size = strlen("[Error]");
+ }
+ return (buf->data);
+}
+
+/*
+ * __wt_buf_set_size --
+ * Set the contents of the buffer to a printable representation of a
+ * byte size.
+ */
+const char *
+__wt_buf_set_size(
+ WT_SESSION_IMPL *session, uint64_t size, bool exact, WT_ITEM *buf)
+{
+ WT_DECL_RET;
+
+ if (size >= WT_EXABYTE)
+ ret = __wt_buf_fmt(session, buf,
+ "%" PRIu64 "EB", size / WT_EXABYTE);
+ else if (size >= WT_PETABYTE)
+ ret = __wt_buf_fmt(session, buf,
+ "%" PRIu64 "PB", size / WT_PETABYTE);
+ else if (size >= WT_TERABYTE)
+ ret = __wt_buf_fmt(session, buf,
+ "%" PRIu64 "TB", size / WT_TERABYTE);
+ else if (size >= WT_GIGABYTE)
+ ret = __wt_buf_fmt(session, buf,
+ "%" PRIu64 "GB", size / WT_GIGABYTE);
+ else if (size >= WT_MEGABYTE)
+ ret = __wt_buf_fmt(session, buf,
+ "%" PRIu64 "MB", size / WT_MEGABYTE);
+ else if (size >= WT_KILOBYTE)
+ ret = __wt_buf_fmt(session, buf,
+ "%" PRIu64 "KB", size / WT_KILOBYTE);
+ else
+ ret = __wt_buf_fmt(session, buf, "%" PRIu64 "B", size);
+
+ if (ret == 0 && exact && size >= WT_KILOBYTE)
+ ret = __wt_buf_catfmt(session, buf, " (%" PRIu64 ")", size);
+
+ if (ret != 0) {
+ buf->data = "[Error]";
+ buf->size = strlen("[Error]");
+ }
+ return (buf->data);
+}
+
+/*
* __wt_scr_alloc_func --
* Scratch buffer allocation function.
*/
diff --git a/src/support/stat.c b/src/support/stat.c
index 7514aac56c4..d972f0c140f 100644
--- a/src/support/stat.c
+++ b/src/support/stat.c
@@ -561,6 +561,8 @@ static const char * const __stats_connection_desc[] = {
"cache: eviction server unable to reach eviction goal",
"cache: eviction worker thread evicting pages",
"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: hazard pointer blocked page eviction",
"cache: hazard pointer check calls",
"cache: hazard pointer check entries walked",
@@ -575,15 +577,19 @@ static const char * const __stats_connection_desc[] = {
"cache: maximum bytes configured",
"cache: maximum page size at eviction",
"cache: modified pages evicted",
+ "cache: modified pages evicted by application threads",
"cache: page split during eviction deepened the tree",
"cache: page written requiring lookaside records",
"cache: pages currently held in the cache",
"cache: pages evicted because they exceeded the in-memory maximum",
"cache: pages evicted because they had chains of deleted items",
"cache: pages evicted by application threads",
+ "cache: pages queued for eviction",
+ "cache: pages queued for urgent eviction",
"cache: pages read into cache",
"cache: pages read into cache requiring lookaside entries",
"cache: pages requested from the cache",
+ "cache: pages seen by eviction walk",
"cache: pages selected for eviction unable to be evicted",
"cache: pages walked for eviction",
"cache: pages written from cache",
@@ -604,6 +610,7 @@ static const char * const __stats_connection_desc[] = {
"connection: pthread mutex condition wait calls",
"connection: pthread mutex shared lock read-lock calls",
"connection: pthread mutex shared lock write-lock calls",
+ "connection: total fsync I/Os",
"connection: total read I/Os",
"connection: total write I/Os",
"cursor: cursor create calls",
@@ -646,7 +653,9 @@ static const char * const __stats_connection_desc[] = {
"log: log server thread advances write LSN",
"log: log server thread write LSN walk skipped",
"log: log sync operations",
+ "log: log sync time duration (usecs)",
"log: log sync_dir operations",
+ "log: log sync_dir time duration (usecs)",
"log: log write operations",
"log: logging bytes consolidated",
"log: maximum log file size",
@@ -668,6 +677,9 @@ static const char * const __stats_connection_desc[] = {
"reconciliation: split objects currently awaiting free",
"session: open cursor count",
"session: open session count",
+ "thread-state: active filesystem fsync calls",
+ "thread-state: active filesystem read calls",
+ "thread-state: active filesystem write calls",
"thread-yield: page acquire busy blocked",
"thread-yield: page acquire eviction blocked",
"thread-yield: page acquire locked blocked",
@@ -684,6 +696,10 @@ static const char * const __stats_connection_desc[] = {
"transaction: transaction checkpoint total time (msecs)",
"transaction: transaction checkpoints",
"transaction: transaction failures due to cache overflow",
+ "transaction: transaction fsync calls for checkpoint after allocating the transaction ID",
+ "transaction: transaction fsync calls for checkpoint before allocating the transaction ID",
+ "transaction: transaction fsync duration for checkpoint after allocating the transaction ID (usecs)",
+ "transaction: transaction fsync duration for checkpoint before allocating the transaction ID (usecs)",
"transaction: transaction range of IDs currently pinned",
"transaction: transaction range of IDs currently pinned by a checkpoint",
"transaction: transaction range of IDs currently pinned by named snapshots",
@@ -767,6 +783,8 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats)
stats->cache_eviction_slow = 0;
stats->cache_eviction_worker_evicting = 0;
stats->cache_eviction_force_fail = 0;
+ /* not clearing cache_eviction_walks_active */
+ stats->cache_eviction_walks_started = 0;
stats->cache_eviction_hazard = 0;
stats->cache_hazard_checks = 0;
stats->cache_hazard_walks = 0;
@@ -781,15 +799,19 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats)
/* not clearing cache_bytes_max */
/* not clearing cache_eviction_maximum_page_size */
stats->cache_eviction_dirty = 0;
+ stats->cache_eviction_app_dirty = 0;
stats->cache_eviction_deepen = 0;
stats->cache_write_lookaside = 0;
/* not clearing cache_pages_inuse */
stats->cache_eviction_force = 0;
stats->cache_eviction_force_delete = 0;
stats->cache_eviction_app = 0;
+ stats->cache_eviction_pages_queued = 0;
+ stats->cache_eviction_pages_queued_oldest = 0;
stats->cache_read = 0;
stats->cache_read_lookaside = 0;
stats->cache_pages_requested = 0;
+ stats->cache_eviction_pages_seen = 0;
stats->cache_eviction_fail = 0;
stats->cache_eviction_walk = 0;
stats->cache_write = 0;
@@ -810,6 +832,7 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats)
stats->cond_wait = 0;
stats->rwlock_read = 0;
stats->rwlock_write = 0;
+ stats->fsync_io = 0;
stats->read_io = 0;
stats->write_io = 0;
stats->cursor_create = 0;
@@ -852,7 +875,9 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats)
stats->log_write_lsn = 0;
stats->log_write_lsn_skip = 0;
stats->log_sync = 0;
+ stats->log_sync_duration = 0;
stats->log_sync_dir = 0;
+ stats->log_sync_dir_duration = 0;
stats->log_writes = 0;
stats->log_slot_consolidated = 0;
/* not clearing log_max_filesize */
@@ -874,6 +899,9 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats)
/* not clearing rec_split_stashed_objects */
/* not clearing session_cursor_open */
/* not clearing session_open */
+ /* not clearing fsync_active */
+ /* not clearing read_active */
+ /* not clearing write_active */
stats->page_busy_blocked = 0;
stats->page_forcible_evict_blocked = 0;
stats->page_locked_blocked = 0;
@@ -890,6 +918,10 @@ __wt_stat_connection_clear_single(WT_CONNECTION_STATS *stats)
/* not clearing txn_checkpoint_time_total */
stats->txn_checkpoint = 0;
stats->txn_fail_cache = 0;
+ stats->txn_checkpoint_fsync_post = 0;
+ stats->txn_checkpoint_fsync_pre = 0;
+ stats->txn_checkpoint_fsync_post_duration = 0;
+ stats->txn_checkpoint_fsync_pre_duration = 0;
/* not clearing txn_pinned_range */
/* not clearing txn_pinned_checkpoint_range */
/* not clearing txn_pinned_snapshot_range */
@@ -978,6 +1010,10 @@ __wt_stat_connection_aggregate(
WT_STAT_READ(from, cache_eviction_worker_evicting);
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_hazard +=
WT_STAT_READ(from, cache_eviction_hazard);
to->cache_hazard_checks += WT_STAT_READ(from, cache_hazard_checks);
@@ -1001,6 +1037,8 @@ __wt_stat_connection_aggregate(
to->cache_eviction_maximum_page_size +=
WT_STAT_READ(from, cache_eviction_maximum_page_size);
to->cache_eviction_dirty += WT_STAT_READ(from, cache_eviction_dirty);
+ to->cache_eviction_app_dirty +=
+ WT_STAT_READ(from, cache_eviction_app_dirty);
to->cache_eviction_deepen +=
WT_STAT_READ(from, cache_eviction_deepen);
to->cache_write_lookaside +=
@@ -1010,10 +1048,16 @@ __wt_stat_connection_aggregate(
to->cache_eviction_force_delete +=
WT_STAT_READ(from, cache_eviction_force_delete);
to->cache_eviction_app += WT_STAT_READ(from, cache_eviction_app);
+ to->cache_eviction_pages_queued +=
+ WT_STAT_READ(from, cache_eviction_pages_queued);
+ to->cache_eviction_pages_queued_oldest +=
+ WT_STAT_READ(from, cache_eviction_pages_queued_oldest);
to->cache_read += WT_STAT_READ(from, cache_read);
to->cache_read_lookaside += WT_STAT_READ(from, cache_read_lookaside);
to->cache_pages_requested +=
WT_STAT_READ(from, cache_pages_requested);
+ to->cache_eviction_pages_seen +=
+ WT_STAT_READ(from, cache_eviction_pages_seen);
to->cache_eviction_fail += WT_STAT_READ(from, cache_eviction_fail);
to->cache_eviction_walk += WT_STAT_READ(from, cache_eviction_walk);
to->cache_write += WT_STAT_READ(from, cache_write);
@@ -1034,6 +1078,7 @@ __wt_stat_connection_aggregate(
to->cond_wait += WT_STAT_READ(from, cond_wait);
to->rwlock_read += WT_STAT_READ(from, rwlock_read);
to->rwlock_write += WT_STAT_READ(from, rwlock_write);
+ to->fsync_io += WT_STAT_READ(from, fsync_io);
to->read_io += WT_STAT_READ(from, read_io);
to->write_io += WT_STAT_READ(from, write_io);
to->cursor_create += WT_STAT_READ(from, cursor_create);
@@ -1078,7 +1123,10 @@ __wt_stat_connection_aggregate(
to->log_write_lsn += WT_STAT_READ(from, log_write_lsn);
to->log_write_lsn_skip += WT_STAT_READ(from, log_write_lsn_skip);
to->log_sync += WT_STAT_READ(from, log_sync);
+ to->log_sync_duration += WT_STAT_READ(from, log_sync_duration);
to->log_sync_dir += WT_STAT_READ(from, log_sync_dir);
+ to->log_sync_dir_duration +=
+ WT_STAT_READ(from, log_sync_dir_duration);
to->log_writes += WT_STAT_READ(from, log_writes);
to->log_slot_consolidated +=
WT_STAT_READ(from, log_slot_consolidated);
@@ -1103,6 +1151,9 @@ __wt_stat_connection_aggregate(
WT_STAT_READ(from, rec_split_stashed_objects);
to->session_cursor_open += WT_STAT_READ(from, session_cursor_open);
to->session_open += WT_STAT_READ(from, session_open);
+ to->fsync_active += WT_STAT_READ(from, fsync_active);
+ to->read_active += WT_STAT_READ(from, read_active);
+ to->write_active += WT_STAT_READ(from, write_active);
to->page_busy_blocked += WT_STAT_READ(from, page_busy_blocked);
to->page_forcible_evict_blocked +=
WT_STAT_READ(from, page_forcible_evict_blocked);
@@ -1128,6 +1179,14 @@ __wt_stat_connection_aggregate(
WT_STAT_READ(from, txn_checkpoint_time_total);
to->txn_checkpoint += WT_STAT_READ(from, txn_checkpoint);
to->txn_fail_cache += WT_STAT_READ(from, txn_fail_cache);
+ to->txn_checkpoint_fsync_post +=
+ WT_STAT_READ(from, txn_checkpoint_fsync_post);
+ to->txn_checkpoint_fsync_pre +=
+ WT_STAT_READ(from, txn_checkpoint_fsync_pre);
+ to->txn_checkpoint_fsync_post_duration +=
+ WT_STAT_READ(from, txn_checkpoint_fsync_post_duration);
+ to->txn_checkpoint_fsync_pre_duration +=
+ WT_STAT_READ(from, txn_checkpoint_fsync_pre_duration);
to->txn_pinned_range += WT_STAT_READ(from, txn_pinned_range);
to->txn_pinned_checkpoint_range +=
WT_STAT_READ(from, txn_pinned_checkpoint_range);
@@ -1139,9 +1198,11 @@ __wt_stat_connection_aggregate(
}
static const char * const __stats_join_desc[] = {
- ": accesses",
- ": actual count of items",
+ ": accesses to the main table",
": bloom filter false positives",
+ ": checks that conditions of membership are satisfied",
+ ": items inserted into a bloom filter",
+ ": items iterated",
};
int
@@ -1161,9 +1222,11 @@ __wt_stat_join_init_single(WT_JOIN_STATS *stats)
void
__wt_stat_join_clear_single(WT_JOIN_STATS *stats)
{
- stats->accesses = 0;
- stats->actual_count = 0;
+ stats->main_access = 0;
stats->bloom_false_positive = 0;
+ stats->membership_check = 0;
+ stats->bloom_insert = 0;
+ stats->iterated = 0;
}
void
@@ -1179,7 +1242,9 @@ void
__wt_stat_join_aggregate(
WT_JOIN_STATS **from, WT_JOIN_STATS *to)
{
- to->accesses += WT_STAT_READ(from, accesses);
- to->actual_count += WT_STAT_READ(from, actual_count);
+ to->main_access += WT_STAT_READ(from, main_access);
to->bloom_false_positive += WT_STAT_READ(from, bloom_false_positive);
+ to->membership_check += WT_STAT_READ(from, membership_check);
+ to->bloom_insert += WT_STAT_READ(from, bloom_insert);
+ to->iterated += WT_STAT_READ(from, iterated);
}
diff --git a/src/txn/txn.c b/src/txn/txn.c
index a2ae97fbd20..dd4384d9a9a 100644
--- a/src/txn/txn.c
+++ b/src/txn/txn.c
@@ -257,7 +257,7 @@ __txn_oldest_scan(WT_SESSION_IMPL *session,
* Sweep the running transactions to update the oldest ID required.
*/
int
-__wt_txn_update_oldest(WT_SESSION_IMPL *session, bool force)
+__wt_txn_update_oldest(WT_SESSION_IMPL *session, uint32_t flags)
{
WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
@@ -265,9 +265,12 @@ __wt_txn_update_oldest(WT_SESSION_IMPL *session, bool force)
WT_TXN_GLOBAL *txn_global;
uint64_t current_id, last_running, oldest_id;
uint64_t prev_last_running, prev_oldest_id;
+ bool strict, wait;
conn = S2C(session);
txn_global = &conn->txn_global;
+ strict = LF_ISSET(WT_TXN_OLDEST_STRICT);
+ wait = LF_ISSET(WT_TXN_OLDEST_WAIT);
current_id = last_running = txn_global->current;
prev_last_running = txn_global->last_running;
@@ -278,11 +281,11 @@ __wt_txn_update_oldest(WT_SESSION_IMPL *session, bool force)
* oldest ID isn't too far behind, avoid scanning.
*/
if (prev_oldest_id == current_id ||
- (!force && WT_TXNID_LT(current_id, prev_oldest_id + 100)))
+ (!strict && WT_TXNID_LT(current_id, prev_oldest_id + 100)))
return (0);
/* First do a read-only scan. */
- if (force)
+ if (wait)
WT_RET(__wt_readlock(session, txn_global->scan_rwlock));
else if ((ret =
__wt_try_readlock(session, txn_global->scan_rwlock)) != 0)
@@ -295,13 +298,13 @@ __wt_txn_update_oldest(WT_SESSION_IMPL *session, bool force)
* non-forced updates), give up.
*/
if ((oldest_id == prev_oldest_id ||
- (!force && WT_TXNID_LT(oldest_id, prev_oldest_id + 100))) &&
+ (!strict && WT_TXNID_LT(oldest_id, prev_oldest_id + 100))) &&
((last_running == prev_last_running) ||
- (!force && WT_TXNID_LT(last_running, prev_last_running + 100))))
+ (!strict && WT_TXNID_LT(last_running, prev_last_running + 100))))
return (0);
/* It looks like an update is necessary, wait for exclusive access. */
- if (force)
+ if (wait)
WT_RET(__wt_writelock(session, txn_global->scan_rwlock));
else if ((ret =
__wt_try_writelock(session, txn_global->scan_rwlock)) != 0)
@@ -343,6 +346,7 @@ __wt_txn_update_oldest(WT_SESSION_IMPL *session, bool force)
if (WT_TXNID_LT(txn_global->last_running, last_running)) {
txn_global->last_running = last_running;
+#ifdef HAVE_VERBOSE
/* Output a verbose message about long-running transactions,
* but only when some progress is being made. */
if (WT_VERBOSE_ISSET(session, WT_VERB_TRANSACTION) &&
@@ -355,6 +359,7 @@ __wt_txn_update_oldest(WT_SESSION_IMPL *session, bool force)
oldest_session->lastop,
oldest_session->txn.snap_min));
}
+#endif
}
done: WT_TRET(__wt_writeunlock(session, txn_global->scan_rwlock));
diff --git a/src/txn/txn_ckpt.c b/src/txn/txn_ckpt.c
index c1b435d9897..51d26b9aed6 100644
--- a/src/txn/txn_ckpt.c
+++ b/src/txn/txn_ckpt.c
@@ -350,6 +350,7 @@ __checkpoint_verbose_track(WT_SESSION_IMPL *session,
static int
__txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
{
+ struct timespec fsync_start, fsync_stop;
struct timespec start, stop, verb_timer;
WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
@@ -359,6 +360,7 @@ __txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
WT_TXN_STATE *txn_state;
void *saved_meta_next;
u_int i;
+ uint64_t fsync_duration_usecs;
bool full, idle, logging, tracking;
const char *txn_cfg[] = { WT_CONFIG_BASE(session,
WT_SESSION_begin_transaction), "isolation=snapshot", NULL };
@@ -404,7 +406,8 @@ __txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
* This is particularly important for compact, so that all dirty pages
* can be fully written.
*/
- WT_ERR(__wt_txn_update_oldest(session, true));
+ WT_ERR(__wt_txn_update_oldest(
+ session, WT_TXN_OLDEST_STRICT | WT_TXN_OLDEST_WAIT));
/* Flush data-sources before we start the checkpoint. */
WT_ERR(__checkpoint_data_source(session, cfg));
@@ -424,7 +427,13 @@ __txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
* completion. Do it after flushing the pages to give the
* asynchronous flush as much time as possible before we wait.
*/
+ WT_ERR(__wt_epoch(session, &fsync_start));
WT_ERR(__checkpoint_apply(session, cfg, __wt_checkpoint_sync));
+ WT_ERR(__wt_epoch(session, &fsync_stop));
+ fsync_duration_usecs = WT_TIMEDIFF_US(fsync_stop, fsync_start);
+ WT_STAT_FAST_CONN_INCR(session, txn_checkpoint_fsync_pre);
+ WT_STAT_FAST_CONN_INCRV(session,
+ txn_checkpoint_fsync_pre_duration, fsync_duration_usecs);
/* Tell logging that we are about to start a database checkpoint. */
if (full && logging)
@@ -523,7 +532,13 @@ __txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
* Checkpoints have to hit disk (it would be reasonable to configure for
* lazy checkpoints, but we don't support them yet).
*/
+ WT_ERR(__wt_epoch(session, &fsync_start));
WT_ERR(__checkpoint_apply(session, cfg, __wt_checkpoint_sync));
+ WT_ERR(__wt_epoch(session, &fsync_stop));
+ fsync_duration_usecs = WT_TIMEDIFF_US(fsync_stop, fsync_start);
+ WT_STAT_FAST_CONN_INCR(session, txn_checkpoint_fsync_post);
+ WT_STAT_FAST_CONN_INCRV(session,
+ txn_checkpoint_fsync_post_duration, fsync_duration_usecs);
WT_ERR(__checkpoint_verbose_track(session,
"sync completed", &verb_timer));
@@ -1284,7 +1299,8 @@ __wt_checkpoint_close(WT_SESSION_IMPL *session, bool final)
* for active readers.
*/
if (!btree->modified && !bulk) {
- WT_RET(__wt_txn_update_oldest(session, true));
+ WT_RET(__wt_txn_update_oldest(
+ session, WT_TXN_OLDEST_STRICT | WT_TXN_OLDEST_WAIT));
return (__wt_txn_visible_all(session, btree->rec_max_txn) ?
__wt_cache_op(session, WT_SYNC_DISCARD) : EBUSY);
}
diff --git a/src/txn/txn_log.c b/src/txn/txn_log.c
index da2670fb344..470515244f3 100644
--- a/src/txn/txn_log.c
+++ b/src/txn/txn_log.c
@@ -156,6 +156,7 @@ err: __wt_logrec_free(session, &logrec);
int
__wt_txn_log_op(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt)
{
+ WT_DECL_RET;
WT_ITEM *logrec;
WT_TXN *txn;
WT_TXN_OP *op;
@@ -179,24 +180,25 @@ __wt_txn_log_op(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt)
switch (op->type) {
case WT_TXN_OP_BASIC:
- return (__txn_op_log(session, logrec, op, cbt));
+ ret = __txn_op_log(session, logrec, op, cbt);
+ break;
case WT_TXN_OP_INMEM:
case WT_TXN_OP_REF:
/* Nothing to log, we're done. */
- return (0);
+ break;
case WT_TXN_OP_TRUNCATE_COL:
- return (__wt_logop_col_truncate_pack(session, logrec,
+ ret = __wt_logop_col_truncate_pack(session, logrec,
op->fileid,
- op->u.truncate_col.start, op->u.truncate_col.stop));
+ op->u.truncate_col.start, op->u.truncate_col.stop);
+ break;
case WT_TXN_OP_TRUNCATE_ROW:
- return (__wt_logop_row_truncate_pack(session, txn->logrec,
+ ret = __wt_logop_row_truncate_pack(session, txn->logrec,
op->fileid,
&op->u.truncate_row.start, &op->u.truncate_row.stop,
- (uint32_t)op->u.truncate_row.mode));
- WT_ILLEGAL_VALUE(session);
+ (uint32_t)op->u.truncate_row.mode);
+ break;
}
-
- /* NOTREACHED */
+ return (ret);
}
/*
diff --git a/src/txn/txn_recover.c b/src/txn/txn_recover.c
index 1ea4dba1152..bd004e0f837 100644
--- a/src/txn/txn_recover.c
+++ b/src/txn/txn_recover.c
@@ -424,6 +424,7 @@ __wt_txn_recover(WT_SESSION_IMPL *session)
false, WT_SESSION_NO_LOGGING, &session));
r.session = session;
+ F_SET(conn, WT_CONN_RECOVERING);
WT_ERR(__wt_metadata_search(session, WT_METAFILE_URI, &config));
WT_ERR(__recovery_setup_file(&r, WT_METAFILE_URI, config));
WT_ERR(__wt_metadata_cursor_open(session, NULL, &metac));
@@ -566,6 +567,7 @@ err: WT_TRET(__recovery_free(&r));
WT_TRET(__wt_evict_destroy(session));
WT_TRET(session->iface.close(&session->iface, NULL));
+ F_CLR(conn, WT_CONN_RECOVERING);
return (ret);
}
diff --git a/src/utilities/util_dump.c b/src/utilities/util_dump.c
index 3314b5ba485..da70aea35be 100644
--- a/src/utilities/util_dump.c
+++ b/src/utilities/util_dump.c
@@ -552,14 +552,15 @@ dup_json_string(const char *str, char **result)
nchars = 0;
for (p = str; *p; p++, nchars++)
- nchars += __wt_json_unpack_char(*p, NULL, 0, false);
+ nchars += __wt_json_unpack_char((u_char)*p, NULL, 0, false);
q = malloc(nchars + 1);
if (q == NULL)
return (1);
*result = q;
left = nchars;
for (p = str; *p; p++, nchars++) {
- nchars = __wt_json_unpack_char(*p, (u_char *)q, left, false);
+ nchars = __wt_json_unpack_char((u_char)*p, (u_char *)q, left,
+ false);
left -= nchars;
q += nchars;
}
diff --git a/src/utilities/util_load.c b/src/utilities/util_load.c
index a81d06c6866..ac18df80851 100644
--- a/src/utilities/util_load.c
+++ b/src/utilities/util_load.c
@@ -211,6 +211,8 @@ config_list_free(CONFIG_LIST *clp)
free(*entry);
free(clp->list);
clp->list = NULL;
+ clp->entry = 0;
+ clp->max_entry = 0;
}
/*
diff --git a/src/utilities/util_load_json.c b/src/utilities/util_load_json.c
index f1f6675e99c..020a4ed9ba9 100644
--- a/src/utilities/util_load_json.c
+++ b/src/utilities/util_load_json.c
@@ -248,7 +248,7 @@ json_data(WT_SESSION *session,
keyformat = cursor->key_format;
isrec = strcmp(keyformat, "r") == 0;
for (nkeys = 0; *keyformat; keyformat++)
- if (!isdigit(*keyformat))
+ if (!__wt_isdigit((u_char)*keyformat))
nkeys++;
recno = 0;
@@ -427,6 +427,9 @@ json_top_level(WT_SESSION *session, JSON_INPUT_STATE *ins, uint32_t flags)
flags)) != 0)
goto err;
config_list_free(&cl);
+ free(ins->kvraw);
+ ins->kvraw = NULL;
+ config_list_free(&cl);
break;
}
else
@@ -468,7 +471,7 @@ json_peek(WT_SESSION *session, JSON_INPUT_STATE *ins)
if (!ins->peeking) {
while (!ins->ateof) {
- while (isspace(*ins->p))
+ while (__wt_isspace((u_char)*ins->p))
ins->p++;
if (*ins->p)
break;
@@ -544,15 +547,14 @@ json_skip(WT_SESSION *session, JSON_INPUT_STATE *ins, const char **matches)
const char *hit;
const char **match;
- if (ins->kvraw != NULL)
- return (1);
-
+ WT_ASSERT((WT_SESSION_IMPL *)session, ins->kvraw == NULL);
hit = NULL;
while (!ins->ateof) {
for (match = matches; *match != NULL; match++)
if ((hit = strstr(ins->p, *match)) != NULL)
goto out;
- if (util_read_line(session, &ins->line, true, &ins->ateof)) {
+ if (util_read_line(session, &ins->line, true, &ins->ateof)
+ != 0) {
ins->toktype = -1;
return (1);
}
diff --git a/src/utilities/util_misc.c b/src/utilities/util_misc.c
index f45f6b339f2..3c4e8d2dfa1 100644
--- a/src/utilities/util_misc.c
+++ b/src/utilities/util_misc.c
@@ -108,7 +108,7 @@ util_str2recno(WT_SESSION *session, const char *p, uint64_t *recnop)
* forth -- none of them are OK with us. Check the string starts with
* digit, that turns off the special processing.
*/
- if (!isdigit(p[0]))
+ if (!__wt_isdigit((u_char)p[0]))
goto format;
errno = 0;
diff --git a/src/utilities/util_verify.c b/src/utilities/util_verify.c
index 2df4fa65f43..82bdd780cd3 100644
--- a/src/utilities/util_verify.c
+++ b/src/utilities/util_verify.c
@@ -16,10 +16,10 @@ util_verify(WT_SESSION *session, int argc, char *argv[])
WT_DECL_RET;
size_t size;
int ch;
- bool dump_address, dump_blocks, dump_pages, dump_shape;
+ bool dump_address, dump_blocks, dump_layout, dump_pages;
char *config, *dump_offsets, *name;
- dump_address = dump_blocks = dump_pages = dump_shape = false;
+ dump_address = dump_blocks = dump_layout = dump_pages = false;
config = dump_offsets = name = NULL;
while ((ch = __wt_getopt(progname, argc, argv, "d:")) != EOF)
switch (ch) {
@@ -28,6 +28,8 @@ util_verify(WT_SESSION *session, int argc, char *argv[])
dump_address = true;
else if (strcmp(__wt_optarg, "dump_blocks") == 0)
dump_blocks = true;
+ else if (strcmp(__wt_optarg, "dump_layout") == 0)
+ dump_layout = true;
else if (
WT_PREFIX_MATCH(__wt_optarg, "dump_offsets=")) {
if (dump_offsets != NULL) {
@@ -40,8 +42,6 @@ util_verify(WT_SESSION *session, int argc, char *argv[])
__wt_optarg + strlen("dump_offsets=");
} else if (strcmp(__wt_optarg, "dump_pages") == 0)
dump_pages = true;
- else if (strcmp(__wt_optarg, "dump_shape") == 0)
- dump_shape = true;
else
return (usage());
break;
@@ -60,12 +60,12 @@ util_verify(WT_SESSION *session, int argc, char *argv[])
/* Build the configuration string as necessary. */
if (dump_address ||
- dump_blocks || dump_offsets != NULL || dump_pages || dump_shape) {
+ dump_blocks || dump_layout || dump_offsets != NULL || dump_pages) {
size =
strlen("dump_address,") +
strlen("dump_blocks,") +
+ strlen("dump_layout,") +
strlen("dump_pages,") +
- strlen("dump_shape,") +
strlen("dump_offsets[],") +
(dump_offsets == NULL ? 0 : strlen(dump_offsets)) + 20;
if ((config = malloc(size)) == NULL) {
@@ -76,11 +76,11 @@ util_verify(WT_SESSION *session, int argc, char *argv[])
"%s%s%s%s%s%s%s",
dump_address ? "dump_address," : "",
dump_blocks ? "dump_blocks," : "",
+ dump_layout ? "dump_layout," : "",
dump_offsets != NULL ? "dump_offsets=[" : "",
dump_offsets != NULL ? dump_offsets : "",
dump_offsets != NULL ? "]," : "",
- dump_pages ? "dump_pages," : "",
- dump_shape ? "dump_shape," : "");
+ dump_pages ? "dump_pages," : "");
}
if ((ret = session->verify(session, name, config)) != 0) {
fprintf(stderr, "%s: verify(%s): %s\n",
@@ -109,7 +109,7 @@ usage(void)
"usage: %s %s "
"verify %s\n",
progname, usage_prefix,
- "[-d dump_address | dump_blocks | "
- "dump_offsets=#,# | dump_pages | dump_shape] uri");
+ "[-d dump_address | dump_blocks | dump_layout | "
+ "dump_offsets=#,# | dump_pages] uri");
return (1);
}