diff options
Diffstat (limited to 'src')
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{ 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{ prealloc, * pre-allocate log files., a boolean flag; default \c true.} * @config{ recover, run recovery or error if @@ -2344,7 +2345,7 @@ struct __wt_connection { * integer between 100KB and 2GB; default \c 100MB.} * @config{ 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{ prealloc, pre-allocate log files., a boolean * flag; default \c true.} * @config{ 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); } |