Compare commits

...

40 Commits
1.3.5 ... 1.3.7

Author SHA1 Message Date
Michael Cahill
247fe0f8ce Cut release 1.3.7. 2012-11-09 23:02:36 +11:00
Michael Cahill
450a29d1bc When verbose == 2, copy status output to stdout. 2012-11-09 22:35:35 +11:00
Michael Cahill
04faa7f24e Change the default configuration of ex_test_perf: 4KB pages, no prefix compression. 2012-11-09 22:27:49 +11:00
Michael Cahill
729c4ce6db Use a separate thread for creation of Bloom filters for the newest, unmerged LSM chunks. 2012-11-09 22:25:02 +11:00
Michael Cahill
40a775d5bf Write the metadata after creating missing Bloom filters. 2012-11-09 15:11:33 +11:00
Michael Cahill
e2256d6888 Drop any old Bloom filter before creating a new one -- we may have been interrupted in between creating it and updating the metadata. 2012-11-09 15:11:31 +11:00
Michael Cahill
4166623d77 Clean up some complaints from s_all. 2012-11-09 15:08:24 +11:00
Michael Cahill
366ef0f287 Update auto-generated files. 2012-11-09 15:08:23 +11:00
Michael Cahill
d3aab45b96 Clarify the docs for the default buffer_alignment setting. 2012-11-09 14:50:56 +11:00
Michael Cahill
e040d5a3d9 ex_test_perf.c:456:11: error: 'elapsed' may be used uninitialized in this function 2012-11-09 12:00:57 +11:00
Michael Cahill
f46350b57f ex_test_perf.c:456:11: error: 'elapsed' may be used uninitialized in this function 2012-11-09 11:50:30 +11:00
Alex Gorrod
5d8c1e28bc Clean up error handling in ex_test_perf and add option to populate using
multiple threads.
2012-11-08 14:24:27 +11:00
Michael Cahill
3844f602ff Added tag 1.3.6 for changeset 8b91f84675fd 2012-11-06 17:02:56 +11:00
Michael Cahill
647f83d11a Cut release 1.3.6. 2012-11-06 17:02:28 +11:00
Michael Cahill
7bedb693a6 Report errors from the LSM checkpoint thread. 2012-11-06 16:22:40 +11:00
Michael Cahill
bf6bc01e3f For update-only LSM cursors, only open a cursor in the primary chunk. 2012-11-06 16:17:37 +11:00
Michael Cahill
a1359905ad If there is only a single candidate page for eviction, don't skip it. 2012-11-05 11:21:47 +11:00
Michael Cahill
8246befcd8 Only evict pages with generation numbers in the bottom quarter of the range we see. Fix a bug where the read generation number wrapped at 2**3. 2012-11-05 10:51:55 +11:00
Michael Cahill
61e5b885a2 Add a per-btree cache priority, currently only used for Bloom filters. 2012-11-05 10:30:55 +11:00
Michael Cahill
f347a3301d Only switch trees in an LSM cursor if the primary chunk is on disk. 2012-11-02 17:30:17 +11:00
Michael Cahill
1e14492ea0 LSM: clear the "merging" flag on chunks that are not included in a merge. 2012-11-02 13:56:59 +11:00
Michael Cahill
a1b08d168e Cache the hash values used for Bloom filter lookups, rather than hashing for each Bloom filter in an LSM tree. 2012-11-01 16:36:36 +11:00
Michael Cahill
a31f708a1c Support multiple LSM merge threads with the "lsm_merge_threads" config key. Use IDs rather than array index to mark the start chunk in a merge, in case we race with another thread. 2012-11-01 16:25:51 +11:00
Michael Cahill
e1189da479 Include all of the chosen chunks in a merge. Only pin the current chunk in an LSM cursor if it is writeable. 2012-11-01 15:52:41 +11:00
Michael Cahill
64c54763f0 Minor cleanup in the loop to drop old chunks from an LSM tree. 2012-11-01 15:52:30 +11:00
Michael Cahill
a5aba41271 LSM: only track cursors on the primary chunk if it is not yet on disk. 2012-11-01 15:52:02 +11:00
Michael Cahill
ac1bd50106 Create missing Bloom filters when reading from an LSM tree if "lsm_bloom_newest"is set. 2012-11-01 15:50:21 +11:00
Michael Cahill
bca4607b9e LSM: only save a Bloom URI in the metadata after it is successfully created. 2012-11-01 15:14:19 +11:00
Keith Bostic
57db817d67 fix up some comments. 2012-10-29 12:13:25 +00:00
Michael Cahill
c507009cee Respect "compression=none" in test/format. 2012-10-29 11:00:08 +11:00
Michael Cahill
c062a33272 gettimeofday needs sys/time.h 2012-10-29 10:43:16 +11:00
Michael Cahill
2bce92c180 Remove auto-generated files from the tree. 2012-10-29 10:40:10 +11:00
Keith Bostic
45c1e2a5a3 Move test program software into the public domain, if anyone wants to
cut-and-paste from it, that's fine with us.
2012-10-26 13:22:45 +00:00
Keith Bostic
38591db0fd Rename the WiredTiger installed libraries to libwiredtiger_XXX.
Quit installing the nop and reverse_collator libraries.

Rename the session.create block_compressor configuration strings
"bzip2_compress" to "bzip2", and "snappy_compress" to "snappy".

Add documentation for configuring the built-in bzip2 and snappy
configuration in applications.
2012-10-26 11:23:29 +00:00
Keith Bostic
466e7ade5c Replace test/format's bzip configuration string with compression, which
can take one of four arguments (none, bzip, ext, snappy), change format
to run snappy compression if the library is available.
2012-10-26 08:42:25 +00:00
Keith Bostic
82a6530951 WT_ATOMIC_ADD/WT_ATOMIC_SUB return values. 2012-10-26 08:14:32 +00:00
Keith Bostic
9c371c5a84 Replace test/format's bzip configuration string with compression, which
can take one of four arguments (none, bzip, ext, snappy), change format
to run snappy compression if the library is available.

Use gettimeofday's usecs value to seed the random number generator, and
always seed the random number generator, even if it's a threaded run.
2012-10-26 08:10:42 +00:00
Keith Bostic
0250344b90 For smoke-testing runs with just a few ops, it's possible threads is
larger than ops, don't drop core.
2012-10-26 08:10:42 +00:00
Keith Bostic
6792cd8115 Typo, WiredTiger's configuration script isn't in the dist directory. 2012-10-26 08:10:42 +00:00
Keith Bostic
8fa690dce6 Use gettimeofday() usecs to seed with a better "random" number. 2012-10-26 08:10:42 +00:00
68 changed files with 1986 additions and 721 deletions

View File

@@ -15,3 +15,4 @@ ef3ccde04cb28060319be900a2d31c88071933f6 1.3.0
961b8482202543635417399aca5b1093e5ba5cbd 1.3.2
01380d42b30c74937b7d801062d744823a47fd3d 1.3.3
df87effe7cd3239e3666a76312bae77b92090d98 1.3.4
8b91f84675fd67259b1f513e3f84786501cbc16c 1.3.6

63
NEWS
View File

@@ -1,3 +1,66 @@
WiredTiger release 1.3.7, 2012-11-09
------------------------------------
This release fixes a bug and improves performance with Bloom filters:
* Drop any old Bloom filter before creating a new one -- we may have been
interrupted in between creating it and updating the metadata. Write the
metadata after creating missing Bloom filters.
* Use a separate thread for creation of Bloom filters for the newest,
unmerged LSM chunks.
* Changes to the ex_test_perf example: change the default configuration to
4KB pages and disable prefix compression. Change the "-i" command line
option to be a simple count of records to insert. Clean up error
handling and add option to populate using multiple threads.
* Clarify the docs for the default buffer_alignment setting.
WiredTiger release 1.3.6, 2012-11-06
------------------------------------
This is a bugfix and performance tuning release. The changes are as follows:
* Rename the WiredTiger installed modules to libwiredtiger_XXX. Don't install
the nop and reverse collator modules.
* Replace test/format's bzip configuration string with compression, which can
take one of four arguments (none, bzip, ext, snappy), change format to run
snappy compression if the library is available.
* Rename the builtin block compressor names from "bzip2_compress" to "bzip2",
and from "snappy_compress" to "snappy".
* Support multiple LSM merge threads with the "lsm_merge_threads" config key.
Use IDs rather than array index to mark the start chunk in a merge, in case
we race with another thread.
* Cache the hash values used for Bloom filter lookups, rather than hashing for
each Bloom filter in an LSM tree.
* Only switch trees in an LSM cursor if the primary chunk is on disk.
* Add a per-btree cache priority, currently only used to make it more likely
for Bloom filter pages to stay in cache.
* Only evict pages with read generations in the bottom quarter of the range we
see. Fix a 32-bit wrapping bug in assigning read generations.
* For update-only LSM cursors, only open a cursor in the primary chunk.
* LSM: Report errors from the checkpoint thread.
* LSM: only save a Bloom URI in the metadata after it is successfully created.
* LSM: Create missing Bloom filters when reading from an LSM tree if
"lsm_bloom_newest"is set.
* LSM: Include all of the chosen chunks in a merge. Only pin the current chunk
in an LSM cursor if it is writeable.
WiredTiger release 1.3.5, 2012-10-26
------------------------------------

4
README
View File

@@ -1,6 +1,6 @@
WiredTiger 1.3.5: (October 26, 2012)
WiredTiger 1.3.7: (November 9, 2012)
This is version 1.3.5 of WiredTiger.
This is version 1.3.7 of WiredTiger.
WiredTiger documentation can be found at:

View File

@@ -1,6 +1,6 @@
WIREDTIGER_VERSION_MAJOR=1
WIREDTIGER_VERSION_MINOR=3
WIREDTIGER_VERSION_PATCH=5
WIREDTIGER_VERSION_PATCH=7
WIREDTIGER_VERSION="$WIREDTIGER_VERSION_MAJOR.$WIREDTIGER_VERSION_MINOR.$WIREDTIGER_VERSION_PATCH"
WIREDTIGER_RELEASE_DATE=`date "+%B %e, %Y"`

View File

@@ -8,9 +8,9 @@
bench/tcbench
examples/c
ext/collators/reverse
ext/compressors/bzip2_compress BZIP2
ext/compressors/nop_compress
ext/compressors/snappy_compress SNAPPY
ext/compressors/bzip2 BZIP2
ext/compressors/nop
ext/compressors/snappy SNAPPY
lang/python PYTHON
test/bloom
test/fops

View File

@@ -2,8 +2,8 @@ dnl build by dist/s_version
VERSION_MAJOR=1
VERSION_MINOR=3
VERSION_PATCH=5
VERSION_STRING='"WiredTiger 1.3.5: (October 26, 2012)"'
VERSION_PATCH=7
VERSION_STRING='"WiredTiger 1.3.7: (November 9, 2012)"'
AC_SUBST(VERSION_MAJOR)
AC_SUBST(VERSION_MINOR)

View File

@@ -1,2 +1,2 @@
dnl WiredTiger product version for AC_INIT. Maintained by dist/s_version
1.3.5
1.3.7

21
dist/api_data.py vendored
View File

@@ -113,6 +113,9 @@ lsm_config = [
Config('lsm_merge_max', '15', r'''
the maximum number of chunks to include in a merge operation''',
min='2', max='100'),
Config('lsm_merge_threads', '1', r'''
the number of thread to perform merge operations''',
min='1', max='10'), # !!! max must match WT_LSM_MAX_WORKERS
]
# Per-file configuration
@@ -450,9 +453,9 @@ methods = {
'wiredtiger_open' : Method(connection_runtime_config + [
Config('buffer_alignment', '-1', r'''
in-memory alignment (in bytes) for buffers used for I/O. By
default, a platform-specific alignment value is used (512 bytes
on Linux systems, zero elsewhere)''',
in-memory alignment (in bytes) for buffers used for I/O. The default
value of -1 indicates that a platform-specific alignment value should
be used (512 bytes on Linux systems, zero elsewhere)''',
min='-1', max='1MB'),
Config('create', 'false', r'''
create the database if it does not exist''',
@@ -462,13 +465,15 @@ methods = {
list, such as <code>"direct_io=[data]"</code>''',
type='list', choices=['data', 'log']),
Config('extensions', '', r'''
list of extensions to load. Optional values are passed as the
\c config parameter to WT_CONNECTION::load_extension. Complex
paths may need quoting, for example,
<code>extensions=("/path/to/ext.so"="entry=my_entry")</code>''',
list of shared library extensions to load (using dlopen).
Optional values are passed as the \c config parameter to
WT_CONNECTION::load_extension. Complex paths may require
quoting, for example,
<code>extensions=("/path/ext.so"="entry=my_entry")</code>''',
type='list'),
Config('hazard_max', '1000', r'''
maximum number of simultaneous hazard references per session handle''',
maximum number of simultaneous hazard references per session
handle''',
min='15'),
Config('logging', 'false', r'''
enable logging''',

1
dist/s_funcs.list vendored
View File

@@ -3,6 +3,7 @@ WT_CURDUMP_PASS
__bit_ffs
__bit_nclr
__wt_bloom_drop
__wt_bloom_get
__wt_bm_addr_stderr
__wt_btree_lex_compare
__wt_config_getone

4
dist/s_string.ok vendored
View File

@@ -9,6 +9,7 @@ ADDR
AJZ
API
APIs
ARGS
Alakuijala
Alloc
Athlon
@@ -33,10 +34,10 @@ Bsearch
Btree
Bzip
CAS
CDLMRSTdehikrsuv
CELL's
CELLs
CKPT
CLMPRSTdehikrsuv
CLR
COL's
CONCAT
@@ -205,6 +206,7 @@ WinNT
WiredTiger
WiredTiger's
WiredTigerCheckpoint
WiredTigerHome
WithSeeds
Wuninitialized
XP

View File

@@ -395,6 +395,25 @@ session_ops(WT_SESSION *session)
"table:mytable", "key_format=S,value_format=S");
/*! [Create a table] */
/*
* This example code gets run, and the compression libraries might not
* be loaded, causing the create to fail. The documentation requires
* the code snippets, use #ifdef's to avoid running it.
*/
#ifdef MIGHT_NOT_RUN
/*! [Create a bzip2 compressed table] */
ret = session->create(session,
"table:mytable",
"block_compressor=bzip2,key_format=S,value_format=S");
/*! [Create a bzip2 compressed table] */
/*! [Create a snappy compressed table] */
ret = session->create(session,
"table:mytable",
"block_compressor=snappy,key_format=S,value_format=S");
/*! [Create a snappy compressed table] */
#endif
/*! [Create a cache-resident object] */
ret = session->create(session,
"table:mytable", "key_format=r,value_format=S,cache_resident=true");
@@ -891,16 +910,44 @@ main(void)
{
int ret;
system("rm -rf WiredTigerHome && mkdir WiredTigerHome");
{
/*! [Open a connection] */
WT_CONNECTION *conn;
const char *home = "WT_TEST";
ret = wiredtiger_open(home, NULL, "create,transactional", &conn);
/*! [Open a connection] */
(void)conn->close(conn, NULL);
ret = wiredtiger_open(
"WiredTigerHome", NULL, "create,transactional", &conn);
/*! [Open a connection] */
}
/*
* This example code gets run, and the compression libraries might not
* be installed, causing the open to fail. The documentation requires
* the code snippets, use #ifdef's to avoid running it.
*/
#ifdef MIGHT_NOT_RUN
{
/*! [Configure bzip2 extension] */
WT_CONNECTION *conn;
ret = wiredtiger_open("WiredTigerHome", NULL,
"create,"
"extensions=[\"/usr/local/lib/wiredtiger_bzip2.so\"]", &conn);
/*! [Configure bzip2 extension] */
}
{
/*! [Configure snappy extension] */
WT_CONNECTION *conn;
ret = wiredtiger_open("WiredTigerHome", NULL,
"create,"
"extensions=[\"/usr/local/lib/wiredtiger_snappy.so\"]", &conn);
/*! [Configure snappy extension] */
}
#endif
/*! [Get the WiredTiger library version #1] */
printf("WiredTiger version %s\n", wiredtiger_version(NULL, NULL, NULL));
/*! [Get the WiredTiger library version #1] */

View File

@@ -39,6 +39,9 @@
#include <wiredtiger.h>
#define ATOMIC_ADD(v, val) \
__sync_add_and_fetch(&(v), val)
typedef struct {
const char *home;
const char *uri;
@@ -52,6 +55,7 @@ typedef struct {
uint32_t report_interval;
uint32_t read_time;
uint32_t elapsed_time;
uint32_t populate_threads;/* Number of populate threads. */
uint32_t read_threads; /* Number of read threads. */
uint32_t verbose;
uint32_t stat_thread; /* Whether to create a stat thread. */
@@ -65,20 +69,33 @@ typedef struct {
} CONFIG;
/* Forward function definitions. */
int execute_populate(CONFIG *);
int execute_reads(CONFIG *);
int populate(CONFIG *);
int get_next_op(uint64_t *);
int lprintf(CONFIG *cfg, int err, uint32_t level, const char *fmt, ...)
#ifdef __GNUC__
__attribute__((format (printf, 4, 5)))
#endif
;
void *populate_thread(void *);
void print_config(CONFIG *);
void *read_thread(void *);
int setup_log_file(CONFIG *);
int start_threads(CONFIG *, int, pthread_t **, void *(*func)(void *));
void *stat_worker(void *);
int stop_threads(CONFIG *, int, pthread_t *);
void usage(void);
#define DEFAULT_LSM_CONFIG \
"key_format=S,value_format=S,exclusive," \
"leaf_page_max=4kb,internal_page_max=64kb,allocation_size=4kb,"
/* Default values - these are tiny, we want the basic run to be fast. */
CONFIG default_cfg = {
"WT_TEST", /* home */
"lsm:test", /* uri */
"create,cache_size=200MB", /* conn_config */
"key_format=S,value_format=S", /* table_config */
DEFAULT_LSM_CONFIG, /* table_config */
1, /* create */
14023954, /* rand_seed */
5000, /* icount */
@@ -87,6 +104,7 @@ CONFIG default_cfg = {
2, /* report_interval */
2, /* read_time */
0, /* elapsed_time */
1, /* populate_threads */
2, /* read_threads */
0, /* verbose */
0, /* stat_thread */
@@ -100,8 +118,8 @@ CONFIG small_cfg = {
"WT_TEST", /* home */
"lsm:test", /* uri */
"create,cache_size=500MB", /* conn_config */
"key_format=S,value_format=S,lsm_chunk_size=5MB,"
"leaf_page_max=16k,internal_page_max=16kb", /* table_config */
DEFAULT_LSM_CONFIG /* table_config */
"lsm_chunk_size=5MB,",
1, /* create */
14023954, /* rand_seed */
500000, /* icount 0.5 million */
@@ -110,6 +128,7 @@ CONFIG small_cfg = {
10, /* report_interval */
20, /* read_time */
0, /* elapsed_time */
1, /* populate_threads */
8, /* read_threads */
0, /* verbose */
0, /* stat_thread */
@@ -123,8 +142,8 @@ CONFIG med_cfg = {
"WT_TEST", /* home */
"lsm:test", /* uri */
"create,cache_size=1GB", /* conn_config */
"key_format=S,value_format=S,lsm_chunk_size=20MB,"
"leaf_page_max=16k,internal_page_max=16kb", /* table_config */
DEFAULT_LSM_CONFIG /* table_config */
"lsm_chunk_size=20MB,",
1, /* create */
14023954, /* rand_seed */
50000000, /* icount 50 million */
@@ -133,6 +152,7 @@ CONFIG med_cfg = {
20, /* report_interval */
100, /* read_time */
0, /* elapsed_time */
1, /* populate_threads */
16, /* read_threads */
0, /* verbose */
0, /* stat_thread */
@@ -146,8 +166,8 @@ CONFIG large_cfg = {
"WT_TEST", /* home */
"lsm:test", /* uri */
"create,cache_size=2GB", /* conn_config */
"key_format=S,value_format=S,lsm_chunk_size=50MB,"
"leaf_page_max=16k,internal_page_max=16kb", /* table_config */
DEFAULT_LSM_CONFIG /* table_config */
"lsm_chunk_size=50MB,",
1, /* create */
14023954, /* rand_seed */
500000000, /* icount 500 million */
@@ -156,6 +176,7 @@ CONFIG large_cfg = {
20, /* report_interval */
600, /* read_time */
0, /* elapsed_time */
1, /* populate_threads */
16, /* read_threads */
0, /* verbose */
0, /* stat_thread */
@@ -169,9 +190,10 @@ const char *debug_cconfig = "verbose=[lsm]";
const char *debug_tconfig = "";
/* Global values shared by threads. */
uint64_t nops;
int running;
int stat_running;
uint64_t g_nops;
int g_running;
int g_stat_running;
uint32_t g_threads_quit; /* For tracking threads that exit early. */
void *
read_thread(void *arg)
@@ -181,34 +203,125 @@ read_thread(void *arg)
WT_SESSION *session;
WT_CURSOR *cursor;
char *key_buf;
int ret;
int ret, search_ret;
session = NULL;
key_buf = NULL;
cfg = (CONFIG *)arg;
conn = cfg->conn;
key_buf = calloc(cfg->key_sz, 1);
if (key_buf == NULL)
return (arg);
if (key_buf == NULL) {
ret = ENOMEM;
goto err;
}
if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) {
fprintf(stderr,
"open_session failed in read thread: %d\n", ret);
return (NULL);
lprintf(cfg, ret, 0,
"open_session failed in read thread");
goto err;
}
if ((ret = session->open_cursor(session, cfg->uri,
NULL, NULL, &cursor)) != 0) {
fprintf(stderr, "open_cursor failed in read thread: %d\n", ret);
return (NULL);
lprintf(cfg, ret, 0,
"open_cursor failed in read thread");
goto err;
}
while (running) {
++nops;
sprintf(key_buf, "%d", rand() % cfg->icount);
while (g_running) {
++g_nops;
/* Get a value in range, avoid zero. */
sprintf(key_buf, "%d", (rand() % (cfg->icount - 1)) + 1);
cursor->set_key(cursor, key_buf);
cursor->search(cursor);
/* Report errors and continue. */
if ((search_ret = cursor->search(cursor)) != 0)
lprintf(cfg, search_ret, 0,
"Search failed for: %s", key_buf);
}
session->close(session, NULL);
free(key_buf);
err: if (ret != 0)
++g_threads_quit;
if (session != NULL)
session->close(session, NULL);
if (key_buf != NULL)
free(key_buf);
return (arg);
}
/* Retrieve an ID for the next insert operation. */
int get_next_op(uint64_t *op)
{
*op = ATOMIC_ADD(g_nops, 1);
return (0);
}
void *
populate_thread(void *arg)
{
CONFIG *cfg;
WT_CONNECTION *conn;
WT_CURSOR *cursor;
WT_SESSION *session;
char *data_buf, *key_buf;
int ret;
uint64_t op;
cfg = (CONFIG *)arg;
conn = cfg->conn;
session = NULL;
data_buf = key_buf = NULL;
cfg->phase = LSM_TEST_PERF_POP;
data_buf = calloc(cfg->data_sz, 1);
if (data_buf == NULL) {
lprintf(cfg, ENOMEM, 0, "Populate data buffer");
goto err;
}
key_buf = calloc(cfg->key_sz, 1);
if (key_buf == NULL) {
lprintf(cfg, ENOMEM, 0, "Populate key buffer");
goto err;
}
/* Open a session for the current thread's work. */
if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) {
lprintf(cfg, ret, 0,
"Error opening a session on %s", cfg->home);
goto err;
}
/* Can only use bulk load single threaded. */
if ((ret = session->open_cursor(
session, cfg->uri, NULL,
cfg->populate_threads == 1 ? "bulk" : "", &cursor)) != 0) {
lprintf(cfg, ret, 0, "Error opening cursor %s", cfg->uri);
goto err;
}
memset(data_buf, 'a', cfg->data_sz - 1);
cursor->set_value(cursor, data_buf);
/* Populate the database. */
while (1) {
get_next_op(&op);
if (op > cfg->icount)
break;
sprintf(key_buf, "%"PRIu64, op);
cursor->set_key(cursor, key_buf);
if ((ret = cursor->insert(cursor)) != 0) {
lprintf(cfg, ret, 0, "Failed inserting");
goto err;
}
}
/* To ensure managing thread knows if we exited early. */
err: if (ret != 0)
++g_threads_quit;
if (session != NULL)
session->close(session, NULL);
if (data_buf)
free(data_buf);
if (key_buf)
free(key_buf);
return (arg);
}
@@ -226,193 +339,193 @@ stat_worker(void *arg)
struct timeval e;
uint64_t value;
session = NULL;
cfg = (CONFIG *)arg;
conn = cfg->conn;
lsm_uri = NULL;
if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) {
fprintf(stderr,
"open_session failed in read thread: %d\n", ret);
return (NULL);
lprintf(cfg, ret, 0,
"open_session failed in statistics thread.");
goto err;
}
if (strncmp(cfg->uri, "lsm:", strlen("lsm:")) == 0) {
lsm_uri = calloc(
strlen(cfg->uri) + strlen("statistics:") + 1, 1);
if (lsm_uri == NULL) {
fprintf(stderr, "No memory in stat thread.\n");
lprintf(
cfg, ENOMEM, 0, "Statistics thread uri create.");
goto err;
}
sprintf(lsm_uri, "statistics:%s", cfg->uri);
}
while (stat_running) {
while (g_stat_running) {
sleep(cfg->report_interval);
/* Generic header. */
fprintf(cfg->logf, "=======================================\n");
lprintf(cfg, 0, cfg->verbose,
"=======================================");
gettimeofday(&e, NULL);
secs = e.tv_sec + e.tv_usec / 1000000.0;
secs -= (cfg->phase_start_time.tv_sec +
cfg->phase_start_time.tv_usec / 1000000.0);
if (secs == 0)
++secs;
fprintf(cfg->logf,
"%s completed: %" PRIu64", elapsed time: %.2f\n",
lprintf(cfg, 0, cfg->verbose,
"%s completed: %" PRIu64", elapsed time: %.2f",
cfg->phase == LSM_TEST_PERF_READ ? "reads" : "inserts",
nops, secs);
g_nops, secs);
/* Report LSM tree stats, if using LSM. */
if (lsm_uri != NULL) {
if ((ret = session->open_cursor(session, lsm_uri,
NULL, NULL, &cursor)) != 0) {
fprintf(stderr,
"open_cursor LSM statistics: %d\n", ret);
lprintf(cfg, ret, 0,
"open_cursor failed in LSM statistics");
goto err;
}
while (
(ret = cursor->next(cursor)) == 0 &&
(ret = cursor->get_value(
cursor, &desc, &pvalue, &value)) == 0)
fprintf(cfg->logf,
"stat:lsm: %s=%s\n", desc, pvalue);
lprintf(cfg, 0, cfg->verbose,
"stat:lsm: %s=%s", desc, pvalue);
cursor->close(cursor);
fprintf(cfg->logf, "\n");
lprintf(cfg, 0, cfg->verbose, "-----------------");
}
/* Dump the connection statistics since last time. */
if ((ret = session->open_cursor(session, "statistics:",
NULL, "statistics_clear", &cursor)) != 0) {
fprintf(stderr,
"open_cursor statistics: %d\n", ret);
lprintf(cfg, ret, 0,
"open_cursor failed in statistics");
goto err;
}
while (
(ret = cursor->next(cursor)) == 0 &&
(ret = cursor->get_value(
cursor, &desc, &pvalue, &value)) == 0)
fprintf(cfg->logf,
"stat:conn: %s=%s\n", desc, pvalue);
lprintf(cfg, 0, cfg->verbose,
"stat:conn: %s=%s", desc, pvalue);
cursor->close(cursor);
}
err: session->close(session, NULL);
err: if (session != NULL)
session->close(session, NULL);
if (lsm_uri != NULL)
free(lsm_uri);
return (arg);
}
int populate(CONFIG *cfg)
int execute_populate(CONFIG *cfg)
{
WT_CONNECTION *conn;
WT_CURSOR *cursor;
WT_SESSION *session;
char *data_buf, *key_buf;
pthread_t *threads;
double secs;
int ret;
uint64_t elapsed, last_ops;
struct timeval e;
conn = cfg->conn;
cfg->phase = LSM_TEST_PERF_POP;
if (cfg->verbose > 0)
fprintf(cfg->logf, "Starting bulk load\n");
lprintf(cfg, 0, 1, "Starting populate threads");
data_buf = calloc(cfg->data_sz, 1);
if (data_buf == NULL)
return (ENOMEM);
key_buf = calloc(cfg->key_sz, 1);
if (key_buf == NULL)
return (ENOMEM);
/* Open a session for the current thread's work. */
/* First create the table. */
if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0) {
fprintf(stderr, "Error opening a session on %s: %s\n",
cfg->home, wiredtiger_strerror(ret));
lprintf(cfg, ret, 0,
"Error opening a session on %s", cfg->home);
return (ret);
}
if ((ret = session->create(
session, cfg->uri, cfg->table_config)) != 0) {
fprintf(stderr, "Error creating table %s: %s\n",
cfg->uri, wiredtiger_strerror(ret));
lprintf(cfg, ret, 0, "Error creating table %s", cfg->uri);
session->close(session, NULL);
return (ret);
}
session->close(session, NULL);
if ((ret = session->open_cursor(
session, cfg->uri, NULL, "bulk", &cursor)) != 0) {
fprintf(stderr, "Error opening cursor %s: %s\n",
cfg->uri, wiredtiger_strerror(ret));
if ((ret = start_threads(
cfg, cfg->populate_threads, &threads, populate_thread)) != 0)
return (ret);
}
memset(data_buf, 'a', cfg->data_sz - 1);
cursor->set_value(cursor, data_buf);
/* Populate the database. */
gettimeofday(&cfg->phase_start_time, NULL);
for (nops = 0; nops < cfg->icount; nops++) {
if (cfg->verbose > 0) {
if (nops % 1000000 == 0)
printf(".");
if (nops % 50000000 == 0)
printf("\n");
}
sprintf(key_buf, "%"PRIu64, nops);
cursor->set_key(cursor, key_buf);
if ((ret = cursor->insert(cursor)) != 0) {
fprintf(stderr, "Failed inserting with: %d\n", ret);
return (ret);
for (cfg->elapsed_time = 0, elapsed = last_ops = 0;
g_nops < cfg->icount && g_threads_quit < cfg->populate_threads;) {
/*
* Sleep for 100th of a second, report_interval is in second
* granularity, so adjust accordingly.
*/
usleep(10000);
elapsed += 1;
if (elapsed % 100 == 0 &&
(elapsed / 100) % cfg->report_interval == 0) {
lprintf(cfg, 0, 1, "%" PRIu64 " ops in %d secs",
g_nops - last_ops, cfg->report_interval);
last_ops = g_nops;
}
}
if (g_threads_quit == cfg->populate_threads) {
lprintf(cfg, WT_ERROR, 0,
"Populate threads exited without finishing.");
return (WT_ERROR);
}
gettimeofday(&e, NULL);
cursor->close(cursor);
session->close(session, NULL);
if (cfg->verbose > 0) {
fprintf(cfg->logf,
"Finished bulk load of %d items\n", cfg->icount);
secs = e.tv_sec + e.tv_usec / 1000000.0;
secs -= (cfg->phase_start_time.tv_sec +
cfg->phase_start_time.tv_usec / 1000000.0);
if (secs == 0)
++secs;
fprintf(cfg->logf,
"Load time: %.2f\n" "load ops/sec: %.2f\n",
secs, cfg->icount / secs);
}
free(data_buf);
free(key_buf);
return (ret);
if ((ret = stop_threads(cfg, cfg->populate_threads, threads)) != 0)
return (ret);
lprintf(cfg, 0, 1,
"Finished bulk load of %d items", cfg->icount);
secs = e.tv_sec + e.tv_usec / 1000000.0;
secs -= (cfg->phase_start_time.tv_sec +
cfg->phase_start_time.tv_usec / 1000000.0);
if (secs == 0)
++secs;
lprintf(cfg, 0, 1,
"Load time: %.2f\n" "load ops/sec: %.2f",
secs, cfg->icount / secs);
return (0);
}
/* Setup the logging output mechanism. */
int setup_log_file(CONFIG *cfg)
int execute_reads(CONFIG *cfg)
{
char *fname;
int offset;
pthread_t *threads;
int ret;
uint64_t last_ops;
if (cfg->verbose < 1 && cfg->stat_thread == 0)
return (0);
cfg->phase = LSM_TEST_PERF_READ;
lprintf(cfg, 0, 1, "Starting read threads");
if ((fname = calloc(strlen(cfg->home) +
strlen(cfg->uri) + strlen(".stat") + 1, 1)) == NULL) {
fprintf(stderr, "No memory in stat thread\n");
return (ENOMEM);
if ((ret = start_threads(
cfg, cfg->read_threads, &threads, read_thread)) != 0)
return (ret);
/* Sanity check reporting interval. */
if (cfg->report_interval > cfg->read_time)
cfg->report_interval = cfg->read_time;
gettimeofday(&cfg->phase_start_time, NULL);
for (cfg->elapsed_time = 0, last_ops = 0;
cfg->elapsed_time < cfg->read_time &&
g_threads_quit < cfg->read_threads;
cfg->elapsed_time += cfg->report_interval) {
sleep(cfg->report_interval);
lprintf(cfg, 0, 1, "%" PRIu64 " ops in %d secs",
g_nops - last_ops, cfg->report_interval);
last_ops = g_nops;
}
for (offset = 0;
cfg->uri[offset] != 0 && cfg->uri[offset] != ':';
offset++) {}
if (cfg->uri[offset] == 0)
offset = 0;
else
++offset;
sprintf(fname, "%s/%s.stat", cfg->home, cfg->uri + offset);
if ((cfg->logf = fopen(fname, "w")) == NULL) {
fprintf(stderr, "Statistics failed to open log file.\n");
return (EINVAL);
if (g_threads_quit == cfg->populate_threads) {
lprintf(cfg, WT_ERROR, 0,
"Populate threads exited without finishing.");
return (WT_ERROR);
}
/* Use line buffering for the log file. */
(void)setvbuf(cfg->logf, NULL, _IOLBF, 0);
if (fname != NULL)
free(fname);
if ((ret = stop_threads(cfg, cfg->read_threads, threads)) != 0)
return (ret);
return (0);
}
@@ -421,7 +534,7 @@ int main(int argc, char **argv)
CONFIG cfg;
WT_CONNECTION *conn;
const char *user_cconfig, *user_tconfig;
const char *opts = "C:R:T:d:eh:i:k:lr:s:u:v:SML";
const char *opts = "C:P:R:T:d:eh:i:k:lr:s:u:v:SML";
char *cc_buf, *tc_buf;
int ch, ret, stat_created;
pthread_t stat;
@@ -468,7 +581,7 @@ int main(int argc, char **argv)
cfg.home = optarg;
break;
case 'i':
cfg.icount = atoi(optarg) * 1000;
cfg.icount = atoi(optarg);
break;
case 'k':
cfg.key_sz = atoi(optarg);
@@ -491,6 +604,9 @@ int main(int argc, char **argv)
case 'C':
user_cconfig = optarg;
break;
case 'P':
cfg.populate_threads = atoi(optarg);
break;
case 'R':
cfg.read_threads = atoi(optarg);
break;
@@ -556,46 +672,43 @@ int main(int argc, char **argv)
/* Open a connection to the database, creating it if necessary. */
if ((ret = wiredtiger_open(
cfg.home, NULL, cfg.conn_config, &conn)) != 0) {
fprintf(stderr, "Error connecting to %s: %s\n",
cfg.home, wiredtiger_strerror(ret));
lprintf(&cfg, ret, 0, "Error connecting to %s", cfg.home);
goto err;
}
cfg.conn = conn;
if (cfg.stat_thread) {
stat_running = 1;
g_stat_running = 1;
if ((ret = pthread_create(
&stat, NULL, stat_worker, &cfg)) != 0) {
fprintf(stderr, "Error creating statistics thread.\n");
lprintf(&cfg, ret, 0,
"Error creating statistics thread.");
goto err;
}
stat_created = 1;
}
if (cfg.create != 0 && (ret = populate(&cfg)) != 0)
if (cfg.create != 0 && execute_populate(&cfg) != 0)
goto err;
if (cfg.read_time != 0 && cfg.read_threads != 0)
if ((ret = execute_reads(&cfg)) != 0)
if (cfg.read_time != 0 && cfg.read_threads != 0 &&
(ret = execute_reads(&cfg)) != 0)
goto err;
if (cfg.verbose > 0) {
fprintf(cfg.logf,
"Ran performance test example with %d threads for %d seconds.\n",
cfg.read_threads, cfg.read_time);
fprintf(cfg.logf,
"Executed %" PRIu64 " read operations\n", nops);
}
lprintf(&cfg, 0, 1,
"Ran performance test example with %d threads for %d seconds.",
cfg.read_threads, cfg.read_time);
lprintf(&cfg, 0, 1,
"Executed %" PRIu64 " read operations", g_nops);
if (cfg.stat_thread)
stat_running = 0;
err: if (cfg.stat_thread)
g_stat_running = 0;
/* Cleanup. */
err: if (stat_created != 0 && (ret = pthread_join(stat, NULL)) != 0)
fprintf(stderr, "Error joining stat thread: %d.\n", ret);
if (stat_created != 0 && (ret = pthread_join(stat, NULL)) != 0)
lprintf(&cfg, ret, 0, "Error joining stat thread.");
if (conn != NULL && (ret = conn->close(conn, NULL)) != 0)
fprintf(stderr, "Error connecting to %s: %s\n",
cfg.home, wiredtiger_strerror(ret));
lprintf(&cfg, ret, 0,
"Error closing connection to %s", cfg.home);
if (cc_buf != NULL)
free(cc_buf);
if (tc_buf != NULL)
@@ -608,60 +721,119 @@ err: if (stat_created != 0 && (ret = pthread_join(stat, NULL)) != 0)
return (ret);
}
int execute_reads(CONFIG *cfg)
/*
* Following are utility functions.
*/
int
start_threads(CONFIG *cfg, int num, pthread_t **threadsp, void *(*func)(void *))
{
pthread_t *read_threads;
int ret;
uint32_t i;
uint64_t last_ops;
pthread_t *threads;
int i, ret;
cfg->phase = LSM_TEST_PERF_READ;
if (cfg->verbose > 0)
fprintf(cfg->logf, "Starting read threads\n");
running = 1;
nops = 0;
read_threads = calloc(cfg->read_threads, sizeof(pthread_t *));
if (read_threads == NULL)
g_running = 1;
g_nops = 0;
g_threads_quit = 0;
threads = calloc(num, sizeof(pthread_t *));
if (threads == NULL)
return (ENOMEM);
for (i = 0; i < cfg->read_threads; i++) {
for (i = 0; i < num; i++) {
if ((ret = pthread_create(
&read_threads[i], NULL, read_thread, cfg)) != 0) {
fprintf(stderr, "Error creating thread: %d\n", i);
&threads[i], NULL, func, cfg)) != 0) {
g_running = 0;
lprintf(cfg, ret, 0, "Error creating thread: %d", i);
return (ret);
}
}
*threadsp = threads;
return (0);
}
int
stop_threads(CONFIG *cfg, int num, pthread_t *threads)
{
int i, ret;
g_running = 0;
for (i = 0; i < num; i++) {
if ((ret = pthread_join(threads[i], NULL)) != 0) {
lprintf(cfg, ret, 0, "Error joining thread %d", i);
return (ret);
}
}
/* Sanity check reporting interval. */
if (cfg->report_interval > cfg->read_time)
cfg->report_interval = cfg->read_time;
free(threads);
return (0);
}
gettimeofday(&cfg->phase_start_time, NULL);
for (cfg->elapsed_time = 0, last_ops = 0;
cfg->elapsed_time < cfg->read_time;
cfg->elapsed_time += cfg->report_interval) {
sleep(cfg->report_interval);
if (cfg->verbose > 0) {
fprintf(cfg->logf, "%" PRIu64 " ops in %d secs\n",
nops - last_ops, cfg->report_interval);
printf("%" PRIu64 " ops in %d secs\n",
nops - last_ops, cfg->report_interval);
}
last_ops = nops;
}
running = 0;
/*
* Log printf - output a log message.
*/
int lprintf(CONFIG *cfg, int err, uint32_t level, const char *fmt, ...)
{
va_list ap;
for (i = 0; i < cfg->read_threads; i++) {
if ((ret = pthread_join(read_threads[i], NULL)) != 0) {
fprintf(stderr, "Error joining thread %d\n", i);
return (ret);
if (err == 0 && level <= cfg->verbose) {
va_start(ap, fmt);
vfprintf(cfg->logf, fmt, ap);
va_end(ap);
fprintf(cfg->logf, "\n");
if (level < cfg->verbose) {
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
printf("\n");
}
}
if (err == 0)
return (0);
if (read_threads != NULL)
free(read_threads);
return (ret);
/* We are dealing with an error. */
va_start(ap, fmt);
vfprintf(cfg->logf, fmt, ap);
va_end(ap);
fprintf(cfg->logf, " Error: %s\n", wiredtiger_strerror(err));
if (cfg->logf != stderr) {
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, " Error: %s\n", wiredtiger_strerror(err));
}
return (0);
}
/* Setup the logging output mechanism. */
int setup_log_file(CONFIG *cfg)
{
char *fname;
int offset;
if (cfg->verbose < 1 && cfg->stat_thread == 0)
return (0);
if ((fname = calloc(strlen(cfg->home) +
strlen(cfg->uri) + strlen(".stat") + 1, 1)) == NULL) {
fprintf(stderr, "No memory in stat thread\n");
return (ENOMEM);
}
for (offset = 0;
cfg->uri[offset] != 0 && cfg->uri[offset] != ':';
offset++) {}
if (cfg->uri[offset] == 0)
offset = 0;
else
++offset;
sprintf(fname, "%s/%s.stat", cfg->home, cfg->uri + offset);
if ((cfg->logf = fopen(fname, "w")) == NULL) {
fprintf(stderr, "Statistics failed to open log file.\n");
return (EINVAL);
}
/* Use line buffering for the log file. */
(void)setvbuf(cfg->logf, NULL, _IOLBF, 0);
if (fname != NULL)
free(fname);
return (0);
}
void print_config(CONFIG *cfg)
@@ -673,8 +845,11 @@ void print_config(CONFIG *cfg)
printf("\t Table configuration: %s\n", cfg->table_config);
printf("\t %s\n", cfg->create ? "Creating" : "Using existing");
printf("\t Random seed: %d\n", cfg->rand_seed);
if (cfg->create)
if (cfg->create) {
printf("\t Insert count: %d\n", cfg->icount);
printf("\t Number populate threads: %d\n",
cfg->populate_threads);
}
printf("\t key size: %d data size: %d\n", cfg->key_sz, cfg->data_sz);
printf("\t Reporting interval: %d\n", cfg->report_interval);
printf("\t Read workload period: %d\n", cfg->read_time);
@@ -684,17 +859,18 @@ void print_config(CONFIG *cfg)
void usage(void)
{
printf("ex_perf_test [-CDLMRSTdehikrsuv]\n");
printf("ex_perf_test [-CLMPRSTdehikrsuv]\n");
printf("\t-S Use a small default configuration\n");
printf("\t-M Use a medium default configuration\n");
printf("\t-L Use a large default configuration\n");
printf("\t-C <string> additional connection configuration\n");
printf("\t-P <int> number of populate threads\n");
printf("\t-R <int> number of read threads\n");
printf("\t-T <string> additional table configuration\n");
printf("\t-d <int> data item size\n");
printf("\t-e use existing database (skip population phase)\n");
printf("\t-h <string> Wired Tiger home must exist, default WT_TEST \n");
printf("\t-i <int> number of records to insert in thousands\n");
printf("\t-i <int> number of records to insert\n");
printf("\t-k <int> key item size\n");
printf("\t-r <int> number of seconds to run read phase\n");
printf("\t-s <int> seed for random number generator\n");

View File

@@ -1,4 +1,10 @@
AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include
lib_LTLIBRARIES = reverse_collator.la
reverse_collator_la_LDFLAGS = -avoid-version -module
noinst_LTLIBRARIES = libwiredtiger_reverse_collator.la
libwiredtiger_reverse_collator_la_SOURCES = reverse_collator.c
# libtool hack: noinst_LTLIBRARIES turns off building shared libraries as well
# as installation, it will only build static libraries. As far as I can tell,
# the "approved" libtool way to turn them back on is by adding -rpath.
libwiredtiger_reverse_collator_la_LDFLAGS = \
-avoid-version -module -rpath /nowhere

View File

@@ -0,0 +1,6 @@
AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include
lib_LTLIBRARIES = libwiredtiger_bzip2.la
libwiredtiger_bzip2_la_SOURCES = bzip2_compress.c
libwiredtiger_bzip2_la_LDFLAGS = -avoid-version -module
libwiredtiger_bzip2_la_LIBADD = -lbz2

View File

@@ -72,8 +72,7 @@ wiredtiger_extension_init(
wt_api = api;
conn = session->connection;
return (conn->add_compressor(
conn, "bzip2_compress", &bzip2_compressor, NULL));
return (conn->add_compressor(conn, "bzip2", &bzip2_compressor, NULL));
}
/* Bzip2 WT_COMPRESSOR implementation for WT_CONNECTION::add_compressor. */

View File

@@ -1,5 +0,0 @@
AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include
lib_LTLIBRARIES = bzip2_compress.la
bzip2_compress_la_LDFLAGS = -avoid-version -module
bzip2_compress_la_LIBADD = -lbz2

View File

@@ -0,0 +1,9 @@
AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include
noinst_LTLIBRARIES = libwiredtiger_nop.la
libwiredtiger_nop_la_SOURCES = nop_compress.c
# libtool hack: noinst_LTLIBRARIES turns off building shared libraries as well
# as installation, it will only build static libraries. As far as I can tell,
# the "approved" libtool way to turn them back on is by adding -rpath.
libwiredtiger_nop_la_LDFLAGS = -avoid-version -module -rpath /nowhere

View File

@@ -55,8 +55,7 @@ wiredtiger_extension_init(
wt_api = api;
conn = session->connection;
return (
conn->add_compressor(conn, "nop_compress", &nop_compressor, NULL));
return (conn->add_compressor(conn, "nop", &nop_compressor, NULL));
}
/* Implementation of WT_COMPRESSOR for WT_CONNECTION::add_compressor. */

View File

@@ -1,4 +0,0 @@
AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include
lib_LTLIBRARIES = nop_compress.la
nop_compress_la_LDFLAGS = -avoid-version -module

View File

@@ -0,0 +1,6 @@
AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include
lib_LTLIBRARIES = libwiredtiger_snappy.la
libwiredtiger_snappy_la_SOURCES = snappy_compress.c
libwiredtiger_snappy_la_LDFLAGS = -avoid-version -module
libwiredtiger_snappy_la_LIBADD = -lsnappy

View File

@@ -59,8 +59,8 @@ wiredtiger_extension_init(
wt_api = api;
conn = session->connection;
return (conn->add_compressor(
conn, "snappy_compress", &wt_snappy_compressor, NULL));
return (
conn->add_compressor(conn, "snappy", &wt_snappy_compressor, NULL));
}
/* Snappy WT_COMPRESSOR for WT_CONNECTION::add_compressor. */

View File

@@ -1,5 +0,0 @@
AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir)/src/include
lib_LTLIBRARIES = snappy_compress.la
snappy_compress_la_LDFLAGS = -avoid-version -module
snappy_compress_la_LIBADD = -lsnappy

View File

@@ -6,7 +6,6 @@
*/
#include "wt_internal.h"
#include "bloom.h"
#define WT_BLOOM_TABLE_CONFIG "key_format=r,value_format=1t,exclusive=true"
@@ -125,6 +124,10 @@ __wt_bloom_open(WT_SESSION_IMPL *session,
/* Find the largest key, to get the size of the filter. */
cfg[1] = bloom->config;
WT_RET(__wt_open_cursor(session, bloom->uri, owner, cfg, &c));
/* XXX Layering violation: bump the cache priority for Bloom filters. */
session->btree->evict_priority = (1 << 19);
WT_RET(c->prev(c));
WT_RET(c->get_key(c, &size));
@@ -199,12 +202,27 @@ err: WT_TRET(c->close(c));
}
/*
* __wt_bloom_get --
* Tests whether the given key is in the Bloom filter.
* Returns zero if found, WT_NOTFOUND if not.
* __wt_bloom_hash --
* Calculate the hash values for a given key.
*/
int
__wt_bloom_get(WT_BLOOM *bloom, WT_ITEM *key)
__wt_bloom_hash(WT_BLOOM *bloom, WT_ITEM *key, WT_BLOOM_HASH *bhash)
{
WT_UNUSED(bloom);
bhash->h1 = __wt_hash_fnv64(key->data, key->size);
bhash->h2 = __wt_hash_city64(key->data, key->size);
return (0);
}
/*
* __wt_bloom_hash_get --
* Tests whether the key (as given by its hash signature) is in the Bloom
* filter. Returns zero if found, WT_NOTFOUND if not.
*/
int
__wt_bloom_hash_get(WT_BLOOM *bloom, WT_BLOOM_HASH *bhash)
{
WT_CURSOR *c;
WT_DECL_RET;
@@ -226,24 +244,15 @@ __wt_bloom_get(WT_BLOOM *bloom, WT_ITEM *key)
} else
c = bloom->c;
/*
* This comparison code is complex to avoid calculating the second
* hash if possible.
*/
h1 = __wt_hash_fnv64(key->data, key->size);
h1 = bhash->h1;
h2 = bhash->h2;
/*
* Add 1 to the hash because Wired Tiger tables are 1 based, and the
* original bitstring array was 0 based.
*/
c->set_key(c, (h1 % bloom->m) + 1);
WT_RET(c->search(c));
WT_RET(c->get_value(c, &bit));
if (bit == 0)
return (WT_NOTFOUND);
h2 = __wt_hash_city64(key->data, key->size);
result = 0;
for (i = 0, h1 += h2; i < bloom->k - 1; i++, h1 += h2) {
for (i = 0; i < bloom->k; i++, h1 += h2) {
/*
* Add 1 to the hash because Wired Tiger tables are 1 based and
* the original bitstring array was 0 based.
*/
c->set_key(c, (h1 % bloom->m) + 1);
WT_ERR(c->search(c));
WT_ERR(c->get_value(c, &bit));
@@ -263,6 +272,20 @@ err: /* Don't return WT_NOTFOUND from a failed search. */
return (ret);
}
/*
* __wt_bloom_get --
* Tests whether the given key is in the Bloom filter.
* Returns zero if found, WT_NOTFOUND if not.
*/
int
__wt_bloom_get(WT_BLOOM *bloom, WT_ITEM *key)
{
WT_BLOOM_HASH bhash;
WT_RET(__wt_bloom_hash(bloom, key, &bhash));
return (__wt_bloom_hash_get(bloom, &bhash));
}
/*
* __wt_bloom_close --
* Close the Bloom filter, release any resources.

View File

@@ -12,7 +12,7 @@ static int __evict_file_request(WT_SESSION_IMPL *, int);
static int __evict_file_request_walk(WT_SESSION_IMPL *);
static int __evict_lru(WT_SESSION_IMPL *);
static int __evict_lru_cmp(const void *, const void *);
static int __evict_walk(WT_SESSION_IMPL *);
static int __evict_walk(WT_SESSION_IMPL *, uint32_t *);
static int __evict_walk_file(WT_SESSION_IMPL *, u_int *);
static int __evict_worker(WT_SESSION_IMPL *);
@@ -20,14 +20,48 @@ static int __evict_worker(WT_SESSION_IMPL *);
* Tuning constants: I hesitate to call this tuning, but we want to review some
* number of pages from each file's in-memory tree for each page we evict.
*/
#define WT_EVICT_GROUP 30 /* Consider N pages as LRU candidates */
#define WT_EVICT_INT_SKEW (1<<20) /* Prefer leaf pages over internal
#define WT_EVICT_INT_SKEW (1<<20) /* Prefer leaf pages over internal
pages by this many increments of the
read generation. */
#define WT_EVICT_WALK_PER_FILE 5 /* Pages to visit per file */
#define WT_EVICT_WALK_BASE 50 /* Pages tracked across file visits */
#define WT_EVICT_WALK_BASE 100 /* Pages tracked across file visits */
#define WT_EVICT_WALK_INCR 100 /* Pages added each walk */
/*
* __evict_read_gen --
* Get the adjusted read generation for an eviction entry.
*/
static inline uint64_t
__evict_read_gen(const WT_EVICT_ENTRY *entry)
{
uint64_t read_gen;
if (entry->page == NULL)
return (UINT64_MAX);
read_gen = entry->page->read_gen + entry->btree->evict_priority;
if (entry->page->type == WT_PAGE_ROW_INT ||
entry->page->type == WT_PAGE_COL_INT)
read_gen += WT_EVICT_INT_SKEW;
return (read_gen);
}
/*
* __evict_lru_cmp --
* Qsort function: sort the eviction array.
*/
static int
__evict_lru_cmp(const void *a, const void *b)
{
uint64_t a_lru, b_lru;
a_lru = __evict_read_gen(a);
b_lru = __evict_read_gen(b);
return ((a_lru < b_lru) ? -1 : (a_lru == b_lru) ? 0 : 1);
}
/*
* __evict_list_clr --
* Clear an entry in the LRU eviction list.
@@ -488,16 +522,43 @@ static int
__evict_lru(WT_SESSION_IMPL *session)
{
WT_CACHE *cache;
uint64_t cutoff;
uint32_t i, candidates;
cache = S2C(session)->cache;
/* Get some more pages to consider for eviction. */
WT_RET(__evict_walk(session));
WT_RET(__evict_walk(session, &candidates));
/* Sort the list into LRU order and restart. */
__wt_spin_lock(session, &cache->evict_lock);
while (candidates > 0 && cache->evict[candidates - 1].page == NULL)
--candidates;
if (candidates == 0) {
__wt_spin_unlock(session, &cache->evict_lock);
return (0);
}
qsort(cache->evict,
cache->evict_entries, sizeof(WT_EVICT_ENTRY), __evict_lru_cmp);
candidates, sizeof(WT_EVICT_ENTRY), __evict_lru_cmp);
/* Find the bottom 25% */
while (candidates > 0 && cache->evict[candidates - 1].page == NULL)
--candidates;
cutoff = (3 * __evict_read_gen(&cache->evict[0]) +
__evict_read_gen(&cache->evict[candidates - 1])) / 4;
/*
* Don't take more than half, regardless. That said, if there is only
* one candidate page, which is normal when populating an empty file,
* don't exclude it.
*/
for (i = 0; i < candidates / 2; i++)
if (cache->evict[i].page->read_gen > cutoff)
break;
cache->evict_candidates = i + 1;
__evict_list_clr_all(session, WT_EVICT_WALK_BASE);
cache->evict_current = cache->evict;
@@ -515,7 +576,7 @@ __evict_lru(WT_SESSION_IMPL *session)
* Fill in the array by walking the next set of pages.
*/
static int
__evict_walk(WT_SESSION_IMPL *session)
__evict_walk(WT_SESSION_IMPL *session, u_int *entriesp)
{
WT_BTREE *btree;
WT_CACHE *cache;
@@ -586,6 +647,7 @@ retry: file_count = 0;
retries++ < WT_EVICT_WALK_INCR / WT_EVICT_WALK_PER_FILE)
goto retry;
*entriesp = i;
if (0) {
err: __wt_spin_unlock(session, &cache->evict_lock);
}
@@ -683,7 +745,10 @@ __evict_get_page(
*btreep = NULL;
*pagep = NULL;
candidates = (is_app ? WT_EVICT_GROUP : WT_EVICT_GROUP / 2);
candidates = cache->evict_candidates;
/* The eviction server only considers half of the entries. */
if (!is_app)
candidates /= 2;
/*
* Avoid the LRU lock if no pages are available. If there are pages
@@ -787,44 +852,3 @@ __wt_evict_lru_page(WT_SESSION_IMPL *session, int is_app)
return (ret);
}
/*
* __evict_lru_cmp --
* Qsort function: sort the eviction array.
*/
static int
__evict_lru_cmp(const void *a, const void *b)
{
WT_PAGE *a_page, *b_page;
uint64_t a_lru, b_lru;
/*
* There may be NULL references in the array; sort them as greater than
* anything else so they migrate to the end of the array.
*/
a_page = ((WT_EVICT_ENTRY *)a)->page;
b_page = ((WT_EVICT_ENTRY *)b)->page;
if (a_page == NULL)
return (b_page == NULL ? 0 : 1);
if (b_page == NULL)
return (-1);
/*
* Sort by the LRU in ascending order.
*
* Bias in favor of leaf pages. Otherwise, we can waste time
* considering parent pages for eviction while their child pages are
* still in memory.
*
* Bump the LRU generation by a small fixed amount: the idea being that
* if we have enough good leaf page candidates, we should evict them
* first, but not completely ignore an old internal page.
*/
a_lru = a_page->read_gen;
b_lru = b_page->read_gen;
if (a_page->type == WT_PAGE_ROW_INT || a_page->type == WT_PAGE_COL_INT)
a_lru += WT_EVICT_INT_SKEW;
if (b_page->type == WT_PAGE_ROW_INT || b_page->type == WT_PAGE_COL_INT)
b_lru += WT_EVICT_INT_SKEW;
return (a_lru > b_lru ? 1 : (a_lru < b_lru ? -1 : 0));
}

View File

@@ -1247,12 +1247,13 @@ __rec_split_row_promote(WT_SESSION_IMPL *session, WT_RECONCILE *r, uint8_t type)
* a copy. For a row-store, it's the first key on the page, a variable-
* length byte string, get a copy.
*
* This function is called from __rec_split at each split boundary, but
* that means we're not called before the first boundary. It's painful,
* but we need to detect that case and copy the key from the page we're
* building. We could simplify this by grabbing a copy of the first key
* we put on a page, perhaps in the function building keys for a page,
* but that's going to be uglier than this.
* This function is called from the split code at each split boundary,
* but that means we're not called before the first boundary. When we
* do the split work at the second boundary, we need to copy the key
* for the first boundary from the page we're building. Alternatively,
* we could store a copy of the first key we put on a page somewhere,
* perhaps while building the keys for a page, but that's likely to be
* even uglier.
*/
if (r->bnd_next == 1) {
/*
@@ -1270,7 +1271,11 @@ __rec_split_row_promote(WT_SESSION_IMPL *session, WT_RECONCILE *r, uint8_t type)
/*
* For the current slot, take the last key we built, after doing suffix
* compression.
* compression. The "last key we built" describes some process: before
* calling the split code, we must place the last key on the page before
* the boundary into the "last" key structure, and the first key on the
* page after the boundary into the "current" key structure, we're going
* to compare them for suffix compression.
*
* Suffix compression is a hack to shorten keys on internal pages. We
* only need enough bytes in the promoted key to ensure searches go to

View File

@@ -115,8 +115,9 @@ __wt_confdfl_file_meta =
"internal_page_max=2KB,key_format=u,key_gap=10,leaf_item_max=0,"
"leaf_page_max=1MB,lsm_bloom=,lsm_bloom_bit_count=8,lsm_bloom_config="
",lsm_bloom_hash_count=4,lsm_bloom_newest=0,lsm_bloom_oldest=0,"
"lsm_chunk_size=2MB,lsm_merge_max=15,prefix_compression=,split_pct=75"
",value_format=u,version=(major=0,minor=0)";
"lsm_chunk_size=2MB,lsm_merge_max=15,lsm_merge_threads=1,"
"prefix_compression=,split_pct=75,value_format=u,version=(major=0,"
"minor=0)";
WT_CONFIG_CHECK
__wt_confchk_file_meta[] = {
@@ -146,6 +147,7 @@ __wt_confchk_file_meta[] = {
{ "lsm_bloom_oldest", "boolean", NULL },
{ "lsm_chunk_size", "int", "min=512K,max=500MB" },
{ "lsm_merge_max", "int", "min=2,max=100" },
{ "lsm_merge_threads", "int", "min=1,max=10" },
{ "prefix_compression", "boolean", NULL },
{ "split_pct", "int", "min=25,max=100" },
{ "value_format", "format", NULL },
@@ -232,8 +234,8 @@ __wt_confdfl_session_create =
"key_format=u,key_gap=10,leaf_item_max=0,leaf_page_max=1MB,lsm_bloom="
",lsm_bloom_bit_count=8,lsm_bloom_config=,lsm_bloom_hash_count=4,"
"lsm_bloom_newest=0,lsm_bloom_oldest=0,lsm_chunk_size=2MB,"
"lsm_merge_max=15,prefix_compression=,source=,split_pct=75,type=file,"
"value_format=u,value_format=u";
"lsm_merge_max=15,lsm_merge_threads=1,prefix_compression=,source=,"
"split_pct=75,type=file,value_format=u,value_format=u";
WT_CONFIG_CHECK
__wt_confchk_session_create[] = {
@@ -266,6 +268,7 @@ __wt_confchk_session_create[] = {
{ "lsm_bloom_oldest", "boolean", NULL },
{ "lsm_chunk_size", "int", "min=512K,max=500MB" },
{ "lsm_merge_max", "int", "min=2,max=100" },
{ "lsm_merge_threads", "int", "min=1,max=10" },
{ "prefix_compression", "boolean", NULL },
{ "source", "string", NULL },
{ "split_pct", "int", "min=25,max=100" },

View File

@@ -5,22 +5,35 @@ the bzip2 and snappy compression engines.
@section compression_bzip2 Using bzip2 compression
To use the builtin support for <a href="http://www.bzip.org/">bzip2</a>
To use the builtin support for
<a href="http://www.bzip.org/">Julian Seward's bzip2</a>
compression, first check that bzip2 is installed in include and library
directories searched by the compiler. Once bzip2 is installed, you can
enable bzip2 using the \c --enable-bzip2 option to configure.
If bzip2 is installed in a non-standard location, you'll need to modify
the \c CPPFLAGS and \c LDFLAGS to indicate these locations. For example,
with the bzip2 includes and libraries installed in \c /usr/local/include
and \c /usr/local/lib, you should run configure as follows:
If bzip2 is installed in a location not normally searched by the
compiler toolchain, you'll need to modify the \c CPPFLAGS and \c LDFLAGS
to indicate these locations. For example, with the bzip2 includes and
libraries installed in \c /usr/local/include and \c /usr/local/lib, you
should run configure as follows:
@code
cd build_posix
../dist/configure --enable-bzip2 CPPFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/include"
../configure --enable-bzip2 CPPFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/include"
@endcode
After building, you can confirm the compressor is working by running the
When opening the WiredTiger database, load the bzip2 shared library as
an extension. For example, with the bzip2 library installed in
\c /usr/local/lib, you would use the following extension:
@snippet ex_all.c Configure bzip2 extension
Finally, when creating the WiredTiger object, set \c block_compressor
to \c bzip2:
@snippet ex_all.c Create a bzip2 compressed table
If necessary, you can confirm the compressor is working by running the
compression part of the test suite:
@code
@@ -33,23 +46,35 @@ was not skipped.
@section compression_snappy Using snappy compression
To use the builtin support for Google's
<a href="http://code.google.com/p/snappy/">snappy</a> compression, first
check that snappy is installed in include and library directories
searched by the compiler. Once snappy is installed, you can enable
snappy using the \c --enable-snappy option to configure.
To use the builtin support for
<a href="http://code.google.com/p/snappy/">Google's snappy</a>
compression, first check that snappy is installed in include and library
directories searched by the compiler. Once snappy is installed, you can
enable snappy using the \c --enable-snappy option to configure.
If snappy is installed in a non-standard location, you'll need to modify
the \c CPPFLAGS and \c LDFLAGS to indicate these locations. For example,
with the snappy includes and libraries installed in \c /usr/local/include
and \c /usr/local/lib, you should run configure as follows:
If snappy is installed in a location not normally searched by the
compiler toolchain, you'll need to modify the \c CPPFLAGS and \c LDFLAGS
to indicate these locations. For example, with the snappy includes and
libraries installed in \c /usr/local/include and \c /usr/local/lib, you
should run configure as follows:
@code
cd build_posix
../dist/configure --enable-snappy CPPFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/include"
../configure --enable-snappy CPPFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/include"
@endcode
After building, you can confirm the compressor is working by running the
When opening the WiredTiger database, load the snappy shared library as
an extension. For example, with the snappy library installed in
\c /usr/local/lib, you would use the following extension:
@snippet ex_all.c Configure snappy extension
Finally, when creating the WiredTiger object, set \c block_compressor
to \c snappy:
@snippet ex_all.c Create a snappy compressed table
If necessary, you can confirm the compressor is working by running the
compression part of the test suite:
@code

View File

@@ -13,8 +13,8 @@ DbMultiple
EB
EmpId
FreeBSD
Gawlick
GCC
Gawlick
GitHub
IEC
LDFLAGS
@@ -28,6 +28,7 @@ Mewhort
NoSQL
RepMgr
Rrx
Seward's
URIs
Vv
WiredTiger
@@ -193,6 +194,7 @@ mutexes
mutexing
mvcc
mygcc
namespace
ndary
ndbm
newsite

View File

@@ -13,7 +13,7 @@ To ask questions or discuss issues related to using WiredTiger, visit our
View the documentation online:
- <a href="1.3.5/index.html"><b>WiredTiger 1.3.5 (current release)</b></a>
- <a href="1.3.7/index.html"><b>WiredTiger 1.3.7 (current release)</b></a>
- <a href="1.2.2/index.html"><b>WiredTiger 1.2.2</b></a>
- <a href="1.1.5/index.html"><b>WiredTiger 1.1.5</b></a>

View File

@@ -1,9 +1,48 @@
/*! @page upgrading Upgrading WiredTiger applications
@section version_136 Upgrading to Version 1.3.6
<dl>
<dt>Installed library names</dt>
<dd>
The installed WiredTiger extension library names changed to limit
namespace pollution:
<table>
@hrow{Library, Previous Name, New Name}
@row{Bzip2 compression, bzip2_compress.a, libwiredtiger_bzip2.a}
@row{, bzip2_compress.la, libwiredtiger_bzip2.la}
@row{, bzip2_compress.so, libwiredtiger_bzip2.so}
@row{Snappy compression, snappy_compress.a, libwiredtiger_snappy.a}
@row{, snappy_compress.la, libwiredtiger_snappy.la}
@row{, snappy_compress.so, libwiredtiger_snappy.so}
@row{No-op compression, nop_compress.a, No longer installed}
@row{, nop_compress.la, No longer installed}
@row{, nop_compress.so, No longer installed}
@row{Reverse order collator, reverse_collator.a, No longer installed}
@row{, reverse_collator.la, No longer installed}
@row{, reverse_collator.so, No longer installed}
</table>
</dd>
<dt>Built-in compression names</dt>
<dd>
The built-in compression name arguments to the WT_SESSION:create
\c block_compressor configuration string changed for consistency:
<table>
@hrow{Extension, Previous Name, New Name}
@row{Bzip2 compression, "bzip2_compress", "bzip2"}
@row{Snappy compression, "snappy_compress", "snappy"}
</table>
</dd>
</dl>
<hr>
@section version_135 Upgrading to Version 1.3.5
<dl>
<dt>Version 1.3.5 file format changes</dt>
<dt>File format changes</dt>
<dd>
The underlying file formats changed in the 1.3.5 release; tables and files
should be dumped and re-loaded into a new database.
@@ -100,7 +139,7 @@ returns a cursor comparison status (less than 0, equal to 0, or greater than
0) depending on the cursors' key order.
</dd>
<dt>Version 1.3 file format changes</dt>
<dt>File format changes</dt>
<dd>
The underlying file formats changed in the 1.3 release; tables and files
should be dumped and re-loaded into a new database.

View File

@@ -22,3 +22,7 @@ struct __wt_bloom {
uint64_t m; /* The number of slots in the bit string. */
uint64_t n; /* The number of items to be inserted. */
};
struct __wt_bloom_hash {
uint64_t h1, h2; /* The two hashes used to calculate bits. */
};

View File

@@ -271,7 +271,7 @@ struct __wt_page {
* The read-generation is not declared volatile: read-generation is set
* a lot (on every access), and we don't want to write it that much.
*/
uint64_t read_gen;
uint64_t read_gen;
/*
* In-memory pages optionally reference a number of entries originally

View File

@@ -119,6 +119,7 @@ struct __wt_btree {
u_int block_header; /* Block manager header length */
WT_PAGE *evict_page; /* Eviction thread's location */
uint64_t evict_priority; /* Relative priority of cached pages. */
volatile uint32_t lru_count; /* Count of threads in LRU eviction */
WT_BTREE_STATS *stats; /* Btree statistics */

View File

@@ -34,7 +34,7 @@ struct __wt_cache {
/*
* Read information.
*/
uint32_t read_gen; /* Page read generation (LRU) */
uint64_t read_gen; /* Page read generation (LRU) */
/*
* Eviction thread information.
@@ -52,6 +52,7 @@ struct __wt_cache {
WT_EVICT_ENTRY *evict_current; /* LRU current page to be evicted */
size_t evict_allocated; /* LRU list bytes allocated */
uint32_t evict_entries; /* LRU list eviction slots */
uint32_t evict_candidates; /* LRU list pages to evict */
u_int evict_file_next; /* LRU: next file to search */
/*

View File

@@ -259,6 +259,8 @@ extern int __wt_bloom_open(WT_SESSION_IMPL *session,
WT_BLOOM **bloomp);
extern int __wt_bloom_insert(WT_BLOOM *bloom, WT_ITEM *key);
extern int __wt_bloom_finalize(WT_BLOOM *bloom);
extern int __wt_bloom_hash(WT_BLOOM *bloom, WT_ITEM *key, WT_BLOOM_HASH *bhash);
extern int __wt_bloom_hash_get(WT_BLOOM *bloom, WT_BLOOM_HASH *bhash);
extern int __wt_bloom_get(WT_BLOOM *bloom, WT_ITEM *key);
extern int __wt_bloom_close(WT_BLOOM *bloom);
extern int __wt_bloom_drop(WT_BLOOM *bloom, const char *config);
@@ -704,8 +706,9 @@ extern int __wt_log_printf(WT_SESSION_IMPL *session,
2,
3)));
extern WT_LOGREC_DESC __wt_logdesc_debug;
extern int __wt_clsm_init_merge(WT_CURSOR *cursor,
extern int __wt_clsm_init_merge( WT_CURSOR *cursor,
int start_chunk,
uint32_t start_id,
int nchunks);
extern int __wt_clsm_open(WT_SESSION_IMPL *session,
const char *uri,
@@ -719,8 +722,9 @@ extern int __wt_lsm_merge_update_tree(WT_SESSION_IMPL *session,
int start_chunk,
int nchunks,
WT_LSM_CHUNK *chunk);
extern int __wt_lsm_merge(WT_SESSION_IMPL *session,
extern int __wt_lsm_merge( WT_SESSION_IMPL *session,
WT_LSM_TREE *lsm_tree,
uint32_t id,
int stalls);
extern int __wt_lsm_meta_read(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree);
extern int __wt_lsm_meta_write(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree);
@@ -730,17 +734,15 @@ extern int __wt_lsm_stat_init( WT_SESSION_IMPL *session,
extern int __wt_lsm_tree_close_all(WT_SESSION_IMPL *session);
extern int __wt_lsm_tree_bloom_name( WT_SESSION_IMPL *session,
WT_LSM_TREE *lsm_tree,
int i,
uint32_t id,
WT_ITEM *buf);
extern int __wt_lsm_tree_chunk_name( WT_SESSION_IMPL *session,
WT_LSM_TREE *lsm_tree,
int i,
uint32_t id,
WT_ITEM *buf);
extern int __wt_lsm_tree_setup_chunk(WT_SESSION_IMPL *session,
extern int __wt_lsm_tree_setup_chunk( WT_SESSION_IMPL *session,
WT_LSM_TREE *lsm_tree,
int i,
WT_LSM_CHUNK *chunk,
int create_bloom);
WT_LSM_CHUNK *chunk);
extern int __wt_lsm_tree_create(WT_SESSION_IMPL *session,
const char *uri,
int exclusive,
@@ -769,7 +771,8 @@ extern int __wt_lsm_tree_worker(WT_SESSION_IMPL *session,
const char *[]),
const char *cfg[],
uint32_t open_flags);
extern void *__wt_lsm_worker(void *arg);
extern void *__wt_lsm_merge_worker(void *vargs);
extern void *__wt_lsm_bloom_worker(void *arg);
extern void *__wt_lsm_checkpoint_worker(void *arg);
extern int __wt_lsm_copy_chunks(WT_SESSION_IMPL *session,
WT_LSM_TREE *lsm_tree,

View File

@@ -20,15 +20,15 @@ struct __wt_cursor_lsm {
WT_CURSOR **cursors;
WT_CURSOR *current; /* The current cursor for iteration */
WT_LSM_CHUNK *primary_chunk; /* The current primary chunk. */
WT_LSM_CHUNK *primary_chunk; /* The current primary chunk */
#define WT_CLSM_ITERATE_NEXT 0x01 /* Forward iteration */
#define WT_CLSM_ITERATE_PREV 0x02 /* Backward iteration */
#define WT_CLSM_MERGE 0x04 /* Merge cursor, don't update. */
#define WT_CLSM_MINOR_MERGE 0x08 /* Minor merge, include tombstones. */
#define WT_CLSM_MERGE 0x04 /* Merge cursor, don't update */
#define WT_CLSM_MINOR_MERGE 0x08 /* Minor merge, include tombstones */
#define WT_CLSM_MULTIPLE 0x10 /* Multiple cursors have values for the
current key */
#define WT_CLSM_UPDATED 0x20 /* Cursor has done updates */
#define WT_CLSM_OPEN_READ 0x20 /* Open for reads */
uint32_t flags;
};
@@ -37,14 +37,16 @@ struct __wt_cursor_lsm {
* A single chunk (file) in an LSM tree.
*/
struct __wt_lsm_chunk {
const char *uri; /* Data source for this chunk. */
const char *bloom_uri; /* URI of Bloom filter, if any. */
uint64_t count; /* Approximate count of records. */
uint32_t generation; /* Merge generation. */
uint32_t id; /* ID used to generate URIs */
uint32_t generation; /* Merge generation */
const char *uri; /* Data source for this chunk */
const char *bloom_uri; /* URI of Bloom filter, if any */
uint64_t count; /* Approximate count of records */
uint32_t ncursor; /* Cursors with the chunk as primary. */
#define WT_LSM_CHUNK_ONDISK 0x01
#define WT_LSM_CHUNK_BLOOM 0x02
uint32_t ncursor; /* Cursors with the chunk as primary */
#define WT_LSM_CHUNK_BLOOM 0x01
#define WT_LSM_CHUNK_MERGING 0x02
#define WT_LSM_CHUNK_ONDISK 0x04
uint32_t flags;
};
@@ -59,7 +61,7 @@ struct __wt_lsm_tree {
WT_COLLATOR *collator;
int refcnt; /* Number of users of the tree. */
int refcnt; /* Number of users of the tree */
WT_RWLOCK *rwlock;
TAILQ_ENTRY(__wt_lsm_tree) q;
@@ -74,21 +76,29 @@ struct __wt_lsm_tree {
uint32_t bloom_hash_count;
uint32_t chunk_size;
uint32_t merge_max;
uint32_t merge_threads;
#define WT_LSM_BLOOM_MERGED 0x00000001
#define WT_LSM_BLOOM_NEWEST 0x00000002
#define WT_LSM_BLOOM_OFF 0x00000004
#define WT_LSM_BLOOM_OLDEST 0x00000008
uint32_t bloom; /* Bloom creation policy. */
uint32_t bloom; /* Bloom creation policy */
WT_SESSION_IMPL *worker_session;/* Passed to thread_create */
pthread_t worker_tid; /* LSM worker thread */
#define WT_LSM_MAX_WORKERS 10
/* Passed to thread_create */
WT_SESSION_IMPL *worker_sessions[WT_LSM_MAX_WORKERS];
/* LSM worker thread(s) */
pthread_t worker_tids[WT_LSM_MAX_WORKERS];
WT_SESSION_IMPL *ckpt_session; /* For checkpoint worker */
pthread_t ckpt_tid; /* LSM checkpoint worker thread */
int nchunks; /* Number of active chunks */
int last; /* Last allocated ID. */
WT_SESSION_IMPL *bloom_session; /* For bloom worker */
pthread_t bloom_tid; /* LSM bloom worker thread */
WT_LSM_CHUNK **chunk; /* Array of active LSM chunks */
size_t chunk_alloc; /* Space allocated for chunks */
int nchunks; /* Number of active chunks */
uint32_t last; /* Last allocated ID */
WT_LSM_CHUNK **old_chunks; /* Array of old LSM chunks */
size_t old_alloc; /* Space allocated for old chunks */
@@ -115,7 +125,16 @@ struct __wt_lsm_data_source {
* State for an LSM worker thread.
*/
struct __wt_lsm_worker_cookie {
WT_LSM_CHUNK **chunk_array;
size_t chunk_alloc;
int nchunks;
WT_LSM_CHUNK **chunk_array;
size_t chunk_alloc;
int nchunks;
};
/*
* WT_LSM_WORKER_ARGS --
* State for an LSM worker thread.
*/
struct __wt_lsm_worker_args {
WT_LSM_TREE *lsm_tree;
int id;
};

View File

@@ -685,6 +685,8 @@ struct __wt_session {
* LSM tree.,an integer between 512K and 500MB; default \c 2MB.}
* @config{lsm_merge_max, the maximum number of chunks to include in a
* merge operation.,an integer between 2 and 100; default \c 15.}
* @config{lsm_merge_threads, the number of thread to perform merge
* operations.,an integer between 1 and 10; default \c 1.}
* @config{prefix_compression, configure row-store format key prefix
* compression.,a boolean flag; default \c true.}
* @config{source, override the default data source URI derived from the
@@ -1160,9 +1162,9 @@ struct __wt_connection {
* handler is installed that writes error messages to stderr
* @configstart{wiredtiger_open, see dist/api_data.py}
* @config{buffer_alignment, in-memory alignment (in bytes) for buffers used for
* I/O. By default\, a platform-specific alignment value is used (512 bytes on
* Linux systems\, zero elsewhere).,an integer between -1 and 1MB; default \c
* -1.}
* I/O. The default value of -1 indicates that a platform-specific alignment
* value should be used (512 bytes on Linux systems\, zero elsewhere).,an
* integer between -1 and 1MB; default \c -1.}
* @config{cache_size, maximum heap memory to allocate for the cache.,an integer
* between 1MB and 10TB; default \c 100MB.}
* @config{create, create the database if it does not exist.,a boolean flag;
@@ -1177,11 +1179,11 @@ struct __wt_connection {
* integer between 10 and 99; default \c 80.}
* @config{eviction_trigger, trigger eviction when the cache becomes this full
* (as a percentage).,an integer between 10 and 99; default \c 95.}
* @config{extensions, list of extensions to load. Optional values are passed
* as the \c config parameter to WT_CONNECTION::load_extension. Complex paths
* may need quoting\, for example\,
* <code>extensions=("/path/to/ext.so"="entry=my_entry")</code>.,a list of
* strings; default empty.}
* @config{extensions, list of shared library extensions to load (using dlopen).
* Optional values are passed as the \c config parameter to
* WT_CONNECTION::load_extension. Complex paths may require quoting\, for
* example\, <code>extensions=("/path/ext.so"="entry=my_entry")</code>.,a list
* of strings; default empty.}
* @config{hazard_max, maximum number of simultaneous hazard references per
* session handle.,an integer greater than or equal to 15; default \c 1000.}
* @config{logging, enable logging.,a boolean flag; default \c false.}

View File

@@ -59,6 +59,8 @@ struct __wt_block_header;
typedef struct __wt_block_header WT_BLOCK_HEADER;
struct __wt_bloom;
typedef struct __wt_bloom WT_BLOOM;
struct __wt_bloom_hash;
typedef struct __wt_bloom_hash WT_BLOOM_HASH;
struct __wt_btree;
typedef struct __wt_btree WT_BTREE;
struct __wt_btree_session;
@@ -137,6 +139,8 @@ struct __wt_lsm_stats;
typedef struct __wt_lsm_stats WT_LSM_STATS;
struct __wt_lsm_tree;
typedef struct __wt_lsm_tree WT_LSM_TREE;
struct __wt_lsm_worker_args;
typedef struct __wt_lsm_worker_args WT_LSM_WORKER_ARGS;
struct __wt_lsm_worker_cookie;
typedef struct __wt_lsm_worker_cookie WT_LSM_WORKER_COOKIE;
struct __wt_named_collator;
@@ -206,6 +210,7 @@ struct __wt_update;
#include "stat.h"
#include "api.h"
#include "bloom.h"
#include "cursor.h"
#include "lsm.h"
#include "meta.h"

View File

@@ -26,22 +26,23 @@
#define WT_LSM_ENTER(clsm, cursor, session, n) \
clsm = (WT_CURSOR_LSM *)cursor; \
CURSOR_API_CALL(cursor, session, n, NULL); \
WT_ERR(__clsm_enter(clsm))
WT_ERR(__clsm_enter(clsm, 0))
#define WT_LSM_UPDATE_ENTER(clsm, cursor, session, n) \
clsm = (WT_CURSOR_LSM *)cursor; \
CURSOR_UPDATE_API_CALL(cursor, session, n, NULL); \
WT_ERR(__clsm_enter(clsm))
WT_ERR(__clsm_enter(clsm, 1))
static int __clsm_open_cursors(WT_CURSOR_LSM *, int);
static int __clsm_open_cursors(WT_CURSOR_LSM *, int, int, uint32_t);
static int __clsm_search(WT_CURSOR *);
static inline int
__clsm_enter(WT_CURSOR_LSM *clsm)
__clsm_enter(WT_CURSOR_LSM *clsm, int update)
{
if (!F_ISSET(clsm, WT_CLSM_MERGE) &&
clsm->dsk_gen != clsm->lsm_tree->dsk_gen)
WT_RET(__clsm_open_cursors(clsm, 0));
(clsm->dsk_gen != clsm->lsm_tree->dsk_gen ||
(!update && !F_ISSET(clsm, WT_CLSM_OPEN_READ))))
WT_RET(__clsm_open_cursors(clsm, update, 0, 0));
return (0);
}
@@ -106,7 +107,8 @@ __clsm_close_cursors(WT_CURSOR_LSM *clsm)
* Open cursors for the current set of files.
*/
static int
__clsm_open_cursors(WT_CURSOR_LSM *clsm, int start_chunk)
__clsm_open_cursors(
WT_CURSOR_LSM *clsm, int update, int start_chunk, uint32_t start_id)
{
WT_CURSOR *c, **cp;
WT_DECL_RET;
@@ -124,6 +126,9 @@ __clsm_open_cursors(WT_CURSOR_LSM *clsm, int start_chunk)
c = &clsm->iface;
chunk = NULL;
if (!update)
F_SET(clsm, WT_CLSM_OPEN_READ);
/* Copy the key, so we don't lose the cursor position. */
if (F_ISSET(c, WT_CURSTD_KEY_SET)) {
if (c->key.data != c->key.mem)
@@ -135,10 +140,27 @@ __clsm_open_cursors(WT_CURSOR_LSM *clsm, int start_chunk)
WT_RET(__clsm_close_cursors(clsm));
__wt_spin_lock(session, &lsm_tree->lock);
/* Merge cursors have already figured out how many chunks they need. */
if (F_ISSET(clsm, WT_CLSM_MERGE))
if (F_ISSET(clsm, WT_CLSM_MERGE)) {
nchunks = clsm->nchunks;
else
/*
* We may have raced with another merge completing. Check that
* we're starting at the right offset in the chunk array.
*/
if (start_chunk >= lsm_tree->nchunks ||
lsm_tree->chunk[start_chunk]->id != start_id)
for (start_chunk = 0;
start_chunk < lsm_tree->nchunks;
start_chunk++) {
chunk = lsm_tree->chunk[start_chunk];
if (chunk->id == start_id)
break;
}
WT_ASSERT(session, start_chunk + nchunks <= lsm_tree->nchunks);
} else
nchunks = lsm_tree->nchunks;
if (clsm->cursors == NULL || nchunks > clsm->nchunks) {
@@ -150,6 +172,9 @@ __clsm_open_cursors(WT_CURSOR_LSM *clsm, int start_chunk)
clsm->nchunks = nchunks;
for (i = 0, cp = clsm->cursors; i != clsm->nchunks; i++, cp++) {
if (!F_ISSET(clsm, WT_CLSM_OPEN_READ) && i < clsm->nchunks - 1)
continue;
/*
* Read from the checkpoint if the file has been written.
* Once all cursors switch, the in-memory tree can be evicted.
@@ -182,18 +207,15 @@ __clsm_open_cursors(WT_CURSOR_LSM *clsm, int start_chunk)
}
/* The last chunk is our new primary. */
if ((clsm->primary_chunk = chunk) != NULL) {
WT_ASSERT(session,
!F_ISSET(clsm, WT_CLSM_UPDATED) ||
!F_ISSET(chunk, WT_LSM_CHUNK_ONDISK));
if (chunk != NULL && !F_ISSET(chunk, WT_LSM_CHUNK_ONDISK)) {
clsm->primary_chunk = chunk;
(void)WT_ATOMIC_ADD(clsm->primary_chunk->ncursor, 1);
}
/* Peek into the btree layer to track the in-memory size. */
if (lsm_tree->memsizep == NULL)
(void)__wt_btree_get_memsize(
session, session->btree, &lsm_tree->memsizep);
/* Peek into the btree layer to track the in-memory size. */
if (lsm_tree->memsizep == NULL)
(void)__wt_btree_get_memsize(
session, session->btree, &lsm_tree->memsizep);
}
clsm->dsk_gen = lsm_tree->dsk_gen;
err: __wt_spin_unlock(session, &lsm_tree->lock);
@@ -204,7 +226,8 @@ err: __wt_spin_unlock(session, &lsm_tree->lock);
* Initialize an LSM cursor for a merge.
*/
int
__wt_clsm_init_merge(WT_CURSOR *cursor, int start_chunk, int nchunks)
__wt_clsm_init_merge(
WT_CURSOR *cursor, int start_chunk, uint32_t start_id, int nchunks)
{
WT_CURSOR_LSM *clsm;
@@ -214,7 +237,7 @@ __wt_clsm_init_merge(WT_CURSOR *cursor, int start_chunk, int nchunks)
F_SET(clsm, WT_CLSM_MINOR_MERGE);
clsm->nchunks = nchunks;
return (__clsm_open_cursors(clsm, start_chunk));
return (__clsm_open_cursors(clsm, 0, start_chunk, start_id));
}
/*
@@ -502,11 +525,14 @@ static int
__clsm_search(WT_CURSOR *cursor)
{
WT_BLOOM *bloom;
WT_BLOOM_HASH bhash;
WT_CURSOR *c;
WT_CURSOR_LSM *clsm;
WT_DECL_RET;
WT_SESSION_IMPL *session;
int i;
int have_hash, i;
have_hash = 0;
WT_LSM_ENTER(clsm, cursor, session, search);
WT_CURSOR_NEEDKEY(cursor);
@@ -526,7 +552,13 @@ __clsm_search(WT_CURSOR *cursor)
FORALL_CURSORS(clsm, c, i) {
/* If there is a Bloom filter, see if we can skip the read. */
if ((bloom = clsm->blooms[i]) != NULL) {
ret = __wt_bloom_get(bloom, &cursor->key);
if (!have_hash) {
WT_ERR(__wt_bloom_hash(
bloom, &cursor->key, &bhash));
have_hash = 1;
}
ret = __wt_bloom_hash_get(bloom, &bhash);
if (ret == WT_NOTFOUND) {
WT_STAT_INCR(
clsm->lsm_tree->stats, bloom_misses);
@@ -748,17 +780,18 @@ __clsm_put(
* If this is the first update in this cursor, check if a new in-memory
* chunk is needed.
*/
if (!F_ISSET(clsm, WT_CLSM_UPDATED)) {
if (clsm->primary_chunk == NULL) {
__wt_spin_lock(session, &lsm_tree->lock);
if (clsm->dsk_gen == lsm_tree->dsk_gen)
WT_WITH_SCHEMA_LOCK(session,
ret = __wt_lsm_tree_switch(session, lsm_tree));
__wt_spin_unlock(session, &lsm_tree->lock);
WT_RET(ret);
F_SET(clsm, WT_CLSM_UPDATED);
/* We changed the structure, or someone else did: update. */
WT_RET(__clsm_enter(clsm));
WT_RET(__clsm_enter(clsm, 1));
WT_ASSERT(session, clsm->primary_chunk != NULL);
}
primary = clsm->cursors[clsm->nchunks - 1];

View File

@@ -19,6 +19,8 @@ __wt_lsm_merge_update_tree(WT_SESSION_IMPL *session,
size_t chunk_sz, chunks_after_merge;
int i, j;
WT_ASSERT(session, start_chunk + nchunks <= lsm_tree->nchunks);
/* Setup the array of obsolete chunks. */
if (nchunks > lsm_tree->old_avail) {
chunk_sz = sizeof(*lsm_tree->old_chunks);
@@ -61,17 +63,18 @@ __wt_lsm_merge_update_tree(WT_SESSION_IMPL *session,
* Merge a set of chunks of an LSM tree.
*/
int
__wt_lsm_merge(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, int stalls)
__wt_lsm_merge(
WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, uint32_t id, int stalls)
{
WT_BLOOM *bloom;
WT_CURSOR *src, *dest;
WT_DECL_ITEM(bbuf);
WT_DECL_RET;
WT_ITEM key, value;
WT_ITEM buf, key, value;
WT_LSM_CHUNK *chunk;
const char *cur_cfg[] =
API_CONF_DEFAULTS(session, open_cursor, "bulk,raw");
uint32_t generation;
uint32_t generation, start_id;
uint64_t insert_count, record_count;
int create_bloom, dest_id, end_chunk, i;
int max_chunks, nchunks, start_chunk;
@@ -81,20 +84,13 @@ __wt_lsm_merge(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, int stalls)
max_chunks = (int)lsm_tree->merge_max;
create_bloom = 0;
/*
* Take a copy of the latest chunk id. This value needs to be atomically
* read. We need a copy, since other threads may alter the chunk count
* while we are doing a merge.
*/
nchunks = lsm_tree->nchunks;
/*
* If there aren't any chunks to merge, or some of the chunks aren't
* yet written, we're done. A non-zero error indicates that the worker
* should assume there is no work to do: if there are unwritten chunks,
* the worker should write them immediately.
*/
if (nchunks <= 1)
if (lsm_tree->nchunks <= 1)
return (WT_NOTFOUND);
/*
@@ -104,10 +100,14 @@ __wt_lsm_merge(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, int stalls)
*/
__wt_spin_lock(session, &lsm_tree->lock);
/* Only include chunks that are stable on disk. */
end_chunk = nchunks - 1;
/*
* Only include chunks that are stable on disk and not involved in a
* merge.
*/
end_chunk = lsm_tree->nchunks - 1;
while (end_chunk > 0 &&
!F_ISSET(lsm_tree->chunk[end_chunk], WT_LSM_CHUNK_ONDISK))
(!F_ISSET(lsm_tree->chunk[end_chunk], WT_LSM_CHUNK_ONDISK) ||
F_ISSET(lsm_tree->chunk[end_chunk], WT_LSM_CHUNK_MERGING)))
--end_chunk;
/*
@@ -129,6 +129,10 @@ __wt_lsm_merge(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, int stalls)
chunk = lsm_tree->chunk[start_chunk - 1];
nchunks = end_chunk - start_chunk + 1;
/* If the chunk is already involved in a merge, stop. */
if (F_ISSET(chunk, WT_LSM_CHUNK_MERGING))
break;
/*
* If the next chunk is more than double the average size of
* the chunks we have so far, stop.
@@ -136,23 +140,46 @@ __wt_lsm_merge(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, int stalls)
if (nchunks > 2 && chunk->count > 2 * record_count / nchunks)
break;
/* Don't do any big merges until we have waited for 10s. */
if (nchunks > 0 && stalls < 10 &&
chunk->count > lsm_tree->chunk[end_chunk]->count * 2)
/*
* Never do big merges in the first thread if there are
* multiple threads. If there is a single thread, wait for 10
* seconds looking for small merges before trying a big one.
*/
if (id == 0 && nchunks > 0 &&
chunk->count > lsm_tree->chunk[end_chunk]->count * 2 &&
(lsm_tree->merge_threads > 1 || stalls < 10))
break;
F_SET(chunk, WT_LSM_CHUNK_MERGING);
record_count += chunk->count;
--start_chunk;
if (nchunks == max_chunks)
if (nchunks == max_chunks) {
F_CLR(lsm_tree->chunk[end_chunk], WT_LSM_CHUNK_MERGING);
record_count -= lsm_tree->chunk[end_chunk--]->count;
}
}
__wt_spin_unlock(session, &lsm_tree->lock);
nchunks = end_chunk - start_chunk + 1;
WT_ASSERT(session, nchunks <= max_chunks);
/* Don't do small merges unless we have waited for 2s. */
if (nchunks <= 1 || (stalls < 2 && nchunks < max_chunks / 2))
if (nchunks <= 1 ||
(id == 0 && stalls < 2 && nchunks < max_chunks / 2)) {
for (i = start_chunk; i <= end_chunk; i++)
F_CLR(lsm_tree->chunk[i], WT_LSM_CHUNK_MERGING);
nchunks = 0;
}
/* Find the merge generation. */
for (generation = 0, i = 0; i < nchunks; i++)
if (lsm_tree->chunk[start_chunk + i]->generation > generation)
generation = lsm_tree->chunk[i]->generation;
start_id = lsm_tree->chunk[start_chunk]->id;
__wt_spin_unlock(session, &lsm_tree->lock);
if (nchunks == 0)
return (WT_NOTFOUND);
/* Allocate an ID for the merge. */
@@ -163,17 +190,13 @@ __wt_lsm_merge(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, int stalls)
start_chunk, end_chunk, dest_id, record_count);
WT_RET(__wt_calloc_def(session, 1, &chunk));
chunk->id = dest_id;
if (FLD_ISSET(lsm_tree->bloom, WT_LSM_BLOOM_MERGED) &&
(FLD_ISSET(lsm_tree->bloom, WT_LSM_BLOOM_OLDEST) ||
start_chunk > 0) && record_count > 0)
create_bloom = 1;
/* Find the merge generation. */
for (generation = 0, i = start_chunk; i < end_chunk; i++)
if (lsm_tree->chunk[i]->generation > generation)
generation = lsm_tree->chunk[i]->generation;
/*
* Special setup for the merge cursor:
* first, reset to open the dependent cursors;
@@ -182,16 +205,22 @@ __wt_lsm_merge(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, int stalls)
*/
WT_ERR(__wt_open_cursor(session, lsm_tree->name, NULL, NULL, &src));
F_SET(src, WT_CURSTD_RAW);
WT_ERR(__wt_clsm_init_merge(src, start_chunk, nchunks));
WT_ERR(__wt_clsm_init_merge(src, start_chunk, start_id, nchunks));
WT_WITH_SCHEMA_LOCK(session, ret = __wt_lsm_tree_setup_chunk(
session, lsm_tree, dest_id, chunk, create_bloom));
session, lsm_tree, chunk));
WT_ERR(ret);
if (create_bloom)
if (create_bloom) {
WT_CLEAR(buf);
WT_ERR(__wt_lsm_tree_bloom_name(
session, lsm_tree, chunk->id, &buf));
chunk->bloom_uri = __wt_buf_steal(session, &buf, NULL);
WT_ERR(__wt_bloom_create(session, chunk->bloom_uri,
lsm_tree->bloom_config,
record_count, lsm_tree->bloom_bit_count,
lsm_tree->bloom_hash_count, &bloom));
}
WT_ERR(__wt_open_cursor(session, chunk->uri, NULL, cur_cfg, &dest));
@@ -226,6 +255,19 @@ __wt_lsm_merge(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, int stalls)
WT_ERR(ret);
__wt_spin_lock(session, &lsm_tree->lock);
/*
* Check whether we raced with another merge, and adjust the chunk
* array offset as necessary.
*/
if (start_chunk >= lsm_tree->nchunks ||
lsm_tree->chunk[start_chunk]->id != start_id)
for (start_chunk = 0;
start_chunk < lsm_tree->nchunks;
start_chunk++)
if (lsm_tree->chunk[start_chunk]->id == start_id)
break;
ret = __wt_lsm_merge_update_tree(
session, lsm_tree, start_chunk, nchunks, chunk);

View File

@@ -17,11 +17,15 @@ __wt_lsm_meta_read(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree)
WT_CONFIG cparser, lparser;
WT_CONFIG_ITEM ck, cv, lk, lv;
WT_DECL_RET;
WT_ITEM buf;
WT_LSM_CHUNK *chunk;
const char *config;
int nchunks;
size_t chunk_sz, alloc;
WT_CLEAR(buf);
chunk_sz = sizeof(WT_LSM_CHUNK);
WT_RET(__wt_metadata_read(session, lsm_tree->name, &config));
WT_ERR(__wt_config_init(session, &cparser, config));
while ((ret = __wt_config_next(&cparser, &ck, &cv)) == 0) {
@@ -55,46 +59,54 @@ __wt_lsm_meta_read(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree)
lsm_tree->chunk_size = (uint32_t)cv.val;
else if (WT_STRING_MATCH("lsm_merge_max", ck.str, ck.len))
lsm_tree->merge_max = (uint32_t)cv.val;
else if (WT_STRING_MATCH("lsm_merge_threads", ck.str, ck.len))
lsm_tree->merge_threads = (uint32_t)cv.val;
else if (WT_STRING_MATCH("last", ck.str, ck.len))
lsm_tree->last = (int)cv.val;
else if (WT_STRING_MATCH("chunks", ck.str, ck.len)) {
WT_ERR(__wt_config_subinit(session, &lparser, &cv));
chunk_sz = sizeof(*lsm_tree->chunk);
for (nchunks = 0; (ret =
__wt_config_next(&lparser, &lk, &lv)) == 0; ) {
if (WT_STRING_MATCH("bloom", lk.str, lk.len)) {
WT_ERR(__wt_strndup(session,
lv.str, lv.len, &chunk->bloom_uri));
if (WT_STRING_MATCH("id", lk.str, lk.len)) {
if ((nchunks + 1) * chunk_sz >
lsm_tree->chunk_alloc)
WT_ERR(__wt_realloc(session,
&lsm_tree->chunk_alloc,
WT_MAX(10 * chunk_sz,
2 * lsm_tree->chunk_alloc),
&lsm_tree->chunk));
WT_ERR(__wt_calloc_def(
session, 1, &chunk));
lsm_tree->chunk[nchunks++] = chunk;
chunk->id = (uint32_t)lv.val;
WT_ERR(__wt_lsm_tree_chunk_name(session,
lsm_tree, chunk->id, &buf));
chunk->uri =
__wt_buf_steal(session, &buf, NULL);
F_SET(chunk, WT_LSM_CHUNK_ONDISK);
} else if (WT_STRING_MATCH(
"bloom", lk.str, lk.len)) {
WT_ERR(__wt_lsm_tree_bloom_name(session,
lsm_tree, chunk->id, &buf));
chunk->bloom_uri =
__wt_buf_steal(session, &buf, NULL);
F_SET(chunk, WT_LSM_CHUNK_BLOOM);
continue;
}
if (WT_STRING_MATCH("count", lk.str, lk.len)) {
} else if (WT_STRING_MATCH(
"count", lk.str, lk.len)) {
chunk->count = lv.val;
continue;
}
if (WT_STRING_MATCH(
} else if (WT_STRING_MATCH(
"generation", lk.str, lk.len)) {
chunk->generation = (uint32_t)lv.val;
continue;
}
if ((nchunks + 1) * chunk_sz >
lsm_tree->chunk_alloc)
WT_ERR(__wt_realloc(session,
&lsm_tree->chunk_alloc,
WT_MAX(10 * chunk_sz,
2 * lsm_tree->chunk_alloc),
&lsm_tree->chunk));
WT_ERR(__wt_calloc_def(session, 1, &chunk));
lsm_tree->chunk[nchunks++] = chunk;
WT_ERR(__wt_strndup(session,
lk.str, lk.len, &chunk->uri));
F_SET(chunk, WT_LSM_CHUNK_ONDISK);
}
WT_ERR_NOTFOUND_OK(ret);
lsm_tree->nchunks = nchunks;
} else if (WT_STRING_MATCH("old_chunks", ck.str, ck.len)) {
WT_ERR(__wt_config_subinit(session, &lparser, &cv));
chunk_sz = sizeof(*lsm_tree->old_chunks);
for (nchunks = 0; (ret =
__wt_config_next(&lparser, &lk, &lv)) == 0; ) {
if (WT_STRING_MATCH("bloom", lk.str, lk.len)) {
@@ -157,20 +169,20 @@ __wt_lsm_meta_write(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree)
lsm_tree->key_format, lsm_tree->value_format));
WT_ERR(__wt_buf_catfmt(session, buf,
",last=%" PRIu32 ",lsm_chunk_size=%" PRIu64
",lsm_merge_max=%" PRIu32 ",lsm_bloom=%" PRIu32
",lsm_merge_max=%" PRIu32 ",lsm_merge_threads=%" PRIu32
",lsm_bloom=%" PRIu32
",lsm_bloom_bit_count=%" PRIu32 ",lsm_bloom_hash_count=%" PRIu32,
lsm_tree->last, (uint64_t)lsm_tree->chunk_size,
lsm_tree->merge_max, lsm_tree->bloom,
lsm_tree->merge_max, lsm_tree->merge_threads, lsm_tree->bloom,
lsm_tree->bloom_bit_count, lsm_tree->bloom_hash_count));
WT_ERR(__wt_buf_catfmt(session, buf, ",chunks=["));
for (i = 0; i < lsm_tree->nchunks; i++) {
chunk = lsm_tree->chunk[i];
if (i > 0)
WT_ERR(__wt_buf_catfmt(session, buf, ","));
WT_ERR(__wt_buf_catfmt(session, buf, "\"%s\"", chunk->uri));
if (chunk->bloom_uri != NULL)
WT_ERR(__wt_buf_catfmt(
session, buf, ",bloom=\"%s\"", chunk->bloom_uri));
WT_ERR(__wt_buf_catfmt(session, buf, "id=%" PRIu32, chunk->id));
if (F_ISSET(chunk, WT_LSM_CHUNK_BLOOM))
WT_ERR(__wt_buf_catfmt(session, buf, ",bloom"));
if (chunk->count != 0)
WT_ERR(__wt_buf_catfmt(
session, buf, ",count=%" PRIu64, chunk->count));

View File

@@ -68,12 +68,18 @@ __lsm_tree_close(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree)
{
WT_DECL_RET;
WT_SESSION *wt_session;
WT_SESSION_IMPL *s;
uint32_t i;
if (F_ISSET(lsm_tree, WT_LSM_TREE_WORKING)) {
F_CLR(lsm_tree, WT_LSM_TREE_WORKING);
if (F_ISSET(S2C(session), WT_CONN_LSM_MERGE))
WT_TRET(__wt_thread_join(lsm_tree->worker_tid));
for (i = 0; i < lsm_tree->merge_threads; i++)
WT_TRET(__wt_thread_join(
lsm_tree->worker_tids[i]));
WT_TRET(__wt_thread_join(lsm_tree->ckpt_tid));
if (FLD_ISSET(lsm_tree->bloom, WT_LSM_BLOOM_NEWEST))
WT_TRET(__wt_thread_join(lsm_tree->bloom_tid));
}
/*
@@ -83,19 +89,35 @@ __lsm_tree_close(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree)
*
* Do this in the main thread to avoid deadlocks.
*/
if (lsm_tree->worker_session != NULL) {
F_SET(lsm_tree->worker_session,
F_ISSET(session, WT_SESSION_SCHEMA_LOCKED));
wt_session = &lsm_tree->worker_session->iface;
for (i = 0; i < lsm_tree->merge_threads; i++) {
if ((s = lsm_tree->worker_sessions[i]) == NULL)
continue;
lsm_tree->worker_sessions[i] = NULL;
F_SET(s, F_ISSET(session, WT_SESSION_SCHEMA_LOCKED));
wt_session = &s->iface;
WT_TRET(wt_session->close(wt_session, NULL));
/*
* This is safe after the close because session handles are
* not freed, but are managed by the connection.
*/
__wt_free(NULL, lsm_tree->worker_session->hazard);
__wt_free(NULL, s->hazard);
}
if (lsm_tree->bloom_session != NULL) {
F_SET(lsm_tree->bloom_session,
F_ISSET(session, WT_SESSION_SCHEMA_LOCKED));
wt_session = &lsm_tree->bloom_session->iface;
WT_TRET(wt_session->close(wt_session, NULL));
/*
* This is safe after the close because session handles are
* not freed, but are managed by the connection.
*/
__wt_free(NULL, lsm_tree->bloom_session->hazard);
}
if (lsm_tree->ckpt_session != NULL) {
F_SET(lsm_tree->ckpt_session,
F_ISSET(session, WT_SESSION_SCHEMA_LOCKED));
@@ -137,10 +159,10 @@ __wt_lsm_tree_close_all(WT_SESSION_IMPL *session)
*/
int
__wt_lsm_tree_bloom_name(
WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, int i, WT_ITEM *buf)
WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, uint32_t id, WT_ITEM *buf)
{
WT_RET(__wt_buf_fmt(session, buf, "file:%s-%06d.bf",
lsm_tree->filename, i));
WT_RET(__wt_buf_fmt(session, buf, "file:%s-%06" PRIu32 ".bf",
lsm_tree->filename, id));
return (0);
}
@@ -150,10 +172,10 @@ __wt_lsm_tree_bloom_name(
*/
int
__wt_lsm_tree_chunk_name(
WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, int i, WT_ITEM *buf)
WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, uint32_t id, WT_ITEM *buf)
{
WT_RET(__wt_buf_fmt(session, buf, "file:%s-%06d.lsm",
lsm_tree->filename, i));
WT_RET(__wt_buf_fmt(session, buf, "file:%s-%06" PRIu32 ".lsm",
lsm_tree->filename, id));
return (0);
}
@@ -162,39 +184,31 @@ __wt_lsm_tree_chunk_name(
* Initialize a chunk of an LSM tree.
*/
int
__wt_lsm_tree_setup_chunk(WT_SESSION_IMPL *session,
WT_LSM_TREE *lsm_tree, int i, WT_LSM_CHUNK *chunk, int create_bloom)
__wt_lsm_tree_setup_chunk(
WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree, WT_LSM_CHUNK *chunk)
{
WT_DECL_ITEM(buf);
WT_DECL_ITEM(bbuf);
WT_DECL_RET;
WT_ITEM buf;
const char *cfg[] = API_CONF_DEFAULTS(session, drop, "force");
WT_RET(__wt_scr_alloc(session, 0, &buf));
WT_ERR(__wt_lsm_tree_chunk_name(session, lsm_tree, i, buf));
WT_CLEAR(buf);
WT_RET(__wt_lsm_tree_chunk_name(session, lsm_tree, chunk->id, &buf));
chunk->uri = __wt_buf_steal(session, &buf, NULL);
/*
* Drop the chunk first - there may be some content hanging over from
* an aborted merge.
* an aborted merge or checkpoint.
*
* Don't do this for the very first chunk: we are called during
* WT_SESSION::create, and doing a drop inside there does interesting
* things with handle locks and metadata tracking. It can never have
* been the result of an interrupted merge, anyway.
*/
if (i > 1)
WT_ERR(__wt_schema_drop(session, buf->data, cfg));
WT_ERR(__wt_schema_create(session, buf->data, lsm_tree->file_config));
chunk->uri = __wt_buf_steal(session, buf, NULL);
if (create_bloom) {
WT_ERR(__wt_scr_alloc(session, 0, &bbuf));
WT_ERR(__wt_lsm_tree_bloom_name(
session, lsm_tree, i, bbuf));
chunk->bloom_uri = __wt_buf_steal(session, bbuf, NULL);
}
if (chunk->id > 1)
WT_ERR(__wt_schema_drop(session, chunk->uri, cfg));
WT_ERR(__wt_schema_create(session, chunk->uri, lsm_tree->file_config));
err: __wt_scr_free(&buf);
__wt_scr_free(&bbuf);
return (ret);
err: return (ret);
}
/*
@@ -205,12 +219,12 @@ static int
__lsm_tree_start_worker(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree)
{
WT_CONNECTION *wt_conn;
WT_LSM_WORKER_ARGS *wargs;
WT_SESSION *wt_session;
WT_SESSION_IMPL *s;
uint32_t i;
wt_conn = &S2C(session)->iface;
WT_RET(wt_conn->open_session(wt_conn, NULL, NULL, &wt_session));
lsm_tree->worker_session = (WT_SESSION_IMPL *)wt_session;
F_SET(lsm_tree->worker_session, WT_SESSION_INTERNAL);
WT_RET(wt_conn->open_session(wt_conn, NULL, NULL, &wt_session));
lsm_tree->ckpt_session = (WT_SESSION_IMPL *)wt_session;
@@ -220,8 +234,27 @@ __lsm_tree_start_worker(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree)
/* The new thread will rely on the WORKING value being visible. */
WT_FULL_BARRIER();
if (F_ISSET(S2C(session), WT_CONN_LSM_MERGE))
for (i = 0; i < lsm_tree->merge_threads; i++) {
WT_RET(wt_conn->open_session(
wt_conn, NULL, NULL, &wt_session));
s = (WT_SESSION_IMPL *)wt_session;
F_SET(s, WT_SESSION_INTERNAL);
lsm_tree->worker_sessions[i] = s;
WT_RET(__wt_calloc_def(session, 1, &wargs));
wargs->lsm_tree = lsm_tree;
wargs->id = i;
WT_RET(__wt_thread_create(&lsm_tree->worker_tids[i],
__wt_lsm_merge_worker, wargs));
}
if (FLD_ISSET(lsm_tree->bloom, WT_LSM_BLOOM_NEWEST)) {
WT_RET(wt_conn->open_session(wt_conn, NULL, NULL, &wt_session));
lsm_tree->bloom_session = (WT_SESSION_IMPL *)wt_session;
F_SET(lsm_tree->bloom_session, WT_SESSION_INTERNAL);
WT_RET(__wt_thread_create(
&lsm_tree->worker_tid, __wt_lsm_worker, lsm_tree));
&lsm_tree->bloom_tid, __wt_lsm_bloom_worker, lsm_tree));
}
WT_RET(__wt_thread_create(
&lsm_tree->ckpt_tid, __wt_lsm_checkpoint_worker, lsm_tree));
@@ -306,6 +339,10 @@ __wt_lsm_tree_create(WT_SESSION_IMPL *session,
lsm_tree->chunk_size = (uint32_t)cval.val;
WT_ERR(__wt_config_gets(session, cfg, "lsm_merge_max", &cval));
lsm_tree->merge_max = (uint32_t)cval.val;
WT_ERR(__wt_config_gets(session, cfg, "lsm_merge_threads", &cval));
lsm_tree->merge_threads = (uint32_t)cval.val;
/* Sanity check that api_data.py is in sync with lsm.h */
WT_ASSERT(session, lsm_tree->merge_threads <= WT_LSM_MAX_WORKERS);
WT_ERR(__wt_scr_alloc(session, 0, &buf));
WT_ERR(__wt_buf_fmt(session, buf,
@@ -346,20 +383,21 @@ __lsm_tree_open_check(
WT_CONFIG_ITEM cval;
const char *cfg[] = API_CONF_DEFAULTS(
session, create, lsm_tree->file_config);
uint64_t required;
uint32_t maxleafpage;
uint64_t req;
WT_RET(__wt_config_gets(
session, cfg, "leaf_page_max", &cval));
maxleafpage = (uint32_t)cval.val;
/* Three chunks, plus one page for each participant in a merge. */
req = 3 * lsm_tree->chunk_size + (lsm_tree->merge_max * maxleafpage);
if (S2C(session)->cache_size < req)
required = 3 * lsm_tree->chunk_size +
lsm_tree->merge_threads * (lsm_tree->merge_max * maxleafpage);
if (S2C(session)->cache_size < required)
WT_RET_MSG(session, EINVAL,
"The LSM configuration requires a cache size of at least %"
PRIu64 ". Configured size is %" PRIu64,
req, S2C(session)->cache_size);
required, S2C(session)->cache_size);
return (0);
}
@@ -433,7 +471,7 @@ __wt_lsm_tree_get(WT_SESSION_IMPL *session,
if (exclusive && lsm_tree->refcnt)
return (EBUSY);
WT_ATOMIC_ADD(lsm_tree->refcnt, 1);
(void)WT_ATOMIC_ADD(lsm_tree->refcnt, 1);
*treep = lsm_tree;
return (0);
}
@@ -453,7 +491,7 @@ void
__wt_lsm_tree_release(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree)
{
WT_ASSERT(session, lsm_tree->refcnt > 0);
WT_ATOMIC_SUB(lsm_tree->refcnt, 1);
(void)WT_ATOMIC_SUB(lsm_tree->refcnt, 1);
}
/*
@@ -466,7 +504,7 @@ __wt_lsm_tree_switch(
{
WT_DECL_RET;
WT_LSM_CHUNK *chunk;
int new_id;
uint32_t new_id;
new_id = WT_ATOMIC_ADD(lsm_tree->last, 1);
@@ -486,10 +524,9 @@ __wt_lsm_tree_switch(
&lsm_tree->chunk));
WT_ERR(__wt_calloc_def(session, 1, &chunk));
chunk->id = new_id;
lsm_tree->chunk[lsm_tree->nchunks++] = chunk;
WT_ERR(__wt_lsm_tree_setup_chunk(
session, lsm_tree, new_id, chunk,
FLD_ISSET(lsm_tree->bloom, WT_LSM_BLOOM_NEWEST) ? 1 : 0));
WT_ERR(__wt_lsm_tree_setup_chunk(session, lsm_tree, chunk));
++lsm_tree->dsk_gen;
WT_ERR(__wt_lsm_meta_write(session, lsm_tree));
@@ -556,14 +593,15 @@ int
__wt_lsm_tree_rename(WT_SESSION_IMPL *session,
const char *oldname, const char *newname, const char *cfg[])
{
WT_DECL_ITEM(buf);
WT_DECL_RET;
WT_ITEM buf;
WT_LSM_CHUNK *chunk;
WT_LSM_TREE *lsm_tree;
const char *old;
int i;
old = NULL;
WT_CLEAR(buf);
/* Get the LSM tree. */
WT_RET(__wt_lsm_tree_get(session, oldname, 1, &lsm_tree));
@@ -574,8 +612,6 @@ __wt_lsm_tree_rename(WT_SESSION_IMPL *session,
/* Prevent any new opens. */
WT_RET(__wt_spin_trylock(session, &lsm_tree->lock));
WT_ERR(__wt_scr_alloc(session, 0, &buf));
/* Set the new name. */
__wt_free(session, lsm_tree->name);
WT_ERR(__wt_strdup(session, newname, &lsm_tree->name));
@@ -586,16 +622,18 @@ __wt_lsm_tree_rename(WT_SESSION_IMPL *session,
old = chunk->uri;
chunk->uri = NULL;
WT_ERR(__wt_lsm_tree_chunk_name(session, lsm_tree, i, buf));
chunk->uri = __wt_buf_steal(session, buf, NULL);
WT_ERR(__wt_lsm_tree_chunk_name(
session, lsm_tree, (uint32_t)i, &buf));
chunk->uri = __wt_buf_steal(session, &buf, NULL);
WT_ERR(__wt_schema_rename(session, old, chunk->uri, cfg));
__wt_free(session, old);
if ((old = chunk->bloom_uri) != NULL) {
if (F_ISSET(chunk, WT_LSM_CHUNK_BLOOM)) {
old = chunk->bloom_uri;
chunk->bloom_uri = NULL;
WT_ERR(__wt_lsm_tree_bloom_name(
session, lsm_tree, i, buf));
chunk->bloom_uri = __wt_buf_steal(session, buf, NULL);
session, lsm_tree, (uint32_t)i, &buf));
chunk->bloom_uri = __wt_buf_steal(session, &buf, NULL);
F_SET(chunk, WT_LSM_CHUNK_BLOOM);
WT_ERR(__wt_schema_rename(
session, old, chunk->uri, cfg));
@@ -610,7 +648,6 @@ __wt_lsm_tree_rename(WT_SESSION_IMPL *session,
if (0) {
err: __wt_spin_unlock(session, &lsm_tree->lock);
}
__wt_scr_free(&buf);
if (old != NULL)
__wt_free(session, old);
__lsm_tree_discard(session, lsm_tree);
@@ -640,15 +677,15 @@ __wt_lsm_tree_truncate(
/* Prevent any new opens. */
WT_RET(__wt_spin_trylock(session, &lsm_tree->lock));
/* Mark all chunks old. */
/* Create the new chunk. */
WT_ERR(__wt_calloc_def(session, 1, &chunk));
chunk->id = WT_ATOMIC_ADD(lsm_tree->last, 1);
WT_ERR(__wt_lsm_tree_setup_chunk(session, lsm_tree, chunk));
/* Mark all chunks old. */
WT_ERR(__wt_lsm_merge_update_tree(
session, lsm_tree, 0, lsm_tree->nchunks, chunk));
/* Create the new chunk. */
WT_ERR(__wt_lsm_tree_setup_chunk(
session, lsm_tree, WT_ATOMIC_ADD(lsm_tree->last, 1), chunk, 0));
WT_ERR(__wt_lsm_meta_write(session, lsm_tree));
WT_ERR(__lsm_tree_start_worker(session, lsm_tree));

View File

@@ -12,19 +12,23 @@ static int __lsm_bloom_create(
static int __lsm_free_chunks(WT_SESSION_IMPL *, WT_LSM_TREE *);
/*
* __wt_lsm_worker --
* The worker thread for an LSM tree, responsible for writing in-memory
* trees to disk and merging on-disk trees.
* __wt_lsm_merge_worker --
* The merge worker thread for an LSM tree, responsible for merging
* on-disk trees.
*/
void *
__wt_lsm_worker(void *arg)
__wt_lsm_merge_worker(void *vargs)
{
WT_LSM_WORKER_ARGS *args;
WT_LSM_TREE *lsm_tree;
WT_SESSION_IMPL *session;
int progress, stalls;
int id, progress, stalls;
lsm_tree = arg;
session = lsm_tree->worker_session;
args = vargs;
lsm_tree = args->lsm_tree;
id = args->id;
session = lsm_tree->worker_sessions[id];
__wt_free(session, args);
stalls = 0;
while (F_ISSET(lsm_tree, WT_LSM_TREE_WORKING)) {
@@ -34,13 +38,18 @@ __wt_lsm_worker(void *arg)
session->btree = NULL;
/* Report stalls to merge in seconds. */
if (__wt_lsm_merge(session, lsm_tree, stalls / 1000) == 0)
if (__wt_lsm_merge(session, lsm_tree, id, stalls / 1000) == 0)
progress = 1;
/* Clear any state from previous worker thread iterations. */
session->btree = NULL;
if (lsm_tree->nold_chunks != lsm_tree->old_avail &&
/*
* Only have one thread freeing old chunks, and only if there
* are chunks to free.
*/
if (id == 0 &&
lsm_tree->nold_chunks != lsm_tree->old_avail &&
__lsm_free_chunks(session, lsm_tree) == 0)
progress = 1;
@@ -55,10 +64,80 @@ __wt_lsm_worker(void *arg)
return (NULL);
}
/*
* __wt_lsm_bloom_worker --
* A worker thread for an LSM tree, responsible for creating Bloom filters
* for the newest on-disk chunks.
*/
void *
__wt_lsm_bloom_worker(void *arg)
{
WT_DECL_RET;
WT_LSM_CHUNK *chunk;
WT_LSM_TREE *lsm_tree;
WT_LSM_WORKER_COOKIE cookie;
WT_SESSION_IMPL *session;
int i, j;
lsm_tree = arg;
session = lsm_tree->bloom_session;
WT_CLEAR(cookie);
for (;;) {
WT_ERR(__wt_lsm_copy_chunks(session, lsm_tree, &cookie));
/* Write checkpoints in all completed files. */
for (i = 0, j = 0; i < cookie.nchunks; i++) {
if (!F_ISSET(lsm_tree, WT_LSM_TREE_WORKING))
goto err;
chunk = cookie.chunk_array[i];
/* Stop if a thread is still active in the chunk. */
if (chunk->ncursor != 0 ||
!F_ISSET(chunk, WT_LSM_CHUNK_ONDISK))
break;
if (F_ISSET(chunk, WT_LSM_CHUNK_BLOOM) ||
F_ISSET(chunk, WT_LSM_CHUNK_MERGING) ||
chunk->generation > 0 ||
chunk->count == 0)
continue;
if ((ret = __lsm_bloom_create(
session, lsm_tree, chunk)) != 0) {
(void)__wt_err(
session, ret, "bloom creation failed");
break;
}
++j;
__wt_spin_lock(session, &lsm_tree->lock);
++lsm_tree->dsk_gen;
ret = __wt_lsm_meta_write(session, lsm_tree);
__wt_spin_unlock(session, &lsm_tree->lock);
if (ret != 0) {
(void)__wt_err(session, ret,
"LSM bloom worker metadata write failed");
break;
}
WT_VERBOSE_ERR(session, lsm,
"LSM worker created bloom filter for %d.", i);
}
if (j == 0)
__wt_sleep(0, 100000);
}
err: __wt_free(session, cookie.chunk_array);
return (NULL);
}
/*
* __wt_lsm_checkpoint_worker --
* A worker thread for an LSM tree, responsible for checkpointing chunks
* once they become read only.
* A worker thread for an LSM tree, responsible for flushing new chunks to
* disk.
*/
void *
__wt_lsm_checkpoint_worker(void *arg)
@@ -76,42 +155,57 @@ __wt_lsm_checkpoint_worker(void *arg)
WT_CLEAR(cookie);
while (F_ISSET(lsm_tree, WT_LSM_TREE_WORKING)) {
for (;;) {
WT_ERR(__wt_lsm_copy_chunks(session, lsm_tree, &cookie));
/* Write checkpoints in all completed files. */
for (i = 0, j = 0; i < cookie.nchunks; i++) {
for (i = 0, j = 0; i < cookie.nchunks - 1; i++) {
if (!F_ISSET(lsm_tree, WT_LSM_TREE_WORKING))
goto err;
chunk = cookie.chunk_array[i];
if (F_ISSET(chunk, WT_LSM_CHUNK_ONDISK))
continue;
/* Stop if a thread is still active in the chunk. */
if (chunk->ncursor != 0)
break;
WT_ERR(__lsm_bloom_create(
session, lsm_tree, chunk));
if (F_ISSET(chunk, WT_LSM_CHUNK_ONDISK))
continue;
/*
* NOTE: we pass a non-NULL config, because otherwise
* __wt_checkpoint thinks we're closing the file.
*/
WT_WITH_SCHEMA_LOCK(session,
ret = __wt_schema_worker(session, chunk->uri,
__wt_checkpoint, cfg, 0));
if (ret == 0) {
++j;
__wt_spin_lock(session, &lsm_tree->lock);
F_SET(chunk, WT_LSM_CHUNK_ONDISK);
lsm_tree->dsk_gen++;
__wt_spin_unlock(session, &lsm_tree->lock);
WT_VERBOSE_ERR(session, lsm,
"LSM worker checkpointed %d.", i);
ret = __wt_schema_worker(session,
chunk->uri, __wt_checkpoint, cfg, 0));
if (ret != 0) {
(void)__wt_err(session, ret,
"LSM checkpoint failed");
break;
}
++j;
__wt_spin_lock(session, &lsm_tree->lock);
F_SET(chunk, WT_LSM_CHUNK_ONDISK);
++lsm_tree->dsk_gen;
ret = __wt_lsm_meta_write(session, lsm_tree);
__wt_spin_unlock(session, &lsm_tree->lock);
if (ret != 0) {
(void)__wt_err(session, ret,
"LSM checkpoint metadata write failed");
break;
}
WT_VERBOSE_ERR(session, lsm,
"LSM worker checkpointed %d.", i);
}
if (j == 0)
__wt_sleep(0, 10);
__wt_sleep(0, 10000);
}
err: __wt_free(session, cookie.chunk_array);
err: __wt_free(session, cookie.chunk_array);
return (NULL);
}
@@ -136,12 +230,9 @@ __wt_lsm_copy_chunks(WT_SESSION_IMPL *session,
/* The actual error value is ignored. */
return (WT_ERROR);
}
/*
* Take a copy of the current state of the LSM tree. Skip
* the last chunk - since it is the active one and not relevant
* to merge operations.
*/
nchunks = lsm_tree->nchunks - 1;
/* Take a copy of the current state of the LSM tree. */
nchunks = lsm_tree->nchunks;
/*
* If the tree array of active chunks is larger than our current buffer,
@@ -173,19 +264,33 @@ __lsm_bloom_create(WT_SESSION_IMPL *session,
WT_BLOOM *bloom;
WT_CURSOR *src;
WT_DECL_RET;
WT_ITEM key;
WT_ITEM buf, key;
WT_SESSION *wt_session;
const char *cur_cfg[] = API_CONF_DEFAULTS(session, open_cursor, "raw");
uint64_t insert_count;
if (!FLD_ISSET(lsm_tree->bloom, WT_LSM_BLOOM_NEWEST) ||
chunk->count == 0)
return (0);
/*
* Normally, the Bloom URI is populated when the chunk struct is
* allocated. After an open, however, it may not have been.
* Deal with that here.
*/
if (chunk->bloom_uri == NULL) {
WT_CLEAR(buf);
WT_RET(__wt_lsm_tree_bloom_name(
session, lsm_tree, chunk->id, &buf));
chunk->bloom_uri = __wt_buf_steal(session, &buf, NULL);
}
WT_ASSERT(session, chunk->bloom_uri != NULL);
/*
* Drop the bloom filter first - there may be some content hanging over
* from an aborted merge or checkpoint.
*/
wt_session = &session->iface;
WT_RET(wt_session->drop(wt_session, chunk->bloom_uri, "force"));
bloom = NULL;
WT_ERR(__wt_bloom_create(session, chunk->bloom_uri,
WT_RET(__wt_bloom_create(session, chunk->bloom_uri,
lsm_tree->bloom_config, chunk->count,
lsm_tree->bloom_bit_count, lsm_tree->bloom_hash_count, &bloom));
@@ -236,17 +341,15 @@ __lsm_free_chunks(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree)
* An EBUSY return is acceptable - a cursor may still
* be positioned on this old chunk.
*/
if (ret == 0) {
progress = 1;
F_CLR(chunk, WT_LSM_CHUNK_BLOOM);
__wt_free(session, chunk->bloom_uri);
chunk->bloom_uri = NULL;
} else if (ret != EBUSY)
goto err;
if (ret == EBUSY)
if (ret == EBUSY) {
WT_VERBOSE_ERR(session, lsm,
"LSM worker bloom drop busy: %s.",
chunk->bloom_uri);
continue;
} else
WT_ERR(ret);
F_CLR(chunk, WT_LSM_CHUNK_BLOOM);
}
if (chunk->uri != NULL) {
WT_WITH_SCHEMA_LOCK(session, ret =
@@ -255,19 +358,20 @@ __lsm_free_chunks(WT_SESSION_IMPL *session, WT_LSM_TREE *lsm_tree)
* An EBUSY return is acceptable - a cursor may still
* be positioned on this old chunk.
*/
if (ret == 0) {
progress = 1;
__wt_free(session, chunk->uri);
chunk->uri = NULL;
} else if (ret != EBUSY)
goto err;
if (ret == EBUSY) {
WT_VERBOSE_ERR(session, lsm,
"LSM worker drop busy: %s.",
chunk->uri);
continue;
} else
WT_ERR(ret);
}
if (chunk->uri == NULL &&
!F_ISSET(chunk, WT_LSM_CHUNK_BLOOM)) {
__wt_free(session, lsm_tree->old_chunks[i]);
++lsm_tree->old_avail;
}
progress = 1;
__wt_free(session, chunk->bloom_uri);
__wt_free(session, chunk->uri);
__wt_free(session, lsm_tree->old_chunks[i]);
++lsm_tree->old_avail;
}
if (locked) {
err: WT_TRET(__wt_lsm_meta_write(session, lsm_tree));

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include <signal.h>

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include "thread.h"

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include "thread.h"

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include "thread.h"

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include <sys/types.h>

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#define BDB 1 /* Berkeley DB header files */

View File

@@ -1,16 +1,36 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include "format.h"
#include "config.h"
static const char *config_file_type(int);
static const char *config_file_type(u_int);
static CONFIG *config_find(const char *, size_t);
static uint32_t config_translate(const char *);
static u_int config_translate(const char *);
/*
* config_setup --
@@ -20,6 +40,7 @@ void
config_setup(void)
{
CONFIG *cp;
const char *cstr;
/* Clear any temporary values. */
config_clear();
@@ -30,7 +51,7 @@ config_setup(void)
* them.
*/
cp = config_find("data_source", strlen("data_source"));
if (!(cp->flags & C_PERM)) {
if (!(cp->flags & C_PERM))
switch (MMRAND(0, 2)) {
case 0:
config_single("data_source=file", 0);
@@ -44,7 +65,6 @@ config_setup(void)
config_single("data_source=table", 0);
break;
}
}
cp = config_find("file_type", strlen("file_type"));
if (!(cp->flags & C_PERM)) {
@@ -62,8 +82,8 @@ config_setup(void)
config_single("file_type=row", 0);
break;
}
}
g.type = (int)config_translate(g.c_file_type);
}
g.type = config_translate(g.c_file_type);
/*
* If data_source and file_type were both "permanent", we may still
@@ -76,6 +96,48 @@ config_setup(void)
exit(EXIT_FAILURE);
}
/*
* Compression: choose something if compression wasn't specified,
* otherwise confirm the appropriate shared library is available.
*/
cp = config_find("compression", strlen("compression"));
if (!(cp->flags & C_PERM)) {
cstr = "compression=none";
switch (MMRAND(0, 9)) {
case 0: /* 10% */
break;
case 1: case 2: case 3: case 4: /* 40% */
if (access(BZIP_PATH, R_OK) == 0)
cstr = "compression=bzip";
break;
case 5: /* 10% */
#if 0
cstr = "compression=ext";
#endif
break;
case 6: case 7: case 8: case 9: /* 40% */
if (access(SNAPPY_PATH, R_OK) == 0)
cstr = "compression=snappy";
break;
}
config_single(cstr, 0);
}
g.compression = config_translate(g.c_compression);
if (cp->flags & C_PERM) {
if (g.compression == COMPRESS_BZIP &&
access(BZIP_PATH, R_OK) != 0) {
fprintf(stderr,
"bzip library not found or not readable\n");
exit(EXIT_FAILURE);
}
if (g.compression == COMPRESS_SNAPPY &&
access(SNAPPY_PATH, R_OK) != 0) {
fprintf(stderr,
"snappy library not found or not readable\n");
exit(EXIT_FAILURE);
}
}
/* Build the object name. */
if ((g.uri = malloc(
strlen(g.c_data_source) + strlen(WT_NAME) + 2)) == NULL)
@@ -274,7 +336,9 @@ config_single(const char *s, int perm)
}
else if (strncmp(s, "file_type", strlen("file_type")) == 0)
*cp->vstr = strdup(
config_file_type((int)config_translate(ep)));
config_file_type(config_translate(ep)));
else if (strncmp(s, "compression", strlen("compression")) == 0)
*cp->vstr = strdup(ep);
if (*cp->vstr == NULL)
syserr("strdup");
return;
@@ -299,25 +363,35 @@ config_single(const char *s, int perm)
* config_translate --
* Return an integer value representing the argument.
*/
static uint32_t
static u_int
config_translate(const char *s)
{
/* If it's already a integer value, we're done. */
if (isdigit(s[0]))
return (uint32_t)atoi(s);
return ((u_int)atoi(s));
/* Currently, all we translate are the file type names. */
/* File type names. */
if (strcmp(s, "fix") == 0 ||
strcmp(s, "flcs") == 0 || /* Deprecated */
strcmp(s, "fixed-length column-store") == 0)
return ((uint32_t)FIX);
return (FIX);
if (strcmp(s, "var") == 0 ||
strcmp(s, "vlcs") == 0 || /* Deprecated */
strcmp(s, "variable-length column-store") == 0)
return ((uint32_t)VAR);
return (VAR);
if (strcmp(s, "row") == 0 ||
strcmp(s, "row-store") == 0)
return ((uint32_t)ROW);
return (ROW);
/* Compression type names. */
if (strcmp(s, "none") == 0)
return (COMPRESS_NONE);
if (strcmp(s, "bzip") == 0)
return (COMPRESS_BZIP);
if (strcmp(s, "ext") == 0)
return (COMPRESS_EXT);
if (strcmp(s, "snappy") == 0)
return (COMPRESS_SNAPPY);
fprintf(stderr, "%s: %s: unknown configuration value\n", g.progname, s);
exit(EXIT_FAILURE);
@@ -347,7 +421,7 @@ config_find(const char *s, size_t len)
* Return the file type as a string.
*/
static const char *
config_file_type(int type)
config_file_type(u_int type)
{
switch (type) {
case FIX:

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
/*
@@ -39,7 +59,7 @@ typedef struct {
uint32_t min; /* Minimum value */
uint32_t max; /* Maximum value */
uint32_t *v; /* Value for this run */
u_int *v; /* Value for this run */
char **vstr; /* Value for string options */
} CONFIG;
@@ -54,14 +74,14 @@ static CONFIG c[] = {
"number of bits for fixed-length column-store files",
C_FIX, 0, 1, 8, &g.c_bitcnt, NULL },
{ "bzip",
"if blocks are BZIP2 encoded", /* 80% */
0, C_BOOL, 80, 0, &g.c_bzip, NULL },
{ "cache",
"size of the cache in MB",
0, 0, 1, 100, &g.c_cache, NULL },
{ "compression",
"type of compression (none | bzip | ext | snappy)",
0, C_IGNORE|C_STRING, 1, 4, NULL, &g.c_compression },
{ "data_source",
"type of data source to create (file | table | lsm)",
0, C_IGNORE | C_STRING, 0, 0, NULL, &g.c_data_source },

View File

@@ -1,12 +1,33 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <assert.h>
#include <ctype.h>
@@ -26,6 +47,14 @@
#include <wiredtiger.h>
#endif
#define EXTPATH "../../ext/" /* Extensions path */
#define BZIP_PATH \
EXTPATH "compressors/bzip2/.libs/libwiredtiger_bzip2.so"
#define SNAPPY_PATH \
EXTPATH "compressors/snappy/.libs/libwiredtiger_snappy.so"
#define REVERSE_PATH \
EXTPATH "collators/reverse/.libs/libwiredtiger_reverse_collator.so"
#define M(v) ((v) * 1000000) /* Million */
#define UNUSED(var) (void)(var) /* Quiet unused var warnings */
@@ -59,37 +88,44 @@ typedef struct {
int replay; /* Replaying a run. */
int track; /* Track progress */
char *uri; /* Object name */
#define FIX 1 /* File types */
#define ROW 2
#define VAR 3
int type; /* File type */
char *uri; /* Object name */
u_int type; /* File type */
#define COMPRESS_NONE 1
#define COMPRESS_BZIP 2
#define COMPRESS_EXT 3
#define COMPRESS_SNAPPY 4
u_int compression; /* Compression type */
char *config_open; /* Command-line configuration */
uint32_t c_bitcnt; /* Config values */
uint32_t c_bzip;
uint32_t c_cache;
char *c_data_source;
uint32_t c_delete_pct;
uint32_t c_dictionary;
char *c_file_type;
uint32_t c_huffman_key;
uint32_t c_huffman_value;
uint32_t c_insert_pct;
uint32_t c_intl_page_max;
uint32_t c_key_max;
uint32_t c_key_min;
uint32_t c_leaf_page_max;
uint32_t c_ops;
uint32_t c_repeat_data_pct;
uint32_t c_reverse;
uint32_t c_rows;
uint32_t c_runs;
uint32_t c_threads;
uint32_t c_value_max;
uint32_t c_value_min;
uint32_t c_write_pct;
u_int c_bitcnt; /* Config values */
u_int c_cache;
char *c_compression;
char *c_data_source;
u_int c_delete_pct;
u_int c_dictionary;
char *c_file_type;
u_int c_huffman_key;
u_int c_huffman_value;
u_int c_insert_pct;
u_int c_intl_page_max;
u_int c_key_max;
u_int c_key_min;
u_int c_leaf_page_max;
u_int c_ops;
u_int c_repeat_data_pct;
u_int c_reverse;
u_int c_rows;
u_int c_runs;
u_int c_threads;
u_int c_value_max;
u_int c_value_min;
u_int c_write_pct;
uint32_t key_cnt; /* Keys loaded so far */
uint32_t rows; /* Total rows */

View File

@@ -32,13 +32,16 @@ if test $# -ne 0; then
exit 1
fi
revext="$top/ext/collators/reverse/.libs/reverse_collator.so"
bzext="$top/ext/compressors/bzip2_compress/.libs/bzip2_compress.so"
if test -e $bzext ; then
ext="\"$revext\",\"$bzext\""
else
ext="\"$revext\""
ext="\"$top/ext/collators/reverse/.libs/libwiredtiger_reverse_collator.so\""
bz_ext="$top/ext/compressors/bzip2/.libs/libwiredtiger_bzip2.so"
if test -e $bz_ext ; then
ext="$ext,\"$bz_ext\""
fi
sn_ext="$top/ext/compressors/snappy/.libs/libwiredtiger_snappy.so"
if test -e $sn_ext ; then
ext="$ext,\"$sn_ext\""
fi
config='extensions=['$ext']'
$top/wt -h RUNDIR -C "$config" dump $wt_name |

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include "format.h"

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include "format.h"
@@ -183,9 +203,17 @@ track(const char *tag, uint64_t cnt, TINFO *tinfo)
uint32_t
wts_rand(void)
{
struct timeval t;
char buf[64];
uint32_t r;
/* If it's not a replay, seed the random number generator. */
if (!g.replay) {
if (gettimeofday(&t, NULL) != 0)
die(errno, "gettimeofday");
srand((u_int)(0xdeadbeef ^ (u_int)t.tv_usec));
}
/* If we're threaded, it's not repeatable, ignore the log. */
if (!SINGLETHREADED)
return ((uint32_t)rand());
@@ -202,10 +230,8 @@ wts_rand(void)
if ((g.rand_log =
fopen("RUNDIR/rand", g.replay ? "r" : "w")) == NULL)
die(errno, "fopen: RUNDIR/rand");
if (!g.replay) {
srand((u_int)(0xdeadbeef ^ (u_int)time(NULL)));
if (!g.replay)
(void)setvbuf(g.rand_log, NULL, _IOLBF, 0);
}
}
if (g.replay) {
if (fgets(buf, sizeof(buf), g.rand_log) == NULL) {

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include "format.h"
@@ -45,44 +65,45 @@ wts_open(void)
WT_SESSION *session;
uint32_t maxintlpage, maxintlitem, maxleafpage, maxleafitem;
int ret;
const char *ext1, *ext2;
char config[512], *end, *p;
/* If the bzip2 compression module has been built, use it. */
#define EXTPATH "../../ext"
ext1 = EXTPATH "compressors/bzip2_compress/.libs/bzip2_compress.so";
if (access(ext1, R_OK) != 0) {
ext1 = "";
g.c_bzip = 0;
}
ext2 = EXTPATH "/collators/reverse/.libs/reverse_collator.so";
char config[1024], *end, *p;
/*
* Open configuration -- put command line configuration options at the
* end so they can override "standard" configuration.
* Open configuration.
*
* Put command line configuration options at the end so they override
* the standard configuration.
*/
snprintf(config, sizeof(config),
"create,error_prefix=\"%s\",cache_size=%" PRIu32 "MB,sync=false,"
"extensions=[\"%s\",\"%s\"],%s",
g.progname, g.c_cache, ext1, ext2,
"extensions=[\"%s\",\"%s\", \"%s\"],%s",
g.progname, g.c_cache,
access(BZIP_PATH, R_OK) == 0 ? BZIP_PATH : "",
access(SNAPPY_PATH, R_OK) == 0 ? SNAPPY_PATH : "",
REVERSE_PATH,
g.config_open == NULL ? "" : g.config_open);
if ((ret =
wiredtiger_open("RUNDIR", &event_handler, config, &conn)) != 0)
die(ret, "wiredtiger_open");
g.wts_conn = conn;
if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
die(ret, "connection.open_session");
/*
* Create the object.
*
* Make sure at least 2 internal page per thread can fit in cache.
*/
maxintlpage = 1U << g.c_intl_page_max;
/* Make sure at least 2 internal page per thread can fit in cache. */
while (2 * g.c_threads * maxintlpage > g.c_cache << 20)
maxintlpage >>= 1;
maxintlitem = MMRAND(maxintlpage / 50, maxintlpage / 40);
if (maxintlitem < 40)
maxintlitem = 40;
maxleafpage = 1U << g.c_leaf_page_max;
/* Make sure at least one leaf page per thread can fit in cache. */
maxleafpage = 1U << g.c_leaf_page_max;
while (g.c_threads * (maxintlpage + maxleafpage) > g.c_cache << 20)
maxleafpage >>= 1;
maxleafitem = MMRAND(maxleafpage / 50, maxleafpage / 40);
@@ -98,10 +119,6 @@ wts_open(void)
(g.type == ROW) ? "u" : "r",
maxintlpage, maxintlitem, maxleafpage, maxleafitem);
if (g.c_bzip)
p += snprintf(p, (size_t)(end - p),
",block_compressor=\"bzip2_compress\"");
switch (g.type) {
case FIX:
p += snprintf(p, (size_t)(end - p),
@@ -125,13 +142,27 @@ wts_open(void)
break;
}
/* Configure compression. */
switch (g.compression) {
case COMPRESS_NONE:
break;
case COMPRESS_BZIP:
p += snprintf(p, (size_t)(end - p),
",block_compressor=\"bzip2\"");
break;
case COMPRESS_EXT:
break;
case COMPRESS_SNAPPY:
p += snprintf(p, (size_t)(end - p),
",block_compressor=\"snappy\"");
break;
}
if ((ret = session->create(session, g.uri, config)) != 0)
die(ret, "session.create: %s", g.uri);
if ((ret = session->close(session, NULL)) != 0)
die(ret, "session.close");
g.wts_conn = conn;
}
void

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include "format.h"

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include "format.h"
@@ -120,8 +140,11 @@ ops(void *arg)
memset(&value, 0, sizeof(value));
val_gen_setup(&valbuf);
/* Each thread does its share of the total operations. */
thread_ops = g.c_ops / g.c_threads;
/*
* Each thread does its share of the total operations, and make sure
* that it's not 0 (testing runs: threads might be larger than ops).
*/
thread_ops = g.c_threads + g.c_ops / g.c_threads;
/* Pick a period for re-opening the session and cursors. */
session = NULL;

View File

@@ -1,3 +1,30 @@
/*-
* Public Domain 2008-2012 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.
*/
#include <assert.h>
#include <stdlib.h>
#include <time.h>

View File

@@ -1,3 +1,30 @@
/*-
* Public Domain 2008-2012 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.
*/
#include <assert.h>
#include <stdlib.h>
#include <time.h>

View File

@@ -1,3 +1,30 @@
/*-
* Public Domain 2008-2012 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.
*/
#include <assert.h>
#include <stdlib.h>
#include <time.h>

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include "wt_internal.h"

View File

@@ -97,7 +97,8 @@ class test_compress01_base(wttest.WiredTigerTestCase):
testdir = os.path.dirname(__file__)
import run
extdir = os.path.join(run.wt_builddir, 'ext/compressors')
extfile = os.path.join(extdir, name, '.libs', name + '.so')
extfile = os.path.join(
extdir, name, '.libs', 'libwiredtiger_' + name + '.so')
if not os.path.exists(extfile):
self.skipTest('Extension "' + extfile + '" not built')
return 'extensions=["' + extfile + '"]'
@@ -130,15 +131,15 @@ class compress01_tests(object):
class test_compress01_1_nop(test_compress01_base, compress01_tests):
def __init__(self, testname):
test_compress01_base.__init__(self, testname, 'nop_compress', 'nop')
test_compress01_base.__init__(self, testname, 'nop', 'nop')
class test_compress01_2_bz(test_compress01_base, compress01_tests):
def __init__(self, testname):
test_compress01_base.__init__(self, testname, 'bzip2_compress', 'bz')
test_compress01_base.__init__(self, testname, 'bzip2', 'bz')
class test_compress01_3_sn(test_compress01_base, compress01_tests):
def __init__(self, testname):
test_compress01_base.__init__(self, testname, 'snappy_compress', 'sn')
test_compress01_base.__init__(self, testname, 'snappy', 'sn')
if __name__ == '__main__':

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include "thread.h"

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include "thread.h"

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include "thread.h"

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include "thread.h"

View File

@@ -1,8 +1,28 @@
/*-
* Copyright (c) 2008-2012 WiredTiger, Inc.
* All rights reserved.
* Public Domain 2008-2012 WiredTiger, Inc.
*
* See the file LICENSE for redistribution information.
* 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.
*/
#include <sys/types.h>