summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/examples
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/wiredtiger/examples')
-rw-r--r--src/third_party/wiredtiger/examples/c/Makefile.am38
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_access.c99
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_all.c1226
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_async.c224
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_backup.c326
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_call_center.c249
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_config.c91
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_config_parse.c166
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_cursor.c228
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_data_source.c673
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_encrypt.c593
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_extending.c133
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_extractor.c284
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_hello.c76
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_log.c358
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_pack.c89
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_process.c79
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_schema.c364
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_scope.c214
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_stat.c227
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_sync.c153
-rw-r--r--src/third_party/wiredtiger/examples/c/ex_thread.c127
-rw-r--r--src/third_party/wiredtiger/examples/java/Makefile.am21
-rw-r--r--src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_access.java94
-rw-r--r--src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_all.java1036
-rw-r--r--src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_async.java221
-rw-r--r--src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_call_center.java302
-rw-r--r--src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_cursor.java242
-rw-r--r--src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_log.java382
-rw-r--r--src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_schema.java392
-rw-r--r--src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_stat.java256
-rw-r--r--src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_thread.java149
-rwxr-xr-xsrc/third_party/wiredtiger/examples/python/ex_access.py55
-rwxr-xr-xsrc/third_party/wiredtiger/examples/python/ex_stat.py109
34 files changed, 9276 insertions, 0 deletions
diff --git a/src/third_party/wiredtiger/examples/c/Makefile.am b/src/third_party/wiredtiger/examples/c/Makefile.am
new file mode 100644
index 00000000000..587204efff1
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/Makefile.am
@@ -0,0 +1,38 @@
+LDADD = $(top_builddir)/libwiredtiger.la
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+noinst_PROGRAMS = \
+ ex_access \
+ ex_all \
+ ex_async \
+ ex_backup \
+ ex_call_center \
+ ex_config \
+ ex_config_parse \
+ ex_cursor \
+ ex_data_source \
+ ex_encrypt \
+ ex_extending \
+ ex_extractor \
+ ex_hello \
+ ex_log \
+ ex_pack \
+ ex_process \
+ ex_schema \
+ ex_scope \
+ ex_stat \
+ ex_sync \
+ ex_thread
+
+ex_encrypt_LDFLAGS = -rdynamic
+
+# The examples can be run with no arguments as simple smoke tests
+TESTS = $(noinst_PROGRAMS)
+
+AM_TESTS_ENVIRONMENT = WIREDTIGER_HOME=`mktemp -d WT_HOME.XXXX` ; export WIREDTIGER_HOME ; rm -rf $$WIREDTIGER_HOME ; mkdir $$WIREDTIGER_HOME ;
+
+# Inject valgrind or similar
+LOG_COMPILER = $(TEST_WRAPPER)
+
+clean-local:
+ rm -rf WT_HOME* *.core backup_full.* backup_incr.*
diff --git a/src/third_party/wiredtiger/examples/c/ex_access.c b/src/third_party/wiredtiger/examples/c/ex_access.c
new file mode 100644
index 00000000000..cc42982617b
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_access.c
@@ -0,0 +1,99 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_access.c
+ * demonstrates how to create and access a simple table.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <wiredtiger.h>
+
+static const char *home;
+
+int
+main(void)
+{
+ /*! [access example connection] */
+ WT_CONNECTION *conn;
+ WT_CURSOR *cursor;
+ WT_SESSION *session;
+ const char *key, *value;
+ int ret;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (getenv("WIREDTIGER_HOME") == NULL) {
+ home = "WT_HOME";
+ ret = system("rm -rf WT_HOME && mkdir WT_HOME");
+ } else
+ home = NULL;
+
+ /* Open a connection to the database, creating it if necessary. */
+ if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0 ||
+ (ret = conn->open_session(conn, NULL, NULL, &session)) != 0) {
+ fprintf(stderr, "Error connecting to %s: %s\n",
+ home, wiredtiger_strerror(ret));
+ return (ret);
+ }
+ /*! [access example connection] */
+
+ /*! [access example table create] */
+ ret = session->create(session,
+ "table:access", "key_format=S,value_format=S");
+ /*! [access example table create] */
+
+ /*! [access example cursor open] */
+ ret = session->open_cursor(session,
+ "table:access", NULL, NULL, &cursor);
+ /*! [access example cursor open] */
+
+ /*! [access example cursor insert] */
+ cursor->set_key(cursor, "key1"); /* Insert a record. */
+ cursor->set_value(cursor, "value1");
+ ret = cursor->insert(cursor);
+ /*! [access example cursor insert] */
+
+ /*! [access example cursor list] */
+ ret = cursor->reset(cursor); /* Restart the scan. */
+ while ((ret = cursor->next(cursor)) == 0) {
+ ret = cursor->get_key(cursor, &key);
+ ret = cursor->get_value(cursor, &value);
+
+ printf("Got record: %s : %s\n", key, value);
+ }
+ /*! [access example cursor list] */
+
+ /*! [access example close] */
+ ret = conn->close(conn, NULL);
+ /*! [access example close] */
+
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_all.c b/src/third_party/wiredtiger/examples/c/ex_all.c
new file mode 100644
index 00000000000..f7ee857a7c7
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_all.c
@@ -0,0 +1,1226 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_all.c
+ * Containing a call to every method in the WiredTiger API.
+ *
+ * It doesn't do anything very useful, just demonstrates how to call each
+ * method. This file is used to populate the API reference with code
+ * fragments.
+ */
+
+#include <sys/stat.h>
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#include "windows_shim.h"
+#endif
+
+#include <wiredtiger.h>
+
+int add_collator(WT_CONNECTION *conn);
+int add_extractor(WT_CONNECTION *conn);
+int backup(WT_SESSION *session);
+int checkpoint_ops(WT_SESSION *session);
+int connection_ops(WT_CONNECTION *conn);
+int cursor_ops(WT_SESSION *session);
+int cursor_search_near(WT_CURSOR *cursor);
+int cursor_statistics(WT_SESSION *session);
+int pack_ops(WT_SESSION *session);
+int named_snapshot_ops(WT_SESSION *session);
+int session_ops(WT_SESSION *session);
+int transaction_ops(WT_CONNECTION *conn, WT_SESSION *session);
+
+static const char * const progname = "ex_all";
+static const char *home;
+
+int
+cursor_ops(WT_SESSION *session)
+{
+ WT_CURSOR *cursor;
+ int ret;
+
+ /*! [Open a cursor] */
+ ret = session->open_cursor(
+ session, "table:mytable", NULL, NULL, &cursor);
+ /*! [Open a cursor] */
+
+ /*! [Open a cursor on the metadata] */
+ ret = session->open_cursor(
+ session, "metadata:", NULL, NULL, &cursor);
+ /*! [Open a cursor on the metadata] */
+
+ {
+ WT_CURSOR *duplicate;
+ const char *key = "some key";
+ /*! [Duplicate a cursor] */
+ ret = session->open_cursor(
+ session, "table:mytable", NULL, NULL, &cursor);
+ cursor->set_key(cursor, key);
+ ret = cursor->search(cursor);
+
+ /* Duplicate the cursor. */
+ ret = session->open_cursor(session, NULL, cursor, NULL, &duplicate);
+ /*! [Duplicate a cursor] */
+ }
+
+ {
+ const char *key = "some key", *value = "some value";
+ /*! [Reconfigure a cursor] */
+ ret = session->open_cursor(
+ session, "table:mytable", NULL, "overwrite=false", &cursor);
+ cursor->set_key(cursor, key);
+ cursor->set_value(cursor, value);
+
+ /* Reconfigure the cursor to overwrite the record. */
+ ret = cursor->reconfigure(cursor, "overwrite=true");
+ ret = cursor->insert(cursor);
+ /*! [Reconfigure a cursor] */
+ }
+
+ {
+ /*! [boolean configuration string example] */
+ ret = session->open_cursor(session, "table:mytable", NULL,
+ "overwrite", &cursor);
+ ret = session->open_cursor(session, "table:mytable", NULL,
+ "overwrite=true", &cursor);
+ ret = session->open_cursor(session, "table:mytable", NULL,
+ "overwrite=1", &cursor);
+ /*! [boolean configuration string example] */
+ }
+
+ {
+ /*! [open a named checkpoint] */
+ ret = session->open_cursor(session,
+ "table:mytable", NULL, "checkpoint=midnight", &cursor);
+ /*! [open a named checkpoint] */
+ }
+
+ {
+ /*! [open the default checkpoint] */
+ ret = session->open_cursor(session,
+ "table:mytable", NULL, "checkpoint=WiredTigerCheckpoint", &cursor);
+ /*! [open the default checkpoint] */
+ }
+
+ {
+ /*! [Get the cursor's string key] */
+ const char *key; /* Get the cursor's string key. */
+ ret = cursor->get_key(cursor, &key);
+ /*! [Get the cursor's string key] */
+ }
+
+ {
+ /*! [Set the cursor's string key] */
+ /* Set the cursor's string key. */
+ const char *key = "another key";
+ cursor->set_key(cursor, key);
+ /*! [Set the cursor's string key] */
+ }
+
+ {
+ /*! [Get the cursor's record number key] */
+ uint64_t recno; /* Get the cursor's record number key. */
+ ret = cursor->get_key(cursor, &recno);
+ /*! [Get the cursor's record number key] */
+ }
+
+ {
+ /*! [Set the cursor's record number key] */
+ uint64_t recno = 37; /* Set the cursor's record number key. */
+ cursor->set_key(cursor, recno);
+ /*! [Set the cursor's record number key] */
+ }
+
+ {
+ /*! [Get the cursor's composite key] */
+ /* Get the cursor's "SiH" format composite key. */
+ const char *first;
+ int32_t second;
+ uint16_t third;
+ ret = cursor->get_key(cursor, &first, &second, &third);
+ /*! [Get the cursor's composite key] */
+ }
+
+ {
+ /*! [Set the cursor's composite key] */
+ /* Set the cursor's "SiH" format composite key. */
+ cursor->set_key(cursor, "first", (int32_t)5, (uint16_t)7);
+ /*! [Set the cursor's composite key] */
+ }
+
+ {
+ /*! [Get the cursor's string value] */
+ const char *value; /* Get the cursor's string value. */
+ ret = cursor->get_value(cursor, &value);
+ /*! [Get the cursor's string value] */
+ }
+
+ {
+ /*! [Set the cursor's string value] */
+ /* Set the cursor's string value. */
+ const char *value = "another value";
+ cursor->set_value(cursor, value);
+ /*! [Set the cursor's string value] */
+ }
+
+ {
+ /*! [Get the cursor's raw value] */
+ WT_ITEM value; /* Get the cursor's raw value. */
+ ret = cursor->get_value(cursor, &value);
+ /*! [Get the cursor's raw value] */
+ }
+
+ {
+ /*! [Set the cursor's raw value] */
+ WT_ITEM value; /* Set the cursor's raw value. */
+ value.data = "another value";
+ value.size = strlen("another value");
+ cursor->set_value(cursor, &value);
+ /*! [Set the cursor's raw value] */
+ }
+
+ /*! [Return the next record] */
+ ret = cursor->next(cursor);
+ /*! [Return the next record] */
+
+ /*! [Return the previous record] */
+ ret = cursor->prev(cursor);
+ /*! [Return the previous record] */
+
+ /*! [Reset the cursor] */
+ ret = cursor->reset(cursor);
+ /*! [Reset the cursor] */
+
+ {
+ WT_CURSOR *other = NULL;
+ /*! [Cursor comparison] */
+ int compare;
+ ret = cursor->compare(cursor, other, &compare);
+ if (compare == 0) {
+ /* Cursors reference the same key */
+ } else if (compare < 0) {
+ /* Cursor key less than other key */
+ } else if (compare > 0) {
+ /* Cursor key greater than other key */
+ }
+ /*! [Cursor comparison] */
+ }
+
+ {
+ WT_CURSOR *other = NULL;
+ /*! [Cursor equality] */
+ int equal;
+ ret = cursor->equals(cursor, other, &equal);
+ if (equal) {
+ /* Cursors reference the same key */
+ } else {
+ /* Cursors don't reference the same key */
+ }
+ /*! [Cursor equality] */
+ }
+
+ {
+ /*! [Search for an exact match] */
+ const char *key = "some key";
+ cursor->set_key(cursor, key);
+ ret = cursor->search(cursor);
+ /*! [Search for an exact match] */
+ }
+
+ ret = cursor_search_near(cursor);
+
+ {
+ /*! [Insert a new record or overwrite an existing record] */
+ /* Insert a new record or overwrite an existing record. */
+ const char *key = "some key", *value = "some value";
+ ret = session->open_cursor(
+ session, "table:mytable", NULL, NULL, &cursor);
+ cursor->set_key(cursor, key);
+ cursor->set_value(cursor, value);
+ ret = cursor->insert(cursor);
+ /*! [Insert a new record or overwrite an existing record] */
+ }
+
+ {
+ /*! [Insert a new record and fail if the record exists] */
+ /* Insert a new record and fail if the record exists. */
+ const char *key = "some key", *value = "some value";
+ ret = session->open_cursor(
+ session, "table:mytable", NULL, "overwrite=false", &cursor);
+ cursor->set_key(cursor, key);
+ cursor->set_value(cursor, value);
+ ret = cursor->insert(cursor);
+ /*! [Insert a new record and fail if the record exists] */
+ }
+
+ {
+ /*! [Insert a new record and assign a record number] */
+ /* Insert a new record and assign a record number. */
+ uint64_t recno;
+ const char *value = "some value";
+ ret = session->open_cursor(
+ session, "table:mytable", NULL, "append", &cursor);
+ cursor->set_value(cursor, value);
+ ret = cursor->insert(cursor);
+ if (ret == 0)
+ ret = cursor->get_key(cursor, &recno);
+ /*! [Insert a new record and assign a record number] */
+ }
+
+ {
+ /*! [Update an existing record or insert a new record] */
+ const char *key = "some key", *value = "some value";
+ ret = session->open_cursor(
+ session, "table:mytable", NULL, NULL, &cursor);
+ cursor->set_key(cursor, key);
+ cursor->set_value(cursor, value);
+ ret = cursor->update(cursor);
+ /*! [Update an existing record or insert a new record] */
+ }
+
+ {
+ /*! [Update an existing record and fail if DNE] */
+ const char *key = "some key", *value = "some value";
+ ret = session->open_cursor(
+ session, "table:mytable", NULL, "overwrite=false", &cursor);
+ cursor->set_key(cursor, key);
+ cursor->set_value(cursor, value);
+ ret = cursor->update(cursor);
+ /*! [Update an existing record and fail if DNE] */
+ }
+
+ {
+ /*! [Remove a record] */
+ const char *key = "some key";
+ ret = session->open_cursor(
+ session, "table:mytable", NULL, NULL, &cursor);
+ cursor->set_key(cursor, key);
+ ret = cursor->remove(cursor);
+ /*! [Remove a record] */
+ }
+
+ {
+ /*! [Remove a record and fail if DNE] */
+ const char *key = "some key";
+ ret = session->open_cursor(
+ session, "table:mytable", NULL, "overwrite=false", &cursor);
+ cursor->set_key(cursor, key);
+ ret = cursor->remove(cursor);
+ /*! [Remove a record and fail if DNE] */
+ }
+
+ {
+ /*! [Display an error] */
+ const char *key = "non-existent key";
+ cursor->set_key(cursor, key);
+ if ((ret = cursor->remove(cursor)) != 0) {
+ fprintf(stderr,
+ "cursor.remove: %s\n",
+ cursor->session->strerror(cursor->session, ret));
+ return (ret);
+ }
+ /*! [Display an error] */
+ }
+
+ {
+ /*! [Display an error thread safe] */
+ const char *key = "non-existent key";
+ cursor->set_key(cursor, key);
+ if ((ret = cursor->remove(cursor)) != 0) {
+ fprintf(stderr,
+ "cursor.remove: %s\n", session->strerror(session, ret));
+ return (ret);
+ }
+ /*! [Display an error thread safe] */
+ }
+
+ /*! [Close the cursor] */
+ ret = cursor->close(cursor);
+ /*! [Close the cursor] */
+
+ return (ret);
+}
+
+int
+cursor_search_near(WT_CURSOR *cursor)
+{
+ int exact, ret;
+ const char *key = "some key";
+
+ /*! [Search for an exact or adjacent match] */
+ cursor->set_key(cursor, key);
+ ret = cursor->search_near(cursor, &exact);
+ if (ret == 0) {
+ if (exact == 0) {
+ /* an exact match */
+ } else if (exact < 0) {
+ /* returned smaller key */
+ } else if (exact > 0) {
+ /* returned larger key */
+ }
+ }
+ /*! [Search for an exact or adjacent match] */
+
+ /*! [Forward scan greater than or equal] */
+ cursor->set_key(cursor, key);
+ ret = cursor->search_near(cursor, &exact);
+ if (ret == 0 && exact >= 0) {
+ /* include first key returned in the scan */
+ }
+
+ while ((ret = cursor->next(cursor)) == 0) {
+ /* the rest of the scan */
+ }
+ /*! [Forward scan greater than or equal] */
+
+ /*! [Backward scan less than] */
+ cursor->set_key(cursor, key);
+ ret = cursor->search_near(cursor, &exact);
+ if (ret == 0 && exact < 0) {
+ /* include first key returned in the scan */
+ }
+
+ while ((ret = cursor->prev(cursor)) == 0) {
+ /* the rest of the scan */
+ }
+ /*! [Backward scan less than] */
+
+ return (ret);
+}
+
+int
+checkpoint_ops(WT_SESSION *session)
+{
+ int ret;
+
+ /*! [Checkpoint examples] */
+ /* Checkpoint the database. */
+ ret = session->checkpoint(session, NULL);
+
+ /* Checkpoint of the database, creating a named snapshot. */
+ ret = session->checkpoint(session, "name=June01");
+
+ /*
+ * Checkpoint a list of objects.
+ * JSON parsing requires quoting the list of target URIs.
+ */
+ ret = session->
+ checkpoint(session, "target=(\"table:table1\",\"table:table2\")");
+
+ /*
+ * Checkpoint a list of objects, creating a named snapshot.
+ * JSON parsing requires quoting the list of target URIs.
+ */
+ ret = session->
+ checkpoint(session, "target=(\"table:mytable\"),name=midnight");
+
+ /* Checkpoint the database, discarding all previous snapshots. */
+ ret = session->checkpoint(session, "drop=(from=all)");
+
+ /* Checkpoint the database, discarding the "midnight" snapshot. */
+ ret = session->checkpoint(session, "drop=(midnight)");
+
+ /*
+ * Checkpoint the database, discarding all snapshots after and
+ * including "noon".
+ */
+ ret = session->checkpoint(session, "drop=(from=noon)");
+
+ /*
+ * Checkpoint the database, discarding all snapshots before and
+ * including "midnight".
+ */
+ ret = session->checkpoint(session, "drop=(to=midnight)");
+
+ /*
+ * Create a checkpoint of a table, creating the "July01" snapshot and
+ * discarding the "May01" and "June01" snapshots.
+ * JSON parsing requires quoting the list of target URIs.
+ */
+ ret = session->checkpoint(session,
+ "target=(\"table:mytable\"),name=July01,drop=(May01,June01)");
+ /*! [Checkpoint examples] */
+
+ /*! [JSON quoting example] */
+ /*
+ * Checkpoint a list of objects.
+ * JSON parsing requires quoting the list of target URIs.
+ */
+ ret = session->
+ checkpoint(session, "target=(\"table:table1\",\"table:table2\")");
+ /*! [JSON quoting example] */
+
+ return (ret);
+}
+
+int
+cursor_statistics(WT_SESSION *session)
+{
+ WT_CURSOR *cursor;
+ int ret;
+
+ /*! [Statistics cursor database] */
+ ret = session->open_cursor(
+ session, "statistics:", NULL, NULL, &cursor);
+ /*! [Statistics cursor database] */
+
+ /*! [Statistics cursor table] */
+ ret = session->open_cursor(
+ session, "statistics:table:mytable", NULL, NULL, &cursor);
+ /*! [Statistics cursor table] */
+
+ /*! [Statistics cursor table fast] */
+ ret = session->open_cursor(session,
+ "statistics:table:mytable", NULL, "statistics=(fast)", &cursor);
+ /*! [Statistics cursor table fast] */
+
+ /*! [Statistics clear configuration] */
+ ret = session->open_cursor(session,
+ "statistics:", NULL, "statistics=(fast,clear)", &cursor);
+ /*! [Statistics clear configuration] */
+
+ /*! [Statistics cursor clear configuration] */
+ ret = session->open_cursor(session,
+ "statistics:table:mytable",
+ NULL, "statistics=(all,clear)", &cursor);
+ /*! [Statistics cursor clear configuration] */
+
+ return (ret);
+}
+
+int
+named_snapshot_ops(WT_SESSION *session)
+{
+ int ret;
+
+ /*! [Snapshot examples] */
+
+ /* Create a named snapshot */
+ ret = session->snapshot(session, "name=June01");
+
+ /* Open a transaction at a given snapshot */
+ ret = session->begin_transaction(session, "snapshot=June01");
+
+ /* Drop all named snapshots */
+ ret = session->snapshot(session, "drop=(all)");
+ /*! [Snapshot examples] */
+
+ return (ret);
+}
+
+int
+session_ops(WT_SESSION *session)
+{
+ int ret;
+
+ /*! [Reconfigure a session] */
+ ret = session->reconfigure(session, "isolation=snapshot");
+ /*! [Reconfigure a session] */
+
+ /*! [Create a table] */
+ ret = session->create(session,
+ "table:mytable", "key_format=S,value_format=S");
+ /*! [Create a table] */
+ ret = session->drop(session, "table:mytable", NULL);
+
+ /*! [Create a column-store table] */
+ ret = session->create(session,
+ "table:mytable", "key_format=r,value_format=S");
+ /*! [Create a column-store table] */
+ ret = session->drop(session, "table:mytable", NULL);
+
+ /*! [Create a table with columns] */
+ /*
+ * Create a table with columns: keys are record numbers, values are
+ * (string, signed 32-bit integer, unsigned 16-bit integer).
+ */
+ ret = session->create(session, "table:mytable",
+ "key_format=r,value_format=SiH,"
+ "columns=(id,department,salary,year-started)");
+ /*! [Create a table with columns] */
+ ret = session->drop(session, "table:mytable", NULL);
+
+ /*! [Create a table and configure the page size] */
+ ret = session->create(session,
+ "table:mytable", "key_format=S,value_format=S,"
+ "internal_page_max=16KB,leaf_page_max=1MB,leaf_value_max=64KB");
+ /*! [Create a table and configure the page size] */
+ ret = session->drop(session, "table:mytable", NULL);
+
+ /*! [Create a table and configure a large leaf value max] */
+ ret = session->create(session,
+ "table:mytable", "key_format=S,value_format=S,"
+ "leaf_page_max=16KB,leaf_value_max=256KB");
+ /*! [Create a table and configure a large leaf value max] */
+ ret = session->drop(session, "table:mytable", NULL);
+
+ /*
+ * This example code gets run, and the compression libraries might not
+ * be loaded, causing the create to fail. The documentation requires
+ * the code snippets, use #ifdef's to avoid running it.
+ */
+#ifdef MIGHT_NOT_RUN
+ /*! [Create a bzip2 compressed table] */
+ ret = session->create(session,
+ "table:mytable",
+ "block_compressor=bzip2,key_format=S,value_format=S");
+ /*! [Create a bzip2 compressed table] */
+ ret = session->drop(session, "table:mytable", NULL);
+
+ /*! [Create a lz4 compressed table] */
+ ret = session->create(session,
+ "table:mytable",
+ "block_compressor=lz4,key_format=S,value_format=S");
+ /*! [Create a lz4 compressed table] */
+ ret = session->drop(session, "table:mytable", NULL);
+
+ /*! [Create a snappy compressed table] */
+ ret = session->create(session,
+ "table:mytable",
+ "block_compressor=snappy,key_format=S,value_format=S");
+ /*! [Create a snappy compressed table] */
+ ret = session->drop(session, "table:mytable", NULL);
+
+ /*! [Create a zlib compressed table] */
+ ret = session->create(session,
+ "table:mytable",
+ "block_compressor=zlib,key_format=S,value_format=S");
+ /*! [Create a zlib compressed table] */
+ ret = session->drop(session, "table:mytable", NULL);
+#endif
+
+ /*! [Configure checksums to uncompressed] */
+ ret = session->create(session, "table:mytable",
+ "key_format=S,value_format=S,checksum=uncompressed");
+ /*! [Configure checksums to uncompressed] */
+ ret = session->drop(session, "table:mytable", NULL);
+
+ /*! [Configure dictionary compression on] */
+ ret = session->create(session, "table:mytable",
+ "key_format=S,value_format=S,dictionary=1000");
+ /*! [Configure dictionary compression on] */
+ ret = session->drop(session, "table:mytable", NULL);
+
+ /*! [Configure key prefix compression on] */
+ ret = session->create(session, "table:mytable",
+ "key_format=S,value_format=S,prefix_compression=true");
+ /*! [Configure key prefix compression on] */
+ ret = session->drop(session, "table:mytable", NULL);
+
+#ifdef MIGHT_NOT_RUN
+ /* Requires sync_file_range */
+ /*! [os_cache_dirty_max configuration] */
+ ret = session->create(
+ session, "table:mytable", "os_cache_dirty_max=500MB");
+ /*! [os_cache_dirty_max configuration] */
+ ret = session->drop(session, "table:mytable", NULL);
+
+ /* Requires posix_fadvise */
+ /*! [os_cache_max configuration] */
+ ret = session->create(session, "table:mytable", "os_cache_max=1GB");
+ /*! [os_cache_max configuration] */
+ ret = session->drop(session, "table:mytable", NULL);
+#endif
+ /*! [Configure block_allocation] */
+ ret = session->create(session, "table:mytable",
+ "key_format=S,value_format=S,block_allocation=first");
+ /*! [Configure block_allocation] */
+ ret = session->drop(session, "table:mytable", NULL);
+
+ /*! [Create a cache-resident object] */
+ ret = session->create(session,
+ "table:mytable", "key_format=r,value_format=S,cache_resident=true");
+ /*! [Create a cache-resident object] */
+ ret = session->drop(session, "table:mytable", NULL);
+
+ {
+ /* Create a table for the session operations. */
+ ret = session->create(
+ session, "table:mytable", "key_format=S,value_format=S");
+
+ /*! [Compact a table] */
+ ret = session->compact(session, "table:mytable", NULL);
+ /*! [Compact a table] */
+
+ /*! [Rebalance a table] */
+ ret = session->rebalance(session, "table:mytable", NULL);
+ /*! [Rebalance a table] */
+
+ /*! [Rename a table] */
+ ret = session->rename(session, "table:old", "table:new", NULL);
+ /*! [Rename a table] */
+
+ /*! [Salvage a table] */
+ ret = session->salvage(session, "table:mytable", NULL);
+ /*! [Salvage a table] */
+
+ /*! [Truncate a table] */
+ ret = session->truncate(session, "table:mytable", NULL, NULL, NULL);
+ /*! [Truncate a table] */
+
+ /*! [Transaction sync] */
+ ret = session->transaction_sync(session, NULL);
+ /*! [Transaction sync] */
+
+ /*! [Reset the session] */
+ ret = session->reset(session);
+ /*! [Reset the session] */
+
+ {
+ /*
+ * Insert a pair of keys so we can truncate a range.
+ */
+ WT_CURSOR *cursor;
+ ret = session->open_cursor(
+ session, "table:mytable", NULL, NULL, &cursor);
+ cursor->set_key(cursor, "June01");
+ cursor->set_value(cursor, "value");
+ ret = cursor->update(cursor);
+ cursor->set_key(cursor, "June30");
+ cursor->set_value(cursor, "value");
+ ret = cursor->update(cursor);
+ ret = cursor->close(cursor);
+
+ {
+ /*! [Truncate a range] */
+ WT_CURSOR *start, *stop;
+
+ ret = session->open_cursor(
+ session, "table:mytable", NULL, NULL, &start);
+ start->set_key(start, "June01");
+ ret = start->search(start);
+
+ ret = session->open_cursor(
+ session, "table:mytable", NULL, NULL, &stop);
+ stop->set_key(stop, "June30");
+ ret = stop->search(stop);
+
+ ret = session->truncate(session, NULL, start, stop, NULL);
+ /*! [Truncate a range] */
+ }
+ }
+
+ /*! [Upgrade a table] */
+ ret = session->upgrade(session, "table:mytable", NULL);
+ /*! [Upgrade a table] */
+
+ /*! [Verify a table] */
+ ret = session->verify(session, "table:mytable", NULL);
+ /*! [Verify a table] */
+
+ /*! [Drop a table] */
+ ret = session->drop(session, "table:mytable", NULL);
+ /*! [Drop a table] */
+ }
+
+ /*! [Close a session] */
+ ret = session->close(session, NULL);
+ /*! [Close a session] */
+
+ return (ret);
+}
+
+int
+transaction_ops(WT_CONNECTION *conn, WT_SESSION *session)
+{
+ WT_CURSOR *cursor;
+ int ret;
+
+ /*! [transaction commit/rollback] */
+ /*
+ * Cursors may be opened before or after the transaction begins, and in
+ * either case, subsequent operations are included in the transaction.
+ * Opening cursors before the transaction begins allows applications to
+ * cache cursors and use them for multiple operations.
+ */
+ ret =
+ session->open_cursor(session, "table:mytable", NULL, NULL, &cursor);
+ ret = session->begin_transaction(session, NULL);
+
+ cursor->set_key(cursor, "key");
+ cursor->set_value(cursor, "value");
+ switch (ret = cursor->update(cursor)) {
+ case 0: /* Update success */
+ ret = session->commit_transaction(session, NULL);
+ /*
+ * If commit_transaction succeeds, cursors remain positioned; if
+ * commit_transaction fails, the transaction was rolled-back and
+ * and all cursors are reset.
+ */
+ break;
+ case WT_ROLLBACK: /* Update conflict */
+ default: /* Other error */
+ ret = session->rollback_transaction(session, NULL);
+ /* The rollback_transaction call resets all cursors. */
+ break;
+ }
+
+ /*
+ * Cursors remain open and may be used for multiple transactions.
+ */
+ /*! [transaction commit/rollback] */
+ ret = cursor->close(cursor);
+
+ /*! [transaction isolation] */
+ /* A single transaction configured for snapshot isolation. */
+ ret =
+ session->open_cursor(session, "table:mytable", NULL, NULL, &cursor);
+ ret = session->begin_transaction(session, "isolation=snapshot");
+ cursor->set_key(cursor, "some-key");
+ cursor->set_value(cursor, "some-value");
+ ret = cursor->update(cursor);
+ ret = session->commit_transaction(session, NULL);
+ /*! [transaction isolation] */
+
+ /*! [session isolation configuration] */
+ /* Open a session configured for read-uncommitted isolation. */
+ ret = conn->open_session(
+ conn, NULL, "isolation=read_uncommitted", &session);
+ /*! [session isolation configuration] */
+
+ /*! [session isolation re-configuration] */
+ /* Re-configure a session for snapshot isolation. */
+ ret = session->reconfigure(session, "isolation=snapshot");
+ /*! [session isolation re-configuration] */
+
+ {
+ /*! [transaction pinned range] */
+ /* Check the transaction ID range pinned by the session handle. */
+ uint64_t range;
+
+ ret = session->transaction_pinned_range(session, &range);
+ /*! [transaction pinned range] */
+ }
+
+ return (ret);
+}
+
+/*! [Implement WT_COLLATOR] */
+/*
+ * A simple example of the collator API: compare the keys as strings.
+ */
+static int
+my_compare(WT_COLLATOR *collator, WT_SESSION *session,
+ const WT_ITEM *value1, const WT_ITEM *value2, int *cmp)
+{
+ const char *p1, *p2;
+
+ /* Unused parameters */
+ (void)collator;
+ (void)session;
+
+ p1 = (const char *)value1->data;
+ p2 = (const char *)value2->data;
+ while (*p1 != '\0' && *p1 == *p2)
+ p1++, p2++;
+
+ *cmp = (int)*p2 - (int)*p1;
+ return (0);
+}
+/*! [Implement WT_COLLATOR] */
+
+int
+add_collator(WT_CONNECTION *conn)
+{
+ int ret;
+
+ /*! [WT_COLLATOR register] */
+ static WT_COLLATOR my_collator = { my_compare, NULL, NULL };
+ ret = conn->add_collator(conn, "my_collator", &my_collator, NULL);
+ /*! [WT_COLLATOR register] */
+
+ return (ret);
+}
+
+/*! [WT_EXTRACTOR] */
+static int
+my_extract(WT_EXTRACTOR *extractor, WT_SESSION *session,
+ const WT_ITEM *key, const WT_ITEM *value,
+ WT_CURSOR *result_cursor)
+{
+ /* Unused parameters */
+ (void)extractor;
+ (void)session;
+ (void)key;
+
+ result_cursor->set_key(result_cursor, value);
+ return (result_cursor->insert(result_cursor));
+}
+/*! [WT_EXTRACTOR] */
+
+int
+add_extractor(WT_CONNECTION *conn)
+{
+ int ret;
+
+ /*! [WT_EXTRACTOR register] */
+ static WT_EXTRACTOR my_extractor = {my_extract, NULL, NULL};
+
+ ret = conn->add_extractor(conn, "my_extractor", &my_extractor, NULL);
+ /*! [WT_EXTRACTOR register] */
+
+ return (ret);
+}
+
+int
+connection_ops(WT_CONNECTION *conn)
+{
+ int ret;
+
+#ifdef MIGHT_NOT_RUN
+ /*! [Load an extension] */
+ ret = conn->load_extension(conn, "my_extension.dll", NULL);
+
+ ret = conn->load_extension(conn,
+ "datasource/libdatasource.so",
+ "config=[device=/dev/sd1,alignment=64]");
+ /*! [Load an extension] */
+#endif
+
+ ret = add_collator(conn);
+ ret = add_extractor(conn);
+
+ /*! [Reconfigure a connection] */
+ ret = conn->reconfigure(conn, "eviction_target=75");
+ /*! [Reconfigure a connection] */
+
+ /*! [Get the database home directory] */
+ printf("The database home is %s\n", conn->get_home(conn));
+ /*! [Get the database home directory] */
+
+ /*! [Check if the database is newly created] */
+ if (conn->is_new(conn)) {
+ /* First time initialization. */
+ }
+ /*! [Check if the database is newly created] */
+
+ /*! [Validate a configuration string] */
+ /*
+ * Validate a configuration string for a WiredTiger function or method.
+ *
+ * Functions are specified by name (for example, "wiredtiger_open").
+ *
+ * Methods are specified using a concatenation of the handle name, a
+ * period and the method name (for example, session create would be
+ * "WT_SESSION.create" and cursor close would be WT_CURSOR.close").
+ */
+ ret = wiredtiger_config_validate(
+ NULL, NULL, "WT_SESSION.create", "allocation_size=32KB");
+ /*! [Validate a configuration string] */
+
+ {
+ /*! [Open a session] */
+ WT_SESSION *session;
+ ret = conn->open_session(conn, NULL, NULL, &session);
+ /*! [Open a session] */
+
+ ret = session_ops(session);
+ }
+
+ /*! [Configure method configuration] */
+ /*
+ * Applications opening a cursor for the data-source object "my_data"
+ * have an additional configuration option "entries", which is an
+ * integer type, defaults to 5, and must be an integer between 1 and 10.
+ *
+ * The method being configured is specified using a concatenation of the
+ * handle name, a period and the method name.
+ */
+ ret = conn->configure_method(conn,
+ "WT_SESSION.open_cursor",
+ "my_data:", "entries=5", "int", "min=1,max=10");
+
+ /*
+ * Applications opening a cursor for the data-source object "my_data"
+ * have an additional configuration option "devices", which is a list
+ * of strings.
+ */
+ ret = conn->configure_method(conn,
+ "WT_SESSION.open_cursor", "my_data:", "devices", "list", NULL);
+ /*! [Configure method configuration] */
+
+ /*! [Close a connection] */
+ ret = conn->close(conn, NULL);
+ /*! [Close a connection] */
+
+ return (ret);
+}
+
+int
+pack_ops(WT_SESSION *session)
+{
+ int ret;
+
+ {
+ /*! [Get the packed size] */
+ size_t size;
+ ret = wiredtiger_struct_size(session, &size, "iSh", 42, "hello", -3);
+ /*! [Get the packed size] */
+ }
+
+ {
+ /*! [Pack fields into a buffer] */
+ char buf[100];
+ ret = wiredtiger_struct_pack(
+ session, buf, sizeof(buf), "iSh", 42, "hello", -3);
+ /*! [Pack fields into a buffer] */
+
+ {
+ /*! [Unpack fields from a buffer] */
+ int i;
+ char *s;
+ short h;
+ ret = wiredtiger_struct_unpack(
+ session, buf, sizeof(buf), "iSh", &i, &s, &h);
+ /*! [Unpack fields from a buffer] */
+ }
+ }
+
+ return (ret);
+}
+
+int
+backup(WT_SESSION *session)
+{
+ char buf[1024];
+
+ /*! [backup]*/
+ WT_CURSOR *cursor;
+ const char *filename;
+ int ret;
+
+ /* Create the backup directory. */
+ ret = mkdir("/path/database.backup", 077);
+
+ /* Open the backup data source. */
+ ret = session->open_cursor(session, "backup:", NULL, NULL, &cursor);
+
+ /* Copy the list of files. */
+ while (
+ (ret = cursor->next(cursor)) == 0 &&
+ (ret = cursor->get_key(cursor, &filename)) == 0) {
+ (void)snprintf(buf, sizeof(buf),
+ "cp /path/database/%s /path/database.backup/%s",
+ filename, filename);
+ ret = system(buf);
+ }
+ if (ret == WT_NOTFOUND)
+ ret = 0;
+ if (ret != 0)
+ fprintf(stderr, "%s: cursor next(backup:) failed: %s\n",
+ progname, session->strerror(session, ret));
+
+ ret = cursor->close(cursor);
+ /*! [backup]*/
+
+ /*! [backup of a checkpoint]*/
+ ret = session->checkpoint(session, "drop=(from=June01),name=June01");
+ /*! [backup of a checkpoint]*/
+
+ return (ret);
+}
+
+int
+main(void)
+{
+ WT_CONNECTION *conn;
+ int ret;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (getenv("WIREDTIGER_HOME") == NULL) {
+ home = "WT_HOME";
+ ret = system("rm -rf WT_HOME && mkdir WT_HOME");
+ } else
+ home = NULL;
+
+ /*! [Open a connection] */
+ ret = wiredtiger_open(home, NULL,
+ "create,cache_size=5GB,log=(enabled,recover=on)", &conn);
+ /*! [Open a connection] */
+
+ if (ret == 0)
+ ret = connection_ops(conn);
+ /*
+ * The connection has been closed.
+ */
+
+#ifdef MIGHT_NOT_RUN
+ /*
+ * This example code gets run, and the compression libraries might not
+ * be installed, causing the open to fail. The documentation requires
+ * the code snippets, use #ifdef's to avoid running it.
+ */
+ /*! [Configure bzip2 extension] */
+ ret = wiredtiger_open(home, NULL,
+ "create,"
+ "extensions=[/usr/local/lib/libwiredtiger_bzip2.so]", &conn);
+ /*! [Configure bzip2 extension] */
+ if (ret == 0)
+ (void)conn->close(conn, NULL);
+
+ /*! [Configure lz4 extension] */
+ ret = wiredtiger_open(home, NULL,
+ "create,"
+ "extensions=[/usr/local/lib/libwiredtiger_lz4.so]", &conn);
+ /*! [Configure lz4 extension] */
+ if (ret == 0)
+ (void)conn->close(conn, NULL);
+
+ /*! [Configure snappy extension] */
+ ret = wiredtiger_open(home, NULL,
+ "create,"
+ "extensions=[/usr/local/lib/libwiredtiger_snappy.so]", &conn);
+ /*! [Configure snappy extension] */
+ if (ret == 0)
+ (void)conn->close(conn, NULL);
+
+ /*! [Configure zlib extension] */
+ ret = wiredtiger_open(home, NULL,
+ "create,"
+ "extensions=[/usr/local/lib/libwiredtiger_zlib.so]", &conn);
+ /*! [Configure zlib extension] */
+ if (ret == 0)
+ (void)conn->close(conn, NULL);
+
+ /*
+ * This example code gets run, and direct I/O might not be available,
+ * causing the open to fail. The documentation requires code snippets,
+ * use #ifdef's to avoid running it.
+ */
+ /* Might Not Run: direct I/O may not be available. */
+ /*! [Configure direct_io for data files] */
+ ret = wiredtiger_open(home, NULL, "create,direct_io=[data]", &conn);
+ /*! [Configure direct_io for data files] */
+ if (ret == 0)
+ (void)conn->close(conn, NULL);
+#endif
+
+ /*! [Configure file_extend] */
+ ret = wiredtiger_open(
+ home, NULL, "create,file_extend=(data=16MB)", &conn);
+ /*! [Configure file_extend] */
+ if (ret == 0)
+ (void)conn->close(conn, NULL);
+
+ /*! [Eviction configuration] */
+ /*
+ * Configure eviction to begin at 90% full, and run until the cache
+ * is only 75% dirty.
+ */
+ ret = wiredtiger_open(home, NULL,
+ "create,eviction_trigger=90,eviction_dirty_target=75", &conn);
+ /*! [Eviction configuration] */
+ if (ret == 0)
+ (void)conn->close(conn, NULL);
+
+ /*! [Eviction worker configuration] */
+ /* Configure up to four eviction threads */
+ ret = wiredtiger_open(home, NULL,
+ "create,eviction_trigger=90,eviction=(threads_max=4)", &conn);
+ /*! [Eviction worker configuration] */
+ if (ret == 0)
+ (void)conn->close(conn, NULL);
+
+ /*! [Statistics configuration] */
+ ret = wiredtiger_open(home, NULL, "create,statistics=(all)", &conn);
+ /*! [Statistics configuration] */
+ if (ret == 0)
+ (void)conn->close(conn, NULL);
+
+ /*! [Statistics logging] */
+ ret = wiredtiger_open(
+ home, NULL, "create,statistics_log=(wait=30)", &conn);
+ /*! [Statistics logging] */
+ if (ret == 0)
+ (void)conn->close(conn, NULL);
+
+ /*! [Statistics logging with a table] */
+ ret = wiredtiger_open(home, NULL,
+ "create, statistics_log=("
+ "sources=(\"lsm:table1\",\"lsm:table2\"), wait=5)",
+ &conn);
+ /*! [Statistics logging with a table] */
+ if (ret == 0)
+ (void)conn->close(conn, NULL);
+
+ /*! [Statistics logging with all tables] */
+ ret = wiredtiger_open(home, NULL,
+ "create, statistics_log=(sources=(\"lsm:\"), wait=5)",
+ &conn);
+ /*! [Statistics logging with all tables] */
+ if (ret == 0)
+ (void)conn->close(conn, NULL);
+
+#ifdef MIGHT_NOT_RUN
+ /*
+ * This example code gets run, and a non-existent log file path might
+ * cause the open to fail. The documentation requires code snippets,
+ * use #ifdef's to avoid running it.
+ */
+ /*! [Statistics logging with path] */
+ ret = wiredtiger_open(home, NULL,
+ "create,"
+ "statistics_log=(wait=120,path=/log/log.%m.%d.%y)", &conn);
+ /*! [Statistics logging with path] */
+ if (ret == 0)
+ (void)conn->close(conn, NULL);
+
+ /*
+ * Don't run this code, because memory checkers get very upset when we
+ * leak memory.
+ */
+ (void)wiredtiger_open(home, NULL, "create", &conn);
+ /*! [Connection close leaking memory] */
+ ret = conn->close(conn, "leak_memory=true");
+ /*! [Connection close leaking memory] */
+#endif
+
+ /*! [Get the WiredTiger library version #1] */
+ printf("WiredTiger version %s\n", wiredtiger_version(NULL, NULL, NULL));
+ /*! [Get the WiredTiger library version #1] */
+
+ {
+ /*! [Get the WiredTiger library version #2] */
+ int major_v, minor_v, patch;
+ (void)wiredtiger_version(&major_v, &minor_v, &patch);
+ printf("WiredTiger version is %d, %d (patch %d)\n",
+ major_v, minor_v, patch);
+ /*! [Get the WiredTiger library version #2] */
+ }
+
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_async.c b/src/third_party/wiredtiger/examples/c/ex_async.c
new file mode 100644
index 00000000000..584c3e54b87
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_async.c
@@ -0,0 +1,224 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_async.c
+ * demonstrates how to use the asynchronous API.
+ */
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#include "windows_shim.h"
+#endif
+
+#include <wiredtiger.h>
+
+#if defined(_lint)
+#define ATOMIC_ADD(v, val) ((v) += (val), (v))
+#elif defined(_WIN32)
+#define ATOMIC_ADD(v, val) (_InterlockedExchangeAdd(&(v), val) + val)
+#else
+#define ATOMIC_ADD(v, val) __sync_add_and_fetch(&(v), val)
+#endif
+
+static const char * const home = NULL;
+static int global_error = 0;
+
+/*! [async example callback implementation] */
+typedef struct {
+ WT_ASYNC_CALLBACK iface;
+ uint32_t num_keys;
+} ASYNC_KEYS;
+
+static int
+async_callback(WT_ASYNC_CALLBACK *cb,
+ WT_ASYNC_OP *op, int wiredtiger_error, uint32_t flags)
+{
+ ASYNC_KEYS *asynckey = (ASYNC_KEYS *)cb;
+ WT_ASYNC_OPTYPE type;
+ WT_ITEM k, v;
+ const char *key, *value;
+ uint64_t id;
+ int ret;
+
+ (void)flags; /* Unused */
+
+ ret = 0;
+
+ /*! [async get type] */
+ /* Retrieve the operation's WT_ASYNC_OPTYPE type. */
+ type = op->get_type(op);
+ /*! [async get type] */
+
+ /*! [async get identifier] */
+ /* Retrieve the operation's 64-bit identifier. */
+ id = op->get_id(op);
+ /*! [async get identifier] */
+
+ /* Check for a WiredTiger error. */
+ if (wiredtiger_error != 0) {
+ fprintf(stderr,
+ "ID %" PRIu64 " error %d: %s\n",
+ id, wiredtiger_error,
+ wiredtiger_strerror(wiredtiger_error));
+ global_error = wiredtiger_error;
+ return (1);
+ }
+
+ /* If doing a search, retrieve the key/value pair. */
+ if (type == WT_AOP_SEARCH) {
+ /*! [async get the operation's string key] */
+ ret = op->get_key(op, &k);
+ key = k.data;
+ /*! [async get the operation's string key] */
+ /*! [async get the operation's string value] */
+ ret = op->get_value(op, &v);
+ value = v.data;
+ /*! [async get the operation's string value] */
+ ATOMIC_ADD(asynckey->num_keys, 1);
+ printf("Id %" PRIu64 " got record: %s : %s\n", id, key, value);
+ }
+ return (ret);
+}
+/*! [async example callback implementation] */
+
+static ASYNC_KEYS ex_asynckeys = { {async_callback}, 0 };
+
+#define MAX_KEYS 15
+
+int
+main(void)
+{
+ WT_ASYNC_OP *op;
+ WT_CONNECTION *conn;
+ WT_SESSION *session;
+ int i, ret;
+ char k[MAX_KEYS][16], v[MAX_KEYS][16];
+
+ /*! [async example connection] */
+ ret = wiredtiger_open(home, NULL,
+ "create,cache_size=100MB,"
+ "async=(enabled=true,ops_max=20,threads=2)", &conn);
+ /*! [async example connection] */
+
+ /*! [async example table create] */
+ ret = conn->open_session(conn, NULL, NULL, &session);
+ ret = session->create(
+ session, "table:async", "key_format=S,value_format=S");
+ /*! [async example table create] */
+
+ /* Insert a set of keys asynchronously. */
+ for (i = 0; i < MAX_KEYS; i++) {
+ /*! [async handle allocation] */
+ while ((ret = conn->async_new_op(conn,
+ "table:async", NULL, &ex_asynckeys.iface, &op)) != 0) {
+ /*
+ * If we used up all the handles, pause and retry to
+ * give the workers a chance to catch up.
+ */
+ fprintf(stderr,
+ "asynchronous operation handle not available\n");
+ if (ret == EBUSY)
+ sleep(1);
+ else
+ return (ret);
+ }
+ /*! [async handle allocation] */
+
+ /*! [async insert] */
+ /*
+ * Set the operation's string key and value, and then do
+ * an asynchronous insert.
+ */
+ /*! [async set the operation's string key] */
+ snprintf(k[i], sizeof(k), "key%d", i);
+ op->set_key(op, k[i]);
+ /*! [async set the operation's string key] */
+
+ /*! [async set the operation's string value] */
+ snprintf(v[i], sizeof(v), "value%d", i);
+ op->set_value(op, v[i]);
+ /*! [async set the operation's string value] */
+
+ ret = op->insert(op);
+ /*! [async insert] */
+ }
+
+ /*! [async flush] */
+ /* Wait for all outstanding operations to complete. */
+ ret = conn->async_flush(conn);
+ /*! [async flush] */
+
+ /*! [async compaction] */
+ /*
+ * Compact a table asynchronously, limiting the run-time to 5 minutes.
+ */
+ ret = conn->async_new_op(
+ conn, "table:async", "timeout=300", &ex_asynckeys.iface, &op);
+ ret = op->compact(op);
+ /*! [async compaction] */
+
+ /* Search for the keys we just inserted, asynchronously. */
+ for (i = 0; i < MAX_KEYS; i++) {
+ while ((ret = conn->async_new_op(conn,
+ "table:async", NULL, &ex_asynckeys.iface, &op)) != 0) {
+ /*
+ * If we used up all the handles, pause and retry to
+ * give the workers a chance to catch up.
+ */
+ fprintf(stderr,
+ "asynchronous operation handle not available\n");
+ if (ret == EBUSY)
+ sleep(1);
+ else
+ return (ret);
+ }
+
+ /*! [async search] */
+ /*
+ * Set the operation's string key and value, and then do
+ * an asynchronous search.
+ */
+ snprintf(k[i], sizeof(k), "key%d", i);
+ op->set_key(op, k[i]);
+ ret = op->search(op);
+ /*! [async search] */
+ }
+
+ /*
+ * Connection close automatically does an async_flush so it will wait
+ * for all queued search operations to complete.
+ */
+ ret = conn->close(conn, NULL);
+
+ printf("Searched for %d keys\n", ex_asynckeys.num_keys);
+
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_backup.c b/src/third_party/wiredtiger/examples/c/ex_backup.c
new file mode 100644
index 00000000000..12eeaa4b7c3
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_backup.c
@@ -0,0 +1,326 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_backup.c
+ * demonstrates how to use incremental backup and log files.
+ */
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef _WIN32
+#include <unistd.h>
+#else
+/* snprintf is not supported on <= VS2013 */
+#define snprintf _snprintf
+#endif
+
+#include <wiredtiger.h>
+
+static const char * const home = "WT_HOME_LOG";
+static const char * const home_full = "WT_HOME_LOG_FULL";
+static const char * const home_incr = "WT_HOME_LOG_INCR";
+
+static const char * const full_out = "./backup_full";
+static const char * const incr_out = "./backup_incr";
+
+static const char * const uri = "table:logtest";
+
+#define CONN_CONFIG \
+ "create,cache_size=100MB,log=(archive=false,enabled=true,file_max=100K)"
+#define MAX_ITERATIONS 5
+#define MAX_KEYS 10000
+
+static int
+compare_backups(int i)
+{
+ int ret;
+ char buf[1024], msg[8];
+
+ /*
+ * We run 'wt dump' on both the full backup directory and the
+ * incremental backup directory for this iteration. Since running
+ * 'wt' runs recovery and makes both directories "live", we need
+ * a new directory for each iteration.
+ *
+ * If i == 0, we're comparing against the main, original directory
+ * with the final incremental directory.
+ */
+ if (i == 0)
+ (void)snprintf(buf, sizeof(buf),
+ "../../wt -R -h %s dump logtest > %s.%d",
+ home, full_out, i);
+ else
+ (void)snprintf(buf, sizeof(buf),
+ "../../wt -R -h %s.%d dump logtest > %s.%d",
+ home_full, i, full_out, i);
+ ret = system(buf);
+ /*
+ * Now run dump on the incremental directory.
+ */
+ (void)snprintf(buf, sizeof(buf),
+ "../../wt -R -h %s.%d dump logtest > %s.%d",
+ home_incr, i, incr_out, i);
+ ret = system(buf);
+
+ /*
+ * Compare the files.
+ */
+ (void)snprintf(buf, sizeof(buf), "cmp %s.%d %s.%d",
+ full_out, i, incr_out, i);
+ ret = system(buf);
+ if (i == 0)
+ (void)strncpy(msg, "MAIN", sizeof(msg));
+ else
+ snprintf(msg, sizeof(msg), "%d", i);
+ printf(
+ "Iteration %s: Tables %s.%d and %s.%d %s\n",
+ msg, full_out, i, incr_out, i, ret == 0 ? "identical" : "differ");
+ if (ret != 0)
+ exit (1);
+
+ /*
+ * If they compare successfully, clean up.
+ */
+ if (i != 0) {
+ (void)snprintf(buf, sizeof(buf),
+ "rm -rf %s.%d %s.%d %s.%d %s.%d",
+ home_full, i, home_incr, i, full_out, i, incr_out, i);
+ ret = system(buf);
+ }
+ return (ret);
+}
+
+/*
+ * Set up all the directories needed for the test. We have a full backup
+ * directory for each iteration and an incremental backup for each iteration.
+ * That way we can compare the full and incremental each time through.
+ */
+static int
+setup_directories(void)
+{
+ int i, ret;
+ char buf[1024];
+
+ for (i = 0; i < MAX_ITERATIONS; i++) {
+ /*
+ * For incremental backups we need 0-N. The 0 incremental
+ * directory will compare with the original at the end.
+ */
+ snprintf(buf, sizeof(buf), "rm -rf %s.%d && mkdir %s.%d",
+ home_incr, i, home_incr, i);
+ if ((ret = system(buf)) != 0) {
+ fprintf(stderr, "%s: failed ret %d\n", buf, ret);
+ return (ret);
+ }
+ if (i == 0)
+ continue;
+ /*
+ * For full backups we need 1-N.
+ */
+ snprintf(buf, sizeof(buf), "rm -rf %s.%d && mkdir %s.%d",
+ home_full, i, home_full, i);
+ if ((ret = system(buf)) != 0) {
+ fprintf(stderr, "%s: failed ret %d\n", buf, ret);
+ return (ret);
+ }
+ }
+ return (0);
+}
+
+static int
+add_work(WT_SESSION *session, int iter)
+{
+ WT_CURSOR *cursor;
+ int i, ret;
+ char k[32], v[32];
+
+ ret = session->open_cursor(session, uri, NULL, NULL, &cursor);
+ /*
+ * Perform some operations with individual auto-commit transactions.
+ */
+ for (i = 0; i < MAX_KEYS; i++) {
+ snprintf(k, sizeof(k), "key.%d.%d", iter, i);
+ snprintf(v, sizeof(v), "value.%d.%d", iter, i);
+ cursor->set_key(cursor, k);
+ cursor->set_value(cursor, v);
+ ret = cursor->insert(cursor);
+ }
+ ret = cursor->close(cursor);
+ return (ret);
+}
+
+static int
+take_full_backup(WT_SESSION *session, int i)
+{
+ WT_CURSOR *cursor;
+ int j, ret;
+ char buf[1024], h[256];
+ const char *filename, *hdir;
+
+ /*
+ * First time through we take a full backup into the incremental
+ * directories. Otherwise only into the appropriate full directory.
+ */
+ if (i != 0) {
+ snprintf(h, sizeof(h), "%s.%d", home_full, i);
+ hdir = h;
+ } else
+ hdir = home_incr;
+ ret = session->open_cursor(session, "backup:", NULL, NULL, &cursor);
+
+ while ((ret = cursor->next(cursor)) == 0) {
+ ret = cursor->get_key(cursor, &filename);
+ if (i == 0)
+ /*
+ * Take a full backup into each incremental directory.
+ */
+ for (j = 0; j < MAX_ITERATIONS; j++) {
+ snprintf(h, sizeof(h), "%s.%d", home_incr, j);
+ (void)snprintf(buf, sizeof(buf),
+ "cp %s/%s %s/%s",
+ home, filename, h, filename);
+ ret = system(buf);
+ }
+ else {
+ snprintf(h, sizeof(h), "%s.%d", home_full, i);
+ (void)snprintf(buf, sizeof(buf), "cp %s/%s %s/%s",
+ home, filename, hdir, filename);
+ ret = system(buf);
+ }
+ }
+ if (ret != WT_NOTFOUND)
+ fprintf(stderr,
+ "WT_CURSOR.next: %s\n", session->strerror(session, ret));
+ ret = cursor->close(cursor);
+ return (ret);
+}
+
+static int
+take_incr_backup(WT_SESSION *session, int i)
+{
+ WT_CURSOR *cursor;
+ int j, ret;
+ char buf[1024], h[256];
+ const char *filename;
+
+ ret = session->open_cursor(session, "backup:",
+ NULL, "target=(\"log:\")", &cursor);
+
+ while ((ret = cursor->next(cursor)) == 0) {
+ ret = cursor->get_key(cursor, &filename);
+ /*
+ * Copy into the 0 incremental directory and then each of the
+ * incremental directories for this iteration and later.
+ */
+ snprintf(h, sizeof(h), "%s.0", home_incr);
+ (void)snprintf(buf, sizeof(buf), "cp %s/%s %s/%s",
+ home, filename, h, filename);
+ ret = system(buf);
+ for (j = i; j < MAX_ITERATIONS; j++) {
+ snprintf(h, sizeof(h), "%s.%d", home_incr, j);
+ (void)snprintf(buf, sizeof(buf), "cp %s/%s %s/%s",
+ home, filename, h, filename);
+ ret = system(buf);
+ }
+ }
+ if (ret != WT_NOTFOUND)
+ fprintf(stderr,
+ "WT_CURSOR.next: %s\n", session->strerror(session, ret));
+ ret = 0;
+ /*
+ * With an incremental cursor, we want to truncate on the backup
+ * cursor to archive the logs. Only do this if the copy process
+ * was entirely successful.
+ */
+ ret = session->truncate(session, "log:", cursor, NULL, NULL);
+ ret = cursor->close(cursor);
+ return (ret);
+}
+
+int
+main(void)
+{
+ WT_CONNECTION *wt_conn;
+ WT_SESSION *session;
+ int i, ret;
+ char cmd_buf[256];
+
+ snprintf(cmd_buf, sizeof(cmd_buf), "rm -rf %s && mkdir %s", home, home);
+ if ((ret = system(cmd_buf)) != 0) {
+ fprintf(stderr, "%s: failed ret %d\n", cmd_buf, ret);
+ return (ret);
+ }
+ if ((ret = wiredtiger_open(home, NULL, CONN_CONFIG, &wt_conn)) != 0) {
+ fprintf(stderr, "Error connecting to %s: %s\n",
+ home, wiredtiger_strerror(ret));
+ return (ret);
+ }
+
+ ret = setup_directories();
+ ret = wt_conn->open_session(wt_conn, NULL, NULL, &session);
+ ret = session->create(session, uri, "key_format=S,value_format=S");
+ printf("Adding initial data\n");
+ ret = add_work(session, 0);
+
+ printf("Taking initial backup\n");
+ ret = take_full_backup(session, 0);
+
+ ret = session->checkpoint(session, NULL);
+
+ for (i = 1; i < MAX_ITERATIONS; i++) {
+ printf("Iteration %d: adding data\n", i);
+ ret = add_work(session, i);
+ ret = session->checkpoint(session, NULL);
+ /*
+ * The full backup here is only needed for testing and
+ * comparison purposes. A normal incremental backup
+ * procedure would not include this.
+ */
+ printf("Iteration %d: taking full backup\n", i);
+ ret = take_full_backup(session, i);
+ /*
+ * Taking the incremental backup also calls truncate
+ * to archive the log files, if the copies were successful.
+ * See that function for details on that call.
+ */
+ printf("Iteration %d: taking incremental backup\n", i);
+ ret = take_incr_backup(session, i);
+
+ printf("Iteration %d: dumping and comparing data\n", i);
+ ret = compare_backups(i);
+ }
+
+ /*
+ * Close the connection. We're done and want to run the final
+ * comparison between the incremental and original.
+ */
+ ret = wt_conn->close(wt_conn, NULL);
+ printf("Final comparison: dumping and comparing data\n");
+ ret = compare_backups(0);
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_call_center.c b/src/third_party/wiredtiger/examples/c/ex_call_center.c
new file mode 100644
index 00000000000..d401507d165
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_call_center.c
@@ -0,0 +1,249 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_call_center.c
+ * This is an example application that demonstrates how to map a
+ * moderately complex SQL application into WiredTiger.
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <wiredtiger.h>
+
+static const char *home;
+
+/*! [call-center decl] */
+/*
+ * In SQL, the tables are described as follows:
+ *
+ * CREATE TABLE Customers(id INTEGER PRIMARY KEY,
+ * name VARCHAR(30), address VARCHAR(50), phone VARCHAR(15))
+ * CREATE INDEX CustomersPhone ON Customers(phone)
+ *
+ * CREATE TABLE Calls(id INTEGER PRIMARY KEY, call_date DATE,
+ * cust_id INTEGER, emp_id INTEGER, call_type VARCHAR(12),
+ * notes VARCHAR(25))
+ * CREATE INDEX CallsCustDate ON Calls(cust_id, call_date)
+ *
+ * In this example, both tables will use record numbers for their IDs, which
+ * will be the key. The C structs for the records are as follows.
+ */
+
+/* Customer records. */
+typedef struct {
+ uint64_t id;
+ const char *name;
+ const char *address;
+ const char *phone;
+} CUSTOMER;
+
+/* Call records. */
+typedef struct {
+ uint64_t id;
+ uint64_t call_date;
+ uint64_t cust_id;
+ uint64_t emp_id;
+ const char *call_type;
+ const char *notes;
+} CALL;
+/*! [call-center decl] */
+
+int
+main(void)
+{
+ int count, exact, ret;
+ WT_CONNECTION *conn;
+ WT_SESSION *session;
+ WT_CURSOR *cursor;
+ CUSTOMER cust, *custp, cust_sample[] = {
+ { 0, "Professor Oak", "LeafGreen Avenue", "123-456-7890" },
+ { 0, "Lorelei", "Sevii Islands", "098-765-4321" },
+ { 0, NULL, NULL, NULL }
+ };
+ CALL call, *callp, call_sample[] = {
+ { 0, 32, 1, 2, "billing", "unavailable" },
+ { 0, 33, 1, 2, "billing", "available" },
+ { 0, 34, 1, 2, "reminder", "unavailable" },
+ { 0, 35, 1, 2, "reminder", "available" },
+ { 0, 0, 0, 0, NULL, NULL }
+ };
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (getenv("WIREDTIGER_HOME") == NULL) {
+ home = "WT_HOME";
+ ret = system("rm -rf WT_HOME && mkdir WT_HOME");
+ } else
+ home = NULL;
+
+ if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0) {
+ fprintf(stderr, "Error connecting to %s: %s\n",
+ home, wiredtiger_strerror(ret));
+ return (1);
+ }
+ /* Note: further error checking omitted for clarity. */
+
+ /*! [call-center work] */
+ ret = conn->open_session(conn, NULL, NULL, &session);
+
+ /*
+ * Create the customers table, give names and types to the columns.
+ * The columns will be stored in two groups: "main" and "address",
+ * created below.
+ */
+ ret = session->create(session, "table:customers",
+ "key_format=r,"
+ "value_format=SSS,"
+ "columns=(id,name,address,phone),"
+ "colgroups=(main,address)");
+
+ /* Create the main column group with value columns except address. */
+ ret = session->create(session,
+ "colgroup:customers:main", "columns=(name,phone)");
+
+ /* Create the address column group with just the address. */
+ ret = session->create(session,
+ "colgroup:customers:address", "columns=(address)");
+
+ /* Create an index on the customer table by phone number. */
+ ret = session->create(session,
+ "index:customers:phone", "columns=(phone)");
+
+ /* Populate the customers table with some data. */
+ ret = session->open_cursor(
+ session, "table:customers", NULL, "append", &cursor);
+ for (custp = cust_sample; custp->name != NULL; custp++) {
+ cursor->set_value(cursor,
+ custp->name, custp->address, custp->phone);
+ ret = cursor->insert(cursor);
+ }
+ ret = cursor->close(cursor);
+
+ /*
+ * Create the calls table, give names and types to the columns. All the
+ * columns will be stored together, so no column groups are declared.
+ */
+ ret = session->create(session, "table:calls",
+ "key_format=r,"
+ "value_format=qrrSS,"
+ "columns=(id,call_date,cust_id,emp_id,call_type,notes)");
+
+ /*
+ * Create an index on the calls table with a composite key of cust_id
+ * and call_date.
+ */
+ ret = session->create(session, "index:calls:cust_date",
+ "columns=(cust_id,call_date)");
+
+ /* Populate the calls table with some data. */
+ ret = session->open_cursor(
+ session, "table:calls", NULL, "append", &cursor);
+ for (callp = call_sample; callp->call_type != NULL; callp++) {
+ cursor->set_value(cursor, callp->call_date, callp->cust_id,
+ callp->emp_id, callp->call_type, callp->notes);
+ ret = cursor->insert(cursor);
+ }
+ ret = cursor->close(cursor);
+
+ /*
+ * First query: a call arrives. In SQL:
+ *
+ * SELECT id, name FROM Customers WHERE phone=?
+ *
+ * Use the cust_phone index, lookup by phone number to fill the
+ * customer record. The cursor will have a key format of "S" for a
+ * string because the cust_phone index has a single column ("phone"),
+ * which is of type "S".
+ *
+ * Specify the columns we want: the customer ID and the name. This
+ * means the cursor's value format will be "rS".
+ */
+ ret = session->open_cursor(session,
+ "index:customers:phone(id,name)", NULL, NULL, &cursor);
+ cursor->set_key(cursor, "123-456-7890");
+ ret = cursor->search(cursor);
+ if (ret == 0) {
+ ret = cursor->get_value(cursor, &cust.id, &cust.name);
+ printf("Read customer record for %s (ID %" PRIu64 ")\n",
+ cust.name, cust.id);
+ }
+ ret = cursor->close(cursor);
+
+ /*
+ * Next query: get the recent order history. In SQL:
+ *
+ * SELECT * FROM Calls WHERE cust_id=? ORDER BY call_date DESC LIMIT 3
+ *
+ * Use the call_cust_date index to find the matching calls. Since it is
+ * is in increasing order by date for a given customer, we want to start
+ * with the last record for the customer and work backwards.
+ *
+ * Specify a subset of columns to be returned. (Note that if these were
+ * all covered by the index, the primary would not have to be accessed.)
+ * Stop after getting 3 records.
+ */
+ ret = session->open_cursor(session,
+ "index:calls:cust_date(cust_id,call_type,notes)",
+ NULL, NULL, &cursor);
+
+ /*
+ * The keys in the index are (cust_id,call_date) -- we want the largest
+ * call date for a given cust_id. Search for (cust_id+1,0), then work
+ * backwards.
+ */
+ cust.id = 1;
+ cursor->set_key(cursor, cust.id + 1, 0);
+ ret = cursor->search_near(cursor, &exact);
+
+ /*
+ * If the table is empty, search_near will return WT_NOTFOUND, else the
+ * cursor will be positioned on a matching key if one exists, or an
+ * adjacent key if one does not. If the positioned key is equal to or
+ * larger than the search key, go back one.
+ */
+ if (ret == 0 && exact >= 0)
+ ret = cursor->prev(cursor);
+ for (count = 0; ret == 0 && count < 3; ++count) {
+ ret = cursor->get_value(cursor,
+ &call.cust_id, &call.call_type, &call.notes);
+ if (call.cust_id != cust.id)
+ break;
+ printf("Call record: customer %" PRIu64 " (%s: %s)\n",
+ call.cust_id, call.call_type, call.notes);
+ ret = cursor->prev(cursor);
+ }
+ /*! [call-center work] */
+
+ ret = conn->close(conn, NULL);
+
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_config.c b/src/third_party/wiredtiger/examples/c/ex_config.c
new file mode 100644
index 00000000000..2ac8198176c
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_config.c
@@ -0,0 +1,91 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_config.c
+ * This is an example demonstrating how to configure various database and
+ * table properties.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <wiredtiger.h>
+
+static const char *home;
+
+int
+main(void)
+{
+ int ret;
+ WT_CONNECTION *conn;
+ WT_SESSION *session;
+ WT_CURSOR *cursor;
+ const char *key, *value;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (getenv("WIREDTIGER_HOME") == NULL) {
+ home = "WT_HOME";
+ ret = system("rm -rf WT_HOME && mkdir WT_HOME");
+ } else
+ home = NULL;
+
+ /*! [configure cache size] */
+ if ((ret = wiredtiger_open(home, NULL,
+ "create,cache_size=500M", &conn)) != 0)
+ fprintf(stderr, "Error connecting to %s: %s\n",
+ home, wiredtiger_strerror(ret));
+ /*! [configure cache size] */
+
+ /*! [create a table] */
+ ret = conn->open_session(conn, NULL, NULL, &session);
+
+ ret = session->create(session,
+ "table:access", "key_format=S,value_format=S");
+ /*! [create a table] */
+
+ /*! [transaction] */
+ ret = session->begin_transaction(session, "priority=100,name=mytxn");
+
+ ret = session->open_cursor(session, "config:", NULL, NULL, &cursor);
+
+ while ((ret = cursor->next(cursor)) == 0) {
+ ret = cursor->get_key(cursor, &key);
+ ret = cursor->get_value(cursor, &value);
+ printf("configuration value: %s = %s\n", key, value);
+ }
+
+ ret = session->commit_transaction(session, NULL);
+ /*! [transaction] */
+
+ ret = conn->close(conn, NULL);
+
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_config_parse.c b/src/third_party/wiredtiger/examples/c/ex_config_parse.c
new file mode 100644
index 00000000000..124eff21130
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_config_parse.c
@@ -0,0 +1,166 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_config_parse.c
+ * This is an example demonstrating how to parse WiredTiger compatible
+ * configuration strings.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <wiredtiger.h>
+
+int
+main(void)
+{
+ int ret;
+
+ /*! [Create a configuration parser] */
+ WT_CONFIG_ITEM k, v;
+ WT_CONFIG_PARSER *parser;
+ const char *config_string =
+ "path=/dev/loop,page_size=1024,log=(archive=true,file_max=20MB)";
+
+ if ((ret = wiredtiger_config_parser_open(
+ NULL, config_string, strlen(config_string), &parser)) != 0) {
+ fprintf(stderr, "Error creating configuration parser: %s\n",
+ wiredtiger_strerror(ret));
+ return (ret);
+ }
+ if ((ret = parser->close(parser)) != 0) {
+ fprintf(stderr, "Error closing configuration parser: %s\n",
+ wiredtiger_strerror(ret));
+ return (ret);
+ }
+ /*! [Create a configuration parser] */
+
+ if ((ret = wiredtiger_config_parser_open(
+ NULL, config_string, strlen(config_string), &parser)) != 0) {
+ fprintf(stderr, "Error creating configuration parser: %s\n",
+ wiredtiger_strerror(ret));
+ return (ret);
+ }
+
+ {
+ /*! [get] */
+ int64_t my_page_size;
+ /*
+ * Retrieve the value of the integer configuration string "page_size".
+ */
+ if ((ret = parser->get(parser, "page_size", &v)) != 0) {
+ fprintf(stderr,
+ "page_size configuration: %s", wiredtiger_strerror(ret));
+ return (ret);
+ }
+ my_page_size = v.val;
+ /*! [get] */
+
+ ret = parser->close(parser);
+
+ (void)my_page_size;
+ }
+
+ {
+ if ((ret = wiredtiger_config_parser_open(
+ NULL, config_string, strlen(config_string), &parser)) != 0) {
+ fprintf(stderr, "Error creating configuration parser: %s\n",
+ wiredtiger_strerror(ret));
+ return (ret);
+ }
+ /*! [next] */
+ /*
+ * Retrieve and print the values of the configuration strings.
+ */
+ while ((ret = parser->next(parser, &k, &v)) == 0) {
+ printf("%.*s:", (int)k.len, k.str);
+ if (v.type == WT_CONFIG_ITEM_NUM)
+ printf("%d\n", (int)v.val);
+ else
+ printf("%.*s\n", (int)v.len, v.str);
+ }
+ /*! [next] */
+ ret = parser->close(parser);
+ }
+
+ if ((ret = wiredtiger_config_parser_open(
+ NULL, config_string, strlen(config_string), &parser)) != 0) {
+ fprintf(stderr, "Error creating configuration parser: %s\n",
+ wiredtiger_strerror(ret));
+ return (ret);
+ }
+
+ /*! [nested get] */
+ /*
+ * Retrieve the value of the nested log file_max configuration string
+ * using dot shorthand. Utilize the configuration parsing automatic
+ * conversion of value strings into an integer.
+ */
+ v.type = WT_CONFIG_ITEM_NUM;
+ if ((ret = parser->get(parser, "log.file_max", &v)) != 0) {
+ fprintf(stderr,
+ "log.file_max configuration: %s", wiredtiger_strerror(ret));
+ return (ret);
+ }
+ printf("log file max: %d\n", (int)v.val);
+ /*! [nested get] */
+ ret = parser->close(parser);
+
+ if ((ret = wiredtiger_config_parser_open(
+ NULL, config_string, strlen(config_string), &parser)) != 0) {
+ fprintf(stderr, "Error creating configuration parser: %s\n",
+ wiredtiger_strerror(ret));
+ return (ret);
+ }
+ /*! [nested traverse] */
+ {
+ WT_CONFIG_PARSER *sub_parser;
+ while ((ret = parser->next(parser, &k, &v)) == 0) {
+ if (v.type == WT_CONFIG_ITEM_STRUCT) {
+ printf("Found nested configuration: %.*s\n",
+ (int)k.len, k.str);
+ if ((ret = wiredtiger_config_parser_open(
+ NULL, v.str, v.len, &sub_parser)) != 0) {
+ fprintf(stderr,
+ "Error creating nested configuration "
+ "parser: %s\n",
+ wiredtiger_strerror(ret));
+ ret = parser->close(parser);
+ return (ret);
+ }
+ while ((ret = sub_parser->next(
+ sub_parser, &k, &v)) == 0)
+ printf("\t%.*s\n", (int)k.len, k.str);
+ ret = sub_parser->close(sub_parser);
+ }
+ }
+ /*! [nested traverse] */
+ ret = parser->close(parser);
+ }
+
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_cursor.c b/src/third_party/wiredtiger/examples/c/ex_cursor.c
new file mode 100644
index 00000000000..67c945ebc0b
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_cursor.c
@@ -0,0 +1,228 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_cursor.c
+ * This is an example demonstrating some cursor types and operations.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <wiredtiger.h>
+
+int cursor_reset(WT_CURSOR *cursor);
+int cursor_forward_scan(WT_CURSOR *cursor);
+int cursor_reverse_scan(WT_CURSOR *cursor);
+int cursor_search(WT_CURSOR *cursor);
+int cursor_search_near(WT_CURSOR *cursor);
+int cursor_insert(WT_CURSOR *cursor);
+int cursor_update(WT_CURSOR *cursor);
+int cursor_remove(WT_CURSOR *cursor);
+
+static const char *home;
+
+/*! [cursor next] */
+int
+cursor_forward_scan(WT_CURSOR *cursor)
+{
+ const char *key, *value;
+ int ret;
+
+ while ((ret = cursor->next(cursor)) == 0) {
+ ret = cursor->get_key(cursor, &key);
+ ret = cursor->get_value(cursor, &value);
+ }
+ return (ret);
+}
+/*! [cursor next] */
+
+/*! [cursor prev] */
+int
+cursor_reverse_scan(WT_CURSOR *cursor)
+{
+ const char *key, *value;
+ int ret;
+
+ while ((ret = cursor->prev(cursor)) == 0) {
+ ret = cursor->get_key(cursor, &key);
+ ret = cursor->get_value(cursor, &value);
+ }
+ return (ret);
+}
+/*! [cursor prev] */
+
+/*! [cursor reset] */
+int
+cursor_reset(WT_CURSOR *cursor)
+{
+ return (cursor->reset(cursor));
+}
+/*! [cursor reset] */
+
+/*! [cursor search] */
+int
+cursor_search(WT_CURSOR *cursor)
+{
+ const char *value;
+ int ret;
+
+ cursor->set_key(cursor, "foo");
+
+ if ((ret = cursor->search(cursor)) == 0)
+ ret = cursor->get_value(cursor, &value);
+
+ return (ret);
+}
+/*! [cursor search] */
+
+/*! [cursor search near] */
+int
+cursor_search_near(WT_CURSOR *cursor)
+{
+ const char *key, *value;
+ int exact, ret;
+
+ cursor->set_key(cursor, "foo");
+
+ if ((ret = cursor->search_near(cursor, &exact)) == 0) {
+ switch (exact) {
+ case -1: /* Returned key smaller than search key */
+ ret = cursor->get_key(cursor, &key);
+ break;
+ case 0: /* Exact match found */
+ break;
+ case 1: /* Returned key larger than search key */
+ ret = cursor->get_key(cursor, &key);
+ break;
+ }
+
+ ret = cursor->get_value(cursor, &value);
+ }
+
+ return (ret);
+}
+/*! [cursor search near] */
+
+/*! [cursor insert] */
+int
+cursor_insert(WT_CURSOR *cursor)
+{
+ cursor->set_key(cursor, "foo");
+ cursor->set_value(cursor, "bar");
+
+ return (cursor->insert(cursor));
+}
+/*! [cursor insert] */
+
+/*! [cursor update] */
+int
+cursor_update(WT_CURSOR *cursor)
+{
+ cursor->set_key(cursor, "foo");
+ cursor->set_value(cursor, "newbar");
+
+ return (cursor->update(cursor));
+}
+/*! [cursor update] */
+
+/*! [cursor remove] */
+int
+cursor_remove(WT_CURSOR *cursor)
+{
+ cursor->set_key(cursor, "foo");
+ return (cursor->remove(cursor));
+}
+/*! [cursor remove] */
+
+int
+main(void)
+{
+ WT_CONNECTION *conn;
+ WT_CURSOR *cursor;
+ WT_SESSION *session;
+ int ret;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (getenv("WIREDTIGER_HOME") == NULL) {
+ home = "WT_HOME";
+ ret = system("rm -rf WT_HOME && mkdir WT_HOME");
+ } else
+ home = NULL;
+
+ /* Open a connection to the database, creating it if necessary. */
+ if ((ret = wiredtiger_open(
+ home, NULL, "create,statistics=(fast)", &conn)) != 0)
+ fprintf(stderr, "Error connecting to %s: %s\n",
+ home, wiredtiger_strerror(ret));
+
+ /* Open a session for the current thread's work. */
+ if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
+ fprintf(stderr, "Error opening a session on %s: %s\n",
+ home, wiredtiger_strerror(ret));
+
+ ret = session->create(session, "table:world",
+ "key_format=r,value_format=5sii,"
+ "columns=(id,country,population,area)");
+
+ /*! [open cursor #1] */
+ ret = session->open_cursor(session, "table:world", NULL, NULL, &cursor);
+ /*! [open cursor #1] */
+
+ /*! [open cursor #2] */
+ ret = session->open_cursor(session,
+ "table:world(country,population)", NULL, NULL, &cursor);
+ /*! [open cursor #2] */
+
+ /*! [open cursor #3] */
+ ret = session->open_cursor(session, "statistics:", NULL, NULL, &cursor);
+ /*! [open cursor #3] */
+
+ /* Create a simple string table to illustrate basic operations. */
+ ret = session->create(session, "table:map",
+ "key_format=S,value_format=S");
+ ret = session->open_cursor(session, "table:map", NULL, NULL, &cursor);
+ ret = cursor_insert(cursor);
+ ret = cursor_reset(cursor);
+ ret = cursor_forward_scan(cursor);
+ ret = cursor_reset(cursor);
+ ret = cursor_reverse_scan(cursor);
+ ret = cursor_search_near(cursor);
+ ret = cursor_update(cursor);
+ ret = cursor_remove(cursor);
+ ret = cursor->close(cursor);
+
+ /* Note: closing the connection implicitly closes open session(s). */
+ if ((ret = conn->close(conn, NULL)) != 0)
+ fprintf(stderr, "Error closing %s: %s\n",
+ home, wiredtiger_strerror(ret));
+
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_data_source.c b/src/third_party/wiredtiger/examples/c/ex_data_source.c
new file mode 100644
index 00000000000..dd2b835e6ae
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_data_source.c
@@ -0,0 +1,673 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_data_source.c
+ * demonstrates how to create and access a data source
+ */
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wiredtiger.h>
+
+/*! [WT_EXTENSION_API declaration] */
+#include <wiredtiger_ext.h>
+
+static WT_EXTENSION_API *wt_api;
+
+static void
+my_data_source_init(WT_CONNECTION *connection)
+{
+ wt_api = connection->get_extension_api(connection);
+}
+/*! [WT_EXTENSION_API declaration] */
+
+/*! [WT_DATA_SOURCE create] */
+static int
+my_create(WT_DATA_SOURCE *dsrc, WT_SESSION *session,
+ const char *uri, WT_CONFIG_ARG *config)
+/*! [WT_DATA_SOURCE create] */
+{
+ /* Unused parameters */
+ (void)dsrc;
+ (void)uri;
+ (void)config;
+
+ {
+ const char *msg = "string";
+ /*! [WT_EXTENSION_API err_printf] */
+ (void)wt_api->err_printf(
+ wt_api, session, "extension error message: %s", msg);
+ /*! [WT_EXTENSION_API err_printf] */
+ }
+
+ {
+ const char *msg = "string";
+ /*! [WT_EXTENSION_API msg_printf] */
+ (void)wt_api->msg_printf(wt_api, session, "extension message: %s", msg);
+ /*! [WT_EXTENSION_API msg_printf] */
+ }
+
+ {
+ int ret = 0;
+ /*! [WT_EXTENSION_API strerror] */
+ (void)wt_api->err_printf(wt_api, session,
+ "WiredTiger error return: %s",
+ wt_api->strerror(wt_api, session, ret));
+ /*! [WT_EXTENSION_API strerror] */
+ }
+
+ {
+ /*! [WT_EXTENSION_API scr_alloc] */
+ void *buffer;
+ if ((buffer = wt_api->scr_alloc(wt_api, session, 512)) == NULL) {
+ (void)wt_api->err_printf(wt_api, session,
+ "buffer allocation: %s",
+ session->strerror(session, ENOMEM));
+ return (ENOMEM);
+ }
+ /*! [WT_EXTENSION_API scr_alloc] */
+
+ /*! [WT_EXTENSION_API scr_free] */
+ wt_api->scr_free(wt_api, session, buffer);
+ /*! [WT_EXTENSION_API scr_free] */
+ }
+
+ return (0);
+}
+
+/*! [WT_DATA_SOURCE compact] */
+static int
+my_compact(WT_DATA_SOURCE *dsrc, WT_SESSION *session,
+ const char *uri, WT_CONFIG_ARG *config)
+/*! [WT_DATA_SOURCE compact] */
+{
+ /* Unused parameters */
+ (void)dsrc;
+ (void)session;
+ (void)uri;
+ (void)config;
+
+ return (0);
+}
+
+/*! [WT_DATA_SOURCE drop] */
+static int
+my_drop(WT_DATA_SOURCE *dsrc, WT_SESSION *session,
+ const char *uri, WT_CONFIG_ARG *config)
+/*! [WT_DATA_SOURCE drop] */
+{
+ /* Unused parameters */
+ (void)dsrc;
+ (void)session;
+ (void)uri;
+ (void)config;
+
+ return (0);
+}
+
+static int
+data_source_cursor(void)
+{
+ return (0);
+}
+
+static const char *
+data_source_error(int v)
+{
+ return (v == 0 ? "one" : "two");
+}
+
+static int
+data_source_notify(
+ WT_TXN_NOTIFY *handler, WT_SESSION *session, uint64_t txnid, int committed)
+{
+ /* Unused parameters */
+ (void)handler;
+ (void)session;
+ (void)txnid;
+ (void)committed;
+
+ return (0);
+}
+
+static int my_cursor_next(WT_CURSOR *wtcursor)
+ { (void)wtcursor; return (0); }
+static int my_cursor_prev(WT_CURSOR *wtcursor)
+ { (void)wtcursor; return (0); }
+static int my_cursor_reset(WT_CURSOR *wtcursor)
+ { (void)wtcursor; return (0); }
+static int my_cursor_search(WT_CURSOR *wtcursor)
+ { (void)wtcursor; return (0); }
+static int my_cursor_search_near(WT_CURSOR *wtcursor, int *exactp)
+ { (void)wtcursor; (void)exactp; return (0); }
+static int my_cursor_insert(WT_CURSOR *wtcursor)
+{
+ WT_SESSION *session = NULL;
+ int ret;
+
+ /* Unused parameters */
+ (void)wtcursor;
+
+ {
+ int is_snapshot_isolation, isolation_level;
+ /*! [WT_EXTENSION transaction isolation level] */
+ isolation_level = wt_api->transaction_isolation_level(wt_api, session);
+ if (isolation_level == WT_TXN_ISO_SNAPSHOT)
+ is_snapshot_isolation = 1;
+ else
+ is_snapshot_isolation = 0;
+ /*! [WT_EXTENSION transaction isolation level] */
+ (void)is_snapshot_isolation;
+ }
+
+ {
+ /*! [WT_EXTENSION transaction ID] */
+ uint64_t transaction_id;
+
+ transaction_id = wt_api->transaction_id(wt_api, session);
+ /*! [WT_EXTENSION transaction ID] */
+ (void)transaction_id;
+ }
+
+ {
+ /*! [WT_EXTENSION transaction oldest] */
+ uint64_t transaction_oldest;
+
+ transaction_oldest = wt_api->transaction_oldest(wt_api);
+ /*! [WT_EXTENSION transaction oldest] */
+ (void)transaction_oldest;
+ }
+
+ {
+ /*! [WT_EXTENSION transaction notify] */
+ WT_TXN_NOTIFY handler;
+ handler.notify = data_source_notify;
+ ret = wt_api->transaction_notify(wt_api, session, &handler);
+ /*! [WT_EXTENSION transaction notify] */
+ }
+
+ {
+ uint64_t transaction_id = 1;
+ int is_visible;
+ /*! [WT_EXTENSION transaction visible] */
+ is_visible =
+ wt_api->transaction_visible(wt_api, session, transaction_id);
+ /*! [WT_EXTENSION transaction visible] */
+ (void)is_visible;
+ }
+
+ {
+ const char *key1 = NULL, *key2 = NULL;
+ uint32_t key1_len = 0, key2_len = 0;
+ WT_COLLATOR *collator = NULL;
+ /*! [WT_EXTENSION collate] */
+ WT_ITEM first, second;
+ int cmp;
+
+ first.data = key1;
+ first.size = key1_len;
+ second.data = key2;
+ second.size = key2_len;
+
+ ret = wt_api->collate(wt_api, session, collator, &first, &second, &cmp);
+ if (cmp == 0)
+ printf("key1 collates identically to key2\n");
+ else if (cmp < 0)
+ printf("key1 collates less than key2\n");
+ else
+ printf("key1 collates greater than key2\n");
+ /*! [WT_EXTENSION collate] */
+ }
+
+ return (ret);
+}
+
+static int my_cursor_update(WT_CURSOR *wtcursor)
+ { (void)wtcursor; return (0); }
+static int my_cursor_remove(WT_CURSOR *wtcursor)
+ { (void)wtcursor; return (0); }
+static int my_cursor_close(WT_CURSOR *wtcursor)
+ { (void)wtcursor; return (0); }
+
+/*! [WT_DATA_SOURCE open_cursor] */
+typedef struct __my_cursor {
+ WT_CURSOR wtcursor; /* WiredTiger cursor, must come first */
+
+ /*
+ * Local cursor information: for example, we might want to have a
+ * reference to the extension functions.
+ */
+ WT_EXTENSION_API *wtext; /* Extension functions */
+} MY_CURSOR;
+
+static int
+my_open_cursor(WT_DATA_SOURCE *dsrc, WT_SESSION *session,
+ const char *uri, WT_CONFIG_ARG *config, WT_CURSOR **new_cursor)
+{
+ MY_CURSOR *cursor;
+
+ /* Allocate and initialize a WiredTiger cursor. */
+ if ((cursor = calloc(1, sizeof(*cursor))) == NULL)
+ return (errno);
+
+ cursor->wtcursor.next = my_cursor_next;
+ cursor->wtcursor.prev = my_cursor_prev;
+ cursor->wtcursor.reset = my_cursor_reset;
+ cursor->wtcursor.search = my_cursor_search;
+ cursor->wtcursor.search_near = my_cursor_search_near;
+ cursor->wtcursor.insert = my_cursor_insert;
+ cursor->wtcursor.update = my_cursor_update;
+ cursor->wtcursor.remove = my_cursor_remove;
+ cursor->wtcursor.close = my_cursor_close;
+
+ /*
+ * Configure local cursor information.
+ */
+
+ /* Return combined cursor to WiredTiger. */
+ *new_cursor = (WT_CURSOR *)cursor;
+
+/*! [WT_DATA_SOURCE open_cursor] */
+ {
+ int ret = 0;
+ (void)dsrc; /* Unused parameters */
+ (void)session;
+ (void)uri;
+ (void)new_cursor;
+
+ {
+ /*! [WT_EXTENSION_CONFIG boolean] */
+ WT_CONFIG_ITEM v;
+ int my_data_source_overwrite;
+
+ /*
+ * Retrieve the value of the boolean type configuration string
+ * "overwrite".
+ */
+ if ((ret = wt_api->config_get(
+ wt_api, session, config, "overwrite", &v)) != 0) {
+ (void)wt_api->err_printf(wt_api, session,
+ "overwrite configuration: %s",
+ session->strerror(session, ret));
+ return (ret);
+ }
+ my_data_source_overwrite = v.val != 0;
+ /*! [WT_EXTENSION_CONFIG boolean] */
+
+ (void)my_data_source_overwrite;
+ }
+
+ {
+ /*! [WT_EXTENSION_CONFIG integer] */
+ WT_CONFIG_ITEM v;
+ int64_t my_data_source_page_size;
+
+ /*
+ * Retrieve the value of the integer type configuration string
+ * "page_size".
+ */
+ if ((ret = wt_api->config_get(
+ wt_api, session, config, "page_size", &v)) != 0) {
+ (void)wt_api->err_printf(wt_api, session,
+ "page_size configuration: %s",
+ session->strerror(session, ret));
+ return (ret);
+ }
+ my_data_source_page_size = v.val;
+ /*! [WT_EXTENSION_CONFIG integer] */
+
+ (void)my_data_source_page_size;
+ }
+
+ {
+ /*! [WT_EXTENSION config_get] */
+ WT_CONFIG_ITEM v;
+ const char *my_data_source_key;
+
+ /*
+ * Retrieve the value of the string type configuration string
+ * "key_format".
+ */
+ if ((ret = wt_api->config_get(
+ wt_api, session, config, "key_format", &v)) != 0) {
+ (void)wt_api->err_printf(wt_api, session,
+ "key_format configuration: %s",
+ session->strerror(session, ret));
+ return (ret);
+ }
+
+ /*
+ * Values returned from WT_EXTENSION_API::config in the str field are
+ * not nul-terminated; the associated length must be used instead.
+ */
+ if (v.len == 1 && v.str[0] == 'r')
+ my_data_source_key = "recno";
+ else
+ my_data_source_key = "bytestring";
+ /*! [WT_EXTENSION config_get] */
+
+ (void)my_data_source_key;
+ }
+
+ {
+ /*! [WT_EXTENSION collator config] */
+ WT_COLLATOR *collator;
+ int collator_owned;
+ /*
+ * Configure the appropriate collator.
+ */
+ if ((ret = wt_api->collator_config(wt_api, session,
+ "dsrc:", config, &collator, &collator_owned)) != 0) {
+ (void)wt_api->err_printf(wt_api, session,
+ "collator configuration: %s",
+ session->strerror(session, ret));
+ return (ret);
+ }
+ /*! [WT_EXTENSION collator config] */
+ }
+
+ /*! [WT_DATA_SOURCE error message] */
+ /*
+ * If an underlying function fails, log the error and then return an
+ * error within WiredTiger's name space.
+ */
+ if ((ret = data_source_cursor()) != 0) {
+ (void)wt_api->err_printf(wt_api,
+ session, "my_open_cursor: %s", data_source_error(ret));
+ return (WT_ERROR);
+ }
+ /*! [WT_DATA_SOURCE error message] */
+
+ {
+ /*! [WT_EXTENSION metadata insert] */
+ /*
+ * Insert a new WiredTiger metadata record.
+ */
+ const char *key = "datasource_uri";
+ const char *value = "data source uri's record";
+
+ if ((ret = wt_api->metadata_insert(wt_api, session, key, value)) != 0) {
+ (void)wt_api->err_printf(wt_api, session,
+ "%s: metadata insert: %s", key,
+ session->strerror(session, ret));
+ return (ret);
+ }
+ /*! [WT_EXTENSION metadata insert] */
+ }
+
+ {
+ /*! [WT_EXTENSION metadata remove] */
+ /*
+ * Remove a WiredTiger metadata record.
+ */
+ const char *key = "datasource_uri";
+
+ if ((ret = wt_api->metadata_remove(wt_api, session, key)) != 0) {
+ (void)wt_api->err_printf(wt_api, session,
+ "%s: metadata remove: %s", key,
+ session->strerror(session, ret));
+ return (ret);
+ }
+ /*! [WT_EXTENSION metadata remove] */
+ }
+
+ {
+ /*! [WT_EXTENSION metadata search] */
+ /*
+ * Search for a WiredTiger metadata record.
+ */
+ const char *key = "datasource_uri";
+ char *value;
+
+ if ((ret =
+ wt_api->metadata_search(wt_api, session, key, &value)) != 0) {
+ (void)wt_api->err_printf(wt_api, session,
+ "%s: metadata search: %s", key,
+ session->strerror(session, ret));
+ return (ret);
+ }
+ printf("metadata: %s has a value of %s\n", key, value);
+ /*! [WT_EXTENSION metadata search] */
+ }
+
+ {
+ /*! [WT_EXTENSION metadata update] */
+ /*
+ * Update a WiredTiger metadata record (insert it if it does not yet
+ * exist, update it if it does).
+ */
+ const char *key = "datasource_uri";
+ const char *value = "data source uri's record";
+
+ if ((ret = wt_api->metadata_update(wt_api, session, key, value)) != 0) {
+ (void)wt_api->err_printf(wt_api, session,
+ "%s: metadata update: %s", key,
+ session->strerror(session, ret));
+ return (ret);
+ }
+ /*! [WT_EXTENSION metadata update] */
+ }
+
+ }
+ return (0);
+}
+
+/*! [WT_DATA_SOURCE rename] */
+static int
+my_rename(WT_DATA_SOURCE *dsrc, WT_SESSION *session,
+ const char *uri, const char *newname, WT_CONFIG_ARG *config)
+/*! [WT_DATA_SOURCE rename] */
+{
+ /* Unused parameters */
+ (void)dsrc;
+ (void)session;
+ (void)uri;
+ (void)newname;
+ (void)config;
+
+ return (0);
+}
+
+/*! [WT_DATA_SOURCE salvage] */
+static int
+my_salvage(WT_DATA_SOURCE *dsrc, WT_SESSION *session,
+ const char *uri, WT_CONFIG_ARG *config)
+/*! [WT_DATA_SOURCE salvage] */
+{
+ /* Unused parameters */
+ (void)dsrc;
+ (void)session;
+ (void)uri;
+ (void)config;
+
+ return (0);
+}
+
+/*! [WT_DATA_SOURCE truncate] */
+static int
+my_truncate(WT_DATA_SOURCE *dsrc, WT_SESSION *session,
+ const char *uri, WT_CONFIG_ARG *config)
+/*! [WT_DATA_SOURCE truncate] */
+{
+ /* Unused parameters */
+ (void)dsrc;
+ (void)session;
+ (void)uri;
+ (void)config;
+
+ return (0);
+}
+
+/*! [WT_DATA_SOURCE range truncate] */
+static int
+my_range_truncate(WT_DATA_SOURCE *dsrc, WT_SESSION *session,
+ WT_CURSOR *start, WT_CURSOR *stop)
+/*! [WT_DATA_SOURCE range truncate] */
+{
+ /* Unused parameters */
+ (void)dsrc;
+ (void)session;
+ (void)start;
+ (void)stop;
+
+ return (0);
+}
+
+/*! [WT_DATA_SOURCE verify] */
+static int
+my_verify(WT_DATA_SOURCE *dsrc, WT_SESSION *session,
+ const char *uri, WT_CONFIG_ARG *config)
+/*! [WT_DATA_SOURCE verify] */
+{
+ /* Unused parameters */
+ (void)dsrc;
+ (void)session;
+ (void)uri;
+ (void)config;
+
+ return (0);
+}
+
+/*! [WT_DATA_SOURCE checkpoint] */
+static int
+my_checkpoint(WT_DATA_SOURCE *dsrc, WT_SESSION *session, WT_CONFIG_ARG *config)
+/*! [WT_DATA_SOURCE checkpoint] */
+{
+ /* Unused parameters */
+ (void)dsrc;
+ (void)session;
+ (void)config;
+
+ return (0);
+}
+
+/*! [WT_DATA_SOURCE terminate] */
+static int
+my_terminate(WT_DATA_SOURCE *dsrc, WT_SESSION *session)
+/*! [WT_DATA_SOURCE terminate] */
+{
+ /* Unused parameters */
+ (void)dsrc;
+ (void)session;
+
+ return (0);
+}
+
+int
+main(void)
+{
+ WT_CONNECTION *conn;
+ WT_SESSION *session;
+ int ret;
+
+ ret = wiredtiger_open(NULL, NULL, "create", &conn);
+ ret = conn->open_session(conn, NULL, NULL, &session);
+
+ my_data_source_init(conn);
+
+ {
+ /*! [WT_DATA_SOURCE register] */
+ static WT_DATA_SOURCE my_dsrc = {
+ my_create,
+ my_compact,
+ my_drop,
+ my_open_cursor,
+ my_rename,
+ my_salvage,
+ my_truncate,
+ my_range_truncate,
+ my_verify,
+ my_checkpoint,
+ my_terminate
+ };
+ ret = conn->add_data_source(conn, "dsrc:", &my_dsrc, NULL);
+ /*! [WT_DATA_SOURCE register] */
+ }
+
+ /*! [WT_DATA_SOURCE configure boolean] */
+ /* my_boolean defaults to true. */
+ ret = conn->configure_method(conn,
+ "WT_SESSION.open_cursor", NULL, "my_boolean=true", "boolean", NULL);
+ /*! [WT_DATA_SOURCE configure boolean] */
+
+ /*! [WT_DATA_SOURCE configure integer] */
+ /* my_integer defaults to 5. */
+ ret = conn->configure_method(conn,
+ "WT_SESSION.open_cursor", NULL, "my_integer=5", "int", NULL);
+ /*! [WT_DATA_SOURCE configure integer] */
+
+ /*! [WT_DATA_SOURCE configure string] */
+ /* my_string defaults to "name". */
+ ret = conn->configure_method(conn,
+ "WT_SESSION.open_cursor", NULL, "my_string=name", "string", NULL);
+ /*! [WT_DATA_SOURCE configure string] */
+
+ /*! [WT_DATA_SOURCE configure list] */
+ /* my_list defaults to "first" and "second". */
+ ret = conn->configure_method(conn,
+ "WT_SESSION.open_cursor",
+ NULL, "my_list=[first, second]", "list", NULL);
+ /*! [WT_DATA_SOURCE configure list] */
+
+ /*! [WT_DATA_SOURCE configure integer with checking] */
+ /*
+ * Limit the number of devices to between 1 and 30; the default is 5.
+ */
+ ret = conn->configure_method(conn,
+ "WT_SESSION.open_cursor",
+ NULL, "devices=5", "int", "min=1, max=30");
+ /*! [WT_DATA_SOURCE configure integer with checking] */
+
+ /*! [WT_DATA_SOURCE configure string with checking] */
+ /*
+ * Limit the target string to one of /device, /home or /target; default
+ * to /home.
+ */
+ ret = conn->configure_method(conn,
+ "WT_SESSION.open_cursor", NULL, "target=/home", "string",
+ "choices=[/device, /home, /target]");
+ /*! [WT_DATA_SOURCE configure string with checking] */
+
+ /*! [WT_DATA_SOURCE configure list with checking] */
+ /*
+ * Limit the paths list to one or more of /device, /home, /mnt or
+ * /target; default to /mnt.
+ */
+ ret = conn->configure_method(conn,
+ "WT_SESSION.open_cursor", NULL, "paths=[/mnt]", "list",
+ "choices=[/device, /home, /mnt, /target]");
+ /*! [WT_DATA_SOURCE configure list with checking] */
+
+ /*! [WT_EXTENSION_API default_session] */
+ (void)wt_api->msg_printf(wt_api, NULL, "configuration complete");
+ /*! [WT_EXTENSION_API default_session] */
+
+ (void)conn->close(conn, NULL);
+
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_encrypt.c b/src/third_party/wiredtiger/examples/c/ex_encrypt.c
new file mode 100644
index 00000000000..425ee6b7287
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_encrypt.c
@@ -0,0 +1,593 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_encrypt.c
+ * demonstrates how to use the encryption API.
+ */
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#include "windows_shim.h"
+#endif
+
+#include <wiredtiger.h>
+#include <wiredtiger_ext.h>
+
+#ifdef _WIN32
+/*
+ * Explicitly export this function so it is visible when loading extensions.
+ */
+__declspec(dllexport)
+#endif
+int add_my_encryptors(WT_CONNECTION *connection);
+
+static const char *home = NULL;
+
+#define SYS_KEYID "system"
+#define SYS_PW "system_password"
+#define USER1_KEYID "user1"
+#define USER2_KEYID "user2"
+#define USERBAD_KEYID "userbad"
+
+#define ITEM_MATCHES(config_item, s) \
+ (strlen(s) == (config_item).len && \
+ strncmp((config_item).str, s, (config_item).len) == 0)
+
+/*! [encryption example callback implementation] */
+typedef struct {
+ WT_ENCRYPTOR encryptor; /* Must come first */
+ int rot_N; /* rotN value */
+ uint32_t num_calls; /* Count of calls */
+ char *keyid; /* Saved keyid */
+ char *password; /* Saved password */
+} MY_CRYPTO;
+
+#define CHKSUM_LEN 4
+#define IV_LEN 16
+
+/*
+ * make_cksum --
+ * This is where one would call a checksum function on the encrypted
+ * buffer. Here we just put a constant value in it.
+ */
+static void
+make_cksum(uint8_t *dst)
+{
+ int i;
+ /*
+ * Assume array is big enough for the checksum.
+ */
+ for (i = 0; i < CHKSUM_LEN; i++)
+ dst[i] = 'C';
+}
+
+/*
+ * make_iv --
+ * This is where one would generate the initialization vector.
+ * Here we just put a constant value in it.
+ */
+static void
+make_iv(uint8_t *dst)
+{
+ int i;
+ /*
+ * Assume array is big enough for the initialization vector.
+ */
+ for (i = 0; i < IV_LEN; i++)
+ dst[i] = 'I';
+}
+
+/*
+ * Rotate encryption functions.
+ */
+/*
+ * do_rotate --
+ * Perform rot-N on the buffer given.
+ */
+static void
+do_rotate(char *buf, size_t len, int rotn)
+{
+ uint32_t i;
+ /*
+ * Now rotate
+ */
+ for (i = 0; i < len; i++)
+ if (isalpha(buf[i])) {
+ if (islower(buf[i]))
+ buf[i] = ((buf[i] - 'a') + rotn) % 26 + 'a';
+ else
+ buf[i] = ((buf[i] - 'A') + rotn) % 26 + 'A';
+ }
+}
+
+/*
+ * rotate_decrypt --
+ * A simple rotate decryption.
+ */
+static int
+rotate_decrypt(WT_ENCRYPTOR *encryptor, WT_SESSION *session,
+ uint8_t *src, size_t src_len,
+ uint8_t *dst, size_t dst_len,
+ size_t *result_lenp)
+{
+ MY_CRYPTO *my_crypto = (MY_CRYPTO *)encryptor;
+ size_t mylen;
+ uint32_t i;
+
+ (void)session; /* Unused */
+ ++my_crypto->num_calls;
+
+ if (src == NULL)
+ return (0);
+ /*
+ * Make sure it is big enough.
+ */
+ mylen = src_len - (CHKSUM_LEN + IV_LEN);
+ if (dst_len < mylen) {
+ fprintf(stderr,
+ "Rotate: ENOMEM ERROR: dst_len %zu src_len %zu\n",
+ dst_len, src_len);
+ return (ENOMEM);
+ }
+
+ /*
+ * !!! Most implementations would verify any needed
+ * checksum and initialize the IV here.
+ */
+ /*
+ * Copy the encrypted data to the destination buffer and then
+ * decrypt the destination buffer in place.
+ */
+ i = CHKSUM_LEN + IV_LEN;
+ memcpy(&dst[0], &src[i], mylen);
+ /*
+ * Call common rotate function on the text portion of the
+ * buffer. Send in dst_len as the length of the text.
+ */
+ /*
+ * !!! Most implementations would need the IV too.
+ */
+ do_rotate((char *)dst, mylen, 26 - my_crypto->rot_N);
+ *result_lenp = mylen;
+ return (0);
+}
+
+/*
+ * rotate_encrypt --
+ * A simple rotate encryption.
+ */
+static int
+rotate_encrypt(WT_ENCRYPTOR *encryptor, WT_SESSION *session,
+ uint8_t *src, size_t src_len,
+ uint8_t *dst, size_t dst_len,
+ size_t *result_lenp)
+{
+ MY_CRYPTO *my_crypto = (MY_CRYPTO *)encryptor;
+ uint32_t i;
+
+ (void)session; /* Unused */
+ ++my_crypto->num_calls;
+
+ if (src == NULL)
+ return (0);
+ if (dst_len < src_len + CHKSUM_LEN + IV_LEN)
+ return (ENOMEM);
+
+ i = CHKSUM_LEN + IV_LEN;
+ /*
+ * Skip over space reserved for checksum and initialization
+ * vector. Copy text into destination buffer then encrypt
+ * in place.
+ */
+ memcpy(&dst[i], &src[0], src_len);
+ /*
+ * Call common rotate function on the text portion of the
+ * destination buffer. Send in src_len as the length of
+ * the text.
+ */
+ do_rotate((char *)dst + i, src_len, my_crypto->rot_N);
+ /*
+ * Checksum the encrypted buffer and add the IV.
+ */
+ i = 0;
+ make_cksum(&dst[i]);
+ i += CHKSUM_LEN;
+ make_iv(&dst[i]);
+ *result_lenp = dst_len;
+ return (0);
+}
+
+/*
+ * rotate_sizing --
+ * A sizing example that returns the header size needed.
+ */
+static int
+rotate_sizing(WT_ENCRYPTOR *encryptor, WT_SESSION *session,
+ size_t *expansion_constantp)
+{
+ MY_CRYPTO *my_crypto = (MY_CRYPTO *)encryptor;
+
+ (void)session; /* Unused parameters */
+
+ ++my_crypto->num_calls; /* Call count */
+
+ *expansion_constantp = CHKSUM_LEN + IV_LEN;
+ return (0);
+}
+
+/*
+ * rotate_customize --
+ * The customize function creates a customized encryptor
+ */
+static int
+rotate_customize(WT_ENCRYPTOR *encryptor, WT_SESSION *session,
+ WT_CONFIG_ARG *encrypt_config, WT_ENCRYPTOR **customp)
+{
+ MY_CRYPTO *my_crypto;
+ WT_CONFIG_ITEM keyid, secret;
+ WT_EXTENSION_API *extapi;
+ int ret;
+ const MY_CRYPTO *orig_crypto;
+
+ extapi = session->connection->get_extension_api(session->connection);
+
+ orig_crypto = (const MY_CRYPTO *)encryptor;
+ if ((my_crypto = calloc(1, sizeof(MY_CRYPTO))) == NULL) {
+ ret = errno;
+ goto err;
+ }
+ *my_crypto = *orig_crypto;
+ my_crypto->keyid = my_crypto->password = NULL;
+
+ /*
+ * Stash the keyid and the (optional) secret key
+ * from the configuration string.
+ */
+ if ((ret = extapi->config_get(extapi, session, encrypt_config,
+ "keyid", &keyid)) == 0 && keyid.len != 0) {
+ if ((my_crypto->keyid = malloc(keyid.len + 1)) == NULL) {
+ ret = errno;
+ goto err;
+ }
+ strncpy(my_crypto->keyid, keyid.str, keyid.len + 1);
+ my_crypto->keyid[keyid.len] = '\0';
+ }
+
+ if ((ret = extapi->config_get(extapi, session, encrypt_config,
+ "secretkey", &secret)) == 0 && secret.len != 0) {
+ if ((my_crypto->password = malloc(secret.len + 1)) == NULL) {
+ ret = errno;
+ goto err;
+ }
+ strncpy(my_crypto->password, secret.str, secret.len + 1);
+ my_crypto->password[secret.len] = '\0';
+ }
+ /*
+ * Presumably we'd have some sophisticated key management
+ * here that maps the id onto a secret key.
+ */
+ if (ITEM_MATCHES(keyid, "system")) {
+ if (my_crypto->password == NULL ||
+ strcmp(my_crypto->password, SYS_PW) != 0) {
+ ret = EPERM;
+ goto err;
+ }
+ my_crypto->rot_N = 13;
+ } else if (ITEM_MATCHES(keyid, USER1_KEYID))
+ my_crypto->rot_N = 4;
+ else if (ITEM_MATCHES(keyid, USER2_KEYID))
+ my_crypto->rot_N = 19;
+ else {
+ ret = EINVAL;
+ goto err;
+ }
+
+ ++my_crypto->num_calls; /* Call count */
+
+ *customp = (WT_ENCRYPTOR *)my_crypto;
+ return (0);
+
+err: free(my_crypto->keyid);
+ free(my_crypto->password);
+ free(my_crypto);
+ return (ret);
+}
+
+/*
+ * rotate_terminate --
+ * WiredTiger rotate encryption termination.
+ */
+static int
+rotate_terminate(WT_ENCRYPTOR *encryptor, WT_SESSION *session)
+{
+ MY_CRYPTO *my_crypto = (MY_CRYPTO *)encryptor;
+
+ (void)session; /* Unused parameters */
+
+ ++my_crypto->num_calls; /* Call count */
+
+ /* Free the allocated memory. */
+ free(my_crypto->password);
+ my_crypto->password = NULL;
+
+ free(my_crypto->keyid);
+ my_crypto->keyid = NULL;
+
+ free(encryptor);
+
+ return (0);
+}
+
+/*
+ * add_my_encryptors --
+ * A simple example of adding encryption callbacks.
+ */
+int
+add_my_encryptors(WT_CONNECTION *connection)
+{
+ MY_CRYPTO *m;
+ WT_ENCRYPTOR *wt;
+ int ret;
+
+ /*
+ * Initialize our top level encryptor.
+ */
+ if ((m = calloc(1, sizeof(MY_CRYPTO))) == NULL)
+ return (errno);
+ wt = (WT_ENCRYPTOR *)&m->encryptor;
+ wt->encrypt = rotate_encrypt;
+ wt->decrypt = rotate_decrypt;
+ wt->sizing = rotate_sizing;
+ wt->customize = rotate_customize;
+ wt->terminate = rotate_terminate;
+ m->num_calls = 0;
+ if ((ret = connection->add_encryptor(
+ connection, "rotn", (WT_ENCRYPTOR *)m, NULL)) != 0)
+ return (ret);
+
+ return (0);
+}
+
+/*
+ * simple_walk_log --
+ * A simple walk of the write-ahead log.
+ * We wrote text messages into the log. Print them.
+ * This verifies we're decrypting properly.
+ */
+static int
+simple_walk_log(WT_SESSION *session)
+{
+ WT_CURSOR *cursor;
+ WT_ITEM logrec_key, logrec_value;
+ WT_LSN lsn;
+ uint64_t txnid;
+ uint32_t fileid, opcount, optype, rectype;
+ int found, ret;
+
+ ret = session->open_cursor(session, "log:", NULL, NULL, &cursor);
+
+ found = 0;
+ while ((ret = cursor->next(cursor)) == 0) {
+ ret = cursor->get_key(cursor, &lsn.file, &lsn.offset, &opcount);
+ ret = cursor->get_value(cursor, &txnid,
+ &rectype, &optype, &fileid, &logrec_key, &logrec_value);
+
+ if (rectype == WT_LOGREC_MESSAGE) {
+ found = 1;
+ printf("Application Log Record: %s\n",
+ (char *)logrec_value.data);
+ }
+ }
+ if (ret == WT_NOTFOUND)
+ ret = 0;
+ ret = cursor->close(cursor);
+ if (found == 0) {
+ fprintf(stderr, "Did not find log messages.\n");
+ exit(EXIT_FAILURE);
+ }
+ return (ret);
+}
+
+#define MAX_KEYS 20
+
+#define EXTENSION_NAME "local=(entry=add_my_encryptors)"
+
+#define WT_OPEN_CONFIG_COMMON \
+ "create,cache_size=100MB,extensions=[" EXTENSION_NAME "],"\
+ "log=(archive=false,enabled=true)," \
+
+#define WT_OPEN_CONFIG_GOOD \
+ WT_OPEN_CONFIG_COMMON \
+ "encryption=(name=rotn,keyid=" SYS_KEYID ",secretkey=" SYS_PW ")"
+
+#define COMP_A "AAAAAAAAAAAAAAAAAA"
+#define COMP_B "BBBBBBBBBBBBBBBBBB"
+#define COMP_C "CCCCCCCCCCCCCCCCCC"
+
+int
+main(void)
+{
+ WT_CONNECTION *conn;
+ WT_CURSOR *c1, *c2, *nc;
+ WT_SESSION *session;
+ int i, ret;
+ char keybuf[16], valbuf[16];
+ char *key1, *key2, *key3, *val1, *val2, *val3;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (getenv("WIREDTIGER_HOME") == NULL) {
+ home = "WT_HOME";
+ ret = system("rm -rf WT_HOME && mkdir WT_HOME");
+ } else
+ home = NULL;
+
+ ret = wiredtiger_open(home, NULL, WT_OPEN_CONFIG_GOOD, &conn);
+
+ ret = conn->open_session(conn, NULL, NULL, &session);
+
+ /*
+ * Write a log record that is larger than the base 128 bytes and
+ * also should compress well.
+ */
+ ret = session->log_printf(session,
+ COMP_A COMP_B COMP_C COMP_A COMP_B COMP_C
+ COMP_A COMP_B COMP_C COMP_A COMP_B COMP_C
+ "The quick brown fox jumps over the lazy dog ");
+ ret = simple_walk_log(session);
+
+ /*
+ * Create and open some encrypted and not encrypted tables.
+ * Also use column store and compression for some tables.
+ */
+ ret = session->create(session, "table:crypto1",
+ "encryption=(name=rotn,keyid=" USER1_KEYID"),"
+ "columns=(key0,value0),"
+ "key_format=S,value_format=S");
+ ret = session->create(session, "index:crypto1:byvalue",
+ "encryption=(name=rotn,keyid=" USER1_KEYID"),"
+ "columns=(value0,key0)");
+ ret = session->create(session, "table:crypto2",
+ "encryption=(name=rotn,keyid=" USER2_KEYID"),"
+ "key_format=S,value_format=S");
+ ret = session->create(session, "table:nocrypto",
+ "key_format=S,value_format=S");
+
+ /*
+ * Send in an unknown keyid. WiredTiger will try to add in the
+ * new keyid, but the customize function above will return an
+ * error since it is unrecognized.
+ */
+ ret = session->create(session, "table:cryptobad",
+ "encryption=(name=rotn,keyid=" USERBAD_KEYID"),"
+ "key_format=S,value_format=S");
+ if (ret == 0) {
+ fprintf(stderr, "Did not detect bad/unknown keyid error\n");
+ exit(EXIT_FAILURE);
+ }
+
+ ret = session->open_cursor(session, "table:crypto1", NULL, NULL, &c1);
+ ret = session->open_cursor(session, "table:crypto2", NULL, NULL, &c2);
+ ret = session->open_cursor(session, "table:nocrypto", NULL, NULL, &nc);
+
+ /*
+ * Insert a set of keys and values. Insert the same data into
+ * all tables so that we can verify they're all the same after
+ * we decrypt on read.
+ */
+ for (i = 0; i < MAX_KEYS; i++) {
+ snprintf(keybuf, sizeof(keybuf), "key%d", i);
+ c1->set_key(c1, keybuf);
+ c2->set_key(c2, keybuf);
+ nc->set_key(nc, keybuf);
+
+ snprintf(valbuf, sizeof(valbuf), "value%d", i);
+ c1->set_value(c1, valbuf);
+ c2->set_value(c2, valbuf);
+ nc->set_value(nc, valbuf);
+
+ ret = c1->insert(c1);
+ ret = c2->insert(c2);
+ ret = nc->insert(nc);
+ if (i % 5 == 0)
+ ret = session->log_printf(session,
+ "Wrote %d records", i);
+ }
+ ret = session->log_printf(session, "Done. Wrote %d total records", i);
+
+ while (c1->next(c1) == 0) {
+ ret = c1->get_key(c1, &key1);
+ ret = c1->get_value(c1, &val1);
+
+ printf("Read key %s; value %s\n", key1, val1);
+ }
+ ret = simple_walk_log(session);
+ printf("CLOSE\n");
+ ret = conn->close(conn, NULL);
+
+ /*
+ * We want to close and reopen so that we recreate the cache
+ * by reading the data from disk, forcing decryption.
+ */
+ printf("REOPEN and VERIFY encrypted data\n");
+
+ ret = wiredtiger_open(home, NULL, WT_OPEN_CONFIG_GOOD, &conn);
+
+ ret = conn->open_session(conn, NULL, NULL, &session);
+ /*
+ * Verify we can read the encrypted log after restart.
+ */
+ ret = simple_walk_log(session);
+ ret = session->open_cursor(session, "table:crypto1", NULL, NULL, &c1);
+ ret = session->open_cursor(session, "table:crypto2", NULL, NULL, &c2);
+ ret = session->open_cursor(session, "table:nocrypto", NULL, NULL, &nc);
+
+ /*
+ * Read the same data from each cursor. All should be identical.
+ */
+ while (c1->next(c1) == 0) {
+ ret = c2->next(c2);
+ ret = nc->next(nc);
+ ret = c1->get_key(c1, &key1);
+ ret = c1->get_value(c1, &val1);
+ ret = c2->get_key(c2, &key2);
+ ret = c2->get_value(c2, &val2);
+ ret = nc->get_key(nc, &key3);
+ ret = nc->get_value(nc, &val3);
+
+ if (strcmp(key1, key2) != 0)
+ fprintf(stderr, "Key1 %s and Key2 %s do not match\n",
+ key1, key2);
+ if (strcmp(key1, key3) != 0)
+ fprintf(stderr, "Key1 %s and Key3 %s do not match\n",
+ key1, key3);
+ if (strcmp(key2, key3) != 0)
+ fprintf(stderr, "Key2 %s and Key3 %s do not match\n",
+ key2, key3);
+ if (strcmp(val1, val2) != 0)
+ fprintf(stderr, "Val1 %s and Val2 %s do not match\n",
+ val1, val2);
+ if (strcmp(val1, val3) != 0)
+ fprintf(stderr, "Val1 %s and Val3 %s do not match\n",
+ val1, val3);
+ if (strcmp(val2, val3) != 0)
+ fprintf(stderr, "Val2 %s and Val3 %s do not match\n",
+ val2, val3);
+
+ printf("Verified key %s; value %s\n", key1, val1);
+ }
+ ret = conn->close(conn, NULL);
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_extending.c b/src/third_party/wiredtiger/examples/c/ex_extending.c
new file mode 100644
index 00000000000..4d265ae1d2b
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_extending.c
@@ -0,0 +1,133 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_extending.c
+ * This is an example demonstrating ways to extend WiredTiger with
+ * extractors, collators and loadable modules.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <wiredtiger.h>
+
+#ifdef _WIN32
+#define strcasecmp stricmp
+#endif
+
+static const char *home;
+
+/*! [case insensitive comparator] */
+/* A simple case insensitive comparator. */
+static int
+__compare_nocase(WT_COLLATOR *collator, WT_SESSION *session,
+ const WT_ITEM *v1, const WT_ITEM *v2, int *cmp)
+{
+ const char *s1 = (const char *)v1->data;
+ const char *s2 = (const char *)v2->data;
+
+ (void)session; /* unused */
+ (void)collator; /* unused */
+
+ *cmp = strcasecmp(s1, s2);
+ return (0);
+}
+
+static WT_COLLATOR nocasecoll = { __compare_nocase, NULL, NULL };
+/*! [case insensitive comparator] */
+
+/*! [n character comparator] */
+/*
+ * Comparator that only compares the first N prefix characters of the string.
+ * This has associated data, so we need to extend WT_COLLATOR.
+ */
+typedef struct {
+ WT_COLLATOR iface;
+ uint32_t maxlen;
+} PREFIX_COLLATOR;
+
+static int
+__compare_prefixes(WT_COLLATOR *collator, WT_SESSION *session,
+ const WT_ITEM *v1, const WT_ITEM *v2, int *cmp)
+{
+ PREFIX_COLLATOR *pcoll = (PREFIX_COLLATOR *)collator;
+ const char *s1 = (const char *)v1->data;
+ const char *s2 = (const char *)v2->data;
+
+ (void)session; /* unused */
+
+ *cmp = strncmp(s1, s2, pcoll->maxlen);
+ return (0);
+}
+
+static PREFIX_COLLATOR pcoll10 = { {__compare_prefixes, NULL, NULL}, 10 };
+/*! [n character comparator] */
+
+int
+main(void)
+{
+ int ret;
+ WT_CONNECTION *conn;
+ WT_SESSION *session;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (getenv("WIREDTIGER_HOME") == NULL) {
+ home = "WT_HOME";
+ ret = system("rm -rf WT_HOME && mkdir WT_HOME");
+ } else
+ home = NULL;
+
+ /* Open a connection to the database, creating it if necessary. */
+ if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0)
+ fprintf(stderr, "Error connecting to %s: %s\n",
+ home, wiredtiger_strerror(ret));
+
+ /*! [add collator nocase] */
+ ret = conn->add_collator(conn, "nocase", &nocasecoll, NULL);
+ /*! [add collator nocase] */
+ /*! [add collator prefix10] */
+ ret = conn->add_collator(conn, "prefix10", &pcoll10.iface, NULL);
+
+ /* Open a session for the current thread's work. */
+ if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
+ fprintf(stderr, "Error opening a session on %s: %s\n",
+ home, wiredtiger_strerror(ret));
+
+ /* XXX Do some work... */
+
+ /* Note: closing the connection implicitly closes open session(s). */
+ if ((ret = conn->close(conn, NULL)) != 0)
+ /*! [add collator prefix10] */
+ fprintf(stderr, "Error closing %s: %s\n",
+ home, wiredtiger_strerror(ret));
+
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_extractor.c b/src/third_party/wiredtiger/examples/c/ex_extractor.c
new file mode 100644
index 00000000000..fff9c79f8e0
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_extractor.c
@@ -0,0 +1,284 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_extractor.c
+ * Example of how to use a WiredTiger custom index extractor extension.
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <wiredtiger.h>
+
+#define RET_OK(ret) ((ret) == 0 || (ret) == WT_NOTFOUND)
+
+int add_extractor(WT_CONNECTION *conn);
+
+static const char *home;
+
+struct president_data {
+ int id;
+ const char *last_name;
+ const char *first_name;
+ uint16_t term_start;
+ uint16_t term_end;
+};
+
+static const struct president_data example_data[] = {
+ { 0, "Obama", "Barack", 2009, 2014 },
+ { 1, "Bush", "George W", 2001, 2009 },
+ { 2, "Clinton", "Bill", 1993, 2001 },
+ { 3, "Bush", "George H", 1989, 1993 },
+ { 4, "Reagan", "Ronald", 1981, 1989 },
+ { 0, NULL, NULL, 0, 0 }
+};
+/*
+ * Number of years this data spans
+ */
+#define YEAR_BASE 1981
+#define YEAR_SPAN (2014-1981)
+
+/*
+ * A custom index extractor function that adds an index entry for each year of
+ * the given president's term.
+ */
+static int
+my_extract(WT_EXTRACTOR *extractor, WT_SESSION *session,
+ const WT_ITEM *key, const WT_ITEM *value, WT_CURSOR *result_cursor)
+{
+ char *last_name, *first_name;
+ uint16_t term_end, term_start, year;
+ int ret;
+
+ /* Unused parameters */
+ (void)extractor;
+ (void)key;
+
+ /* Unpack the value. */
+ if ((ret = wiredtiger_struct_unpack(
+ session, value->data, value->size, "SSHH",
+ &last_name, &first_name, &term_start, &term_end)) != 0)
+ return (ret);
+
+ /*
+ * We have overlapping years, so multiple records may share the same
+ * index key.
+ */
+ for (year = term_start; year <= term_end; ++year) {
+ /*
+ * Note that the extract callback is called for all operations
+ * that update the table, not just inserts. The user sets the
+ * key and uses the cursor->insert() method to return the index
+ * key(s). WiredTiger will perform the required operation
+ * (such as a remove()).
+ */
+ fprintf(stderr, "EXTRACTOR: index op for year %d: %s %s\n",
+ year, first_name, last_name);
+ result_cursor->set_key(result_cursor, year);
+ if ((ret = result_cursor->insert(result_cursor)) != 0) {
+ fprintf(stderr, "EXTRACTOR: op year %d: error %d\n",
+ year, ret);
+ return (ret);
+ }
+ }
+ return (0);
+}
+
+/*
+ * The terminate method is called to release any allocated resources when the
+ * table is closed. In this example, no cleanup is required.
+ */
+static int
+my_extract_terminate(WT_EXTRACTOR *extractor, WT_SESSION *session)
+{
+ (void)extractor;
+ (void)session;
+
+ return (0);
+}
+
+int
+add_extractor(WT_CONNECTION *conn)
+{
+ int ret;
+
+ static WT_EXTRACTOR my_extractor = {
+ my_extract, NULL, my_extract_terminate
+ };
+ ret = conn->add_extractor(conn, "my_extractor", &my_extractor, NULL);
+
+ return (ret);
+}
+
+/*
+ * Read the index by year and print out who was in office that year.
+ */
+static int
+read_index(WT_SESSION *session)
+{
+ WT_CURSOR *cursor;
+ int i, ret;
+ char *first_name, *last_name;
+ uint16_t rec_year, term_end, term_start, year;
+
+ year = 0;
+ srand((unsigned int)getpid());
+ ret = session->open_cursor(
+ session, "index:presidents:term", NULL, NULL, &cursor);
+ /*
+ * Pick 10 random years and read the data.
+ */
+ for (i = 0; i < 10 && RET_OK(ret); i++) {
+ year = (uint16_t)((rand() % YEAR_SPAN) + YEAR_BASE);
+ printf("Year %d:\n", year);
+ cursor->set_key(cursor, year);
+ if ((ret = cursor->search(cursor)) != 0)
+ break;
+ if ((ret = cursor->get_key(cursor, &rec_year)) != 0)
+ break;
+ if ((ret = cursor->get_value(cursor,
+ &last_name, &first_name, &term_start, &term_end)) != 0)
+ break;
+
+ /* Report all presidents that served during the chosen year */
+ while (term_start <= year &&
+ year <= term_end && year == rec_year) {
+ printf("\t%s %s\n", first_name, last_name);
+ if ((ret = cursor->next(cursor)) != 0)
+ break;
+ if ((ret = cursor->get_key(cursor, &rec_year)) != 0)
+ break;
+ if ((ret = cursor->get_value(cursor, &last_name,
+ &first_name, &term_start, &term_end)) != 0)
+ break;
+ }
+ }
+ if (!RET_OK(ret))
+ fprintf(stderr, "Error %d for year %d\n", ret, year);
+
+ ret = cursor->close(cursor);
+ return (ret);
+}
+
+/*
+ * Remove some items from the primary table.
+ */
+static int
+remove_items(WT_SESSION *session)
+{
+ WT_CURSOR *cursor;
+ struct president_data p;
+ int i, ret;
+
+ /*
+ * Removing items from the primary table will call the extractor
+ * for the index and allow our custom extractor code to handle
+ * each custom key.
+ */
+ ret = session->open_cursor(
+ session, "table:presidents", NULL, NULL, &cursor);
+ /*
+ * Just remove the first few items.
+ */
+ for (i = 0; example_data[i].last_name != NULL && i < 2; i++) {
+ p = example_data[i];
+ cursor->set_key(cursor, p.id);
+ ret = cursor->remove(cursor);
+ }
+ return (ret);
+}
+
+/*
+ * Set up the table and index of the data.
+ */
+static int
+setup_table(WT_SESSION *session)
+{
+ WT_CURSOR *cursor;
+ struct president_data p;
+ int i, ret;
+
+ /* Create the primary table. It has a key of the unique ID. */
+ ret = session->create(session, "table:presidents",
+ "key_format=I,value_format=SSHH,"
+ "columns=(ID,last_name,first_name,term_begin,term_end)");
+
+ /*
+ * Create the index that is generated with an extractor. The index
+ * will generate an entry in the index for each year a president
+ * was in office.
+ */
+ ret = session->create(session, "index:presidents:term",
+ "key_format=H,columns=(term),extractor=my_extractor");
+
+ ret = session->open_cursor(
+ session, "table:presidents", NULL, NULL, &cursor);
+ for (i = 0; example_data[i].last_name != NULL; i++) {
+ p = example_data[i];
+ cursor->set_key(cursor, p.id);
+ cursor->set_value(cursor,
+ p.last_name, p.first_name, p.term_start, p.term_end);
+ fprintf(stderr, "SETUP: table insert %d-%d: %s %s\n",
+ p.term_start, p.term_end,
+ p.first_name, p.last_name);
+ ret = cursor->insert(cursor);
+ }
+ return (ret);
+}
+
+int
+main(void)
+{
+ WT_CONNECTION *conn;
+ WT_SESSION *session;
+ int ret;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (getenv("WIREDTIGER_HOME") == NULL) {
+ home = "WT_HOME";
+ ret = system("rm -rf WT_HOME && mkdir WT_HOME");
+ } else
+ home = NULL;
+
+ ret = wiredtiger_open(home, NULL, "create,cache_size=500M", &conn);
+ ret = add_extractor(conn);
+ ret = conn->open_session(conn, NULL, NULL, &session);
+
+ ret = setup_table(session);
+ ret = read_index(session);
+ ret = remove_items(session);
+
+ ret = conn->close(conn, NULL);
+
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_hello.c b/src/third_party/wiredtiger/examples/c/ex_hello.c
new file mode 100644
index 00000000000..345e434741f
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_hello.c
@@ -0,0 +1,76 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_hello.c
+ * This is an example demonstrating how to create and connect to a
+ * database.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <wiredtiger.h>
+
+static const char *home;
+
+int
+main(void)
+{
+ WT_CONNECTION *conn;
+ WT_SESSION *session;
+ int ret;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (getenv("WIREDTIGER_HOME") == NULL) {
+ home = "WT_HOME";
+ ret = system("rm -rf WT_HOME && mkdir WT_HOME");
+ } else
+ home = NULL;
+
+ /* Open a connection to the database, creating it if necessary. */
+ if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0)
+ fprintf(stderr, "Error connecting to %s: %s\n",
+ home, wiredtiger_strerror(ret));
+
+ /* Open a session for the current thread's work. */
+ if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
+ fprintf(stderr, "Error opening a session on %s: %s\n",
+ home, wiredtiger_strerror(ret));
+
+ /* Do some work... */
+
+ /* Note: closing the connection implicitly closes open session(s). */
+ if ((ret = conn->close(conn, NULL)) != 0)
+ fprintf(stderr, "Error closing %s: %s\n",
+ home, wiredtiger_strerror(ret));
+
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_log.c b/src/third_party/wiredtiger/examples/c/ex_log.c
new file mode 100644
index 00000000000..cc6a3c46b93
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_log.c
@@ -0,0 +1,358 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_log.c
+ * demonstrates how to use logging and log cursors.
+ */
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef _WIN32
+#include <unistd.h>
+#else
+/* snprintf is not supported on <= VS2013 */
+#define snprintf _snprintf
+#endif
+
+#include <wiredtiger.h>
+
+static const char *home1 = "WT_HOME_LOG_1";
+static const char *home2 = "WT_HOME_LOG_2";
+
+static const char * const uri = "table:logtest";
+
+#define CONN_CONFIG "create,cache_size=100MB,log=(archive=false,enabled=true)"
+#define MAX_KEYS 10
+
+static int
+setup_copy(WT_CONNECTION **wt_connp, WT_SESSION **sessionp)
+{
+ int ret;
+
+ if ((ret = wiredtiger_open(home2, NULL, CONN_CONFIG, wt_connp)) != 0) {
+ fprintf(stderr, "Error connecting to %s: %s\n",
+ home1, wiredtiger_strerror(ret));
+ return (ret);
+ }
+
+ ret = (*wt_connp)->open_session(*wt_connp, NULL, NULL, sessionp);
+ ret = (*sessionp)->create(*sessionp, uri,
+ "key_format=S,value_format=S");
+ return (ret);
+}
+
+static int
+compare_tables(WT_SESSION *session, WT_SESSION *sess_copy)
+{
+ WT_CURSOR *cursor, *curs_copy;
+ int ret;
+ const char *key, *key_copy, *value, *value_copy;
+
+ ret = session->open_cursor(session, uri, NULL, NULL, &cursor);
+ ret = sess_copy->open_cursor(sess_copy, uri, NULL, NULL, &curs_copy);
+
+ while ((ret = cursor->next(cursor)) == 0) {
+ ret = curs_copy->next(curs_copy);
+ ret = cursor->get_key(cursor, &key);
+ ret = cursor->get_value(cursor, &value);
+ ret = curs_copy->get_key(curs_copy, &key_copy);
+ ret = curs_copy->get_value(curs_copy, &value_copy);
+ if (strcmp(key, key_copy) != 0 ||
+ strcmp(value, value_copy) != 0) {
+ fprintf(stderr,
+ "Mismatched: key %s, key_copy %s "
+ "value %s value_copy %s\n",
+ key, key_copy, value, value_copy);
+ return (1);
+ }
+ }
+ if (ret != WT_NOTFOUND)
+ fprintf(stderr,
+ "WT_CURSOR.next: %s\n", session->strerror(session, ret));
+ ret = cursor->close(cursor);
+
+ ret = curs_copy->next(curs_copy);
+ if (ret != WT_NOTFOUND)
+ fprintf(stderr,
+ "copy: WT_CURSOR.next: %s\n",
+ session->strerror(session, ret));
+ ret = curs_copy->close(curs_copy);
+
+ return (ret);
+}
+
+/*! [log cursor walk] */
+static void
+print_record(WT_LSN *lsn, uint32_t opcount,
+ uint32_t rectype, uint32_t optype, uint64_t txnid, uint32_t fileid,
+ WT_ITEM *key, WT_ITEM *value)
+{
+ printf(
+ "LSN [%" PRIu32 "][%" PRIu64 "].%" PRIu32
+ ": record type %" PRIu32 " optype %" PRIu32
+ " txnid %" PRIu64 " fileid %" PRIu32,
+ lsn->file, (uint64_t)lsn->offset, opcount,
+ rectype, optype, txnid, fileid);
+ printf(" key size %zu value size %zu\n", key->size, value->size);
+ if (rectype == WT_LOGREC_MESSAGE)
+ printf("Application Record: %s\n", (char *)value->data);
+}
+
+/*
+ * simple_walk_log --
+ * A simple walk of the log.
+ */
+static int
+simple_walk_log(WT_SESSION *session, int count_min)
+{
+ WT_CURSOR *cursor;
+ WT_LSN lsn;
+ WT_ITEM logrec_key, logrec_value;
+ uint64_t txnid;
+ uint32_t fileid, opcount, optype, rectype;
+ int count, ret;
+
+ /*! [log cursor open] */
+ ret = session->open_cursor(session, "log:", NULL, NULL, &cursor);
+ /*! [log cursor open] */
+
+ count = 0;
+ while ((ret = cursor->next(cursor)) == 0) {
+ count++;
+ /*! [log cursor get_key] */
+ ret = cursor->get_key(cursor, &lsn.file, &lsn.offset, &opcount);
+ /*! [log cursor get_key] */
+ /*! [log cursor get_value] */
+ ret = cursor->get_value(cursor, &txnid,
+ &rectype, &optype, &fileid, &logrec_key, &logrec_value);
+ /*! [log cursor get_value] */
+
+ print_record(&lsn, opcount,
+ rectype, optype, txnid, fileid, &logrec_key, &logrec_value);
+ }
+ if (ret == WT_NOTFOUND)
+ ret = 0;
+ ret = cursor->close(cursor);
+ if (count < count_min) {
+ fprintf(stderr,
+ "Expected minimum %d records, found %d\n",
+ count_min, count);
+ abort();
+ }
+ return (ret);
+}
+/*! [log cursor walk] */
+
+static int
+walk_log(WT_SESSION *session)
+{
+ WT_CONNECTION *wt_conn2;
+ WT_CURSOR *cursor, *cursor2;
+ WT_LSN lsn, lsnsave;
+ WT_ITEM logrec_key, logrec_value;
+ WT_SESSION *session2;
+ uint64_t txnid;
+ uint32_t fileid, opcount, optype, rectype;
+ int first, i, in_txn, ret;
+
+ ret = setup_copy(&wt_conn2, &session2);
+ ret = session->open_cursor(session, "log:", NULL, NULL, &cursor);
+ ret = session2->open_cursor(session2, uri, NULL, "raw=true", &cursor2);
+ i = 0;
+ in_txn = 0;
+ txnid = 0;
+ memset(&lsnsave, 0, sizeof(lsnsave));
+ while ((ret = cursor->next(cursor)) == 0) {
+ ret = cursor->get_key(cursor, &lsn.file, &lsn.offset, &opcount);
+ /*
+ * Save one of the LSNs we get back to search for it
+ * later. Pick a later one because we want to walk from
+ * that LSN to the end (where the multi-step transaction
+ * was performed). Just choose the record that is MAX_KEYS.
+ */
+ if (++i == MAX_KEYS)
+ lsnsave = lsn;
+ ret = cursor->get_value(cursor, &txnid, &rectype,
+ &optype, &fileid, &logrec_key, &logrec_value);
+
+ print_record(&lsn, opcount,
+ rectype, optype, txnid, fileid, &logrec_key, &logrec_value);
+
+ /*
+ * If we are in a transaction and this is a new one, end
+ * the previous one.
+ */
+ if (in_txn && opcount == 0) {
+ ret = session2->commit_transaction(session2, NULL);
+ in_txn = 0;
+ }
+
+ /*
+ * If the operation is a put, replay it here on the backup
+ * connection.
+ *
+ * !!!
+ * Minor cheat: the metadata is fileid 0, skip its records.
+ */
+ if (fileid != 0 &&
+ rectype == WT_LOGREC_COMMIT && optype == WT_LOGOP_ROW_PUT) {
+ if (!in_txn) {
+ ret = session2->begin_transaction(session2,
+ NULL);
+ in_txn = 1;
+ }
+ cursor2->set_key(cursor2, &logrec_key);
+ cursor2->set_value(cursor2, &logrec_value);
+ ret = cursor2->insert(cursor2);
+ }
+ }
+ if (in_txn)
+ ret = session2->commit_transaction(session2, NULL);
+
+ ret = cursor2->close(cursor2);
+ /*
+ * Compare the tables after replay. They should be identical.
+ */
+ if (compare_tables(session, session2))
+ printf("compare failed\n");
+ ret = session2->close(session2, NULL);
+ ret = wt_conn2->close(wt_conn2, NULL);
+
+ ret = cursor->reset(cursor);
+ /*! [log cursor set_key] */
+ cursor->set_key(cursor, lsnsave.file, lsnsave.offset, 0);
+ /*! [log cursor set_key] */
+ /*! [log cursor search] */
+ ret = cursor->search(cursor);
+ /*! [log cursor search] */
+ printf("Reset to saved...\n");
+ /*
+ * Walk all records starting with this key.
+ */
+ first = 1;
+ while ((ret = cursor->get_key(cursor,
+ &lsn.file, &lsn.offset, &opcount)) == 0) {
+ if (first) {
+ first = 0;
+ if (lsnsave.file != lsn.file ||
+ lsnsave.offset != lsn.offset) {
+ fprintf(stderr,
+ "search returned the wrong LSN\n");
+ exit (1);
+ }
+ }
+ ret = cursor->get_value(cursor, &txnid, &rectype,
+ &optype, &fileid, &logrec_key, &logrec_value);
+
+ print_record(&lsn, opcount,
+ rectype, optype, txnid, fileid, &logrec_key, &logrec_value);
+
+ ret = cursor->next(cursor);
+ if (ret != 0)
+ break;
+ }
+ ret = cursor->close(cursor);
+ return (ret);
+}
+
+int
+main(void)
+{
+ WT_CONNECTION *wt_conn;
+ WT_CURSOR *cursor;
+ WT_SESSION *session;
+ int count_min, i, record_count, ret;
+ char cmd_buf[256], k[16], v[16];
+
+ count_min = 0;
+ snprintf(cmd_buf, sizeof(cmd_buf), "rm -rf %s %s && mkdir %s %s",
+ home1, home2, home1, home2);
+ if ((ret = system(cmd_buf)) != 0) {
+ fprintf(stderr, "%s: failed ret %d\n", cmd_buf, ret);
+ return (ret);
+ }
+ if ((ret = wiredtiger_open(home1, NULL, CONN_CONFIG, &wt_conn)) != 0) {
+ fprintf(stderr, "Error connecting to %s: %s\n",
+ home1, wiredtiger_strerror(ret));
+ return (ret);
+ }
+
+ ret = wt_conn->open_session(wt_conn, NULL, NULL, &session);
+ ret = session->create(session, uri, "key_format=S,value_format=S");
+ count_min++;
+
+ ret = session->open_cursor(session, uri, NULL, NULL, &cursor);
+ /*
+ * Perform some operations with individual auto-commit transactions.
+ */
+ for (record_count = 0, i = 0; i < MAX_KEYS; i++, record_count++) {
+ snprintf(k, sizeof(k), "key%d", i);
+ snprintf(v, sizeof(v), "value%d", i);
+ cursor->set_key(cursor, k);
+ cursor->set_value(cursor, v);
+ ret = cursor->insert(cursor);
+ count_min++;
+ }
+ ret = session->begin_transaction(session, NULL);
+ /*
+ * Perform some operations within a single transaction.
+ */
+ for (i = MAX_KEYS; i < MAX_KEYS+5; i++, record_count++) {
+ snprintf(k, sizeof(k), "key%d", i);
+ snprintf(v, sizeof(v), "value%d", i);
+ cursor->set_key(cursor, k);
+ cursor->set_value(cursor, v);
+ ret = cursor->insert(cursor);
+ }
+ ret = session->commit_transaction(session, NULL);
+ count_min++;
+ ret = cursor->close(cursor);
+
+ /*! [log cursor printf] */
+ ret = session->log_printf(session, "Wrote %d records", record_count);
+ count_min++;
+ /*! [log cursor printf] */
+
+ /*
+ * Close and reopen the connection so that the log ends up with
+ * a variety of records such as file sync and checkpoint. We
+ * have archiving turned off.
+ */
+ ret = wt_conn->close(wt_conn, NULL);
+ if ((ret = wiredtiger_open(home1, NULL, CONN_CONFIG, &wt_conn)) != 0) {
+ fprintf(stderr, "Error connecting to %s: %s\n",
+ home1, wiredtiger_strerror(ret));
+ return (ret);
+ }
+
+ ret = wt_conn->open_session(wt_conn, NULL, NULL, &session);
+ ret = simple_walk_log(session, count_min);
+ ret = walk_log(session);
+ ret = wt_conn->close(wt_conn, NULL);
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_pack.c b/src/third_party/wiredtiger/examples/c/ex_pack.c
new file mode 100644
index 00000000000..43b57880674
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_pack.c
@@ -0,0 +1,89 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_pack.c
+ * This is an example demonstrating basic packing and unpacking of fields.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <wiredtiger.h>
+
+static const char *home;
+
+int
+main(void)
+{
+ WT_CONNECTION *conn;
+ WT_SESSION *session;
+ int i, j, k, ret;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (getenv("WIREDTIGER_HOME") == NULL) {
+ home = "WT_HOME";
+ ret = system("rm -rf WT_HOME && mkdir WT_HOME");
+ } else
+ home = NULL;
+
+ /* Open a connection to the database, creating it if necessary. */
+ if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0)
+ fprintf(stderr, "Error connecting to %s: %s\n",
+ home, wiredtiger_strerror(ret));
+
+ /* Open a session for the current thread's work. */
+ if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
+ fprintf(stderr, "Error opening a session on %s: %s\n",
+ home, wiredtiger_strerror(ret));
+
+ {
+ /*! [packing] */
+ size_t size;
+ char buf[50];
+
+ ret = wiredtiger_struct_size(session, &size, "iii", 42, 1000, -9);
+ if (size > sizeof(buf)) {
+ /* Allocate a bigger buffer. */
+ }
+
+ ret = wiredtiger_struct_pack(session, buf, size, "iii", 42, 1000, -9);
+
+ ret = wiredtiger_struct_unpack(session, buf, size, "iii", &i, &j, &k);
+ /*! [packing] */
+ }
+
+ /* Note: closing the connection implicitly closes open session(s). */
+ if ((ret = conn->close(conn, NULL)) != 0)
+ fprintf(stderr, "Error closing %s: %s\n",
+ home, wiredtiger_strerror(ret));
+
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_process.c b/src/third_party/wiredtiger/examples/c/ex_process.c
new file mode 100644
index 00000000000..19f395dddaf
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_process.c
@@ -0,0 +1,79 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_process.c
+ * This is an example demonstrating how to connect to a database from
+ * multiple processes.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <wiredtiger.h>
+
+static const char *home;
+
+int
+main(void)
+{
+ int ret;
+ WT_CONNECTION *conn;
+ WT_SESSION *session;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (getenv("WIREDTIGER_HOME") == NULL) {
+ home = "WT_HOME";
+ ret = system("rm -rf WT_HOME && mkdir WT_HOME");
+ } else
+ home = NULL;
+
+ /*! [processes] */
+ /* Open a connection to the database, creating it if necessary. */
+ if ((ret =
+ wiredtiger_open(home, NULL, "create,multiprocess", &conn)) != 0)
+ fprintf(stderr, "Error connecting to %s: %s\n",
+ home, wiredtiger_strerror(ret));
+
+ /* Open a session for the current thread's work. */
+ if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
+ fprintf(stderr, "Error opening a session on %s: %s\n",
+ home, wiredtiger_strerror(ret));
+
+ /* XXX Do some work... */
+
+ /* Note: closing the connection implicitly closes open session(s). */
+ if ((ret = conn->close(conn, NULL)) != 0)
+ fprintf(stderr, "Error closing %s: %s\n",
+ home, wiredtiger_strerror(ret));
+ /*! [processes] */
+
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_schema.c b/src/third_party/wiredtiger/examples/c/ex_schema.c
new file mode 100644
index 00000000000..fdf02d12302
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_schema.c
@@ -0,0 +1,364 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_schema.c
+ * This is an example application demonstrating how to create and access
+ * tables using a schema.
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <wiredtiger.h>
+
+static const char *home;
+
+/*! [schema declaration] */
+/* The C struct for the data we are storing in a WiredTiger table. */
+typedef struct {
+ char country[5];
+ uint16_t year;
+ uint64_t population;
+} POP_RECORD;
+
+static POP_RECORD pop_data[] = {
+ { "AU", 1900, 4000000 },
+ { "AU", 1950, 8267337 },
+ { "AU", 2000, 19053186 },
+ { "CAN", 1900, 5500000 },
+ { "CAN", 1950, 14011422 },
+ { "CAN", 2000, 31099561 },
+ { "UK", 1900, 369000000 },
+ { "UK", 1950, 50127000 },
+ { "UK", 2000, 59522468 },
+ { "USA", 1900, 76212168 },
+ { "USA", 1950, 150697361 },
+ { "USA", 2000, 301279593 },
+ { "", 0, 0 }
+};
+/*! [schema declaration] */
+
+int
+main(void)
+{
+ POP_RECORD *p;
+ WT_CONNECTION *conn;
+ WT_CURSOR *cursor, *cursor2, *join_cursor;
+ WT_SESSION *session;
+ const char *country;
+ uint64_t recno, population;
+ uint16_t year;
+ int ret;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (getenv("WIREDTIGER_HOME") == NULL) {
+ home = "WT_HOME";
+ ret = system("rm -rf WT_HOME && mkdir WT_HOME");
+ } else
+ home = NULL;
+
+ if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0) {
+ fprintf(stderr, "Error connecting to %s: %s\n",
+ home, wiredtiger_strerror(ret));
+ return (ret);
+ }
+ /* Note: error checking omitted for clarity. */
+
+ ret = conn->open_session(conn, NULL, NULL, &session);
+
+ /*! [Create a table with column groups] */
+ /*
+ * Create the population table.
+ * Keys are record numbers, the format for values is (5-byte string,
+ * uint16_t, uint64_t).
+ * See ::wiredtiger_struct_pack for details of the format strings.
+ */
+ ret = session->create(session, "table:poptable",
+ "key_format=r,"
+ "value_format=5sHQ,"
+ "columns=(id,country,year,population),"
+ "colgroups=(main,population)");
+
+ /*
+ * Create two column groups: a primary column group with the country
+ * code, year and population (named "main"), and a population column
+ * group with the population by itself (named "population").
+ */
+ ret = session->create(session,
+ "colgroup:poptable:main", "columns=(country,year,population)");
+ ret = session->create(session,
+ "colgroup:poptable:population", "columns=(population)");
+ /*! [Create a table with column groups] */
+
+ /*! [Create an index] */
+ /* Create an index with a simple key. */
+ ret = session->create(session,
+ "index:poptable:country", "columns=(country)");
+ /*! [Create an index] */
+
+ /*! [Create an index with a composite key] */
+ /* Create an index with a composite key (country,year). */
+ ret = session->create(session,
+ "index:poptable:country_plus_year", "columns=(country,year)");
+ /*! [Create an index with a composite key] */
+
+ /*! [Create an immutable index] */
+ /* Create an immutable index. */
+ ret = session->create(session,
+ "index:poptable:immutable_year", "columns=(year),immutable");
+ /*! [Create an immutable index] */
+
+ /* Insert the records into the table. */
+ ret = session->open_cursor(
+ session, "table:poptable", NULL, "append", &cursor);
+ for (p = pop_data; p->year != 0; p++) {
+ cursor->set_value(cursor, p->country, p->year, p->population);
+ ret = cursor->insert(cursor);
+ }
+ ret = cursor->close(cursor);
+
+ /* Update records in the table. */
+ ret = session->open_cursor(session,
+ "table:poptable", NULL, NULL, &cursor);
+ while ((ret = cursor->next(cursor)) == 0) {
+ ret = cursor->get_key(cursor, &recno);
+ ret = cursor->get_value(cursor, &country, &year, &population);
+ cursor->set_value(cursor, country, year, population + 1);
+ ret = cursor->update(cursor);
+ }
+ ret = cursor->close(cursor);
+
+ /* List the records in the table. */
+ ret = session->open_cursor(session,
+ "table:poptable", NULL, NULL, &cursor);
+ while ((ret = cursor->next(cursor)) == 0) {
+ ret = cursor->get_key(cursor, &recno);
+ ret = cursor->get_value(cursor, &country, &year, &population);
+ printf("ID %" PRIu64, recno);
+ printf(": country %s, year %u, population %" PRIu64 "\n",
+ country, year, population);
+ }
+ ret = cursor->close(cursor);
+
+ /*! [List the records in the table using raw mode.] */
+ /* List the records in the table using raw mode. */
+ ret = session->open_cursor(session,
+ "table:poptable", NULL, "raw", &cursor);
+ while ((ret = cursor->next(cursor)) == 0) {
+ WT_ITEM key, value;
+
+ ret = cursor->get_key(cursor, &key);
+ ret = wiredtiger_struct_unpack(session,
+ key.data, key.size, "r", &recno);
+ printf("ID %" PRIu64, recno);
+
+ ret = cursor->get_value(cursor, &value);
+ ret = wiredtiger_struct_unpack(session,
+ value.data, value.size,
+ "5sHQ", &country, &year, &population);
+ printf(": country %s, year %u, population %" PRIu64 "\n",
+ country, year, population);
+ }
+ /*! [List the records in the table using raw mode.] */
+ ret = cursor->close(cursor);
+
+ /*! [Read population from the primary column group] */
+ /*
+ * Open a cursor on the main column group, and return the information
+ * for a particular country.
+ */
+ ret = session->open_cursor(
+ session, "colgroup:poptable:main", NULL, NULL, &cursor);
+ cursor->set_key(cursor, 2);
+ if ((ret = cursor->search(cursor)) == 0) {
+ ret = cursor->get_value(cursor, &country, &year, &population);
+ printf("ID 2: country %s, year %u, population %" PRIu64 "\n",
+ country, year, population);
+ }
+ /*! [Read population from the primary column group] */
+ ret = cursor->close(cursor);
+
+ /*! [Read population from the standalone column group] */
+ /*
+ * Open a cursor on the population column group, and return the
+ * population of a particular country.
+ */
+ ret = session->open_cursor(session,
+ "colgroup:poptable:population", NULL, NULL, &cursor);
+ cursor->set_key(cursor, 2);
+ if ((ret = cursor->search(cursor)) == 0) {
+ ret = cursor->get_value(cursor, &population);
+ printf("ID 2: population %" PRIu64 "\n", population);
+ }
+ /*! [Read population from the standalone column group] */
+ ret = cursor->close(cursor);
+
+ /*! [Search in a simple index] */
+ /* Search in a simple index. */
+ ret = session->open_cursor(session,
+ "index:poptable:country", NULL, NULL, &cursor);
+ cursor->set_key(cursor, "AU\0\0\0");
+ ret = cursor->search(cursor);
+ ret = cursor->get_value(cursor, &country, &year, &population);
+ printf("AU: country %s, year %u, population %" PRIu64 "\n",
+ country, (unsigned int)year, population);
+ /*! [Search in a simple index] */
+ ret = cursor->close(cursor);
+
+ /*! [Search in a composite index] */
+ /* Search in a composite index. */
+ ret = session->open_cursor(session,
+ "index:poptable:country_plus_year", NULL, NULL, &cursor);
+ cursor->set_key(cursor, "USA\0\0", (uint16_t)1900);
+ ret = cursor->search(cursor);
+ ret = cursor->get_value(cursor, &country, &year, &population);
+ printf("US 1900: country %s, year %u, population %" PRIu64 "\n",
+ country, (unsigned int)year, population);
+ /*! [Search in a composite index] */
+ ret = cursor->close(cursor);
+
+ /*! [Return a subset of values from the table] */
+ /*
+ * Use a projection to return just the table's country and year
+ * columns.
+ */
+ ret = session->open_cursor(session,
+ "table:poptable(country,year)", NULL, NULL, &cursor);
+ while ((ret = cursor->next(cursor)) == 0) {
+ ret = cursor->get_value(cursor, &country, &year);
+ printf("country %s, year %u\n", country, year);
+ }
+ /*! [Return a subset of values from the table] */
+ ret = cursor->close(cursor);
+
+ /*! [Return a subset of values from the table using raw mode] */
+ /*
+ * Use a projection to return just the table's country and year
+ * columns, using raw mode.
+ */
+ ret = session->open_cursor(session,
+ "table:poptable(country,year)", NULL, "raw", &cursor);
+ while ((ret = cursor->next(cursor)) == 0) {
+ WT_ITEM value;
+
+ ret = cursor->get_value(cursor, &value);
+ ret = wiredtiger_struct_unpack(
+ session, value.data, value.size, "5sH", &country, &year);
+ printf("country %s, year %u\n", country, year);
+ }
+ /*! [Return a subset of values from the table using raw mode] */
+ ret = cursor->close(cursor);
+
+ /*! [Return the table's record number key using an index] */
+ /*
+ * Use a projection to return just the table's record number key
+ * from an index.
+ */
+ ret = session->open_cursor(session,
+ "index:poptable:country_plus_year(id)", NULL, NULL, &cursor);
+ while ((ret = cursor->next(cursor)) == 0) {
+ ret = cursor->get_key(cursor, &country, &year);
+ ret = cursor->get_value(cursor, &recno);
+ printf("row ID %" PRIu64 ": country %s, year %u\n",
+ recno, country, year);
+ }
+ /*! [Return the table's record number key using an index] */
+ ret = cursor->close(cursor);
+
+ /*! [Return a subset of the value columns from an index] */
+ /*
+ * Use a projection to return just the population column from an
+ * index.
+ */
+ ret = session->open_cursor(session,
+ "index:poptable:country_plus_year(population)",
+ NULL, NULL, &cursor);
+ while ((ret = cursor->next(cursor)) == 0) {
+ ret = cursor->get_key(cursor, &country, &year);
+ ret = cursor->get_value(cursor, &population);
+ printf("population %" PRIu64 ": country %s, year %u\n",
+ population, country, year);
+ }
+ /*! [Return a subset of the value columns from an index] */
+ ret = cursor->close(cursor);
+
+ /*! [Access only the index] */
+ /*
+ * Use a projection to avoid accessing any other column groups when
+ * using an index: supply an empty list of value columns.
+ */
+ ret = session->open_cursor(session,
+ "index:poptable:country_plus_year()", NULL, NULL, &cursor);
+ while ((ret = cursor->next(cursor)) == 0) {
+ ret = cursor->get_key(cursor, &country, &year);
+ printf("country %s, year %u\n", country, year);
+ }
+ /*! [Access only the index] */
+ ret = cursor->close(cursor);
+
+ /*! [Join cursors] */
+ /* Open cursors needed by the join. */
+ ret = session->open_cursor(session,
+ "join:table:poptable", NULL, NULL, &join_cursor);
+ ret = session->open_cursor(session,
+ "index:poptable:country", NULL, NULL, &cursor);
+ ret = session->open_cursor(session,
+ "index:poptable:immutable_year", NULL, NULL, &cursor2);
+
+ /* select values WHERE country == "AU" AND year > 1900 */
+ cursor->set_key(cursor, "AU\0\0\0");
+ ret = cursor->search(cursor);
+ ret = session->join(session, join_cursor, cursor,
+ "compare=eq,count=10");
+ cursor2->set_key(cursor2, (uint16_t)1900);
+ ret = cursor2->search(cursor2);
+ ret = session->join(session, join_cursor, cursor2,
+ "compare=gt,count=10,strategy=bloom");
+
+ /* List the values that are joined */
+ while ((ret = join_cursor->next(join_cursor)) == 0) {
+ ret = join_cursor->get_key(join_cursor, &recno);
+ ret = join_cursor->get_value(join_cursor, &country, &year,
+ &population);
+ printf("ID %" PRIu64, recno);
+ printf(": country %s, year %u, population %" PRIu64 "\n",
+ country, year, population);
+ }
+ /*! [Join cursors] */
+ ret = join_cursor->close(join_cursor);
+ ret = cursor2->close(cursor2);
+ ret = cursor->close(cursor);
+
+ ret = conn->close(conn, NULL);
+
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_scope.c b/src/third_party/wiredtiger/examples/c/ex_scope.c
new file mode 100644
index 00000000000..93878ec7e3d
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_scope.c
@@ -0,0 +1,214 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_scope.c
+ * demonstrates the scope of buffers holding cursor keys and values.
+ */
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <wiredtiger.h>
+
+#ifdef _WIN32
+/* snprintf is not supported on <= VS2013 */
+#define snprintf _snprintf
+#endif
+
+static const char *home;
+
+static int
+cursor_scope_ops(WT_CURSOR *cursor)
+{
+ struct {
+ const char *op;
+ const char *key;
+ const char *value;
+ int (*apply)(WT_CURSOR *);
+ } *op, ops[] = {
+ { "insert", "key1", "value1", cursor->insert, },
+ { "update", "key1", "value2", cursor->update, },
+ { "search", "key1", "value2", cursor->search, },
+ { "remove", "key1", "value2", cursor->remove, },
+ { NULL, NULL, NULL, NULL }
+ };
+ WT_SESSION *session;
+ const char *key, *value;
+ char keybuf[10], valuebuf[10];
+ int ret;
+
+ session = cursor->session;
+
+ for (op = ops; op->key != NULL; op++) {
+ key = value = NULL;
+
+ /*! [cursor scope operation] */
+ (void)snprintf(keybuf, sizeof(keybuf), "%s", op->key);
+ cursor->set_key(cursor, keybuf);
+ (void)snprintf(valuebuf, sizeof(valuebuf), "%s", op->value);
+ cursor->set_value(cursor, valuebuf);
+
+ /*
+ * The application must keep key and value memory valid until
+ * the next operation that positions the cursor, modifies the
+ * data, or resets or closes the cursor.
+ *
+ * Modifying either the key or value buffers is not permitted.
+ */
+
+ /* Apply the operation (insert, update, search or remove). */
+ if ((ret = op->apply(cursor)) != 0) {
+ fprintf(stderr,
+ "%s: error performing the operation: %s\n",
+ op->op, session->strerror(session, ret));
+ return (ret);
+ }
+
+ /*
+ * The cursor no longer references application memory, so
+ * application buffers can be safely overwritten.
+ */
+ strcpy(keybuf, "no key");
+ strcpy(valuebuf, "no value");
+
+ /*
+ * Check that get_key/value behave as expected after the
+ * operation.
+ */
+ if (op->apply == cursor->insert) {
+ /*
+ * WT_CURSOR::insert no longer references application
+ * memory, but as it does not position the cursor, it
+ * doesn't reference memory owned by the cursor, either.
+ */
+ if ((ret = cursor->get_key(cursor, &key)) == 0 ||
+ (ret = cursor->get_value(cursor, &value)) == 0) {
+ fprintf(stderr,
+ "%s: error in s get_key/value: %s\n",
+ op->op, session->strerror(session, ret));
+ return (ret);
+ }
+ continue;
+ }
+ if (op->apply == cursor->remove) {
+ /*
+ * WT_CURSOR::remove no longer references application
+ * memory; as it does not position the cursor, it will
+ * reference key memory owned by the cursor, but has no
+ * value.
+ */
+ if ((ret = cursor->get_key(cursor, &key)) != 0 ||
+ (ret = cursor->get_value(cursor, &value)) == 0) {
+ fprintf(stderr,
+ "%s: error in get_key/value: %s\n",
+ op->op, session->strerror(session, ret));
+ return (ret);
+ }
+ } else /* search, update */{
+ /*
+ * WT_CURSOR::search and WT_CURSOR::update no longer
+ * reference application memory; as they position the
+ * cursor, they will reference key/value memory owned
+ * by the cursor.
+ */
+ if ((ret = cursor->get_key(cursor, &key)) != 0 ||
+ (ret = cursor->get_value(cursor, &value)) != 0) {
+ fprintf(stderr,
+ "%s: error in get_key/value: %s\n",
+ op->op, session->strerror(session, ret));
+ return (ret);
+ }
+ }
+
+ /*
+ * Modifying the memory referenced by either key or value is
+ * not permitted.
+ *
+ * Check that the cursor's key and value are what we expect.
+ */
+ if (key == keybuf ||
+ (op->apply != cursor->remove && value == valuebuf)) {
+ fprintf(stderr,
+ "%s: cursor points at application memory!\n",
+ op->op);
+ return (EINVAL);
+ }
+
+ if (strcmp(key, op->key) != 0 ||
+ (op->apply != cursor->remove &&
+ strcmp(value, op->value) != 0)) {
+ fprintf(stderr,
+ "%s: unexpected key / value!\n", op->op);
+ return (EINVAL);
+ }
+ /*! [cursor scope operation] */
+ }
+
+ return (0);
+}
+
+int
+main(void)
+{
+ WT_CONNECTION *conn;
+ WT_CURSOR *cursor;
+ WT_SESSION *session;
+ int ret, tret;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (getenv("WIREDTIGER_HOME") == NULL) {
+ home = "WT_HOME";
+ ret = system("rm -rf WT_HOME && mkdir WT_HOME");
+ } else
+ home = NULL;
+
+ /* Open a connection, create a simple table, open a cursor. */
+ if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0 ||
+ (ret = conn->open_session(conn, NULL, NULL, &session)) != 0) {
+ fprintf(stderr, "Error connecting to %s: %s\n",
+ home, wiredtiger_strerror(ret));
+ return (ret);
+ }
+
+ ret = session->create(session,
+ "table:scope", "key_format=S,value_format=S,columns=(k,v)");
+
+ ret = session->open_cursor(session,
+ "table:scope", NULL, NULL, &cursor);
+
+ ret = cursor_scope_ops(cursor);
+
+ /* Close the connection and clean up. */
+ if ((tret = conn->close(conn, NULL)) != 0 && ret == 0)
+ ret = tret;
+
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_stat.c b/src/third_party/wiredtiger/examples/c/ex_stat.c
new file mode 100644
index 00000000000..65402230eb8
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_stat.c
@@ -0,0 +1,227 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_stat.c
+ * This is an example demonstrating how to query database statistics.
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <wiredtiger.h>
+
+int print_cursor(WT_CURSOR *);
+int print_database_stats(WT_SESSION *);
+int print_file_stats(WT_SESSION *);
+int print_overflow_pages(WT_SESSION *);
+int get_stat(WT_CURSOR *cursor, int stat_field, uint64_t *valuep);
+int print_derived_stats(WT_SESSION *);
+
+static const char *home;
+
+/*! [statistics display function] */
+int
+print_cursor(WT_CURSOR *cursor)
+{
+ const char *desc, *pvalue;
+ uint64_t value;
+ int ret;
+
+ while ((ret = cursor->next(cursor)) == 0 &&
+ (ret = cursor->get_value(cursor, &desc, &pvalue, &value)) == 0)
+ if (value != 0)
+ printf("%s=%s\n", desc, pvalue);
+
+ return (ret == WT_NOTFOUND ? 0 : ret);
+}
+/*! [statistics display function] */
+
+int
+print_database_stats(WT_SESSION *session)
+{
+ WT_CURSOR *cursor;
+ int ret;
+
+ /*! [statistics database function] */
+ if ((ret = session->open_cursor(session,
+ "statistics:", NULL, NULL, &cursor)) != 0)
+ return (ret);
+
+ ret = print_cursor(cursor);
+ ret = cursor->close(cursor);
+ /*! [statistics database function] */
+
+ return (ret);
+}
+
+int
+print_file_stats(WT_SESSION *session)
+{
+ WT_CURSOR *cursor;
+ int ret;
+
+ /*! [statistics table function] */
+ if ((ret = session->open_cursor(session,
+ "statistics:table:access", NULL, NULL, &cursor)) != 0)
+ return (ret);
+
+ ret = print_cursor(cursor);
+ ret = cursor->close(cursor);
+ /*! [statistics table function] */
+
+ return (ret);
+}
+
+int
+print_overflow_pages(WT_SESSION *session)
+{
+ /*! [statistics retrieve by key] */
+ WT_CURSOR *cursor;
+ const char *desc, *pvalue;
+ uint64_t value;
+ int ret;
+
+ if ((ret = session->open_cursor(session,
+ "statistics:table:access", NULL, NULL, &cursor)) != 0)
+ return (ret);
+
+ cursor->set_key(cursor, WT_STAT_DSRC_BTREE_OVERFLOW);
+ ret = cursor->search(cursor);
+ ret = cursor->get_value(cursor, &desc, &pvalue, &value);
+ printf("%s=%s\n", desc, pvalue);
+
+ ret = cursor->close(cursor);
+ /*! [statistics retrieve by key] */
+
+ return (ret);
+}
+
+/*! [statistics calculation helper function] */
+int
+get_stat(WT_CURSOR *cursor, int stat_field, uint64_t *valuep)
+{
+ const char *desc, *pvalue;
+ int ret;
+
+ cursor->set_key(cursor, stat_field);
+ if ((ret = cursor->search(cursor)) != 0)
+ return (ret);
+
+ return (cursor->get_value(cursor, &desc, &pvalue, valuep));
+}
+/*! [statistics calculation helper function] */
+
+int
+print_derived_stats(WT_SESSION *session)
+{
+ WT_CURSOR *cursor;
+ int ret;
+
+ /*! [statistics calculate open table stats] */
+ if ((ret = session->open_cursor(session,
+ "statistics:table:access", NULL, NULL, &cursor)) != 0)
+ return (ret);
+ /*! [statistics calculate open table stats] */
+
+ {
+ /*! [statistics calculate table fragmentation] */
+ uint64_t ckpt_size, file_size, percent;
+ ret = get_stat(cursor, WT_STAT_DSRC_BLOCK_CHECKPOINT_SIZE, &ckpt_size);
+ ret = get_stat(cursor, WT_STAT_DSRC_BLOCK_SIZE, &file_size);
+
+ percent = 0;
+ if (file_size != 0)
+ percent = 100 * ((file_size - ckpt_size) / file_size);
+ printf("Table is %" PRIu64 "%% fragmented\n", percent);
+ /*! [statistics calculate table fragmentation] */
+ }
+
+ {
+ /*! [statistics calculate write amplification] */
+ uint64_t app_insert, app_remove, app_update, fs_writes;
+
+ ret = get_stat(cursor, WT_STAT_DSRC_CURSOR_INSERT_BYTES, &app_insert);
+ ret = get_stat(cursor, WT_STAT_DSRC_CURSOR_REMOVE_BYTES, &app_remove);
+ ret = get_stat(cursor, WT_STAT_DSRC_CURSOR_UPDATE_BYTES, &app_update);
+
+ ret = get_stat(cursor, WT_STAT_DSRC_CACHE_BYTES_WRITE, &fs_writes);
+
+ if (app_insert + app_remove + app_update != 0)
+ printf("Write amplification is %.2lf\n",
+ (double)fs_writes / (app_insert + app_remove + app_update));
+ /*! [statistics calculate write amplification] */
+ }
+
+ ret = cursor->close(cursor);
+
+ return (ret);
+}
+
+int
+main(void)
+{
+ WT_CONNECTION *conn;
+ WT_CURSOR *cursor;
+ WT_SESSION *session;
+ int ret;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (getenv("WIREDTIGER_HOME") == NULL) {
+ home = "WT_HOME";
+ ret = system("rm -rf WT_HOME && mkdir WT_HOME");
+ } else
+ home = NULL;
+
+ ret = wiredtiger_open(home, NULL, "create,statistics=(all)", &conn);
+ ret = conn->open_session(conn, NULL, NULL, &session);
+ ret = session->create(
+ session, "table:access", "key_format=S,value_format=S");
+
+ ret = session->open_cursor(
+ session, "table:access", NULL, NULL, &cursor);
+ cursor->set_key(cursor, "key");
+ cursor->set_value(cursor, "value");
+ ret = cursor->insert(cursor);
+ ret = cursor->close(cursor);
+
+ ret = session->checkpoint(session, NULL);
+
+ ret = print_database_stats(session);
+
+ ret = print_file_stats(session);
+
+ ret = print_overflow_pages(session);
+
+ ret = print_derived_stats(session);
+
+ return (conn->close(conn, NULL) == 0 ? ret : EXIT_FAILURE);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_sync.c b/src/third_party/wiredtiger/examples/c/ex_sync.c
new file mode 100644
index 00000000000..8c3a6463a82
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_sync.c
@@ -0,0 +1,153 @@
+/*
+ * Public Domain 2014-2016 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.
+ *
+ * ex_sync.c
+ * demonstrates how to use the transaction sync configuration.
+ */
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef _WIN32
+#include <unistd.h>
+#else
+/* snprintf is not supported on <= VS2013 */
+#define snprintf _snprintf
+#endif
+
+#include <wiredtiger.h>
+
+static const char *home = "WT_HOME";
+
+static const char * const uri = "table:test";
+
+#define CONN_CONFIG "create,cache_size=100MB,log=(archive=false,enabled=true)"
+#define MAX_KEYS 100
+
+int
+main(void)
+{
+ WT_CONNECTION *wt_conn;
+ WT_CURSOR *cursor;
+ WT_SESSION *session;
+ int i, record_count, ret;
+ char cmd_buf[256], k[16], v[16];
+ const char *conf;
+
+ snprintf(cmd_buf, sizeof(cmd_buf), "rm -rf %s && mkdir %s",
+ home, home);
+ if ((ret = system(cmd_buf)) != 0) {
+ fprintf(stderr, "%s: failed ret %d\n", cmd_buf, ret);
+ return (ret);
+ }
+ if ((ret = wiredtiger_open(home, NULL, CONN_CONFIG, &wt_conn)) != 0) {
+ fprintf(stderr, "Error connecting to %s: %s\n",
+ home, wiredtiger_strerror(ret));
+ return (ret);
+ }
+
+ ret = wt_conn->open_session(wt_conn, NULL, NULL, &session);
+ ret = session->create(session, uri, "key_format=S,value_format=S");
+
+ ret = session->open_cursor(session, uri, NULL, NULL, &cursor);
+ /*
+ * Perform some operations with individual auto-commit transactions.
+ */
+ ret = session->begin_transaction(session, NULL);
+ for (record_count = 0, i = 0; i < MAX_KEYS; i++, record_count++) {
+ if (i == MAX_KEYS/2) {
+ ret = session->commit_transaction(
+ session, "sync=background");
+ ret = session->transaction_sync(
+ session, "timeout_ms=0");
+ if (ret == ETIMEDOUT)
+ printf("Transactions not yet stable\n");
+ else if (ret != 0)
+ printf("Got error %d\n", ret);
+ ret = session->begin_transaction(session, NULL);
+ } else {
+ if ((record_count % 3) == 0)
+ conf = "sync=background";
+ else
+ conf = "sync=off";
+ ret = session->commit_transaction(session, conf);
+ ret = session->begin_transaction(session, NULL);
+ }
+ snprintf(k, sizeof(k), "key%d", i);
+ snprintf(v, sizeof(v), "value%d", i);
+ cursor->set_key(cursor, k);
+ cursor->set_value(cursor, v);
+ ret = cursor->insert(cursor);
+ }
+ ret = session->commit_transaction(session, "sync=background");
+ printf("Wait forever until stable\n");
+ ret = session->transaction_sync(session, NULL);
+ printf("Transactions now stable\n");
+ ret = session->begin_transaction(session, NULL);
+ /*
+ * Perform some operations within a single transaction.
+ */
+ for (i = MAX_KEYS; i < MAX_KEYS+5; i++, record_count++) {
+ snprintf(k, sizeof(k), "key%d", i);
+ snprintf(v, sizeof(v), "value%d", i);
+ cursor->set_key(cursor, k);
+ cursor->set_value(cursor, v);
+ ret = cursor->insert(cursor);
+ }
+ ret = session->commit_transaction(session, "sync=on");
+ ret = session->transaction_sync(session, "timeout_ms=0");
+ if (ret != 0)
+ fprintf(stderr,
+ "Unexpected error %d from WT_SESSION::transaction_sync\n",
+ ret);
+ /*
+ * Demonstrate using log_flush to force the log to disk.
+ */
+ for (i = 0; i < MAX_KEYS; i++, record_count++) {
+ snprintf(k, sizeof(k), "key%d", record_count);
+ snprintf(v, sizeof(v), "value%d", record_count);
+ cursor->set_key(cursor, k);
+ cursor->set_value(cursor, v);
+ ret = cursor->insert(cursor);
+ }
+ ret = session->log_flush(session, "sync=on");
+
+ for (i = 0; i < MAX_KEYS; i++, record_count++) {
+ snprintf(k, sizeof(k), "key%d", record_count);
+ snprintf(v, sizeof(v), "value%d", record_count);
+ cursor->set_key(cursor, k);
+ cursor->set_value(cursor, v);
+ ret = cursor->insert(cursor);
+ }
+ ret = cursor->close(cursor);
+ ret = session->log_flush(session, "sync=off");
+ ret = session->log_flush(session, "sync=on");
+
+ ret = wt_conn->close(wt_conn, NULL);
+ return (ret);
+}
diff --git a/src/third_party/wiredtiger/examples/c/ex_thread.c b/src/third_party/wiredtiger/examples/c/ex_thread.c
new file mode 100644
index 00000000000..a72211b6243
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/c/ex_thread.c
@@ -0,0 +1,127 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_thread.c
+ * This is an example demonstrating how to create and access a simple
+ * table from multiple threads.
+ */
+
+#ifndef _WIN32
+#include <pthread.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _WIN32
+#include "windows_shim.h"
+#endif
+
+#include <wiredtiger.h>
+
+static const char *home;
+
+void *scan_thread(void *arg);
+
+#define NUM_THREADS 10
+
+/*! [thread scan] */
+void *
+scan_thread(void *conn_arg)
+{
+ WT_CONNECTION *conn;
+ WT_CURSOR *cursor;
+ WT_SESSION *session;
+ const char *key, *value;
+ int ret;
+
+ conn = conn_arg;
+ ret = conn->open_session(conn, NULL, NULL, &session);
+ ret = session->open_cursor(
+ session, "table:access", NULL, NULL, &cursor);
+
+ /* Show all records. */
+ while ((ret = cursor->next(cursor)) == 0) {
+ ret = cursor->get_key(cursor, &key);
+ ret = cursor->get_value(cursor, &value);
+
+ printf("Got record: %s : %s\n", key, value);
+ }
+ if (ret != WT_NOTFOUND)
+ fprintf(stderr,
+ "WT_CURSOR.next: %s\n", session->strerror(session, ret));
+
+ return (NULL);
+}
+/*! [thread scan] */
+
+/*! [thread main] */
+int
+main(void)
+{
+ WT_CONNECTION *conn;
+ WT_SESSION *session;
+ WT_CURSOR *cursor;
+ pthread_t threads[NUM_THREADS];
+ int i, ret;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (getenv("WIREDTIGER_HOME") == NULL) {
+ home = "WT_HOME";
+ ret = system("rm -rf WT_HOME && mkdir WT_HOME");
+ } else
+ home = NULL;
+
+ if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0)
+ fprintf(stderr, "Error connecting to %s: %s\n",
+ home, wiredtiger_strerror(ret));
+ /* Note: further error checking omitted for clarity. */
+
+ ret = conn->open_session(conn, NULL, NULL, &session);
+ ret = session->create(session, "table:access",
+ "key_format=S,value_format=S");
+ ret = session->open_cursor(session, "table:access", NULL,
+ "overwrite", &cursor);
+ cursor->set_key(cursor, "key1");
+ cursor->set_value(cursor, "value1");
+ ret = cursor->insert(cursor);
+ ret = session->close(session, NULL);
+
+ for (i = 0; i < NUM_THREADS; i++)
+ ret = pthread_create(&threads[i], NULL, scan_thread, conn);
+
+ for (i = 0; i < NUM_THREADS; i++)
+ ret = pthread_join(threads[i], NULL);
+
+ ret = conn->close(conn, NULL);
+
+ return (ret);
+}
+/*! [thread main] */
diff --git a/src/third_party/wiredtiger/examples/java/Makefile.am b/src/third_party/wiredtiger/examples/java/Makefile.am
new file mode 100644
index 00000000000..c7fbfffa48c
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/java/Makefile.am
@@ -0,0 +1,21 @@
+AM_CPPFLAGS = -I$(abs_top_builddir)
+
+JAVAEXAMPLES = $(top_srcdir)/examples/java/com/wiredtiger/examples
+
+# TODO: How to add to existing Javadoc from main API?
+# JDOCDIR = $(top_srcdir)/docs/java
+# java_DATA = $(JDOCDIR)/index.html
+
+javadir = $(datadir)/java
+dist_java_JAVA = \
+ $(JAVAEXAMPLES)/ex_access.java
+
+all-local: wiredtiger.jar
+
+$(JDOCDIR)/index.html: $(dist_java_JAVA)
+ mkdir -p $(JDOCDIR)
+ javadoc -public -d $(JDOCDIR) -link http://docs.oracle.com/javase/6/docs/api $(JAVAEXAMPLES)/[A-Z]*.java
+
+wiredtiger.jar: $(dist_java_JAVA)
+ (cd $(top_builddir) && \
+ $(JAR) -cf wiredtiger.jar com/)
diff --git a/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_access.java b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_access.java
new file mode 100644
index 00000000000..104f86d5545
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_access.java
@@ -0,0 +1,94 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_access.java
+ * demonstrates how to create and access a simple table.
+ */
+package com.wiredtiger.examples;
+import com.wiredtiger.db.*;
+
+public class ex_access {
+ public static void main(String[] args) {
+ /*! [access example connection] */
+ Connection conn;
+ Session s;
+ Cursor c;
+
+ try {
+ conn = wiredtiger.open("WT_HOME", "create");
+ s = conn.open_session(null);
+ } catch (WiredTigerException wte) {
+ System.err.println("WiredTigerException: " + wte);
+ return;
+ }
+ /*! [access example connection] */
+ try {
+ /*! [access example table create] */
+ s.create("table:t", "key_format=S,value_format=u");
+ /*! [access example table create] */
+ /*! [access example cursor open] */
+ c = s.open_cursor("table:t", null, null);
+ /*! [access example cursor open] */
+ } catch (WiredTigerException wte) {
+ System.err.println("WiredTigerException: " + wte);
+ return;
+ }
+ System.out.println("Key format: " + c.getKeyFormat());
+ System.out.println("Value format: " + c.getValueFormat());
+ /*! [access example cursor insert] */
+ try {
+ c.putKeyString("foo");
+ c.putValueByteArray("bar".getBytes());
+ c.insert();
+ } catch (WiredTigerPackingException wtpe) {
+ System.err.println("WiredTigerPackingException: " + wtpe);
+ } catch (WiredTigerException wte) {
+ System.err.println("WiredTigerException: " + wte);
+ }
+ /*! [access example cursor insert] */
+ /*! [access example cursor list] */
+ try {
+ c.reset();
+ while (c.next() == 0) {
+ System.out.println("Got: " + c.getKeyString());
+ }
+ } catch (WiredTigerPackingException wtpe) {
+ System.err.println("WiredTigerPackingException: " + wtpe);
+ } catch (WiredTigerException wte) {
+ System.err.println("WiredTigerException: " + wte);
+ }
+ /*! [access example cursor list] */
+
+ /*! [access example close] */
+ try {
+ conn.close(null);
+ } catch (WiredTigerException wte) {
+ System.err.println("WiredTigerException: " + wte);
+ }
+ /*! [access example close] */
+ }
+}
diff --git a/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_all.java b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_all.java
new file mode 100644
index 00000000000..153f12d3e27
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_all.java
@@ -0,0 +1,1036 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_all.java
+ * Containing a call to every method in the WiredTiger API.
+ *
+ * It doesn't do anything very useful, just demonstrates how to call each
+ * method. This file is used to populate the API reference with code
+ * fragments.
+ */
+package com.wiredtiger.examples;
+import com.wiredtiger.db.*;
+import java.io.*;
+import java.nio.*;
+
+/* Note: indentation in non-standard so it will display nicely in doc. */
+public class ex_all {
+
+public static String progname = "ex_all";
+
+public static int cursor_ops(Session session)
+ throws WiredTigerException
+{
+ Cursor cursor;
+ int ret;
+
+ /*! [Open a cursor] */
+ cursor = session.open_cursor("table:mytable", null, null);
+ /*! [Open a cursor] */
+
+ /*! [Open a cursor on the metadata] */
+ cursor = session.open_cursor("metadata:", null, null);
+ /*! [Open a cursor on the metadata] */
+
+ {
+ Cursor duplicate;
+ String key = "some key";
+ /*! [Duplicate a cursor] */
+ cursor = session.open_cursor("table:mytable", null, null);
+ cursor.putKeyString(key);
+ ret = cursor.search();
+
+ /* Duplicate the cursor. */
+ duplicate = session.open_cursor(null, cursor, null);
+ /*! [Duplicate a cursor] */
+ }
+
+ {
+ Cursor overwrite_cursor;
+ String key = "some key", value = "some value";
+ /*! [Reconfigure a cursor] */
+ cursor = session.open_cursor("table:mytable", null, null);
+ cursor.putKeyString(key);
+
+ /* Reconfigure the cursor to overwrite the record. */
+ overwrite_cursor = session.open_cursor(null, cursor, "overwrite");
+ ret = cursor.close();
+
+ overwrite_cursor.putValueString(value);
+ ret = overwrite_cursor.insert();
+ /*! [Reconfigure a cursor] */
+ }
+
+ {
+ /*! [boolean configuration string example] */
+ cursor = session.open_cursor("table:mytable", null, "overwrite");
+ cursor = session.open_cursor("table:mytable", null, "overwrite=true");
+ cursor = session.open_cursor("table:mytable", null, "overwrite=1");
+ /*! [boolean configuration string example] */
+ }
+
+ {
+ /*! [open a named checkpoint] */
+ cursor = session.open_cursor("table:mytable", null, "checkpoint=midnight");
+ /*! [open a named checkpoint] */
+ }
+
+ {
+ /*! [open the default checkpoint] */
+ cursor = session.open_cursor("table:mytable", null,
+ "checkpoint=WiredTigerCheckpoint");
+ /*! [open the default checkpoint] */
+ }
+
+ {
+ /*! [Get the cursor's string key] */
+ String key; /* Get the cursor's string key. */
+ key = cursor.getKeyString();
+ /*! [Get the cursor's string key] */
+ }
+
+ {
+ /*! [Set the cursor's string key] */
+ /* Set the cursor's string key. */
+ String key = "another key";
+ cursor.putKeyString(key);
+ /*! [Set the cursor's string key] */
+ }
+
+ {
+ /*! [Get the cursor's record number key] */
+ long recno; /* Get the cursor's record number key. */
+ recno = cursor.getKeyLong();
+ /*! [Get the cursor's record number key] */
+ }
+
+ {
+ /*! [Set the cursor's record number key] */
+ long recno = 37; /* Set the cursor's record number key. */
+ cursor.putKeyLong(recno);
+ /*! [Set the cursor's record number key] */
+ }
+
+ {
+ /*! [Get the cursor's composite key] */
+ /* Get the cursor's "SiH" format composite key. */
+ String first;
+ int second;
+ short third;
+
+ first = cursor.getKeyString();
+ second = cursor.getKeyInt();
+ third = cursor.getKeyShort();
+ /*! [Get the cursor's composite key] */
+ }
+
+ {
+ /*! [Set the cursor's composite key] */
+ /* Set the cursor's "SiH" format composite key. */
+ cursor.putKeyString("first");
+ cursor.putKeyInt(5);
+ cursor.putKeyShort((short)7);
+ /*! [Set the cursor's composite key] */
+ }
+
+ {
+ /*! [Get the cursor's string value] */
+ String value; /* Get the cursor's string value. */
+ value = cursor.getValueString();
+ /*! [Get the cursor's string value] */
+ }
+
+ {
+ /*! [Set the cursor's string value] */
+ /* Set the cursor's string value. */
+ String value = "another value";
+ cursor.putValueString(value);
+ /*! [Set the cursor's string value] */
+ }
+
+ {
+ /*! [Get the cursor's raw value] */
+ byte[] value; /* Get the cursor's raw value. */
+ value = cursor.getValueByteArray();
+ /*! [Get the cursor's raw value] */
+ }
+
+ {
+ /*! [Set the cursor's raw value] */
+ byte[] value; /* Set the cursor's raw value. */
+ value = "another value".getBytes();
+ cursor.putValueByteArray(value);
+ /*! [Set the cursor's raw value] */
+ }
+
+ /*! [Return the next record] */
+ ret = cursor.next();
+ /*! [Return the next record] */
+
+ /*! [Return the previous record] */
+ ret = cursor.prev();
+ /*! [Return the previous record] */
+
+ /*! [Reset the cursor] */
+ ret = cursor.reset();
+ /*! [Reset the cursor] */
+
+ {
+ Cursor other = null;
+ /*! [Cursor comparison] */
+ int compare;
+ compare = cursor.compare(other);
+ if (compare == 0) {
+ /* Cursors reference the same key */
+ } else if (compare < 0) {
+ /* Cursor key less than other key */
+ } else if (compare > 0) {
+ /* Cursor key greater than other key */
+ }
+ /*! [Cursor comparison] */
+ }
+
+ {
+ Cursor other = null;
+ /*! [Cursor equality] */
+ int compare;
+ compare = cursor.equals(other);
+ if (compare == 0) {
+ /* redtiger.iCursors reference the same key */
+ } else {
+ /* Cursors don't reference the same key */
+ }
+ /*! [Cursor equality] */
+ }
+
+ {
+ /*! [Search for an exact match] */
+ String key = "some key";
+ cursor.putKeyString(key);
+ ret = cursor.search();
+ /*! [Search for an exact match] */
+ }
+
+ cursor_search_near(cursor);
+
+ {
+ /*! [Insert a new record or overwrite an existing record] */
+ /* Insert a new record or overwrite an existing record. */
+ String key = "some key", value = "some value";
+ cursor = session.open_cursor("table:mytable", null, null);
+ cursor.putKeyString(key);
+ cursor.putValueString(value);
+ ret = cursor.insert();
+ /*! [Insert a new record or overwrite an existing record] */
+ }
+
+ {
+ /*! [Insert a new record and fail if the record exists] */
+ /* Insert a new record and fail if the record exists. */
+ String key = "some key", value = "some value";
+ cursor = session.open_cursor("table:mytable", null, "overwrite=false");
+ cursor.putKeyString(key);
+ cursor.putValueString(value);
+ ret = cursor.insert();
+ /*! [Insert a new record and fail if the record exists] */
+ }
+
+ {
+ /*! [Insert a new record and assign a record number] */
+ /* Insert a new record and assign a record number. */
+ long recno;
+ String value = "some value";
+ cursor = session.open_cursor("table:mytable", null, "append");
+ cursor.putValueString(value);
+ ret = cursor.insert();
+ if (ret == 0)
+ recno = cursor.getKeyLong();
+ /*! [Insert a new record and assign a record number] */
+ }
+
+ {
+ /*! [Update an existing record or insert a new record] */
+ String key = "some key", value = "some value";
+ cursor = session.open_cursor("table:mytable", null, null);
+ cursor.putKeyString(key);
+ cursor.putValueString(value);
+ ret = cursor.update();
+ /*! [Update an existing record or insert a new record] */
+ }
+
+ {
+ /*! [Update an existing record and fail if DNE] */
+ String key = "some key", value = "some value";
+ cursor = session.open_cursor("table:mytable", null, "overwrite=false");
+ cursor.putKeyString(key);
+ cursor.putValueString(value);
+ ret = cursor.update();
+ /*! [Update an existing record and fail if DNE] */
+ }
+
+ {
+ /*! [Remove a record] */
+ String key = "some key";
+ cursor = session.open_cursor("table:mytable", null, null);
+ cursor.putKeyString(key);
+ ret = cursor.remove();
+ /*! [Remove a record] */
+ }
+
+ {
+ /*! [Remove a record and fail if DNE] */
+ String key = "some key";
+ cursor = session.open_cursor("table:mytable", null, "overwrite=false");
+ cursor.putKeyString(key);
+ ret = cursor.remove();
+ /*! [Remove a record and fail if DNE] */
+ }
+
+ {
+ /*! [Display an error] */
+ try {
+ String key = "non-existent key";
+ cursor.putKeyString(key);
+ if ((ret = cursor.remove()) != 0) {
+ System.err.println(
+ "cursor.remove: " + wiredtiger.wiredtiger_strerror(ret));
+ return (ret);
+ }
+ } catch (WiredTigerException wte) { /* Catch severe errors. */
+ System.err.println("cursor.remove exception: " + wte);
+ }
+ /*! [Display an error] */
+ }
+
+ /*! [Close the cursor] */
+ ret = cursor.close();
+ /*! [Close the cursor] */
+
+ return (ret);
+}
+
+static int
+cursor_search_near(Cursor cursor)
+ throws WiredTigerException
+{
+ int ret;
+ String key = "some key";
+ SearchStatus status;
+
+ /*! [Search for an exact or adjacent match] */
+ cursor.putKeyString(key);
+ status = cursor.search_near();
+ if (status == SearchStatus.FOUND) {
+ /* an exact match */
+ } else if (status == SearchStatus.SMALLER) {
+ /* returned smaller key */
+ } else if (status == SearchStatus.LARGER) {
+ /* returned larger key */
+ } else if (status == SearchStatus.NOTFOUND) {
+ /* no match found */
+ }
+ /*! [Search for an exact or adjacent match] */
+
+ /*! [Forward scan greater than or equal] */
+ cursor.putKeyString(key);
+ status = cursor.search_near();
+ if (status == SearchStatus.FOUND || status == SearchStatus.LARGER) {
+ /* include first key returned in the scan */
+ }
+
+ while ((ret = cursor.next()) == 0) {
+ /* the rest of the scan */
+ }
+ /*! [Forward scan greater than or equal] */
+
+ /*! [Backward scan less than] */
+ cursor.putKeyString(key);
+ status = cursor.search_near();
+ if (status == SearchStatus.SMALLER) {
+ /* include first key returned in the scan */
+ }
+
+ while ((ret = cursor.prev()) == 0) {
+ /* the rest of the scan */
+ }
+ /*! [Backward scan less than] */
+
+ return (ret);
+}
+
+static int
+checkpoint_ops(Session session)
+ throws WiredTigerException
+{
+ int ret;
+
+ /*! [Checkpoint examples] */
+ /* Checkpoint the database. */
+ ret = session.checkpoint(null);
+
+ /* Checkpoint of the database, creating a named snapshot. */
+ ret = session.checkpoint("name=June01");
+
+ /*
+ * Checkpoint a list of objects.
+ * JSON parsing requires quoting the list of target URIs.
+ */
+ ret = session.
+ checkpoint("target=(\"table:table1\",\"table:table2\")");
+
+ /*
+ * Checkpoint a list of objects, creating a named snapshot.
+ * JSON parsing requires quoting the list of target URIs.
+ */
+ ret = session.
+ checkpoint("target=(\"table:mytable\"),name=midnight");
+
+ /* Checkpoint the database, discarding all previous snapshots. */
+ ret = session.checkpoint("drop=(from=all)");
+
+ /* Checkpoint the database, discarding the "midnight" snapshot. */
+ ret = session.checkpoint("drop=(midnight)");
+
+ /*
+ * Checkpoint the database, discarding all snapshots after and
+ * including "noon".
+ */
+ ret = session.checkpoint("drop=(from=noon)");
+
+ /*
+ * Checkpoint the database, discarding all snapshots before and
+ * including "midnight".
+ */
+ ret = session.checkpoint("drop=(to=midnight)");
+
+ /*
+ * Create a checkpoint of a table, creating the "July01" snapshot and
+ * discarding the "May01" and "June01" snapshots.
+ * JSON parsing requires quoting the list of target URIs.
+ */
+ ret = session.checkpoint("target=(\"table:mytable\"),name=July01,drop=(May01,June01)");
+ /*! [Checkpoint examples] */
+
+ /*! [JSON quoting example] */
+ /*
+ * Checkpoint a list of objects.
+ * JSON parsing requires quoting the list of target URIs.
+ */
+ ret = session.
+ checkpoint("target=(\"table:table1\",\"table:table2\")");
+ /*! [JSON quoting example] */
+
+ return (ret);
+}
+
+static boolean
+cursor_statistics(Session session)
+ throws WiredTigerException
+{
+ Cursor cursor;
+
+ /*! [Statistics cursor database] */
+ cursor = session.open_cursor(
+ "statistics:", null, null);
+ /*! [Statistics cursor database] */
+
+ /*! [Statistics cursor table] */
+ cursor = session.open_cursor(
+ "statistics:table:mytable", null, null);
+ /*! [Statistics cursor table] */
+
+ /*! [Statistics cursor table fast] */
+ cursor = session.open_cursor("statistics:table:mytable", null, "statistics=(fast)");
+ /*! [Statistics cursor table fast] */
+
+ /*! [Statistics clear configuration] */
+ cursor = session.open_cursor("statistics:", null, "statistics=(fast,clear)");
+ /*! [Statistics clear configuration] */
+
+ /*! [Statistics cursor clear configuration] */
+ cursor = session.open_cursor("statistics:table:mytable",
+ null, "statistics=(all,clear)");
+ /*! [Statistics cursor clear configuration] */
+
+ return (true);
+}
+
+static int
+session_ops(Session session)
+ throws WiredTigerException
+{
+ int ret;
+
+ /*! [Reconfigure a session] */
+ ret = session.reconfigure("isolation=snapshot");
+ /*! [Reconfigure a session] */
+
+ /*! [Create a table] */
+ ret = session.create("table:mytable", "key_format=S,value_format=S");
+ /*! [Create a table] */
+ ret = session.drop("table:mytable", null);
+
+ /*! [Create a column-store table] */
+ ret = session.create("table:mytable", "key_format=r,value_format=S");
+ /*! [Create a column-store table] */
+ ret = session.drop("table:mytable", null);
+
+ /*! [Create a table with columns] */
+ /*
+ * Create a table with columns: keys are record numbers, values are
+ * (string, signed 32-bit integer, unsigned 16-bit integer).
+ */
+ ret = session.create("table:mytable",
+ "key_format=r,value_format=SiH," +
+ "columns=(id,department,salary,year-started)");
+ /*! [Create a table with columns] */
+ ret = session.drop("table:mytable", null);
+
+ /*
+ * This example code gets run, and the compression libraries might not
+ * be loaded, causing the create to fail. The documentation requires
+ * the code snippets, use if (false) to avoid running it.
+ */
+ if (false) { // MIGHT_NOT_RUN
+ /*! [Create a bzip2 compressed table] */
+ ret = session.create("table:mytable",
+ "block_compressor=bzip2,key_format=S,value_format=S");
+ /*! [Create a bzip2 compressed table] */
+ ret = session.drop("table:mytable", null);
+
+ /*! [Create a lz4 compressed table] */
+ ret = session.create("table:mytable",
+ "block_compressor=lz4,key_format=S,value_format=S");
+ /*! [Create a lz4 compressed table] */
+ ret = session.drop("table:mytable", null);
+
+ /*! [Create a snappy compressed table] */
+ ret = session.create("table:mytable",
+ "block_compressor=snappy,key_format=S,value_format=S");
+ /*! [Create a snappy compressed table] */
+ ret = session.drop("table:mytable", null);
+
+ /*! [Create a zlib compressed table] */
+ ret = session.create("table:mytable",
+ "block_compressor=zlib,key_format=S,value_format=S");
+ /*! [Create a zlib compressed table] */
+ ret = session.drop("table:mytable", null);
+ } // if (false)
+
+ /*! [Configure checksums to uncompressed] */
+ ret = session.create("table:mytable",
+ "key_format=S,value_format=S,checksum=uncompressed");
+ /*! [Configure checksums to uncompressed] */
+ ret = session.drop("table:mytable", null);
+
+ /*! [Configure dictionary compression on] */
+ ret = session.create("table:mytable",
+ "key_format=S,value_format=S,dictionary=1000");
+ /*! [Configure dictionary compression on] */
+ ret = session.drop("table:mytable", null);
+
+ /*! [Configure key prefix compression on] */
+ ret = session.create("table:mytable",
+ "key_format=S,value_format=S,prefix_compression=true");
+ /*! [Configure key prefix compression on] */
+ ret = session.drop("table:mytable", null);
+
+ if (false) { // MIGHT_NOT_RUN
+ /* Requires sync_file_range */
+ /*! [os_cache_dirty_max configuration] */
+ ret = session.create(
+ "table:mytable", "os_cache_dirty_max=500MB");
+ /*! [os_cache_dirty_max configuration] */
+ ret = session.drop("table:mytable", null);
+
+ /* Requires posix_fadvise */
+ /*! [os_cache_max configuration] */
+ ret = session.create("table:mytable", "os_cache_max=1GB");
+ /*! [os_cache_max configuration] */
+ ret = session.drop("table:mytable", null);
+ } // if (false)
+
+ /*! [Configure block_allocation] */
+ ret = session.create("table:mytable",
+ "key_format=S,value_format=S,block_allocation=first");
+ /*! [Configure block_allocation] */
+ ret = session.drop("table:mytable", null);
+
+ /*! [Create a cache-resident object] */
+ ret = session.create("table:mytable", "key_format=r,value_format=S,cache_resident=true");
+ /*! [Create a cache-resident object] */
+ ret = session.drop("table:mytable", null);
+
+ {
+ /* Create a table for the session operations. */
+ ret = session.create(
+ "table:mytable", "key_format=S,value_format=S");
+
+ /*! [Compact a table] */
+ ret = session.compact("table:mytable", null);
+ /*! [Compact a table] */
+
+ /*! [Rename a table] */
+ ret = session.rename("table:old", "table:new", null);
+ /*! [Rename a table] */
+
+ /*! [Salvage a table] */
+ ret = session.salvage("table:mytable", null);
+ /*! [Salvage a table] */
+
+ /*! [Truncate a table] */
+ ret = session.truncate("table:mytable", null, null, null);
+ /*! [Truncate a table] */
+
+ {
+ /*
+ * Insert a pair of keys so we can truncate a range.
+ */
+ Cursor cursor;
+ cursor = session.open_cursor(
+ "table:mytable", null, null);
+ cursor.putKeyString("June01");
+ cursor.putValueString("value");
+ ret = cursor.update();
+ cursor.putKeyString("June30");
+ cursor.putValueString("value");
+ ret = cursor.update();
+ cursor.close();
+
+ {
+ /*! [Truncate a range] */
+ Cursor start, stop;
+
+ start = session.open_cursor(
+ "table:mytable", null, null);
+ start.putKeyString("June01");
+ ret = start.search();
+
+ stop = session.open_cursor(
+ "table:mytable", null, null);
+ stop.putKeyString("June30");
+ ret = stop.search();
+
+ ret = session.truncate(null, start, stop, null);
+ /*! [Truncate a range] */
+ }
+ }
+
+ /*! [Upgrade a table] */
+ ret = session.upgrade("table:mytable", null);
+ /*! [Upgrade a table] */
+
+ /*! [Verify a table] */
+ ret = session.verify("table:mytable", null);
+ /*! [Verify a table] */
+
+ /*! [Drop a table] */
+ ret = session.drop("table:mytable", null);
+ /*! [Drop a table] */
+ }
+
+ /*! [Close a session] */
+ ret = session.close(null);
+ /*! [Close a session] */
+
+ return (ret);
+}
+
+static int
+transaction_ops(Connection conn, Session session)
+ throws WiredTigerException
+{
+ Cursor cursor;
+ int ret;
+
+ /*! [transaction commit/rollback] */
+ cursor = session.open_cursor("table:mytable", null, null);
+ ret = session.begin_transaction(null);
+ /*
+ * Cursors may be opened before or after the transaction begins, and in
+ * either case, subsequent operations are included in the transaction.
+ * The begin_transaction call resets all open cursors.
+ */
+
+ cursor.putKeyString("key");
+ cursor.putValueString("value");
+ switch (ret = cursor.update()) {
+ case 0: /* Update success */
+ ret = session.commit_transaction(null);
+ /*
+ * The commit_transaction call resets all open cursors.
+ * If commit_transaction fails, the transaction was rolled-back.
+ */
+ break;
+ case wiredtiger.WT_ROLLBACK: /* Update conflict */
+ default: /* Other error */
+ ret = session.rollback_transaction(null);
+ /* The rollback_transaction call resets all open cursors. */
+ break;
+ }
+
+ /* Cursors remain open and may be used for multiple transactions. */
+ /*! [transaction commit/rollback] */
+ ret = cursor.close();
+
+ /*! [transaction isolation] */
+ /* A single transaction configured for snapshot isolation. */
+ cursor = session.open_cursor("table:mytable", null, null);
+ ret = session.begin_transaction("isolation=snapshot");
+ cursor.putKeyString("some-key");
+ cursor.putValueString("some-value");
+ ret = cursor.update();
+ ret = session.commit_transaction(null);
+ /*! [transaction isolation] */
+
+ /*! [session isolation configuration] */
+ /* Open a session configured for read-uncommitted isolation. */
+ session = conn.open_session(
+ "isolation=read_uncommitted");
+ /*! [session isolation configuration] */
+
+ /*! [session isolation re-configuration] */
+ /* Re-configure a session for snapshot isolation. */
+ ret = session.reconfigure("isolation=snapshot");
+ /*! [session isolation re-configuration] */
+
+ return (ret);
+}
+
+/*! [Implement WT_COLLATOR] */
+/* Not available for java */
+/*! [Implement WT_COLLATOR] */
+
+/*! [WT_EXTRACTOR] */
+/* Not available for java */
+/*! [WT_EXTRACTOR] */
+
+static int
+connection_ops(Connection conn)
+ throws WiredTigerException
+{
+ int ret;
+
+ if (false) { // Might not run.
+ /*! [Load an extension] */
+ ret = conn.load_extension("my_extension.dll", null);
+
+ ret = conn.load_extension(
+ "datasource/libdatasource.so",
+ "config=[device=/dev/sd1,alignment=64]");
+ /*! [Load an extension] */
+ } // if (false)
+
+ /*! [Reconfigure a connection] */
+ ret = conn.reconfigure("eviction_target=75");
+ /*! [Reconfigure a connection] */
+
+ /*! [Get the database home directory] */
+ System.out.println("The database home is " + conn.get_home());
+ /*! [Get the database home directory] */
+
+ /*! [Check if the database is newly created] */
+ if (conn.is_new() != 0) {
+ /* First time initialization. */
+ }
+ /*! [Check if the database is newly created] */
+
+ {
+ /*! [Open a session] */
+ Session session;
+ session = conn.open_session(null);
+ /*! [Open a session] */
+
+ session_ops(session);
+ }
+
+ /*! [Configure method configuration] */
+ /*
+ * Applications opening a cursor for the data-source object "my_data"
+ * have an additional configuration option "entries", which is an
+ * integer type, defaults to 5, and must be an integer between 1 and 10.
+ */
+ ret = conn.configure_method(
+ "session.open_cursor",
+ "my_data:", "entries=5", "int", "min=1,max=10");
+
+ /*
+ * Applications opening a cursor for the data-source object "my_data"
+ * have an additional configuration option "devices", which is a list
+ * of strings.
+ */
+ ret = conn.configure_method(
+ "session.open_cursor", "my_data:", "devices", "list", null);
+ /*! [Configure method configuration] */
+
+ /*! [Close a connection] */
+ ret = conn.close(null);
+ /*! [Close a connection] */
+
+ return (ret);
+}
+
+static int
+pack_ops(Session session)
+{
+ {
+ /*! [Get the packed size] */
+ /* Not available for java */
+ /*! [Get the packed size] */
+ }
+
+ {
+ /*! [Pack fields into a buffer] */
+ /* Not available for java */
+ /*! [Pack fields into a buffer] */
+ }
+
+ {
+ /*! [Unpack fields from a buffer] */
+ /* Not available for java */
+ /*! [Unpack fields from a buffer] */
+ }
+
+ return (0);
+}
+
+static boolean
+backup(Session session)
+ throws WiredTigerException
+{
+ char buf[] = new char[1024];
+
+ /*! [backup]*/
+ Cursor cursor;
+ String filename;
+ int ret = 0;
+ String databasedir = "/path/database";
+ String backdir = "/path/database.backup";
+ final String sep = File.separator;
+
+ try {
+ /* Create the backup directory. */
+ if (!(new File(backdir)).mkdir()) {
+ System.err.println(progname + ": cannot create backup dir: " +
+ backdir);
+ return false;
+ }
+
+ /* Open the backup data source. */
+ cursor = session.open_cursor("backup:", null, null);
+
+ /* Copy the list of files. */
+ while ((ret = cursor.next()) == 0 &&
+ (filename = cursor.getKeyString()) != null) {
+ String src = databasedir + sep + filename;
+ String dest = backdir + sep + filename;
+ java.nio.file.Files.copy(
+ new java.io.File(src).toPath(),
+ new java.io.File(dest).toPath(),
+ java.nio.file.StandardCopyOption.REPLACE_EXISTING,
+ java.nio.file.StandardCopyOption.COPY_ATTRIBUTES);
+ }
+ if (ret == wiredtiger.WT_NOTFOUND)
+ ret = 0;
+ if (ret != 0)
+ System.err.println(progname +
+ ": cursor next(backup:) failed: " +
+ wiredtiger.wiredtiger_strerror(ret));
+
+ ret = cursor.close();
+ }
+ catch (Exception ex) {
+ System.err.println(progname +
+ ": backup failed: " + ex.toString());
+ }
+ /*! [backup]*/
+
+ /*! [backup of a checkpoint]*/
+ ret = session.checkpoint("drop=(from=June01),name=June01");
+ /*! [backup of a checkpoint]*/
+
+ return (ret == 0);
+}
+
+public static int
+allExample()
+ throws WiredTigerException
+{
+ Connection conn;
+ int ret = 0;
+ String home = "/home/example/WT_TEST";
+
+ /*! [Open a connection] */
+ conn = wiredtiger.open(home, "create,cache_size=500M");
+ /*! [Open a connection] */
+
+ connection_ops(conn);
+ /*
+ * The connection has been closed.
+ */
+
+ if (false) { // MIGHT_NOT_RUN
+ /*
+ * This example code gets run, and the compression libraries might not
+ * be installed, causing the open to fail. The documentation requires
+ * the code snippets, use if (false) to avoid running it.
+ */
+ /*! [Configure bzip2 extension] */
+ conn = wiredtiger.open(home,
+ "create," +
+ "extensions=[/usr/local/lib/libwiredtiger_bzip2.so]");
+ /*! [Configure bzip2 extension] */
+ conn.close(null);
+
+ /*! [Configure lz4 extension] */
+ conn = wiredtiger.open(home,
+ "create," +
+ "extensions=[/usr/local/lib/libwiredtiger_lz4.so]");
+ /*! [Configure lz4 extension] */
+ conn.close(null);
+
+ /*! [Configure snappy extension] */
+ conn = wiredtiger.open(home,
+ "create," +
+ "extensions=[/usr/local/lib/libwiredtiger_snappy.so]");
+ /*! [Configure snappy extension] */
+ conn.close(null);
+
+ /*! [Configure zlib extension] */
+ conn = wiredtiger.open(home,
+ "create," +
+ "extensions=[/usr/local/lib/libwiredtiger_zlib.so]");
+ /*! [Configure zlib extension] */
+ conn.close(null);
+
+ /*
+ * This example code gets run, and direct I/O might not be available,
+ * causing the open to fail. The documentation requires code snippets,
+ * use if (false) to avoid running it.
+ */
+ /* Might Not Run: direct I/O may not be available. */
+ /*! [Configure direct_io for data files] */
+ conn = wiredtiger.open(home, "create,direct_io=[data]");
+ /*! [Configure direct_io for data files] */
+ conn.close(null);
+ } // if (false)
+
+ /*! [Configure file_extend] */
+ conn = wiredtiger.open(
+ home, "create,file_extend=(data=16MB)");
+ /*! [Configure file_extend] */
+ conn.close(null);
+
+ /*! [Eviction configuration] */
+ /*
+ * Configure eviction to begin at 90% full, and run until the cache
+ * is only 75% dirty.
+ */
+ conn = wiredtiger.open(home,
+ "create,eviction_trigger=90,eviction_dirty_target=75");
+ /*! [Eviction configuration] */
+ conn.close(null);
+
+ /*! [Eviction worker configuration] */
+ /* Configure up to four eviction threads */
+ conn = wiredtiger.open(home,
+ "create,eviction_trigger=90,eviction=(threads_max=4)");
+ /*! [Eviction worker configuration] */
+ conn.close(null);
+
+ /*! [Statistics configuration] */
+ conn = wiredtiger.open(home, "create,statistics=(all)");
+ /*! [Statistics configuration] */
+ conn.close(null);
+
+ /*! [Statistics logging] */
+ conn = wiredtiger.open(
+ home, "create,statistics_log=(wait=30)");
+ /*! [Statistics logging] */
+ conn.close(null);
+
+ /*! [Statistics logging with a table] */
+ conn = wiredtiger.open(home,
+ "create," +
+ "statistics_log=(sources=(\"table:table1\",\"table:table2\"))");
+ /*! [Statistics logging with a table] */
+ conn.close(null);
+
+ /*! [Statistics logging with all tables] */
+ conn = wiredtiger.open(home,
+ "create,statistics_log=(sources=(\"table:\"))");
+ /*! [Statistics logging with all tables] */
+ conn.close(null);
+
+ if (false) { // MIGHT_NOT_RUN
+ /*
+ * This example code gets run, and a non-existent log file path might
+ * cause the open to fail. The documentation requires code snippets,
+ * use if (false) to avoid running it.
+ */
+ /*! [Statistics logging with path] */
+ conn = wiredtiger.open(home,
+ "create," +
+ "statistics_log=(wait=120,path=/log/log.%m.%d.%y)");
+ /*! [Statistics logging with path] */
+ conn.close(null);
+
+ /*
+ * Don't run this code, because memory checkers get very upset when we
+ * leak memory.
+ */
+ conn = wiredtiger.open(home, "create");
+ /*! [Connection close leaking memory] */
+ ret = conn.close("leak_memory=true");
+ /*! [Connection close leaking memory] */
+ } // if (false)
+
+ /*! [Get the WiredTiger library version #1] */
+ /* Not available for java */
+ /*! [Get the WiredTiger library version #1] */
+
+ {
+ /*! [Get the WiredTiger library version #2] */
+ /* Not available for java */
+ /*! [Get the WiredTiger library version #2] */
+ }
+
+ return (0);
+}
+
+public static int
+main(String[] argv)
+{
+ try {
+ return (allExample());
+ }
+ catch (WiredTigerException wte) {
+ System.err.println("Exception: " + wte);
+ return (-1);
+ }
+}
+} /* Non-standard indentation */
diff --git a/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_async.java b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_async.java
new file mode 100644
index 00000000000..2e890095b2d
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_async.java
@@ -0,0 +1,221 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_async.java
+ * demonstrates how to use the asynchronous API.
+ */
+package com.wiredtiger.examples;
+import com.wiredtiger.db.*;
+import java.io.*;
+import java.util.*;
+
+/*! [async example callback implementation] */
+class AsyncKeys implements AsyncCallback {
+
+ public int numKeys = 0;
+
+ public AsyncKeys() {}
+
+ public void notifyError(String desc) {
+ System.err.println("ERROR: notify: " + desc);
+ }
+
+ public int notify(AsyncOp op, int opReturn, int flags) {
+ /*
+ * Note: we are careful not to throw any errors here. Any
+ * exceptions would be swallowed by a native worker thread.
+ */
+ int ret = 0;
+ try {
+ /*! [async get type] */
+ /* Retrieve the operation's type. */
+ AsyncOpType optype = op.getType();
+ /*! [async get type] */
+ /*! [async get identifier] */
+ /* Retrieve the operation's 64-bit identifier. */
+ long id = op.getId();
+ /*! [async get identifier] */
+
+ /* If doing a search, retrieve the key/value pair. */
+ if (optype == AsyncOpType.WT_AOP_SEARCH) {
+ /*! [async get the operation's string key] */
+ String key = op.getKeyString();
+ /*! [async get the operation's string key] */
+ /*! [async get the operation's string value] */
+ String value = op.getValueString();
+ /*! [async get the operation's string value] */
+ synchronized (this) {
+ numKeys += 1;
+ }
+ System.out.println("Id " + id + " got record: " + key +
+ " : " + value);
+ }
+ }
+ catch (Exception e) {
+ System.err.println("ERROR: exception in notify: " + e.toString() +
+ ", opreturn=" + opReturn);
+ ret = 1;
+ }
+ return (ret);
+ }
+}
+/*! [async example callback implementation] */
+
+public class ex_async {
+
+ public static String home;
+
+ public static final int MAX_KEYS = 15;
+
+ public static AsyncOp tryAsyncNewOp(Connection conn, String uri,
+ String config, AsyncCallback cb) throws WiredTigerException
+ {
+ WiredTigerException savedwte = null;
+
+ for (int tries = 0; tries < 10; tries++)
+ try {
+ return conn.async_new_op(uri, config, cb);
+ }
+ catch (WiredTigerException wte) {
+ /*
+ * If we used up all the handles, pause and retry to
+ * give the workers a chance to catch up.
+ */
+ System.err.println(
+ "asynchronous operation handle not available: " + wte);
+ savedwte = wte;
+ try {
+ Thread.sleep(1);
+ } catch (InterruptedException ie) {
+ /* not a big problem, continue to retry */
+ }
+ }
+
+ throw savedwte;
+ }
+
+ public static int
+ asyncExample()
+ throws WiredTigerException
+ {
+ AsyncOp op;
+ Connection conn;
+ Session session;
+ int i, ret;
+ String k[] = new String[MAX_KEYS];
+ String v[] = new String[MAX_KEYS];
+
+ /*! [async example callback implementation part 2] */
+ AsyncKeys asynciface = new AsyncKeys();
+ /*! [async example callback implementation part 2] */
+
+ /*! [async example connection] */
+ conn = wiredtiger.open(home, "create,cache_size=100MB," +
+ "async=(enabled=true,ops_max=20,threads=2)");
+ /*! [async example connection] */
+
+ /*! [async example table create] */
+ session = conn.open_session(null);
+ ret = session.create("table:async", "key_format=S,value_format=S");
+ /*! [async example table create] */
+
+ /* Insert a set of keys asynchronously. */
+ for (i = 0; i < MAX_KEYS; i++) {
+ /*! [async handle allocation] */
+ op = tryAsyncNewOp(conn, "table:async", null, asynciface);
+ /*! [async handle allocation] */
+
+ /*! [async insert] */
+ /*
+ * Set the operation's string key and value, and then do
+ * an asynchronous insert.
+ */
+ /*! [async set the operation's string key] */
+ k[i] = "key" + i;
+ op.putKeyString(k[i]);
+ /*! [async set the operation's string key] */
+
+ /*! [async set the operation's string value] */
+ v[i] = "value" + i;
+ op.putValueString(v[i]);
+ /*! [async set the operation's string value] */
+
+ ret = op.insert();
+ /*! [async insert] */
+ }
+
+ /*! [async flush] */
+ /* Wait for all outstanding operations to complete. */
+ ret = conn.async_flush();
+ /*! [async flush] */
+
+ /*! [async compaction] */
+ /*
+ * Compact a table asynchronously, limiting the run-time to 5 minutes.
+ */
+ op = tryAsyncNewOp(conn, "table:async", "timeout=300", asynciface);
+ ret = op.compact();
+ /*! [async compaction] */
+
+ /* Search for the keys we just inserted, asynchronously. */
+ for (i = 0; i < MAX_KEYS; i++) {
+ op = tryAsyncNewOp(conn, "table:async", null, asynciface);
+ /*! [async search] */
+ /*
+ * Set the operation's string key and value, and then do
+ * an asynchronous search.
+ */
+ k[i] = "key" + i;
+ op.putKeyString(k[i]);
+ ret = op.search();
+ /*! [async search] */
+ }
+
+ /*
+ * Connection close automatically does an async_flush so it will wait
+ * for all queued search operations to complete.
+ */
+ ret = conn.close(null);
+
+ System.out.println("Searched for " + asynciface.numKeys + " keys");
+
+ return (ret);
+ }
+
+ public static void
+ main(String[] argv)
+ {
+ try {
+ System.exit(asyncExample());
+ }
+ catch (WiredTigerException wte) {
+ System.err.println("Exception: " + wte);
+ wte.printStackTrace();
+ System.exit(1);
+ }
+ }
+}
diff --git a/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_call_center.java b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_call_center.java
new file mode 100644
index 00000000000..a3f0f56ded8
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_call_center.java
@@ -0,0 +1,302 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_call_center.java
+ * This is an example application that demonstrates how to map a
+ * moderately complex SQL application into WiredTiger.
+ */
+
+package com.wiredtiger.examples;
+import com.wiredtiger.db.*;
+import java.io.*;
+import java.util.*;
+
+/*! [call-center decl] */
+/*
+ * In SQL, the tables are described as follows:
+ *
+ * CREATE TABLE Customers(id INTEGER PRIMARY KEY,
+ * name VARCHAR(30), address VARCHAR(50), phone VARCHAR(15))
+ * CREATE INDEX CustomersPhone ON Customers(phone)
+ *
+ * CREATE TABLE Calls(id INTEGER PRIMARY KEY, call_date DATE,
+ * cust_id INTEGER, emp_id INTEGER, call_type VARCHAR(12),
+ * notes VARCHAR(25))
+ * CREATE INDEX CallsCustDate ON Calls(cust_id, call_date)
+ *
+ * In this example, both tables will use record numbers for their IDs, which
+ * will be the key. The C structs for the records are as follows.
+ */
+
+/* Customer records. */
+class Customer {
+ public long id;
+ public String name;
+ public String address;
+ public String phone;
+ public Customer(long id, String name, String address, String phone) {
+ this.id = id;
+ this.name = name;
+ this.address = address;
+ this.phone = phone;
+ }
+ public Customer() {}
+}
+
+/* Call records. */
+class Call {
+ public long id;
+ public long call_date;
+ public long cust_id;
+ public long emp_id;
+ public String call_type;
+ public String notes;
+ public Call(long id, long call_date, long cust_id, long emp_id,
+ String call_type, String notes) {
+ this.id = id;
+ this.call_date = call_date;
+ this.cust_id = cust_id;
+ this.emp_id = emp_id;
+ this.call_type = call_type;
+ this.notes = notes;
+ }
+ public Call() {}
+}
+/*! [call-center decl] */
+
+public class ex_call_center {
+
+ public static String home;
+
+ public static int
+ callCenterExample()
+ throws WiredTigerException
+ {
+ Connection conn;
+ Cursor cursor;
+ Session session;
+ int count, ret;
+ SearchStatus nearstatus;
+ List<Customer> custSample = new ArrayList<Customer>();
+ List<Call> callSample = new ArrayList<Call>();
+
+ custSample.add(new Customer(0, "Professor Oak",
+ "LeafGreen Avenue", "123-456-7890"));
+ custSample.add(new Customer(0, "Lorelei",
+ "Sevii Islands", "098-765-4321"));
+ callSample.add(new Call(0, 32, 1, 2, "billing", "unavailable"));
+ callSample.add(new Call(0, 33, 1, 2, "billing", "available"));
+ callSample.add(new Call(0, 34, 1, 2, "reminder", "unavailable"));
+ callSample.add(new Call(0, 35, 1, 2, "reminder", "available"));
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (System.getenv("WIREDTIGER_HOME") == null) {
+ home = "WT_HOME";
+ try {
+ Process proc = Runtime.getRuntime().exec("/bin/rm -rf WT_HOME");
+ BufferedReader br = new BufferedReader(
+ new InputStreamReader(proc.getInputStream()));
+ while(br.ready())
+ System.out.println(br.readLine());
+ br.close();
+ proc.waitFor();
+ new File("WT_HOME").mkdir();
+ } catch (Exception ex) {
+ System.err.println("Exception: " + ex);
+ return (1);
+ }
+ } else
+ home = null;
+
+ try {
+ conn = wiredtiger.open(home, "create");
+ session = conn.open_session(null);
+ } catch (WiredTigerException wte) {
+ System.err.println("WiredTigerException: " + wte);
+ return(1);
+ }
+ /* Note: further error checking omitted for clarity. */
+
+ /*! [call-center work] */
+ /*
+ * Create the customers table, give names and types to the columns.
+ * The columns will be stored in two groups: "main" and "address",
+ * created below.
+ */
+ ret = session.create("table:customers",
+ "key_format=r," +
+ "value_format=SSS," +
+ "columns=(id,name,address,phone)," +
+ "colgroups=(main,address)");
+
+ /* Create the main column group with value columns except address. */
+ ret = session.create(
+ "colgroup:customers:main", "columns=(name,phone)");
+
+ /* Create the address column group with just the address. */
+ ret = session.create(
+ "colgroup:customers:address", "columns=(address)");
+
+ /* Create an index on the customer table by phone number. */
+ ret = session.create(
+ "index:customers:phone", "columns=(phone)");
+
+ /* Populate the customers table with some data. */
+ cursor = session.open_cursor("table:customers", null, "append");
+ for (Customer cust : custSample) {
+ cursor.putValueString(cust.name);
+ cursor.putValueString(cust.address);
+ cursor.putValueString(cust.phone);
+ ret = cursor.insert();
+ }
+ ret = cursor.close();
+
+ /*
+ * Create the calls table, give names and types to the columns. All the
+ * columns will be stored together, so no column groups are declared.
+ */
+ ret = session.create("table:calls",
+ "key_format=r," +
+ "value_format=qrrSS," +
+ "columns=(id,call_date,cust_id,emp_id,call_type,notes)");
+
+ /*
+ * Create an index on the calls table with a composite key of cust_id
+ * and call_date.
+ */
+ ret = session.create("index:calls:cust_date",
+ "columns=(cust_id,call_date)");
+
+ /* Populate the calls table with some data. */
+ cursor = session.open_cursor("table:calls", null, "append");
+ for (Call call : callSample) {
+ cursor.putValueLong(call.call_date);
+ cursor.putValueRecord(call.cust_id);
+ cursor.putValueRecord(call.emp_id);
+ cursor.putValueString(call.call_type);
+ cursor.putValueString(call.notes);
+ ret = cursor.insert();
+ }
+ ret = cursor.close();
+
+ /*
+ * First query: a call arrives. In SQL:
+ *
+ * SELECT id, name FROM Customers WHERE phone=?
+ *
+ * Use the cust_phone index, lookup by phone number to fill the
+ * customer record. The cursor will have a key format of "S" for a
+ * string because the cust_phone index has a single column ("phone"),
+ * which is of type "S".
+ *
+ * Specify the columns we want: the customer ID and the name. This
+ * means the cursor's value format will be "rS".
+ */
+ cursor = session.open_cursor(
+ "index:customers:phone(id,name)", null, null);
+ cursor.putKeyString("123-456-7890");
+ ret = cursor.search();
+ if (ret == 0) {
+ Customer cust = new Customer();
+ cust.id = cursor.getValueRecord();
+ cust.name = cursor.getValueString();
+ System.out.println("Read customer record for " + cust.name +
+ " (ID " + cust.id + ")");
+ }
+ ret = cursor.close();
+
+ /*
+ * Next query: get the recent order history. In SQL:
+ *
+ * SELECT * FROM Calls WHERE cust_id=? ORDER BY call_date DESC LIMIT 3
+ *
+ * Use the call_cust_date index to find the matching calls. Since it is
+ * is in increasing order by date for a given customer, we want to start
+ * with the last record for the customer and work backwards.
+ *
+ * Specify a subset of columns to be returned. (Note that if these were
+ * all covered by the index, the primary would not have to be accessed.)
+ * Stop after getting 3 records.
+ */
+ cursor = session.open_cursor(
+ "index:calls:cust_date(cust_id,call_type,notes)",
+ null, null);
+
+ /*
+ * The keys in the index are (cust_id,call_date) -- we want the largest
+ * call date for a given cust_id. Search for (cust_id+1,0), then work
+ * backwards.
+ */
+ long custid = 1;
+ cursor.putKeyRecord(custid + 1);
+ cursor.putKeyLong(0);
+ nearstatus = cursor.search_near();
+
+ /*
+ * If the table is empty, search_near will return WT_NOTFOUND, else the
+ * cursor will be positioned on a matching key if one exists, or an
+ * adjacent key if one does not. If the positioned key is equal to or
+ * larger than the search key, go back one.
+ */
+ if (ret == 0 && (nearstatus == SearchStatus.LARGER ||
+ nearstatus == SearchStatus.FOUND))
+ ret = cursor.prev();
+ for (count = 0; ret == 0 && count < 3; ++count) {
+ Call call = new Call();
+ call.cust_id = cursor.getValueRecord();
+ call.call_type = cursor.getValueString();
+ call.notes = cursor.getValueString();
+ if (call.cust_id != custid)
+ break;
+ System.out.println("Call record: customer " + call.cust_id +
+ " (" + call.call_type +
+ ": " + call.notes + ")");
+ ret = cursor.prev();
+ }
+ /*! [call-center work] */
+
+ ret = conn.close(null);
+
+ return (ret);
+ }
+
+ public static void
+ main(String[] argv)
+ {
+ try {
+ System.exit(callCenterExample());
+ }
+ catch (WiredTigerException wte) {
+ System.err.println("Exception: " + wte);
+ wte.printStackTrace();
+ System.exit(1);
+ }
+ }
+}
diff --git a/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_cursor.java b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_cursor.java
new file mode 100644
index 00000000000..a0a6e48aa46
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_cursor.java
@@ -0,0 +1,242 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_cursor.java
+ * This is an example demonstrating some cursor types and operations.
+ */
+
+package com.wiredtiger.examples;
+import com.wiredtiger.db.*;
+import java.io.*;
+import java.util.*;
+
+public class ex_cursor {
+
+ public static String home;
+
+ /*! [cursor next] */
+ public static int
+ cursor_forward_scan(Cursor cursor)
+ throws WiredTigerException
+ {
+ String key, value;
+ int ret;
+
+ while ((ret = cursor.next()) == 0) {
+ key = cursor.getKeyString();
+ value = cursor.getValueString();
+ }
+ return (ret);
+ }
+ /*! [cursor next] */
+
+ /*! [cursor prev] */
+ public static int
+ cursor_reverse_scan(Cursor cursor)
+ throws WiredTigerException
+ {
+ String key, value;
+ int ret;
+
+ while ((ret = cursor.prev()) == 0) {
+ key = cursor.getKeyString();
+ value = cursor.getValueString();
+ }
+ return (ret);
+ }
+ /*! [cursor prev] */
+
+ /*! [cursor reset] */
+ public static int
+ cursor_reset(Cursor cursor)
+ throws WiredTigerException
+ {
+ return (cursor.reset());
+ }
+ /*! [cursor reset] */
+
+ /*! [cursor search] */
+ public static int
+ cursor_search(Cursor cursor)
+ throws WiredTigerException
+ {
+ String value;
+ int ret;
+
+ cursor.putKeyString("foo");
+
+ if ((ret = cursor.search()) != 0)
+ value = cursor.getValueString();
+
+ return (ret);
+ }
+ /*! [cursor search] */
+
+ /*! [cursor search near] */
+ public static int
+ cursor_search_near(Cursor cursor)
+ throws WiredTigerException
+ {
+ String key, value;
+ SearchStatus exact;
+
+ key = "foo";
+ cursor.putKeyString(key);
+
+ exact = cursor.search_near();
+ if (exact == SearchStatus.SMALLER)
+ /* Returned key smaller than search key */
+ key = cursor.getKeyString();
+ else if (exact == SearchStatus.LARGER)
+ /* Returned key larger than search key */
+ key = cursor.getKeyString();
+ /* Else exact match found, and key already set */
+
+ value = cursor.getValueString();
+
+ return (0);
+ }
+ /*! [cursor search near] */
+
+ /*! [cursor insert] */
+ public static int
+ cursor_insert(Cursor cursor)
+ throws WiredTigerException
+ {
+ cursor.putKeyString("foo");
+ cursor.putValueString("bar");
+
+ return (cursor.insert());
+ }
+ /*! [cursor insert] */
+
+ /*! [cursor update] */
+ public static int
+ cursor_update(Cursor cursor)
+ throws WiredTigerException
+ {
+ cursor.putKeyString("foo");
+ cursor.putValueString("newbar");
+
+ return (cursor.update());
+ }
+ /*! [cursor update] */
+
+ /*! [cursor remove] */
+ public static int
+ cursor_remove(Cursor cursor)
+ throws WiredTigerException
+ {
+ cursor.putKeyString("foo");
+ return (cursor.remove());
+ }
+ /*! [cursor remove] */
+
+ public static int
+ cursorExample()
+ throws WiredTigerException
+ {
+ Connection conn;
+ Cursor cursor;
+ Session session;
+ int ret;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (System.getenv("WIREDTIGER_HOME") == null) {
+ home = "WT_HOME";
+ try {
+ Process proc = Runtime.getRuntime().exec("/bin/rm -rf WT_HOME");
+ BufferedReader br = new BufferedReader(
+ new InputStreamReader(proc.getInputStream()));
+ while(br.ready())
+ System.out.println(br.readLine());
+ br.close();
+ proc.waitFor();
+ new File("WT_HOME").mkdir();
+ } catch (Exception ex) {
+ System.err.println("Exception: " + ex);
+ return (1);
+ }
+ } else
+ home = null;
+
+ conn = wiredtiger.open(home, "create,statistics=(fast)");
+ session = conn.open_session(null);
+
+ ret = session.create("table:world",
+ "key_format=r,value_format=5sii," +
+ "columns=(id,country,population,area)");
+
+ /*! [open cursor #1] */
+ cursor = session.open_cursor("table:world", null, null);
+ /*! [open cursor #1] */
+
+ /*! [open cursor #2] */
+ cursor = session.open_cursor("table:world(country,population)", null, null);
+ /*! [open cursor #2] */
+
+ /*! [open cursor #3] */
+ cursor = session.open_cursor("statistics:", null, null);
+ /*! [open cursor #3] */
+
+ /* Create a simple string table to illustrate basic operations. */
+ ret = session.create("table:map", "key_format=S,value_format=S");
+ cursor = session.open_cursor("table:map", null, null);
+ ret = cursor_insert(cursor);
+ ret = cursor_reset(cursor);
+ ret = cursor_forward_scan(cursor);
+ ret = cursor_reset(cursor);
+ ret = cursor_reverse_scan(cursor);
+ ret = cursor_search_near(cursor);
+ ret = cursor_update(cursor);
+ ret = cursor_remove(cursor);
+ ret = cursor.close();
+
+ /* Note: closing the connection implicitly closes open session(s). */
+ if ((ret = conn.close(null)) != 0)
+ System.err.println("Error connecting to " + home + ": " +
+ wiredtiger.wiredtiger_strerror(ret));
+
+ return (ret);
+ }
+
+ public static void
+ main(String[] argv)
+ {
+ try {
+ System.exit(cursorExample());
+ }
+ catch (WiredTigerException wte) {
+ System.err.println("Exception: " + wte);
+ wte.printStackTrace();
+ System.exit(1);
+ }
+ }
+}
diff --git a/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_log.java b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_log.java
new file mode 100644
index 00000000000..03eab6b38b1
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_log.java
@@ -0,0 +1,382 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_log.java
+ * demonstrates how to logging and log cursors.
+ */
+package com.wiredtiger.examples;
+import com.wiredtiger.db.*;
+import java.io.*;
+import java.util.*;
+
+class Lsn {
+ int file;
+ long offset;
+}
+
+public class ex_log {
+
+ public static String home1 = "WT_HOME_LOG_1";
+ public static String home2 = "WT_HOME_LOG_2";
+ public static String uri = "table:logtest";
+
+ public static final String CONN_CONFIG =
+ "create,cache_size=100MB,log=(archive=false,enabled=true)";
+ public static final int MAX_KEYS = 10;
+
+ static Session
+ setup_copy()
+ throws WiredTigerException
+ {
+ int ret = 0;
+ Connection conn;
+
+ conn = wiredtiger.open(home2, CONN_CONFIG);
+ Session session = conn.open_session(null);
+ session.create(uri, "key_format=U,value_format=U");
+ return (session);
+ }
+
+ static int
+ compare_tables(Session session, Session sess_copy)
+ throws WiredTigerException
+ {
+ int ret;
+
+ Cursor cursor = session.open_cursor(uri, null, null);
+ Cursor curs_copy = sess_copy.open_cursor(uri, null, null);
+
+ while ((ret = cursor.next()) == 0) {
+ ret = curs_copy.next();
+ byte[] key = cursor.getKeyByteArray();
+ byte[] value = cursor.getValueByteArray();
+ byte[] key_copy = curs_copy.getKeyByteArray();
+ byte[] value_copy = curs_copy.getValueByteArray();
+ if (!Arrays.equals(key, key_copy) ||
+ !Arrays.equals(value, value_copy)) {
+ System.err.println(
+ "Mismatched: key " + new String(key) +
+ ", key_copy " + new String(key_copy) +
+ ", value " + new String(value) +
+ ", value_copy " + new String(value_copy));
+ return (1);
+ }
+ }
+ if (ret != wiredtiger.WT_NOTFOUND)
+ System.err.println("WT_CURSOR.next: " +
+ wiredtiger.wiredtiger_strerror(ret));
+ ret = cursor.close();
+
+ ret = curs_copy.next();
+ if (ret != wiredtiger.WT_NOTFOUND)
+ System.err.println("WT_CURSOR.next: " +
+ wiredtiger.wiredtiger_strerror(ret));
+ ret = curs_copy.close();
+
+ return (ret);
+ }
+
+ /*! [log cursor walk] */
+ static void
+ print_record(Lsn lsn, int opcount,
+ int rectype, int optype, long txnid, int fileid,
+ byte[] key, byte[] value)
+ {
+ System.out.print(
+ "LSN [" + lsn.file + "][" + lsn.offset + "]." + opcount +
+ ": record type " + rectype + " optype " + optype +
+ " txnid " + txnid + " fileid " + fileid);
+ System.out.println(" key size " + key.length +
+ " value size " + value.length);
+ if (rectype == wiredtiger.WT_LOGREC_MESSAGE)
+ System.out.println("Application Record: " + new String(value));
+ }
+
+ /*
+ * simple_walk_log --
+ * A simple walk of the log.
+ */
+ static int
+ simple_walk_log(Session session)
+ throws WiredTigerException
+ {
+ Cursor cursor;
+ Lsn lsn = new Lsn();
+ byte[] logrec_key, logrec_value;
+ long txnid;
+ int fileid, opcount, optype, rectype;
+ int ret;
+
+ /*! [log cursor open] */
+ cursor = session.open_cursor("log:", null, null);
+ /*! [log cursor open] */
+
+ while ((ret = cursor.next()) == 0) {
+ /*! [log cursor get_key] */
+ lsn.file = cursor.getKeyInt();
+ lsn.offset = cursor.getKeyLong();
+ opcount = cursor.getKeyInt();
+ /*! [log cursor get_key] */
+ /*! [log cursor get_value] */
+ txnid = cursor.getValueLong();
+ rectype = cursor.getValueInt();
+ optype = cursor.getValueInt();
+ fileid = cursor.getValueInt();
+ logrec_key = cursor.getValueByteArray();
+ logrec_value = cursor.getValueByteArray();
+ /*! [log cursor get_value] */
+
+ print_record(lsn, opcount,
+ rectype, optype, txnid, fileid, logrec_key, logrec_value);
+ }
+ if (ret == wiredtiger.WT_NOTFOUND)
+ ret = 0;
+ ret = cursor.close();
+ return (ret);
+ }
+ /*! [log cursor walk] */
+
+ static int
+ walk_log(Session session)
+ throws WiredTigerException
+ {
+ Connection wt_conn2;
+ Cursor cursor, cursor2;
+ Lsn lsn, lsnsave;
+ byte[] logrec_key, logrec_value;
+ Session session2;
+ long txnid;
+ int fileid, opcount, optype, rectype;
+ int i, ret;
+ boolean in_txn, first;
+
+ session2 = setup_copy();
+ wt_conn2 = session2.getConnection();
+ cursor = session.open_cursor("log:", null, null);
+ cursor2 = session2.open_cursor(uri, null, "raw=true");
+ i = 0;
+ in_txn = false;
+ txnid = 0;
+ lsn = new Lsn();
+ lsnsave = new Lsn();
+ while ((ret = cursor.next()) == 0) {
+ lsn.file = cursor.getKeyInt();
+ lsn.offset = cursor.getKeyLong();
+ opcount = cursor.getKeyInt();
+
+ /*
+ * Save one of the LSNs we get back to search for it
+ * later. Pick a later one because we want to walk from
+ * that LSN to the end (where the multi-step transaction
+ * was performed). Just choose the record that is MAX_KEYS.
+ */
+ if (++i == MAX_KEYS)
+ lsnsave = lsn;
+ txnid = cursor.getValueLong();
+ rectype = cursor.getValueInt();
+ optype = cursor.getValueInt();
+ fileid = cursor.getValueInt();
+ logrec_key = cursor.getValueByteArray();
+ logrec_value = cursor.getValueByteArray();
+
+ print_record(lsn, opcount,
+ rectype, optype, txnid, fileid, logrec_key, logrec_value);
+
+ /*
+ * If we are in a transaction and this is a new one, end
+ * the previous one.
+ */
+ if (in_txn && opcount == 0) {
+ ret = session2.commit_transaction(null);
+ in_txn = false;
+ }
+
+ /*
+ * If the operation is a put, replay it here on the backup
+ * connection. Note, we cheat by looking only for fileid 1
+ * in this example. The metadata is fileid 0.
+ */
+ if (fileid == 1 && rectype == wiredtiger.WT_LOGREC_COMMIT &&
+ optype == wiredtiger.WT_LOGOP_ROW_PUT) {
+ if (!in_txn) {
+ ret = session2.begin_transaction(null);
+ in_txn = true;
+ }
+ cursor2.putKeyByteArray(logrec_key);
+ cursor2.putValueByteArray(logrec_value);
+ ret = cursor2.insert();
+ }
+ }
+ if (in_txn)
+ ret = session2.commit_transaction(null);
+
+ ret = cursor2.close();
+ /*
+ * Compare the tables after replay. They should be identical.
+ */
+ if (compare_tables(session, session2) != 0)
+ System.out.println("compare failed");
+ ret = session2.close(null);
+ ret = wt_conn2.close(null);
+
+ ret = cursor.reset();
+ /*! [log cursor set_key] */
+ cursor.putKeyInt(lsnsave.file);
+ cursor.putKeyLong(lsnsave.offset);
+ /*! [log cursor set_key] */
+ /*! [log cursor search] */
+ ret = cursor.search();
+ /*! [log cursor search] */
+ System.out.println("Reset to saved...");
+ /*
+ * Walk all records starting with this key.
+ */
+ first = true;
+ while (ret == 0) { /*TODO: not quite right*/
+ lsn.file = cursor.getKeyInt();
+ lsn.offset = cursor.getKeyLong();
+ opcount = cursor.getKeyInt();
+ if (first) {
+ first = false;
+ if (lsnsave.file != lsn.file ||
+ lsnsave.offset != lsn.offset) {
+ System.err.println("search returned the wrong LSN");
+ System.exit(1);
+ }
+ }
+ txnid = cursor.getValueLong();
+ rectype = cursor.getValueInt();
+ optype = cursor.getValueInt();
+ fileid = cursor.getValueInt();
+ logrec_key = cursor.getValueByteArray();
+ logrec_value = cursor.getValueByteArray();
+
+ print_record(lsn, opcount, rectype, optype, txnid,
+ fileid, logrec_key, logrec_value);
+
+ ret = cursor.next();
+ if (ret != 0)
+ break;
+ }
+ ret = cursor.close();
+ return (ret);
+ }
+
+ public static int
+ logExample()
+ throws WiredTigerException
+ {
+ Connection wt_conn;
+ Cursor cursor;
+ Session session;
+ int i, record_count, ret;
+
+ try {
+ String command = "/bin/rm -rf " + home1 + " " + home2;
+ Process proc = Runtime.getRuntime().exec(command);
+ BufferedReader br = new BufferedReader(
+ new InputStreamReader(proc.getInputStream()));
+ while(br.ready())
+ System.out.println(br.readLine());
+ br.close();
+ proc.waitFor();
+ new File(home1).mkdir();
+ new File(home2).mkdir();
+ } catch (Exception ex) {
+ System.err.println("Exception: " + ex);
+ return (1);
+ }
+ if ((wt_conn = wiredtiger.open(home1, CONN_CONFIG)) == null) {
+ System.err.println("Error connecting to " + home1);
+ return (1);
+ }
+
+ session = wt_conn.open_session(null);
+ ret = session.create(uri, "key_format=S,value_format=S");
+
+ cursor = session.open_cursor(uri, null, null);
+ /*
+ * Perform some operations with individual auto-commit transactions.
+ */
+ for (record_count = 0, i = 0; i < MAX_KEYS; i++, record_count++) {
+ String k = "key" + i;
+ String v = "value" + i;
+ cursor.putKeyString(k);
+ cursor.putValueString(v);
+ ret = cursor.insert();
+ }
+ ret = session.begin_transaction(null);
+ /*
+ * Perform some operations within a single transaction.
+ */
+ for (i = MAX_KEYS; i < MAX_KEYS+5; i++, record_count++) {
+ String k = "key" + i;
+ String v = "value" + i;
+ cursor.putKeyString(k);
+ cursor.putValueString(v);
+ ret = cursor.insert();
+ }
+ ret = session.commit_transaction(null);
+ ret = cursor.close();
+
+ /*! [log cursor printf] */
+ ret = session.log_printf("Wrote " + record_count + " records");
+ /*! [log cursor printf] */
+
+ session.close(null);
+ /*
+ * Close and reopen the connection so that the log ends up with
+ * a variety of records such as file sync and checkpoint. We
+ * have archiving turned off.
+ */
+ ret = wt_conn.close(null);
+ if ((wt_conn = wiredtiger.open(home1, CONN_CONFIG)) == null) {
+ System.err.println("Error connecting to " + home1);
+ return (ret);
+ }
+
+ session = wt_conn.open_session(null);
+ ret = simple_walk_log(session);
+ ret = walk_log(session);
+ ret = session.close(null);
+ ret = wt_conn.close(null);
+ return (ret);
+ }
+
+ public static void
+ main(String[] args)
+ {
+ try {
+ System.exit(logExample());
+ }
+ catch (WiredTigerException wte) {
+ System.err.println("Exception: " + wte);
+ wte.printStackTrace();
+ System.exit(1);
+ }
+ }
+}
diff --git a/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_schema.java b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_schema.java
new file mode 100644
index 00000000000..be1077ee2df
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_schema.java
@@ -0,0 +1,392 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_schema.java
+ * This is an example application demonstrating how to create and access
+ * tables using a schema.
+ */
+package com.wiredtiger.examples;
+import com.wiredtiger.db.*;
+import java.io.*;
+import java.util.*;
+
+public class ex_schema {
+
+ public static String home;
+
+ /*! [schema declaration] */
+ /* The class for the data we are storing in a WiredTiger table. */
+ static class PopRecord {
+ public String country; // Stored in database as fixed size char[5];
+ public short year;
+ public long population;
+ public PopRecord(String country, short year, long population) {
+ this.country = country;
+ this.year = year;
+ this.population = population;
+ }
+ }
+
+ static List<PopRecord> popData;
+
+ static {
+ popData = new ArrayList<PopRecord>();
+
+ popData.add(new PopRecord("AU", (short)1900, 4000000 ));
+ popData.add(new PopRecord("AU", (short)1950, 8267337 ));
+ popData.add(new PopRecord("AU", (short)2000, 19053186 ));
+ popData.add(new PopRecord("CAN", (short)1900, 5500000 ));
+ popData.add(new PopRecord("CAN", (short)1950, 14011422 ));
+ popData.add(new PopRecord("CAN", (short)2000, 31099561 ));
+ popData.add(new PopRecord("UK", (short)1900, 369000000 ));
+ popData.add(new PopRecord("UK", (short)1950, 50127000 ));
+ popData.add(new PopRecord("UK", (short)2000, 59522468 ));
+ popData.add(new PopRecord("USA", (short)1900, 76212168 ));
+ popData.add(new PopRecord("USA", (short)1950, 150697361 ));
+ popData.add(new PopRecord("USA", (short)2000, 301279593 ));
+ };
+ /*! [schema declaration] */
+
+ public static int
+ schemaExample()
+ throws WiredTigerException
+ {
+ Connection conn;
+ Cursor cursor, cursor2, join_cursor;
+ Session session;
+ String country;
+ long recno, population;
+ short year;
+ int ret;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (System.getenv("WIREDTIGER_HOME") == null) {
+ home = "WT_HOME";
+ try {
+ Process proc = Runtime.getRuntime().exec("/bin/rm -rf WT_HOME");
+ BufferedReader br = new BufferedReader(
+ new InputStreamReader(proc.getInputStream()));
+ while(br.ready())
+ System.out.println(br.readLine());
+ br.close();
+ proc.waitFor();
+ new File("WT_HOME").mkdir();
+ } catch (Exception ex) {
+ System.err.println("Exception: " + ex);
+ return (1);
+ }
+ } else
+ home = null;
+
+ try {
+ conn = wiredtiger.open(home, "create");
+ session = conn.open_session(null);
+ } catch (WiredTigerException wte) {
+ System.err.println("WiredTigerException: " + wte);
+ return(1);
+ }
+
+ /*! [Create a table with column groups] */
+ /*
+ * Create the population table.
+ * Keys are record numbers, the format for values is (5-byte string,
+ * long, long).
+ * See ::wiredtiger_struct_pack for details of the format strings.
+ */
+ ret = session.create("table:poptable",
+ "key_format=r,value_format=5sHQ," +
+ "columns=(id,country,year,population),colgroups=(main,population)");
+
+ /*
+ * Create two column groups: a primary column group with the country
+ * code, year and population (named "main"), and a population column
+ * group with the population by itself (named "population").
+ */
+ ret = session.create("colgroup:poptable:main",
+ "columns=(country,year,population)");
+ ret = session.create("colgroup:poptable:population",
+ "columns=(population)");
+ /*! [Create a table with column groups] */
+
+ /*! [Create an index] */
+ /* Create an index with a simple key. */
+ ret = session.create("index:poptable:country",
+ "columns=(country)");
+ /*! [Create an index] */
+
+ /*! [Create an immutable index] */
+ /* Create an index with a simple key. */
+ ret = session.create("index:poptable:immutable_year",
+ "columns=(year),immutable");
+ /*! [Create an immutable index] */
+
+ /*! [Create an index with a composite key] */
+ /* Create an index with a composite key (country,year). */
+ ret = session.create("index:poptable:country_plus_year",
+ "columns=(country,year)");
+ /*! [Create an index with a composite key] */
+
+ /*! [Insert and list records] */
+ /* Insert the records into the table. */
+ cursor = session.open_cursor("table:poptable", null, "append");
+ for (PopRecord p : popData) {
+ cursor.putValueString(p.country);
+ cursor.putValueShort(p.year);
+ cursor.putValueLong(p.population);
+ ret = cursor.insert();
+ }
+ ret = cursor.close();
+
+ /* Update records in the table. */
+ cursor = session.open_cursor("table:poptable", null, null);
+ while ((ret = cursor.next()) == 0) {
+ recno = cursor.getKeyRecord();
+ country = cursor.getValueString();
+ year = cursor.getValueShort();
+ population = cursor.getValueLong();
+ cursor.putValueString(country);
+ cursor.putValueShort(year);
+ cursor.putValueLong(population + 1);
+ }
+ ret = cursor.close();
+
+ /* List the records in the table. */
+ cursor = session.open_cursor("table:poptable", null, null);
+ while ((ret = cursor.next()) == 0) {
+ recno = cursor.getKeyRecord();
+ country = cursor.getValueString();
+ year = cursor.getValueShort();
+ population = cursor.getValueLong();
+ System.out.print("ID " + recno);
+ System.out.println(": country " + country + ", year " + year +
+ ", population " + population);
+ }
+ ret = cursor.close();
+ /*! [Insert and list records] */
+
+ /*! [List the records in the table using raw mode.] */
+ cursor = session.open_cursor("table:poptable", null, "raw");
+ while ((ret = cursor.next()) == 0) {
+ byte[] key, value;
+
+ key = cursor.getKeyByteArray();
+ System.out.println(Arrays.toString(key));
+ value = cursor.getValueByteArray();
+ System.out.println("raw key: " + Arrays.toString(key) +
+ ", raw value: " + Arrays.toString(value));
+ }
+ /*! [List the records in the table using raw mode.] */
+
+ /*! [Read population from the primary column group] */
+ /*
+ * Open a cursor on the main column group, and return the information
+ * for a particular country.
+ */
+ cursor = session.open_cursor("colgroup:poptable:main", null, null);
+ cursor.putKeyRecord(2);
+ if ((ret = cursor.search()) == 0) {
+ country = cursor.getValueString();
+ year = cursor.getValueShort();
+ population = cursor.getValueLong();
+ System.out.println("ID 2: country " + country +
+ ", year " + year + ", population " + population);
+ }
+ /*! [Read population from the primary column group] */
+ ret = cursor.close();
+
+ /*! [Read population from the standalone column group] */
+ /*
+ * Open a cursor on the population column group, and return the
+ * population of a particular country.
+ */
+ cursor = session.open_cursor("colgroup:poptable:population", null, null);
+ cursor.putKeyRecord(2);
+ if ((ret = cursor.search()) == 0) {
+ population = cursor.getValueLong();
+ System.out.println("ID 2: population " + population);
+ }
+ /*! [Read population from the standalone column group] */
+ ret = cursor.close();
+
+ /*! [Search in a simple index] */
+ /* Search in a simple index. */
+ cursor = session.open_cursor("index:poptable:country", null, null);
+ cursor.putKeyString("AU");
+ ret = cursor.search();
+ country = cursor.getValueString();
+ year = cursor.getValueShort();
+ population = cursor.getValueLong();
+ System.out.println("AU: country " + country + ", year " + year +
+ ", population " + population);
+ /*! [Search in a simple index] */
+ ret = cursor.close();
+
+ /*! [Search in a composite index] */
+ /* Search in a composite index. */
+ cursor = session.open_cursor(
+ "index:poptable:country_plus_year", null, null);
+ cursor.putKeyString("USA");
+ cursor.putKeyShort((short)1900);
+ ret = cursor.search();
+ country = cursor.getValueString();
+ year = cursor.getValueShort();
+ population = cursor.getValueLong();
+ System.out.println("US 1900: country " + country +
+ ", year " + year + ", population " + population);
+ /*! [Search in a composite index] */
+ ret = cursor.close();
+
+ /*! [Return a subset of values from the table] */
+ /*
+ * Use a projection to return just the table's country and year
+ * columns.
+ */
+ cursor = session.open_cursor("table:poptable(country,year)", null, null);
+ while ((ret = cursor.next()) == 0) {
+ country = cursor.getValueString();
+ year = cursor.getValueShort();
+ System.out.println("country " + country + ", year " + year);
+ }
+ /*! [Return a subset of values from the table] */
+ ret = cursor.close();
+
+ /*! [Return a subset of values from the table using raw mode] */
+ /*
+ * Use a projection to return just the table's country and year
+ * columns.
+ */
+ cursor = session.open_cursor("table:poptable(country,year)", null, null);
+ while ((ret = cursor.next()) == 0) {
+ country = cursor.getValueString();
+ year = cursor.getValueShort();
+ System.out.println("country " + country + ", year " + year);
+ }
+ /*! [Return a subset of values from the table using raw mode] */
+ ret = cursor.close();
+
+ /*! [Return the table's record number key using an index] */
+ /*
+ * Use a projection to return just the table's record number key
+ * from an index.
+ */
+ cursor = session.open_cursor("index:poptable:country_plus_year(id)", null, null);
+ while ((ret = cursor.next()) == 0) {
+ country = cursor.getKeyString();
+ year = cursor.getKeyShort();
+ recno = cursor.getValueRecord();
+ System.out.println("row ID " + recno + ": country " + country +
+ ", year " + year);
+ }
+ /*! [Return the table's record number key using an index] */
+ ret = cursor.close();
+
+ /*! [Return a subset of the value columns from an index] */
+ /*
+ * Use a projection to return just the population column from an
+ * index.
+ */
+ cursor = session.open_cursor(
+ "index:poptable:country_plus_year(population)", null, null);
+ while ((ret = cursor.next()) == 0) {
+ country = cursor.getKeyString();
+ year = cursor.getKeyShort();
+ population = cursor.getValueLong();
+ System.out.println("population " + population +
+ ": country " + country + ", year " + year);
+ }
+ /*! [Return a subset of the value columns from an index] */
+ ret = cursor.close();
+
+ /*! [Access only the index] */
+ /*
+ * Use a projection to avoid accessing any other column groups when
+ * using an index: supply an empty list of value columns.
+ */
+ cursor = session.open_cursor(
+ "index:poptable:country_plus_year()", null, null);
+ while ((ret = cursor.next()) == 0) {
+ country = cursor.getKeyString();
+ year = cursor.getKeyShort();
+ System.out.println("country " + country + ", year " + year);
+ }
+ /*! [Access only the index] */
+ ret = cursor.close();
+
+ /*! [Join cursors] */
+ /* Open cursors needed by the join. */
+ join_cursor = session.open_cursor(
+ "join:table:poptable", null, null);
+ cursor = session.open_cursor(
+ "index:poptable:country", null, null);
+ cursor2 = session.open_cursor(
+ "index:poptable:immutable_year", null, null);
+
+ /* select values WHERE country == "AU" AND year > 1900 */
+ cursor.putKeyString("AU");
+ ret = cursor.search();
+ session.join(join_cursor, cursor, "compare=eq,count=10");
+ cursor2.putKeyShort((short)1900);
+ ret = cursor2.search();
+ session.join(join_cursor, cursor2,
+ "compare=gt,count=10,strategy=bloom");
+
+ /* List the values that are joined */
+ while ((ret = join_cursor.next()) == 0) {
+ recno = join_cursor.getKeyRecord();
+ country = join_cursor.getValueString();
+ year = join_cursor.getValueShort();
+ population = join_cursor.getValueLong();
+ System.out.print("ID " + recno);
+ System.out.println( ": country " + country + ", year " + year +
+ ", population " + population);
+ }
+ /*! [Join cursors] */
+ ret = join_cursor.close();
+ ret = cursor2.close();
+ ret = cursor.close();
+
+ ret = conn.close(null);
+
+ return (ret);
+ }
+
+ public static void
+ main(String[] argv)
+ {
+ try {
+ System.exit(schemaExample());
+ }
+ catch (WiredTigerException wte) {
+ System.err.println("Exception: " + wte);
+ wte.printStackTrace();
+ System.exit(1);
+ }
+ }
+}
diff --git a/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_stat.java b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_stat.java
new file mode 100644
index 00000000000..b0b83a2d3b2
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_stat.java
@@ -0,0 +1,256 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_stat.java
+ * This is an example demonstrating how to query database statistics.
+ */
+package com.wiredtiger.examples;
+import com.wiredtiger.db.*;
+import java.io.*;
+import java.util.*;
+
+public class ex_stat {
+
+ public static String home;
+
+ /*! [statistics display function] */
+ int
+ print_cursor(Cursor cursor)
+ throws WiredTigerException
+ {
+ String desc, pvalue;
+ long value;
+ int ret;
+
+ while ((ret = cursor.next()) == 0) {
+ desc = cursor.getValueString();
+ pvalue = cursor.getValueString();
+ value = cursor.getValueLong();
+ if (value != 0)
+ System.out.println(desc + "=" + pvalue);
+ }
+
+ return (ret == wiredtiger.WT_NOTFOUND ? 0 : ret);
+ }
+ /*! [statistics display function] */
+
+ int
+ print_database_stats(Session session)
+ throws WiredTigerException
+ {
+ Cursor cursor;
+ int ret;
+
+ /*! [statistics database function] */
+ cursor = session.open_cursor("statistics:", null, null);
+
+ ret = print_cursor(cursor);
+ ret = cursor.close();
+ /*! [statistics database function] */
+
+ return (ret);
+ }
+
+ int
+ print_file_stats(Session session)
+ throws WiredTigerException
+ {
+ Cursor cursor;
+ int ret;
+
+ /*! [statistics table function] */
+ cursor = session.open_cursor("statistics:table:access", null, null);
+ ret = print_cursor(cursor);
+ ret = cursor.close();
+ /*! [statistics table function] */
+
+ return (ret);
+ }
+
+ int
+ print_overflow_pages(Session session)
+ throws WiredTigerException
+ {
+ /*! [statistics retrieve by key] */
+ Cursor cursor;
+ String desc, pvalue;
+ long value;
+ int ret;
+
+ cursor = session.open_cursor("statistics:table:access", null, null);
+
+ cursor.putKeyInt(wiredtiger.WT_STAT_DSRC_BTREE_OVERFLOW);
+ ret = cursor.search();
+ desc = cursor.getValueString();
+ pvalue = cursor.getValueString();
+ value = cursor.getValueLong();
+ System.out.println(desc + "=" + pvalue);
+
+ ret = cursor.close();
+ /*! [statistics retrieve by key] */
+
+ return (ret);
+ }
+
+ /*! [statistics calculation helper function] */
+ long
+ get_stat(Cursor cursor, int stat_field)
+ throws WiredTigerException
+ {
+ long value;
+ int ret;
+
+ cursor.putKeyInt(stat_field);
+ if ((ret = cursor.search()) != 0) {
+ System.err.println("stat_field: " + stat_field + " not found");
+ value = 0;
+ }
+ else {
+ String desc = cursor.getValueString();
+ String pvalue = cursor.getValueString();
+ value = cursor.getValueLong();
+ }
+ return (value);
+ }
+ /*! [statistics calculation helper function] */
+
+ int
+ print_derived_stats(Session session)
+ throws WiredTigerException
+ {
+ Cursor cursor;
+ int ret;
+
+ /*! [statistics calculate open table stats] */
+ cursor = session.open_cursor("statistics:table:access", null, null);
+ /*! [statistics calculate open table stats] */
+
+ {
+ /*! [statistics calculate table fragmentation] */
+ long ckpt_size = get_stat(cursor,
+ wiredtiger.WT_STAT_DSRC_BLOCK_CHECKPOINT_SIZE);
+ long file_size = get_stat(cursor,
+ wiredtiger.WT_STAT_DSRC_BLOCK_SIZE);
+
+ System.out.println("File is " +
+ (int)(100 * (file_size - ckpt_size) / file_size) +
+ "% fragmented\n");
+ /*! [statistics calculate table fragmentation] */
+ }
+
+ {
+ /*! [statistics calculate write amplification] */
+ long app_insert = get_stat(cursor,
+ wiredtiger.WT_STAT_DSRC_CURSOR_INSERT_BYTES);
+ long app_remove = get_stat(cursor,
+ wiredtiger.WT_STAT_DSRC_CURSOR_REMOVE_BYTES);
+ long app_update = get_stat(cursor,
+ wiredtiger.WT_STAT_DSRC_CURSOR_UPDATE_BYTES);
+
+ long fs_writes = get_stat(cursor,
+ wiredtiger.WT_STAT_DSRC_CACHE_BYTES_WRITE);
+
+ if (app_insert + app_remove + app_update != 0)
+ System.out.println("Write amplification is " +
+ (double)fs_writes / (app_insert + app_remove + app_update));
+ /*! [statistics calculate write amplification] */
+ }
+
+ ret = cursor.close();
+
+ return (ret);
+ }
+
+ public int
+ statExample()
+ throws WiredTigerException
+ {
+ Connection conn;
+ Cursor cursor;
+ Session session;
+ int ret;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (System.getenv("WIREDTIGER_HOME") == null) {
+ home = "WT_HOME";
+ try {
+ Process proc = Runtime.getRuntime().exec("/bin/rm -rf " + home);
+ BufferedReader br = new BufferedReader(
+ new InputStreamReader(proc.getInputStream()));
+ while(br.ready())
+ System.out.println(br.readLine());
+ br.close();
+ proc.waitFor();
+ if (!(new File(home)).mkdir())
+ System.err.println("mkdir: failed");
+ } catch (Exception ex) {
+ System.err.println("Exception: " + home + ": " + ex);
+ System.exit(1);
+ }
+ } else
+ home = null;
+
+ conn = wiredtiger.open(home, "create,statistics=(all)");
+ session = conn.open_session(null);
+
+ ret = session.create("table:access", "key_format=S,value_format=S");
+
+ cursor = session.open_cursor("table:access", null, null);
+ cursor.putKeyString("key");
+ cursor.putValueString("value");
+ ret = cursor.insert();
+ ret = cursor.close();
+
+ ret = session.checkpoint(null);
+
+ ret = print_database_stats(session);
+
+ ret = print_file_stats(session);
+
+ ret = print_overflow_pages(session);
+
+ ret = print_derived_stats(session);
+
+ return (conn.close(null) == 0 ? ret : -1);
+ }
+
+ public static void
+ main(String[] argv)
+ {
+ try {
+ System.exit((new ex_stat()).statExample());
+ }
+ catch (WiredTigerException wte) {
+ System.err.println("Exception: " + wte);
+ wte.printStackTrace();
+ System.exit(1);
+ }
+ }
+}
diff --git a/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_thread.java b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_thread.java
new file mode 100644
index 00000000000..402daebbd61
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/java/com/wiredtiger/examples/ex_thread.java
@@ -0,0 +1,149 @@
+/*-
+ * Public Domain 2014-2016 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.
+ *
+ * ex_thread.java
+ * This is an example demonstrating how to create and access a simple
+ * table from multiple threads.
+ */
+
+package com.wiredtiger.examples;
+import com.wiredtiger.db.*;
+import java.io.*;
+import java.util.*;
+
+/*! [thread scan] */
+class ScanThread extends Thread {
+ private Connection conn;
+
+ public ScanThread(Connection conn) {
+ this.conn = conn;
+ }
+
+ public void run()
+ {
+ try {
+ int ret;
+
+ Session session = conn.open_session(null);
+ Cursor cursor = session.open_cursor("table:access", null, null);
+
+ /* Show all records. */
+ while ((ret = cursor.next()) == 0) {
+ String key = cursor.getKeyString();
+ String value = cursor.getValueString();
+ System.out.println("Got record: " + key + " : " + value);
+ }
+ if (ret != wiredtiger.WT_NOTFOUND)
+ System.err.println("Cursor.next: " +
+ wiredtiger.wiredtiger_strerror(ret));
+ cursor.close();
+ session.close(null);
+ } catch (WiredTigerException wte) {
+ System.err.println("Exception " + wte);
+ }
+ }
+}
+/*! [thread scan] */
+
+public class ex_thread {
+
+ public static String home;
+
+ public static final int NUM_THREADS = 10;
+
+ /*! [thread main] */
+ public static void main(String[] argv)
+ {
+ try {
+ Thread[] threads = new Thread[NUM_THREADS];
+ int i, ret;
+ Connection conn;
+
+ /*
+ * Create a clean test directory for this run of the test program if the
+ * environment variable isn't already set (as is done by make check).
+ */
+ if (System.getenv("WIREDTIGER_HOME") == null) {
+ home = "WT_HOME";
+ try {
+ Process proc = Runtime.getRuntime().exec("/bin/rm -rf " + home);
+ BufferedReader br = new BufferedReader(
+ new InputStreamReader(proc.getInputStream()));
+ while(br.ready())
+ System.out.println(br.readLine());
+ br.close();
+ proc.waitFor();
+ if (!(new File(home)).mkdir())
+ System.err.println("mkdir: failed");
+ } catch (Exception ex) {
+ System.err.println("Exception: " + home + ": " + ex);
+ System.exit(1);
+ }
+ } else
+ home = null;
+
+ if ((conn = wiredtiger.open(home, "create")) == null) {
+ System.err.println("Error connecting to " + home);
+ System.exit(1);
+ }
+
+ /* Note: further error checking omitted for clarity. */
+
+ Session session = conn.open_session(null);
+ ret = session.create("table:access", "key_format=S,value_format=S");
+ Cursor cursor = session.open_cursor("table:access", null, "overwrite");
+ cursor.putKeyString("key1");
+ cursor.putValueString("value1");
+ ret = cursor.insert();
+ cursor.close();
+ ret = session.close(null);
+
+ for (i = 0; i < NUM_THREADS; i++) {
+ threads[i] = new ScanThread(conn);
+ threads[i].start();
+ }
+
+ for (i = 0; i < NUM_THREADS; i++)
+ try {
+ threads[i].join();
+ ret = -1;
+ }
+ catch (InterruptedException ie) {
+ }
+
+ ret = conn.close(null);
+ System.exit(ret);
+ }
+ catch (WiredTigerException wte) {
+ System.err.println("Exception: " + wte);
+ wte.printStackTrace();
+ System.exit(1);
+ }
+ }
+ /*! [thread main] */
+
+}
diff --git a/src/third_party/wiredtiger/examples/python/ex_access.py b/src/third_party/wiredtiger/examples/python/ex_access.py
new file mode 100755
index 00000000000..aa99c1f6547
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/python/ex_access.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2016 MongoDB, Inc.
+# Public Domain 2008-2014 WiredTiger, Inc.
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+import os
+from wiredtiger import wiredtiger_open
+
+# Connect to the database and open a session
+os.system('rm -rf WT_HOME')
+os.makedirs('WT_HOME')
+
+conn = wiredtiger_open('WT_HOME', 'create')
+session = conn.open_session()
+
+# Create a simple table
+session.create('table:T', 'key_format=S,value_format=S')
+
+# Open a cursor and insert a record
+cursor = session.open_cursor('table:T', None)
+
+cursor.set_key('key1')
+cursor.set_value('value1')
+cursor.insert()
+
+# Iterate through the records
+cursor.reset()
+for key, value in cursor:
+ print('Got record: %s : %s' % (key, value))
+
+conn.close()
diff --git a/src/third_party/wiredtiger/examples/python/ex_stat.py b/src/third_party/wiredtiger/examples/python/ex_stat.py
new file mode 100755
index 00000000000..10f1d6d597c
--- /dev/null
+++ b/src/third_party/wiredtiger/examples/python/ex_stat.py
@@ -0,0 +1,109 @@
+#!/usr/bin/env python
+#
+# Public Domain 2014-2016 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.
+#
+# ex_stat.py
+# This is an example demonstrating how to query database statistics.
+
+import os
+from wiredtiger import wiredtiger_open,WIREDTIGER_VERSION_STRING,stat
+
+
+def main():
+ # Create a clean test directory for this run of the test program
+ os.system('rm -rf WT_HOME')
+ os.makedirs('WT_HOME')
+ # Connect to the database and open a session
+ conn = wiredtiger_open('WT_HOME', 'create,statistics=(all)')
+ session = conn.open_session()
+
+ # Create a simple table
+ session.create('table:access', 'key_format=S,value_format=S')
+
+ # Open a cursor and insert a record
+ cursor = session.open_cursor('table:access', None)
+
+ cursor['key'] = 'value'
+ cursor.close()
+
+ session.checkpoint()
+ print WIREDTIGER_VERSION_STRING
+ print_database_stats(session)
+ print_file_stats(session)
+ print_overflow_pages(session)
+ print_derived_stats(session)
+ conn.close()
+
+
+def print_database_stats(session):
+ statcursor = session.open_cursor("statistics:")
+ print_cursor(statcursor)
+ statcursor.close()
+
+
+def print_file_stats(session):
+ fstatcursor = session.open_cursor("statistics:table:access")
+ print_cursor(fstatcursor)
+ fstatcursor.close()
+
+
+def print_overflow_pages(session):
+ ostatcursor = session.open_cursor("statistics:table:access")
+ val = ostatcursor[stat.dsrc.btree_overflow]
+ if val != 0:
+ print '%s=%s' % (str(val[0]), str(val[1]))
+ ostatcursor.close()
+
+
+def print_derived_stats(session):
+ dstatcursor = session.open_cursor("statistics:table:access")
+ ckpt_size = dstatcursor[stat.dsrc.block_checkpoint_size][1]
+ file_size = dstatcursor[stat.dsrc.block_size][1]
+ percent = 0
+ if file_size != 0:
+ percent = 100 * ((float(file_size) - float(ckpt_size)) / float(file_size))
+ print "Table is %%%s fragmented" % str(percent)
+
+ app_insert = int(dstatcursor[stat.dsrc.cursor_insert_bytes][1])
+ app_remove = int(dstatcursor[stat.dsrc.cursor_remove_bytes][1])
+ app_update = int(dstatcursor[stat.dsrc.cursor_update_bytes][1])
+ fs_writes = int(dstatcursor[stat.dsrc.cache_bytes_write][1])
+
+ if app_insert + app_remove + app_update != 0:
+ print "Write amplification is " + '{:.2f}'.format(fs_writes / (app_insert + app_remove + app_update))
+ dstatcursor.close()
+
+
+def print_cursor(mycursor):
+ while mycursor.next() == 0:
+ val = mycursor.get_value()
+ if val[1] != '0':
+ print '%s=%s' % (str(val[0]), str(val[1]))
+
+if __name__ == "__main__":
+ main()
+