diff options
author | Michael Cahill <michael.cahill@mongodb.com> | 2015-09-11 12:08:12 +1000 |
---|---|---|
committer | Michael Cahill <michael.cahill@mongodb.com> | 2015-09-28 16:35:18 +1000 |
commit | 8e212cf8907a5d2462dead47aebcce074dd3c066 (patch) | |
tree | f25d5eba63c16a964a73f5e4168d54466f816125 | |
parent | 3489b0bec18adcf574b274dad4b390182deb7c13 (diff) | |
download | mongo-8e212cf8907a5d2462dead47aebcce074dd3c066.tar.gz |
WT-2093 Use the C99 bool type to clarify when functions return true/false
Merge pull request #2178 from wiredtiger/use-bool
(cherry picked from commit d9391c0df4dc38c8ea571bde4808ced194d7cff0)
38 files changed, 341 insertions, 680 deletions
diff --git a/dist/s_define.list b/dist/s_define.list index 65fc60e9c7a..91c703e66e8 100644 --- a/dist/s_define.list +++ b/dist/s_define.list @@ -12,7 +12,6 @@ LF_SET LLONG_MAX LLONG_MIN SIZE_CHECK -TXNID_LE TXN_API_CALL TXN_API_CALL_NOCONF TXN_API_END diff --git a/src/block/block_ext.c b/src/block/block_ext.c index d593537446b..b368856bc1d 100644 --- a/src/block/block_ext.c +++ b/src/block/block_ext.c @@ -86,7 +86,7 @@ __block_off_srch(WT_EXT **head, wt_off_t off, WT_EXT ***stack, int skip_off) * __block_first_srch -- * Search the skiplist for the first available slot. */ -static inline int +static inline bool __block_first_srch(WT_EXT **head, wt_off_t size, WT_EXT ***stack) { WT_EXT *ext; @@ -99,11 +99,11 @@ __block_first_srch(WT_EXT **head, wt_off_t size, WT_EXT ***stack) if (ext->size >= size) break; if (ext == NULL) - return (0); + return (false); /* Build a stack for the offset we want. */ __block_off_srch(head, ext->off, stack, 0); - return (1); + return (true); } /* @@ -251,7 +251,7 @@ __block_off_insert( * Return if any part of a specified range appears on a specified extent * list. */ -static int +static bool __block_off_match(WT_EXTLIST *el, wt_off_t off, wt_off_t size) { WT_EXT *before, *after; @@ -261,10 +261,10 @@ __block_off_match(WT_EXTLIST *el, wt_off_t off, wt_off_t size) /* If "before" or "after" overlaps, we have a winner. */ if (before != NULL && before->off + before->size > off) - return (1); + return (true); if (after != NULL && off + size > after->off) - return (1); - return (0); + return (true); + return (false); } /* diff --git a/src/block/block_slvg.c b/src/block/block_slvg.c index c78a6c39942..641bb8a42f7 100644 --- a/src/block/block_slvg.c +++ b/src/block/block_slvg.c @@ -73,19 +73,19 @@ __wt_block_salvage_end(WT_SESSION_IMPL *session, WT_BLOCK *block) * __wt_block_offset_invalid -- * Return if the block offset is insane. */ -int +bool __wt_block_offset_invalid(WT_BLOCK *block, wt_off_t offset, uint32_t size) { if (size == 0) /* < minimum page size */ - return (1); + return (true); if (size % block->allocsize != 0) /* not allocation-size units */ - return (1); + return (true); if (size > WT_BTREE_PAGE_SIZE_MAX) /* > maximum page size */ - return (1); + return (true); /* past end-of-file */ if (offset + (wt_off_t)size > block->fh->size) - return (1); - return (0); + return (true); + return (false); } /* diff --git a/src/btree/bt_cursor.c b/src/btree/bt_cursor.c index 8409b0cd6a2..2f907d978bd 100644 --- a/src/btree/bt_cursor.c +++ b/src/btree/bt_cursor.c @@ -70,7 +70,7 @@ __cursor_fix_implicit(WT_BTREE *btree, WT_CURSOR_BTREE *cbt) * __cursor_valid -- * Return if the cursor references an valid key/value pair. */ -static inline int +static inline bool __cursor_valid(WT_CURSOR_BTREE *cbt, WT_UPDATE **updp) { WT_BTREE *btree; @@ -133,10 +133,10 @@ __cursor_valid(WT_CURSOR_BTREE *cbt, WT_UPDATE **updp) if (cbt->ins != NULL && (upd = __wt_txn_read(session, cbt->ins->upd)) != NULL) { if (WT_UPDATE_DELETED_ISSET(upd)) - return (0); + return (false); if (updp != NULL) *updp = upd; - return (1); + return (true); } /* @@ -155,7 +155,7 @@ __cursor_valid(WT_CURSOR_BTREE *cbt, WT_UPDATE **updp) * keys, check for retrieval past the end of the page. */ if (cbt->recno >= page->pg_fix_recno + page->pg_fix_entries) - return (0); + return (false); /* * Updates aren't stored on the page, an update would have @@ -170,7 +170,7 @@ __cursor_valid(WT_CURSOR_BTREE *cbt, WT_UPDATE **updp) * "slots", check if search returned a valid slot. */ if (cbt->slot >= page->pg_var_entries) - return (0); + return (false); /* * Updates aren't stored on the page, an update would have @@ -181,7 +181,7 @@ __cursor_valid(WT_CURSOR_BTREE *cbt, WT_UPDATE **updp) cip = &page->pg_var_d[cbt->slot]; if ((cell = WT_COL_PTR(page, cip)) == NULL || __wt_cell_type(cell) == WT_CELL_DEL) - return (0); + return (false); break; case BTREE_ROW: /* @@ -189,7 +189,7 @@ __cursor_valid(WT_CURSOR_BTREE *cbt, WT_UPDATE **updp) * key as an on-page object, we're done. */ if (cbt->ins != NULL) - return (0); + return (false); /* * Check if searched returned a valid slot (the failure mode is @@ -198,19 +198,19 @@ __cursor_valid(WT_CURSOR_BTREE *cbt, WT_UPDATE **updp) * mirrors the column-store test). */ if (cbt->slot >= page->pg_row_entries) - return (0); + return (false); /* Updates are stored on the page, check for a delete. */ if (page->pg_row_upd != NULL && (upd = __wt_txn_read( session, page->pg_row_upd[cbt->slot])) != NULL) { if (WT_UPDATE_DELETED_ISSET(upd)) - return (0); + return (false); if (updp != NULL) *updp = upd; } break; } - return (1); + return (true); } /* @@ -842,7 +842,7 @@ __wt_btcur_compare(WT_CURSOR_BTREE *a_arg, WT_CURSOR_BTREE *b_arg, int *cmpp) * __cursor_equals -- * Return if two cursors reference the same row. */ -static inline int +static inline bool __cursor_equals(WT_CURSOR_BTREE *a, WT_CURSOR_BTREE *b) { switch (a->btree->type) { @@ -854,21 +854,21 @@ __cursor_equals(WT_CURSOR_BTREE *a, WT_CURSOR_BTREE *b) * one being returned to the application. */ if (((WT_CURSOR *)a)->recno == ((WT_CURSOR *)b)->recno) - return (1); + return (true); break; case BTREE_ROW: if (a->ref != b->ref) - return (0); + return (false); if (a->ins != NULL || b->ins != NULL) { if (a->ins == b->ins) - return (1); + return (true); break; } if (a->slot == b->slot) - return (1); + return (true); break; } - return (0); + return (false); } /* diff --git a/src/btree/bt_delete.c b/src/btree/bt_delete.c index cddfa0ef801..3cf581dcfd2 100644 --- a/src/btree/bt_delete.c +++ b/src/btree/bt_delete.c @@ -216,10 +216,10 @@ __wt_delete_page_rollback(WT_SESSION_IMPL *session, WT_REF *ref) * __wt_delete_page_skip -- * If iterating a cursor, skip deleted pages that are visible to us. */ -int +bool __wt_delete_page_skip(WT_SESSION_IMPL *session, WT_REF *ref) { - int skip; + bool skip; /* * Deleted pages come from two sources: either it's a fast-delete as @@ -240,10 +240,10 @@ __wt_delete_page_skip(WT_SESSION_IMPL *session, WT_REF *ref) * the structure, just to be safe. */ if (ref->page_del == NULL) - return (1); + return (true); if (!__wt_atomic_casv32(&ref->state, WT_REF_DELETED, WT_REF_LOCKED)) - return (0); + return (false); skip = (ref->page_del == NULL || __wt_txn_visible(session, ref->page_del->txnid)); diff --git a/src/btree/bt_ovfl.c b/src/btree/bt_ovfl.c index d8456c5b61f..7104e702418 100644 --- a/src/btree/bt_ovfl.c +++ b/src/btree/bt_ovfl.c @@ -79,7 +79,7 @@ __wt_ovfl_read(WT_SESSION_IMPL *session, * __ovfl_cache_col_visible -- * column-store: check for a globally visible update. */ -static int +static bool __ovfl_cache_col_visible( WT_SESSION_IMPL *session, WT_UPDATE *upd, WT_CELL_UNPACK *unpack) { @@ -99,15 +99,15 @@ __ovfl_cache_col_visible( if (__wt_cell_rle(unpack) == 1 && upd != NULL && /* Sanity: upd should always be set. */ __wt_txn_visible_all(session, upd->txnid)) - return (1); - return (0); + return (true); + return (false); } /* * __ovfl_cache_row_visible -- * row-store: check for a globally visible update. */ -static int +static bool __ovfl_cache_row_visible(WT_SESSION_IMPL *session, WT_PAGE *page, WT_ROW *rip) { WT_UPDATE *upd; @@ -115,9 +115,9 @@ __ovfl_cache_row_visible(WT_SESSION_IMPL *session, WT_PAGE *page, WT_ROW *rip) /* Check to see if there's a globally visible update. */ for (upd = WT_ROW_UPDATE(page, rip); upd != NULL; upd = upd->next) if (__wt_txn_visible_all(session, upd->txnid)) - return (1); + return (true); - return (0); + return (false); } /* diff --git a/src/btree/bt_page.c b/src/btree/bt_page.c index 3ae3ee23e58..9d84a76132e 100644 --- a/src/btree/bt_page.c +++ b/src/btree/bt_page.c @@ -53,7 +53,7 @@ __evict_force_check(WT_SESSION_IMPL *session, WT_PAGE *page, uint32_t flags) __wt_txn_update_oldest(session, 0); /* If eviction cannot succeed, don't try. */ - return (__wt_page_can_evict(session, page, 1)); + return (__wt_page_can_evict(session, page, 1, NULL)); } /* diff --git a/src/btree/bt_split.c b/src/btree/bt_split.c index 98102b76398..4661212c05e 100644 --- a/src/btree/bt_split.c +++ b/src/btree/bt_split.c @@ -166,7 +166,7 @@ __split_safe_free(WT_SESSION_IMPL *session, * __split_should_deepen -- * Return if we should deepen the tree. */ -static int +static bool __split_should_deepen( WT_SESSION_IMPL *session, WT_REF *ref, uint32_t *childrenp) { @@ -186,7 +186,7 @@ __split_should_deepen( * pressure on the cache). */ if (page->memory_footprint < btree->maxmempage) - return (0); + return (false); /* * Ensure the page has enough entries to make it worth splitting and @@ -195,7 +195,7 @@ __split_should_deepen( */ if (pindex->entries > btree->split_deepen_min_child) { *childrenp = pindex->entries / btree->split_deepen_per_child; - return (1); + return (true); } /* @@ -209,10 +209,10 @@ __split_should_deepen( (__wt_ref_is_root(ref) || page->memory_footprint >= S2C(session)->cache_size / 4)) { *childrenp = pindex->entries / 10; - return (1); + return (true); } - return (0); + return (false); } /* @@ -1068,7 +1068,6 @@ err: if (!complete) int __wt_split_insert(WT_SESSION_IMPL *session, WT_REF *ref, int *splitp) { - WT_BTREE *btree; WT_DECL_RET; WT_DECL_ITEM(key); WT_INSERT *ins, **insp, *moved_ins, *prev_ins; @@ -1080,61 +1079,28 @@ __wt_split_insert(WT_SESSION_IMPL *session, WT_REF *ref, int *splitp) *splitp = 0; - btree = S2BT(session); page = ref->page; right = NULL; page_decr = parent_incr = right_incr = 0; - /* - * Check for pages with append-only workloads. A common application - * pattern is to have multiple threads frantically appending to the - * tree. We want to reconcile and evict this page, but we'd like to - * do it without making the appending threads wait. If we're not - * discarding the tree, check and see if it's worth doing a split to - * let the threads continue before doing eviction. - * - * Ignore anything other than large, dirty row-store leaf pages. - * - * XXX KEITH - * Need a better test for append-only workloads. - */ - if (page->type != WT_PAGE_ROW_LEAF || - page->memory_footprint < btree->maxmempage || - !__wt_page_is_modified(page)) - return (0); + /* + * Assert splitting makes sense; specifically assert the page is dirty, + * we depend on that, otherwise the page might be evicted based on its + * last reconciliation which no longer matches reality after the split. + * + * Note this page has already been through an in-memory split. + */ + WT_ASSERT(session, __wt_page_can_split(session, page)); + WT_ASSERT(session, __wt_page_is_modified(page)); + F_SET_ATOMIC(page, WT_PAGE_SPLIT_INSERT); - /* - * There is no point splitting if the list is small, no deep items is - * our heuristic for that. (A 1/4 probability of adding a new skiplist - * level means there will be a new 6th level for roughly each 4KB of - * entries in the list. If we have at least two 6th level entries, the - * list is at least large enough to work with.) - * - * The following code requires at least two items on the insert list, - * this test serves the additional purpose of confirming that. - */ -#define WT_MIN_SPLIT_SKIPLIST_DEPTH WT_MIN(6, WT_SKIP_MAXDEPTH - 1) + /* Find the last item in the insert list. */ ins_head = page->pg_row_entries == 0 ? WT_ROW_INSERT_SMALLEST(page) : WT_ROW_INSERT_SLOT(page, page->pg_row_entries - 1); - if (ins_head == NULL || - ins_head->head[WT_MIN_SPLIT_SKIPLIST_DEPTH] == NULL || - ins_head->head[WT_MIN_SPLIT_SKIPLIST_DEPTH] == - ins_head->tail[WT_MIN_SPLIT_SKIPLIST_DEPTH]) - return (0); - - /* Find the last item in the insert list. */ moved_ins = WT_SKIP_LAST(ins_head); /* - * Only split a page once, otherwise workloads that update in the middle - * of the page could continually split without benefit. - */ - if (F_ISSET_ATOMIC(page, WT_PAGE_SPLIT_INSERT)) - return (0); - F_SET_ATOMIC(page, WT_PAGE_SPLIT_INSERT); - - /* * The first page in the split is the current page, but we still have * to create a replacement WT_REF, the original WT_REF will be set to * split status and eventually freed. diff --git a/src/btree/bt_sync.c b/src/btree/bt_sync.c index 0650f26e5e9..1b5c182577b 100644 --- a/src/btree/bt_sync.c +++ b/src/btree/bt_sync.c @@ -117,7 +117,7 @@ __sync_file(WT_SESSION_IMPL *session, int syncop) */ if (walk != NULL && walk->page != NULL && (mod = walk->page->modify) != NULL && - TXNID_LT(btree->rec_max_txn, mod->rec_max_txn)) + WT_TXNID_LT(btree->rec_max_txn, mod->rec_max_txn)) btree->rec_max_txn = mod->rec_max_txn; WT_ERR(__wt_tree_walk(session, &walk, NULL, flags)); @@ -149,8 +149,8 @@ __sync_file(WT_SESSION_IMPL *session, int syncop) * is written. */ if (!WT_PAGE_IS_INTERNAL(page) && - F_ISSET(txn, TXN_HAS_SNAPSHOT) && - TXNID_LT(txn->snap_max, mod->first_dirty_txn) && + F_ISSET(txn, WT_TXN_HAS_SNAPSHOT) && + WT_TXNID_LT(txn->snap_max, mod->first_dirty_txn) && !F_ISSET(mod, WT_PM_REC_REWRITE)) { __wt_page_modify_set(session, page); continue; diff --git a/src/conn/conn_api.c b/src/conn/conn_api.c index dacbb0539a9..98ff56290be 100644 --- a/src/conn/conn_api.c +++ b/src/conn/conn_api.c @@ -814,7 +814,7 @@ err: /* */ for (s = conn->sessions, i = 0; i < conn->session_cnt; ++s, ++i) if (s->active && !F_ISSET(s, WT_SESSION_INTERNAL) && - F_ISSET(&s->txn, TXN_RUNNING)) { + F_ISSET(&s->txn, WT_TXN_RUNNING)) { wt_session = &s->iface; WT_TRET(wt_session->rollback_transaction( wt_session, NULL)); diff --git a/src/evict/evict_lru.c b/src/evict/evict_lru.c index f077f168a26..1f8260e54e1 100644 --- a/src/evict/evict_lru.c +++ b/src/evict/evict_lru.c @@ -422,9 +422,6 @@ __evict_has_work(WT_SESSION_IMPL *session, uint32_t *flagsp) flags = 0; *flagsp = 0; - if (!F_ISSET(conn, WT_CONN_EVICTION_RUN)) - return (0); - /* * Figure out whether the cache usage exceeds either the eviction * target or the dirty target. @@ -709,8 +706,8 @@ __wt_evict_page(WT_SESSION_IMPL *session, WT_REF *ref) * Sanity check: if a transaction has updates, its updates should not * be visible to eviction. */ - WT_ASSERT(session, - !F_ISSET(txn, TXN_HAS_ID) || !__wt_txn_visible(session, txn->id)); + WT_ASSERT(session, !F_ISSET(txn, WT_TXN_HAS_ID) || + !__wt_txn_visible(session, txn->id)); ret = __wt_evict(session, ref, 0); txn->isolation = saved_iso; @@ -1239,7 +1236,7 @@ __evict_walk_file(WT_SESSION_IMPL *session, u_int *slotp, uint32_t flags) page->read_gen = __wt_cache_read_gen_new(session); fast: /* If the page can't be evicted, give up. */ - if (!__wt_page_can_evict(session, page, 1)) + if (!__wt_page_can_evict(session, page, 1, NULL)) continue; /* diff --git a/src/evict/evict_page.c b/src/evict/evict_page.c index fe08916b24c..9fb6c5e396a 100644 --- a/src/evict/evict_page.c +++ b/src/evict/evict_page.c @@ -314,23 +314,32 @@ __evict_review( } /* Check if the page can be evicted. */ - if (!exclusive && !__wt_page_can_evict(session, page, 0)) - return (EBUSY); - - /* - * Check for an append-only workload needing an in-memory split. - * - * We can't do this earlier because in-memory splits require exclusive - * access, and we can't split if a checkpoint is in progress because - * the checkpoint could be walking the parent page. - * - * If an in-memory split completes, the page stays in memory and the - * tree is left in the desired state: avoid the usual cleanup. - */ if (!exclusive) { - WT_RET(__wt_split_insert(session, ref, inmem_splitp)); + /* + * Update the oldest ID to avoid wasted effort should it have + * fallen behind current. + */ + if (__wt_page_is_modified(page)) + __wt_txn_update_oldest(session, true); + + if (!__wt_page_can_evict(session, page, 0, inmem_splitp)) + return (EBUSY); + + /* + * Check for an append-only workload needing an in-memory + * split. + * + * We can't do this earlier because in-memory splits require + * exclusive access, and we can't split if a checkpoint is in + * progress because the checkpoint could be walking the parent + * page. + * + * If an in-memory split completes, the page stays in memory + * and the tree is left in the desired state: avoid the usual + * cleanup. + */ if (*inmem_splitp) - return (0); + return (__wt_split_insert(session, ref, inmem_splitp)); } /* diff --git a/src/include/api.h b/src/include/api.h index 70068e32b9b..eda5d327295 100644 --- a/src/include/api.h +++ b/src/include/api.h @@ -33,11 +33,11 @@ if ((s) != NULL) { \ (s)->dhandle = __olddh; \ (s)->name = __oldname; \ - if (F_ISSET(&(s)->txn, TXN_RUNNING) && \ + if (F_ISSET(&(s)->txn, WT_TXN_RUNNING) && \ (ret) != 0 && \ (ret) != WT_NOTFOUND && \ (ret) != WT_DUPLICATE_KEY) \ - F_SET(&(s)->txn, TXN_ERROR); \ + F_SET(&(s)->txn, WT_TXN_ERROR); \ } \ } while (0) @@ -45,25 +45,25 @@ #define TXN_API_CALL(s, h, n, cur, bt, config, cfg) do { \ int __autotxn = 0; \ API_CALL(s, h, n, bt, cur, config, cfg); \ - __autotxn = !F_ISSET(&(s)->txn, TXN_AUTOCOMMIT | TXN_RUNNING); \ + __autotxn = !F_ISSET(&(s)->txn, WT_TXN_AUTOCOMMIT | WT_TXN_RUNNING);\ if (__autotxn) \ - F_SET(&(s)->txn, TXN_AUTOCOMMIT) + F_SET(&(s)->txn, WT_TXN_AUTOCOMMIT) /* An API call wrapped in a transaction if necessary. */ #define TXN_API_CALL_NOCONF(s, h, n, cur, bt) do { \ int __autotxn = 0; \ API_CALL_NOCONF(s, h, n, cur, bt); \ - __autotxn = !F_ISSET(&(s)->txn, TXN_AUTOCOMMIT | TXN_RUNNING); \ + __autotxn = !F_ISSET(&(s)->txn, WT_TXN_AUTOCOMMIT | WT_TXN_RUNNING);\ if (__autotxn) \ - F_SET(&(s)->txn, TXN_AUTOCOMMIT) + F_SET(&(s)->txn, WT_TXN_AUTOCOMMIT) /* End a transactional API call, optional retry on deadlock. */ #define TXN_API_END_RETRY(s, ret, retry) \ API_END(s, ret); \ if (__autotxn) { \ - if (F_ISSET(&(s)->txn, TXN_AUTOCOMMIT)) \ - F_CLR(&(s)->txn, TXN_AUTOCOMMIT); \ - else if (ret == 0 && !F_ISSET(&(s)->txn, TXN_ERROR)) \ + if (F_ISSET(&(s)->txn, WT_TXN_AUTOCOMMIT)) \ + F_CLR(&(s)->txn, WT_TXN_AUTOCOMMIT); \ + else if (ret == 0 && !F_ISSET(&(s)->txn, WT_TXN_ERROR)) \ ret = __wt_txn_commit((s), NULL); \ else { \ WT_TRET(__wt_txn_rollback((s), NULL)); \ diff --git a/src/include/bitstring.i b/src/include/bitstring.i index c548c12761d..5449ffe6209 100644 --- a/src/include/bitstring.i +++ b/src/include/bitstring.i @@ -84,10 +84,10 @@ __bit_alloc(WT_SESSION_IMPL *session, uint64_t nbits, void *retp) * __bit_test -- * Test one bit in name. */ -static inline int +static inline bool __bit_test(uint8_t *bitf, uint64_t bit) { - return (bitf[__bit_byte(bit)] & __bit_mask(bit) ? 1 : 0); + return ((bitf[__bit_byte(bit)] & __bit_mask(bit)) != 0); } /* diff --git a/src/include/btree.i b/src/include/btree.i index 5db6ff1f002..2eae1c5e1f4 100644 --- a/src/include/btree.i +++ b/src/include/btree.i @@ -10,17 +10,17 @@ * __wt_ref_is_root -- * Return if the page reference is for the root page. */ -static inline int +static inline bool __wt_ref_is_root(WT_REF *ref) { - return (ref->home == NULL ? 1 : 0); + return (ref->home == NULL); } /* * __wt_page_is_empty -- * Return if the page is empty. */ -static inline int +static inline bool __wt_page_is_empty(WT_PAGE *page) { return (page->modify != NULL && @@ -31,10 +31,10 @@ __wt_page_is_empty(WT_PAGE *page) * __wt_page_is_modified -- * Return if the page is dirty. */ -static inline int +static inline bool __wt_page_is_modified(WT_PAGE *page) { - return (page->modify != NULL && page->modify->write_gen != 0 ? 1 : 0); + return (page->modify != NULL && page->modify->write_gen != 0); } /* @@ -350,7 +350,7 @@ __wt_page_only_modify_set(WT_SESSION_IMPL *session, WT_PAGE *page) * The page can never end up with changes older than the oldest * running transaction. */ - if (F_ISSET(&session->txn, TXN_HAS_SNAPSHOT)) + if (F_ISSET(&session->txn, WT_TXN_HAS_SNAPSHOT)) page->modify->disk_snap_min = session->txn.snap_min; /* @@ -367,7 +367,7 @@ __wt_page_only_modify_set(WT_SESSION_IMPL *session, WT_PAGE *page) } /* Check if this is the largest transaction ID to update the page. */ - if (TXNID_LT(page->modify->update_txn, session->txn.id)) + if (WT_TXNID_LT(page->modify->update_txn, session->txn.id)) page->modify->update_txn = session->txn.id; } @@ -432,7 +432,7 @@ __wt_page_parent_modify_set( * __wt_off_page -- * Return if a pointer references off-page data. */ -static inline int +static inline bool __wt_off_page(WT_PAGE *page, const void *p) { /* @@ -543,7 +543,7 @@ __wt_ref_key_clear(WT_REF *ref) * had without unpacking a cell, and information about the cell, if the key * isn't cheaply available. */ -static inline int +static inline bool __wt_row_leaf_key_info(WT_PAGE *page, void *copy, WT_IKEY **ikeyp, WT_CELL **cellp, void *datap, size_t *sizep) { @@ -634,7 +634,7 @@ __wt_row_leaf_key_info(WT_PAGE *page, void *copy, if (cellp != NULL) *cellp = WT_PAGE_REF_OFFSET(page, WT_CELL_DECODE_OFFSET(v)); - return (0); + return (false); case WT_K_FLAG: /* Encoded key: no instantiated key, no cell. */ if (cellp != NULL) @@ -645,9 +645,9 @@ __wt_row_leaf_key_info(WT_PAGE *page, void *copy, *(void **)datap = WT_PAGE_REF_OFFSET(page, WT_K_DECODE_KEY_OFFSET(v)); *sizep = WT_K_DECODE_KEY_LEN(v); - return (1); + return (true); } - return (0); + return (false); case WT_KV_FLAG: /* Encoded key/value pair: no instantiated key, no cell. */ if (cellp != NULL) @@ -658,9 +658,9 @@ __wt_row_leaf_key_info(WT_PAGE *page, void *copy, *(void **)datap = WT_PAGE_REF_OFFSET( page, WT_KV_DECODE_KEY_OFFSET(v)); *sizep = WT_KV_DECODE_KEY_LEN(v); - return (1); + return (true); } - return (0); + return (false); } @@ -673,9 +673,9 @@ __wt_row_leaf_key_info(WT_PAGE *page, void *copy, if (datap != NULL) { *(void **)datap = WT_IKEY_DATA(ikey); *sizep = ikey->size; - return (1); + return (true); } - return (0); + return (false); } /* @@ -863,7 +863,7 @@ __wt_row_leaf_value_cell(WT_PAGE *page, WT_ROW *rip, WT_CELL_UNPACK *kpack) * __wt_row_leaf_value -- * Return the value for a row-store leaf page encoded key/value pair. */ -static inline int +static inline bool __wt_row_leaf_value(WT_PAGE *page, WT_ROW *rip, WT_ITEM *value) { uintptr_t v; @@ -879,9 +879,9 @@ __wt_row_leaf_value(WT_PAGE *page, WT_ROW *rip, WT_ITEM *value) value->data = WT_PAGE_REF_OFFSET(page, WT_KV_DECODE_VALUE_OFFSET(v)); value->size = WT_KV_DECODE_VALUE_LEN(v); - return (1); + return (true); } - return (0); + return (false); } /* @@ -937,21 +937,94 @@ __wt_ref_info(WT_SESSION_IMPL *session, } /* + * __wt_page_can_split -- + * Check whether a page can be split in memory. + */ +static inline bool +__wt_page_can_split(WT_SESSION_IMPL *session, WT_PAGE *page) +{ + WT_BTREE *btree; + WT_INSERT_HEAD *ins_head; + WT_INSERT *ins; + int i; + + btree = S2BT(session); + + /* + * Only split a page once, otherwise workloads that update in the middle + * of the page could continually split without benefit. + */ + if (F_ISSET_ATOMIC(page, WT_PAGE_SPLIT_INSERT)) + return (false); + + /* + * Check for pages with append-only workloads. A common application + * pattern is to have multiple threads frantically appending to the + * tree. We want to reconcile and evict this page, but we'd like to + * do it without making the appending threads wait. See if it's worth + * doing a split to let the threads continue before doing eviction. + * + * Ignore anything other than large, dirty row-store leaf pages. The + * split code only supports row-store pages, and we depend on the page + * being dirty for correctness (the page must be reconciled again + * before being evicted after the split, information from a previous + * reconciliation will be wrong, so we can't evict immediately). + */ + if (page->type != WT_PAGE_ROW_LEAF || + page->memory_footprint < btree->maxmempage || + !__wt_page_is_modified(page)) + return (false); + + /* + * There is no point splitting if the list is small, no deep items is + * our heuristic for that. A 1/4 probability of adding a new skiplist + * level, with level-0 always created, means there will be a 5th level + * entry for roughly every 1024 entries in the list. If there are at + * least 4 5th level entries (4K items), the list is large enough. + */ +#define WT_MIN_SPLIT_SKIPLIST_DEPTH WT_MIN(5, WT_SKIP_MAXDEPTH - 1) + ins_head = page->pg_row_entries == 0 ? + WT_ROW_INSERT_SMALLEST(page) : + WT_ROW_INSERT_SLOT(page, page->pg_row_entries - 1); + if (ins_head == NULL) + return (false); + for (i = 0, ins = ins_head->head[WT_MIN_SPLIT_SKIPLIST_DEPTH]; + ins != NULL; ins = ins->next[WT_MIN_SPLIT_SKIPLIST_DEPTH]) + if (++i == 4) + return (true); + return (false); +} + +/* * __wt_page_can_evict -- * Check whether a page can be evicted. */ -static inline int -__wt_page_can_evict(WT_SESSION_IMPL *session, WT_PAGE *page, int check_splits) +static inline bool +__wt_page_can_evict(WT_SESSION_IMPL *session, + WT_PAGE *page, int check_splits, int *inmem_splitp) { WT_BTREE *btree; WT_PAGE_MODIFY *mod; + WT_TXN_GLOBAL *txn_global; btree = S2BT(session); mod = page->modify; /* Pages that have never been modified can always be evicted. */ if (mod == NULL) - return (1); + return (true); + + /* + * Check for in-memory splits before other eviction tests. If the page + * should split in-memory, return success immediately and skip more + * detailed eviction tests. We don't need further tests since the page + * won't be written or discarded from the cache. + */ + if (__wt_page_can_split(session, page)) { + if (inmem_splitp != NULL) + *inmem_splitp = 1; + return (true); + } /* * If the tree was deepened, there's a requirement that newly created @@ -964,7 +1037,7 @@ __wt_page_can_evict(WT_SESSION_IMPL *session, WT_PAGE *page, int check_splits) */ if (check_splits && WT_PAGE_IS_INTERNAL(page) && !__wt_txn_visible_all(session, mod->mod_split_txn)) - return (0); + return (false); /* * If the file is being checkpointed, we can't evict dirty pages: @@ -977,41 +1050,20 @@ __wt_page_can_evict(WT_SESSION_IMPL *session, WT_PAGE *page, int check_splits) F_ISSET(mod, WT_PM_REC_MULTIBLOCK))) { WT_STAT_FAST_CONN_INCR(session, cache_eviction_checkpoint); WT_STAT_FAST_DATA_INCR(session, cache_eviction_checkpoint); - return (0); + return (false); } /* - * If we aren't (potentially) doing eviction that can restore updates - * and the updates on this page are too recent, give up. - * - * Don't rely on new updates being skipped by the transaction used - * for transaction reads: (1) there are paths that dirty pages for - * artificial reasons; (2) internal pages aren't transactional; and - * (3) if an update was skipped during the checkpoint (leaving the page - * dirty), then rolled back, we could still successfully overwrite a - * page and corrupt the checkpoint. - * - * Further, we can't race with the checkpoint's reconciliation of - * an internal page as we evict a clean child from the page's subtree. - * This works in the usual way: eviction locks the page and then checks - * for existing hazard pointers, the checkpoint thread reconciling an - * internal page acquires hazard pointers on child pages it reads, and - * is blocked by the exclusive lock. - */ - if (page->read_gen != WT_READGEN_OLDEST && - !__wt_txn_visible_all(session, __wt_page_is_modified(page) ? - mod->update_txn : mod->rec_max_txn)) - return (0); - - /* * If the page was recently split in-memory, don't force it out: we * hope an eviction thread will find it first. */ - if (check_splits && - !__wt_txn_visible_all(session, mod->inmem_split_txn)) - return (0); + if (check_splits) { + txn_global = &S2C(session)->txn_global; + if (WT_TXNID_LE(txn_global->oldest_id, mod->inmem_split_txn)) + return (false); + } - return (1); + return (true); } /* @@ -1097,7 +1149,7 @@ __wt_page_release(WT_SESSION_IMPL *session, WT_REF *ref, uint32_t flags) if (page->read_gen != WT_READGEN_OLDEST || LF_ISSET(WT_READ_NO_EVICT) || F_ISSET(btree, WT_BTREE_NO_EVICTION) || - !__wt_page_can_evict(session, page, 1)) + !__wt_page_can_evict(session, page, 1, NULL)) return (__wt_hazard_clear(session, page)); WT_RET_BUSY_OK(__wt_page_release_evict(session, ref)); @@ -1211,13 +1263,13 @@ __wt_skip_choose_depth(WT_SESSION_IMPL *session) } /* - * __wt_btree_lsm_size -- - * Check if the size of an in-memory tree with a single leaf page is over + * __wt_btree_lsm_over_size -- + * Return if the size of an in-memory tree with a single leaf page is over * a specified maximum. If called on anything other than a simple tree with a * single leaf page, returns true so the calling code will switch to a new tree. */ -static inline int -__wt_btree_lsm_size(WT_SESSION_IMPL *session, uint64_t maxsize) +static inline bool +__wt_btree_lsm_over_size(WT_SESSION_IMPL *session, uint64_t maxsize) { WT_BTREE *btree; WT_PAGE *child, *root; @@ -1229,20 +1281,20 @@ __wt_btree_lsm_size(WT_SESSION_IMPL *session, uint64_t maxsize) /* Check for a non-existent tree. */ if (root == NULL) - return (0); + return (false); /* A tree that can be evicted always requires a switch. */ if (!F_ISSET(btree, WT_BTREE_NO_EVICTION)) - return (1); + return (true); /* Check for a tree with a single leaf page. */ pindex = WT_INTL_INDEX_GET_SAFE(root); if (pindex->entries != 1) /* > 1 child page, switch */ - return (1); + return (true); first = pindex->index[0]; if (first->state != WT_REF_MEM) /* no child page, ignore */ - return (0); + return (false); /* * We're reaching down into the page without a hazard pointer, but @@ -1251,7 +1303,7 @@ __wt_btree_lsm_size(WT_SESSION_IMPL *session, uint64_t maxsize) */ child = first->page; if (child->type != WT_PAGE_ROW_LEAF) /* not a single leaf page */ - return (1); + return (true); return (child->memory_footprint > maxsize); } diff --git a/src/include/cache.i b/src/include/cache.i index d84069c43fb..3af454775b2 100644 --- a/src/include/cache.i +++ b/src/include/cache.i @@ -169,7 +169,7 @@ __wt_session_can_wait(WT_SESSION_IMPL *session) /* * __wt_cache_full_check -- - * Wait for there to be space in the cache before a read or update. + * Evict pages if the cache crosses its boundaries. */ static inline int __wt_cache_full_check(WT_SESSION_IMPL *session) diff --git a/src/include/extern.h b/src/include/extern.h index 447a74d2d67..b66954566a9 100644 --- a/src/include/extern.h +++ b/src/include/extern.h @@ -63,7 +63,7 @@ extern int __wt_block_ext_prealloc(WT_SESSION_IMPL *session, u_int max); extern int __wt_block_ext_discard(WT_SESSION_IMPL *session, u_int max); extern int __wt_block_salvage_start(WT_SESSION_IMPL *session, WT_BLOCK *block); extern int __wt_block_salvage_end(WT_SESSION_IMPL *session, WT_BLOCK *block); -extern int __wt_block_offset_invalid(WT_BLOCK *block, wt_off_t offset, uint32_t size); +extern bool __wt_block_offset_invalid(WT_BLOCK *block, wt_off_t offset, uint32_t size); extern int __wt_block_salvage_next(WT_SESSION_IMPL *session, WT_BLOCK *block, uint8_t *addr, size_t *addr_sizep, int *eofp); extern int __wt_block_salvage_valid(WT_SESSION_IMPL *session, WT_BLOCK *block, uint8_t *addr, size_t addr_size, int valid); extern int __wt_block_verify_start(WT_SESSION_IMPL *session, WT_BLOCK *block, WT_CKPT *ckptbase, const char *cfg[]); @@ -114,7 +114,7 @@ extern int __wt_debug_tree(WT_SESSION_IMPL *session, WT_PAGE *page, const char * extern int __wt_debug_page(WT_SESSION_IMPL *session, WT_PAGE *page, const char *ofile); extern int __wt_delete_page(WT_SESSION_IMPL *session, WT_REF *ref, int *skipp); extern void __wt_delete_page_rollback(WT_SESSION_IMPL *session, WT_REF *ref); -extern int __wt_delete_page_skip(WT_SESSION_IMPL *session, WT_REF *ref); +extern bool __wt_delete_page_skip(WT_SESSION_IMPL *session, WT_REF *ref); extern int __wt_delete_page_instantiate(WT_SESSION_IMPL *session, WT_REF *ref); extern void __wt_ref_out(WT_SESSION_IMPL *session, WT_REF *ref); extern void __wt_page_out(WT_SESSION_IMPL *session, WT_PAGE **pagep); @@ -491,7 +491,7 @@ extern int __wt_rwlock_destroy(WT_SESSION_IMPL *session, WT_RWLOCK **rwlockp); extern int __wt_once(void (*init_routine)(void)); extern int __wt_open(WT_SESSION_IMPL *session, const char *name, int ok_create, int exclusive, int dio_type, WT_FH **fhp); extern int __wt_close(WT_SESSION_IMPL *session, WT_FH **fhp); -extern int __wt_absolute_path(const char *path); +extern bool __wt_absolute_path(const char *path); extern const char *__wt_path_separator(void); extern int __wt_has_priv(void); extern int __wt_remove(WT_SESSION_IMPL *session, const char *name); @@ -642,7 +642,7 @@ extern int __wt_statlog_dump_spinlock(WT_CONNECTION_IMPL *conn, const char *tag) extern uint32_t __wt_nlpo2_round(uint32_t v); extern uint32_t __wt_nlpo2(uint32_t v); extern uint32_t __wt_log2_int(uint32_t n); -extern int __wt_ispo2(uint32_t v); +extern bool __wt_ispo2(uint32_t v); extern uint32_t __wt_rduppo2(uint32_t n, uint32_t po2); extern void __wt_random_init(WT_RAND_STATE volatile *rnd_state); extern uint32_t __wt_random(WT_RAND_STATE volatile *rnd_state); diff --git a/src/include/gcc.h b/src/include/gcc.h index 831dcd735d5..238c54fed9e 100644 --- a/src/include/gcc.h +++ b/src/include/gcc.h @@ -123,7 +123,7 @@ __wt_atomic_sub##name(type *vp, type v) \ { \ return (__sync_sub_and_fetch(vp, v)); \ } \ -static inline int \ +static inline bool \ __wt_atomic_cas##name(type *vp, type old, type new) \ { \ return (WT_ATOMIC_CAS(vp, old, new)); \ @@ -145,7 +145,7 @@ WT_ATOMIC_FUNC(size, size_t, size_t) * __wt_atomic_cas_ptr -- * Pointer compare and swap. */ -static inline int +static inline bool __wt_atomic_cas_ptr(void *vp, void *old, void *new) { return (WT_ATOMIC_CAS((void **)vp, old, new)); diff --git a/src/include/lint.h b/src/include/lint.h index eba4a1c3b3f..f288fb98683 100644 --- a/src/include/lint.h +++ b/src/include/lint.h @@ -49,14 +49,14 @@ __wt_atomic_sub##name(type *vp, type v) \ *vp -= v; \ return (*vp); \ } \ -static inline int \ +static inline bool \ __wt_atomic_cas##name(type *vp, type old, type new) \ { \ if (*vp == old) { \ *vp = new; \ - return (1); \ + return (true); \ } \ - return (0); \ + return (false); \ } WT_ATOMIC_FUNC(8, uint8_t, uint8_t) @@ -75,13 +75,13 @@ WT_ATOMIC_FUNC(size, size_t, size_t) * __wt_atomic_cas_ptr -- * Pointer compare and swap. */ -static inline int +static inline bool __wt_atomic_cas_ptr(void *vp, void *old, void *new) { if (*(void **)vp == old) { *(void **)vp = new; - return (1); + return (true); } - return (0); + return (false); } static inline void WT_BARRIER(void) { return; } diff --git a/src/include/msvc.h b/src/include/msvc.h index f4d8ba52fc1..8f5aa9abde8 100644 --- a/src/include/msvc.h +++ b/src/include/msvc.h @@ -52,7 +52,7 @@ __wt_atomic_sub##name(type *vp, type v) \ { \ return (_InterlockedExchangeAdd ## s((t *)(vp), - (t)v) - (v)); \ } \ -static inline int \ +static inline bool \ __wt_atomic_cas##name(type *vp, type old, type new) \ { \ return (_InterlockedCompareExchange ## s \ @@ -75,7 +75,7 @@ WT_ATOMIC_FUNC(size, size_t, size_t, 64, __int64) * __wt_atomic_cas_ptr -- * Pointer compare and swap. */ -static inline int +static inline bool __wt_atomic_cas_ptr(void *vp, void *old, void *new) { return (_InterlockedCompareExchange64( diff --git a/src/include/txn.h b/src/include/txn.h index 7a31ed2f3fe..4f6a79eb20e 100644 --- a/src/include/txn.h +++ b/src/include/txn.h @@ -17,11 +17,11 @@ * transaction), WT_TXN_NONE is smaller than any possible ID (visible to all * running transactions). */ -#define TXNID_LE(t1, t2) \ +#define WT_TXNID_LE(t1, t2) \ ((t1) <= (t2)) -#define TXNID_LT(t1, t2) \ - ((t1) != (t2) && TXNID_LE(t1, t2)) +#define WT_TXNID_LT(t1, t2) \ + ((t1) != (t2) && WT_TXNID_LE(t1, t2)) #define WT_SESSION_TXN_STATE(s) (&S2C(s)->txn_global.states[(s)->id]) @@ -143,10 +143,10 @@ struct __wt_txn { uint32_t ckpt_nsnapshot; WT_ITEM *ckpt_snapshot; -#define TXN_AUTOCOMMIT 0x01 -#define TXN_ERROR 0x02 -#define TXN_HAS_ID 0x04 -#define TXN_HAS_SNAPSHOT 0x08 -#define TXN_RUNNING 0x10 +#define WT_TXN_AUTOCOMMIT 0x01 +#define WT_TXN_ERROR 0x02 +#define WT_TXN_HAS_ID 0x04 +#define WT_TXN_HAS_SNAPSHOT 0x08 +#define WT_TXN_RUNNING 0x10 uint32_t flags; }; diff --git a/src/include/txn.i b/src/include/txn.i index a262672630f..8b414e80eef 100644 --- a/src/include/txn.i +++ b/src/include/txn.i @@ -26,7 +26,7 @@ __txn_next_op(WT_SESSION_IMPL *session, WT_TXN_OP **opp) * Make sure we have allocated a transaction ID. */ WT_RET(__wt_txn_id_check(session)); - WT_ASSERT(session, F_ISSET(txn, TXN_HAS_ID)); + WT_ASSERT(session, F_ISSET(txn, WT_TXN_HAS_ID)); WT_RET(__wt_realloc_def(session, &txn->mod_alloc, txn->mod_count + 1, &txn->mod)); @@ -49,7 +49,7 @@ __wt_txn_unmodify(WT_SESSION_IMPL *session) WT_TXN *txn; txn = &session->txn; - if (F_ISSET(txn, TXN_HAS_ID)) { + if (F_ISSET(txn, WT_TXN_HAS_ID)) { WT_ASSERT(session, txn->mod_count > 0); txn->mod_count--; } @@ -123,7 +123,7 @@ __wt_txn_oldest_id(WT_SESSION_IMPL *session) * then it's safe to ignore the checkpoint ID in the visibility check. */ if (checkpoint_pinned == WT_TXN_NONE || - TXNID_LT(oldest_id, checkpoint_pinned) || + WT_TXNID_LT(oldest_id, checkpoint_pinned) || WT_SESSION_IS_CHECKPOINT(session) || (btree != NULL && btree->checkpoint_gen == checkpoint_gen)) return (oldest_id); @@ -137,21 +137,21 @@ __wt_txn_oldest_id(WT_SESSION_IMPL *session) * all sessions in the system will see the transaction ID including the * ID that belongs to a running checkpoint. */ -static inline int +static inline bool __wt_txn_visible_all(WT_SESSION_IMPL *session, uint64_t id) { uint64_t oldest_id; oldest_id = __wt_txn_oldest_id(session); - return (TXNID_LT(id, oldest_id)); + return (WT_TXNID_LT(id, oldest_id)); } /* * __wt_txn_visible -- * Can the current transaction see the given ID? */ -static inline int +static inline bool __wt_txn_visible(WT_SESSION_IMPL *session, uint64_t id) { WT_TXN *txn; @@ -160,11 +160,11 @@ __wt_txn_visible(WT_SESSION_IMPL *session, uint64_t id) /* Changes with no associated transaction are always visible. */ if (id == WT_TXN_NONE) - return (1); + return (true); /* Nobody sees the results of aborted transactions. */ if (id == WT_TXN_ABORTED) - return (0); + return (false); /* * Eviction only sees globally visible updates, or if there is a @@ -185,11 +185,11 @@ __wt_txn_visible(WT_SESSION_IMPL *session, uint64_t id) */ if (txn->isolation == WT_ISO_READ_UNCOMMITTED || session->dhandle == session->meta_dhandle) - return (1); + return (true); /* Transactions see their own changes. */ if (id == txn->id) - return (1); + return (true); /* * WT_ISO_SNAPSHOT, WT_ISO_READ_COMMITTED: the ID is visible if it is @@ -200,10 +200,10 @@ __wt_txn_visible(WT_SESSION_IMPL *session, uint64_t id) * saw when taking the snapshot should be invisible, even if the * snapshot is empty. */ - if (TXNID_LE(txn->snap_max, id)) - return (0); - if (txn->snapshot_count == 0 || TXNID_LT(id, txn->snap_min)) - return (1); + if (WT_TXNID_LE(txn->snap_max, id)) + return (false); + if (txn->snapshot_count == 0 || WT_TXNID_LT(id, txn->snap_min)) + return (true); return (bsearch(&id, txn->snapshot, txn->snapshot_count, sizeof(uint64_t), __wt_txnid_cmp) == NULL); @@ -225,7 +225,6 @@ __wt_txn_begin(WT_SESSION_IMPL *session, const char *cfg[]) if (cfg != NULL) WT_RET(__wt_txn_config(session, cfg)); - F_SET(txn, TXN_RUNNING); if (txn->isolation == WT_ISO_SNAPSHOT) { if (session->ncursors > 0) WT_RET(__wt_session_copy_values(session)); @@ -237,7 +236,9 @@ __wt_txn_begin(WT_SESSION_IMPL *session, const char *cfg[]) WT_RET(__wt_cache_full_check(session)); __wt_txn_get_snapshot(session); } - return (0); + + F_SET(txn, WT_TXN_RUNNING); + return (false); } /* @@ -263,8 +264,8 @@ __wt_txn_autocommit_check(WT_SESSION_IMPL *session) WT_TXN *txn; txn = &session->txn; - if (F_ISSET(txn, TXN_AUTOCOMMIT)) { - F_CLR(txn, TXN_AUTOCOMMIT); + if (F_ISSET(txn, WT_TXN_AUTOCOMMIT)) { + F_CLR(txn, WT_TXN_AUTOCOMMIT); return (__wt_txn_begin(session, NULL)); } return (0); @@ -304,10 +305,10 @@ __wt_txn_idle_cache_check(WT_SESSION_IMPL *session) /* * Check the published snap_min because read-uncommitted never sets - * TXN_HAS_SNAPSHOT. + * WT_TXN_HAS_SNAPSHOT. */ - if (F_ISSET(txn, TXN_RUNNING) && - !F_ISSET(txn, TXN_HAS_ID) && txn_state->snap_min == WT_TXN_NONE) + if (F_ISSET(txn, WT_TXN_RUNNING) && + !F_ISSET(txn, WT_TXN_HAS_ID) && txn_state->snap_min == WT_TXN_NONE) WT_RET(__wt_cache_full_check(session)); return (0); @@ -328,12 +329,12 @@ __wt_txn_id_check(WT_SESSION_IMPL *session) txn = &session->txn; - WT_ASSERT(session, F_ISSET(txn, TXN_RUNNING)); + WT_ASSERT(session, F_ISSET(txn, WT_TXN_RUNNING)); /* If the transaction is idle, check that the cache isn't full. */ WT_RET(__wt_txn_idle_cache_check(session)); - if (!F_ISSET(txn, TXN_HAS_ID)) { + if (!F_ISSET(txn, WT_TXN_HAS_ID)) { conn = S2C(session); txn_global = &conn->txn_global; txn_state = WT_SESSION_TXN_STATE(session); @@ -362,7 +363,7 @@ __wt_txn_id_check(WT_SESSION_IMPL *session) txn_state->id = txn->id = txn_global->current; } while (!__wt_atomic_casv64( &txn_global->current, txn->id, txn->id + 1) || - TXNID_LT(txn->id, txn_global->last_running)); + WT_TXNID_LT(txn->id, txn_global->last_running)); /* * If we have used 64-bits of transaction IDs, there is nothing @@ -370,7 +371,7 @@ __wt_txn_id_check(WT_SESSION_IMPL *session) */ if (txn->id == WT_TXN_ABORTED) WT_RET_MSG(session, ENOMEM, "Out of transaction IDs"); - F_SET(txn, TXN_HAS_ID); + F_SET(txn, WT_TXN_HAS_ID); } return (0); @@ -411,7 +412,7 @@ __wt_txn_read_last(WT_SESSION_IMPL *session) txn = &session->txn; /* Release the snap_min ID we put in the global table. */ - if (!F_ISSET(txn, TXN_RUNNING) || + if (!F_ISSET(txn, WT_TXN_RUNNING) || txn->isolation != WT_ISO_SNAPSHOT) __wt_txn_release_snapshot(session); } @@ -448,12 +449,12 @@ __wt_txn_cursor_op(WT_SESSION_IMPL *session) * positioned on a value, it can't be freed. */ if (txn->isolation == WT_ISO_READ_UNCOMMITTED && - !F_ISSET(txn, TXN_HAS_ID) && - TXNID_LT(txn_state->snap_min, txn_global->last_running)) + !F_ISSET(txn, WT_TXN_HAS_ID) && + WT_TXNID_LT(txn_state->snap_min, txn_global->last_running)) txn_state->snap_min = txn_global->last_running; if (txn->isolation != WT_ISO_READ_UNCOMMITTED && - !F_ISSET(txn, TXN_HAS_SNAPSHOT)) + !F_ISSET(txn, WT_TXN_HAS_SNAPSHOT)) __wt_txn_get_snapshot(session); } @@ -461,7 +462,7 @@ __wt_txn_cursor_op(WT_SESSION_IMPL *session) * __wt_txn_am_oldest -- * Am I the oldest transaction in the system? */ -static inline int +static inline bool __wt_txn_am_oldest(WT_SESSION_IMPL *session) { WT_CONNECTION_IMPL *conn; @@ -476,12 +477,12 @@ __wt_txn_am_oldest(WT_SESSION_IMPL *session) txn_global = &conn->txn_global; if (txn->id == WT_TXN_NONE) - return (0); + return (false); WT_ORDERED_READ(session_cnt, conn->session_cnt); for (i = 0, s = txn_global->states; i < session_cnt; i++, s++) - if ((id = s->id) != WT_TXN_NONE && TXNID_LT(id, txn->id)) - return (0); + if ((id = s->id) != WT_TXN_NONE && WT_TXNID_LT(id, txn->id)) + return (false); - return (1); + return (true); } diff --git a/src/include/wiredtiger.in b/src/include/wiredtiger.in index 2667e02c5b6..e00e53e5af7 100644 --- a/src/include/wiredtiger.in +++ b/src/include/wiredtiger.in @@ -1216,7 +1216,12 @@ struct __wt_session { * Flush the log. * * @param session the session handle - * @configstart{WT_SESSION.log_flush, see dist/api_data.py} + * @configstart{session.log_flush, see dist/api_data.py} + * @config{sync, forcibly flush the log and wait for it to synchronize. + * If using \c off\, then wait for the log to be written to the file + * system. If using \c on\, wait for the log to be synchronized to the + * backing store., a string\, chosen from the following options: \c + * "off"\, \c "on"; default \c on.} * @configend * @errors */ diff --git a/src/include/wt_internal.h b/src/include/wt_internal.h index fa25fc872f4..6e9f37737bf 100644 --- a/src/include/wt_internal.h +++ b/src/include/wt_internal.h @@ -41,9 +41,7 @@ extern "C" { #else #include <pthread.h> #endif -#ifdef HAVE_PTHREAD_NP_H -#include <pthread_np.h> -#endif +#include <stdbool.h> #include <stddef.h> #include <stdio.h> #include <stdint.h> diff --git a/src/lsm/lsm_cursor.c b/src/lsm/lsm_cursor.c index 0962da7768b..ebbeeed8649 100644 --- a/src/lsm/lsm_cursor.c +++ b/src/lsm/lsm_cursor.c @@ -115,7 +115,7 @@ __clsm_enter_update(WT_CURSOR_LSM *clsm) WT_ASSERT(session, F_ISSET(&session->txn, TXN_HAS_ID)); have_primary = (primary != NULL && primary_chunk != NULL && (primary_chunk->switch_txn == WT_TXN_NONE || - TXNID_LT(session->txn.id, primary_chunk->switch_txn))); + WT_TXNID_LT(session->txn.id, primary_chunk->switch_txn))); } /* @@ -134,7 +134,7 @@ __clsm_enter_update(WT_CURSOR_LSM *clsm) if (have_primary) { WT_ENTER_PAGE_INDEX(session); WT_WITH_BTREE(session, ((WT_CURSOR_BTREE *)primary)->btree, - ovfl = __wt_btree_lsm_size(session, hard_limit ? + ovfl = __wt_btree_lsm_over_size(session, hard_limit ? 2 * lsm_tree->chunk_size : lsm_tree->chunk_size)); WT_LEAVE_PAGE_INDEX(session); @@ -229,7 +229,7 @@ __clsm_enter(WT_CURSOR_LSM *clsm, int reset, int update) &clsm->switch_txn[clsm->nchunks - 2]; clsm->nupdates < clsm->nchunks; clsm->nupdates++, switch_txnp--) { - if (TXNID_LT(*switch_txnp, snap_min)) + if (WT_TXNID_LT(*switch_txnp, snap_min)) break; WT_ASSERT(session, !__wt_txn_visible_all( @@ -1289,7 +1289,7 @@ __clsm_put(WT_SESSION_IMPL *session, F_ISSET(&session->txn, TXN_HAS_ID) && clsm->primary_chunk != NULL && (clsm->primary_chunk->switch_txn == WT_TXN_NONE || - TXNID_LE(session->txn.id, clsm->primary_chunk->switch_txn))); + WT_TXNID_LE(session->txn.id, clsm->primary_chunk->switch_txn))); /* * Clear the existing cursor position. Don't clear the primary cursor: diff --git a/src/meta/meta_table.c b/src/meta/meta_table.c index eae0079effd..fde7ccd625e 100644 --- a/src/meta/meta_table.c +++ b/src/meta/meta_table.c @@ -12,22 +12,22 @@ * __metadata_turtle -- * Return if a key's value should be taken from the turtle file. */ -static int +static bool __metadata_turtle(const char *key) { switch (key[0]) { case 'f': if (strcmp(key, WT_METAFILE_URI) == 0) - return (1); + return (true); break; case 'W': if (strcmp(key, "WiredTiger version") == 0) - return (1); + return (true); if (strcmp(key, "WiredTiger version string") == 0) - return (1); + return (true); break; } - return (0); + return (false); } /* diff --git a/src/os_posix/os_path.c b/src/os_posix/os_path.c index 07b14b55b44..af28e1b3b56 100644 --- a/src/os_posix/os_path.c +++ b/src/os_posix/os_path.c @@ -12,10 +12,10 @@ * __wt_absolute_path -- * Return if a filename is an absolute path. */ -int +bool __wt_absolute_path(const char *path) { - return (path[0] == '/' ? 1 : 0); + return (path[0] == '/'); } /* diff --git a/src/os_win/os_path.c b/src/os_win/os_path.c index 89f05e238c4..9d001e50571 100644 --- a/src/os_win/os_path.c +++ b/src/os_win/os_path.c @@ -12,7 +12,7 @@ * __wt_absolute_path -- * Return if a filename is an absolute path. */ -int +bool __wt_absolute_path(const char *path) { /* @@ -21,7 +21,7 @@ __wt_absolute_path(const char *path) */ if (strlen(path) >= 3 && isalpha(path[0]) && path[1] == ':') path += 2; - return (path[0] == '/' || path[0] == '\\' ? 1 : 0); + return (path[0] == '/' || path[0] == '\\'); } /* diff --git a/src/reconcile/rec_track.c b/src/reconcile/rec_track.c index df170cec470..36e85713421 100644 --- a/src/reconcile/rec_track.c +++ b/src/reconcile/rec_track.c @@ -722,7 +722,7 @@ __ovfl_txnc_wrapup(WT_SESSION_IMPL *session, WT_PAGE *page) */ for (i = WT_SKIP_MAXDEPTH - 1; i > 0; --i) for (e = &head[i]; (txnc = *e) != NULL;) { - if (TXNID_LE(oldest_txn, txnc->current)) { + if (WT_TXNID_LE(oldest_txn, txnc->current)) { e = &txnc->next[i]; continue; } @@ -732,7 +732,7 @@ __ovfl_txnc_wrapup(WT_SESSION_IMPL *session, WT_PAGE *page) /* Second, discard any no longer needed transaction-cache records. */ decr = 0; for (e = &head[0]; (txnc = *e) != NULL;) { - if (TXNID_LE(oldest_txn, txnc->current)) { + if (WT_TXNID_LE(oldest_txn, txnc->current)) { e = &txnc->next[0]; continue; } diff --git a/src/reconcile/rec_write.c b/src/reconcile/rec_write.c index eaaa3a56be3..3dc204a5173 100644 --- a/src/reconcile/rec_write.c +++ b/src/reconcile/rec_write.c @@ -372,7 +372,7 @@ __wt_reconcile(WT_SESSION_IMPL *session, * reconciliation will need. */ uint64_t oldest_id = __wt_txn_oldest_id(session); - WT_ASSERT(session, TXNID_LE(mod->last_oldest_id, oldest_id)); + WT_ASSERT(session, WT_TXNID_LE(mod->last_oldest_id, oldest_id)); mod->last_oldest_id = oldest_id; } #endif @@ -578,7 +578,7 @@ err: __wt_page_out(session, &next); * __rec_raw_compression_config -- * Configure raw compression. */ -static inline int +static inline bool __rec_raw_compression_config( WT_SESSION_IMPL *session, WT_PAGE *page, WT_SALVAGE_COOKIE *salvage) { @@ -589,11 +589,11 @@ __rec_raw_compression_config( /* Check if raw compression configured. */ if (btree->compressor == NULL || btree->compressor->compress_raw == NULL) - return (0); + return (false); /* Only for row-store and variable-length column-store objects. */ if (page->type == WT_PAGE_COL_FIX) - return (0); + return (false); /* * Raw compression cannot support dictionary compression. (Technically, @@ -603,11 +603,11 @@ __rec_raw_compression_config( * that seems an unlikely use case.) */ if (btree->dictionary != 0) - return (0); + return (false); /* Raw compression cannot support prefix compression. */ if (btree->prefix_compression != 0) - return (0); + return (false); /* * Raw compression is also turned off during salvage: we can't allow @@ -615,9 +615,9 @@ __rec_raw_compression_config( * can't manipulate the page size. */ if (salvage != NULL) - return (0); + return (false); - return (1); + return (true); } /* @@ -896,11 +896,11 @@ __rec_txn_read(WT_SESSION_IMPL *session, WT_RECONCILE *r, continue; /* Track the largest/smallest transaction IDs on the list. */ - if (TXNID_LT(max_txn, txnid)) + if (WT_TXNID_LT(max_txn, txnid)) max_txn = txnid; - if (TXNID_LT(txnid, min_txn)) + if (WT_TXNID_LT(txnid, min_txn)) min_txn = txnid; - if (TXNID_LT(txnid, r->skipped_txn) && + if (WT_TXNID_LT(txnid, r->skipped_txn) && !__wt_txn_visible_all(session, txnid)) r->skipped_txn = txnid; @@ -928,7 +928,7 @@ __rec_txn_read(WT_SESSION_IMPL *session, WT_RECONCILE *r, * used to avoid evicting clean pages from memory with changes required * to satisfy a snapshot read. */ - if (TXNID_LT(r->max_txn, max_txn)) + if (WT_TXNID_LT(r->max_txn, max_txn)) r->max_txn = max_txn; /* @@ -1792,9 +1792,9 @@ __rec_is_checkpoint(WT_RECONCILE *r, WT_BOUNDARY *bnd) bnd->addr.addr = NULL; bnd->addr.size = 0; bnd->addr.type = 0; - return (1); + return (true); } - return (0); + return (false); } /* @@ -5066,7 +5066,7 @@ err: __wt_scr_free(session, &tkey); } else { mod->rec_max_txn = r->max_txn; if (!F_ISSET(r, WT_EVICTING) && - TXNID_LT(btree->rec_max_txn, r->max_txn)) + WT_TXNID_LT(btree->rec_max_txn, r->max_txn)) btree->rec_max_txn = r->max_txn; if (__wt_atomic_cas32(&mod->write_gen, r->orig_write_gen, 0)) diff --git a/src/session/session_api.c b/src/session/session_api.c index af30edb9251..38f5536f441 100644 --- a/src/session/session_api.c +++ b/src/session/session_api.c @@ -95,7 +95,7 @@ __session_close(WT_SESSION *wt_session, const char *config) WT_UNUSED(cfg); /* Rollback any active transaction. */ - if (F_ISSET(&session->txn, TXN_RUNNING)) + if (F_ISSET(&session->txn, WT_TXN_RUNNING)) WT_TRET(__session_rollback_transaction(wt_session, NULL)); /* @@ -193,7 +193,7 @@ __session_reconfigure(WT_SESSION *wt_session, const char *config) session = (WT_SESSION_IMPL *)wt_session; SESSION_API_CALL(session, reconfigure, config, cfg); - if (F_ISSET(&session->txn, TXN_RUNNING)) + if (F_ISSET(&session->txn, WT_TXN_RUNNING)) WT_ERR_MSG(session, EINVAL, "transaction in progress"); WT_TRET(__wt_session_reset_cursors(session)); @@ -798,7 +798,7 @@ __session_begin_transaction(WT_SESSION *wt_session, const char *config) SESSION_API_CALL(session, begin_transaction, config, cfg); WT_STAT_FAST_CONN_INCR(session, txn_begin); - if (F_ISSET(&session->txn, TXN_RUNNING)) + if (F_ISSET(&session->txn, WT_TXN_RUNNING)) WT_ERR_MSG(session, EINVAL, "Transaction already running"); ret = __wt_txn_begin(session, cfg); @@ -822,7 +822,7 @@ __session_commit_transaction(WT_SESSION *wt_session, const char *config) WT_STAT_FAST_CONN_INCR(session, txn_commit); txn = &session->txn; - if (F_ISSET(txn, TXN_ERROR)) { + if (F_ISSET(txn, WT_TXN_ERROR)) { __wt_errx(session, "failed transaction requires rollback"); ret = EINVAL; } @@ -877,7 +877,7 @@ __session_transaction_pinned_range(WT_SESSION *wt_session, uint64_t *prange) /* Assign pinned to the lesser of id or snap_min */ if (txn_state->id != WT_TXN_NONE && - TXNID_LT(txn_state->id, txn_state->snap_min)) + WT_TXNID_LT(txn_state->id, txn_state->snap_min)) pinned = txn_state->id; else pinned = txn_state->snap_min; @@ -921,7 +921,7 @@ __session_checkpoint(WT_SESSION *wt_session, const char *config) * from evicting anything newer than this because we track the oldest * transaction ID in the system that is not visible to all readers. */ - if (F_ISSET(txn, TXN_RUNNING)) + if (F_ISSET(txn, WT_TXN_RUNNING)) WT_ERR_MSG(session, EINVAL, "Checkpoint not permitted in a transaction"); diff --git a/src/session/session_compact.c b/src/session/session_compact.c index 2a18eb3be93..23fe0f0449d 100644 --- a/src/session/session_compact.c +++ b/src/session/session_compact.c @@ -161,7 +161,8 @@ __compact_file(WT_SESSION_IMPL *session, const char *uri, const char *cfg[]) * transactional context. Check now so the error message isn't * confusing. */ - if (session->compact->file_count != 0 && F_ISSET(txn, TXN_RUNNING)) + if (session->compact->file_count != 0 && + F_ISSET(txn, WT_TXN_RUNNING)) WT_ERR_MSG(session, EINVAL, " File compaction not permitted in a transaction"); diff --git a/src/support/pow.c b/src/support/pow.c index 8e42113a2ee..0f50bfe56a1 100644 --- a/src/support/pow.c +++ b/src/support/pow.c @@ -100,7 +100,7 @@ __wt_log2_int(uint32_t n) * __wt_ispo2 -- * Return if a number is a power-of-two. */ -int +bool __wt_ispo2(uint32_t v) { /* diff --git a/src/txn/txn.c b/src/txn/txn.c index 45be0a15a32..3529d1c6d66 100644 --- a/src/txn/txn.c +++ b/src/txn/txn.c @@ -20,7 +20,7 @@ __wt_txnid_cmp(const void *v1, const void *v2) id1 = *(uint64_t *)v1; id2 = *(uint64_t *)v2; - return ((id1 == id2) ? 0 : TXNID_LT(id1, id2) ? -1 : 1); + return ((id1 == id2) ? 0 : WT_TXNID_LT(id1, id2) ? -1 : 1); } /* @@ -38,9 +38,9 @@ __txn_sort_snapshot(WT_SESSION_IMPL *session, uint32_t n, uint64_t snap_max) qsort(txn->snapshot, n, sizeof(uint64_t), __wt_txnid_cmp); txn->snapshot_count = n; txn->snap_max = snap_max; - txn->snap_min = (n > 0 && TXNID_LE(txn->snapshot[0], snap_max)) ? + txn->snap_min = (n > 0 && WT_TXNID_LE(txn->snapshot[0], snap_max)) ? txn->snapshot[0] : snap_max; - F_SET(txn, TXN_HAS_SNAPSHOT); + F_SET(txn, WT_TXN_HAS_SNAPSHOT); WT_ASSERT(session, n == 0 || txn->snap_min != WT_TXN_NONE); } @@ -63,7 +63,7 @@ __wt_txn_release_snapshot(WT_SESSION_IMPL *session) !__wt_txn_visible_all(session, txn_state->snap_min)); txn_state->snap_min = WT_TXN_NONE; - F_CLR(txn, TXN_HAS_SNAPSHOT); + F_CLR(txn, WT_TXN_HAS_SNAPSHOT); } /* @@ -129,9 +129,9 @@ __wt_txn_get_snapshot(WT_SESSION_IMPL *session) */ if (s != txn_state && (id = s->id) != WT_TXN_NONE && - TXNID_LE(prev_oldest_id, id)) { + WT_TXNID_LE(prev_oldest_id, id)) { txn->snapshot[n++] = id; - if (TXNID_LT(id, snap_min)) + if (WT_TXNID_LT(id, snap_min)) snap_min = id; } } @@ -140,7 +140,7 @@ __wt_txn_get_snapshot(WT_SESSION_IMPL *session) * If we got a new snapshot, update the published snap_min for this * session. */ - WT_ASSERT(session, TXNID_LE(prev_oldest_id, snap_min)); + WT_ASSERT(session, WT_TXNID_LE(prev_oldest_id, snap_min)); WT_ASSERT(session, prev_oldest_id == txn_global->oldest_id); txn_state->snap_min = snap_min; @@ -191,7 +191,7 @@ __wt_txn_update_oldest(WT_SESSION_IMPL *session, int force) * oldest ID isn't too far behind, avoid scanning. */ if (prev_oldest_id == current_id || - (!force && TXNID_LT(current_id, prev_oldest_id + 100))) + (!force && WT_TXNID_LT(current_id, prev_oldest_id + 100))) return; /* @@ -221,7 +221,8 @@ __wt_txn_update_oldest(WT_SESSION_IMPL *session, int force) * it gets a valid one. */ if ((id = s->id) != WT_TXN_NONE && - TXNID_LE(prev_oldest_id, id) && TXNID_LT(id, snap_min)) + WT_TXNID_LE(prev_oldest_id, id) && + WT_TXNID_LT(id, snap_min)) snap_min = id; /* @@ -233,35 +234,35 @@ __wt_txn_update_oldest(WT_SESSION_IMPL *session, int force) * more details. */ if ((id = s->snap_min) != WT_TXN_NONE && - TXNID_LT(id, oldest_id)) { + WT_TXNID_LT(id, oldest_id)) { oldest_id = id; oldest_session = &conn->sessions[i]; } } - if (TXNID_LT(snap_min, oldest_id)) + if (WT_TXNID_LT(snap_min, oldest_id)) oldest_id = snap_min; /* Update the last running ID. */ - if (TXNID_LT(txn_global->last_running, snap_min)) { + if (WT_TXNID_LT(txn_global->last_running, snap_min)) { txn_global->last_running = snap_min; last_running_moved = 1; } else last_running_moved = 0; /* Update the oldest ID. */ - if (TXNID_LT(prev_oldest_id, oldest_id) && + if (WT_TXNID_LT(prev_oldest_id, oldest_id) && __wt_atomic_casiv32(&txn_global->scan_count, 1, -1)) { WT_ORDERED_READ(session_cnt, conn->session_cnt); for (i = 0, s = txn_global->states; i < session_cnt; i++, s++) { if ((id = s->id) != WT_TXN_NONE && - TXNID_LT(id, oldest_id)) + WT_TXNID_LT(id, oldest_id)) oldest_id = id; if ((id = s->snap_min) != WT_TXN_NONE && - TXNID_LT(id, oldest_id)) + WT_TXNID_LT(id, oldest_id)) oldest_id = id; } - if (TXNID_LT(txn_global->oldest_id, oldest_id)) + if (WT_TXNID_LT(txn_global->oldest_id, oldest_id)) txn_global->oldest_id = oldest_id; txn_global->scan_count = 0; } else { @@ -349,7 +350,7 @@ __wt_txn_release(WT_SESSION_IMPL *session) /* Clear the global checkpoint transaction IDs. */ txn_global->checkpoint_id = 0; txn_global->checkpoint_pinned = WT_TXN_NONE; - } else if (F_ISSET(txn, TXN_HAS_ID)) { + } else if (F_ISSET(txn, WT_TXN_HAS_ID)) { WT_ASSERT(session, txn_state->id != WT_TXN_NONE && txn->id != WT_TXN_NONE); WT_PUBLISH(txn_state->id, WT_TXN_NONE); @@ -397,9 +398,9 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[]) u_int i; txn = &session->txn; - WT_ASSERT(session, !F_ISSET(txn, TXN_ERROR)); + WT_ASSERT(session, !F_ISSET(txn, WT_TXN_ERROR)); - if (!F_ISSET(txn, TXN_RUNNING)) + if (!F_ISSET(txn, WT_TXN_RUNNING)) WT_RET_MSG(session, EINVAL, "No transaction is active"); /* Commit notification. */ @@ -464,7 +465,7 @@ __wt_txn_rollback(WT_SESSION_IMPL *session, const char *cfg[]) WT_UNUSED(cfg); txn = &session->txn; - if (!F_ISSET(txn, TXN_RUNNING)) + if (!F_ISSET(txn, WT_TXN_RUNNING)) WT_RET_MSG(session, EINVAL, "No transaction is active"); /* Rollback notification. */ diff --git a/src/txn/txn_ckpt.c b/src/txn/txn_ckpt.c index 1ae99fb1c97..aa2ba850310 100644 --- a/src/txn/txn_ckpt.c +++ b/src/txn/txn_ckpt.c @@ -481,8 +481,8 @@ __wt_txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[]) * cleared our entry. */ WT_ASSERT(session, - TXNID_LE(txn_global->oldest_id, txn_state->id) && - TXNID_LE(txn_global->oldest_id, txn_state->snap_min)); + WT_TXNID_LE(txn_global->oldest_id, txn_state->id) && + WT_TXNID_LE(txn_global->oldest_id, txn_state->snap_min)); /* * Clear our entry from the global transaction session table. Any @@ -578,7 +578,7 @@ err: /* if (tracking) WT_TRET(__wt_meta_track_off(session, 0, ret != 0)); - if (F_ISSET(txn, TXN_RUNNING)) { + if (F_ISSET(txn, WT_TXN_RUNNING)) { /* * Clear the dhandle so the visibility check doesn't get * confused about the snap min. Don't bother restoring the @@ -1069,7 +1069,7 @@ fake: /* */ if (F_ISSET(conn, WT_CONN_CKPT_SYNC) && (WT_IS_METADATA(dhandle) || - !F_ISSET(&session->txn, TXN_RUNNING))) + !F_ISSET(&session->txn, WT_TXN_RUNNING))) WT_ERR(__wt_checkpoint_sync(session, NULL)); WT_ERR(__wt_meta_ckptlist_set( diff --git a/src/txn/txn_log.c b/src/txn/txn_log.c index 1f19dcfc3ac..634f8a9c803 100644 --- a/src/txn/txn_log.c +++ b/src/txn/txn_log.c @@ -163,7 +163,7 @@ __wt_txn_log_op(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt) /* We'd better have a transaction. */ WT_ASSERT(session, - F_ISSET(txn, TXN_RUNNING) && F_ISSET(txn, TXN_HAS_ID)); + F_ISSET(txn, WT_TXN_RUNNING) && F_ISSET(txn, WT_TXN_HAS_ID)); WT_ASSERT(session, txn->mod_count > 0); op = txn->mod + txn->mod_count - 1; diff --git a/src/txn/txn_nsnap.c b/src/txn/txn_nsnap.c deleted file mode 100644 index be736cc1c98..00000000000 --- a/src/txn/txn_nsnap.c +++ /dev/null @@ -1,367 +0,0 @@ -/*- - * Copyright (c) 2014-2015 MongoDB, Inc. - * Copyright (c) 2008-2014 WiredTiger, Inc. - * All rights reserved. - * - * See the file LICENSE for redistribution information. - */ - -#include "wt_internal.h" - -/* - * __nsnap_destroy -- - * Destroy a named snapshot structure. - */ -static void -__nsnap_destroy(WT_SESSION_IMPL *session, WT_NAMED_SNAPSHOT *nsnap) -{ - __wt_free(session, nsnap->name); - __wt_free(session, nsnap->snapshot); - __wt_free(session, nsnap); -} - -/* - * __nsnap_drop_one -- - * Drop a single named snapshot. The named snapshot lock must be held - * write locked. - */ -static int -__nsnap_drop_one(WT_SESSION_IMPL *session, WT_CONFIG_ITEM *name) -{ - WT_DECL_RET; - WT_NAMED_SNAPSHOT *found; - WT_TXN_GLOBAL *txn_global; - - txn_global = &S2C(session)->txn_global; - - TAILQ_FOREACH(found, &txn_global->nsnaph, q) - if (WT_STRING_MATCH(found->name, name->str, name->len)) - break; - - if (found == NULL) - return (WT_NOTFOUND); - - /* Bump the global ID if we are removing the first entry */ - if (found == TAILQ_FIRST(&txn_global->nsnaph)) - txn_global->nsnap_oldest_id = (TAILQ_NEXT(found, q) != NULL) ? - TAILQ_NEXT(found, q)->snap_min : WT_TXN_NONE; - TAILQ_REMOVE(&txn_global->nsnaph, found, q); - __nsnap_destroy(session, found); - - return (ret); -} - -/* - * __nsnap_drop_to -- - * Drop named snapshots, if the name is NULL all snapshots will be - * dropped. The named snapshot lock must be held write locked. - */ -static int -__nsnap_drop_to(WT_SESSION_IMPL *session, WT_CONFIG_ITEM *name, int inclusive) -{ - WT_DECL_RET; - WT_NAMED_SNAPSHOT *last, *nsnap, *prev; - WT_TXN_GLOBAL *txn_global; - uint64_t new_nsnap_oldest; - - last = nsnap = prev = NULL; - txn_global = &S2C(session)->txn_global; - - if (TAILQ_EMPTY(&txn_global->nsnaph)) { - if (name == NULL) - return (0); - /* - * Dropping specific snapshots when there aren't any it's an - * error. - */ - WT_RET_MSG(session, EINVAL, - "Named snapshot '%.*s' for drop not found", - (int)name->len, name->str); - } - - /* - * The new ID will be none if we are removing all named snapshots - * which is the default behavior of this loop. - */ - new_nsnap_oldest = WT_TXN_NONE; - if (name != NULL) { - TAILQ_FOREACH(last, &txn_global->nsnaph, q) { - if (WT_STRING_MATCH(last->name, name->str, name->len)) - break; - prev = last; - } - if (last == NULL) - WT_RET_MSG(session, EINVAL, - "Named snapshot '%.*s' for drop not found", - (int)name->len, name->str); - - if (!inclusive) { - /* We are done if a drop before points to the head */ - if (prev == 0) - return (0); - last = prev; - } - - if (TAILQ_NEXT(last, q) != NULL) - new_nsnap_oldest = TAILQ_NEXT(last, q)->snap_min; - } - - do { - nsnap = TAILQ_FIRST(&txn_global->nsnaph); - WT_ASSERT(session, nsnap != NULL); - TAILQ_REMOVE(&txn_global->nsnaph, nsnap, q); - __nsnap_destroy(session, nsnap); - /* Last will be NULL in the all case so it will never match */ - } while (nsnap != last && !TAILQ_EMPTY(&txn_global->nsnaph)); - - /* Now that the queue of named snapshots is updated, update the ID */ - txn_global->nsnap_oldest_id = new_nsnap_oldest; - - return (ret); -} - -/* - * __wt_txn_named_snapshot_begin -- - * Begin an named in-memory snapshot. - */ -int -__wt_txn_named_snapshot_begin(WT_SESSION_IMPL *session, const char *cfg[]) -{ - WT_CONFIG_ITEM cval; - WT_DECL_RET; - WT_NAMED_SNAPSHOT *nsnap, *nsnap_new; - WT_TXN *txn; - WT_TXN_GLOBAL *txn_global; - const char *txn_cfg[] = - { WT_CONFIG_BASE(session, WT_SESSION_begin_transaction), - "isolation=snapshot", NULL }; - int started_txn; - - started_txn = 0; - nsnap_new = NULL; - txn_global = &S2C(session)->txn_global; - txn = &session->txn; - - WT_RET(__wt_config_gets_def(session, cfg, "name", 0, &cval)); - WT_ASSERT(session, cval.len != 0); - - if (!F_ISSET(txn, WT_TXN_RUNNING)) { - WT_RET(__wt_txn_begin(session, txn_cfg)); - started_txn = 1; - } - F_SET(txn, WT_TXN_READONLY); - - /* Save a copy of the transaction's snapshot. */ - WT_ERR(__wt_calloc_one(session, &nsnap_new)); - nsnap = nsnap_new; - WT_ERR(__wt_strndup(session, cval.str, cval.len, &nsnap->name)); - nsnap->snap_min = txn->snap_min; - nsnap->snap_max = txn->snap_max; - if (txn->snapshot_count > 0) { - WT_ERR(__wt_calloc_def( - session, txn->snapshot_count, &nsnap->snapshot)); - memcpy(nsnap->snapshot, txn->snapshot, - txn->snapshot_count * sizeof(*nsnap->snapshot)); - } - nsnap->snapshot_count = txn->snapshot_count; - - /* Update the list. */ - - /* - * The semantic is that a new snapshot with the same name as an - * existing snapshot will replace the old one. - */ - WT_ERR_NOTFOUND_OK(__nsnap_drop_one(session, &cval)); - - if (TAILQ_EMPTY(&txn_global->nsnaph)) - txn_global->nsnap_oldest_id = nsnap_new->snap_min; - TAILQ_INSERT_TAIL(&txn_global->nsnaph, nsnap_new, q); - nsnap_new = NULL; - -err: if (started_txn) - WT_TRET(__wt_txn_rollback(session, NULL)); - else if (ret == 0) - F_SET(txn, WT_TXN_NAMED_SNAPSHOT); - - if (nsnap_new != NULL) - __nsnap_destroy(session, nsnap_new); - - return (ret); -} - -/* - * __wt_txn_named_snapshot_drop -- - * Drop named snapshots - */ -int -__wt_txn_named_snapshot_drop(WT_SESSION_IMPL *session, const char *cfg[]) -{ - WT_CONFIG objectconf; - WT_CONFIG_ITEM all_config, k, names_config, to_config, before_config, v; - WT_DECL_RET; - - WT_RET(__wt_config_gets_def(session, cfg, "drop.all", 0, &all_config)); - WT_RET(__wt_config_gets_def( - session, cfg, "drop.names", 0, &names_config)); - WT_RET(__wt_config_gets_def(session, cfg, "drop.to", 0, &to_config)); - WT_RET(__wt_config_gets_def( - session, cfg, "drop.before", 0, &before_config)); - - if (all_config.val != 0) - WT_RET(__nsnap_drop_to(session, NULL, 1)); - else if (before_config.len != 0) - WT_RET(__nsnap_drop_to(session, &before_config, 0)); - else if (to_config.len != 0) - WT_RET(__nsnap_drop_to(session, &to_config, 1)); - - /* We are done if there are no named drops */ - - if (names_config.len != 0) { - WT_RET(__wt_config_subinit( - session, &objectconf, &names_config)); - while ((ret = __wt_config_next(&objectconf, &k, &v)) == 0) { - ret = __nsnap_drop_one(session, &k); - if (ret != 0) - WT_RET_MSG(session, EINVAL, - "Named snapshot '%.*s' for drop not found", - (int)k.len, k.str); - } - if (ret == WT_NOTFOUND) - ret = 0; - } - - return (ret); -} - -/* - * __wt_txn_named_snapshot_get -- - * Lookup a named snapshot for a transaction. - */ -int -__wt_txn_named_snapshot_get(WT_SESSION_IMPL *session, WT_CONFIG_ITEM *nameval) -{ - WT_NAMED_SNAPSHOT *nsnap; - WT_TXN *txn; - WT_TXN_GLOBAL *txn_global; - WT_TXN_STATE *txn_state; - - txn = &session->txn; - txn_global = &S2C(session)->txn_global; - txn_state = WT_SESSION_TXN_STATE(session); - - txn->isolation = WT_ISO_SNAPSHOT; - if (session->ncursors > 0) - WT_RET(__wt_session_copy_values(session)); - - WT_RET(__wt_readlock(session, txn_global->nsnap_rwlock)); - TAILQ_FOREACH(nsnap, &txn_global->nsnaph, q) - if (WT_STRING_MATCH(nsnap->name, nameval->str, nameval->len)) { - txn->snap_min = txn_state->snap_min = nsnap->snap_min; - txn->snap_max = nsnap->snap_max; - if ((txn->snapshot_count = nsnap->snapshot_count) != 0) - memcpy(txn->snapshot, nsnap->snapshot, - nsnap->snapshot_count * - sizeof(*nsnap->snapshot)); - F_SET(txn, WT_TXN_HAS_SNAPSHOT); - break; - } - WT_RET(__wt_readunlock(session, txn_global->nsnap_rwlock)); - - if (nsnap == NULL) - WT_RET_MSG(session, EINVAL, - "Named snapshot '%.*s' not found", - (int)nameval->len, nameval->str); - - /* Flag that this transaction is opened on a named snapshot */ - F_SET(txn, WT_TXN_NAMED_SNAPSHOT); - - return (0); -} - -/* - * __wt_txn_named_snapshot_config -- - * Check the configuration for a named snapshot - */ -int -__wt_txn_named_snapshot_config(WT_SESSION_IMPL *session, - const char *cfg[], int *has_create, int *has_drops) -{ - WT_CONFIG_ITEM cval; - WT_CONFIG_ITEM all_config, names_config, to_config, before_config; - WT_TXN *txn; - - txn = &session->txn; - *has_create = *has_drops = 0; - - /* Verify that the name is legal. */ - WT_RET(__wt_config_gets_def(session, cfg, "name", 0, &cval)); - if (cval.len != 0) { - if (WT_STRING_MATCH("all", cval.str, cval.len)) - WT_RET_MSG(session, EINVAL, - "Can't create snapshot with reserved \"all\" name"); - - WT_RET(__wt_name_check(session, cval.str, cval.len)); - - if (F_ISSET(txn, WT_TXN_RUNNING) && - txn->isolation != WT_ISO_SNAPSHOT) - WT_RET_MSG(session, EINVAL, - "Can't create a named snapshot from a running " - "transaction that isn't snapshot isolation"); - else if (F_ISSET(txn, WT_TXN_RUNNING) && txn->mod_count != 0) - WT_RET_MSG(session, EINVAL, - "Can't create a named snapshot from a running " - "transaction that has made updates"); - *has_create = 1; - } - - /* Verify that the drop configuration is sane. */ - WT_RET(__wt_config_gets_def(session, cfg, "drop.all", 0, &all_config)); - WT_RET(__wt_config_gets_def( - session, cfg, "drop.names", 0, &names_config)); - WT_RET(__wt_config_gets_def(session, cfg, "drop.to", 0, &to_config)); - WT_RET(__wt_config_gets_def( - session, cfg, "drop.before", 0, &before_config)); - - /* Avoid more work if no drops are configured. */ - if (all_config.val != 0 || names_config.len != 0 || - before_config.len != 0 || to_config.len != 0) { - if (before_config.len != 0 && to_config.len != 0) - WT_RET_MSG(session, EINVAL, - "Illegal configuration; named snapshot drop can't " - "specify both before and to options"); - if (all_config.val != 0 && (names_config.len != 0 || - to_config.len != 0 || before_config.len != 0)) - WT_RET_MSG(session, EINVAL, - "Illegal configuration; named snapshot drop can't " - "specify all and any other options"); - *has_drops = 1; - } - - if (!*has_create && !*has_drops) - WT_RET_MSG(session, EINVAL, - "WT_SESSION::snapshot API called without any drop or " - "name option."); - - return (0); -} - -/* - * __wt_txn_named_snapshot_destroy -- - * Destroy all named snapshots on connection close - */ -int -__wt_txn_named_snapshot_destroy(WT_SESSION_IMPL *session) -{ - WT_NAMED_SNAPSHOT *nsnap; - WT_TXN_GLOBAL *txn_global; - - txn_global = &S2C(session)->txn_global; - txn_global->nsnap_oldest_id = WT_TXN_NONE; - - while ((nsnap = TAILQ_FIRST(&txn_global->nsnaph)) != NULL) { - TAILQ_REMOVE(&txn_global->nsnaph, nsnap, q); - __nsnap_destroy(session, nsnap); - } - - return (0); -} diff --git a/test/format/t.c b/test/format/t.c index 3aa6527ee07..21dc02ce522 100644 --- a/test/format/t.c +++ b/test/format/t.c @@ -34,7 +34,6 @@ static void startup(void); static void usage(void); extern int __wt_optind; -extern int __wt_getopt(const char *, int, char * const *, const char *); extern char *__wt_optarg; int |