Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2698a34aa3 | ||
|
|
2da36349a2 | ||
|
|
21386f956e | ||
|
|
59fddb2109 | ||
|
|
a82a65805f | ||
|
|
6a7972d8ca | ||
|
|
3c8f54583a | ||
|
|
1a2cf3ba21 | ||
|
|
405f6a3969 | ||
|
|
a3de556296 | ||
|
|
39fdfd8d48 | ||
|
|
787035cf14 | ||
|
|
fb9d316b61 | ||
|
|
c4db159a08 | ||
|
|
261b6640d4 | ||
|
|
f977094e54 | ||
|
|
d346eade1e | ||
|
|
966b216ee8 | ||
|
|
763fd3c876 | ||
|
|
99bc3af83b | ||
|
|
06b0957920 |
57
NEWS
57
NEWS
@@ -1,11 +1,51 @@
|
||||
WiredTiger release 1.1.2, 2012-03-20
|
||||
------------------------------------
|
||||
|
||||
Add public-domain copyright notices to the extension code.
|
||||
|
||||
test/format can now run multi-threaded, fixed two bugs it found:
|
||||
(1) When iterating backwards through a skiplist, we could race with an insert.
|
||||
(2) If eviction fails for a page, we have to assume that eviction has unlocked
|
||||
the reference.
|
||||
|
||||
Scan row-store leaf pages twice when reading to reduce the overhead of the
|
||||
index array.
|
||||
|
||||
Eviction race fixes:
|
||||
(1) Call __rec_review with WT_REFs: don't look at the page until we've checked
|
||||
the state.
|
||||
(2) Clear the eviction point if we hit it when discarding a child page, not
|
||||
just the parent.
|
||||
|
||||
Eviction tuning changes, particularly for read-only, out-of-cache workloads.
|
||||
|
||||
Only notify the eviction server if an application thread doesn't find any pages
|
||||
to evict, and then only once.
|
||||
|
||||
Only spin on the LRU lock if there might be pages in the LRU queue to evict.
|
||||
|
||||
Keep the current eviction point in memory and make the eviction walk run
|
||||
concurrent with LRU eviction.
|
||||
|
||||
Every test now has err/out captured, and it is checked to assure it is empty at
|
||||
the end of every test.
|
||||
|
||||
|
||||
WiredTiger release 1.1.1, 2012-03-12
|
||||
------------------------------------
|
||||
|
||||
Default to a verbose build: that can be switched off by running "configure --enable-silent-rules").
|
||||
Default to a verbose build: that can be switched off by running "configure
|
||||
--enable-silent-rules").
|
||||
|
||||
Account for all memory allocated when reading a page into cache. Total memory usage is now much closer to the cache size when using many small keys and values.
|
||||
Account for all memory allocated when reading a page into cache. Total memory
|
||||
usage is now much closer to the cache size when using many small keys and
|
||||
values.
|
||||
|
||||
Have application threads trigger a retry forced page eviction rather than blocking eviction. This allows rec_evict.c to simply set the WT_REF state to WT_REF_MEM after all failures, and fixes a bug where pages on the forced eviction queue would end up with state WT_REF_MEM, meaning they could be chosen for eviction multiple times.
|
||||
Have application threads trigger a retry forced page eviction rather than
|
||||
blocking eviction. This allows rec_evict.c to simply set the WT_REF state to
|
||||
WT_REF_MEM after all failures, and fixes a bug where pages on the forced
|
||||
eviction queue would end up with state WT_REF_MEM, meaning they could be chosen
|
||||
for eviction multiple times.
|
||||
|
||||
Grow existing scratch buffers in preference to allocating new ones.
|
||||
|
||||
@@ -13,11 +53,16 @@ Fix a race between threads reading in and then modifying a page.
|
||||
|
||||
Get rid of the pinned flag: it is no longer used.
|
||||
|
||||
Fix a race where btree files weren't completely closed before they could be re-opened. This behavior can be triggered by using a new session on every operation (see the new -S flag to the test/thread program). [#178]
|
||||
Fix a race where btree files weren't completely closed before they could be
|
||||
re-opened. This behavior can be triggered by using a new session on every
|
||||
operation (see the new -S flag to the test/thread program). [#178]
|
||||
|
||||
When connections are closed, create a session and discard the btree handles. This fixes a long-standing bug in closing a connection: if for any reason there are btree handles still open, we need a real session handle to close them.
|
||||
When connections are closed, create a session and discard the btree handles.
|
||||
This fixes a long-standing bug in closing a connection: if for any reason there
|
||||
are btree handles still open, we need a real session handle to close them.
|
||||
|
||||
Really close btree handles: otherwise we can't safely remove or rename them. Fixes test failures in test_base02 (among others).
|
||||
Really close btree handles: otherwise we can't safely remove or rename them.
|
||||
Fixes test failures in test_base02 (among others).
|
||||
|
||||
Wait for application threads in LRU eviction to drain before walking a file.
|
||||
|
||||
|
||||
4
README
4
README
@@ -1,6 +1,6 @@
|
||||
WiredTiger 1.1.1: (March 16, 2012)
|
||||
WiredTiger 1.1.2: (March 20, 2012)
|
||||
|
||||
This is version 1.1.1 of WiredTiger.
|
||||
This is version 1.1.2 of WiredTiger.
|
||||
|
||||
WiredTiger documentation can be found at:
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ dnl build by dist/s_version
|
||||
|
||||
VERSION_MAJOR=1
|
||||
VERSION_MINOR=1
|
||||
VERSION_PATCH=1
|
||||
VERSION_STRING='"WiredTiger 1.1.1: (March 12, 2012)"'
|
||||
VERSION_PATCH=2
|
||||
VERSION_STRING='"WiredTiger 1.1.2: (March 20, 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.1.1
|
||||
1.1.2
|
||||
|
||||
2
dist/RELEASE
vendored
2
dist/RELEASE
vendored
@@ -1,6 +1,6 @@
|
||||
WIREDTIGER_VERSION_MAJOR=1
|
||||
WIREDTIGER_VERSION_MINOR=1
|
||||
WIREDTIGER_VERSION_PATCH=1
|
||||
WIREDTIGER_VERSION_PATCH=2
|
||||
WIREDTIGER_VERSION="$WIREDTIGER_VERSION_MAJOR.$WIREDTIGER_VERSION_MINOR.$WIREDTIGER_VERSION_PATCH"
|
||||
|
||||
WIREDTIGER_RELEASE_DATE=`date "+%B %e, %Y"`
|
||||
|
||||
1
dist/s_copyright.list
vendored
1
dist/s_copyright.list
vendored
@@ -12,7 +12,6 @@ skip dist/serial.py
|
||||
skip dist/stat_data.py
|
||||
skip dist/stat.py
|
||||
skip docs/tools/doxypy.py
|
||||
skip docs/tools/fixlinks.py
|
||||
skip lang/python/setup.py
|
||||
skip lang/python/src/wiredtiger/service/constants.py
|
||||
skip lang/python/src/wiredtiger/service/__init__.py
|
||||
|
||||
1
dist/s_funcs.list
vendored
1
dist/s_funcs.list
vendored
@@ -1,4 +1,5 @@
|
||||
# List of functions that aren't found by s_funcs, but that's OK.
|
||||
WT_CURDUMP_PASS
|
||||
__bit_ffs
|
||||
__bit_nclr
|
||||
__wt_bm_addr_stderr
|
||||
|
||||
2
dist/s_release
vendored
2
dist/s_release
vendored
@@ -47,3 +47,5 @@ echo "Packing release into $RELEASE_DIR/$PKG.tar.bz2"
|
||||
echo "Packing documentation into $RELEASE_DIR/$PKG-docs.tar.bz2"
|
||||
(cd "$RELEASE_DIR" && tar cf - $PKG/[A-Z][A-Z]* $PKG/docs | \
|
||||
bzip2 -9 > $PKG-docs.tar.bz2)
|
||||
|
||||
rm -r $DEST
|
||||
|
||||
6
dist/s_types
vendored
6
dist/s_types
vendored
@@ -3,12 +3,8 @@
|
||||
t=__wt.$$
|
||||
trap 'rm -f $t; exit 0' 0 1 2 3 13 15
|
||||
|
||||
l="`cd .. && echo src/include/*.[hi] src/include/*.in`"
|
||||
l="`cd .. && find test -name '*.c' -print`"
|
||||
l="`cd .. && echo */*.i`"
|
||||
l="$l `sed -e '/^[a-z]/! d' filelist`"
|
||||
|
||||
(cd .. &&
|
||||
l="`find examples ext src test -name '*.[chi]' -o -name '*.in'`"
|
||||
egrep 'u_quad|u_int8_t|u_int16_t|u_int32_t|u_int64_t' $l |
|
||||
sed '/@u_quad_decl@/d') > $t
|
||||
test -s $t && cat $t && exit 1
|
||||
|
||||
@@ -133,6 +133,7 @@ inuse
|
||||
io
|
||||
ip
|
||||
je
|
||||
jemalloc
|
||||
jni
|
||||
json
|
||||
keyexist
|
||||
@@ -154,6 +155,7 @@ lsn
|
||||
lt
|
||||
mailto
|
||||
mainpage
|
||||
malloc
|
||||
malloc'd
|
||||
marshalled
|
||||
marshalling
|
||||
@@ -255,6 +257,7 @@ subpage
|
||||
superset
|
||||
tablename
|
||||
tcl
|
||||
tcmalloc
|
||||
td
|
||||
th
|
||||
thang
|
||||
|
||||
@@ -9,7 +9,7 @@ function.
|
||||
The effectiveness of the cache can be measured by reviewing the page
|
||||
eviction statistics for the database.
|
||||
|
||||
An example of setting a cache size to 10MB:
|
||||
An example of setting a cache size to 500MB:
|
||||
|
||||
@snippet ex_config.c configure cache size
|
||||
|
||||
@@ -90,6 +90,17 @@ An example of configuring page sizes:
|
||||
|
||||
@snippet ex_file.c file create
|
||||
|
||||
@section memory Memory allocation
|
||||
|
||||
I/O intensive threaded applications, where the working set does not fit
|
||||
into the available cache, can be dominated by memory allocation because
|
||||
the WiredTiger engine has to free and re-allocate memory as part of many
|
||||
queries. Replacing the system's malloc implementation with one that has
|
||||
better threaded performance (for example, Google's
|
||||
<a href="http://goog-perftools.sourceforge.net/doc/tcmalloc.html">tcmalloc</a>,
|
||||
or <a href="http://www.canonware.com/jemalloc">jemalloc</a>),
|
||||
can dramatically improve throughput.
|
||||
|
||||
@section statistics Performance monitoring with statistics
|
||||
|
||||
WiredTiger maintains a variety of statistics that can be read with a
|
||||
@@ -116,5 +127,4 @@ statistics until the cursor returns the end of the list.
|
||||
Note the raw value of the statistic is available from the \c value
|
||||
field, as well as a printable string version of the value.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,30 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (c) 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.
|
||||
#
|
||||
# This Python script is run as part of generating the documentation for the
|
||||
# WiredTiger Python API. It runs after doxypy, and turns method names in
|
||||
# comments into references to the corresponding function in the C API.
|
||||
|
||||
@@ -1,4 +1,29 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 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.
|
||||
|
||||
tooldir=`dirname $0`
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ int main(void)
|
||||
|
||||
/*! [configure cache size] */
|
||||
if ((ret = wiredtiger_open(home, NULL,
|
||||
"create,cache_size=10M", &conn)) != 0)
|
||||
"create,cache_size=500M", &conn)) != 0)
|
||||
fprintf(stderr, "Error connecting to %s: %s\n",
|
||||
home, wiredtiger_strerror(ret));
|
||||
/*! [configure cache size] */
|
||||
|
||||
@@ -158,9 +158,9 @@ bzip2_compress(WT_COMPRESSOR *compressor, WT_SESSION *session,
|
||||
return (bzip2_error(session, "BZ2_bzCompressInit", ret));
|
||||
|
||||
bz.next_in = (char *)src;
|
||||
bz.avail_in = src_len;
|
||||
bz.avail_in = (uint32_t)src_len;
|
||||
bz.next_out = (char *)dst;
|
||||
bz.avail_out = dst_len;
|
||||
bz.avail_out = (uint32_t)dst_len;
|
||||
if ((ret = BZ2_bzCompress(&bz, BZ_FINISH)) == BZ_STREAM_END) {
|
||||
*compression_failed = 0;
|
||||
*result_lenp = dst_len - bz.avail_out;
|
||||
@@ -193,9 +193,9 @@ bzip2_decompress(WT_COMPRESSOR *compressor, WT_SESSION *session,
|
||||
return (bzip2_error(session, "BZ2_bzDecompressInit", ret));
|
||||
|
||||
bz.next_in = (char *)src;
|
||||
bz.avail_in = src_len;
|
||||
bz.avail_in = (uint32_t)src_len;
|
||||
bz.next_out = (char *)dst;
|
||||
bz.avail_out = dst_len;
|
||||
bz.avail_out = (uint32_t)dst_len;
|
||||
if ((ret = BZ2_bzDecompress(&bz)) == BZ_STREAM_END) {
|
||||
*result_lenp = dst_len - bz.avail_out;
|
||||
ret = 0;
|
||||
|
||||
@@ -21,7 +21,7 @@ __wt_block_truncate(WT_SESSION_IMPL *session, const char *filename)
|
||||
int ret;
|
||||
|
||||
/* Open the underlying file handle. */
|
||||
WT_RET(__wt_open(session, filename, 0, 1, &fh));
|
||||
WT_RET(__wt_open(session, filename, 0, 0, 1, &fh));
|
||||
|
||||
/* Truncate the file. */
|
||||
WT_ERR(__wt_ftruncate(session, fh, (off_t)0));
|
||||
@@ -43,18 +43,10 @@ int
|
||||
__wt_block_create(WT_SESSION_IMPL *session, const char *filename)
|
||||
{
|
||||
WT_FH *fh;
|
||||
int exist, ret;
|
||||
int ret;
|
||||
|
||||
/* Check to see if the file exists -- we don't want to overwrite it. */
|
||||
WT_RET(__wt_exist(session, filename, &exist));
|
||||
if (exist)
|
||||
WT_RET_MSG(session, WT_ERROR,
|
||||
"the file %s already exists; to re-create it, remove it "
|
||||
"first, then create it",
|
||||
filename);
|
||||
|
||||
/* Open the underlying file handle. */
|
||||
WT_RET(__wt_open(session, filename, 1, 1, &fh));
|
||||
/* Create the underlying file and open a handle. */
|
||||
WT_RET(__wt_open(session, filename, 1, 1, 1, &fh));
|
||||
|
||||
/* Write out the file's meta-data. */
|
||||
ret = __wt_desc_init(session, fh);
|
||||
@@ -96,7 +88,7 @@ __wt_block_open(WT_SESSION_IMPL *session, const char *filename,
|
||||
__wt_block_freelist_open(session, block);
|
||||
|
||||
/* Open the underlying file handle. */
|
||||
WT_ERR(__wt_open(session, filename, 1, 1, &block->fh));
|
||||
WT_ERR(__wt_open(session, filename, 0, 0, 1, &block->fh));
|
||||
|
||||
/* Get the allocation size. */
|
||||
WT_ERR(__wt_config_getones(session, config, "allocation_size", &cval));
|
||||
|
||||
@@ -812,8 +812,8 @@ __slvg_col_range_overlap(
|
||||
* #7 AAAAAAAAAAAAAAAA same as #2
|
||||
* #8 AAAAAAAAAAAAA same as #3
|
||||
* #9 AAAAA A is a prefix of B
|
||||
* #10 AAAAAAAAAA A is a suffix of B
|
||||
* #11 AAAAAA A is middle of B
|
||||
* #10 AAAAAA A is middle of B
|
||||
* #11 AAAAAAAAAA A is a suffix of B
|
||||
*
|
||||
* Because the leaf page array was sorted by record number and a_trk
|
||||
* appears earlier in that array than b_trk, cases #2/7, #10 and #11
|
||||
@@ -1351,8 +1351,8 @@ __slvg_row_range_overlap(
|
||||
* #7 AAAAAAAAAAAAAAAA same as #2
|
||||
* #8 AAAAAAAAAAAAA same as #3
|
||||
* #9 AAAAA A is a prefix of B
|
||||
* #10 AAAAAAAAAA A is a suffix of B
|
||||
* #11 AAAAAA A is middle of B
|
||||
* #10 AAAAAA A is middle of B
|
||||
* #11 AAAAAAAAAA A is a suffix of B
|
||||
*
|
||||
* Because the leaf page array was sorted by record number and a_trk
|
||||
* appears earlier in that array than b_trk, cases #2/7, #10 and #11
|
||||
|
||||
@@ -356,9 +356,6 @@ __process_value(WT_CONFIG *conf, WT_CONFIG_ITEM *value)
|
||||
} else if (value->type == ITEM_NUM) {
|
||||
errno = 0;
|
||||
value->val = strtoll(value->str, &endptr, 10);
|
||||
if (errno == ERANGE)
|
||||
return (
|
||||
__config_err(conf, "Number out of range", ERANGE));
|
||||
|
||||
/* Check any leftover characters. */
|
||||
while (endptr < value->str + value->len)
|
||||
@@ -396,7 +393,17 @@ __process_value(WT_CONFIG *conf, WT_CONFIG_ITEM *value)
|
||||
value->type = ITEM_ID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we parsed the the whole string but the number is out of
|
||||
* range, report an error. Don't report an error for strings
|
||||
* that aren't well-formed integers: if an integer is expected,
|
||||
* that will be caught by __wt_config_check.
|
||||
*/
|
||||
if (value->type == ITEM_NUM && errno == ERANGE)
|
||||
return (
|
||||
__config_err(conf, "Number out of range", ERANGE));
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -464,7 +464,7 @@ wiredtiger_open(const char *home, WT_EVENT_HANDLER *event_handler,
|
||||
WT_ERR(__wt_config_gets(session, cfg, "logging", &cval));
|
||||
if (cval.val != 0)
|
||||
WT_ERR(__wt_open(
|
||||
session, WT_LOG_FILENAME, 1, 0, &conn->log_fh));
|
||||
session, WT_LOG_FILENAME, 1, 0, 0, &conn->log_fh));
|
||||
|
||||
/* Configure direct I/O and buffer alignment. */
|
||||
WT_ERR(__wt_config_gets(session, cfg, "buffer_alignment", &cval));
|
||||
@@ -606,7 +606,7 @@ __conn_single(WT_CONNECTION_IMPL *conn, const char **cfg)
|
||||
*/
|
||||
WT_RET(__wt_config_gets(session, cfg, "create", &cval));
|
||||
WT_RET(__wt_open(session,
|
||||
WT_FLAGFILE, cval.val == 0 ? 0 : 1, 0, &conn->lock_fh));
|
||||
WT_FLAGFILE, cval.val == 0 ? 0 : 1, 0, 0, &conn->lock_fh));
|
||||
|
||||
/*
|
||||
* Lock a byte of the file: if we don't get the lock, some other process
|
||||
@@ -698,7 +698,7 @@ __conn_config(WT_CONNECTION_IMPL *conn, const char **cfg, WT_ITEM **cbufp)
|
||||
return (0);
|
||||
|
||||
/* Open the configuration file. */
|
||||
WT_RET(__wt_open(session, WT_CONFIGFILE, 0, 0, &fh));
|
||||
WT_RET(__wt_open(session, WT_CONFIGFILE, 0, 0, 0, &fh));
|
||||
WT_ERR(__wt_filesize(session, fh, &size));
|
||||
if (size == 0)
|
||||
goto err;
|
||||
|
||||
@@ -67,8 +67,7 @@ __wt_curconfig_open(WT_SESSION_IMPL *session,
|
||||
cursor->key_format = cursor->value_format = "S";
|
||||
|
||||
STATIC_ASSERT(offsetof(WT_CURSOR_CONFIG, iface) == 0);
|
||||
WT_ERR(__wt_cursor_init(cursor, uri, 0, 1, cfg));
|
||||
*cursorp = cursor;
|
||||
WT_ERR(__wt_cursor_init(cursor, uri, 0, cfg, cursorp));
|
||||
|
||||
if (0) {
|
||||
err: __wt_free(session, cconfig);
|
||||
|
||||
@@ -9,63 +9,36 @@
|
||||
|
||||
/*
|
||||
* __raw_to_dump --
|
||||
* We have a buffer where the data item contains a raw value, convert it
|
||||
* to a printable string.
|
||||
* We have a buffer where the data item contains a raw value,
|
||||
* convert it to a printable string.
|
||||
*/
|
||||
static int
|
||||
__raw_to_dump(
|
||||
WT_SESSION_IMPL *session, WT_ITEM *from, WT_ITEM *to, int hexonly)
|
||||
{
|
||||
WT_ITEM *tmp;
|
||||
uint32_t size;
|
||||
|
||||
/*
|
||||
* In the worst case, every character takes up 3 spaces, plus a
|
||||
* trailing nul byte.
|
||||
*/
|
||||
WT_RET(__wt_scr_alloc(session, from->size * 3 + 10, &tmp));
|
||||
size = from->size;
|
||||
if (hexonly)
|
||||
__wt_raw_to_hex(from->data, tmp->mem, &size);
|
||||
WT_RET(__wt_raw_to_hex(session, from->data, from->size, to));
|
||||
else
|
||||
__wt_raw_to_esc_hex(from->data, tmp->mem, &size);
|
||||
tmp->size = size;
|
||||
|
||||
__wt_buf_swap(to, tmp);
|
||||
__wt_scr_free(&tmp);
|
||||
WT_RET(
|
||||
__wt_raw_to_esc_hex(session, from->data, from->size, to));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __dump_to_raw --
|
||||
* We have a scratch buffer where the data item contains a dump string,
|
||||
* We have a buffer containing a dump string,
|
||||
* convert it to a raw value.
|
||||
*/
|
||||
static int
|
||||
__dump_to_raw(
|
||||
WT_SESSION_IMPL *session, const char *src_arg, WT_ITEM *item, int hexonly)
|
||||
{
|
||||
uint32_t size;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* Overwrite the string in place: the underlying cursor set_key and
|
||||
* set_value functions are going to use the cursor's key and value
|
||||
* buffers, which means we can't. This should probably be fixed by
|
||||
* layering the dump cursor on top of other cursors and then we can
|
||||
* use the dump cursor's key/value buffers.
|
||||
*/
|
||||
if (hexonly)
|
||||
WT_RET(__wt_hex_to_raw(
|
||||
session, (void *)src_arg, (void *)src_arg, &size));
|
||||
WT_RET(__wt_hex_to_raw(session, src_arg, item));
|
||||
else
|
||||
WT_RET(__wt_esc_hex_to_raw(
|
||||
session, (void *)src_arg, (void *)src_arg, &size));
|
||||
WT_RET(__wt_esc_hex_to_raw(session, src_arg, item));
|
||||
|
||||
memset(item, 0, sizeof(WT_ITEM));
|
||||
item->data = src_arg;
|
||||
item->size = size;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -76,26 +49,24 @@ __dump_to_raw(
|
||||
static int
|
||||
__curdump_get_key(WT_CURSOR *cursor, ...)
|
||||
{
|
||||
WT_CURSOR *child;
|
||||
WT_CURSOR_DUMP *cdump;
|
||||
WT_ITEM item, *itemp;
|
||||
WT_SESSION_IMPL *session;
|
||||
int ret;
|
||||
uint64_t recno;
|
||||
va_list ap;
|
||||
|
||||
cdump = (WT_CURSOR_DUMP *)cursor;
|
||||
child = cdump->child;
|
||||
CURSOR_API_CALL(cursor, session, get_key, NULL);
|
||||
|
||||
if (WT_CURSOR_RECNO(cursor) && !F_ISSET(cursor, WT_CURSTD_RAW)) {
|
||||
if (F_ISSET(cursor, WT_CURSTD_TABLE))
|
||||
WT_ERR(__wt_curtable_get_key(cursor, &recno));
|
||||
else
|
||||
WT_ERR(__wt_cursor_get_key(cursor, &recno));
|
||||
WT_ERR(child->get_key(child, &recno));
|
||||
|
||||
WT_ERR(__wt_buf_fmt(session, &cursor->key, "%" PRIu64, recno));
|
||||
} else {
|
||||
if (F_ISSET(cursor, WT_CURSTD_TABLE))
|
||||
WT_ERR(__wt_curtable_get_key(cursor, &item));
|
||||
else
|
||||
WT_ERR(__wt_cursor_get_key(cursor, &item));
|
||||
WT_ERR(child->get_key(child, &item));
|
||||
|
||||
WT_ERR(__raw_to_dump(session, &item,
|
||||
&cursor->key, F_ISSET(cursor, WT_CURSTD_DUMP_HEX) ? 1 : 0));
|
||||
@@ -150,13 +121,16 @@ format: WT_RET_MSG(session, EINVAL, "%s: invalid record number", p);
|
||||
static void
|
||||
__curdump_set_key(WT_CURSOR *cursor, ...)
|
||||
{
|
||||
WT_ITEM item;
|
||||
WT_CURSOR_DUMP *cdump;
|
||||
WT_CURSOR *child;
|
||||
WT_SESSION_IMPL *session;
|
||||
uint64_t recno;
|
||||
va_list ap;
|
||||
const char *p;
|
||||
int ret;
|
||||
|
||||
cdump = (WT_CURSOR_DUMP *)cursor;
|
||||
child = cdump->child;
|
||||
CURSOR_API_CALL(cursor, session, set_key, NULL);
|
||||
|
||||
va_start(ap, cursor);
|
||||
@@ -169,18 +143,12 @@ __curdump_set_key(WT_CURSOR *cursor, ...)
|
||||
if (WT_CURSOR_RECNO(cursor) && !F_ISSET(cursor, WT_CURSTD_RAW)) {
|
||||
WT_ERR(str2recno(session, p, &recno));
|
||||
|
||||
if (F_ISSET(cursor, WT_CURSTD_TABLE))
|
||||
__wt_curtable_set_key(cursor, recno);
|
||||
else
|
||||
__wt_cursor_set_key(cursor, recno);
|
||||
child->set_key(child, recno);
|
||||
} else {
|
||||
WT_ERR(__dump_to_raw(session,
|
||||
p, &item, F_ISSET(cursor, WT_CURSTD_DUMP_HEX) ? 1 : 0));
|
||||
WT_ERR(__dump_to_raw(session, p, &cursor->key,
|
||||
F_ISSET(cursor, WT_CURSTD_DUMP_HEX) ? 1 : 0));
|
||||
|
||||
if (F_ISSET(cursor, WT_CURSTD_TABLE))
|
||||
__wt_curtable_set_key(cursor, &item);
|
||||
else
|
||||
__wt_cursor_set_key(cursor, &item);
|
||||
child->set_key(child, &cursor->key);
|
||||
}
|
||||
|
||||
if (0) {
|
||||
@@ -198,17 +166,18 @@ err: cursor->saved_err = ret;
|
||||
static int
|
||||
__curdump_get_value(WT_CURSOR *cursor, ...)
|
||||
{
|
||||
WT_CURSOR_DUMP *cdump;
|
||||
WT_CURSOR *child;
|
||||
WT_ITEM item, *itemp;
|
||||
WT_SESSION_IMPL *session;
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
cdump = (WT_CURSOR_DUMP *)cursor;
|
||||
child = cdump->child;
|
||||
CURSOR_API_CALL(cursor, session, get_value, NULL);
|
||||
|
||||
if (F_ISSET(cursor, WT_CURSTD_TABLE))
|
||||
WT_ERR(__wt_curtable_get_value(cursor, &item));
|
||||
else
|
||||
WT_ERR(__wt_cursor_get_value(cursor, &item));
|
||||
WT_ERR(child->get_value(child, &item));
|
||||
|
||||
WT_ERR(__raw_to_dump(session, &item,
|
||||
&cursor->value, F_ISSET(cursor, WT_CURSTD_DUMP_HEX) ? 1 : 0));
|
||||
@@ -233,12 +202,15 @@ err: API_END(session);
|
||||
static void
|
||||
__curdump_set_value(WT_CURSOR *cursor, ...)
|
||||
{
|
||||
WT_ITEM item;
|
||||
WT_CURSOR_DUMP *cdump;
|
||||
WT_CURSOR *child;
|
||||
WT_SESSION_IMPL *session;
|
||||
va_list ap;
|
||||
int ret;
|
||||
const char *p;
|
||||
|
||||
cdump = (WT_CURSOR_DUMP *)cursor;
|
||||
child = cdump->child;
|
||||
CURSOR_API_CALL(cursor, session, set_value, NULL);
|
||||
|
||||
va_start(ap, cursor);
|
||||
@@ -249,12 +221,9 @@ __curdump_set_value(WT_CURSOR *cursor, ...)
|
||||
va_end(ap);
|
||||
|
||||
WT_ERR(__dump_to_raw(session,
|
||||
p, &item, F_ISSET(cursor, WT_CURSTD_DUMP_HEX) ? 1 : 0));
|
||||
p, &cursor->value, F_ISSET(cursor, WT_CURSTD_DUMP_HEX) ? 1 : 0));
|
||||
|
||||
if (F_ISSET(cursor, WT_CURSTD_TABLE))
|
||||
__wt_curtable_set_value(cursor, &item);
|
||||
else
|
||||
__wt_cursor_set_value(cursor, &item);
|
||||
child->set_value(child, &cursor->value);
|
||||
|
||||
if (0) {
|
||||
err: cursor->saved_err = ret;
|
||||
@@ -264,15 +233,111 @@ err: cursor->saved_err = ret;
|
||||
API_END(session);
|
||||
}
|
||||
|
||||
/* Pass through a call to the underlying cursor. */
|
||||
#define WT_CURDUMP_PASS(op) \
|
||||
static int \
|
||||
__curdump_##op(WT_CURSOR *cursor) \
|
||||
{ \
|
||||
WT_CURSOR_DUMP *cdump; \
|
||||
\
|
||||
cdump = (WT_CURSOR_DUMP *)cursor; \
|
||||
return (cdump->child->op(cdump->child)); \
|
||||
}
|
||||
|
||||
WT_CURDUMP_PASS(next)
|
||||
WT_CURDUMP_PASS(prev)
|
||||
WT_CURDUMP_PASS(reset)
|
||||
WT_CURDUMP_PASS(search)
|
||||
|
||||
static int
|
||||
__curdump_search_near(WT_CURSOR *cursor, int *exact)
|
||||
{
|
||||
WT_CURSOR_DUMP *cdump;
|
||||
|
||||
cdump = (WT_CURSOR_DUMP *)cursor;
|
||||
return (cdump->child->search_near(cdump->child, exact));
|
||||
}
|
||||
|
||||
WT_CURDUMP_PASS(insert)
|
||||
WT_CURDUMP_PASS(update)
|
||||
WT_CURDUMP_PASS(remove)
|
||||
|
||||
static int
|
||||
__curdump_close(WT_CURSOR *cursor)
|
||||
{
|
||||
WT_CURSOR_DUMP *cdump;
|
||||
WT_CURSOR *child;
|
||||
WT_SESSION_IMPL *session;
|
||||
int ret;
|
||||
|
||||
cdump = (WT_CURSOR_DUMP *)cursor;
|
||||
child = cdump->child;
|
||||
ret = 0;
|
||||
|
||||
CURSOR_API_CALL(cursor, session, get_key, NULL);
|
||||
if (child != NULL)
|
||||
WT_TRET(child->close(child));
|
||||
/* We shared the child's URI. */
|
||||
cursor->uri = NULL;
|
||||
WT_TRET(__wt_cursor_close(cursor));
|
||||
API_END(session);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* __wt_curdump_init --
|
||||
* initialize a dump cursor.
|
||||
*/
|
||||
void
|
||||
__wt_curdump_init(WT_CURSOR *cursor)
|
||||
int
|
||||
__wt_curdump_create(WT_CURSOR *child, WT_CURSOR *owner, WT_CURSOR **cursorp)
|
||||
{
|
||||
cursor->get_key = __curdump_get_key;
|
||||
cursor->get_value = __curdump_get_value;
|
||||
cursor->set_key = __curdump_set_key;
|
||||
cursor->set_value = __curdump_set_value;
|
||||
static WT_CURSOR iface = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
__curdump_get_key,
|
||||
__curdump_get_value,
|
||||
__curdump_set_key,
|
||||
__curdump_set_value,
|
||||
NULL,
|
||||
__curdump_next,
|
||||
__curdump_prev,
|
||||
__curdump_reset,
|
||||
__curdump_search,
|
||||
__curdump_search_near,
|
||||
__curdump_insert,
|
||||
__curdump_update,
|
||||
__curdump_remove,
|
||||
__curdump_close,
|
||||
{ NULL, NULL }, /* TAILQ_ENTRY q */
|
||||
0, /* recno key */
|
||||
{ 0 }, /* recno raw buffer */
|
||||
{ NULL, 0, 0, NULL, 0 },/* WT_ITEM key */
|
||||
{ NULL, 0, 0, NULL, 0 },/* WT_ITEM value */
|
||||
0, /* int saved_err */
|
||||
0 /* uint32_t flags */
|
||||
};
|
||||
WT_CURSOR *cursor;
|
||||
WT_CURSOR_DUMP *cdump;
|
||||
WT_SESSION_IMPL *session;
|
||||
const char *cfg[] = API_CONF_DEFAULTS(session, open_cursor, NULL);
|
||||
|
||||
session = (WT_SESSION_IMPL *)child->session;
|
||||
WT_RET(__wt_calloc_def(session, 1, &cdump));
|
||||
cursor = &cdump->iface;
|
||||
*cursor = iface;
|
||||
cursor->session = child->session;
|
||||
cursor->uri = child->uri;
|
||||
cursor->key_format = child->key_format;
|
||||
cursor->value_format = child->value_format;
|
||||
cdump->child = child;
|
||||
|
||||
/* Copy the dump flags from the child cursor. */
|
||||
F_SET(cursor,
|
||||
F_ISSET(child, WT_CURSTD_DUMP_PRINT | WT_CURSTD_DUMP_HEX));
|
||||
|
||||
WT_RET(__wt_cursor_init(cursor, NULL, owner, cfg, cursorp));
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ __curfile_close(WT_CURSOR *cursor)
|
||||
*/
|
||||
int
|
||||
__wt_curfile_create(WT_SESSION_IMPL *session,
|
||||
const char *cfg[], WT_CURSOR **cursorp)
|
||||
WT_CURSOR *owner, const char *cfg[], WT_CURSOR **cursorp)
|
||||
{
|
||||
static WT_CURSOR iface = {
|
||||
NULL,
|
||||
@@ -260,32 +260,8 @@ __wt_curfile_create(WT_SESSION_IMPL *session,
|
||||
if (bulk)
|
||||
WT_ERR(__wt_curbulk_init((WT_CURSOR_BULK *)cbt));
|
||||
|
||||
/* The append flag is only relevant to column stores. */
|
||||
if (WT_CURSOR_RECNO(cursor)) {
|
||||
WT_ERR(__wt_config_gets(session, cfg, "append", &cval));
|
||||
if (cval.val != 0)
|
||||
F_SET(cursor, WT_CURSTD_APPEND);
|
||||
}
|
||||
|
||||
WT_ERR(__wt_config_gets(session, cfg, "dump", &cval));
|
||||
if (cval.len != 0) {
|
||||
__wt_curdump_init(cursor);
|
||||
F_SET(cursor,
|
||||
strncmp(cval.str, "print", cval.len) == 0 ?
|
||||
WT_CURSTD_DUMP_PRINT : WT_CURSTD_DUMP_HEX);
|
||||
}
|
||||
|
||||
WT_ERR(__wt_config_gets(session, cfg, "raw", &cval));
|
||||
if (cval.val != 0)
|
||||
F_SET(cursor, WT_CURSTD_RAW);
|
||||
|
||||
WT_ERR(__wt_config_gets(session, cfg, "overwrite", &cval));
|
||||
if (cval.val != 0)
|
||||
F_SET(cursor, WT_CURSTD_OVERWRITE);
|
||||
|
||||
STATIC_ASSERT(offsetof(WT_CURSOR_BTREE, iface) == 0);
|
||||
WT_ERR(__wt_cursor_init(cursor, cursor->uri, 1, 0, cfg));
|
||||
*cursorp = cursor;
|
||||
WT_ERR(__wt_cursor_init(cursor, cursor->uri, owner, cfg, cursorp));
|
||||
|
||||
if (0) {
|
||||
err: __wt_free(session, cbt);
|
||||
@@ -313,5 +289,5 @@ __wt_curfile_open(WT_SESSION_IMPL *session,
|
||||
else
|
||||
return (EINVAL);
|
||||
|
||||
return (__wt_curfile_create(session, cfg, cursorp));
|
||||
return (__wt_curfile_create(session, NULL, cfg, cursorp));
|
||||
}
|
||||
|
||||
@@ -319,7 +319,8 @@ __curindex_open_colgroups(
|
||||
cp[arg] != NULL)
|
||||
continue;
|
||||
session->btree = table->colgroup[arg];
|
||||
WT_RET(__wt_curfile_create(session, cfg, &cp[arg]));
|
||||
WT_RET(__wt_curfile_create(
|
||||
session, &cindex->cbt.iface, cfg, &cp[arg]));
|
||||
}
|
||||
|
||||
return (0);
|
||||
@@ -425,9 +426,7 @@ __wt_curindex_open(WT_SESSION_IMPL *session,
|
||||
|
||||
/* Open the column groups needed for this index cursor. */
|
||||
WT_ERR(__curindex_open_colgroups(session, cindex, cfg));
|
||||
|
||||
WT_ERR(__wt_cursor_init(cursor, cursor->uri, 1, 1, cfg));
|
||||
*cursorp = cursor;
|
||||
WT_ERR(__wt_cursor_init(cursor, cursor->uri, 0, cfg, cursorp));
|
||||
|
||||
if (0) {
|
||||
err: (void)__curindex_close(cursor);
|
||||
|
||||
@@ -309,10 +309,10 @@ __wt_curstat_open(WT_SESSION_IMPL *session,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
__curstat_get_key,
|
||||
__curstat_get_value,
|
||||
__curstat_set_key,
|
||||
__curstat_set_value,
|
||||
NULL,
|
||||
__curstat_next,
|
||||
__curstat_prev,
|
||||
@@ -338,7 +338,7 @@ __wt_curstat_open(WT_SESSION_IMPL *session,
|
||||
WT_CURSOR *cursor;
|
||||
WT_STATS *stats_first;
|
||||
void (*clear_func)(WT_STATS *);
|
||||
int clear_on_close, raw, ret, stats_count;
|
||||
int clear_on_close, ret, stats_count;
|
||||
|
||||
btree = NULL;
|
||||
clear_func = NULL;
|
||||
@@ -348,9 +348,6 @@ __wt_curstat_open(WT_SESSION_IMPL *session,
|
||||
WT_RET(__wt_config_gets(session, cfg, "clear_on_close", &cval));
|
||||
clear_on_close = (cval.val != 0);
|
||||
|
||||
WT_RET(__wt_config_gets(session, cfg, "raw", &cval));
|
||||
raw = (cval.val != 0);
|
||||
|
||||
if (!WT_PREFIX_SKIP(uri, "statistics:"))
|
||||
return (EINVAL);
|
||||
if (WT_PREFIX_MATCH(uri, "file:")) {
|
||||
@@ -371,27 +368,9 @@ __wt_curstat_open(WT_SESSION_IMPL *session,
|
||||
}
|
||||
|
||||
WT_ERR(__wt_calloc_def(session, 1, &cst));
|
||||
cst->stats_first = stats_first;
|
||||
cst->stats_count = stats_count;
|
||||
cst->notpositioned = 1;
|
||||
cst->clear_func = clear_func;
|
||||
|
||||
cursor = &cst->iface;
|
||||
*cursor = iface;
|
||||
cursor->session = &session->iface;
|
||||
|
||||
cursor->get_key = __curstat_get_key;
|
||||
cursor->set_key = __curstat_set_key;
|
||||
cursor->get_value = __curstat_get_value;
|
||||
cursor->set_value = __curstat_set_value;
|
||||
|
||||
cst->btree = btree;
|
||||
if (raw)
|
||||
F_SET(cursor, WT_CURSTD_RAW);
|
||||
|
||||
STATIC_ASSERT(offsetof(WT_CURSOR_STAT, iface) == 0);
|
||||
WT_ERR(__wt_cursor_init(cursor, uri, 0, 1, cfg));
|
||||
|
||||
/*
|
||||
* We return the statistics field's offset as the key, and a string
|
||||
* description, a string value, and a uint64_t value as the value
|
||||
@@ -400,7 +379,14 @@ __wt_curstat_open(WT_SESSION_IMPL *session,
|
||||
cursor->key_format = "i";
|
||||
cursor->value_format = "SSq";
|
||||
|
||||
*cursorp = cursor;
|
||||
cst->btree = btree;
|
||||
cst->stats_first = stats_first;
|
||||
cst->stats_count = stats_count;
|
||||
cst->notpositioned = 1;
|
||||
cst->clear_func = clear_func;
|
||||
|
||||
STATIC_ASSERT(offsetof(WT_CURSOR_STAT, iface) == 0);
|
||||
WT_ERR(__wt_cursor_init(cursor, uri, NULL, cfg, cursorp));
|
||||
|
||||
if (0) {
|
||||
err: __wt_free(session, cst);
|
||||
|
||||
@@ -293,10 +293,8 @@ __wt_cursor_close(WT_CURSOR *cursor)
|
||||
__wt_buf_free(session, &cursor->key);
|
||||
__wt_buf_free(session, &cursor->value);
|
||||
|
||||
if (F_ISSET(cursor, WT_CURSTD_PUBLIC))
|
||||
TAILQ_REMOVE(&session->public_cursors, cursor, q);
|
||||
else if (F_ISSET(cursor, WT_CURSTD_FILE))
|
||||
TAILQ_REMOVE(&session->file_cursors, cursor, q);
|
||||
if (F_ISSET(cursor, WT_CURSTD_OPEN))
|
||||
TAILQ_REMOVE(&session->cursors, cursor, q);
|
||||
|
||||
__wt_free(session, cursor->uri);
|
||||
__wt_free(session, cursor);
|
||||
@@ -373,11 +371,12 @@ err: if (cursor != NULL)
|
||||
*/
|
||||
int
|
||||
__wt_cursor_init(WT_CURSOR *cursor,
|
||||
const char *uri, int is_file, int is_public, const char *cfg[])
|
||||
const char *uri, WT_CURSOR *owner, const char *cfg[], WT_CURSOR **cursorp)
|
||||
{
|
||||
WT_CURSOR *cdump;
|
||||
WT_CONFIG_ITEM cval;
|
||||
WT_SESSION_IMPL *session;
|
||||
|
||||
WT_UNUSED(cfg);
|
||||
session = (WT_SESSION_IMPL *)cursor->session;
|
||||
|
||||
if (cursor->get_key == NULL)
|
||||
@@ -399,14 +398,44 @@ __wt_cursor_init(WT_CURSOR *cursor,
|
||||
WT_CLEAR(cursor->key);
|
||||
WT_CLEAR(cursor->value);
|
||||
|
||||
if (is_file) {
|
||||
F_SET(cursor, WT_CURSTD_FILE);
|
||||
TAILQ_INSERT_HEAD(&session->file_cursors, cursor, q);
|
||||
} else if (is_public) {
|
||||
F_SET(cursor, WT_CURSTD_PUBLIC);
|
||||
TAILQ_INSERT_HEAD(&session->public_cursors, cursor, q);
|
||||
/* The append flag is only relevant to column stores. */
|
||||
if (WT_CURSOR_RECNO(cursor)) {
|
||||
WT_RET(__wt_config_gets(session, cfg, "append", &cval));
|
||||
if (cval.val != 0)
|
||||
F_SET(cursor, WT_CURSTD_APPEND);
|
||||
}
|
||||
|
||||
WT_RET(__wt_config_gets(session, cfg, "dump", &cval));
|
||||
if (cval.len != 0) {
|
||||
F_SET(cursor, (strncmp(cval.str, "print", cval.len) == 0) ?
|
||||
WT_CURSTD_DUMP_PRINT : WT_CURSTD_DUMP_HEX);
|
||||
WT_RET(__wt_curdump_create(cursor, owner, &cdump));
|
||||
owner = cdump;
|
||||
} else
|
||||
cdump = NULL;
|
||||
|
||||
WT_RET(__wt_config_gets(session, cfg, "raw", &cval));
|
||||
if (cval.val != 0)
|
||||
F_SET(cursor, WT_CURSTD_RAW);
|
||||
|
||||
WT_RET(__wt_config_gets(session, cfg, "overwrite", &cval));
|
||||
if (cval.val != 0)
|
||||
F_SET(cursor, WT_CURSTD_OVERWRITE);
|
||||
|
||||
/*
|
||||
* Cursors that are internal to some other cursor (such as file cursors
|
||||
* inside a table cursor) should be closed after the containing cursor.
|
||||
* Arrange for that to happen by putting internal cursors after their
|
||||
* owners on the queue.
|
||||
*/
|
||||
if (owner != NULL)
|
||||
TAILQ_INSERT_AFTER(&session->cursors, owner, cursor, q);
|
||||
else
|
||||
TAILQ_INSERT_HEAD(&session->cursors, cursor, q);
|
||||
|
||||
F_SET(cursor, WT_CURSTD_OPEN);
|
||||
|
||||
*cursorp = (cdump != NULL) ? cdump : cursor;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@@ -464,7 +464,8 @@ __curtable_open_colgroups(WT_CURSOR_TABLE *ctable, const char *cfg[])
|
||||
i < WT_COLGROUPS(table);
|
||||
i++, cp++) {
|
||||
session->btree = table->colgroup[i];
|
||||
WT_RET(__wt_curfile_create(session, cfg_no_overwrite, cp));
|
||||
WT_RET(__wt_curfile_create(
|
||||
session, &ctable->iface, cfg_no_overwrite, cp));
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@@ -493,7 +494,7 @@ __curtable_open_indices(WT_CURSOR_TABLE *ctable)
|
||||
WT_RET(__wt_calloc_def(session, table->nindices, &ctable->idx_cursors));
|
||||
for (i = 0, cp = ctable->idx_cursors; i < table->nindices; i++, cp++) {
|
||||
session->btree = table->index[i];
|
||||
WT_RET(__wt_curfile_create(session, cfg, cp));
|
||||
WT_RET(__wt_curfile_create(session, &ctable->iface, cfg, cp));
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@@ -533,7 +534,6 @@ __wt_curtable_open(WT_SESSION_IMPL *session,
|
||||
0, /* int saved_err */
|
||||
0 /* uint32_t flags */
|
||||
};
|
||||
WT_CONFIG_ITEM cval;
|
||||
WT_CURSOR *cursor;
|
||||
WT_CURSOR_TABLE *ctable;
|
||||
WT_ITEM fmt, plan;
|
||||
@@ -571,7 +571,7 @@ __wt_curtable_open(WT_SESSION_IMPL *session,
|
||||
* table cursor.
|
||||
*/
|
||||
session->btree = table->colgroup[0];
|
||||
return (__wt_curfile_create(session, cfg, cursorp));
|
||||
return (__wt_curfile_create(session, NULL, cfg, cursorp));
|
||||
}
|
||||
|
||||
WT_RET(__wt_calloc_def(session, 1, &ctable));
|
||||
@@ -582,7 +582,6 @@ __wt_curtable_open(WT_SESSION_IMPL *session,
|
||||
cursor->uri = table->name;
|
||||
cursor->key_format = table->key_format;
|
||||
cursor->value_format = table->value_format;
|
||||
F_SET(cursor, WT_CURSTD_TABLE);
|
||||
|
||||
ctable->table = table;
|
||||
ctable->plan = table->plan;
|
||||
@@ -598,42 +597,22 @@ __wt_curtable_open(WT_SESSION_IMPL *session,
|
||||
ctable->plan = __wt_buf_steal(session, &plan, NULL);
|
||||
}
|
||||
|
||||
/* The append flag is only relevant to column stores. */
|
||||
if (WT_CURSOR_RECNO(cursor)) {
|
||||
WT_ERR(__wt_config_gets(session, cfg, "append", &cval));
|
||||
if (cval.val != 0)
|
||||
F_SET(cursor, WT_CURSTD_APPEND);
|
||||
}
|
||||
|
||||
WT_ERR(__wt_config_gets(session, cfg, "dump", &cval));
|
||||
if (cval.len != 0) {
|
||||
__wt_curdump_init(cursor);
|
||||
F_SET(cursor,
|
||||
strncmp(cval.str, "print", cval.len) == 0 ?
|
||||
WT_CURSTD_DUMP_PRINT : WT_CURSTD_DUMP_HEX);
|
||||
}
|
||||
|
||||
WT_ERR(__wt_config_gets(session, cfg, "raw", &cval));
|
||||
if (cval.val != 0)
|
||||
F_SET(cursor, WT_CURSTD_RAW);
|
||||
|
||||
WT_ERR(__wt_config_gets(session, cfg, "overwrite", &cval));
|
||||
if (cval.val != 0)
|
||||
F_SET(cursor, WT_CURSTD_OVERWRITE);
|
||||
STATIC_ASSERT(offsetof(WT_CURSOR_TABLE, iface) == 0);
|
||||
WT_ERR(__wt_cursor_init(cursor, cursor->uri, NULL, cfg, cursorp));
|
||||
|
||||
/*
|
||||
* Open the colgroup cursors immediately: we're going to need them for
|
||||
* any operation. We defer opening index cursors until we need them
|
||||
* for an update.
|
||||
* for an update. Note that this must come after the call to
|
||||
* __wt_cursor_init: the table cursor must already be on the list of
|
||||
* session cursors or we can't work out where to put the colgroup
|
||||
* cursor(s).
|
||||
*/
|
||||
WT_ERR(__curtable_open_colgroups(ctable, cfg));
|
||||
|
||||
STATIC_ASSERT(offsetof(WT_CURSOR_TABLE, iface) == 0);
|
||||
WT_ERR(__wt_cursor_init(cursor, cursor->uri, 0, 1, cfg));
|
||||
*cursorp = cursor;
|
||||
|
||||
if (0) {
|
||||
err: (void)__curtable_close(cursor);
|
||||
*cursorp = NULL;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
|
||||
@@ -67,10 +67,8 @@ struct __wt_session_impl {
|
||||
TAILQ_HEAD(__btrees, __wt_btree_session) btrees;
|
||||
|
||||
WT_CURSOR *cursor; /* Current cursor */
|
||||
/* All file cursors */
|
||||
TAILQ_HEAD(__file_cursors, __wt_cursor) file_cursors;
|
||||
/* Cursors closed with the session */
|
||||
TAILQ_HEAD(__public_cursors, __wt_cursor) public_cursors;
|
||||
TAILQ_HEAD(__cursors, __wt_cursor) cursors;
|
||||
|
||||
WT_BTREE *schematab; /* Schema tables */
|
||||
TAILQ_HEAD(__tables, __wt_table) tables;
|
||||
|
||||
@@ -120,6 +120,12 @@ struct __wt_cursor_config {
|
||||
WT_CURSOR iface;
|
||||
};
|
||||
|
||||
struct __wt_cursor_dump {
|
||||
WT_CURSOR iface;
|
||||
|
||||
WT_CURSOR *child;
|
||||
};
|
||||
|
||||
struct __wt_cursor_index {
|
||||
WT_CURSOR_BTREE cbt;
|
||||
|
||||
|
||||
@@ -455,8 +455,11 @@ extern int __wt_curconfig_open(WT_SESSION_IMPL *session,
|
||||
const char *uri,
|
||||
const char *cfg[],
|
||||
WT_CURSOR **cursorp);
|
||||
extern void __wt_curdump_init(WT_CURSOR *cursor);
|
||||
extern int __wt_curdump_create(WT_CURSOR *child,
|
||||
WT_CURSOR *owner,
|
||||
WT_CURSOR **cursorp);
|
||||
extern int __wt_curfile_create(WT_SESSION_IMPL *session,
|
||||
WT_CURSOR *owner,
|
||||
const char *cfg[],
|
||||
WT_CURSOR **cursorp);
|
||||
extern int __wt_curfile_open(WT_SESSION_IMPL *session,
|
||||
@@ -485,9 +488,9 @@ extern int __wt_cursor_dup(WT_SESSION_IMPL *session,
|
||||
WT_CURSOR **cursorp);
|
||||
extern int __wt_cursor_init(WT_CURSOR *cursor,
|
||||
const char *uri,
|
||||
int is_file,
|
||||
int is_public,
|
||||
const char *cfg[]);
|
||||
WT_CURSOR *owner,
|
||||
const char *cfg[],
|
||||
WT_CURSOR **cursorp);
|
||||
extern int __wt_cursor_kv_not_set(WT_CURSOR *cursor, int key);
|
||||
extern int __wt_curtable_get_key(WT_CURSOR *cursor, ...);
|
||||
extern int __wt_curtable_get_value(WT_CURSOR *cursor, ...);
|
||||
@@ -560,6 +563,7 @@ extern int __wt_rwlock_destroy(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock);
|
||||
extern int __wt_open(WT_SESSION_IMPL *session,
|
||||
const char *name,
|
||||
int ok_create,
|
||||
int exclusive,
|
||||
int is_tree,
|
||||
WT_FH **fhp);
|
||||
extern int __wt_close(WT_SESSION_IMPL *session, WT_FH *fh);
|
||||
@@ -617,6 +621,7 @@ extern int __wt_struct_unpack(WT_SESSION_IMPL *session,
|
||||
extern int __wt_create_file(WT_SESSION_IMPL *session,
|
||||
const char *name,
|
||||
const char *fileuri,
|
||||
int exclusive,
|
||||
const char *config);
|
||||
extern int __wt_schema_create( WT_SESSION_IMPL *session,
|
||||
const char *name,
|
||||
@@ -769,7 +774,7 @@ extern int __wt_btree_get_root(WT_SESSION_IMPL *session, WT_ITEM *addr);
|
||||
extern int __wt_btree_free_root(WT_SESSION_IMPL *session);
|
||||
extern int __wt_btree_set_root(WT_SESSION_IMPL *session,
|
||||
const char *filename,
|
||||
uint8_t *addr,
|
||||
const uint8_t *addr,
|
||||
uint32_t size);
|
||||
extern void __wt_eventv(WT_SESSION_IMPL *session,
|
||||
int msg_event,
|
||||
@@ -825,16 +830,20 @@ __wt_hazard_set(WT_SESSION_IMPL *session, WT_REF *ref
|
||||
extern void __wt_hazard_clear(WT_SESSION_IMPL *session, WT_PAGE *page);
|
||||
extern void __wt_hazard_empty(WT_SESSION_IMPL *session);
|
||||
extern void __wt_hazard_validate(WT_SESSION_IMPL *session, WT_PAGE *page);
|
||||
extern void __wt_raw_to_hex(const void *from, void *to, uint32_t *sizep);
|
||||
extern void __wt_raw_to_esc_hex(const void *from, void *to, uint32_t *sizep);
|
||||
extern int __wt_hex_to_raw( WT_SESSION_IMPL *session,
|
||||
void *from,
|
||||
void *to,
|
||||
uint32_t *sizep);
|
||||
extern int __wt_esc_hex_to_raw( WT_SESSION_IMPL *session,
|
||||
void *from,
|
||||
void *to,
|
||||
uint32_t *sizep);
|
||||
extern int __wt_raw_to_hex(WT_SESSION_IMPL *session,
|
||||
const uint8_t *from,
|
||||
uint32_t size,
|
||||
WT_ITEM *to);
|
||||
extern int __wt_raw_to_esc_hex(WT_SESSION_IMPL *session,
|
||||
const uint8_t *from,
|
||||
size_t size,
|
||||
WT_ITEM *to);
|
||||
extern int __wt_hex_to_raw(WT_SESSION_IMPL *session,
|
||||
const char *from,
|
||||
WT_ITEM *to);
|
||||
extern int __wt_esc_hex_to_raw(WT_SESSION_IMPL *session,
|
||||
const char *from,
|
||||
WT_ITEM *to);
|
||||
extern int __wt_huffman_open(WT_SESSION_IMPL *session,
|
||||
void *symbol_frequency_array,
|
||||
u_int symcnt,
|
||||
@@ -872,7 +881,6 @@ extern int __wt_buf_set_printable( WT_SESSION_IMPL *session,
|
||||
extern void *__wt_buf_steal(WT_SESSION_IMPL *session,
|
||||
WT_ITEM *buf,
|
||||
uint32_t *sizep);
|
||||
extern void __wt_buf_swap(WT_ITEM *a, WT_ITEM *b);
|
||||
extern void __wt_buf_free(WT_SESSION_IMPL *session, WT_ITEM *buf);
|
||||
extern int __wt_buf_fmt(WT_SESSION_IMPL *session,
|
||||
WT_ITEM *buf,
|
||||
|
||||
@@ -395,13 +395,11 @@ struct __wt_cursor {
|
||||
#define WT_CURSTD_APPEND 0x0001
|
||||
#define WT_CURSTD_DUMP_HEX 0x0002
|
||||
#define WT_CURSTD_DUMP_PRINT 0x0004
|
||||
#define WT_CURSTD_FILE 0x0008
|
||||
#define WT_CURSTD_KEY_SET 0x0010
|
||||
#define WT_CURSTD_KEY_SET 0x0008
|
||||
#define WT_CURSTD_OPEN 0x0010
|
||||
#define WT_CURSTD_OVERWRITE 0x0020
|
||||
#define WT_CURSTD_PUBLIC 0x0040
|
||||
#define WT_CURSTD_RAW 0x0080
|
||||
#define WT_CURSTD_TABLE 0x0100
|
||||
#define WT_CURSTD_VALUE_SET 0x0200
|
||||
#define WT_CURSTD_RAW 0x0040
|
||||
#define WT_CURSTD_VALUE_SET 0x0080
|
||||
uint32_t flags;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -86,6 +86,8 @@ struct __wt_cursor_bulk;
|
||||
typedef struct __wt_cursor_bulk WT_CURSOR_BULK;
|
||||
struct __wt_cursor_config;
|
||||
typedef struct __wt_cursor_config WT_CURSOR_CONFIG;
|
||||
struct __wt_cursor_dump;
|
||||
typedef struct __wt_cursor_dump WT_CURSOR_DUMP;
|
||||
struct __wt_cursor_index;
|
||||
typedef struct __wt_cursor_index WT_CURSOR_INDEX;
|
||||
struct __wt_cursor_stat;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*/
|
||||
int
|
||||
__wt_open(WT_SESSION_IMPL *session,
|
||||
const char *name, int ok_create, int is_tree, WT_FH **fhp)
|
||||
const char *name, int ok_create, int exclusive, int is_tree, WT_FH **fhp)
|
||||
{
|
||||
const char *path;
|
||||
WT_CONNECTION_IMPL *conn;
|
||||
@@ -52,6 +52,8 @@ __wt_open(WT_SESSION_IMPL *session,
|
||||
#endif
|
||||
if (ok_create) {
|
||||
f |= O_CREAT;
|
||||
if (exclusive)
|
||||
f |= O_EXCL;
|
||||
mode = 0666;
|
||||
} else
|
||||
mode = 0;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
int
|
||||
__wt_create_file(WT_SESSION_IMPL *session,
|
||||
const char *name, const char *fileuri, const char *config)
|
||||
const char *name, const char *fileuri, int exclusive, const char *config)
|
||||
{
|
||||
WT_ITEM *val;
|
||||
const char *cfg[] = API_CONF_DEFAULTS(session, create, config);
|
||||
@@ -34,8 +34,12 @@ __wt_create_file(WT_SESSION_IMPL *session,
|
||||
|
||||
/* If the file exists, don't try to recreate it. */
|
||||
if ((ret = __wt_session_get_btree(session, name, fileuri,
|
||||
is_schema ? config : NULL, NULL, WT_BTREE_NO_LOCK)) != WT_NOTFOUND)
|
||||
is_schema ? config : NULL,
|
||||
NULL, WT_BTREE_NO_LOCK)) != WT_NOTFOUND) {
|
||||
if (ret == 0 && exclusive)
|
||||
ret = EEXIST;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
WT_RET(__wt_btree_create(session, filename));
|
||||
WT_ERR(__wt_schema_table_track_fileop(session, NULL, filename));
|
||||
@@ -84,8 +88,8 @@ err: __wt_scr_free(&val);
|
||||
}
|
||||
|
||||
static int
|
||||
__create_colgroup(
|
||||
WT_SESSION_IMPL *session, const char *name, const char *config)
|
||||
__create_colgroup(WT_SESSION_IMPL *session,
|
||||
const char *name, int exclusive, const char *config)
|
||||
{
|
||||
WT_CONFIG_ITEM cval;
|
||||
WT_ITEM fmt, namebuf, uribuf;
|
||||
@@ -93,11 +97,12 @@ __create_colgroup(
|
||||
const char *cfg[] = { __wt_confdfl_colgroup_meta, config, NULL, NULL };
|
||||
const char *filecfg[] = { config, NULL, NULL };
|
||||
const char **cfgp;
|
||||
const char *cgconf, *cgname, *fileconf, *filename, *fileuri, *tablename;
|
||||
const char *cgconf, *cgname, *fileconf, *filename, *fileuri;
|
||||
const char *oldconf, *tablename;
|
||||
size_t tlen;
|
||||
int ret;
|
||||
|
||||
cgconf = fileconf = NULL;
|
||||
cgconf = fileconf = oldconf = NULL;
|
||||
WT_CLEAR(fmt);
|
||||
WT_CLEAR(namebuf);
|
||||
WT_CLEAR(uribuf);
|
||||
@@ -115,7 +120,7 @@ __create_colgroup(
|
||||
if ((ret =
|
||||
__wt_schema_get_table(session, tablename, tlen, &table)) != 0)
|
||||
WT_RET_MSG(session, (ret == WT_NOTFOUND) ? ENOENT : ret,
|
||||
"Can't create '%s' for non-existent table %.*s",
|
||||
"Can't create '%s' for non-existent table '%.*s'",
|
||||
name, (int)tlen, tablename);
|
||||
|
||||
/* Make sure the column group is referenced from the table. */
|
||||
@@ -167,13 +172,22 @@ __create_colgroup(
|
||||
WT_ERR(__wt_buf_fmt(session, &uribuf, "file:%s", filename));
|
||||
fileuri = uribuf.data;
|
||||
|
||||
WT_ERR(__wt_schema_table_insert(session, name, cgconf));
|
||||
WT_ERR(__wt_create_file(session, name, fileuri, fileconf));
|
||||
if ((ret = __wt_schema_table_insert(session, name, cgconf)) != 0) {
|
||||
/*
|
||||
* If the entry already exists in the schema table, we're done.
|
||||
* This is an error for exclusive creates but okay otherwise.
|
||||
*/
|
||||
if (ret == WT_DUPLICATE_KEY)
|
||||
ret = exclusive ? EEXIST : 0;
|
||||
goto err;
|
||||
}
|
||||
WT_ERR(__wt_create_file(session, name, fileuri, exclusive, fileconf));
|
||||
|
||||
WT_ERR(__wt_schema_open_colgroups(session, table));
|
||||
|
||||
err: __wt_free(session, cgconf);
|
||||
__wt_free(session, fileconf);
|
||||
__wt_free(session, oldconf);
|
||||
__wt_buf_free(session, &fmt);
|
||||
__wt_buf_free(session, &namebuf);
|
||||
__wt_buf_free(session, &uribuf);
|
||||
@@ -181,7 +195,8 @@ err: __wt_free(session, cgconf);
|
||||
}
|
||||
|
||||
static int
|
||||
__create_index(WT_SESSION_IMPL *session, const char *name, const char *config)
|
||||
__create_index(WT_SESSION_IMPL *session,
|
||||
const char *name, int exclusive, const char *config)
|
||||
{
|
||||
WT_CONFIG pkcols;
|
||||
WT_CONFIG_ITEM ckey, cval, icols;
|
||||
@@ -266,8 +281,16 @@ __create_index(WT_SESSION_IMPL *session, const char *name, const char *config)
|
||||
WT_ERR(__wt_buf_fmt(session, &uribuf, "file:%s", filename));
|
||||
fileuri = uribuf.data;
|
||||
|
||||
WT_ERR(__wt_create_file(session, name, fileuri, fileconf));
|
||||
WT_ERR(__wt_schema_table_insert(session, name, idxconf));
|
||||
if ((ret = __wt_schema_table_insert(session, name, idxconf)) != 0) {
|
||||
/*
|
||||
* If the entry already exists in the schema table, we're done.
|
||||
* This is an error for exclusive creates but okay otherwise.
|
||||
*/
|
||||
if (ret == WT_DUPLICATE_KEY)
|
||||
ret = exclusive ? EEXIST : 0;
|
||||
goto err;
|
||||
}
|
||||
WT_ERR(__wt_create_file(session, name, fileuri, exclusive, fileconf));
|
||||
|
||||
err: __wt_free(session, fileconf);
|
||||
__wt_free(session, idxconf);
|
||||
@@ -279,7 +302,8 @@ err: __wt_free(session, fileconf);
|
||||
}
|
||||
|
||||
static int
|
||||
__create_table(WT_SESSION_IMPL *session, const char *name, const char *config)
|
||||
__create_table(WT_SESSION_IMPL *session,
|
||||
const char *name, int exclusive, const char *config)
|
||||
{
|
||||
WT_CONFIG conf;
|
||||
WT_CONFIG_ITEM cgkey, cgval, cval;
|
||||
@@ -300,10 +324,8 @@ __create_table(WT_SESSION_IMPL *session, const char *name, const char *config)
|
||||
|
||||
if ((ret = __wt_schema_get_table(session,
|
||||
tablename, strlen(tablename), &table)) == 0) {
|
||||
if (__wt_config_getones(session,
|
||||
config, "exclusive", &cval) == 0 && cval.val)
|
||||
WT_RET_MSG(
|
||||
session, EEXIST, "Table exists: %s", tablename);
|
||||
if (exclusive)
|
||||
ret = EEXIST;
|
||||
return (0);
|
||||
}
|
||||
if (ret != WT_NOTFOUND)
|
||||
@@ -329,7 +351,7 @@ __create_table(WT_SESSION_IMPL *session, const char *name, const char *config)
|
||||
cgsize = strlen("colgroup:") + strlen(tablename) + 1;
|
||||
WT_ERR(__wt_calloc_def(session, cgsize, &cgname));
|
||||
snprintf(cgname, cgsize, "colgroup:%s", tablename);
|
||||
WT_ERR(__create_colgroup(session, cgname, config));
|
||||
WT_ERR(__create_colgroup(session, cgname, exclusive, config));
|
||||
}
|
||||
|
||||
if (0) {
|
||||
@@ -345,12 +367,16 @@ int
|
||||
__wt_schema_create(
|
||||
WT_SESSION_IMPL *session, const char *name, const char *config)
|
||||
{
|
||||
|
||||
int ret;
|
||||
WT_CONFIG_ITEM cval;
|
||||
int exclusive, ret;
|
||||
|
||||
/* Disallow objects in the WiredTiger name space. */
|
||||
WT_RET(__wt_schema_name_check(session, name));
|
||||
|
||||
exclusive = (
|
||||
__wt_config_getones(session, config, "exclusive", &cval) == 0 &&
|
||||
cval.val != 0);
|
||||
|
||||
/*
|
||||
* We track rename operations, if we fail in the middle, we want to
|
||||
* back it all out.
|
||||
@@ -358,13 +384,13 @@ __wt_schema_create(
|
||||
WT_RET(__wt_schema_table_track_on(session));
|
||||
|
||||
if (WT_PREFIX_MATCH(name, "colgroup:"))
|
||||
ret = __create_colgroup(session, name, config);
|
||||
ret = __create_colgroup(session, name, exclusive, config);
|
||||
else if (WT_PREFIX_MATCH(name, "file:"))
|
||||
ret = __wt_create_file(session, name, name, config);
|
||||
ret = __wt_create_file(session, name, name, exclusive, config);
|
||||
else if (WT_PREFIX_MATCH(name, "index:"))
|
||||
ret = __create_index(session, name, config);
|
||||
ret = __create_index(session, name, exclusive, config);
|
||||
else if (WT_PREFIX_MATCH(name, "table:"))
|
||||
ret = __create_table(session, name, config);
|
||||
ret = __create_table(session, name, exclusive, config);
|
||||
else
|
||||
ret = __wt_unknown_object_type(session, name);
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ __open_schema_table(WT_SESSION_IMPL *session)
|
||||
__wt_schema_table_track_off(session, 0);
|
||||
WT_ERR(__wt_create_file(session,
|
||||
"file:" WT_SCHEMA_FILENAME,
|
||||
"file:" WT_SCHEMA_FILENAME, schemaconf));
|
||||
"file:" WT_SCHEMA_FILENAME, 0, schemaconf));
|
||||
session->schematab = session->btree;
|
||||
err: __wt_free(session, schemaconf);
|
||||
if (tracking)
|
||||
@@ -56,7 +56,7 @@ __wt_schema_table_cursor(
|
||||
|
||||
WT_RET(__open_schema_table(session));
|
||||
session->btree = session->schematab;
|
||||
return (__wt_curfile_create(session, cfg, cursorp));
|
||||
return (__wt_curfile_create(session, NULL, cfg, cursorp));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -26,15 +26,7 @@ __session_close(WT_SESSION *wt_session, const char *config)
|
||||
SESSION_API_CALL(session, close, config, cfg);
|
||||
WT_UNUSED(cfg);
|
||||
|
||||
/*
|
||||
* We first close all public cursors, then all remaining file cursors.
|
||||
* File cursors are special because the btree code looks inside them
|
||||
* to work out whether pages are in use.
|
||||
*/
|
||||
while ((cursor = TAILQ_FIRST(&session->public_cursors)) != NULL)
|
||||
WT_TRET(cursor->close(cursor));
|
||||
|
||||
while ((cursor = TAILQ_FIRST(&session->file_cursors)) != NULL)
|
||||
while ((cursor = TAILQ_FIRST(&session->cursors)) != NULL)
|
||||
WT_TRET(cursor->close(cursor));
|
||||
|
||||
while ((btree_session = TAILQ_FIRST(&session->btrees)) != NULL)
|
||||
@@ -476,8 +468,7 @@ __wt_open_session(WT_CONNECTION_IMPL *conn, int internal,
|
||||
session_ret->event_handler = session->event_handler;
|
||||
session_ret->hazard = conn->hazard + slot * conn->hazard_size;
|
||||
|
||||
TAILQ_INIT(&session_ret->file_cursors);
|
||||
TAILQ_INIT(&session_ret->public_cursors);
|
||||
TAILQ_INIT(&session_ret->cursors);
|
||||
TAILQ_INIT(&session_ret->btrees);
|
||||
if (event_handler != NULL)
|
||||
session_ret->event_handler = event_handler;
|
||||
|
||||
@@ -28,7 +28,6 @@ int
|
||||
__wt_btree_get_root(WT_SESSION_IMPL *session, WT_ITEM *addr)
|
||||
{
|
||||
WT_BTREE *btree;
|
||||
uint32_t size;
|
||||
int majorv, minorv, ret;
|
||||
const char *v;
|
||||
|
||||
@@ -59,10 +58,8 @@ __wt_btree_get_root(WT_SESSION_IMPL *session, WT_ITEM *addr)
|
||||
"%s is an unsupported version of a WiredTiger file",
|
||||
btree->filename);
|
||||
|
||||
if (v != NULL && strlen(v) != 0 && strcmp(v, WT_NOADDR) != 0) {
|
||||
WT_ERR(__wt_hex_to_raw(session, (void *)v, (void *)v, &size));
|
||||
WT_ERR(__wt_buf_set(session, addr, v, size));
|
||||
}
|
||||
if (v != NULL && strlen(v) != 0 && strcmp(v, WT_NOADDR) != 0)
|
||||
WT_ERR(__wt_hex_to_raw(session, v, addr));
|
||||
|
||||
err: if (ret != 0)
|
||||
__wt_errx(session,
|
||||
@@ -108,7 +105,7 @@ err: __wt_scr_free(&addr);
|
||||
*/
|
||||
int
|
||||
__wt_btree_set_root(WT_SESSION_IMPL *session,
|
||||
const char *filename, uint8_t *addr, uint32_t size)
|
||||
const char *filename, const uint8_t *addr, uint32_t size)
|
||||
{
|
||||
WT_ITEM *v;
|
||||
int ret;
|
||||
@@ -118,7 +115,7 @@ __wt_btree_set_root(WT_SESSION_IMPL *session,
|
||||
|
||||
/*
|
||||
* Every bytes is encoded as 2 bytes, plus a trailing nul byte,
|
||||
* and it needs to hold the [NoAddr] string.
|
||||
* and it needs to hold the "no address" string.
|
||||
*/
|
||||
WT_RET(__wt_scr_alloc(
|
||||
session, size * 2 + 1 + WT_STORE_SIZE(strlen(WT_NOADDR)), &v));
|
||||
@@ -133,11 +130,8 @@ __wt_btree_set_root(WT_SESSION_IMPL *session,
|
||||
if (addr == NULL) {
|
||||
v->data = WT_NOADDR;
|
||||
v->size = WT_STORE_SIZE(strlen(WT_NOADDR)) + 1;
|
||||
} else {
|
||||
__wt_raw_to_hex(addr, v->mem, &size);
|
||||
v->data = v->mem;
|
||||
v->size = size;
|
||||
}
|
||||
} else
|
||||
WT_ERR(__wt_raw_to_hex(session, addr, size, v));
|
||||
|
||||
WT_ERR(strcmp(filename, WT_SCHEMA_FILENAME) == 0 ?
|
||||
__btree_set_turtle(session, v) :
|
||||
|
||||
@@ -7,44 +7,59 @@
|
||||
|
||||
#include "wt_internal.h"
|
||||
|
||||
static const u_char hex[] = "0123456789abcdef";
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
|
||||
/*
|
||||
* __wt_raw_to_hex --
|
||||
* Convert a chunk of data to a printable hex string.
|
||||
*/
|
||||
void
|
||||
__wt_raw_to_hex(const void *from, void *to, uint32_t *sizep)
|
||||
int
|
||||
__wt_raw_to_hex(WT_SESSION_IMPL *session,
|
||||
const uint8_t *from, uint32_t size, WT_ITEM *to)
|
||||
{
|
||||
uint32_t i;
|
||||
const uint8_t *p;
|
||||
uint8_t *t, *t_start;
|
||||
char *t;
|
||||
|
||||
for (p = from, t = t_start = to, i = *sizep; i > 0; --i, ++p) {
|
||||
/*
|
||||
* In the worst case, every character takes up 2 spaces, plus a
|
||||
* trailing nul byte.
|
||||
*/
|
||||
WT_RET(__wt_buf_init(session, to, size * 2 + 1));
|
||||
|
||||
for (p = from, t = to->mem, i = size; i > 0; --i, ++p) {
|
||||
*t++ = hex[(*p & 0xf0) >> 4];
|
||||
*t++ = hex[*p & 0x0f];
|
||||
}
|
||||
*t++ = '\0';
|
||||
*sizep = WT_PTRDIFF32(t, t_start);
|
||||
to->size = WT_PTRDIFF32(t, to->mem);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __wt_raw_to_esc_hex --
|
||||
* Convert a chunk of data to an printable string using escaped hex as
|
||||
* necessary.
|
||||
* necessary.
|
||||
*/
|
||||
void
|
||||
__wt_raw_to_esc_hex(const void *from, void *to, uint32_t *sizep)
|
||||
int
|
||||
__wt_raw_to_esc_hex(WT_SESSION_IMPL *session,
|
||||
const uint8_t *from, size_t size, WT_ITEM *to)
|
||||
{
|
||||
uint32_t i;
|
||||
size_t i;
|
||||
const uint8_t *p;
|
||||
uint8_t *t, *t_start;
|
||||
uint8_t *t;
|
||||
|
||||
/*
|
||||
* In the worst case, every character takes up 3 spaces, plus a
|
||||
* trailing nul byte.
|
||||
*/
|
||||
for (p = from, t = t_start = to, i = *sizep; i > 0; --i, ++p)
|
||||
WT_RET(__wt_buf_init(session, to, size * 3 + 1));
|
||||
|
||||
/*
|
||||
* In the worst case, every character takes up 3 spaces, plus a
|
||||
* trailing nul byte.
|
||||
*/
|
||||
for (p = from, t = to->mem, i = size; i > 0; --i, ++p)
|
||||
if (isprint((int)*p)) {
|
||||
if (*p == '\\')
|
||||
*t++ = '\\';
|
||||
@@ -55,7 +70,8 @@ __wt_raw_to_esc_hex(const void *from, void *to, uint32_t *sizep)
|
||||
*t++ = hex[*p & 0x0f];
|
||||
}
|
||||
*t++ = '\0';
|
||||
*sizep = WT_PTRDIFF32(t, t_start);
|
||||
to->size = WT_PTRDIFF32(t, to->mem);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -63,7 +79,7 @@ __wt_raw_to_esc_hex(const void *from, void *to, uint32_t *sizep)
|
||||
* Convert a pair of hex characters into a byte.
|
||||
*/
|
||||
static inline int
|
||||
hex2byte(uint8_t *from, uint8_t *to)
|
||||
hex2byte(const char *from, uint8_t *to)
|
||||
{
|
||||
uint8_t byte;
|
||||
|
||||
@@ -123,34 +139,40 @@ __hex_fmterr(WT_SESSION_IMPL *session)
|
||||
* Convert a printable hex string to a chunk of data.
|
||||
*/
|
||||
int
|
||||
__wt_hex_to_raw(
|
||||
WT_SESSION_IMPL *session, void *from, void *to, uint32_t *sizep)
|
||||
__wt_hex_to_raw(WT_SESSION_IMPL *session, const char *from, WT_ITEM *to)
|
||||
{
|
||||
uint8_t *p, *t, *t_start;
|
||||
const char *p;
|
||||
uint8_t *t;
|
||||
size_t size;
|
||||
|
||||
if (strlen(from) % 2 != 0)
|
||||
size = strlen(from);
|
||||
if (size % 2 != 0)
|
||||
return (__hex_fmterr(session));
|
||||
|
||||
for (p = from, t = t_start = to; *p != '\0'; p += 2, ++t)
|
||||
WT_RET(__wt_buf_init(session, to, size / 2));
|
||||
|
||||
for (p = from, t = to->mem; *p != '\0'; p += 2, ++t)
|
||||
if (hex2byte(p, t))
|
||||
return (__hex_fmterr(session));
|
||||
|
||||
*sizep = WT_PTRDIFF32(t, t_start);
|
||||
to->size = WT_PTRDIFF32(t, to->mem);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __wt_esc_hex_to_raw --
|
||||
* Convert a printable string using escaped hex as necessary to a chunk
|
||||
* of data.
|
||||
* of data.
|
||||
*/
|
||||
int
|
||||
__wt_esc_hex_to_raw(
|
||||
WT_SESSION_IMPL *session, void *from, void *to, uint32_t *sizep)
|
||||
__wt_esc_hex_to_raw(WT_SESSION_IMPL *session, const char *from, WT_ITEM *to)
|
||||
{
|
||||
uint8_t *p, *t, *t_start;
|
||||
const char *p;
|
||||
uint8_t *t;
|
||||
|
||||
for (p = from, t = t_start = to; *p != '\0'; ++p, ++t) {
|
||||
WT_RET(__wt_buf_init(session, to, strlen(from)));
|
||||
|
||||
for (p = from, t = to->mem; *p != '\0'; ++p, ++t) {
|
||||
if ((*t = *p) != '\\')
|
||||
continue;
|
||||
++p;
|
||||
@@ -160,6 +182,6 @@ __wt_esc_hex_to_raw(
|
||||
++p;
|
||||
}
|
||||
}
|
||||
*sizep = WT_PTRDIFF32(t, t_start);
|
||||
to->size = WT_PTRDIFF32(t, to->mem);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -120,19 +120,7 @@ int
|
||||
__wt_buf_set_printable(
|
||||
WT_SESSION_IMPL *session, WT_ITEM *buf, const void *from_arg, size_t size)
|
||||
{
|
||||
uint32_t u32size;
|
||||
|
||||
/*
|
||||
* In the worst case, every character takes up 3 spaces, plus a
|
||||
* trailing nul byte.
|
||||
*/
|
||||
WT_RET(__wt_buf_init(session, buf, size * 3 + 10));
|
||||
|
||||
u32size = (uint32_t)size;
|
||||
__wt_raw_to_esc_hex(from_arg, buf->mem, &u32size);
|
||||
buf->size = u32size;
|
||||
|
||||
return (0);
|
||||
return (__wt_raw_to_esc_hex(session, from_arg, size, buf));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -177,20 +165,6 @@ __wt_buf_steal(WT_SESSION_IMPL *session, WT_ITEM *buf, uint32_t *sizep)
|
||||
return (retp);
|
||||
}
|
||||
|
||||
/*
|
||||
* __wt_buf_swap --
|
||||
* Swap a pair of buffers.
|
||||
*/
|
||||
void
|
||||
__wt_buf_swap(WT_ITEM *a, WT_ITEM *b)
|
||||
{
|
||||
WT_ITEM tmp;
|
||||
|
||||
tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* __wt_buf_free --
|
||||
* Free a buffer.
|
||||
@@ -382,9 +356,11 @@ __wt_scr_discard(WT_SESSION_IMPL *session)
|
||||
bufp = session->scratch; i < session->scratch_alloc; ++i, ++bufp) {
|
||||
if (*bufp == NULL)
|
||||
continue;
|
||||
#if 0
|
||||
if (F_ISSET(*bufp, WT_ITEM_INUSE))
|
||||
__wt_errx(session,
|
||||
"scratch buffer allocated and never discarded");
|
||||
#endif
|
||||
__wt_buf_free(session, *bufp);
|
||||
__wt_free(session, *bufp);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ __wt_session_dump(WT_SESSION_IMPL *session)
|
||||
session->name == NULL ? "" : " ", session);
|
||||
|
||||
first = 0;
|
||||
TAILQ_FOREACH(cursor, &session->file_cursors, q) {
|
||||
TAILQ_FOREACH(cursor, &session->cursors, q) {
|
||||
if (++first == 1)
|
||||
__wt_msg(session, "\tcursors:");
|
||||
__wt_msg(session, "\t\t%p", cursor);
|
||||
|
||||
@@ -102,7 +102,7 @@ usage(void)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: %s %s "
|
||||
"read [-ao] uri key ...\n",
|
||||
"write [-ao] uri key ...\n",
|
||||
progname, usage_prefix);
|
||||
return (1);
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
%module config
|
||||
|
||||
%{
|
||||
#include <wt_internal.h>
|
||||
%}
|
||||
|
||||
typedef struct WT_CONFIG WT_CONFIG;
|
||||
typedef struct WT_CONFIG_ITEM WT_CONFIG_ITEM;
|
||||
|
||||
struct WT_CONFIG
|
||||
{
|
||||
char *orig;
|
||||
char *end;
|
||||
char *cur;
|
||||
|
||||
int depth, top;
|
||||
void **go;
|
||||
};
|
||||
|
||||
struct WT_CONFIG_ITEM
|
||||
{
|
||||
char *str;
|
||||
size_t len;
|
||||
uint64_t val;
|
||||
enum { ITEM_STRING, ITEM_ID, ITEM_NUM, ITEM_STRUCT } type;
|
||||
};
|
||||
|
||||
/*
|
||||
* XXX: leak, but the string needs to last beyond the call to config_init.
|
||||
* It should be freed when the WT_CONFIG object is deleted.
|
||||
*/
|
||||
%typemap(in) char *confstr {
|
||||
$1 = strdup(PyString_AsString($input));
|
||||
}
|
||||
|
||||
int config_init(WT_CONFIG *conf, char *confstr, int len);
|
||||
int config_next(WT_CONFIG *conf, WT_CONFIG_ITEM *key, WT_CONFIG_ITEM *value);
|
||||
@@ -1,21 +0,0 @@
|
||||
#include <wt_int.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
WT_CONFIG c;
|
||||
WT_CONFIG_ITEM k, v;
|
||||
const char *cstr = "create,cachesize=10MB";
|
||||
|
||||
config_init(&c, cstr, strlen(cstr));
|
||||
while ((ret = config_next(&c, &k, &v)) == 0) {
|
||||
printf("Got key '%.*s', value '%.*s'\n",
|
||||
(int)k.len, k.str, (int)v.len, v.str);
|
||||
}
|
||||
|
||||
printf("Last call to config_next failed with %d\n", ret);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
import config
|
||||
|
||||
def parse(s):
|
||||
print "Parsing '%s':" % s
|
||||
|
||||
c = config.WT_CONFIG()
|
||||
k = config.WT_CONFIG_ITEM()
|
||||
v = config.WT_CONFIG_ITEM()
|
||||
|
||||
config.config_init(c, s, len(s))
|
||||
ret = config.config_next(c, k, v)
|
||||
while ret == 0:
|
||||
print " => '%s' = '%s'" % (k.str[:k.len], v.str[:v.len])
|
||||
ret = config.config_next(c, k, v)
|
||||
|
||||
# XXX hard-coding WT_NOTFOUND until we fix this
|
||||
if ret != -31801:
|
||||
print "Last call to config_next failed with %d" % ret
|
||||
|
||||
if __name__ == '__main__':
|
||||
parse("create")
|
||||
parse("create,cachesize=10MB")
|
||||
parse('create,cachesize=10MB,path="/foo/bar"')
|
||||
parse('columns=(first,second, third)')
|
||||
parse('key_format="S", value_format="5sq", columns=(first,second, third)')
|
||||
parse('key_columns=(first=S),value_columns=(second="5s", third=q)')
|
||||
parse(',,columns=(first=S,second="5s", third=q),,')
|
||||
parse('index.country_year=(country,year),key_format=r,colgroup.population=(population),columns=(id,country,year,population),value_format=5sHQ')
|
||||
|
||||
import json
|
||||
parse(json.dumps({'hello' : 'world', 'columns' : ('one', 'two', 'three')}))
|
||||
|
||||
parse(json.dumps({
|
||||
"key_format" : "r",
|
||||
"value_format" : "5sHQ",
|
||||
"columns" : ("id", "country", "year", "population"),
|
||||
"colgroup.population" : ("population",),
|
||||
"index.country_year" : ("country","year")
|
||||
}))
|
||||
@@ -59,9 +59,18 @@ config_setup(void)
|
||||
*cp->v = CONF_RAND(cp);
|
||||
}
|
||||
|
||||
/* Periodically, set the delete percentage to 0 so salvage gets run. */
|
||||
if (!g.replay && g.run_cnt % 10 == 0)
|
||||
g.c_delete_pct = 0;
|
||||
/*
|
||||
* Periodically, set the delete percentage to 0 so salvage gets run,
|
||||
* as long as the delete percentage isn't nailed down.
|
||||
*/
|
||||
if (!g.replay && g.run_cnt % 10 == 0) {
|
||||
for (cp = c; cp->name != NULL; ++cp)
|
||||
if (strcmp(cp->name, "delete_pct") == 0)
|
||||
break;
|
||||
if (cp->name != NULL &&
|
||||
!(cp->flags & (C_IGNORE | C_PERM | C_TEMP)))
|
||||
g.c_delete_pct = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -70,7 +70,7 @@ class test_schema02(wttest.WiredTigerTestCase):
|
||||
# bad table name
|
||||
self.expect_failure_colgroup("nomatch:c", "columns=(S1,i2)",
|
||||
"/Can't create 'colgroup:nomatch:c'"
|
||||
" for non-existent table nomatch/")
|
||||
" for non-existent table 'nomatch'/")
|
||||
# colgroup not declared in initial create
|
||||
self.expect_failure_colgroup("main:nomatch", "columns=(S1,i2)",
|
||||
"/Column group 'nomatch' not found"
|
||||
|
||||
Reference in New Issue
Block a user