summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Bostic <keith.bostic@mongodb.com>2016-05-24 19:40:00 -0400
committerMichael Cahill <michael.cahill@mongodb.com>2016-05-25 09:40:00 +1000
commitc0a04f1d22075b63f8da063226e6871a9ccfd78e (patch)
tree8e3d197c4bbc31b2930bf2aca114584fa3b1e046
parentea8840e93c316e6fa78ebb969caf2eaff8065132 (diff)
downloadmongo-c0a04f1d22075b63f8da063226e6871a9ccfd78e.tar.gz
WT-2653: the custom file-system example should show device configuration (#2741)
Add examples of passing in per-device configuration information to the demo file system initialization function. Use the WiredTiger extension API to handle errors in functions called by WiredTiger. Set the default session's strerror method. If one of the extensions being loaded reports an error via the WT_EXTENSION_API strerror method, but doesn't supply that method a WT_SESSION handle, we'll use the WT_CONNECTION_IMPL's default session and its strerror method.
-rw-r--r--dist/s_string.ok1
-rw-r--r--examples/c/ex_file_system.c150
-rw-r--r--src/conn/conn_api.c8
-rw-r--r--src/include/extern.h1
-rw-r--r--src/session/session_api.c10
5 files changed, 133 insertions, 37 deletions
diff --git a/dist/s_string.ok b/dist/s_string.ok
index 0cf4eb703eb..2cceccc538e 100644
--- a/dist/s_string.ok
+++ b/dist/s_string.ok
@@ -146,6 +146,7 @@ IEC
IEEE
IKEY
IMPL
+IMPL's
INCR
INIT
INITIALIZER
diff --git a/examples/c/ex_file_system.c b/examples/c/ex_file_system.c
index 3b632df252e..f2ea5cfae75 100644
--- a/examples/c/ex_file_system.c
+++ b/examples/c/ex_file_system.c
@@ -29,6 +29,7 @@
* demonstrates how to use the custom file system interface
*/
#include <errno.h>
+#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#if (defined(_WIN32) && _MSC_VER < 1900)
@@ -37,6 +38,8 @@
#endif
#include <wiredtiger.h>
+#include <wiredtiger_ext.h>
+
#include "queue_example.h"
static const char *home;
@@ -58,6 +61,8 @@ typedef struct {
/* Queue of file handles */
TAILQ_HEAD(demo_file_handle_qh, demo_file_handle) fileq;
+ WT_EXTENSION_API *wtext; /* Extension functions */
+
} DEMO_FILE_SYSTEM;
typedef struct demo_file_handle {
@@ -131,22 +136,93 @@ static DEMO_FILE_HANDLE *demo_handle_search(WT_FILE_SYSTEM *, const char *);
#define DEMO_FILE_SIZE_INCREMENT 32768
/*
+ * string_match --
+ * Return if a string matches a byte string of len bytes.
+ */
+static inline bool
+byte_string_match(const char *str, const char *bytes, size_t len)
+{
+ return (strncmp(str, bytes, len) == 0 && (str)[(len)] == '\0');
+}
+
+/*
* demo_file_system_create --
* Initialization point for demo file system
*/
int
demo_file_system_create(WT_CONNECTION *conn, WT_CONFIG_ARG *config)
{
- WT_FILE_SYSTEM *file_system;
DEMO_FILE_SYSTEM *demo_fs;
+ WT_CONFIG_ITEM k, v;
+ WT_CONFIG_PARSER *config_parser;
+ WT_EXTENSION_API *wtext;
+ WT_FILE_SYSTEM *file_system;
int ret = 0;
- (void)config; /* Unused */
+ wtext = conn->get_extension_api(conn);
- if ((demo_fs = calloc(1, sizeof(DEMO_FILE_SYSTEM))) == NULL)
+ if ((demo_fs = calloc(1, sizeof(DEMO_FILE_SYSTEM))) == NULL) {
+ (void)wtext->err_printf(wtext, NULL,
+ "demo_file_system_create: %s",
+ wtext->strerror(wtext, NULL, ENOMEM));
return (ENOMEM);
+ }
+ demo_fs->wtext = wtext;
file_system = (WT_FILE_SYSTEM *)demo_fs;
+ /* Retrieve our configuration information, the "config" value. */
+ if ((ret = wtext->config_get(wtext, NULL, config, "config", &v)) != 0) {
+ (void)wtext->err_printf(wtext, NULL,
+ "WT_EXTENSION_API.config_get: config: %s",
+ wtext->strerror(wtext, NULL, ret));
+ goto err;
+ }
+
+ /* Open a WiredTiger parser on the "config" value. */
+ if ((ret = wtext->config_parser_open(
+ wtext, NULL, v.str, v.len, &config_parser)) != 0) {
+ (void)wtext->err_printf(wtext, NULL,
+ "WT_EXTENSION_API.config_parser_open: config: %s",
+ wtext->strerror(wtext, NULL, ret));
+ goto err;
+ }
+
+ /* Step through our configuration values. */
+ printf("Custom file system configuration\n");
+ while ((ret = config_parser->next(config_parser, &k, &v)) == 0) {
+ if (byte_string_match("config_string", k.str, k.len)) {
+ printf("\t" "key %.*s=\"%.*s\"\n",
+ (int)k.len, k.str, (int)v.len, v.str);
+ continue;
+ }
+ if (byte_string_match("config_value", k.str, k.len)) {
+ printf("\t" "key %.*s=%" PRId64 "\n",
+ (int)k.len, k.str, v.val);
+ continue;
+ }
+ ret = EINVAL;
+ (void)wtext->err_printf(wtext, NULL,
+ "WT_CONFIG_PARSER.next: unexpected configuration "
+ "information: %.*s=%.*s: %s",
+ (int)k.len, k.str, (int)v.len, v.str,
+ wtext->strerror(wtext, NULL, ret));
+ goto err;
+ }
+
+ /* Check for expected parser termination and close the parser. */
+ if (ret != WT_NOTFOUND) {
+ (void)wtext->err_printf(wtext, NULL,
+ "WT_CONFIG_PARSER.next: config: %s",
+ wtext->strerror(wtext, NULL, ret));
+ goto err;
+ }
+ if ((ret = config_parser->close(config_parser)) != 0) {
+ (void)wtext->err_printf(wtext, NULL,
+ "WT_CONFIG_PARSER.close: config: %s",
+ wtext->strerror(wtext, NULL, ret));
+ goto err;
+ }
+
/* Initialize the in-memory jump table. */
file_system->fs_directory_list = demo_fs_directory_list;
file_system->fs_directory_list_free = demo_fs_directory_list_free;
@@ -159,11 +235,11 @@ demo_file_system_create(WT_CONNECTION *conn, WT_CONFIG_ARG *config)
file_system->terminate = demo_fs_terminate;
if ((ret = conn->set_file_system(conn, file_system, NULL)) != 0) {
- fprintf(stderr, "Error setting custom file system: %s\n",
- wiredtiger_strerror(ret));
+ (void)wtext->err_printf(wtext, NULL,
+ "WT_CONNECTION.set_file_system: %s",
+ wtext->strerror(wtext, NULL, ret));
goto err;
}
-
return (0);
err: free(demo_fs);
@@ -180,16 +256,17 @@ demo_fs_open(WT_FILE_SYSTEM *file_system, WT_SESSION *session,
const char *name, WT_OPEN_FILE_TYPE file_type, uint32_t flags,
WT_FILE_HANDLE **file_handlep)
{
- WT_FILE_HANDLE *file_handle;
DEMO_FILE_HANDLE *demo_fh;
DEMO_FILE_SYSTEM *demo_fs;
+ WT_EXTENSION_API *wtext;
+ WT_FILE_HANDLE *file_handle;
(void)file_type; /* Unused */
- (void)session; /* Unused */
(void)flags; /* Unused */
demo_fs = (DEMO_FILE_SYSTEM *)file_system;
demo_fh = NULL;
+ wtext = demo_fs->wtext;
++demo_fs->opened_file_count;
@@ -200,9 +277,8 @@ demo_fs_open(WT_FILE_SYSTEM *file_system, WT_SESSION *session,
demo_fh = demo_handle_search(file_system, name);
if (demo_fh != NULL) {
if (demo_fh->ref != 0) {
- fprintf(stderr,
- "demo_file_open of already open file %s\n",
- name);
+ (void)wtext->err_printf(wtext, session,
+ "demo_fs_open: %s: file already open", name);
return (EBUSY);
}
@@ -461,12 +537,14 @@ static int
demo_file_close(WT_FILE_HANDLE *file_handle, WT_SESSION *session)
{
DEMO_FILE_HANDLE *demo_fh;
-
- (void)session; /* Unused */
+ WT_EXTENSION_API *wtext;
demo_fh = (DEMO_FILE_HANDLE *)file_handle;
+ wtext = demo_fh->demo_fs->wtext;
+
if (demo_fh->ref < 1) {
- fprintf(stderr, "Closing already closed handle: %s\n",
+ (void)wtext->err_printf(wtext, session,
+ "demo_file_close: %s: handle already closed",
demo_fh->iface.name);
return (EINVAL);
}
@@ -501,11 +579,12 @@ demo_file_read(WT_FILE_HANDLE *file_handle,
WT_SESSION *session, wt_off_t offset, size_t len, void *buf)
{
DEMO_FILE_HANDLE *demo_fh;
+ WT_EXTENSION_API *wtext;
size_t off;
int ret = 0;
- (void)session; /* Unused */
demo_fh = (DEMO_FILE_HANDLE *)file_handle;
+ wtext = demo_fh->demo_fs->wtext;
off = (size_t)offset;
if (off < demo_fh->size) {
@@ -518,14 +597,15 @@ demo_file_read(WT_FILE_HANDLE *file_handle,
if (ret == 0)
return (0);
+
/*
* WiredTiger should never request data past the end of a file, so
* flag an error if it does.
*/
- fprintf(stderr,
- "%s: handle-read: failed to read %zu bytes at offset %zu\n",
- demo_fh->iface.name, len, off);
- return (EINVAL);
+ (void)wtext->err_printf(wtext, session,
+ "%s: handle-read: failed to read %zu bytes at offset %zu: %s",
+ demo_fh->iface.name, len, off, wtext->strerror(wtext, NULL, ret));
+ return (ret);
}
/*
@@ -582,10 +662,11 @@ demo_file_truncate(
WT_FILE_HANDLE *file_handle, WT_SESSION *session, wt_off_t offset)
{
DEMO_FILE_HANDLE *demo_fh;
+ WT_EXTENSION_API *wtext;
size_t off;
- (void)session; /* Unused */
demo_fh = (DEMO_FILE_HANDLE *)file_handle;
+ wtext = demo_fh->demo_fs->wtext;
/*
* Grow the buffer as necessary, clear any new space in the file,
@@ -594,9 +675,11 @@ demo_file_truncate(
off = (size_t)offset;
if (demo_fh->bufsize < off ) {
if ((demo_fh->buf = realloc(demo_fh->buf, off)) == NULL) {
- fprintf(stderr,
- "Failed to resize buffer in truncate\n");
- return (ENOSPC);
+ (void)wtext->err_printf(wtext, session,
+ "demo_file_truncate: %s: failed to resize buffer",
+ demo_fh->iface.name,
+ wtext->strerror(wtext, NULL, ENOMEM));
+ return (ENOMEM);
}
demo_fh->bufsize = off;
}
@@ -645,16 +728,16 @@ static int
demo_handle_remove(WT_SESSION *session, DEMO_FILE_HANDLE *demo_fh)
{
DEMO_FILE_SYSTEM *demo_fs;
+ WT_EXTENSION_API *wtext;
- (void)session; /* Unused */
demo_fs = demo_fh->demo_fs;
+ wtext = demo_fh->demo_fs->wtext;
if (demo_fh->ref != 0) {
- fprintf(stderr,
- "demo_handle_remove on file %s with non-zero reference "
- "count of %u\n",
- demo_fh->iface.name, demo_fh->ref);
- return (EINVAL);
+ (void)wtext->err_printf(wtext, session,
+ "demo_handle_remove: %s: file is currently open",
+ demo_fh->iface.name, wtext->strerror(wtext, NULL, EBUSY));
+ return (EBUSY);
}
TAILQ_REMOVE(&demo_fs->fileq, demo_fh, q);
@@ -716,10 +799,13 @@ main(void)
* Use the special local extension to indicate that the entry point is
* in the same executable. Also enable early load for this extension,
* since WiredTiger needs to be able to find it before doing any file
- * operations.
+ * operations. Finally, pass in two pieces of configuration information
+ * to our initialization function as the "config" value.
*/
- open_config = "create,log=(enabled=true),extensions=(local="
- "{entry=demo_file_system_create,early_load=true})";
+ open_config = "create,log=(enabled=true),extensions=(local={"
+ "entry=demo_file_system_create,early_load=true,"
+ "config={config_string=\"demo-file-system\",config_value=37}"
+ "})";
/* Open a connection to the database, creating it if necessary. */
if ((ret = wiredtiger_open(home, NULL, open_config, &conn)) != 0) {
fprintf(stderr, "Error connecting to %s: %s\n",
diff --git a/src/conn/conn_api.c b/src/conn/conn_api.c
index 6e7b07693d5..279e3d4a8b5 100644
--- a/src/conn/conn_api.c
+++ b/src/conn/conn_api.c
@@ -2012,6 +2012,14 @@ wiredtiger_open(const char *home, WT_EVENT_HANDLER *event_handler,
WT_ERR(__wt_os_stdio(session));
__wt_event_handler_set(session, event_handler);
+ /*
+ * Set the default session's strerror method. If one of the extensions
+ * being loaded reports an error via the WT_EXTENSION_API strerror
+ * method, but doesn't supply that method a WT_SESSION handle, we'll
+ * use the WT_CONNECTION_IMPL's default session and its strerror method.
+ */
+ conn->default_session->iface.strerror = __wt_session_strerror;
+
/* Basic initialization of the connection structure. */
WT_ERR(__wt_connection_init(conn));
diff --git a/src/include/extern.h b/src/include/extern.h
index f534785ebea..e8c20930aaf 100644
--- a/src/include/extern.h
+++ b/src/include/extern.h
@@ -570,6 +570,7 @@ extern int __wt_open_cursor(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR
extern int __wt_session_create( WT_SESSION_IMPL *session, const char *uri, const char *config);
extern int __wt_session_drop(WT_SESSION_IMPL *session, const char *uri, const char *cfg[]);
extern int __wt_session_range_truncate(WT_SESSION_IMPL *session, const char *uri, WT_CURSOR *start, WT_CURSOR *stop);
+extern const char *__wt_session_strerror(WT_SESSION *wt_session, int error);
extern int __wt_open_session(WT_CONNECTION_IMPL *conn, WT_EVENT_HANDLER *event_handler, const char *config, bool open_metadata, WT_SESSION_IMPL **sessionp);
extern int __wt_open_internal_session(WT_CONNECTION_IMPL *conn, const char *name, bool open_metadata, uint32_t session_flags, WT_SESSION_IMPL **sessionp);
extern int __wt_session_compact( WT_SESSION *wt_session, const char *uri, const char *config);
diff --git a/src/session/session_api.c b/src/session/session_api.c
index 20d97c2518a..77d1dc74c84 100644
--- a/src/session/session_api.c
+++ b/src/session/session_api.c
@@ -1523,11 +1523,11 @@ err: WT_TRET(__wt_writeunlock(session, txn_global->nsnap_rwlock));
}
/*
- * __session_strerror --
+ * __wt_session_strerror --
* WT_SESSION->strerror method.
*/
-static const char *
-__session_strerror(WT_SESSION *wt_session, int error)
+const char *
+__wt_session_strerror(WT_SESSION *wt_session, int error)
{
WT_SESSION_IMPL *session;
@@ -1550,7 +1550,7 @@ __open_session(WT_CONNECTION_IMPL *conn,
NULL,
__session_close,
__session_reconfigure,
- __session_strerror,
+ __wt_session_strerror,
__session_open_cursor,
__session_create,
__wt_session_compact,
@@ -1577,7 +1577,7 @@ __open_session(WT_CONNECTION_IMPL *conn,
NULL,
__session_close,
__session_reconfigure,
- __session_strerror,
+ __wt_session_strerror,
__session_open_cursor,
__session_create_readonly,
__wt_session_compact_readonly,