diff options
Diffstat (limited to 'examples')
-rw-r--r-- | examples/c/ex_file_system.c | 150 |
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", |