summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/src/cursor/cur_dump.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/wiredtiger/src/cursor/cur_dump.c')
-rw-r--r--src/third_party/wiredtiger/src/cursor/cur_dump.c400
1 files changed, 400 insertions, 0 deletions
diff --git a/src/third_party/wiredtiger/src/cursor/cur_dump.c b/src/third_party/wiredtiger/src/cursor/cur_dump.c
new file mode 100644
index 00000000000..003b7e1f961
--- /dev/null
+++ b/src/third_party/wiredtiger/src/cursor/cur_dump.c
@@ -0,0 +1,400 @@
+/*-
+ * Copyright (c) 2008-2014 WiredTiger, Inc.
+ * All rights reserved.
+ *
+ * See the file LICENSE for redistribution information.
+ */
+
+#include "wt_internal.h"
+
+/*
+ * __raw_to_dump --
+ * We have a buffer where the data item contains a raw value,
+ * convert it to a printable string.
+ */
+static int
+__raw_to_dump(
+ WT_SESSION_IMPL *session, WT_ITEM *from, WT_ITEM *to, int hexonly)
+{
+ if (hexonly)
+ WT_RET(__wt_raw_to_hex(session, from->data, from->size, to));
+ else
+ WT_RET(
+ __wt_raw_to_esc_hex(session, from->data, from->size, to));
+
+ return (0);
+}
+
+/*
+ * __dump_to_raw --
+ * We have a buffer containing a dump string,
+ * convert it to a raw value.
+ */
+static int
+__dump_to_raw(
+ WT_SESSION_IMPL *session, const char *src_arg, WT_ITEM *item, int hexonly)
+{
+ if (hexonly)
+ WT_RET(__wt_hex_to_raw(session, src_arg, item));
+ else
+ WT_RET(__wt_esc_hex_to_raw(session, src_arg, item));
+
+ return (0);
+}
+
+/*
+ * __curdump_get_key --
+ * WT_CURSOR->get_key for dump cursors.
+ */
+static int
+__curdump_get_key(WT_CURSOR *cursor, ...)
+{
+ WT_CURSOR *child;
+ WT_CURSOR_DUMP *cdump;
+ WT_CURSOR_JSON *json;
+ WT_DECL_RET;
+ WT_ITEM item, *itemp;
+ WT_SESSION_IMPL *session;
+ size_t size;
+ uint64_t recno;
+ const char *fmt;
+ const void *buffer;
+ va_list ap;
+
+ cdump = (WT_CURSOR_DUMP *)cursor;
+ child = cdump->child;
+
+ va_start(ap, cursor);
+ CURSOR_API_CALL(cursor, session, get_key, NULL);
+
+ if (F_ISSET(cursor, WT_CURSTD_DUMP_JSON)) {
+ json = (WT_CURSOR_JSON *)cursor->json_private;
+ WT_ASSERT(session, json != NULL);
+ if (WT_CURSOR_RECNO(cursor)) {
+ WT_ERR(child->get_key(child, &recno));
+ buffer = &recno;
+ size = sizeof(recno);
+ fmt = "R";
+ } else {
+ WT_ERR(__wt_cursor_get_raw_key(child, &item));
+ buffer = item.data;
+ size = item.size;
+ if (F_ISSET(cursor, WT_CURSTD_RAW))
+ fmt = "u";
+ else
+ fmt = cursor->key_format;
+ }
+ ret = __wt_json_alloc_unpack(session, buffer, size, fmt,
+ json, 1, ap);
+ } else {
+ if (WT_CURSOR_RECNO(cursor) &&
+ !F_ISSET(cursor, WT_CURSTD_RAW)) {
+ WT_ERR(child->get_key(child, &recno));
+
+ WT_ERR(__wt_buf_fmt(session, &cursor->key, "%"
+ PRIu64, recno));
+ } else {
+ WT_ERR(child->get_key(child, &item));
+
+ WT_ERR(__raw_to_dump(session, &item, &cursor->key,
+ F_ISSET(cursor, WT_CURSTD_DUMP_HEX) ? 1 : 0));
+ }
+
+ if (F_ISSET(cursor, WT_CURSTD_RAW)) {
+ itemp = va_arg(ap, WT_ITEM *);
+ itemp->data = cursor->key.data;
+ itemp->size = cursor->key.size;
+ } else
+ *va_arg(ap, const char **) = cursor->key.data;
+ }
+
+err: va_end(ap);
+ API_END_RET(session, ret);
+}
+
+/*
+ * str2recno --
+ * Convert a string to a record number.
+ */
+static int
+str2recno(WT_SESSION_IMPL *session, const char *p, uint64_t *recnop)
+{
+ uint64_t recno;
+ char *endptr;
+
+ /*
+ * strtouq takes lots of things like hex values, signs and so on and so
+ * forth -- none of them are OK with us. Check the string starts with
+ * digit, that turns off the special processing.
+ */
+ if (!isdigit(p[0]))
+ goto format;
+
+ errno = 0;
+ recno = __wt_strtouq(p, &endptr, 0);
+ if (recno == ULLONG_MAX && errno == ERANGE)
+ WT_RET_MSG(session, ERANGE, "%s: invalid record number", p);
+ if (endptr[0] != '\0')
+format: WT_RET_MSG(session, EINVAL, "%s: invalid record number", p);
+
+ *recnop = recno;
+ return (0);
+}
+
+/*
+ * __curdump_set_key --
+ * WT_CURSOR->set_key for dump cursors.
+ */
+static void
+__curdump_set_key(WT_CURSOR *cursor, ...)
+{
+ WT_CURSOR_DUMP *cdump;
+ WT_CURSOR *child;
+ WT_DECL_RET;
+ WT_SESSION_IMPL *session;
+ uint64_t recno;
+ va_list ap;
+ const char *p;
+
+ cdump = (WT_CURSOR_DUMP *)cursor;
+ child = cdump->child;
+ CURSOR_API_CALL(cursor, session, set_key, NULL);
+
+ va_start(ap, cursor);
+ if (F_ISSET(cursor, WT_CURSTD_RAW))
+ p = va_arg(ap, WT_ITEM *)->data;
+ else
+ p = va_arg(ap, const char *);
+ va_end(ap);
+
+ if (WT_CURSOR_RECNO(cursor) && !F_ISSET(cursor, WT_CURSTD_RAW)) {
+ WT_ERR(str2recno(session, p, &recno));
+
+ child->set_key(child, recno);
+ } else {
+ if (F_ISSET(cursor, WT_CURSTD_DUMP_JSON))
+ WT_ERR(__wt_json_to_item(session, p, cursor->key_format,
+ (WT_CURSOR_JSON *)cursor->json_private, 1,
+ &cursor->key));
+ else
+ WT_ERR(__dump_to_raw(session, p, &cursor->key,
+ F_ISSET(cursor, WT_CURSTD_DUMP_HEX) ? 1 : 0));
+
+ child->set_key(child, &cursor->key);
+ }
+
+ if (0) {
+err: cursor->saved_err = ret;
+ F_CLR(cursor, WT_CURSTD_KEY_SET);
+ }
+ API_END(session, ret);
+}
+
+/*
+ * __curdump_get_value --
+ * WT_CURSOR->get_value for dump cursors.
+ */
+static int
+__curdump_get_value(WT_CURSOR *cursor, ...)
+{
+ WT_CURSOR_DUMP *cdump;
+ WT_CURSOR_JSON *json;
+ WT_CURSOR *child;
+ WT_DECL_RET;
+ WT_ITEM item, *itemp;
+ WT_SESSION_IMPL *session;
+ va_list ap;
+ const char *fmt;
+
+ cdump = (WT_CURSOR_DUMP *)cursor;
+ child = cdump->child;
+
+ va_start(ap, cursor);
+ CURSOR_API_CALL(cursor, session, get_value, NULL);
+
+ if (F_ISSET(cursor, WT_CURSTD_DUMP_JSON)) {
+ json = (WT_CURSOR_JSON *)cursor->json_private;
+ WT_ASSERT(session, json != NULL);
+ WT_ERR(__wt_cursor_get_raw_value(child, &item));
+ fmt = F_ISSET(cursor, WT_CURSTD_RAW) ?
+ "u" : cursor->value_format;
+ ret = __wt_json_alloc_unpack(session, item.data,
+ item.size, fmt, json, 0, ap);
+ } else {
+ WT_ERR(child->get_value(child, &item));
+
+ WT_ERR(__raw_to_dump(session, &item, &cursor->value,
+ F_ISSET(cursor, WT_CURSTD_DUMP_HEX) ? 1 : 0));
+
+ if (F_ISSET(cursor, WT_CURSTD_RAW)) {
+ itemp = va_arg(ap, WT_ITEM *);
+ itemp->data = cursor->value.data;
+ itemp->size = cursor->value.size;
+ } else
+ *va_arg(ap, const char **) = cursor->value.data;
+ }
+
+err: va_end(ap);
+ API_END_RET(session, ret);
+}
+
+/*
+ * __curdump_set_value --
+ * WT_CURSOR->set_value for dump cursors.
+ */
+static void
+__curdump_set_value(WT_CURSOR *cursor, ...)
+{
+ WT_CURSOR_DUMP *cdump;
+ WT_CURSOR *child;
+ WT_DECL_RET;
+ WT_SESSION_IMPL *session;
+ va_list ap;
+ const char *p;
+
+ cdump = (WT_CURSOR_DUMP *)cursor;
+ child = cdump->child;
+ CURSOR_API_CALL(cursor, session, set_value, NULL);
+
+ va_start(ap, cursor);
+ if (F_ISSET(cursor, WT_CURSTD_RAW))
+ p = va_arg(ap, WT_ITEM *)->data;
+ else
+ p = va_arg(ap, const char *);
+ va_end(ap);
+
+ if (F_ISSET(cursor, WT_CURSTD_DUMP_JSON))
+ WT_ERR(__wt_json_to_item(session, p, cursor->value_format,
+ (WT_CURSOR_JSON *)cursor->json_private, 0, &cursor->value));
+ else
+ WT_ERR(__dump_to_raw(session, p, &cursor->value,
+ F_ISSET(cursor, WT_CURSTD_DUMP_HEX) ? 1 : 0));
+
+ child->set_value(child, &cursor->value);
+
+ if (0) {
+err: cursor->saved_err = ret;
+ F_CLR(cursor, WT_CURSTD_VALUE_SET);
+ }
+ API_END(session, ret);
+}
+
+/* Pass through a call to the underlying cursor. */
+#define WT_CURDUMP_PASS(op) \
+static int \
+__curdump_##op(WT_CURSOR *cursor) \
+{ \
+ WT_CURSOR *child; \
+ \
+ child = ((WT_CURSOR_DUMP *)cursor)->child; \
+ return (child->op(child)); \
+}
+
+WT_CURDUMP_PASS(next)
+WT_CURDUMP_PASS(prev)
+WT_CURDUMP_PASS(reset)
+WT_CURDUMP_PASS(search)
+
+/*
+ * __curdump_search_near --
+ * WT_CURSOR::search_near for dump cursors.
+ */
+static int
+__curdump_search_near(WT_CURSOR *cursor, int *exact)
+{
+ WT_CURSOR_DUMP *cdump;
+
+ cdump = (WT_CURSOR_DUMP *)cursor;
+ return (cdump->child->search_near(cdump->child, exact));
+}
+
+WT_CURDUMP_PASS(insert)
+WT_CURDUMP_PASS(update)
+WT_CURDUMP_PASS(remove)
+
+/*
+ * __curdump_close --
+ * WT_CURSOR::close for dump cursors.
+ */
+static int
+__curdump_close(WT_CURSOR *cursor)
+{
+ WT_CURSOR_DUMP *cdump;
+ WT_CURSOR *child;
+ WT_DECL_RET;
+ WT_SESSION_IMPL *session;
+
+ cdump = (WT_CURSOR_DUMP *)cursor;
+ child = cdump->child;
+
+ CURSOR_API_CALL(cursor, session, get_key, NULL);
+ if (child != NULL)
+ WT_TRET(child->close(child));
+ /* We shared the child's URI. */
+ cursor->internal_uri = NULL;
+ __wt_json_close(session, cursor);
+ WT_TRET(__wt_cursor_close(cursor));
+
+err: API_END_RET(session, ret);
+}
+
+/*
+ * __wt_curdump_create --
+ * initialize a dump cursor.
+ */
+int
+__wt_curdump_create(WT_CURSOR *child, WT_CURSOR *owner, WT_CURSOR **cursorp)
+{
+ WT_CURSOR_STATIC_INIT(iface,
+ __curdump_get_key, /* get-key */
+ __curdump_get_value, /* get-value */
+ __curdump_set_key, /* set-key */
+ __curdump_set_value, /* set-value */
+ __wt_cursor_notsup, /* compare */
+ __curdump_next, /* next */
+ __curdump_prev, /* prev */
+ __curdump_reset, /* reset */
+ __curdump_search, /* search */
+ __curdump_search_near, /* search-near */
+ __curdump_insert, /* insert */
+ __curdump_update, /* update */
+ __curdump_remove, /* remove */
+ __curdump_close); /* close */
+ WT_CURSOR *cursor;
+ WT_CURSOR_DUMP *cdump;
+ WT_CURSOR_JSON *json;
+ WT_DECL_RET;
+ WT_SESSION_IMPL *session;
+ const char *cfg[2];
+
+ WT_STATIC_ASSERT(offsetof(WT_CURSOR_DUMP, iface) == 0);
+
+ session = (WT_SESSION_IMPL *)child->session;
+
+ WT_RET(__wt_calloc_def(session, 1, &cdump));
+ cursor = &cdump->iface;
+ *cursor = iface;
+ cursor->session = child->session;
+ cursor->internal_uri = child->internal_uri;
+ cursor->key_format = child->key_format;
+ cursor->value_format = child->value_format;
+ cdump->child = child;
+
+ /* Copy the dump flags from the child cursor. */
+ F_SET(cursor, F_ISSET(child,
+ WT_CURSTD_DUMP_HEX | WT_CURSTD_DUMP_JSON | WT_CURSTD_DUMP_PRINT));
+ if (F_ISSET(cursor, WT_CURSTD_DUMP_JSON)) {
+ WT_ERR(__wt_calloc_def(session, 1, &json));
+ cursor->json_private = child->json_private = json;
+ }
+
+ /* __wt_cursor_init is last so we don't have to clean up on error. */
+ cfg[0] = WT_CONFIG_BASE(session, session_open_cursor);
+ cfg[1] = NULL;
+ WT_ERR(__wt_cursor_init(cursor, NULL, owner, cfg, cursorp));
+
+ if (0) {
+err: __wt_free(session, cursor);
+ }
+ return (ret);
+}