Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
247fe0f8ce | ||
|
|
450a29d1bc | ||
|
|
04faa7f24e | ||
|
|
729c4ce6db | ||
|
|
40a775d5bf | ||
|
|
e2256d6888 | ||
|
|
4166623d77 | ||
|
|
366ef0f287 | ||
|
|
d3aab45b96 | ||
|
|
e040d5a3d9 | ||
|
|
f46350b57f | ||
|
|
5d8c1e28bc | ||
|
|
3844f602ff | ||
|
|
647f83d11a | ||
|
|
7bedb693a6 | ||
|
|
bf6bc01e3f | ||
|
|
a1359905ad | ||
|
|
8246befcd8 | ||
|
|
61e5b885a2 | ||
|
|
f347a3301d | ||
|
|
1e14492ea0 | ||
|
|
a1b08d168e | ||
|
|
a31f708a1c | ||
|
|
e1189da479 | ||
|
|
64c54763f0 | ||
|
|
a5aba41271 | ||
|
|
ac1bd50106 | ||
|
|
bca4607b9e | ||
|
|
57db817d67 | ||
|
|
c507009cee | ||
|
|
c062a33272 | ||
|
|
2bce92c180 | ||
|
|
45c1e2a5a3 | ||
|
|
38591db0fd | ||
|
|
466e7ade5c | ||
|
|
82a6530951 | ||
|
|
9c371c5a84 | ||
|
|
0250344b90 | ||
|
|
6792cd8115 | ||
|
|
8fa690dce6 |
1
.hgtags
1
.hgtags
@@ -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
63
NEWS
@@ -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
4
README
@@ -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:
|
||||
|
||||
|
||||
2
RELEASE
2
RELEASE
@@ -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"`
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
21
dist/api_data.py
vendored
@@ -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
1
dist/s_funcs.list
vendored
@@ -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
4
dist/s_string.ok
vendored
@@ -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
|
||||
|
||||
@@ -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] */
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
6
ext/compressors/bzip2/Makefile.am
Normal file
6
ext/compressors/bzip2/Makefile.am
Normal 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
|
||||
@@ -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. */
|
||||
@@ -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
|
||||
9
ext/compressors/nop/Makefile.am
Normal file
9
ext/compressors/nop/Makefile.am
Normal 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
|
||||
@@ -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. */
|
||||
@@ -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
|
||||
6
ext/compressors/snappy/Makefile.am
Normal file
6
ext/compressors/snappy/Makefile.am
Normal 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
|
||||
@@ -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. */
|
||||
@@ -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
|
||||
@@ -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.
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" },
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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. */
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
/*
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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.}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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__':
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user