summaryrefslogtreecommitdiff
path: root/examples
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 /examples
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.
Diffstat (limited to 'examples')
-rw-r--r--examples/c/ex_file_system.c150
1 files changed, 118 insertions, 32 deletions
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",