diff options
Diffstat (limited to 'src/utilities/util_dump.c')
-rw-r--r-- | src/utilities/util_dump.c | 362 |
1 files changed, 94 insertions, 268 deletions
diff --git a/src/utilities/util_dump.c b/src/utilities/util_dump.c index aedd9168fbd..0f09009cd4c 100644 --- a/src/utilities/util_dump.c +++ b/src/utilities/util_dump.c @@ -8,24 +8,19 @@ #include "util.h" -static int dump_config(WT_SESSION *, const char *, bool); +static int dump_config(WT_SESSION *, const char *, bool, bool); static int dump_json_begin(WT_SESSION *); static int dump_json_end(WT_SESSION *); static int dump_json_separator(WT_SESSION *); -static int dump_json_table_begin( - WT_SESSION *, WT_CURSOR *, const char *, const char *); -static int dump_json_table_cg( - WT_SESSION *, WT_CURSOR *, const char *, const char *, const char *); -static int dump_json_table_config(WT_SESSION *, const char *); static int dump_json_table_end(WT_SESSION *); -static int dump_prefix(WT_SESSION *, bool); +static int dump_prefix(WT_SESSION *, bool, bool); static int dump_record(WT_CURSOR *, bool, bool); -static int dump_suffix(WT_SESSION *); -static int dump_table_config(WT_SESSION *, WT_CURSOR *, const char *); +static int dump_suffix(WT_SESSION *, bool); +static int dump_table_config(WT_SESSION *, WT_CURSOR *, const char *, bool); static int dump_table_config_complex( - WT_SESSION *, WT_CURSOR *, WT_CURSOR *, const char *, const char *); + WT_SESSION *, WT_CURSOR *, WT_CURSOR *, const char *, const char *, bool); static int dup_json_string(const char *, char **); -static int print_config(WT_SESSION *, const char *, char *[]); +static int print_config(WT_SESSION *, const char *, char *[], bool, bool); static int usage(void); int @@ -91,9 +86,7 @@ util_dump(WT_SESSION *session, int argc, char *argv[]) if ((name = util_name(session, argv[i], "table")) == NULL) goto err; - if (json && dump_json_table_config(session, name) != 0) - goto err; - if (!json && dump_config(session, name, hex) != 0) + if (dump_config(session, name, hex, json) != 0) goto err; len = @@ -142,7 +135,7 @@ err: ret = 1; * Dump the config for the uri. */ static int -dump_config(WT_SESSION *session, const char *uri, bool hex) +dump_config(WT_SESSION *session, const char *uri, bool hex, bool json) { WT_CURSOR *cursor; WT_DECL_RET; @@ -162,9 +155,9 @@ dump_config(WT_SESSION *session, const char *uri, bool hex) */ cursor->set_key(cursor, uri); if ((ret = cursor->search(cursor)) == 0) { - if (dump_prefix(session, hex) != 0 || - dump_table_config(session, cursor, uri) != 0 || - dump_suffix(session) != 0) + if (dump_prefix(session, hex, json) != 0 || + dump_table_config(session, cursor, uri, json) != 0 || + dump_suffix(session, json) != 0) ret = 1; } else if (ret == WT_NOTFOUND) ret = util_err(session, 0, "%s: No such object exists", uri); @@ -217,225 +210,6 @@ dump_json_separator(WT_SESSION *session) } /* - * dump_json_table_begin -- - * Output the JSON syntax that starts a table, along with its config. - */ -static int -dump_json_table_begin( - WT_SESSION *session, WT_CURSOR *cursor, const char *uri, const char *config) -{ - WT_DECL_RET; - const char *name; - char *jsonconfig; - - jsonconfig = NULL; - - /* Get the table name. */ - if ((name = strchr(uri, ':')) == NULL) { - fprintf(stderr, "%s: %s: corrupted uri\n", progname, uri); - return (1); - } - ++name; - - if ((ret = dup_json_string(config, &jsonconfig)) != 0) - return (util_cerr(cursor, "config dup", ret)); - if (printf(" \"%s\" : [\n {\n", uri) < 0) - goto eio; - if (printf(" \"config\" : \"%s\",\n", jsonconfig) < 0) - goto eio; - - if ((ret = dump_json_table_cg( - session, cursor, name, "colgroup:", "colgroups")) == 0) { - if (printf(",\n") < 0) - goto eio; - ret = dump_json_table_cg( - session, cursor, name, "index:", "indices"); - } - - if (printf("\n },\n {\n \"data\" : [") < 0) - goto eio; - - if (0) { -eio: ret = util_err(session, EIO, NULL); - } - - free(jsonconfig); - return (ret); -} - -/* - * dump_json_table_cg -- - * Dump the column groups or indices for a table. - */ -static int -dump_json_table_cg(WT_SESSION *session, WT_CURSOR *cursor, - const char *name, const char *entry, const char *header) -{ - static const char * const indent = " "; - WT_DECL_RET; - int exact; - bool once; - const char *key, *skip, *value; - char *jsonconfig; - - once = false; - if (printf(" \"%s\" : [", header) < 0) - return (util_err(session, EIO, NULL)); - - /* - * For table dumps, we're done. - */ - if (cursor == NULL) { - if (printf("]") < 0) - return (util_err(session, EIO, NULL)); - else - return (0); - } - - /* - * Search the file looking for column group and index key/value pairs: - * for each one, look up the related source information and append it - * to the base record. - */ - cursor->set_key(cursor, entry); - if ((ret = cursor->search_near(cursor, &exact)) != 0) { - if (ret == WT_NOTFOUND) - return (0); - return (util_cerr(cursor, "search_near", ret)); - } - if (exact >= 0) - goto match; - while ((ret = cursor->next(cursor)) == 0) { -match: if ((ret = cursor->get_key(cursor, &key)) != 0) - return (util_cerr(cursor, "get_key", ret)); - - /* Check if we've finished the list of entries. */ - if (!WT_PREFIX_MATCH(key, entry)) - break; - - /* Check for a table name match. */ - skip = key + strlen(entry); - if (strncmp( - skip, name, strlen(name)) != 0 || skip[strlen(name)] != ':') - continue; - - /* Get the value. */ - if ((ret = cursor->get_value(cursor, &value)) != 0) - return (util_cerr(cursor, "get_value", ret)); - - if ((ret = dup_json_string(value, &jsonconfig)) != 0) - return (util_cerr(cursor, "config dup", ret)); - ret = printf("%s\n" - "%s{\n" - "%s \"uri\" : \"%s\",\n" - "%s \"config\" : \"%s\"\n" - "%s}", - once ? "," : "", - indent, indent, key, indent, jsonconfig, indent); - free(jsonconfig); - if (ret < 0) - return (util_err(session, EIO, NULL)); - - once = true; - } - if (printf("%s]", once ? "\n " : "") < 0) - return (util_err(session, EIO, NULL)); - if (ret == 0 || ret == WT_NOTFOUND) - return (0); - return (util_cerr(cursor, "next", ret)); -} - -/* - * dump_json_table_config -- - * Dump the config for the uri. - */ -static int -dump_json_table_config(WT_SESSION *session, const char *uri) -{ - WT_CONFIG_ITEM cval; - WT_CURSOR *cursor; - WT_DECL_RET; - size_t len; - int tret; - const char *name, *value; - char *p; - - p = NULL; - - /* Get the table name. */ - if ((name = strchr(uri, ':')) == NULL) { - fprintf(stderr, "%s: %s: corrupted uri\n", progname, uri); - return (1); - } - ++name; - - /* Open a metadata cursor. */ - if ((ret = session->open_cursor( - session, "metadata:create", NULL, NULL, &cursor)) != 0) { - fprintf(stderr, "%s: %s: session.open_cursor: %s\n", - progname, "metadata:create", - session->strerror(session, ret)); - return (1); - } - - /* - * Search for the object itself, just to make sure it exists, we don't - * want to output a header if the user entered the wrong name. This is - * where we find out a table doesn't exist, use a simple error message. - * - * Workaround for WiredTiger "simple" table handling. Simple tables - * have column-group entries, but they aren't listed in the metadata's - * table entry. Figure out if it's a simple table and in that case, - * retrieve the column-group entry and use the value from its "source" - * file. - */ - if (WT_PREFIX_MATCH(uri, "table:")) { - len = strlen("colgroup:") + strlen(name) + 1; - if ((p = malloc(len)) == NULL) - return (util_err(session, errno, NULL)); - (void)snprintf(p, len, "colgroup:%s", name); - cursor->set_key(cursor, p); - if ((ret = cursor->search(cursor)) == 0) { - if ((ret = cursor->get_value(cursor, &value)) != 0) - return (util_cerr(cursor, "get_value", ret)); - if ((ret = __wt_config_getones( - (WT_SESSION_IMPL *)session, - value, "source", &cval)) != 0) - return (util_err( - session, ret, "%s: source entry", p)); - free(p); - len = cval.len + 10; - if ((p = malloc(len)) == NULL) - return (util_err(session, errno, NULL)); - (void)snprintf(p, len, "%.*s", (int)cval.len, cval.str); - cursor->set_key(cursor, p); - } else - cursor->set_key(cursor, uri); - } else - cursor->set_key(cursor, uri); - - if ((ret = cursor->search(cursor)) == 0) { - if ((ret = cursor->get_value(cursor, &value)) != 0) - ret = util_cerr(cursor, "get_value", ret); - else if (dump_json_table_begin( - session, cursor, uri, value) != 0) - ret = 1; - } else if (ret == WT_NOTFOUND) - ret = util_err(session, 0, "%s: No such object exists", uri); - else - ret = util_err(session, ret, "%s", uri); - - if ((tret = cursor->close(cursor)) != 0) { - tret = util_cerr(cursor, "close", tret); - if (ret == 0) - ret = tret; - } - - free(p); - return (ret); -} - -/* * dump_json_table_end -- * Output the JSON syntax that ends a table. */ @@ -452,7 +226,8 @@ dump_json_table_end(WT_SESSION *session) * Dump the config for a table. */ static int -dump_table_config(WT_SESSION *session, WT_CURSOR *cursor, const char *uri) +dump_table_config( + WT_SESSION *session, WT_CURSOR *cursor, const char *uri, bool json) { WT_CONFIG_ITEM cval; WT_CURSOR *srch; @@ -479,11 +254,11 @@ dump_table_config(WT_SESSION *session, WT_CURSOR *cursor, const char *uri) */ cursor->set_key(cursor, uri); if ((ret = cursor->search(cursor)) != 0) - return (util_cerr(cursor, "search", ret)); + WT_ERR(util_cerr(cursor, "search", ret)); if ((ret = cursor->get_value(cursor, &v)) != 0) - return (util_cerr(cursor, "get_value", ret)); + WT_ERR(util_cerr(cursor, "get_value", ret)); if ((*--cfg = strdup(v)) == NULL) - return (util_err(session, errno, NULL)); + WT_ERR(util_err(session, errno, NULL)); /* * Workaround for WiredTiger "simple" table handling. Simple tables @@ -497,37 +272,36 @@ dump_table_config(WT_SESSION *session, WT_CURSOR *cursor, const char *uri) if (WT_PREFIX_MATCH(uri, "table:")) { len = strlen("colgroup:") + strlen(name) + 1; if ((p = malloc(len)) == NULL) - return (util_err(session, errno, NULL)); + WT_ERR(util_err(session, errno, NULL)); (void)snprintf(p, len, "colgroup:%s", name); cursor->set_key(cursor, p); if ((ret = cursor->search(cursor)) == 0) { if ((ret = cursor->get_value(cursor, &v)) != 0) - return (util_cerr(cursor, "get_value", ret)); + WT_ERR(util_cerr(cursor, "get_value", ret)); if ((*--cfg = strdup(v)) == NULL) - return (util_err(session, errno, NULL)); + WT_ERR(util_err(session, errno, NULL)); if ((ret =__wt_config_getones( (WT_SESSION_IMPL *)session, *cfg, "source", &cval)) != 0) - return (util_err( + WT_ERR(util_err( session, ret, "%s: source entry", p)); free(p); len = cval.len + 10; if ((p = malloc(len)) == NULL) - return (util_err(session, errno, NULL)); + WT_ERR(util_err(session, errno, NULL)); (void)snprintf(p, len, "%.*s", (int)cval.len, cval.str); cursor->set_key(cursor, p); if ((ret = cursor->search(cursor)) != 0) - return (util_cerr(cursor, "search", ret)); + WT_ERR(util_cerr(cursor, "search", ret)); if ((ret = cursor->get_value(cursor, &v)) != 0) - return (util_cerr(cursor, "get_value", ret)); + WT_ERR(util_cerr(cursor, "get_value", ret)); if ((*--cfg = strdup(v)) == NULL) - return (util_err(session, errno, NULL)); + WT_ERR(util_err(session, errno, NULL)); } else complex_table = true; } - if (print_config(session, uri, cfg) != 0) - return (1); + WT_ERR(print_config(session, uri, cfg, json, true)); if (complex_table) { /* @@ -537,21 +311,24 @@ dump_table_config(WT_SESSION *session, WT_CURSOR *cursor, const char *uri) */ if ((ret = session->open_cursor( session, "metadata:", NULL, NULL, &srch)) != 0) - return (util_cerr(cursor, "open_cursor", ret)); + WT_ERR(util_cerr(cursor, "open_cursor", ret)); if ((ret = dump_table_config_complex( - session, cursor, srch, name, "colgroup:")) == 0) + session, cursor, srch, name, "colgroup:", json)) == 0) ret = dump_table_config_complex( - session, cursor, srch, name, "index:"); + session, cursor, srch, name, "index:", json); if ((tret = srch->close(srch)) != 0) { tret = util_cerr(cursor, "close", tret); if (ret == 0) ret = tret; } - } + } else if (json && printf( + " \"colgroups\" : [],\n" + " \"indices\" : []\n") < 0) + WT_ERR(util_cerr(cursor, NULL, EIO)); - free(p); +err: free(p); free(_cfg[0]); free(_cfg[1]); free(_cfg[2]); @@ -563,17 +340,31 @@ dump_table_config(WT_SESSION *session, WT_CURSOR *cursor, const char *uri) * Dump the column groups or indices for a table. */ static int -dump_table_config_complex(WT_SESSION *session, - WT_CURSOR *cursor, WT_CURSOR *srch, const char *name, const char *entry) +dump_table_config_complex(WT_SESSION *session, WT_CURSOR *cursor, + WT_CURSOR *srch, const char *name, const char *entry, bool json) { WT_CONFIG_ITEM cval; WT_DECL_RET; - const char *key; + bool multiple; + const char *groupname, *key, *sep; size_t len; int exact; const char *v; char *p, *cfg[3] = {NULL, NULL, NULL}; + multiple = false; + sep = ""; + + if (json) { + if (strcmp(entry, "colgroup:") == 0) { + groupname = "colgroups"; + sep = ","; + } else { + groupname = "indices"; + } + if (printf(" \"%s\" : [", groupname) < 0) + return (util_err(session, EIO, NULL)); + } /* * Search the file looking for column group and index key/value pairs: * for each one, look up the related source information and append it @@ -594,7 +385,7 @@ match: if ((ret = cursor->get_key(cursor, &key)) != 0) /* Check if we've finished the list of entries. */ if (!WT_PREFIX_MATCH(key, entry)) - return (0); + break; /* * Check for a table name match. This test will match "simple" @@ -635,14 +426,19 @@ match: if ((ret = cursor->get_key(cursor, &key)) != 0) if ((cfg[0] = strdup(v)) == NULL) return (util_err(session, errno, NULL)); + if (json && printf("%s\n", multiple ? "," : "") < 0) + return (util_err(session, EIO, NULL)); /* * The dumped configuration string is the original key plus the * source's configuration, where the values of the original key * override any source configurations of the same name. */ - if (print_config(session, key, cfg) != 0) + if (print_config(session, key, cfg, json, false) != 0) return (util_err(session, EIO, NULL)); + multiple = true; } + if (json && printf("\n ]%s\n", sep) < 0) + return (util_err(session, EIO, NULL)); free(cfg[0]); free(cfg[1]); @@ -656,10 +452,13 @@ match: if ((ret = cursor->get_key(cursor, &key)) != 0) * Output the dump file header prefix. */ static int -dump_prefix(WT_SESSION *session, bool hex) +dump_prefix(WT_SESSION *session, bool hex, bool json) { int vmajor, vminor, vpatch; + if (json) + return (0); + (void)wiredtiger_version(&vmajor, &vminor, &vpatch); if (printf( @@ -718,10 +517,18 @@ dump_record(WT_CURSOR *cursor, bool reverse, bool json) * Output the dump file header suffix. */ static int -dump_suffix(WT_SESSION *session) +dump_suffix(WT_SESSION *session, bool json) { - if (printf("Data\n") < 0) - return (util_err(session, EIO, NULL)); + if (json) { + if (printf( + " },\n" + " {\n" + " \"data\" : [") < 0) + return (util_err(session, EIO, NULL)); + } else { + if (printf("Data\n") < 0) + return (util_err(session, EIO, NULL)); + } return (0); } @@ -759,21 +566,40 @@ dup_json_string(const char *str, char **result) * Output a key/value URI pair by combining v1 and v2. */ static int -print_config(WT_SESSION *session, const char *key, char *cfg[]) +print_config( + WT_SESSION *session, const char *key, char *cfg[], bool json, bool toplevel) { WT_DECL_RET; - char *value_ret; + char *jsonconfig, *value_ret; /* * We have all of the object configuration, but don't have the default * session.create configuration. Have the underlying library add in the * defaults and collapse it all into one load configuration string. */ + jsonconfig = NULL; if ((ret = __wt_schema_create_final( (WT_SESSION_IMPL *)session, cfg, &value_ret)) != 0) return (util_err(session, ret, NULL)); - ret = printf("%s\n%s\n", key, value_ret); + if (json && (ret = dup_json_string(value_ret, &jsonconfig)) != 0) { + free(value_ret); + return (util_err(session, ret, NULL)); + } + if (json) { + if (toplevel) + ret = printf( + " \"%s\" : [\n {\n " + "\"config\" : \"%s\",\n", key, jsonconfig); + else + ret = printf( + " {\n" + " \"uri\" : \"%s\",\n" + " \"config\" : \"%s\"\n" + " }", key, jsonconfig); + } else + ret = printf("%s\n%s\n", key, value_ret); free(value_ret); + free(jsonconfig); if (ret < 0) return (util_err(session, EIO, NULL)); return (0); |