diff options
author | Michael Cahill <michael.cahill@mongodb.com> | 2016-02-09 09:26:06 +1100 |
---|---|---|
committer | Michael Cahill <michael.cahill@mongodb.com> | 2016-02-09 09:26:06 +1100 |
commit | 8a276527cea8d040bc6950ef858adf81f26b1e5d (patch) | |
tree | 0a04c3267a74a50807af36807bde0e0949884a5c | |
parent | 9bf9311365e9b213d5e67a965c8dd21185c9fbd3 (diff) | |
parent | 0ef9946c93ab5272acab59eba8158f19ff68e1cf (diff) | |
download | mongo-8a276527cea8d040bc6950ef858adf81f26b1e5d.tar.gz |
Merge branch 'develop' into wt-2361
39 files changed, 194 insertions, 143 deletions
diff --git a/SConstruct b/SConstruct index 3f395d17543..a7306262f82 100644 --- a/SConstruct +++ b/SConstruct @@ -456,6 +456,7 @@ if useBdb: t = env.Program("wtperf", [ "bench/wtperf/config.c", + "bench/wtperf/idle_table_cycle.c", "bench/wtperf/misc.c", "bench/wtperf/track.c", "bench/wtperf/wtperf.c", diff --git a/bench/wtperf/wtperf.h b/bench/wtperf/wtperf.h index f8d5a5c0bc9..929880b0aef 100644 --- a/bench/wtperf/wtperf.h +++ b/bench/wtperf/wtperf.h @@ -29,6 +29,8 @@ #ifndef HAVE_WTPERF_H #define HAVE_WTPERF_H +#include <wt_internal.h> + #ifndef _WIN32 #include <sys/time.h> #endif @@ -56,8 +58,6 @@ #include <unistd.h> #endif -#include <wt_internal.h> - #ifdef _WIN32 #include "windows_shim.h" #endif @@ -88,7 +88,7 @@ typedef struct { int64_t insert; /* Insert ratio */ int64_t read; /* Read ratio */ int64_t update; /* Update ratio */ - uint64_t throttle; /* Maximum operations/second */ + uint64_t throttle; /* Maximum operations/second */ /* Number of operations per transaction. Zero for autocommit */ int64_t ops_per_txn; int64_t truncate; /* Truncate ratio */ @@ -403,16 +403,18 @@ dstrdup(const char *str) /* * dstrndup -- - * Call strndup, dying on failure. + * Call emulating strndup, dying on failure. Don't use actual strndup here + * as it is not supported within MSVC. */ static inline char * dstrndup(const char *str, const size_t len) { char *p; + p = dcalloc(len + 1, 1); - if ((p = strndup(str, len)) == NULL) - die(errno, "strndup"); + strncpy(p, str, len); + if (p == NULL) + die(errno, "dstrndup"); return (p); } - #endif diff --git a/dist/s_define.list b/dist/s_define.list index ff24e3db822..e3f0dc7f181 100644 --- a/dist/s_define.list +++ b/dist/s_define.list @@ -52,7 +52,9 @@ WT_STAT_WRITE WT_TIMEDIFF_US WT_TRET_ERROR_OK WT_WITH_LOCK +WT_WITH_LOCK_WAIT __F __WIREDTIGER_EXT_H_ __WIREDTIGER_H_ +__WT_INTERNAL_H __wt_bswap16 diff --git a/ext/compressors/lz4/lz4_compress.c b/ext/compressors/lz4/lz4_compress.c index 3e6609beb80..062307b721a 100644 --- a/ext/compressors/lz4/lz4_compress.c +++ b/ext/compressors/lz4/lz4_compress.c @@ -26,13 +26,13 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include <wt_internal.h> + #include <lz4.h> #include <errno.h> #include <stdlib.h> #include <string.h> -#include <wt_internal.h> - /* Local compressor structure. */ typedef struct { WT_COMPRESSOR compressor; /* Must come first */ diff --git a/ext/compressors/snappy/snappy_compress.c b/ext/compressors/snappy/snappy_compress.c index d1bd2e1813c..fcefb8bb575 100644 --- a/ext/compressors/snappy/snappy_compress.c +++ b/ext/compressors/snappy/snappy_compress.c @@ -26,13 +26,13 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include <wt_internal.h> + #include <snappy-c.h> #include <errno.h> #include <stdlib.h> #include <string.h> -#include <wt_internal.h> - /* Local compressor structure. */ typedef struct { WT_COMPRESSOR compressor; /* Must come first */ diff --git a/src/btree/bt_curprev.c b/src/btree/bt_curprev.c index a083ec4016e..7475c0f1312 100644 --- a/src/btree/bt_curprev.c +++ b/src/btree/bt_curprev.c @@ -51,7 +51,8 @@ restart: if (cbt->btree->type == BTREE_ROW) { key.data = WT_INSERT_KEY(current); key.size = WT_INSERT_KEY_SIZE(current); - WT_RET(__wt_search_insert(session, cbt, &key)); + WT_RET(__wt_search_insert( + session, cbt, cbt->ins_head, &key)); } else cbt->ins = __col_insert_search(cbt->ins_head, cbt->ins_stack, cbt->next_stack, diff --git a/src/btree/row_srch.c b/src/btree/row_srch.c index 097b0b7a520..955568bcd50 100644 --- a/src/btree/row_srch.c +++ b/src/btree/row_srch.c @@ -9,18 +9,17 @@ #include "wt_internal.h" /* - * __wt_search_insert_append -- + * __search_insert_append -- * Fast append search of a row-store insert list, creating a skiplist stack * as we go. */ static inline int -__wt_search_insert_append(WT_SESSION_IMPL *session, - WT_CURSOR_BTREE *cbt, WT_ITEM *srch_key, bool *donep) +__search_insert_append(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, + WT_INSERT_HEAD *ins_head, WT_ITEM *srch_key, bool *donep) { WT_BTREE *btree; WT_COLLATOR *collator; WT_INSERT *ins; - WT_INSERT_HEAD *inshead; WT_ITEM key; int cmp, i; @@ -28,8 +27,7 @@ __wt_search_insert_append(WT_SESSION_IMPL *session, collator = btree->collator; *donep = 0; - inshead = cbt->ins_head; - if ((ins = WT_SKIP_LAST(inshead)) == NULL) + if ((ins = WT_SKIP_LAST(ins_head)) == NULL) return (0); key.data = WT_INSERT_KEY(ins); key.size = WT_INSERT_KEY_SIZE(ins); @@ -48,12 +46,13 @@ __wt_search_insert_append(WT_SESSION_IMPL *session, */ for (i = WT_SKIP_MAXDEPTH - 1; i >= 0; i--) { cbt->ins_stack[i] = (i == 0) ? &ins->next[0] : - (inshead->tail[i] != NULL) ? - &inshead->tail[i]->next[i] : &inshead->head[i]; + (ins_head->tail[i] != NULL) ? + &ins_head->tail[i]->next[i] : &ins_head->head[i]; cbt->next_stack[i] = NULL; } cbt->compare = -cmp; cbt->ins = ins; + cbt->ins_head = ins_head; *donep = 1; } return (0); @@ -64,20 +63,18 @@ __wt_search_insert_append(WT_SESSION_IMPL *session, * Search a row-store insert list, creating a skiplist stack as we go. */ int -__wt_search_insert( - WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, WT_ITEM *srch_key) +__wt_search_insert(WT_SESSION_IMPL *session, + WT_CURSOR_BTREE *cbt, WT_INSERT_HEAD *ins_head, WT_ITEM *srch_key) { WT_BTREE *btree; WT_COLLATOR *collator; WT_INSERT *ins, **insp, *last_ins; - WT_INSERT_HEAD *inshead; WT_ITEM key; size_t match, skiphigh, skiplow; int cmp, i; btree = S2BT(session); collator = btree->collator; - inshead = cbt->ins_head; cmp = 0; /* -Wuninitialized */ /* @@ -86,7 +83,7 @@ __wt_search_insert( */ match = skiphigh = skiplow = 0; ins = last_ins = NULL; - for (i = WT_SKIP_MAXDEPTH - 1, insp = &inshead->head[i]; i >= 0;) { + for (i = WT_SKIP_MAXDEPTH - 1, insp = &ins_head->head[i]; i >= 0;) { if ((ins = *insp) == NULL) { cbt->next_stack[i] = NULL; cbt->ins_stack[i--] = insp--; @@ -128,6 +125,7 @@ __wt_search_insert( */ cbt->compare = -cmp; cbt->ins = (ins != NULL) ? ins : last_ins; + cbt->ins_head = ins_head; return (0); } @@ -212,6 +210,7 @@ __wt_row_search(WT_SESSION_IMPL *session, WT_BTREE *btree; WT_COLLATOR *collator; WT_DECL_RET; + WT_INSERT_HEAD *ins_head; WT_ITEM *item; WT_PAGE *page; WT_PAGE_INDEX *pindex, *parent_pindex; @@ -486,24 +485,18 @@ leaf_only: cbt->slot = WT_ROW_SLOT(page, page->pg_row_d); F_SET(cbt, WT_CBT_SEARCH_SMALLEST); - cbt->ins_head = WT_ROW_INSERT_SMALLEST(page); + ins_head = WT_ROW_INSERT_SMALLEST(page); } else { cbt->slot = WT_ROW_SLOT(page, page->pg_row_d + (page->pg_row_entries - 1)); - cbt->ins_head = WT_ROW_INSERT_SLOT(page, cbt->slot); + ins_head = WT_ROW_INSERT_SLOT(page, cbt->slot); } - WT_ERR( - __wt_search_insert_append(session, cbt, srch_key, &done)); + WT_ERR(__search_insert_append( + session, cbt, ins_head, srch_key, &done)); if (done) return (0); - - /* - * Don't leave the insert list head set, code external to the - * search uses it. - */ - cbt->ins_head = NULL; } /* @@ -596,16 +589,16 @@ leaf_match: cbt->compare = 0; cbt->slot = WT_ROW_SLOT(page, page->pg_row_d); F_SET(cbt, WT_CBT_SEARCH_SMALLEST); - cbt->ins_head = WT_ROW_INSERT_SMALLEST(page); + ins_head = WT_ROW_INSERT_SMALLEST(page); } else { cbt->compare = -1; cbt->slot = WT_ROW_SLOT(page, page->pg_row_d + (base - 1)); - cbt->ins_head = WT_ROW_INSERT_SLOT(page, cbt->slot); + ins_head = WT_ROW_INSERT_SLOT(page, cbt->slot); } /* If there's no insert list, we're done. */ - if (WT_SKIP_FIRST(cbt->ins_head) == NULL) + if (WT_SKIP_FIRST(ins_head) == NULL) return (0); /* @@ -613,12 +606,12 @@ leaf_match: cbt->compare = 0; * catch cursors repeatedly inserting at a single point. */ if (insert) { - WT_ERR( - __wt_search_insert_append(session, cbt, srch_key, &done)); + WT_ERR(__search_insert_append( + session, cbt, ins_head, srch_key, &done)); if (done) return (0); } - WT_ERR(__wt_search_insert(session, cbt, srch_key)); + WT_ERR(__wt_search_insert(session, cbt, ins_head, srch_key)); return (0); @@ -667,19 +660,16 @@ __wt_row_random_leaf(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt) /* * If the tree is new (and not empty), it might have a large insert * list. - */ - F_SET(cbt, WT_CBT_SEARCH_SMALLEST); - if ((cbt->ins_head = WT_ROW_INSERT_SMALLEST(page)) == NULL) - return (WT_NOTFOUND); - - /* + * * Walk down the list until we find a level with at least 50 entries, * that's where we'll start rolling random numbers. The value 50 is * used to ignore levels with only a few entries, that is, levels which * are potentially badly skewed. */ - for (ins_head = cbt->ins_head, - level = WT_SKIP_MAXDEPTH - 1; level >= 0; --level) { + F_SET(cbt, WT_CBT_SEARCH_SMALLEST); + if ((ins_head = WT_ROW_INSERT_SMALLEST(page)) == NULL) + return (WT_NOTFOUND); + for (level = WT_SKIP_MAXDEPTH - 1; level >= 0; --level) { start = &ins_head->head[level]; for (entries = 0, stop = start; *stop != NULL; stop = &(*stop)->next[level]) @@ -774,6 +764,7 @@ __wt_row_random_leaf(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt) ins = ins->next[0]; cbt->ins = ins; + cbt->ins_head = ins_head; cbt->compare = 0; return (0); diff --git a/src/conn/conn_api.c b/src/conn/conn_api.c index a53f7d96e64..27977de63b2 100644 --- a/src/conn/conn_api.c +++ b/src/conn/conn_api.c @@ -402,7 +402,7 @@ __wt_encryptor_config(WT_SESSION_IMPL *session, WT_CONFIG_ITEM *cval, { WT_CONNECTION_IMPL *conn; WT_DECL_RET; - WT_ENCRYPTOR *encryptor; + WT_ENCRYPTOR *custom, *encryptor; WT_KEYED_ENCRYPTOR *kenc; WT_NAMED_ENCRYPTOR *nenc; uint64_t bucket, hash; @@ -440,12 +440,13 @@ __wt_encryptor_config(WT_SESSION_IMPL *session, WT_CONFIG_ITEM *cval, WT_ERR(__wt_strndup(session, keyid->str, keyid->len, &kenc->keyid)); encryptor = nenc->encryptor; if (encryptor->customize != NULL) { + custom = NULL; WT_ERR(encryptor->customize(encryptor, &session->iface, - cfg_arg, &encryptor)); - if (encryptor == NULL) - encryptor = nenc->encryptor; - else + cfg_arg, &custom)); + if (custom != NULL) { kenc->owned = 1; + encryptor = custom; + } } WT_ERR(encryptor->sizing(encryptor, &session->iface, &kenc->size_const)); diff --git a/src/conn/conn_dhandle.c b/src/conn/conn_dhandle.c index a3cb26afb27..60136a71b99 100644 --- a/src/conn/conn_dhandle.c +++ b/src/conn/conn_dhandle.c @@ -644,7 +644,7 @@ __wt_conn_dhandle_discard_single( F_SET(S2C(session)->cache, WT_CACHE_CLEAR_WALKS); /* Try to remove the handle, protected by the data handle lock. */ - WT_WITH_HANDLE_LIST_LOCK(session, tret, + WT_WITH_HANDLE_LIST_LOCK(session, tret = __conn_dhandle_remove(session, final)); WT_TRET(tret); diff --git a/src/conn/conn_stat.c b/src/conn/conn_stat.c index 9edc6091b10..08ad105c725 100644 --- a/src/conn/conn_stat.c +++ b/src/conn/conn_stat.c @@ -340,7 +340,7 @@ __statlog_log_one(WT_SESSION_IMPL *session, WT_ITEM *path, WT_ITEM *tmp) * any that match the list of object sources. */ if (conn->stat_sources != NULL) { - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __wt_conn_btree_apply( session, false, NULL, __statlog_apply, NULL)); WT_RET(ret); diff --git a/src/conn/conn_sweep.c b/src/conn/conn_sweep.c index 11fe180d7a4..7628076e605 100644 --- a/src/conn/conn_sweep.c +++ b/src/conn/conn_sweep.c @@ -235,7 +235,7 @@ __sweep_remove_handles(WT_SESSION_IMPL *session) if (!WT_DHANDLE_CAN_DISCARD(dhandle)) continue; - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __sweep_remove_one(session, dhandle)); if (ret == 0) WT_STAT_FAST_CONN_INCR(session, dh_sweep_remove); diff --git a/src/cursor/cur_backup.c b/src/cursor/cur_backup.c index 6d5d68000ee..d7d74da48d4 100644 --- a/src/cursor/cur_backup.c +++ b/src/cursor/cur_backup.c @@ -377,7 +377,7 @@ __backup_all(WT_SESSION_IMPL *session, WT_CURSOR_BACKUP *cb) WT_ERR(__wt_metadata_cursor_release(session, &cursor)); /* Build a list of the file objects that need to be copied. */ - WT_WITH_HANDLE_LIST_LOCK(session, ret, ret = + WT_WITH_HANDLE_LIST_LOCK(session, ret = __wt_meta_btree_apply(session, __backup_list_all_append, NULL)); err: WT_TRET(__wt_metadata_cursor_release(session, &cursor)); diff --git a/src/include/column.i b/src/include/column.i index 9f3e2101f6f..d64e68420a5 100644 --- a/src/include/column.i +++ b/src/include/column.i @@ -11,13 +11,13 @@ * Search a column-store insert list for the next larger record. */ static inline WT_INSERT * -__col_insert_search_gt(WT_INSERT_HEAD *inshead, uint64_t recno) +__col_insert_search_gt(WT_INSERT_HEAD *ins_head, uint64_t recno) { WT_INSERT *ins, **insp; int i; /* If there's no insert chain to search, we're done. */ - if ((ins = WT_SKIP_LAST(inshead)) == NULL) + if ((ins = WT_SKIP_LAST(ins_head)) == NULL) return (NULL); /* Fast path check for targets past the end of the skiplist. */ @@ -29,7 +29,7 @@ __col_insert_search_gt(WT_INSERT_HEAD *inshead, uint64_t recno) * go as far as possible at each level before stepping down to the next. */ ins = NULL; - for (i = WT_SKIP_MAXDEPTH - 1, insp = &inshead->head[i]; i >= 0;) + for (i = WT_SKIP_MAXDEPTH - 1, insp = &ins_head->head[i]; i >= 0;) if (*insp != NULL && recno >= WT_INSERT_RECNO(*insp)) { ins = *insp; /* GTE: keep going at this level */ insp = &(*insp)->next[i]; @@ -50,7 +50,7 @@ __col_insert_search_gt(WT_INSERT_HEAD *inshead, uint64_t recno) * such a record exists before searching. */ if (ins == NULL) - ins = WT_SKIP_FIRST(inshead); + ins = WT_SKIP_FIRST(ins_head); while (recno >= WT_INSERT_RECNO(ins)) ins = WT_SKIP_NEXT(ins); return (ins); @@ -61,13 +61,13 @@ __col_insert_search_gt(WT_INSERT_HEAD *inshead, uint64_t recno) * Search a column-store insert list for the next smaller record. */ static inline WT_INSERT * -__col_insert_search_lt(WT_INSERT_HEAD *inshead, uint64_t recno) +__col_insert_search_lt(WT_INSERT_HEAD *ins_head, uint64_t recno) { WT_INSERT *ins, **insp; int i; /* If there's no insert chain to search, we're done. */ - if ((ins = WT_SKIP_FIRST(inshead)) == NULL) + if ((ins = WT_SKIP_FIRST(ins_head)) == NULL) return (NULL); /* Fast path check for targets before the skiplist. */ @@ -78,7 +78,7 @@ __col_insert_search_lt(WT_INSERT_HEAD *inshead, uint64_t recno) * The insert list is a skip list: start at the highest skip level, then * go as far as possible at each level before stepping down to the next. */ - for (i = WT_SKIP_MAXDEPTH - 1, insp = &inshead->head[i]; i >= 0;) + for (i = WT_SKIP_MAXDEPTH - 1, insp = &ins_head->head[i]; i >= 0;) if (*insp != NULL && recno > WT_INSERT_RECNO(*insp)) { ins = *insp; /* GT: keep going at this level */ insp = &(*insp)->next[i]; @@ -95,14 +95,14 @@ __col_insert_search_lt(WT_INSERT_HEAD *inshead, uint64_t recno) * Search a column-store insert list for an exact match. */ static inline WT_INSERT * -__col_insert_search_match(WT_INSERT_HEAD *inshead, uint64_t recno) +__col_insert_search_match(WT_INSERT_HEAD *ins_head, uint64_t recno) { WT_INSERT **insp, *ret_ins; uint64_t ins_recno; int cmp, i; /* If there's no insert chain to search, we're done. */ - if ((ret_ins = WT_SKIP_LAST(inshead)) == NULL) + if ((ret_ins = WT_SKIP_LAST(ins_head)) == NULL) return (NULL); /* Fast path the check for values at the end of the skiplist. */ @@ -115,7 +115,7 @@ __col_insert_search_match(WT_INSERT_HEAD *inshead, uint64_t recno) * The insert list is a skip list: start at the highest skip level, then * go as far as possible at each level before stepping down to the next. */ - for (i = WT_SKIP_MAXDEPTH - 1, insp = &inshead->head[i]; i >= 0; ) { + for (i = WT_SKIP_MAXDEPTH - 1, insp = &ins_head->head[i]; i >= 0; ) { if (*insp == NULL) { --i; --insp; @@ -143,7 +143,7 @@ __col_insert_search_match(WT_INSERT_HEAD *inshead, uint64_t recno) * Search a column-store insert list, creating a skiplist stack as we go. */ static inline WT_INSERT * -__col_insert_search(WT_INSERT_HEAD *inshead, +__col_insert_search(WT_INSERT_HEAD *ins_head, WT_INSERT ***ins_stack, WT_INSERT **next_stack, uint64_t recno) { WT_INSERT **insp, *ret_ins; @@ -151,15 +151,15 @@ __col_insert_search(WT_INSERT_HEAD *inshead, int cmp, i; /* If there's no insert chain to search, we're done. */ - if ((ret_ins = WT_SKIP_LAST(inshead)) == NULL) + if ((ret_ins = WT_SKIP_LAST(ins_head)) == NULL) return (NULL); /* Fast path appends. */ if (recno >= WT_INSERT_RECNO(ret_ins)) { for (i = 0; i < WT_SKIP_MAXDEPTH; i++) { ins_stack[i] = (i == 0) ? &ret_ins->next[0] : - (inshead->tail[i] != NULL) ? - &inshead->tail[i]->next[i] : &inshead->head[i]; + (ins_head->tail[i] != NULL) ? + &ins_head->tail[i]->next[i] : &ins_head->head[i]; next_stack[i] = NULL; } return (ret_ins); @@ -169,7 +169,7 @@ __col_insert_search(WT_INSERT_HEAD *inshead, * The insert list is a skip list: start at the highest skip level, then * go as far as possible at each level before stepping down to the next. */ - for (i = WT_SKIP_MAXDEPTH - 1, insp = &inshead->head[i]; i >= 0; ) { + for (i = WT_SKIP_MAXDEPTH - 1, insp = &ins_head->head[i]; i >= 0; ) { if ((ret_ins = *insp) == NULL) { next_stack[i] = NULL; ins_stack[i--] = insp--; diff --git a/src/include/extern.h b/src/include/extern.h index a4fd22a290a..3a3d1d9ea92 100644 --- a/src/include/extern.h +++ b/src/include/extern.h @@ -191,7 +191,7 @@ extern int __wt_row_insert_alloc(WT_SESSION_IMPL *session, WT_ITEM *key, u_int s extern int __wt_update_alloc( WT_SESSION_IMPL *session, WT_ITEM *value, WT_UPDATE **updp, size_t *sizep); extern WT_UPDATE *__wt_update_obsolete_check( WT_SESSION_IMPL *session, WT_PAGE *page, WT_UPDATE *upd); extern void __wt_update_obsolete_free( WT_SESSION_IMPL *session, WT_PAGE *page, WT_UPDATE *upd); -extern int __wt_search_insert( WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, WT_ITEM *srch_key); +extern int __wt_search_insert(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt, WT_INSERT_HEAD *ins_head, WT_ITEM *srch_key); extern int __wt_row_search(WT_SESSION_IMPL *session, WT_ITEM *srch_key, WT_REF *leaf, WT_CURSOR_BTREE *cbt, bool insert); extern int __wt_row_random_leaf(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt); extern int __wt_row_random_descent(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt); diff --git a/src/include/meta.h b/src/include/meta.h index d61022c0c44..ac0f5fedac4 100644 --- a/src/include/meta.h +++ b/src/include/meta.h @@ -21,6 +21,7 @@ #define WT_METADATA_TURTLE_SET "WiredTiger.turtle.set" /* Turtle temp file */ #define WT_METADATA_URI "metadata:" /* Metadata alias */ +#define WT_METAFILE "WiredTiger.wt" /* Metadata table */ #define WT_METAFILE_URI "file:WiredTiger.wt" /* Metadata table URI */ #define WT_LAS_URI "file:WiredTigerLAS.wt" /* Lookaside table URI*/ diff --git a/src/include/misc.h b/src/include/misc.h index 78997661851..5dadb1b1484 100644 --- a/src/include/misc.h +++ b/src/include/misc.h @@ -48,6 +48,9 @@ #define WT_ALIGN(n, v) \ ((((uintmax_t)(n)) + ((v) - 1)) & ~(((uintmax_t)(v)) - 1)) +#define WT_ALIGN_NEAREST(n, v) \ + ((((uintmax_t)(n)) + ((v) / 2)) & ~(((uintmax_t)(v)) - 1)) + /* Min, max. */ #define WT_MIN(a, b) ((a) < (b) ? (a) : (b)) #define WT_MAX(a, b) ((a) < (b) ? (b) : (a)) diff --git a/src/include/schema.h b/src/include/schema.h index 88a3a39f8b3..a51030870c1 100644 --- a/src/include/schema.h +++ b/src/include/schema.h @@ -79,27 +79,37 @@ struct __wt_table { #define WT_COLGROUPS(t) WT_MAX((t)->ncolgroups, 1) /* + * WT_WITH_LOCK_WAIT -- + * Wait for a lock, perform an operation, drop the lock. + */ +#define WT_WITH_LOCK_WAIT(session, lock, flag, op) do { \ + if (F_ISSET(session, (flag))) { \ + op; \ + } else { \ + __wt_spin_lock(session, (lock)); \ + F_SET(session, (flag)); \ + op; \ + F_CLR(session, (flag)); \ + __wt_spin_unlock(session, (lock)); \ + } \ +} while (0) + +/* * WT_WITH_LOCK -- * Acquire a lock, perform an operation, drop the lock. */ #define WT_WITH_LOCK(session, ret, lock, flag, op) do { \ ret = 0; \ - if (F_ISSET(session, (flag))) { \ - op; \ - } else if (F_ISSET(session, WT_SESSION_LOCK_NO_WAIT)) { \ + if (!F_ISSET(session, (flag)) && \ + F_ISSET(session, WT_SESSION_LOCK_NO_WAIT)) { \ if ((ret = __wt_spin_trylock(session, (lock))) == 0) { \ F_SET(session, (flag)); \ op; \ F_CLR(session, (flag)); \ __wt_spin_unlock(session, (lock)); \ } \ - } else { \ - __wt_spin_lock(session, (lock)); \ - F_SET(session, (flag)); \ - op; \ - F_CLR(session, (flag)); \ - __wt_spin_unlock(session, (lock)); \ - } \ + } else \ + WT_WITH_LOCK_WAIT(session, lock, flag, op); \ } while (0) /* @@ -113,10 +123,15 @@ struct __wt_table { /* * WT_WITH_HANDLE_LIST_LOCK -- * Acquire the data handle list lock, perform an operation, drop the lock. + * + * Note: always waits because some operations need the handle list lock to + * discard handles, and we only expect it to be held across short + * operations. */ -#define WT_WITH_HANDLE_LIST_LOCK(session, ret, op) \ - WT_WITH_LOCK(session, ret, \ +#define WT_WITH_HANDLE_LIST_LOCK(session, op) \ + WT_WITH_LOCK_WAIT(session, \ &S2C(session)->dhandle_lock, WT_SESSION_LOCKED_HANDLE_LIST, op) + /* * WT_WITH_SCHEMA_LOCK -- * Acquire the schema lock, perform an operation, drop the lock. diff --git a/src/include/swap.h b/src/include/swap.h index 15b7a0d9df9..2040ca88a77 100644 --- a/src/include/swap.h +++ b/src/include/swap.h @@ -7,7 +7,7 @@ */ #if defined(_MSC_VER) && (_MSC_VER >= 1300) -#include <cstdlib> +#include <stdlib.h> #define __wt_bswap16(v) _byteswap_ushort(v) #define __wt_bswap32(v) _byteswap_ulong(v) #define __wt_bswap64(v) _byteswap_uint64(v) diff --git a/src/include/wt_internal.h b/src/include/wt_internal.h index 7ff93b86f92..4533c8cbca0 100644 --- a/src/include/wt_internal.h +++ b/src/include/wt_internal.h @@ -6,6 +6,9 @@ * See the file LICENSE for redistribution information. */ +#ifndef __WT_INTERNAL_H +#define __WT_INTERNAL_H + #if defined(__cplusplus) extern "C" { #endif @@ -368,3 +371,4 @@ union __wt_rand_state; #if defined(__cplusplus) } #endif +#endif /* !__WT_INTERNAL_H */ diff --git a/src/lsm/lsm_cursor.c b/src/lsm/lsm_cursor.c index 1bb9a7238fe..f76b2bfd9ac 100644 --- a/src/lsm/lsm_cursor.c +++ b/src/lsm/lsm_cursor.c @@ -1543,7 +1543,7 @@ __wt_clsm_open(WT_SESSION_IMPL *session, bulk = cval.val != 0; /* Get the LSM tree. */ - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __wt_lsm_tree_get(session, uri, bulk, &lsm_tree)); /* * Check whether the exclusive open for a bulk load succeeded, and diff --git a/src/lsm/lsm_stat.c b/src/lsm/lsm_stat.c index c147cf5774a..76e2ca6185e 100644 --- a/src/lsm/lsm_stat.c +++ b/src/lsm/lsm_stat.c @@ -33,7 +33,7 @@ __curstat_lsm_init( "checkpoint=" WT_CHECKPOINT, NULL, NULL }; locked = false; - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __wt_lsm_tree_get(session, uri, false, &lsm_tree)); WT_RET(ret); WT_ERR(__wt_scr_alloc(session, 0, &uribuf)); diff --git a/src/lsm/lsm_tree.c b/src/lsm/lsm_tree.c index ff6e66fd1a1..ab18e41a2f5 100644 --- a/src/lsm/lsm_tree.c +++ b/src/lsm/lsm_tree.c @@ -315,7 +315,7 @@ __wt_lsm_tree_create(WT_SESSION_IMPL *session, char *tmpconfig; /* If the tree is open, it already exists. */ - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __wt_lsm_tree_get(session, uri, false, &lsm_tree)); if (ret == 0) { __wt_lsm_tree_release(session, lsm_tree); @@ -447,7 +447,7 @@ __wt_lsm_tree_create(WT_SESSION_IMPL *session, * tracking macros handle cleaning up on failure. */ if (ret == 0) - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __lsm_tree_open(session, uri, true, &lsm_tree)); if (ret == 0) __wt_lsm_tree_release(session, lsm_tree); @@ -961,7 +961,7 @@ __wt_lsm_tree_drop( locked = false; /* Get the LSM tree. */ - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __wt_lsm_tree_get(session, name, true, &lsm_tree)); WT_RET(ret); @@ -997,7 +997,7 @@ __wt_lsm_tree_drop( err: if (locked) WT_TRET(__wt_lsm_tree_writeunlock(session, lsm_tree)); - WT_WITH_HANDLE_LIST_LOCK(session, tret, + WT_WITH_HANDLE_LIST_LOCK(session, tret = __lsm_tree_discard(session, lsm_tree, false)); WT_TRET(tret); return (ret); @@ -1023,7 +1023,7 @@ __wt_lsm_tree_rename(WT_SESSION_IMPL *session, locked = false; /* Get the LSM tree. */ - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __wt_lsm_tree_get(session, olduri, true, &lsm_tree)); WT_RET(ret); @@ -1073,7 +1073,7 @@ err: if (locked) * Discard this LSM tree structure. The first operation on the renamed * tree will create a new one. */ - WT_WITH_HANDLE_LIST_LOCK(session, tret, + WT_WITH_HANDLE_LIST_LOCK(session, tret = __lsm_tree_discard(session, lsm_tree, false)); WT_TRET(tret); return (ret); @@ -1098,7 +1098,7 @@ __wt_lsm_tree_truncate( locked = false; /* Get the LSM tree. */ - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __wt_lsm_tree_get(session, name, true, &lsm_tree)); WT_RET(ret); @@ -1137,7 +1137,7 @@ err: if (locked) * the last good version of the metadata will be used, resulting * in a valid (not truncated) tree. */ - WT_WITH_HANDLE_LIST_LOCK(session, tret, + WT_WITH_HANDLE_LIST_LOCK(session, tret = __lsm_tree_discard(session, lsm_tree, false)); WT_TRET(tret); } @@ -1237,7 +1237,7 @@ __wt_lsm_compact(WT_SESSION_IMPL *session, const char *name, bool *skipp) /* Tell __wt_schema_worker not to look inside the LSM tree. */ *skipp = true; - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __wt_lsm_tree_get(session, name, false, &lsm_tree)); WT_RET(ret); @@ -1435,7 +1435,7 @@ __wt_lsm_tree_worker(WT_SESSION_IMPL *session, locked = false; exclusive = FLD_ISSET(open_flags, WT_DHANDLE_EXCLUSIVE); - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __wt_lsm_tree_get(session, uri, exclusive, &lsm_tree)); WT_RET(ret); diff --git a/src/lsm/lsm_work_unit.c b/src/lsm/lsm_work_unit.c index 4faa25967ad..d5d81df6785 100644 --- a/src/lsm/lsm_work_unit.c +++ b/src/lsm/lsm_work_unit.c @@ -272,7 +272,7 @@ __wt_lsm_checkpoint_chunk(WT_SESSION_IMPL *session, if (F_ISSET(chunk, WT_LSM_CHUNK_ONDISK) && !F_ISSET(chunk, WT_LSM_CHUNK_STABLE) && !chunk->evicted) { - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __lsm_discard_handle(session, chunk->uri, NULL)); if (ret == 0) chunk->evicted = 1; @@ -506,7 +506,7 @@ __lsm_drop_file(WT_SESSION_IMPL *session, const char *uri) * * This will fail with EBUSY if the file is still in use. */ - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __lsm_discard_handle(session, uri, WT_CHECKPOINT)); WT_RET(ret); diff --git a/src/meta/meta_turtle.c b/src/meta/meta_turtle.c index 7182bb0fe5f..ec93f526f89 100644 --- a/src/meta/meta_turtle.c +++ b/src/meta/meta_turtle.c @@ -153,10 +153,11 @@ int __wt_turtle_init(WT_SESSION_IMPL *session) { WT_DECL_RET; - bool exist, exist_incr; + bool exist_backup, exist_incr, exist_turtle, load; char *metaconf; metaconf = NULL; + load = false; /* * Discard any turtle setup file left-over from previous runs. This @@ -179,13 +180,30 @@ __wt_turtle_init(WT_SESSION_IMPL *session) * done. */ WT_RET(__wt_exist(session, WT_INCREMENTAL_BACKUP, &exist_incr)); - WT_RET(__wt_exist(session, WT_METADATA_TURTLE, &exist)); - if (exist) { + WT_RET(__wt_exist(session, WT_METADATA_BACKUP, &exist_backup)); + WT_RET(__wt_exist(session, WT_METADATA_TURTLE, &exist_turtle)); + if (exist_turtle) { if (exist_incr) WT_RET_MSG(session, EINVAL, "Incremental backup after running recovery " "is not allowed."); - } else { + /* + * If we have a backup file and metadata and turtle files, + * we want to recreate the metadata from the backup. + */ + if (exist_backup) { + WT_RET(__wt_msg(session, "Both %s and %s exist. " + "Recreating metadata from backup.", + WT_METADATA_TURTLE, WT_METADATA_BACKUP)); + WT_RET(__wt_remove_if_exists( + session, WT_METAFILE)); + WT_RET(__wt_remove_if_exists( + session, WT_METADATA_TURTLE)); + load = true; + } + } else + load = true; + if (load) { if (exist_incr) F_SET(S2C(session), WT_CONN_WAS_BACKUP); diff --git a/src/reconcile/rec_write.c b/src/reconcile/rec_write.c index f60da40a0d2..032b3fa31fa 100644 --- a/src/reconcile/rec_write.c +++ b/src/reconcile/rec_write.c @@ -1896,15 +1896,18 @@ __wt_split_page_size(WT_BTREE *btree, uint32_t maxpagesize) * we don't waste space when we write). */ a = maxpagesize; /* Don't overflow. */ - split_size = (uint32_t) - WT_ALIGN((a * (u_int)btree->split_pct) / 100, btree->allocsize); + split_size = (uint32_t)WT_ALIGN_NEAREST( + (a * (u_int)btree->split_pct) / 100, btree->allocsize); /* - * If the result of that calculation is the same as the allocation unit - * (that happens if the maximum size is the same size as an allocation - * unit, use a percentage of the maximum page size). + * Respect the configured split percentage if the calculated split + * size is either zero or a full page. The user has either configured + * an allocation size that matches the page size, or a split + * percentage that is close to zero or one hundred. Rounding is going + * to provide a worse outcome than having a split point that doesn't + * fall on an allocation size boundary in those cases. */ - if (split_size == btree->allocsize) + if (split_size == 0 || split_size == maxpagesize) split_size = (uint32_t)((a * (u_int)btree->split_pct) / 100); return (split_size); @@ -3293,6 +3296,17 @@ supd_check_complete: } } + bnd->entries = r->entries; + /* 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, + "Reconciliation creating a page with %" PRIu32 + " entries, memory footprint %" PRIu64 + ", page count %" PRIu32 ", %s, split state: %d\n", + r->entries, r->page->memory_footprint, r->bnd_next, + F_ISSET(r, WT_EVICTING) ? "evict" : "checkpoint", + r->bnd_state)); + WT_ERR(__wt_bt_write(session, buf, addr, &addr_size, false, bnd->already_compressed)); WT_ERR(__wt_strndup(session, addr, addr_size, &bnd->addr.addr)); diff --git a/src/schema/schema_create.c b/src/schema/schema_create.c index 8cdcbbcad54..25bbd496798 100644 --- a/src/schema/schema_create.c +++ b/src/schema/schema_create.c @@ -550,8 +550,9 @@ __create_index(WT_SESSION_IMPL *session, /* Make sure that the configuration is valid. */ WT_ERR(__wt_schema_open_index( session, table, idxname, strlen(idxname), &idx)); - if (!exists) - WT_ERR(__fill_index(session, table, idx)); + + /* If there is data in the table, fill the index. */ + WT_ERR(__fill_index(session, table, idx)); err: __wt_free(session, idxconf); __wt_free(session, origconf); diff --git a/src/schema/schema_drop.c b/src/schema/schema_drop.c index 6ac76930c9a..ead8cc45c62 100644 --- a/src/schema/schema_drop.c +++ b/src/schema/schema_drop.c @@ -29,7 +29,7 @@ __drop_file( return (EINVAL); /* Close all btree handles associated with this file. */ - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __wt_conn_dhandle_close_all(session, uri, force)); WT_RET(ret); diff --git a/src/schema/schema_rename.c b/src/schema/schema_rename.c index 4ec126394dd..21402ed9332 100644 --- a/src/schema/schema_rename.c +++ b/src/schema/schema_rename.c @@ -30,7 +30,7 @@ __rename_file( return (EINVAL); /* Close any btree handles in the file. */ - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __wt_conn_dhandle_close_all(session, uri, false)); WT_ERR(ret); diff --git a/src/schema/schema_worker.c b/src/schema/schema_worker.c index a2fe5244c4d..b5ee3bb7f7d 100644 --- a/src/schema/schema_worker.c +++ b/src/schema/schema_worker.c @@ -49,7 +49,7 @@ __wt_schema_worker(WT_SESSION_IMPL *session, * any open file handles, including checkpoints. */ if (FLD_ISSET(open_flags, WT_DHANDLE_EXCLUSIVE)) { - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __wt_conn_dhandle_close_all( session, uri, false)); WT_ERR(ret); @@ -63,7 +63,7 @@ __wt_schema_worker(WT_SESSION_IMPL *session, } else if (ret == EBUSY) { WT_ASSERT(session, !FLD_ISSET( open_flags, WT_DHANDLE_EXCLUSIVE)); - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __wt_conn_btree_apply_single_ckpt( session, uri, file_func, cfg)); } diff --git a/src/session/session_dhandle.c b/src/session/session_dhandle.c index d89bb8d133c..1ee3342442c 100644 --- a/src/session/session_dhandle.c +++ b/src/session/session_dhandle.c @@ -454,7 +454,7 @@ __session_get_dhandle( * We didn't find a match in the session cache, search the shared * handle list and cache the handle we find. */ - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __session_find_shared_dhandle(session, uri, checkpoint)); if (ret == 0) ret = __session_add_dhandle(session, NULL); @@ -511,7 +511,7 @@ __wt_session_get_btree(WT_SESSION_IMPL *session, WT_RET(__wt_writeunlock(session, dhandle->rwlock)); WT_WITH_SCHEMA_LOCK(session, ret, - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __wt_session_get_btree( session, uri, checkpoint, cfg, flags))); diff --git a/src/support/hash_city.c b/src/support/hash_city.c index f12bfc9a70c..7a700aa809c 100644 --- a/src/support/hash_city.c +++ b/src/support/hash_city.c @@ -57,7 +57,6 @@ * compromising on hash quality. */ -#include <string.h> #include "wt_internal.h" /* diff --git a/src/support/hash_fnv.c b/src/support/hash_fnv.c index 35e7e5f3a73..83dd2574099 100644 --- a/src/support/hash_fnv.c +++ b/src/support/hash_fnv.c @@ -83,7 +83,6 @@ * Share and Enjoy! :-) */ -#include <stdlib.h> #include "wt_internal.h" /* diff --git a/src/txn/txn_ckpt.c b/src/txn/txn_ckpt.c index 725e46acb0c..6a2c1eef826 100644 --- a/src/txn/txn_ckpt.c +++ b/src/txn/txn_ckpt.c @@ -184,7 +184,7 @@ __checkpoint_apply(WT_SESSION_IMPL *session, const char *cfg[], session->ckpt_handle[i].dhandle, ret = (*op)(session, cfg)); else - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __wt_conn_btree_apply_single(session, session->ckpt_handle[i].name, NULL, op, cfg)); WT_RET(ret); @@ -387,7 +387,7 @@ __txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[]) */ WT_WITH_SCHEMA_LOCK(session, ret, WT_WITH_TABLE_LOCK(session, ret, - WT_WITH_HANDLE_LIST_LOCK(session, ret, + WT_WITH_HANDLE_LIST_LOCK(session, ret = __checkpoint_apply_all( session, cfg, __wt_checkpoint_list, NULL)))); WT_ERR(ret); diff --git a/test/packing/intpack-test.c b/test/packing/intpack-test.c index a48f9fc4fe4..08cc3807725 100644 --- a/test/packing/intpack-test.c +++ b/test/packing/intpack-test.c @@ -26,10 +26,10 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include <assert.h> - #include "wt_internal.h" /* For __wt_XXX */ +#include <assert.h> + int main(void) { diff --git a/test/packing/intpack-test2.c b/test/packing/intpack-test2.c index 68f794f0bf5..7555d2724e7 100644 --- a/test/packing/intpack-test2.c +++ b/test/packing/intpack-test2.c @@ -26,10 +26,10 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include <assert.h> - #include "wt_internal.h" /* For __wt_XXX */ +#include <assert.h> + int main(void) { diff --git a/test/packing/intpack-test3.c b/test/packing/intpack-test3.c index 2bce88c3568..2ebc01f9e2e 100644 --- a/test/packing/intpack-test3.c +++ b/test/packing/intpack-test3.c @@ -26,10 +26,10 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include <assert.h> - #include "wt_internal.h" /* For __wt_XXX */ +#include <assert.h> + void test_value(int64_t); void test_spread(int64_t, int64_t, int64_t); diff --git a/test/packing/packing-test.c b/test/packing/packing-test.c index 1d2194bee50..9b7105d7d4a 100644 --- a/test/packing/packing-test.c +++ b/test/packing/packing-test.c @@ -26,10 +26,10 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include <assert.h> - #include "wt_internal.h" /* For __wt_XXX */ +#include <assert.h> + static void check(const char *fmt, ...) { diff --git a/test/suite/test_backup05.py b/test/suite/test_backup05.py index 8b176d0f7d7..8ffeb6752df 100644 --- a/test/suite/test_backup05.py +++ b/test/suite/test_backup05.py @@ -71,7 +71,7 @@ class test_backup05(wttest.WiredTigerTestCase, suite_subprocess): session.verify(self.uri) conn.close() - def test_backup(self): + def backup(self): '''Check manual fsyncLock backup strategy''' # Here's the strategy: @@ -95,5 +95,9 @@ class test_backup05(wttest.WiredTigerTestCase, suite_subprocess): else: self.session.verify(self.uri) + def test_backup(self): + with self.expectedStdoutPattern('Recreating metadata'): + self.backup() + if __name__ == '__main__': wttest.run() diff --git a/test/suite/test_txn04.py b/test/suite/test_txn04.py index de49c5fe235..bbd6ce8c4e2 100644 --- a/test/suite/test_txn04.py +++ b/test/suite/test_txn04.py @@ -121,17 +121,14 @@ class test_txn04(wttest.WiredTigerTestCase, suite_subprocess): cmd += self.backup_dir self.runWt(cmd.split()) - self.exception='false' backup_conn_params = 'log=(enabled,file_max=%s)' % self.logmax backup_conn = self.wiredtiger_open(self.backup_dir, backup_conn_params) try: self.check(backup_conn.open_session(), None, committed) - except: - self.exception='true' finally: backup_conn.close() - def test_ops(self): + def ops(self): self.session.create(self.uri, self.create_params) c = self.session.open_cursor(self.uri, None, 'overwrite') # Set up the table with entries for 1-5. @@ -149,7 +146,6 @@ class test_txn04(wttest.WiredTigerTestCase, suite_subprocess): # The runWt command closes our connection and sessions so # we need to reopen them here. self.hot_backup(None, committed) - self.assertEqual(True, self.exception == 'false') c = self.session.open_cursor(self.uri, None, 'overwrite') c.set_value(1) # Then do the given modification. @@ -192,14 +188,13 @@ class test_txn04(wttest.WiredTigerTestCase, suite_subprocess): # Check the state after each commit/rollback. self.check_all(current, committed) - # Backup the target we modified. We expect that running - # recovery now will generate an exception if we committed. + # Backup the target we modified and verify the data. # print 'Call hot_backup with ' + self.uri self.hot_backup(self.uri, committed) - if txn == 'commit': - self.assertEqual(True, self.exception == 'true') - else: - self.assertEqual(True, self.exception == 'false') + + def test_ops(self): + with self.expectedStdoutPattern('Recreating metadata'): + self.ops() if __name__ == '__main__': wttest.run() |