summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/ext
diff options
context:
space:
mode:
authorLuke Chen <luke.chen@mongodb.com>2019-07-05 12:27:29 +1000
committerLuke Chen <luke.chen@mongodb.com>2019-07-05 12:27:29 +1000
commitdaceefe370a71036df6e1ecb209e966d29bc2871 (patch)
tree93d837763bfeb38e8c59bc665742dce99d242e31 /src/third_party/wiredtiger/ext
parent7d88bdb226e8a3dc9b5eb4b57edcca111619c5f9 (diff)
downloadmongo-daceefe370a71036df6e1ecb209e966d29bc2871.tar.gz
Import wiredtiger: b50d65e8560446e2cd205594e07bbcaa2305b144 from branch mongodb-4.2
ref: d86b3a8a33..b50d65e856 for: 4.3.1 WT-4502 Assertion checking hazard pointers on page discard is too strong WT-4733 Change test/format to do longer-term repeatable read testing WT-4743 Fix memory leaks and core dumps in page-split error handling WT-4786 Coverity: Invalid format specifiers in printf-like invocations WT-4805 Modify error message verification for test_prepare04.py WT-4812 Fix the Python distribution script for Python3 changes WT-4818 Add debugging of bad read file descriptor when files are missing during recovery WT-4840 WT_CURSOR.modify must require explicit, snapshot-isolation transaction WT-4864 Coverity: Redundant NULL check WT-4866 Coverity: WT_SESSION.import can leak memory WT-4867 Skip assertion when reserved updates are seen WT-4882 Improve checkpoint performance when there are large metadata pages WT-4887 Skip read timestamp required assert during recovery WT-4888 Remove support for Berkeley DB WT-4891 WT_SESSION.verify memory allocation overrun WT-4895 Fix debug eviction mode so it chooses skew more randomly WT-4910 Port Windows SConstruct to Python 3
Diffstat (limited to 'src/third_party/wiredtiger/ext')
-rw-r--r--src/third_party/wiredtiger/ext/test/kvs_bdb/Makefile.am11
-rw-r--r--src/third_party/wiredtiger/ext/test/kvs_bdb/kvs_bdb.c1107
2 files changed, 0 insertions, 1118 deletions
diff --git a/src/third_party/wiredtiger/ext/test/kvs_bdb/Makefile.am b/src/third_party/wiredtiger/ext/test/kvs_bdb/Makefile.am
deleted file mode 100644
index c7d0f580085..00000000000
--- a/src/third_party/wiredtiger/ext/test/kvs_bdb/Makefile.am
+++ /dev/null
@@ -1,11 +0,0 @@
-AM_CPPFLAGS = -I$(top_builddir) \
- -I$(top_srcdir)/src/include -I$(BERKELEY_DB_PATH)/include
-
-noinst_LTLIBRARIES = libwiredtiger_kvs_bdb.la
-libwiredtiger_kvs_bdb_la_SOURCES = kvs_bdb.c
-libwiredtiger_kvs_bdb_la_LIBADD = -L$(BERKELEY_DB_PATH)/lib -ldb
-
-# 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_kvs_bdb_la_LDFLAGS = -avoid-version -module -rpath /nowhere
diff --git a/src/third_party/wiredtiger/ext/test/kvs_bdb/kvs_bdb.c b/src/third_party/wiredtiger/ext/test/kvs_bdb/kvs_bdb.c
deleted file mode 100644
index d0c176551f4..00000000000
--- a/src/third_party/wiredtiger/ext/test/kvs_bdb/kvs_bdb.c
+++ /dev/null
@@ -1,1107 +0,0 @@
-/*-
- * Public Domain 2014-2019 MongoDB, Inc.
- * Public Domain 2008-2014 WiredTiger, Inc.
- *
- * This is free and unencumbered software released into the public domain.
- *
- * Anyone is free to copy, modify, publish, use, compile, sell, or
- * distribute this software, either in source code form or as a compiled
- * binary, for any purpose, commercial or non-commercial, and by any
- * means.
- *
- * In jurisdictions that recognize copyright laws, the author or authors
- * of this software dedicate any and all copyright interest in the
- * software to the public domain. We make this dedication for the benefit
- * of the public at large and to the detriment of our heirs and
- * successors. We intend this dedication to be an overt act of
- * relinquishment in perpetuity of all present and future rights to this
- * software under copyright law.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/*
- * Berkeley DB has an #ifdef we need to provide a value for, we'll see an
- * undefined error if it's unset during a strict compile.
- */
-#ifndef DB_DBM_HSEARCH
-#define DB_DBM_HSEARCH 0
-#endif
-#include <db.h>
-#include <wiredtiger.h>
-#include <wiredtiger_ext.h>
-
-#undef INLINE
-#define INLINE inline /* Turn off inline */
-
-#ifndef UINT32_MAX /* Maximum 32-bit unsigned */
-#define UINT32_MAX 4294967295U
-#endif
-
-/*
- * Macros to output an error message and set or return an error.
- * Requires local variables:
- * int ret;
- */
-#undef ERET
-#define ERET(wt_api, session, v, ...) do { \
- (void)wt_api->err_printf(wt_api, session, __VA_ARGS__); \
- return (v); \
-} while (0)
-#undef ESET
-#define ESET(wt_api, session, v, ...) do { \
- (void)wt_api->err_printf(wt_api, session, __VA_ARGS__); \
- ret = v; \
-} while (0)
-#undef ETRET
-#define ETRET(a) do { \
- int __ret; \
- if ((__ret = (a)) != 0 && \
- (__ret == WT_PANIC || \
- ret == 0 || ret == WT_DUPLICATE_KEY || ret == WT_NOTFOUND)) \
- ret = __ret; \
-} while (0)
-
-typedef struct __data_source DATA_SOURCE;
-
-typedef struct __cursor_source {
- WT_CURSOR wtcursor; /* Must come first */
-
- WT_EXTENSION_API *wt_api; /* Extension functions */
-
- DATA_SOURCE *ds; /* Underlying Berkeley DB */
-
- DB *db; /* Berkeley DB handles */
- DBC *dbc;
- DBT key, value;
- db_recno_t recno;
-
- int config_append; /* config "append" */
- int config_bitfield; /* config "value_format=#t" */
- int config_overwrite; /* config "overwrite" */
- int config_recno; /* config "key_format=r" */
-} CURSOR_SOURCE;
-
-struct __data_source {
- WT_DATA_SOURCE wtds; /* Must come first */
-
- WT_EXTENSION_API *wt_api; /* Extension functions */
-
- /*
- * We single thread all WT_SESSION methods and return EBUSY if a
- * WT_SESSION method is called and there's an open cursor.
- *
- * XXX
- * This only works for a single object: if there were more than one
- * object in test/format, cursor open would use the passed-in uri to
- * find a { lock, cursor-count } pair to reference from each cursor
- * object, and each session.XXX method call would have to use the
- * appropriate { lock, cursor-count } pair based on their passed-in
- * uri.
- */
- pthread_rwlock_t rwlock; /* Global lock */
-
- DB_ENV *dbenv; /* Berkeley DB environment */
- int open_cursors; /* Open cursor count */
-};
-
-/*
- * os_errno --
- * Limit our use of errno so it's easy to remove.
- */
-static int
-os_errno(void)
-{
- return (errno);
-}
-
-/*
- * lock_init --
- * Initialize an object's lock.
- */
-static int
-lock_init(
- WT_EXTENSION_API *wt_api, WT_SESSION *session, pthread_rwlock_t *lockp)
-{
- int ret = 0;
-
- if ((ret = pthread_rwlock_init(lockp, NULL)) != 0)
- ERET(wt_api, session, WT_PANIC, "lock init: %s", strerror(ret));
- return (0);
-}
-
-/*
- * lock_destroy --
- * Destroy an object's lock.
- */
-static int
-lock_destroy(
- WT_EXTENSION_API *wt_api, WT_SESSION *session, pthread_rwlock_t *lockp)
-{
- int ret = 0;
-
- if ((ret = pthread_rwlock_destroy(lockp)) != 0)
- ERET(wt_api,
- session, WT_PANIC, "lock destroy: %s", strerror(ret));
- return (0);
-}
-
-/*
- * writelock --
- * Acquire a write lock.
- */
-static INLINE int
-writelock(
- WT_EXTENSION_API *wt_api, WT_SESSION *session, pthread_rwlock_t *lockp)
-{
- int ret = 0;
-
- if ((ret = pthread_rwlock_wrlock(lockp)) != 0)
- ERET(wt_api,
- session, WT_PANIC, "write-lock: %s", strerror(ret));
- return (0);
-}
-
-/*
- * unlock --
- * Release an object's lock.
- */
-static INLINE int
-unlock(WT_EXTENSION_API *wt_api, WT_SESSION *session, pthread_rwlock_t *lockp)
-{
- int ret = 0;
-
- if ((ret = pthread_rwlock_unlock(lockp)) != 0)
- ERET(wt_api, session, WT_PANIC, "unlock: %s", strerror(ret));
- return (0);
-}
-
-static int
-single_thread(
- WT_DATA_SOURCE *wtds, WT_SESSION *session, pthread_rwlock_t *lockp)
-{
- DATA_SOURCE *ds;
- WT_EXTENSION_API *wt_api;
- int ret = 0;
-
- ds = (DATA_SOURCE *)wtds;
- wt_api = ds->wt_api;
-
- if ((ret = writelock(wt_api, session, lockp)) != 0)
- return (ret);
- if (ds->open_cursors != 0) {
- if ((ret = unlock(wt_api, session, lockp)) != 0)
- return (ret);
- return (EBUSY);
- }
- return (0);
-}
-
-static int
-uri2name(WT_EXTENSION_API *wt_api,
- WT_SESSION *session, const char *uri, const char **namep)
-{
- const char *name;
-
- if ((name = strchr(uri, ':')) == NULL || *++name == '\0')
- ERET(wt_api, session, EINVAL, "unsupported object: %s", uri);
- *namep = name;
- return (0);
-}
-
-static INLINE int
-recno_convert(WT_CURSOR *wtcursor, db_recno_t *recnop)
-{
- CURSOR_SOURCE *cursor;
- WT_EXTENSION_API *wt_api;
- WT_SESSION *session;
-
- session = wtcursor->session;
- cursor = (CURSOR_SOURCE *)wtcursor;
- wt_api = cursor->wt_api;
-
- if (wtcursor->recno > UINT32_MAX)
- ERET(wt_api,
- session, ERANGE, "record number %" PRIuMAX ": %s",
- (uintmax_t)wtcursor->recno, strerror(ERANGE));
-
- *recnop = (uint32_t)wtcursor->recno;
- return (0);
-}
-
-static INLINE int
-copyin_key(WT_CURSOR *wtcursor)
-{
- CURSOR_SOURCE *cursor;
- DBT *key;
- int ret = 0;
-
- cursor = (CURSOR_SOURCE *)wtcursor;
- key = &cursor->key;
-
- if (cursor->config_recno) {
- if ((ret = recno_convert(wtcursor, &cursor->recno)) != 0)
- return (ret);
- key->data = &cursor->recno;
- key->size = sizeof(db_recno_t);
- } else {
- key->data = (char *)wtcursor->key.data;
- key->size = (uint32_t)wtcursor->key.size;
- }
- return (0);
-}
-
-static INLINE void
-copyout_key(WT_CURSOR *wtcursor)
-{
- CURSOR_SOURCE *cursor;
- DBT *key;
-
- cursor = (CURSOR_SOURCE *)wtcursor;
- key = &cursor->key;
-
- if (cursor->config_recno)
- wtcursor->recno = *(db_recno_t *)key->data;
- else {
- wtcursor->key.data = key->data;
- wtcursor->key.size = key->size;
- }
-}
-
-static INLINE void
-copyin_value(WT_CURSOR *wtcursor)
-{
- CURSOR_SOURCE *cursor;
- DBT *value;
-
- cursor = (CURSOR_SOURCE *)wtcursor;
- value = &cursor->value;
-
- value->data = (char *)wtcursor->value.data;
- value->size = (uint32_t)wtcursor->value.size;
-}
-
-static INLINE void
-copyout_value(WT_CURSOR *wtcursor)
-{
- CURSOR_SOURCE *cursor;
- DBT *value;
-
- cursor = (CURSOR_SOURCE *)wtcursor;
- value = &cursor->value;
-
- wtcursor->value.data = value->data;
- wtcursor->value.size = value->size;
-}
-
-#if 0
-static int
-bdb_dump(WT_CURSOR *wtcursor, WT_SESSION *session, const char *tag)
-{
- CURSOR_SOURCE *cursor;
- DB *db;
- DBC *dbc;
- DBT *key, *value;
- WT_EXTENSION_API *wt_api;
- int ret = 0;
-
- cursor = (CURSOR_SOURCE *)wtcursor;
- wt_api = cursor->wt_api;
-
- db = cursor->db;
- key = &cursor->key;
- value = &cursor->value;
-
- if ((ret = db->cursor(db, NULL, &dbc, 0)) != 0)
- ERET(wt_api,
- session, WT_ERROR, "Db.cursor: %s", db_strerror(ret));
- printf("==> %s\n", tag);
- while ((ret = dbc->get(dbc, key, value, DB_NEXT)) == 0)
- if (cursor->config_recno)
- printf("\t%llu/%.*s\n",
- (unsigned long long)*(db_recno_t *)key->data,
- (int)value->size, (char *)value->data);
- else
- printf("\t%.*s/%.*s\n",
- (int)key->size, (char *)key->data,
- (int)value->size, (char *)value->data);
-
- if (ret != DB_NOTFOUND)
- ERET(wt_api,
- session, WT_ERROR, "DbCursor.get: %s", db_strerror(ret));
-
- return (0);
-}
-#endif
-
-static int
-kvs_cursor_next(WT_CURSOR *wtcursor)
-{
- CURSOR_SOURCE *cursor;
- DBC *dbc;
- DBT *key, *value;
- WT_EXTENSION_API *wt_api;
- WT_SESSION *session;
- int ret = 0;
-
- session = wtcursor->session;
- cursor = (CURSOR_SOURCE *)wtcursor;
- wt_api = cursor->wt_api;
-
- dbc = cursor->dbc;
- key = &cursor->key;
- value = &cursor->value;
-
- if ((ret = dbc->get(dbc, key, value, DB_NEXT)) == 0) {
- copyout_key(wtcursor);
- copyout_value(wtcursor);
- return (0);
- }
-
- if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY)
- return (WT_NOTFOUND);
- ERET(wt_api, session, WT_ERROR, "DbCursor.get: %s", db_strerror(ret));
-}
-
-static int
-kvs_cursor_prev(WT_CURSOR *wtcursor)
-{
- CURSOR_SOURCE *cursor;
- DBC *dbc;
- DBT *key, *value;
- WT_EXTENSION_API *wt_api;
- WT_SESSION *session;
- int ret = 0;
-
- session = wtcursor->session;
- cursor = (CURSOR_SOURCE *)wtcursor;
- wt_api = cursor->wt_api;
-
- dbc = cursor->dbc;
- key = &cursor->key;
- value = &cursor->value;
-
- if ((ret = dbc->get(dbc, key, value, DB_PREV)) == 0) {
- copyout_key(wtcursor);
- copyout_value(wtcursor);
- return (0);
- }
-
- if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY)
- return (WT_NOTFOUND);
- ERET(wt_api, session, WT_ERROR, "DbCursor.get: %s", db_strerror(ret));
-}
-
-static int
-kvs_cursor_reset(WT_CURSOR *wtcursor)
-{
- CURSOR_SOURCE *cursor;
- DBC *dbc;
- WT_EXTENSION_API *wt_api;
- WT_SESSION *session;
- int ret = 0;
-
- session = wtcursor->session;
- cursor = (CURSOR_SOURCE *)wtcursor;
- wt_api = cursor->wt_api;
-
- /* Close and re-open the Berkeley DB cursor */
- if ((dbc = cursor->dbc) != NULL) {
- cursor->dbc = NULL;
- if ((ret = dbc->close(dbc)) != 0)
- ERET(wt_api, session, WT_ERROR,
- "DbCursor.close: %s", db_strerror(ret));
-
- if ((ret = cursor->db->cursor(cursor->db, NULL, &dbc, 0)) != 0)
- ERET(wt_api, session, WT_ERROR,
- "Db.cursor: %s", db_strerror(ret));
- cursor->dbc = dbc;
- }
- return (0);
-}
-
-static int
-kvs_cursor_search(WT_CURSOR *wtcursor)
-{
- CURSOR_SOURCE *cursor;
- DBC *dbc;
- DBT *key, *value;
- WT_EXTENSION_API *wt_api;
- WT_SESSION *session;
- int ret = 0;
-
- session = wtcursor->session;
- cursor = (CURSOR_SOURCE *)wtcursor;
- wt_api = cursor->wt_api;
-
- dbc = cursor->dbc;
- key = &cursor->key;
- value = &cursor->value;
-
- if ((ret = copyin_key(wtcursor)) != 0)
- return (ret);
-
- if ((ret = dbc->get(dbc, key, value, DB_SET)) == 0) {
- copyout_key(wtcursor);
- copyout_value(wtcursor);
- return (0);
- }
-
- if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY)
- return (WT_NOTFOUND);
- ERET(wt_api, session, WT_ERROR, "DbCursor.get: %s", db_strerror(ret));
-}
-
-static int
-kvs_cursor_search_near(WT_CURSOR *wtcursor, int *exact)
-{
- CURSOR_SOURCE *cursor;
- DBC *dbc;
- DBT *key, *value;
- WT_EXTENSION_API *wt_api;
- WT_SESSION *session;
- size_t len;
- int ret = 0;
-
- session = wtcursor->session;
- cursor = (CURSOR_SOURCE *)wtcursor;
- wt_api = cursor->wt_api;
-
- dbc = cursor->dbc;
- key = &cursor->key;
- value = &cursor->value;
-
- if ((ret = copyin_key(wtcursor)) != 0)
- return (ret);
-
-retry: if ((ret = dbc->get(dbc, key, value, DB_SET_RANGE)) == 0) {
- /*
- * WiredTiger returns the logically adjacent key (which might
- * be less than, equal to, or greater than the specified key),
- * Berkeley DB returns a key equal to or greater than the
- * specified key. Check for an exact match, otherwise Berkeley
- * DB must have returned a larger key than the one specified.
- */
- if (key->size == wtcursor->key.size &&
- memcmp(key->data, wtcursor->key.data, key->size) == 0)
- *exact = 0;
- else
- *exact = 1;
- copyout_key(wtcursor);
- copyout_value(wtcursor);
- return (0);
- }
-
- /*
- * Berkeley DB only returns keys equal to or greater than the specified
- * key, while WiredTiger returns adjacent keys, that is, if there's a
- * key smaller than the specified key, it's supposed to be returned. In
- * other words, WiredTiger only fails if the store is empty. Read the
- * last key in the store, and see if it's less than the specified key,
- * in which case we have the right key to return. If it's not less than
- * the specified key, we're racing with some other thread, throw up our
- * hands and try again.
- */
- if ((ret = dbc->get(dbc, key, value, DB_LAST)) == 0) {
- len = key->size < wtcursor->key.size ?
- key->size : wtcursor->key.size;
- if (memcmp(key->data, wtcursor->key.data, len) < 0) {
- *exact = -1;
- copyout_key(wtcursor);
- copyout_value(wtcursor);
- return (0);
- }
- goto retry;
- }
-
- if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY)
- return (WT_NOTFOUND);
- ERET(wt_api, session, WT_ERROR, "DbCursor.get: %s", db_strerror(ret));
-}
-
-static int
-kvs_cursor_insert(WT_CURSOR *wtcursor)
-{
- CURSOR_SOURCE *cursor;
- DB *db;
- DBC *dbc;
- DBT *key, *value;
- WT_EXTENSION_API *wt_api;
- WT_SESSION *session;
- int ret = 0;
-
- session = wtcursor->session;
- cursor = (CURSOR_SOURCE *)wtcursor;
- wt_api = cursor->wt_api;
-
- dbc = cursor->dbc;
- db = cursor->db;
- key = &cursor->key;
- value = &cursor->value;
-
- if ((ret = copyin_key(wtcursor)) != 0)
- return (ret);
- copyin_value(wtcursor);
-
- if (cursor->config_append) {
- /*
- * Berkeley DB cursors have no operation to append/create a
- * new record and set the cursor; use the DB handle instead
- * then set the cursor explicitly.
- *
- * When appending, we're allocating and returning a new record
- * number.
- */
- if ((ret = db->put(db, NULL, key, value, DB_APPEND)) != 0)
- ERET(wt_api,
- session, WT_ERROR, "Db.put: %s", db_strerror(ret));
- wtcursor->recno = *(db_recno_t *)key->data;
-
- if ((ret = dbc->get(dbc, key, value, DB_SET)) != 0)
- ERET(wt_api, session, WT_ERROR,
- "DbCursor.get: %s", db_strerror(ret));
- } else if (cursor->config_overwrite) {
- if ((ret = dbc->put(dbc, key, value, DB_KEYFIRST)) != 0)
- ERET(wt_api, session, WT_ERROR,
- "DbCursor.put: %s", db_strerror(ret));
- } else {
- /*
- * Berkeley DB cursors don't have a no-overwrite flag; use
- * the DB handle instead then set the cursor explicitly.
- */
- if ((ret =
- db->put(db, NULL, key, value, DB_NOOVERWRITE)) != 0) {
- if (ret == DB_KEYEXIST)
- return (WT_DUPLICATE_KEY);
- ERET(wt_api,
- session, WT_ERROR, "Db.put: %s", db_strerror(ret));
- }
- if ((ret = dbc->get(dbc, key, value, DB_SET)) != 0)
- ERET(wt_api, session, WT_ERROR,
- "DbCursor.get: %s", db_strerror(ret));
- }
-
- return (0);
-}
-
-static int
-kvs_cursor_update(WT_CURSOR *wtcursor)
-{
- CURSOR_SOURCE *cursor;
- DBC *dbc;
- DBT *key, *value;
- WT_EXTENSION_API *wt_api;
- WT_SESSION *session;
- int ret = 0;
-
- session = wtcursor->session;
- cursor = (CURSOR_SOURCE *)wtcursor;
- wt_api = cursor->wt_api;
-
- dbc = cursor->dbc;
- key = &cursor->key;
- value = &cursor->value;
-
- if ((ret = copyin_key(wtcursor)) != 0)
- return (ret);
- copyin_value(wtcursor);
-
- if ((ret = dbc->put(dbc, key, value, DB_KEYFIRST)) != 0)
- ERET(wt_api,
- session, WT_ERROR, "DbCursor.put: %s", db_strerror(ret));
-
- return (0);
-}
-
-static int
-kvs_cursor_remove(WT_CURSOR *wtcursor)
-{
- CURSOR_SOURCE *cursor;
- DBC *dbc;
- DBT *key, *value;
- WT_EXTENSION_API *wt_api;
- WT_SESSION *session;
- int ret = 0;
-
- session = wtcursor->session;
- cursor = (CURSOR_SOURCE *)wtcursor;
- wt_api = cursor->wt_api;
-
- dbc = cursor->dbc;
- key = &cursor->key;
- value = &cursor->value;
-
- /*
- * WiredTiger's "remove" of a bitfield is really an update with a value
- * of a single byte of zero.
- */
- if (cursor->config_bitfield) {
- wtcursor->value.size = 1;
- wtcursor->value.data = "\0";
- return (kvs_cursor_update(wtcursor));
- }
-
- if ((ret = copyin_key(wtcursor)) != 0)
- return (ret);
-
- if ((ret = dbc->get(dbc, key, value, DB_SET)) != 0) {
- if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY)
- return (WT_NOTFOUND);
- ERET(wt_api,
- session, WT_ERROR, "DbCursor.get: %s", db_strerror(ret));
- }
- if ((ret = dbc->del(dbc, 0)) != 0)
- ERET(wt_api,
- session, WT_ERROR, "DbCursor.del: %s", db_strerror(ret));
-
- return (0);
-}
-
-static int
-kvs_cursor_close(WT_CURSOR *wtcursor)
-{
- CURSOR_SOURCE *cursor;
- DATA_SOURCE *ds;
- DB *db;
- DBC *dbc;
- WT_EXTENSION_API *wt_api;
- WT_SESSION *session;
- int ret = 0;
-
- session = wtcursor->session;
- cursor = (CURSOR_SOURCE *)wtcursor;
- ds = cursor->ds;
- wt_api = cursor->wt_api;
-
- dbc = cursor->dbc;
- cursor->dbc = NULL;
- if (dbc != NULL && (ret = dbc->close(dbc)) != 0)
- ERET(wt_api, session, WT_ERROR,
- "DbCursor.close: %s", db_strerror(ret));
-
- db = cursor->db;
- cursor->db = NULL;
- if (db != NULL && (ret = db->close(db, 0)) != 0)
- ERET(wt_api,
- session, WT_ERROR, "Db.close: %s", db_strerror(ret));
- free(wtcursor);
-
- if ((ret = writelock(wt_api, session, &ds->rwlock)) != 0)
- return (ret);
- --ds->open_cursors;
- if ((ret = unlock(wt_api, session, &ds->rwlock)) != 0)
- return (ret);
-
- return (0);
-}
-
-static int
-kvs_session_create(WT_DATA_SOURCE *wtds,
- WT_SESSION *session, const char *uri, WT_CONFIG_ARG *config)
-{
- DATA_SOURCE *ds;
- DB *db;
- DBTYPE type;
- WT_CONFIG_ITEM v;
- WT_EXTENSION_API *wt_api;
- int ret = 0;
- const char *name;
-
- ds = (DATA_SOURCE *)wtds;
- wt_api = ds->wt_api;
- /* Get the object name */
- if ((ret = uri2name(wt_api, session, uri, &name)) != 0)
- return (ret);
- /* Check key/value formats */
- if ((ret =
- wt_api->config_get(wt_api, session, config, "key_format", &v)) != 0)
- ERET(wt_api, session, ret,
- "key_format configuration: %s",
- wt_api->strerror(wt_api, session, ret));
- type = v.len == 1 && v.str[0] == 'r' ? DB_RECNO : DB_BTREE;
-
- /* Create the Berkeley DB table */
- if ((ret = db_create(&db, ds->dbenv, 0)) != 0)
- ERET(wt_api,
- session, WT_ERROR, "db_create: %s", db_strerror(ret));
- if ((ret = db->open(db, NULL, name, NULL, type, DB_CREATE, 0)) != 0)
- ERET(wt_api,
- session, WT_ERROR, "Db.open: %s", uri, db_strerror(ret));
- if ((ret = db->close(db, 0)) != 0)
- ERET(wt_api, session, WT_ERROR, "Db.close", db_strerror(ret));
-
- return (0);
-}
-
-static int
-kvs_session_drop(WT_DATA_SOURCE *wtds,
- WT_SESSION *session, const char *uri, WT_CONFIG_ARG *config)
-{
- DB *db;
- DATA_SOURCE *ds;
- WT_EXTENSION_API *wt_api;
- int ret = 0;
- const char *name;
-
- (void)config; /* Unused parameters */
-
- ds = (DATA_SOURCE *)wtds;
- wt_api = ds->wt_api;
- /* Get the object name */
- if ((ret = uri2name(wt_api, session, uri, &name)) != 0)
- return (ret);
-
- if ((ret = single_thread(wtds, session, &ds->rwlock)) != 0)
- return (ret);
-
- if ((ret = db_create(&db, ds->dbenv, 0)) != 0)
- ESET(wt_api,
- session, WT_ERROR, "db_create: %s", db_strerror(ret));
- else if ((ret = db->remove(db, name, NULL, 0)) != 0)
- ESET(wt_api,
- session, WT_ERROR, "Db.remove: %s", db_strerror(ret));
- /* db handle is dead */
-
- ETRET(unlock(wt_api, session, &ds->rwlock));
- return (ret);
-}
-
-static int
-kvs_session_open_cursor(WT_DATA_SOURCE *wtds, WT_SESSION *session,
- const char *uri, WT_CONFIG_ARG *config, WT_CURSOR **new_cursor)
-{
- CURSOR_SOURCE *cursor;
- DATA_SOURCE *ds;
- DB *db;
- WT_CONFIG_ITEM v;
- WT_EXTENSION_API *wt_api;
- int locked, ret;
- const char *name;
-
- ds = (DATA_SOURCE *)wtds;
- wt_api = ds->wt_api;
- locked = 0;
- /* Get the object name */
- if ((ret = uri2name(wt_api, session, uri, &name)) != 0)
- return (ret);
- /* Allocate the cursor */
- if ((cursor = calloc(1, sizeof(CURSOR_SOURCE))) == NULL)
- return (os_errno());
- cursor->ds = (DATA_SOURCE *)wtds;
- cursor->wt_api = wt_api;
- /* Parse configuration */
- if ((ret = wt_api->config_get(
- wt_api, session, config, "append", &v)) != 0) {
- ESET(wt_api, session, ret,
- "append configuration: %s",
- wt_api->strerror(wt_api, session, ret));
- goto err;
- }
- cursor->config_append = v.val != 0;
-
- if ((ret = wt_api->config_get(
- wt_api, session, config, "overwrite", &v)) != 0) {
- ESET(wt_api, session, ret,
- "overwrite configuration: %s",
- wt_api->strerror(wt_api, session, ret));
- goto err;
- }
- cursor->config_overwrite = v.val != 0;
-
- if ((ret = wt_api->config_get(
- wt_api, session, config, "key_format", &v)) != 0) {
- ESET(wt_api, session, ret,
- "key_format configuration: %s",
- wt_api->strerror(wt_api, session, ret));
- goto err;
- }
- cursor->config_recno = v.len == 1 && v.str[0] == 'r';
-
- if ((ret = wt_api->config_get(
- wt_api, session, config, "value_format", &v)) != 0) {
- ESET(wt_api, session, ret,
- "value_format configuration: %s",
- wt_api->strerror(wt_api, session, ret));
- goto err;
- }
- cursor->config_bitfield =
- v.len == 2 && isdigit((u_char)v.str[0]) && v.str[1] == 't';
-
- if ((ret = writelock(wt_api, session, &ds->rwlock)) != 0)
- goto err;
- locked = 1;
- /* Open the Berkeley DB cursor */
- if ((ret = db_create(&cursor->db, ds->dbenv, 0)) != 0) {
- ESET(wt_api,
- session, WT_ERROR, "db_create: %s", db_strerror(ret));
- goto err;
- }
- db = cursor->db;
- if ((ret = db->open(db, NULL, name, NULL,
- cursor->config_recno ? DB_RECNO : DB_BTREE, DB_CREATE, 0)) != 0) {
- ESET(wt_api,
- session, WT_ERROR, "Db.open: %s", db_strerror(ret));
- goto err;
- }
- if ((ret = db->cursor(db, NULL, &cursor->dbc, 0)) != 0) {
- ESET(wt_api,
- session, WT_ERROR, "Db.cursor: %s", db_strerror(ret));
- goto err;
- }
-
- /* Initialize the methods */
- cursor->wtcursor.next = kvs_cursor_next;
- cursor->wtcursor.prev = kvs_cursor_prev;
- cursor->wtcursor.reset = kvs_cursor_reset;
- cursor->wtcursor.search = kvs_cursor_search;
- cursor->wtcursor.search_near = kvs_cursor_search_near;
- cursor->wtcursor.insert = kvs_cursor_insert;
- cursor->wtcursor.update = kvs_cursor_update;
- cursor->wtcursor.remove = kvs_cursor_remove;
- cursor->wtcursor.close = kvs_cursor_close;
-
- *new_cursor = (WT_CURSOR *)cursor;
-
- ++ds->open_cursors;
-
- if (0) {
-err: free(cursor);
- }
-
- if (locked)
- ETRET(unlock(wt_api, session, &ds->rwlock));
- return (ret);
-}
-
-static int
-kvs_session_rename(WT_DATA_SOURCE *wtds, WT_SESSION *session,
- const char *uri, const char *newname, WT_CONFIG_ARG *config)
-{
- DATA_SOURCE *ds;
- DB *db;
- WT_EXTENSION_API *wt_api;
- int ret = 0;
- const char *name;
-
- (void)config; /* Unused parameters */
-
- ds = (DATA_SOURCE *)wtds;
- wt_api = ds->wt_api;
- /* Get the object name */
- if ((ret = uri2name(wt_api, session, uri, &name)) != 0)
- return (ret);
-
- if ((ret = single_thread(wtds, session, &ds->rwlock)) != 0)
- return (ret);
-
- if ((ret = db_create(&db, ds->dbenv, 0)) != 0)
- ESET(wt_api,
- session, WT_ERROR, "db_create: %s", db_strerror(ret));
- else if ((ret = db->rename(db, name, NULL, newname, 0)) != 0)
- ESET(wt_api,
- session, WT_ERROR, "Db.rename: %s", db_strerror(ret));
- /* db handle is dead */
-
- ETRET(unlock(wt_api, session, &ds->rwlock));
- return (ret);
-}
-
-static int
-kvs_session_truncate(WT_DATA_SOURCE *wtds,
- WT_SESSION *session, const char *uri, WT_CONFIG_ARG *config)
-{
- DATA_SOURCE *ds;
- DB *db;
- WT_EXTENSION_API *wt_api;
- int tret, ret = 0;
- const char *name;
-
- (void)config; /* Unused parameters */
-
- ds = (DATA_SOURCE *)wtds;
- wt_api = ds->wt_api;
- /* Get the object name */
- if ((ret = uri2name(wt_api, session, uri, &name)) != 0)
- return (ret);
-
- if ((ret = single_thread(wtds, session, &ds->rwlock)) != 0)
- return (ret);
-
- if ((ret = db_create(&db, ds->dbenv, 0)) != 0)
- ESET(wt_api,
- session, WT_ERROR, "db_create: %s", db_strerror(ret));
- else {
- if ((ret = db->open(db,
- NULL, name, NULL, DB_UNKNOWN, DB_TRUNCATE, 0)) != 0)
- ESET(wt_api, session, WT_ERROR,
- "Db.open: %s", db_strerror(ret));
- if ((tret = db->close(db, 0)) != 0)
- ESET(wt_api, session, WT_ERROR,
- "Db.close: %s", db_strerror(tret));
- }
-
- ETRET(unlock(wt_api, session, &ds->rwlock));
- return (ret);
-}
-
-static int
-kvs_session_verify(WT_DATA_SOURCE *wtds,
- WT_SESSION *session, const char *uri, WT_CONFIG_ARG *config)
-{
- DATA_SOURCE *ds;
- DB *db;
- WT_EXTENSION_API *wt_api;
- int ret = 0;
- const char *name;
-
- (void)config; /* Unused parameters */
-
- ds = (DATA_SOURCE *)wtds;
- wt_api = ds->wt_api;
- /* Get the object name */
- if ((ret = uri2name(wt_api, session, uri, &name)) != 0)
- return (ret);
-
- if ((ret = single_thread(wtds, session, &ds->rwlock)) != 0)
- return (ret);
-
- if ((ret = db_create(&db, ds->dbenv, 0)) != 0)
- ESET(wt_api,
- session, WT_ERROR, "db_create: %s", db_strerror(ret));
- else if ((ret = db->verify(db, name, NULL, NULL, 0)) != 0)
- ESET(wt_api, session, WT_ERROR,
- "Db.verify: %s: %s", uri, db_strerror(ret));
- /* db handle is dead */
-
- ETRET(unlock(wt_api, session, &ds->rwlock));
- return (ret);
-}
-
-static int
-kvs_terminate(WT_DATA_SOURCE *wtds, WT_SESSION *session)
-{
- DB_ENV *dbenv;
- DATA_SOURCE *ds;
- WT_EXTENSION_API *wt_api;
- int ret = 0;
-
- ds = (DATA_SOURCE *)wtds;
- wt_api = ds->wt_api;
- dbenv = ds->dbenv;
-
- if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0)
- ESET(wt_api,
- session, WT_ERROR, "DbEnv.close: %s", db_strerror(ret));
-
- ETRET(lock_destroy(wt_api, session, &ds->rwlock));
-
- return (ret);
-}
-
-int
-wiredtiger_extension_init(WT_CONNECTION *connection, WT_CONFIG_ARG *config)
-{
- /*
- * List of the WT_DATA_SOURCE methods -- it's static so it breaks at
- * compile-time should the structure change underneath us.
- */
- static WT_DATA_SOURCE wtds = {
- NULL, /* No session.alter */
- kvs_session_create, /* session.create */
- NULL, /* No session.compaction */
- kvs_session_drop, /* session.drop */
- kvs_session_open_cursor, /* session.open_cursor */
- kvs_session_rename, /* session.rename */
- NULL, /* No session.salvage */
- NULL, /* No session.size */
- kvs_session_truncate, /* session.truncate */
- NULL, /* No range_truncate */
- kvs_session_verify, /* session.verify */
- NULL, /* session.checkpoint */
- kvs_terminate, /* termination */
- NULL /* lsm_pre_merge */
- };
- DATA_SOURCE *ds;
- DB_ENV *dbenv;
- WT_EXTENSION_API *wt_api;
- size_t len;
- int ret = 0;
- const char *home;
- char *path;
-
- (void)config; /* Unused parameters */
-
- ds = NULL;
- dbenv = NULL;
- path = NULL;
- /* Acquire the extension API */
- wt_api = connection->get_extension_api(connection);
-
- /* Allocate the local data-source structure. */
- if ((ds = calloc(1, sizeof(DATA_SOURCE))) == NULL)
- return (os_errno());
- ds->wt_api = wt_api;
- /* Configure the global lock */
- if ((ret = lock_init(wt_api, NULL, &ds->rwlock)) != 0)
- goto err;
-
- ds->wtds = wtds; /* Configure the methods */
-
- /* Berkeley DB environment */
- if ((ret = db_env_create(&dbenv, 0)) != 0) {
- ESET(wt_api,
- NULL, WT_ERROR, "db_env_create: %s", db_strerror(ret));
- goto err;
- }
- dbenv->set_errpfx(dbenv, "bdb");
- dbenv->set_errfile(dbenv, stderr);
-
- home = connection->get_home(connection);
- len = strlen(home) + 10;
- if ((path = malloc(len)) == NULL)
- goto err;
- (void)snprintf(path, len, "%s/KVS", home);
- if ((ret = dbenv->open(dbenv, path,
- DB_CREATE | DB_INIT_LOCK | DB_INIT_MPOOL | DB_PRIVATE, 0)) != 0) {
- ESET(wt_api,
- NULL, WT_ERROR, "DbEnv.open: %s", db_strerror(ret));
- goto err;
- }
- ds->dbenv = dbenv;
-
- if ((ret = /* Add the data source */
- connection->add_data_source(
- connection, "kvsbdb:", (WT_DATA_SOURCE *)ds, NULL)) != 0) {
- ESET(wt_api, NULL, ret, "WT_CONNECTION.add_data_source");
- goto err;
- }
-
- if (0) {
-err: if (dbenv != NULL)
- (void)dbenv->close(dbenv, 0);
- free(ds);
- }
- free(path);
- return (ret);
-}
-
-int
-wiredtiger_extension_terminate(WT_CONNECTION *connection)
-{
- (void)connection; /* Unused parameters */
-
- return (0);
-}