Ejemplo n.º 1
0
int
util_drop(WT_SESSION *session, int argc, char *argv[])
{
	WT_DECL_RET;
	int ch;
	char *name;

	while ((ch = __wt_getopt(progname, argc, argv, "")) != EOF)
		switch (ch) {
		case '?':
		default:
			return (usage());
		}

	argc -= __wt_optind;
	argv += __wt_optind;

	/* The remaining argument is the uri. */
	if (argc != 1)
		return (usage());
	if ((name = util_name(session, *argv, "table")) == NULL)
		return (1);

	ret = session->drop(session, name, "force");

	free(name);
	return (ret);
}
Ejemplo n.º 2
0
int
util_create(WT_SESSION *session, int argc, char *argv[])
{
	WT_DECL_RET;
	int ch;
	const char *config, *uri;

	config = NULL;
	while ((ch = __wt_getopt(progname, argc, argv, "c:")) != EOF)
		switch (ch) {
		case 'c':			/* command-line configuration */
			config = __wt_optarg;
			break;
		case '?':
		default:
			return (usage());
		}

	argc -= __wt_optind;
	argv += __wt_optind;

	/* The remaining argument is the uri. */
	if (argc != 1)
		return (usage());

	if ((uri = util_name(*argv, "table")) == NULL)
		return (1);

	if ((ret = session->create(session, uri, config)) != 0)
		return (util_err(ret, "%s: session.create", uri));
	return (0);
}
Ejemplo n.º 3
0
int
util_salvage(WT_SESSION *session, int argc, char *argv[])
{
	WT_DECL_RET;
	int ch;
	const char *force;
	char *name;

	force = NULL;
	name = NULL;
	while ((ch = util_getopt(argc, argv, "F")) != EOF)
		switch (ch) {
		case 'F':
			force = "force";
			break;
		case '?':
		default:
			return (usage());
		}
	argc -= util_optind;
	argv += util_optind;

	/* The remaining argument is the file name. */
	if (argc != 1)
		return (usage());
	if ((name = util_name(*argv, "file", UTIL_FILE_OK)) == NULL)
		return (1);

	if ((ret = session->salvage(session, name, force)) != 0) {
		fprintf(stderr, "%s: salvage(%s): %s\n",
		    progname, name, wiredtiger_strerror(ret));
		goto err;
	}

	/* Verbose configures a progress counter, move to the next line. */
	if (verbose)
		printf("\n");

	if (0) {
err:		ret = 1;
	}

	if (name != NULL)
		free(name);

	return (ret);
}
Ejemplo n.º 4
0
int
util_dumpfile(WT_SESSION *session, int argc, char *argv[])
{
	int ch, ret;
	char *name;

	name = NULL;
	while ((ch = util_getopt(argc, argv, "f:")) != EOF)
		switch (ch) {
		case 'f':				/* output file */
			if (freopen(util_optarg, "w", stdout) == NULL) {
				fprintf(stderr, "%s: %s: %s\n",
				    progname, util_optarg, strerror(errno));
				return (1);
			}
			break;
		case '?':
		default:
			return (usage());
		}
	argc -= util_optind;
	argv += util_optind;

	/* The remaining argument is the file name. */
	if (argc != 1)
		return (usage());
	if ((name = util_name(*argv, "file", UTIL_FILE_OK)) == NULL)
		return (1);

	if ((ret = session->dumpfile(session, name, NULL)) != 0) {
		fprintf(stderr, "%s: dumpfile(%s): %s\n",
		    progname, name, wiredtiger_strerror(ret));
		goto err;
	}
	if (verbose)
		printf("\n");

	if (0) {
err:		ret = 1;
	}

	if (name != NULL)
		free(name);

	return (ret);
}
Ejemplo n.º 5
0
int
util_list(WT_SESSION *session, int argc, char *argv[])
{
	WT_DECL_RET;
	int cflag, ch, vflag;
	char *name;

	cflag = vflag = 0;
	name = NULL;
	while ((ch = __wt_getopt(progname, argc, argv, "cv")) != EOF)
		switch (ch) {
		case 'c':
			cflag = 1;
			break;
		case 'v':
			vflag = 1;
			break;
		case '?':
		default:
			return (usage());
		}
	argc -= __wt_optind;
	argv += __wt_optind;

	switch (argc) {
	case 0:
		break;
	case 1:
		if ((name = util_name(*argv, "table")) == NULL)
			return (1);
		break;
	default:
		return (usage());
	}

	ret = list_print(session, name, cflag, vflag);

	if (name != NULL)
		free(name);

	return (ret);
}
Ejemplo n.º 6
0
int
util_rebalance(WT_SESSION *session, int argc, char *argv[])
{
	WT_DECL_RET;
	int ch;
	char *name;

	name = NULL;
	while ((ch = __wt_getopt(progname, argc, argv, "")) != EOF)
		switch (ch) {
		case '?':
		default:
			return (usage());
		}
	argc -= __wt_optind;
	argv += __wt_optind;

	/* The remaining argument is the table name. */
	if (argc != 1)
		return (usage());
	if ((name = util_name(session, *argv, "table")) == NULL)
		return (1);

	if ((ret = session->rebalance(session, name, NULL)) != 0) {
		fprintf(stderr, "%s: rebalance(%s): %s\n",
		    progname, name, session->strerror(session, ret));
		goto err;
	}

	/* Verbose configures a progress counter, move to the next line. */
	if (verbose)
		printf("\n");

	if (0) {
err:		ret = 1;
	}

	free(name);

	return (ret);
}
Ejemplo n.º 7
0
int
util_rename(WT_SESSION *session, int argc, char *argv[])
{
	WT_DECL_RET;
	int ch;
	char *uri, *newname;

	uri = NULL;
	while ((ch = util_getopt(argc, argv, "")) != EOF)
		switch (ch) {
		case '?':
		default:
			return (usage());
		}
	argc -= util_optind;
	argv += util_optind;

	/* The remaining arguments are the object uri and new name. */
	if (argc != 2)
		return (usage());
	if ((uri = util_name(*argv,
	    "table", UTIL_FILE_OK | UTIL_LSM_OK | UTIL_TABLE_OK)) == NULL)
		return (1);
	newname = argv[1];

	if ((ret = session->rename(session, uri, newname, NULL)) != 0) {
		fprintf(stderr, "%s: rename %s to %s: %s\n",
		    progname, uri, newname, wiredtiger_strerror(ret));
		goto err;
	}

	if (0) {
err:		ret = 1;
	}

	if (uri != NULL)
		free(uri);

	return (ret);
}
Ejemplo n.º 8
0
int
util_compact(WT_SESSION *session, int argc, char *argv[])
{
	WT_DECL_RET;
	int ch;
	char *uri;

	uri = NULL;
	while ((ch = __wt_getopt(progname, argc, argv, "")) != EOF)
		switch (ch) {
		case '?':
		default:
			return (usage());
		}
	argc -= __wt_optind;
	argv += __wt_optind;

	/* The remaining argument is the table name. */
	if (argc != 1)
		return (usage());
	if ((uri = util_name(session, *argv, "table")) == NULL)
		return (1);

	if ((ret = session->compact(session, uri, NULL)) != 0) {
		fprintf(stderr, "%s: compact(%s): %s\n",
		    progname, uri, session->strerror(session, ret));
		goto err;
	}

	if (0) {
err:		ret = 1;
	}

	if (uri != NULL)
		free(uri);

	return (ret);
}
Ejemplo n.º 9
0
int
util_rename(WT_SESSION *session, int argc, char *argv[])
{
	WT_DECL_RET;
	int ch;
	char *uri, *newuri;

	uri = NULL;
	while ((ch = __wt_getopt(progname, argc, argv, "")) != EOF)
		switch (ch) {
		case '?':
		default:
			return (usage());
		}
	argc -= __wt_optind;
	argv += __wt_optind;

	/* The remaining arguments are the object uri and new name. */
	if (argc != 2)
		return (usage());
	if ((uri = util_name(session, *argv, "table")) == NULL)
		return (1);
	newuri = argv[1];

	if ((ret = session->rename(session, uri, newuri, NULL)) != 0) {
		fprintf(stderr, "%s: rename %s to %s: %s\n",
		    progname, uri, newuri, session->strerror(session, ret));
		goto err;
	}

	if (0) {
err:		ret = 1;
	}

	free(uri);

	return (ret);
}
Ejemplo n.º 10
0
int
util_stat(WT_SESSION *session, int argc, char *argv[])
{
	WT_CURSOR *cursor;
	WT_DECL_RET;
	size_t urilen;
	int ch;
	bool objname_free;
	const char *config, *pval, *desc;
	char *objname, *uri;

	objname_free = false;
	objname = uri = NULL;
	config = NULL;
	while ((ch = __wt_getopt(progname, argc, argv, "af")) != EOF)
		switch (ch) {
		case 'a':
			/*
			 * Historically, the -a option meant include all of the
			 * statistics; because we are opening the database with
			 * statistics=(all), that is now the default, allow the
			 * option for compatibility.
			 */
			config = NULL;
			break;
		case 'f':
			config = "statistics=(fast)";
			break;
		case '?':
		default:
			return (usage());
		}
	argc -= __wt_optind;
	argv += __wt_optind;

	/*
	 * If there are no arguments, the statistics cursor operates on the
	 * connection, otherwise, the optional remaining argument is a file
	 * or LSM name.
	 */
	switch (argc) {
	case 0:
		objname = (char *)"";
		break;
	case 1:
		if ((objname = util_name(session, *argv, "table")) == NULL)
			return (1);
		objname_free = true;
		break;
	default:
		return (usage());
	}

	urilen = strlen("statistics:") + strlen(objname) + 1;
	if ((uri = calloc(urilen, 1)) == NULL) {
		fprintf(stderr, "%s: %s\n", progname, strerror(errno));
		goto err;
	}
	snprintf(uri, urilen, "statistics:%s", objname);

	if ((ret =
	    session->open_cursor(session, uri, NULL, config, &cursor)) != 0) {
		fprintf(stderr, "%s: cursor open(%s) failed: %s\n",
		    progname, uri, session->strerror(session, ret));
		goto err;
	}

	/* List the statistics. */
	while (
	    (ret = cursor->next(cursor)) == 0 &&
	    (ret = cursor->get_value(cursor, &desc, &pval, NULL)) == 0)
		if (printf("%s=%s\n", desc, pval) < 0) {
			ret = errno;
			break;
		}
	if (ret == WT_NOTFOUND)
		ret = 0;

	if (ret != 0) {
		fprintf(stderr, "%s: cursor get(%s) failed: %s\n",
		    progname, objname, session->strerror(session, ret));
		goto err;
	}

	if (0) {
err:		ret = 1;
	}
	if (objname_free)
		free(objname);
	free(uri);

	return (ret);
}
Ejemplo n.º 11
0
int
util_verify(WT_SESSION *session, int argc, char *argv[])
{
	WT_DECL_RET;
	size_t size;
	int ch, dump_address, dump_blocks, dump_pages;
	char *config, *dump_offsets, *name;

	dump_address = dump_blocks = dump_pages = 0;
	config = dump_offsets = name = NULL;
	while ((ch = util_getopt(argc, argv, OPT_ARGS)) != EOF)
		switch (ch) {
		case 'd':
			if (strcmp(util_optarg, "dump_address") == 0)
				dump_address = 1;
			else if (strcmp(util_optarg, "dump_blocks") == 0)
				dump_blocks = 1;
			else if (
			    WT_PREFIX_MATCH(util_optarg, "dump_offsets=")) {
				if (dump_offsets != NULL) {
					fprintf(stderr,
					    "%s: only a single 'dump_offsets' "
					    "argument supported\n", progname);
					return (usage());
				}
				dump_offsets =
				    util_optarg + strlen("dump_offsets=");
			} else if (strcmp(util_optarg, "dump_pages") == 0)
				dump_pages = 1;
			else
				return (usage());
			break;
		case '?':
		default:
			return (usage());
		}
	argc -= util_optind;
	argv += util_optind;

	/* The remaining argument is the table name. */
	if (argc != 1)
		return (usage());
	if ((name = util_name(*argv,
	    "table", UTIL_FILE_OK | UTIL_LSM_OK | UTIL_TABLE_OK)) == NULL)
		return (1);

	/* Build the configuration string as necessary. */
	if (dump_address || dump_blocks || dump_offsets != NULL || dump_pages) {
		size =
		    strlen("dump_address,") +
		    strlen("dump_blocks,") +
		    strlen("dump_pages,") +
		    strlen("dump_offsets[],") +
		    (dump_offsets == NULL ? 0 : strlen(dump_offsets)) + 20;
		if ((config = malloc(size)) == NULL) {
			ret = util_err(errno, NULL);
			goto err;
		}
		snprintf(config, size,
		    "%s%s%s%s%s%s",
		    dump_address ? "dump_address," : "",
		    dump_blocks ? "dump_blocks," : "",
		    dump_offsets != NULL ? "dump_offsets=[" : "",
		    dump_offsets != NULL ? dump_offsets : "",
		    dump_offsets != NULL ? "]," : "",
		    dump_pages ? "dump_pages" : "");
	}
	if ((ret = session->verify(session, name, config)) != 0) {
		fprintf(stderr, "%s: verify(%s): %s\n",
		    progname, name, wiredtiger_strerror(ret));
		goto err;
	}

	/* Verbose configures a progress counter, move to the next line. */
	if (verbose)
		printf("\n");

	if (0) {
err:		ret = 1;
	}

	if (config != NULL)
		free(config);
	if (name != NULL)
		free(name);

	return (ret);
}
Ejemplo n.º 12
0
int
util_verify(WT_SESSION *session, int argc, char *argv[])
{
	WT_DECL_RET;
	int ch, dump_address, dump_blocks, dump_pages;
	char *name, config[128];

	name = NULL;
	dump_address = dump_blocks = dump_pages = 0;
	while ((ch = util_getopt(argc, argv, "d:")) != EOF)
		switch (ch) {
		case 'd':
			if (strcmp(util_optarg, "dump_address") == 0)
				dump_address = 1;
			else if (strcmp(util_optarg, "dump_blocks") == 0)
				dump_blocks = 1;
			else if (strcmp(util_optarg, "dump_pages") == 0)
				dump_pages = 1;
			else
				return (usage());
			break;
		case '?':
		default:
			return (usage());
		}
	argc -= util_optind;
	argv += util_optind;

	/* The remaining argument is the table name. */
	if (argc != 1)
		return (usage());
	if ((name = util_name(*argv,
	    "table", UTIL_FILE_OK | UTIL_LSM_OK | UTIL_TABLE_OK)) == NULL)
		return (1);

	/* Build the configuration string as necessary. */
	config[0] = '\0';
	if (dump_address)
		(void)strcat(config, "dump_address,");
	if (dump_blocks)
		(void)strcat(config, "dump_blocks,");
	if (dump_pages)
		(void)strcat(config, "dump_pages,");

	if ((ret = session->verify(session, name, config)) != 0) {
		fprintf(stderr, "%s: verify(%s): %s\n",
		    progname, name, wiredtiger_strerror(ret));
		goto err;
	}

	/* Verbose configures a progress counter, move to the next line. */
	if (verbose)
		printf("\n");

	if (0) {
err:		ret = 1;
	}

	if (name != NULL)
		free(name);

	return (ret);
}
Ejemplo n.º 13
0
int
util_stat(WT_SESSION *session, int argc, char *argv[])
{
	WT_CURSOR *cursor;
	uint64_t v;
	size_t urilen;
	int ch, objname_free, ret;
	const char *pval, *desc;
	char *objname, *uri;

	objname_free = 0;
	objname = uri = NULL;
	while ((ch = util_getopt(argc, argv, "")) != EOF)
		switch (ch) {
		case '?':
		default:
			return (usage());
		}
	argc -= util_optind;
	argv += util_optind;

	/*
	 * If there are no arguments, the statistics cursor operates on the
	 * connection, otherwise, the optional remaining argument is a file
	 * name.
	 */
	switch (argc) {
	case 0:
		objname = (char *)"";
		break;
	case 1:
		if ((objname = util_name(*argv, "file", UTIL_FILE_OK)) == NULL)
			return (1);
		objname_free = 1;
		break;
	default:
		return (usage());
	}

	urilen = strlen("statistics:") + strlen(objname) + 1;
	if ((uri = calloc(urilen, 1)) == NULL) {
		fprintf(stderr, "%s: %s\n", progname, strerror(errno));
		return (1);
	}
	snprintf(uri, urilen, "statistics:%s", objname);

	if ((ret = session->open_cursor(
	    session, uri, NULL, NULL, &cursor)) != 0) {
		fprintf(stderr, "%s: cursor open(%s) failed: %s\n",
		    progname, uri, wiredtiger_strerror(ret));
		goto err;
	}

	/* List the statistics. */
	while (
	    (ret = cursor->next(cursor)) == 0 &&
	    (ret = cursor->get_value(cursor, &desc, &pval, &v)) == 0)
		if (printf("%s=%s\n", desc, pval) < 0) {
			ret = errno;
			break;
		}
	if (ret == WT_NOTFOUND)
		ret = 0;

	if (ret != 0) {
		fprintf(stderr, "%s: cursor get(%s) failed: %s\n",
		    progname, objname, wiredtiger_strerror(ret));
		goto err;
	}

err:	if (objname_free)
		free(objname);
	free(uri);

	return (ret);
}
Ejemplo n.º 14
0
int
util_dump(WT_SESSION *session, int argc, char *argv[])
{
	WT_CURSOR *cursor;
	WT_DECL_RET;
	size_t len;
	int ch, hex, reverse;
	char *checkpoint, *config, *name;

	hex = reverse = 0;
	checkpoint = config = name = NULL;
	while ((ch = util_getopt(argc, argv, "c:f:rx")) != EOF)
		switch (ch) {
		case 'c':
			checkpoint = util_optarg;
			break;
		case 'f':			/* output file */
			if (freopen(util_optarg, "w", stdout) == NULL)
				return (
				    util_err(errno, "%s: reopen", util_optarg));
			break;
		case 'r':
			reverse = 1;
			break;
		case 'x':
			hex = 1;
			break;
		case '?':
		default:
			return (usage());
		}
	argc -= util_optind;
	argv += util_optind;

	/* The remaining argument is the uri. */
	if (argc != 1)
		return (usage());
	if ((name = util_name(*argv,
	    "table", UTIL_FILE_OK | UTIL_LSM_OK | UTIL_TABLE_OK)) == NULL)
		goto err;

	if (dump_config(session, name, hex) != 0)
		goto err;

	len =
	    checkpoint == NULL ? 0 : strlen("checkpoint=") + strlen(checkpoint);
	len += strlen(hex ? "dump=hex" : "dump=print");
	if ((config = malloc(len + 10)) == NULL)
		goto err;
	if (checkpoint == NULL)
		config[0] = '\0';
	else {
		(void)strcpy(config, "checkpoint=");
		(void)strcat(config, checkpoint);
		(void)strcat(config, ",");
	}
	(void)strcat(config, hex ? "dump=hex" : "dump=print");
	if ((ret = session->open_cursor(
	    session, name, NULL, config, &cursor)) != 0) {
		fprintf(stderr, "%s: cursor open(%s) failed: %s\n",
		    progname, name, wiredtiger_strerror(ret));
		goto err;
	}

	if (reverse)
		ret = dump_reverse(cursor, name);
	else
		ret = dump_forward(cursor, name);

	if (0) {
err:		ret = 1;
	}

	if (config != NULL)
		free(config);
	if (name != NULL)
		free(name);

	return (ret);
}
Ejemplo n.º 15
0
int
util_dump(WT_SESSION *session, int argc, char *argv[])
{
	WT_CURSOR *cursor;
	WT_DECL_RET;
	size_t len;
	int ch, i;
	bool hex, json, reverse;
	char *checkpoint, *config, *name;

	hex = json = reverse = false;
	checkpoint = config = name = NULL;
	while ((ch = __wt_getopt(progname, argc, argv, "c:f:jrx")) != EOF)
		switch (ch) {
		case 'c':
			checkpoint = __wt_optarg;
			break;
		case 'f':			/* output file */
			if (freopen(__wt_optarg, "w", stdout) == NULL)
				return (util_err(
				    session, errno, "%s: reopen", __wt_optarg));
			break;
		case 'j':
			json = true;
			break;
		case 'r':
			reverse = true;
			break;
		case 'x':
			hex = true;
			break;
		case '?':
		default:
			return (usage());
		}
	argc -= __wt_optind;
	argv += __wt_optind;

	/* -j and -x are incompatible. */
	if (hex && json) {
		fprintf(stderr,
		    "%s: the -j and -x dump options are incompatible\n",
		    progname);
		goto err;
	}

	/* The remaining argument is the uri. */
	if (argc < 1 || (argc != 1 && !json))
		return (usage());

	if (json &&
	    ((ret = dump_json_begin(session)) != 0 ||
	    (ret = dump_prefix(session, hex, json)) != 0))
		goto err;

	for (i = 0; i < argc; i++) {
		if (json && i > 0)
			if ((ret = dump_json_separator(session)) != 0)
				goto err;
		free(name);
		name = NULL;

		if ((name = util_name(session, argv[i], "table")) == NULL)
			goto err;

		if (dump_config(session, name, hex, json) != 0)
			goto err;

		len =
		    checkpoint == NULL ? 0 : strlen("checkpoint=") +
		    strlen(checkpoint) + 1;
		len += strlen(json ? "dump=json" :
		    (hex ? "dump=hex" : "dump=print"));
		if ((config = malloc(len + 10)) == NULL)
			goto err;
		if (checkpoint == NULL)
			config[0] = '\0';
		else {
			(void)strcpy(config, "checkpoint=");
			(void)strcat(config, checkpoint);
			(void)strcat(config, ",");
		}
		(void)strcat(config, json ? "dump=json" :
		    (hex ? "dump=hex" : "dump=print"));
		if ((ret = session->open_cursor(
		    session, name, NULL, config, &cursor)) != 0) {
			fprintf(stderr, "%s: cursor open(%s) failed: %s\n",
			    progname, name, session->strerror(session, ret));
			goto err;
		}

		if ((ret = dump_record(cursor, reverse, json)) != 0)
			goto err;
		if (json && (ret = dump_json_table_end(session)) != 0)
			goto err;
	}
	if (json && ((ret = dump_json_end(session)) != 0))
		goto err;

	if (0) {
err:		ret = 1;
	}

	free(config);
	free(name);

	return (ret);
}
Ejemplo n.º 16
0
int
util_write(WT_SESSION *session, int argc, char *argv[])
{
	WT_CURSOR *cursor;
	uint64_t recno;
	int append, ch, overwrite, rkey, ret;
	const char *uri;
	char config[100];

	append = overwrite = ret = 0;

	while ((ch = util_getopt(argc, argv, "ao")) != EOF)
		switch (ch) {
		case 'a':
			append = 1;
			break;
		case 'o':
			overwrite = 1;
			break;
		case '?':
		default:
			return (usage());
		}
	argc -= util_optind;
	argv += util_optind;

	/*
	 * The remaining arguments are a uri followed by a list of values (if
	 * append is set), or key/value pairs (if append is not set).
	 */
	if (append) {
		if (argc < 2)
			return (usage());
	} else
		if (argc < 3 || ((argc - 1) % 2 != 0))
			return (usage());
	if ((uri =
	    util_name(*argv, "table", UTIL_FILE_OK | UTIL_TABLE_OK)) == NULL)
		return (1);

	/* Open the object. */
	(void)snprintf(config, sizeof(config), "%s,%s",
	    append ? "append=true" : "", overwrite ? "overwrite=true" : "");
	if ((ret = session->open_cursor(
	    session, uri, NULL, config, &cursor)) != 0)
		return (util_err(ret, "%s: session.open", uri));

	/*
	 * A simple search only makes sense if the key format is a string or a
	 * record number, and the value format is a single string.
	 */
	if (strcmp(cursor->key_format, "r") != 0 &&
	    strcmp(cursor->key_format, "S") != 0) {
		fprintf(stderr,
		    "%s: write command only possible when the key format is "
		    "a record number or string\n",
		    progname);
		return (1);
	}
	rkey = strcmp(cursor->key_format, "r") == 0 ? 1 : 0;
	if (strcmp(cursor->value_format, "S") != 0) {
		fprintf(stderr,
		    "%s: write command only possible when the value format is "
		    "a string\n",
		    progname);
		return (1);
	}

	/* Run through the values or key/value pairs. */
	while (*++argv != NULL) {
		if (!append) {
			if (rkey) {
				if (util_str2recno(*argv, &recno))
					return (1);
				cursor->set_key(cursor, recno);
			} else
				cursor->set_key(cursor, *argv);
			++argv;
		}
		cursor->set_value(cursor, *argv);

		if ((ret = cursor->insert(cursor)) != 0)
			return (util_cerr(uri, "search", ret));
	}
		
	return (0);
}
Ejemplo n.º 17
0
int
util_read(WT_SESSION *session, int argc, char *argv[])
{
	WT_CURSOR *cursor;
	WT_DECL_RET;
	uint64_t recno;
	int ch, rkey, rval;
	const char *uri, *value;

	while ((ch = util_getopt(argc, argv, "")) != EOF)
		switch (ch) {
		case '?':
		default:
			return (usage());
		}
	argc -= util_optind;
	argv += util_optind;

	/* The remaining arguments are a uri followed by a list of keys. */
	if (argc < 2)
		return (usage());
	if ((uri = util_name(*argv, "table", UTIL_ALL_OK)) == NULL)
		return (1);

	/* Open the object. */
	if ((ret = session->open_cursor(
	    session, uri, NULL, NULL, &cursor)) != 0)
		return (util_err(ret, "%s: session.open", uri));

	/*
	 * A simple search only makes sense if the key format is a string or a
	 * record number, and the value format is a single string.
	 */
	if (strcmp(cursor->key_format, "r") != 0 &&
	    strcmp(cursor->key_format, "S") != 0) {
		fprintf(stderr,
		    "%s: read command only possible when the key format is "
		    "a record number or string\n",
		    progname);
		return (1);
	}
	rkey = strcmp(cursor->key_format, "r") == 0 ? 1 : 0;
	if (strcmp(cursor->value_format, "S") != 0) {
		fprintf(stderr,
		    "%s: read command only possible when the value format is "
		    "a string\n",
		    progname);
		return (1);
	}

	/*
	 * Run through the keys, returning non-zero on error or if any requested
	 * key isn't found.
	 */
	for (rval = 0; *++argv != NULL;) {
		if (rkey) {
			if (util_str2recno(*argv, &recno))
				return (1);
			cursor->set_key(cursor, recno);
		} else
			cursor->set_key(cursor, *argv);

		switch (ret = cursor->search(cursor)) {
		case 0:
			if ((ret = cursor->get_value(cursor, &value)) != 0)
				return (util_cerr(uri, "get_value", ret));
			if (printf("%s\n", value) < 0)
				return (util_err(EIO, NULL));
			break;
		case WT_NOTFOUND:
			(void)util_err(0, "%s: not found", *argv);
			rval = 1;
			break;
		default:
			return (util_cerr(uri, "search", ret));
		}
	}

	return (rval);
}