summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@wiredtiger.com>2015-02-04 12:27:46 +1100
committerMichael Cahill <michael.cahill@wiredtiger.com>2015-02-04 12:27:46 +1100
commit5adbba6cb1a4e87ac7c4faa5c5b0dbada30f8c66 (patch)
tree7e8025d5d82573272af3293d01509882279235d4
parent0ac6575b5e2f88a8bbfbad9fc17ada5e9247145b (diff)
parentecf5849f9b489d916104df01b48440b6cb6129ee (diff)
downloadmongo-5adbba6cb1a4e87ac7c4faa5c5b0dbada30f8c66.tar.gz
Merge branch 'develop' into discard-dirty
-rw-r--r--src/btree/bt_cursor.c4
-rw-r--r--src/btree/bt_debug.c4
-rw-r--r--src/btree/bt_huffman.c27
-rw-r--r--src/btree/bt_slvg.c12
-rw-r--r--src/btree/bt_split.c51
-rw-r--r--src/btree/bt_stat.c7
-rw-r--r--src/btree/col_srch.c1
-rw-r--r--src/btree/row_srch.c3
-rw-r--r--src/conn/conn_sweep.c8
-rw-r--r--src/include/btmem.h13
-rw-r--r--src/include/btree.i3
-rw-r--r--src/include/connection.h2
-rw-r--r--src/include/cursor.i5
-rw-r--r--src/reconcile/rec_write.c8
-rw-r--r--test/suite/test_huffman01.py76
-rw-r--r--test/suite/test_huffman02.py67
16 files changed, 248 insertions, 43 deletions
diff --git a/src/btree/bt_cursor.c b/src/btree/bt_cursor.c
index c115e44e573..1960e4605ef 100644
--- a/src/btree/bt_cursor.c
+++ b/src/btree/bt_cursor.c
@@ -782,7 +782,9 @@ __wt_btcur_next_random(WT_CURSOR_BTREE *cbt)
WT_RET(__cursor_func_init(cbt, 1));
- WT_ERR(__wt_row_random(session, cbt));
+ WT_WITH_PAGE_INDEX(session,
+ ret = __wt_row_random(session, cbt));
+ WT_ERR(ret);
if (__cursor_valid(cbt, &upd))
WT_ERR(__wt_kv_return(session, cbt, upd));
else
diff --git a/src/btree/bt_debug.c b/src/btree/bt_debug.c
index 5a3342e62a9..e84a63695f9 100644
--- a/src/btree/bt_debug.c
+++ b/src/btree/bt_debug.c
@@ -548,7 +548,9 @@ __debug_page(WT_DBG *ds, WT_PAGE *page, uint32_t flags)
session = ds->session;
/* Dump the page metadata. */
- WT_RET(__debug_page_metadata(ds, page));
+ WT_WITH_PAGE_INDEX(session,
+ ret = __debug_page_metadata(ds, page));
+ WT_RET(ret);
/* Dump the page. */
switch (page->type) {
diff --git a/src/btree/bt_huffman.c b/src/btree/bt_huffman.c
index c1cf3431c3b..c31b3f2fdf1 100644
--- a/src/btree/bt_huffman.c
+++ b/src/btree/bt_huffman.c
@@ -128,6 +128,30 @@ static const struct __wt_huffman_table __wt_huffman_nytenglish[] = {
static int __wt_huffman_read(WT_SESSION_IMPL *,
WT_CONFIG_ITEM *, struct __wt_huffman_table **, u_int *, u_int *);
+#define WT_HUFFMAN_CONFIG_VALID(str, len) \
+ (WT_STRING_CASE_MATCH("english", (str), (len)) || \
+ WT_PREFIX_MATCH((str), "utf8") || WT_PREFIX_MATCH((str), "utf16"))
+
+/*
+ * __btree_huffman_config --
+ * Verify the key or value strings passed in.
+ */
+static int
+__btree_huffman_config(WT_SESSION_IMPL *session,
+ WT_CONFIG_ITEM *key_conf, WT_CONFIG_ITEM *value_conf)
+{
+ if (key_conf->len != 0 &&
+ !WT_HUFFMAN_CONFIG_VALID(key_conf->str, key_conf->len))
+ WT_RET_MSG(
+ session, EINVAL, "illegal Huffman key configuration");
+ if (value_conf->len != 0 &&
+ !WT_HUFFMAN_CONFIG_VALID(value_conf->str, value_conf->len))
+ WT_RET_MSG(
+ session, EINVAL, "illegal Huffman value configuration");
+ return (0);
+
+}
+
/*
* __wt_btree_huffman_open --
* Configure Huffman encoding for the tree.
@@ -150,6 +174,7 @@ __wt_btree_huffman_open(WT_SESSION_IMPL *session)
__wt_config_gets_none(session, cfg, "huffman_value", &value_conf));
if (key_conf.len == 0 && value_conf.len == 0)
return (0);
+ WT_RET(__btree_huffman_config(session, &key_conf, &value_conf));
switch (btree->type) { /* Check file type compatibility. */
case BTREE_COL_FIX:
@@ -311,6 +336,8 @@ __wt_huffman_read(WT_SESSION_IMPL *session, WT_CONFIG_ITEM *ip,
tp->frequency = (uint32_t)frequency;
}
+ if (ret == EOF)
+ ret = 0;
*entriesp = lineno - 1;
*tablep = table;
diff --git a/src/btree/bt_slvg.c b/src/btree/bt_slvg.c
index fbc3890f23b..1cf616a2f6b 100644
--- a/src/btree/bt_slvg.c
+++ b/src/btree/bt_slvg.c
@@ -294,12 +294,16 @@ __wt_bt_salvage(WT_SESSION_IMPL *session, WT_CKPT *ckptbase, const char *cfg[])
switch (ss->page_type) {
case WT_PAGE_COL_FIX:
case WT_PAGE_COL_VAR:
- WT_ERR(
- __slvg_col_build_internal(session, leaf_cnt, ss));
+ WT_WITH_PAGE_INDEX(session,
+ ret = __slvg_col_build_internal(
+ session, leaf_cnt, ss));
+ WT_ERR(ret);
break;
case WT_PAGE_ROW_LEAF:
- WT_ERR(
- __slvg_row_build_internal(session, leaf_cnt, ss));
+ WT_WITH_PAGE_INDEX(session,
+ ret = __slvg_row_build_internal(
+ session, leaf_cnt, ss));
+ WT_ERR(ret);
break;
}
diff --git a/src/btree/bt_split.c b/src/btree/bt_split.c
index 5b6aa9a3be0..05af1a2f885 100644
--- a/src/btree/bt_split.c
+++ b/src/btree/bt_split.c
@@ -42,7 +42,8 @@ __split_oldest_gen(WT_SESSION_IMPL *session)
* Add a new entry into the session's split stash list.
*/
static int
-__split_stash_add(WT_SESSION_IMPL *session, void *p, size_t len)
+__split_stash_add(
+ WT_SESSION_IMPL *session, uint64_t split_gen, void *p, size_t len)
{
WT_SPLIT_STASH *stash;
@@ -53,7 +54,7 @@ __split_stash_add(WT_SESSION_IMPL *session, void *p, size_t len)
session->split_stash_cnt + 1, &session->split_stash));
stash = session->split_stash + session->split_stash_cnt++;
- stash->split_gen = WT_ATOMIC_ADD8(S2C(session)->split_gen, 1);
+ stash->split_gen = split_gen;
stash->p = p;
stash->len = len;
@@ -143,14 +144,14 @@ __wt_split_stash_discard_all(
* it to be freed otherwise.
*/
static int
-__split_safe_free(WT_SESSION_IMPL *session, int exclusive, void *p, size_t s)
+__split_safe_free(WT_SESSION_IMPL *session,
+ uint64_t split_gen, int exclusive, void *p, size_t s)
{
/*
* We have swapped something in a page: if we don't have exclusive
* access, check whether there are other threads in the same tree.
*/
- if (!exclusive &&
- __split_oldest_gen(session) == S2C(session)->split_gen + 1)
+ if (!exclusive && __split_oldest_gen(session) > split_gen)
exclusive = 1;
if (exclusive) {
@@ -158,7 +159,7 @@ __split_safe_free(WT_SESSION_IMPL *session, int exclusive, void *p, size_t s)
return (0);
}
- return (__split_stash_add(session, p, s));
+ return (__split_stash_add(session, split_gen, p, s));
}
/*
@@ -380,6 +381,7 @@ __split_deepen(WT_SESSION_IMPL *session, WT_PAGE *parent, uint32_t children)
WT_REF **alloc_refp;
WT_REF *child_ref, **child_refp, *parent_ref, **parent_refp, *ref;
size_t child_incr, parent_decr, parent_incr, size;
+ uint64_t split_gen;
uint32_t chunk, i, j, remain, slots;
int panic;
void *p;
@@ -514,6 +516,7 @@ __split_deepen(WT_SESSION_IMPL *session, WT_PAGE *parent, uint32_t children)
* needs to be paid.
*/
WT_INTL_INDEX_SET(parent, alloc_index);
+ split_gen = WT_ATOMIC_ADD8(S2C(session)->split_gen, 1);
panic = 1;
#ifdef HAVE_DIAGNOSTIC
@@ -583,7 +586,7 @@ __split_deepen(WT_SESSION_IMPL *session, WT_PAGE *parent, uint32_t children)
* be using the new index.
*/
size = sizeof(WT_PAGE_INDEX) + pindex->entries * sizeof(WT_REF *);
- WT_ERR(__split_safe_free(session, 0, pindex, size));
+ WT_ERR(__split_safe_free(session, split_gen, 0, pindex, size));
parent_decr += size;
/*
@@ -784,7 +787,7 @@ __wt_multi_to_ref(WT_SESSION_IMPL *session,
static int
__split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new,
uint32_t new_entries, size_t parent_decr, size_t parent_incr,
- int exclusive, int ref_discard)
+ int exclusive, int ref_discard, uint64_t *split_genp)
{
WT_DECL_RET;
WT_IKEY *ikey;
@@ -792,6 +795,7 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new,
WT_PAGE_INDEX *alloc_index, *pindex;
WT_REF **alloc_refp, *next_ref, *parent_ref;
size_t size;
+ uint64_t split_gen;
uint32_t children, i, j;
uint32_t deleted_entries, parent_entries, result_entries;
int complete, hazard, locked;
@@ -898,6 +902,7 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new,
* to threads descending the tree.
*/
WT_INTL_INDEX_SET(parent, alloc_index);
+ split_gen = *split_genp = WT_ATOMIC_ADD8(S2C(session)->split_gen, 1);
alloc_index = NULL;
#ifdef HAVE_DIAGNOSTIC
@@ -944,7 +949,7 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new,
if (ikey != NULL) {
size = sizeof(WT_IKEY) + ikey->size;
WT_TRET(__split_safe_free(
- session, 0, ikey, size));
+ session, split_gen, 0, ikey, size));
parent_decr += size;
}
/*
@@ -962,7 +967,7 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new,
}
WT_TRET(__split_safe_free(
- session, 0, next_ref, sizeof(WT_REF)));
+ session, split_gen, 0, next_ref, sizeof(WT_REF)));
parent_decr += sizeof(WT_REF);
}
}
@@ -972,7 +977,7 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new,
* Add it to the session discard list, to be freed when it's safe.
*/
size = sizeof(WT_PAGE_INDEX) + pindex->entries * sizeof(WT_REF *);
- WT_TRET(__split_safe_free(session, exclusive, pindex, size));
+ WT_TRET(__split_safe_free(session, split_gen, exclusive, pindex, size));
parent_decr += size;
/*
@@ -1027,8 +1032,7 @@ __split_parent(WT_SESSION_IMPL *session, WT_REF *ref, WT_REF **ref_new,
*/
uint64_t __a, __b;
__a = parent->memory_footprint;
- WT_WITH_PAGE_INDEX(session,
- ret = __split_deepen(session, parent, children));
+ ret = __split_deepen(session, parent, children);
__b = parent->memory_footprint;
if (__b * 2 >= __a)
F_SET_ATOMIC(parent, WT_PAGE_REFUSE_DEEPEN);
@@ -1076,6 +1080,7 @@ __wt_split_insert(WT_SESSION_IMPL *session, WT_REF *ref, int *splitp)
WT_PAGE *page, *right;
WT_REF *child, *split_ref[2] = { NULL, NULL };
size_t page_decr, parent_decr, parent_incr, right_incr;
+ uint64_t split_gen;
int i;
*splitp = 0;
@@ -1328,8 +1333,8 @@ __wt_split_insert(WT_SESSION_IMPL *session, WT_REF *ref, int *splitp)
* longer locked, so we cannot safely look at it.
*/
page = NULL;
- if ((ret = __split_parent(
- session, ref, split_ref, 2, parent_decr, parent_incr, 0, 0)) != 0) {
+ if ((ret = __split_parent(session, ref, split_ref, 2,
+ parent_decr, parent_incr, 0, 0, &split_gen)) != 0) {
/*
* Move the insert list element back to the original page list.
* For simplicity, the previous skip list pointers originally
@@ -1366,8 +1371,8 @@ __wt_split_insert(WT_SESSION_IMPL *session, WT_REF *ref, int *splitp)
*/
if (ikey != NULL)
WT_TRET(__split_safe_free(
- session, 0, ikey, sizeof(WT_IKEY) + ikey->size));
- WT_TRET(__split_safe_free(session, 0, ref, sizeof(WT_REF)));
+ session, split_gen, 0, ikey, sizeof(WT_IKEY) + ikey->size));
+ WT_TRET(__split_safe_free(session, split_gen, 0, ref, sizeof(WT_REF)));
/*
* A note on error handling: if we completed the split, return success,
@@ -1450,6 +1455,7 @@ __wt_split_multi(WT_SESSION_IMPL *session, WT_REF *ref, int exclusive)
WT_PAGE_MODIFY *mod;
WT_REF **ref_new;
size_t parent_decr, parent_incr;
+ uint64_t split_gen;
uint32_t i, new_entries;
page = ref->page;
@@ -1479,8 +1485,8 @@ __wt_split_multi(WT_SESSION_IMPL *session, WT_REF *ref, int exclusive)
parent_decr += sizeof(WT_IKEY) + ikey->size;
/* Split into the parent. */
- WT_ERR(__split_parent(session,
- ref, ref_new, new_entries, parent_decr, parent_incr, exclusive, 1));
+ WT_ERR(__split_parent(session, ref, ref_new, new_entries,
+ parent_decr, parent_incr, exclusive, 1, &split_gen));
__wt_free(session, ref_new);
@@ -1503,9 +1509,10 @@ __wt_split_multi(WT_SESSION_IMPL *session, WT_REF *ref, int exclusive)
* safe.
*/
if (ikey != NULL)
- WT_TRET(__split_safe_free(
- session, exclusive, ikey, sizeof(WT_IKEY) + ikey->size));
- WT_TRET(__split_safe_free(session, exclusive, ref, sizeof(WT_REF)));
+ WT_TRET(__split_safe_free(session, split_gen, exclusive,
+ ikey, sizeof(WT_IKEY) + ikey->size));
+ WT_TRET(__split_safe_free(session, split_gen, exclusive,
+ ref, sizeof(WT_REF)));
/*
* A note on error handling: if we completed the split, return success,
diff --git a/src/btree/bt_stat.c b/src/btree/bt_stat.c
index d9ff2a6af1e..b7108b52395 100644
--- a/src/btree/bt_stat.c
+++ b/src/btree/bt_stat.c
@@ -45,8 +45,11 @@ __wt_btree_stat_init(WT_SESSION_IMPL *session, WT_CURSOR_STAT *cst)
next_walk = NULL;
while ((ret =
- __wt_tree_walk(session, &next_walk, 0)) == 0 && next_walk != NULL)
- WT_RET(__stat_page(session, next_walk->page, stats));
+ __wt_tree_walk(session, &next_walk, 0)) == 0 && next_walk != NULL) {
+ WT_WITH_PAGE_INDEX(session,
+ ret = __stat_page(session, next_walk->page, stats));
+ WT_RET(ret);
+ }
return (ret == WT_NOTFOUND ? 0 : ret);
}
diff --git a/src/btree/col_srch.c b/src/btree/col_srch.c
index 4c418f91de0..db1b565b439 100644
--- a/src/btree/col_srch.c
+++ b/src/btree/col_srch.c
@@ -49,6 +49,7 @@ restart: page = current->page;
WT_ASSERT(session, current->key.recno == page->pg_intl_recno);
+ WT_ASSERT(session, session->split_gen != 0);
pindex = WT_INTL_INDEX_COPY(page);
base = pindex->entries;
descent = pindex->index[base - 1];
diff --git a/src/btree/row_srch.c b/src/btree/row_srch.c
index 036e11bec6d..9967c5ecb0c 100644
--- a/src/btree/row_srch.c
+++ b/src/btree/row_srch.c
@@ -195,6 +195,7 @@ restart: page = current->page;
if (page->type != WT_PAGE_ROW_INT)
break;
+ WT_ASSERT(session, session->split_gen != 0);
pindex = WT_INTL_INDEX_COPY(page);
/*
@@ -487,6 +488,7 @@ restart:
if (page->type != WT_PAGE_ROW_INT)
break;
+ WT_ASSERT(session, session->split_gen != 0);
pindex = WT_INTL_INDEX_COPY(page);
descent = pindex->index[
__wt_random(session->rnd) % pindex->entries];
@@ -521,6 +523,7 @@ restart:
*/
cbt->ref = current;
cbt->compare = 0;
+ WT_ASSERT(session, session->split_gen != 0);
pindex = WT_INTL_INDEX_COPY(btree->root.page);
cbt->slot = pindex->entries < 2 ?
__wt_random(session->rnd) % page->pg_row_entries : 0;
diff --git a/src/conn/conn_sweep.c b/src/conn/conn_sweep.c
index 01f08aa5f07..a5bd8e1343c 100644
--- a/src/conn/conn_sweep.c
+++ b/src/conn/conn_sweep.c
@@ -32,14 +32,14 @@ __sweep(WT_SESSION_IMPL *session)
dhandle_next = SLIST_NEXT(dhandle, l);
if (WT_IS_METADATA(dhandle))
continue;
- if (dhandle->session_inuse == 0 && dhandle->timeofdeath == 0) {
+ if (dhandle->session_inuse != 0 ||
+ now <= dhandle->timeofdeath + WT_DHANDLE_SWEEP_WAIT)
+ continue;
+ if (dhandle->timeofdeath == 0) {
dhandle->timeofdeath = now;
WT_STAT_FAST_CONN_INCR(session, dh_conn_tod);
continue;
}
- if (dhandle->session_inuse != 0 ||
- now <= dhandle->timeofdeath + WT_DHANDLE_SWEEP_WAIT)
- continue;
/*
* We have a candidate for closing; if it's open, acquire an
diff --git a/src/include/btmem.h b/src/include/btmem.h
index 176d4733f7d..ef6f9b40414 100644
--- a/src/include/btmem.h
+++ b/src/include/btmem.h
@@ -192,7 +192,7 @@ struct __wt_page_modify {
uint64_t inmem_split_txn;
/* Dirty bytes added to the cache. */
- uint64_t bytes_dirty;
+ size_t bytes_dirty;
/*
* When pages are reconciled, the result is one or more replacement
@@ -532,7 +532,7 @@ struct __wt_page {
#define WT_READGEN_STEP 100
uint64_t read_gen;
- uint64_t memory_footprint; /* Memory attached to the page */
+ size_t memory_footprint; /* Memory attached to the page */
#define WT_PAGE_IS_INTERNAL(page) \
((page)->type == WT_PAGE_COL_INT || (page)->type == WT_PAGE_ROW_INT)
@@ -1004,11 +1004,18 @@ struct __wt_insert_head {
* already have a split generation, leave it alone. If our caller is examining
* an index, we don't want the oldest split generation to move forward and
* potentially free it.
+ *
+ * Check that we haven't raced with a split_gen update after publishing: we
+ * rely on the published value not being missed when scanning for the oldest
+ * active split_gen.
*/
#define WT_ENTER_PAGE_INDEX(session) do { \
uint64_t __prev_split_gen = (session)->split_gen; \
if (__prev_split_gen == 0) \
- WT_PUBLISH((session)->split_gen, S2C(session)->split_gen)
+ do { \
+ WT_PUBLISH((session)->split_gen, \
+ S2C(session)->split_gen); \
+ } while ((session)->split_gen != S2C(session)->split_gen)
#define WT_LEAVE_PAGE_INDEX(session) \
if (__prev_split_gen == 0) \
diff --git a/src/include/btree.i b/src/include/btree.i
index f2eee8b8999..a0cbb23f126 100644
--- a/src/include/btree.i
+++ b/src/include/btree.i
@@ -258,8 +258,7 @@ __wt_page_refp(WT_SESSION_IMPL *session,
WT_PAGE_INDEX *pindex;
uint32_t i;
- WT_ASSERT(session,
- WT_SESSION_TXN_STATE(session)->snap_min != WT_TXN_NONE);
+ WT_ASSERT(session, session->split_gen != 0);
/*
* Copy the parent page's index value: the page can split at any time,
diff --git a/src/include/connection.h b/src/include/connection.h
index ff34b014ecf..7b94a7ea94b 100644
--- a/src/include/connection.h
+++ b/src/include/connection.h
@@ -146,7 +146,7 @@ struct __wt_connection_impl {
WT_FH *lock_fh; /* Lock file handle */
- uint64_t split_gen; /* Generation number for splits */
+ volatile uint64_t split_gen; /* Generation number for splits */
/*
* The connection keeps a cache of data handles. The set of handles
diff --git a/src/include/cursor.i b/src/include/cursor.i
index 8fa9790e096..d261635706e 100644
--- a/src/include/cursor.i
+++ b/src/include/cursor.i
@@ -164,8 +164,11 @@ __wt_cursor_dhandle_decr_use(WT_SESSION_IMPL *session)
dhandle = session->dhandle;
+ /* If we close a handle with a time of death set, clear it. */
WT_ASSERT(session, dhandle->session_inuse > 0);
- (void)WT_ATOMIC_SUB4(dhandle->session_inuse, 1);
+ if (WT_ATOMIC_SUB4(dhandle->session_inuse, 1) == 0 &&
+ dhandle->timeofdeath != 0)
+ dhandle->timeofdeath = 0;
}
/*
diff --git a/src/reconcile/rec_write.c b/src/reconcile/rec_write.c
index f5925cb4d3d..be66309c77f 100644
--- a/src/reconcile/rec_write.c
+++ b/src/reconcile/rec_write.c
@@ -440,8 +440,11 @@ __wt_reconcile(WT_SESSION_IMPL *session,
* Root pages are special, splits have to be done, we can't put it off
* as the parent's problem any more.
*/
- if (__wt_ref_is_root(ref))
- return (__rec_root_write(session, page, flags));
+ if (__wt_ref_is_root(ref)) {
+ WT_WITH_PAGE_INDEX(session,
+ ret = __rec_root_write(session, page, flags));
+ return (ret);
+ }
/*
* Otherwise, mark the page's parent dirty.
@@ -504,6 +507,7 @@ __rec_root_write(WT_SESSION_IMPL *session, WT_PAGE *page, uint32_t flags)
WT_ILLEGAL_VALUE(session);
}
+ WT_ASSERT(session, session->split_gen != 0);
pindex = WT_INTL_INDEX_COPY(next);
for (i = 0; i < mod->mod_multi_entries; ++i) {
WT_ERR(__wt_multi_to_ref(session,
diff --git a/test/suite/test_huffman01.py b/test/suite/test_huffman01.py
new file mode 100644
index 00000000000..0c413025e1d
--- /dev/null
+++ b/test/suite/test_huffman01.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2015 MongoDB, Inc.
+# Public Domain 2008-2014 WiredTiger, Inc.
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+import os
+from suite_subprocess import suite_subprocess
+from wtscenario import multiply_scenarios, number_scenarios
+import wiredtiger, wttest
+
+# test_huffman01.py
+# Huffman key and value configurations
+# Basic smoke-test of huffman key and value settings.
+class test_huffman01(wttest.WiredTigerTestCase, suite_subprocess):
+ """
+ Test basic operations
+ """
+ table_name = 'table:test_huff'
+
+ huffkey = [
+ ('none', dict(huffkey='huffman_key=none',kfile=None)),
+ ('english', dict(huffkey='huffman_key=english',kfile=None)),
+ ('English', dict(huffkey='huffman_key=English',kfile=None)),
+ ('utf8', dict(huffkey='huffman_key=utf8t8file',kfile='t8file')),
+ ('utf16', dict(huffkey='huffman_key=utf16t16file',kfile='t16file')),
+ ]
+ huffval = [
+ ('none', dict(huffval=',huffman_value=none',vfile=None)),
+ ('english', dict(huffval=',huffman_value=english',vfile=None)),
+ ('English', dict(huffval=',huffman_value=English',vfile=None)),
+ ('utf8', dict(huffval=',huffman_value=utf8t8file',vfile='t8file')),
+ ('utf16', dict(huffval=',huffman_value=utf16t16file',vfile='t16file')),
+ ]
+ scenarios = number_scenarios(multiply_scenarios('.', huffkey, huffval))
+
+ def test_huffman(self):
+ dir = self.conn.get_home()
+ if self.kfile != None:
+ # For the UTF settings write some made-up frequency information.
+ f = open(dir + '/' + self.kfile, 'w')
+ f.write('48 546233\n49 460946\n')
+ f.close()
+ # if self.vfile != None and not os.path.exists(self.vfile):
+ if self.vfile != None:
+ f = open(dir + '/' + self.vfile, 'w')
+ # For the UTF settings write some made-up frequency information.
+ f.write('50 546233\n51 460946\n')
+ f.close()
+ config=self.huffkey + self.huffval
+ self.session.create(self.table_name, config)
+
+if __name__ == '__main__':
+ wttest.run()
diff --git a/test/suite/test_huffman02.py b/test/suite/test_huffman02.py
new file mode 100644
index 00000000000..d5fd83ab53e
--- /dev/null
+++ b/test/suite/test_huffman02.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2015 MongoDB, Inc.
+# Public Domain 2008-2014 WiredTiger, Inc.
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+import os
+from suite_subprocess import suite_subprocess
+from wtscenario import multiply_scenarios, number_scenarios
+import wiredtiger, wttest
+
+# test_huffman02.py
+# Huffman key and value configurations with bad settings
+class test_huffman02(wttest.WiredTigerTestCase, suite_subprocess):
+ """
+ Test basic operations
+ """
+ table_name = 'table:test_huff'
+
+ huffkey = [
+ ('none', dict(huffkey='huffman_key=none')),
+ ('english', dict(huffkey='huffman_key=english')),
+ ('bad', dict(huffkey='huffman_key=bad')),
+ ]
+ huffval = [
+ ('bad', dict(huffval=',huffman_value=bad')),
+ ]
+ scenarios = number_scenarios(multiply_scenarios('.', huffkey, huffval))
+
+ def test_huffman(self):
+ gotException = False
+ expectMessage = 'illegal Huffman'
+ config=self.huffkey + self.huffval
+ with self.expectedStderrPattern(expectMessage):
+ try:
+ self.pr('expect an error message...')
+ self.session.create(self.table_name, config)
+ except wiredtiger.WiredTigerError as e:
+ gotException = True
+ self.pr('got expected exception: ' + str(e))
+ self.assertTrue(str(e).find('nvalid argument') >= 0)
+ self.assertTrue(gotException, 'expected exception')
+
+if __name__ == '__main__':
+ wttest.run()