Example #1
0
/*
 * __recovery_file_scan --
 *	Scan the files referenced from the metadata and gather information
 *	about them for recovery.
 */
static int
__recovery_file_scan(WT_RECOVERY *r)
{
	WT_CURSOR *c;
	WT_DECL_RET;
	int cmp;
	const char *uri, *config;

	/* Scan through all files in the metadata. */
	c = r->files[0].c;
	c->set_key(c, "file:");
	if ((ret = c->search_near(c, &cmp)) != 0) {
		/* Is the metadata empty? */
		WT_RET_NOTFOUND_OK(ret);
		return (0);
	}
	if (cmp < 0)
		WT_RET_NOTFOUND_OK(c->next(c));
	for (; ret == 0; ret = c->next(c)) {
		WT_RET(c->get_key(c, &uri));
		if (!WT_PREFIX_MATCH(uri, "file:"))
			break;
		WT_RET(c->get_value(c, &config));
		WT_RET(__recovery_setup_file(r, uri, config));
	}
	WT_RET_NOTFOUND_OK(ret);
	return (0);
}
Example #2
0
/*
 * verify_metadata --
 *	Verify all the tables expected are in the metadata. We expect all but
 *	the "corrupt" table name.
 */
static void
verify_metadata(WT_CONNECTION *conn, TABLE_INFO *tables)
{
	TABLE_INFO *t;
	WT_CURSOR *cursor;
	int ret;
	const char *kv;

	/*
	 * Open a metadata cursor.
	 */
	testutil_check(conn->open_session(conn, NULL, NULL, &wt_session));
	testutil_check(wt_session->open_cursor(
	    wt_session, "metadata:", NULL, NULL, &cursor));
	reset_verified(tables);

	/*
	 * We have to walk the cursor and walk the tables to match up that
	 * the expected tables are in the metadata. It is not efficient, but
	 * the list of tables is small. Walk the cursor once and the array
	 * of tables each time.
	 */
	while ((ret = cursor->next(cursor)) == 0) {
		testutil_check(cursor->get_key(cursor, &kv));
		for (t = tables; t->name != NULL; t++) {
			if (strcmp(t->name, kv) == 0) {
				testutil_assert(t->verified == false);
				t->verified = true;
				break;
			}
		}
	}
	testutil_assert(ret == WT_NOTFOUND);
	testutil_check(cursor->close(cursor));
	/*
	 * Any tables that were salvaged, make sure we can read the data.
	 * The corrupt table should never be salvaged.
	 */
	for (t = tables; t->name != NULL; t++) {
		if (strcmp(t->name, CORRUPT) == 0 && !test_out_of_sync)
			testutil_assert(t->verified == false);
		else if (t->verified != true)
			printf("%s not seen in metadata\n", t->name);
		else {
			testutil_check(wt_session->open_cursor(
			    wt_session, t->name, NULL, NULL, &cursor));
			while ((ret = cursor->next(cursor)) == 0) {
				testutil_check(cursor->get_value(cursor, &kv));
				testutil_assert(strcmp(kv, VALUE) == 0);
			}
			testutil_assert(ret == WT_NOTFOUND);
			testutil_check(cursor->close(cursor));
			printf("%s metadata salvaged and data verified\n",
			    t->name);
		}
	}
}
Example #3
0
/*
 * wts_stats --
 *	Dump the run's statistics.
 */
void
wts_stats(void)
{
	WT_CONNECTION *conn;
	WT_CURSOR *cursor;
	WT_SESSION *session;
	FILE *fp;
	const char *pval, *desc;
	uint64_t v;
	int ret;

	track("stat", 0ULL, NULL);

	conn = g.wts_conn;
	if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
		die(ret, "connection.open_session");

	if ((fp = fopen("__stats", "w")) == NULL)
		die(errno, "fopen: __stats");

	/* Connection statistics. */
	if ((ret = session->open_cursor(session,
	    "statistics:", NULL, NULL, &cursor)) != 0)
		die(ret, "session.open_cursor");

	while ((ret = cursor->next(cursor)) == 0 &&
	    (ret = cursor->get_value(cursor, &desc, &pval, &v)) == 0)
		if (fprintf(fp, "%s=%s\n", desc, pval) < 0)
			die(errno, "fprintf");

	if (ret != WT_NOTFOUND)
		die(ret, "cursor.next");
	if ((ret = cursor->close(cursor)) != 0)
		die(ret, "cursor.close");

	/* File statistics. */
	if ((ret = session->open_cursor(session,
	    "statistics:" WT_TABLENAME, NULL, NULL, &cursor)) != 0)
		die(ret, "session.open_cursor");

	while ((ret = cursor->next(cursor)) == 0 &&
	    (ret = cursor->get_value(cursor, &desc, &pval, &v)) == 0)
		if (fprintf(fp, "%s=%s\n", desc, pval) < 0)
			die(errno, "fprintf");

	if (ret != WT_NOTFOUND)
		die(ret, "cursor.next");
	if ((ret = cursor->close(cursor)) != 0)
		die(ret, "cursor.close");

	if ((ret = fclose(fp)) != 0)
		die(ret, "fclose");

	if ((ret = session->close(session, NULL)) != 0)
		die(ret, "session.close");
}
Example #4
0
/*
 * __wt_meta_btree_apply --
 *	Apply a function to all files listed in the metadata, apart from the
 *	metadata file.
 */
int
__wt_meta_btree_apply(WT_SESSION_IMPL *session,
    int (*func)(WT_SESSION_IMPL *, const char *[]), const char *cfg[])
{
	WT_CURSOR *cursor;
	WT_DATA_HANDLE *saved_dhandle;
	WT_DECL_RET;
	const char *uri;
	int cmp, tret;

	saved_dhandle = session->dhandle;
	WT_RET(__wt_metadata_cursor(session, NULL, &cursor));
	cursor->set_key(cursor, "file:");
	if ((tret = cursor->search_near(cursor, &cmp)) == 0 && cmp < 0)
		tret = cursor->next(cursor);
	for (; tret == 0; tret = cursor->next(cursor)) {
		WT_ERR(cursor->get_key(cursor, &uri));
		if (!WT_PREFIX_MATCH(uri, "file:"))
			break;
		else if (strcmp(uri, WT_METAFILE_URI) == 0)
			continue;

		/*
		 * We need to pull the handle into the session handle cache
		 * and make sure it's referenced to stop other internal code
		 * dropping the handle (e.g in LSM when cleaning up obsolete
		 * chunks).  Holding the metadata lock isn't enough.
		 */
		ret = __wt_session_get_btree(session, uri, NULL, NULL, 0);
		if (ret == 0) {
			WT_SAVE_DHANDLE(session,
			    ret = func(session, cfg));
			if (WT_META_TRACKING(session))
				WT_TRET(
				    __wt_meta_track_handle_lock(session, 0));
			else
				WT_TRET(__wt_session_release_btree(session));
		} else if (ret == EBUSY)
			ret = __wt_conn_btree_apply_single(
			    session, uri, NULL, func, cfg);
		WT_ERR(ret);
	}

	if (tret != WT_NOTFOUND)
		WT_TRET(tret);
err:	WT_TRET(cursor->close(cursor));
	session->dhandle = saved_dhandle;
	return (ret);
}
Example #5
0
/*
 * __clsm_next --
 *	WT_CURSOR->next method for the LSM cursor type.
 */
static int
__clsm_next(WT_CURSOR *cursor)
{
	WT_CURSOR_LSM *clsm;
	WT_CURSOR *c;
	WT_DECL_RET;
	WT_SESSION_IMPL *session;
	u_int i;
	int cmp;
	bool check, deleted;

	clsm = (WT_CURSOR_LSM *)cursor;

	CURSOR_API_CALL(cursor, session, next, NULL);
	WT_CURSOR_NOVALUE(cursor);
	WT_ERR(__clsm_enter(clsm, false, false));

	/* If we aren't positioned for a forward scan, get started. */
	if (clsm->current == NULL || !F_ISSET(clsm, WT_CLSM_ITERATE_NEXT)) {
		F_CLR(clsm, WT_CLSM_MULTIPLE);
		WT_FORALL_CURSORS(clsm, c, i) {
			if (!F_ISSET(cursor, WT_CURSTD_KEY_SET)) {
				WT_ERR(c->reset(c));
				ret = c->next(c);
			} else if (c != clsm->current) {
				c->set_key(c, &cursor->key);
				if ((ret = c->search_near(c, &cmp)) == 0) {
					if (cmp < 0)
						ret = c->next(c);
					else if (cmp == 0) {
						if (clsm->current == NULL)
							clsm->current = c;
						else
							F_SET(clsm,
							    WT_CLSM_MULTIPLE);
					}
				} else
					F_CLR(c, WT_CURSTD_KEY_SET);
			}
			WT_ERR_NOTFOUND_OK(ret);
		}
		F_SET(clsm, WT_CLSM_ITERATE_NEXT);
		F_CLR(clsm, WT_CLSM_ITERATE_PREV);

		/* We just positioned *at* the key, now move. */
		if (clsm->current != NULL)
			goto retry;
	} else {
Example #6
0
File: main.c Project: ajdavis/mongo
static void
write_and_read_new(WT_SESSION *session)
{
	WT_CURSOR *logc;
	WT_ITEM logrec_key, logrec_value;
	uint64_t txnid;
	uint32_t fileid, log_file, log_offset, opcount, optype, rectype;
	bool saw_msg;

	/*
	 * Write a log record and force it to disk so we can read it.
	 */
	printf("Write log_printf record and verify.\n");
	testutil_check(session->log_printf(session, "Test Log Record"));
	testutil_check(session->log_flush(session, "sync=on"));
	testutil_check(
	    session->open_cursor(session, "log:", NULL, NULL, &logc));
	testutil_check(
	    session->open_cursor(session, "log:", NULL, NULL, &logc));
	saw_msg = false;
	while (logc->next(logc) == 0) {
		/*
		 * We don't really need to get the key, but in case we want
		 * the LSN for some message, get it.
		 */
		testutil_check(logc->get_key(
		    logc, &log_file, &log_offset, &opcount));
		testutil_check(logc->get_value(logc, &txnid,
		    &rectype, &optype, &fileid, &logrec_key, &logrec_value));
		/*
		 * We should never see a record from us in log file 2.  We wrote
		 * a record there, but then the record in log file 1 was
		 * truncated to be a partial record, ending the log there.
		 * So everything after that, including everything in log
		 * file 2, is invalid until we get to log file 3 which is where
		 * the post-recovery records will be written.
		 * The one exception in log file two is the system record for
		 * the previous log file's LSN.  Although it is written by the
		 * system, we do walk it when using a cursor.
		 */
		if (log_file == 2 && rectype != WT_LOGREC_SYSTEM)
			testutil_die(EINVAL, "Found LSN in Log 2");
#if 0
		printf("LSN [%" PRIu32 "][%" PRIu32 "].%" PRIu32
		    ": record type %" PRIu32 " optype %" PRIu32
		    " txnid %" PRIu64 " fileid %" PRIu32 "\n",
		    log_file, log_offset, opcount,
		    rectype, optype, txnid, fileid);
#endif
		if (rectype == WT_LOGREC_MESSAGE) {
			saw_msg = true;
			printf("Application Record: %s\n",
			    (char *)logrec_value.data);
			break;
		}
	}
	testutil_check(logc->close(logc));
	if (!saw_msg)
		testutil_die(EINVAL, "Did not traverse log printf record");
}
Example #7
0
/*! [thread scan] */
void *
scan_thread(void *conn_arg)
{
	WT_CONNECTION *conn;
	WT_CURSOR *cursor;
	WT_SESSION *session;
	const char *key, *value;
	int ret;

	conn = conn_arg;
	ret = conn->open_session(conn, NULL, NULL, &session);
	ret = session->open_cursor(
	    session, "table:access", NULL, NULL, &cursor);

	/* Show all records. */
	while ((ret = cursor->next(cursor)) == 0) {
		ret = cursor->get_key(cursor, &key);
		ret = cursor->get_value(cursor, &value);

		printf("Got record: %s : %s\n", key, value);
	}
	if (ret != WT_NOTFOUND)
		fprintf(stderr,
		    "WT_CURSOR.next: %s\n", session->strerror(session, ret));

	return (NULL);
}
void WiredTigerOperationStats::fetchStats(WT_SESSION* session,
                                          const std::string& uri,
                                          const std::string& config) {
    invariant(session);

    WT_CURSOR* c = nullptr;
    const char* cursorConfig = config.empty() ? nullptr : config.c_str();
    int ret = session->open_cursor(session, uri.c_str(), nullptr, cursorConfig, &c);
    uassert(ErrorCodes::CursorNotFound, "Unable to open statistics cursor", ret == 0);

    invariant(c);
    ON_BLOCK_EXIT([&] { c->close(c); });

    const char* desc;
    uint64_t value;
    uint64_t key;
    while (c->next(c) == 0 && c->get_key(c, &key) == 0) {
        fassert(51035, c->get_value(c, &desc, nullptr, &value) == 0);
#if defined(__s390x__)
        _stats[key >> 32] = WiredTigerUtil::castStatisticsValue<long long>(value);
#else
        _stats[key] = WiredTigerUtil::castStatisticsValue<long long>(value);
#endif  // __s390x__
    }

    // Reset the statistics so that the next fetch gives the recent values.
    invariantWTOK(c->reset(c));
}
Example #9
0
/*
 * simple_walk_log --
 *	A simple walk of the log.
 */
static int
simple_walk_log(WT_SESSION *session)
{
	WT_CURSOR *cursor;
	WT_LSN lsn;
	WT_ITEM logrec_key, logrec_value;
	uint64_t txnid;
	uint32_t fileid, opcount, optype, rectype;
	int ret;

	/*! [log cursor open] */
	ret = session->open_cursor(session, "log:", NULL, NULL, &cursor);
	/*! [log cursor open] */

	while ((ret = cursor->next(cursor)) == 0) {
		/*! [log cursor get_key] */
		ret = cursor->get_key(cursor, &lsn.file, &lsn.offset, &opcount);
		/*! [log cursor get_key] */
		/*! [log cursor get_value] */
		ret = cursor->get_value(cursor, &txnid,
		    &rectype, &optype, &fileid, &logrec_key, &logrec_value);
		/*! [log cursor get_value] */

		print_record(&lsn, opcount,
		    rectype, optype, txnid, fileid, &logrec_key, &logrec_value);
	}
	if (ret == WT_NOTFOUND)
		ret = 0;
	ret = cursor->close(cursor);
	return (ret);
}
Example #10
0
/*
 * __curindex_search_near --
 *	WT_CURSOR->search_near method for index cursors.
 */
static int
__curindex_search_near(WT_CURSOR *cursor, int *exact)
{
	WT_CURSOR *child;
	WT_CURSOR_INDEX *cindex;
	WT_DECL_RET;
	WT_ITEM found_key;
	WT_SESSION_IMPL *session;
	int cmp;

	cindex = (WT_CURSOR_INDEX *)cursor;
	child = cindex->child;
	JOINABLE_CURSOR_API_CALL(cursor, session, search, NULL);

	/*
	 * We are searching using the application-specified key, which
	 * (usually) doesn't contain the primary key, so it is just a prefix of
	 * any matching index key.  That said, if there is an exact match, we
	 * want to find the first matching index entry and set exact equal to
	 * zero.
	 *
	 * Do a search_near, and if we find an entry that is too small, step to
	 * the next one.  In the unlikely event of a search past the end of the
	 * tree, go back to the last key.
	 */
	__wt_cursor_set_raw_key(child, &cursor->key);
	WT_ERR(child->search_near(child, &cmp));

	if (cmp < 0) {
		if ((ret = child->next(child)) == WT_NOTFOUND)
			ret = child->prev(child);
		WT_ERR(ret);
	}

	/*
	 * We expect partial matches, and want the smallest record with a key
	 * greater than or equal to the search key.
	 *
	 * If the found key starts with the search key, we indicate a match by
	 * setting exact equal to zero.
	 *
	 * The compare function expects application-supplied keys to come first
	 * so we flip the sign of the result to match what callers expect.
	 */
	found_key = child->key;
	if (found_key.size > cursor->key.size)
		found_key.size = cursor->key.size;

	WT_ERR(__wt_compare(
	    session, cindex->index->collator, &cursor->key, &found_key, exact));
	*exact = -*exact;

	WT_ERR(__curindex_move(cindex));

	if (0) {
err:		F_CLR(cursor, WT_CURSTD_KEY_INT | WT_CURSTD_VALUE_INT);
	}

	API_END_RET(session, ret);
}
Example #11
0
/*
 * simple_walk_log --
 *	A simple walk of the write-ahead log.
 *	We wrote text messages into the log.  Print them.
 *	This verifies we're decrypting properly.
 */
static void
simple_walk_log(WT_SESSION *session)
{
	WT_CURSOR *cursor;
	WT_ITEM logrec_key, logrec_value;
	uint64_t txnid;
	uint32_t fileid, log_file, log_offset, opcount, optype, rectype;
	int found, ret;

	error_check(session->open_cursor(session, "log:", NULL, NULL, &cursor));

	found = 0;
	while ((ret = cursor->next(cursor)) == 0) {
		error_check(cursor->get_key(
		    cursor, &log_file, &log_offset, &opcount));
		error_check(cursor->get_value(cursor, &txnid,
		    &rectype, &optype, &fileid, &logrec_key, &logrec_value));

		if (rectype == WT_LOGREC_MESSAGE) {
			found = 1;
			printf("Application Log Record: %s\n",
			    (char *)logrec_value.data);
		}
	}
	scan_end_check(ret == WT_NOTFOUND);

	error_check(cursor->close(cursor));
	if (found == 0) {
		fprintf(stderr, "Did not find log messages.\n");
		exit(EXIT_FAILURE);
	}
}
std::vector<std::string> WiredTigerKVEngine::getAllIdents(OperationContext* opCtx) const {
    std::vector<std::string> all;
    WiredTigerCursor cursor("metadata:", WiredTigerSession::kMetadataTableId, false, opCtx);
    WT_CURSOR* c = cursor.get();
    if (!c)
        return all;

    while (c->next(c) == 0) {
        const char* raw;
        c->get_key(c, &raw);
        StringData key(raw);
        size_t idx = key.find(':');
        if (idx == string::npos)
            continue;
        StringData type = key.substr(0, idx);
        if (type != "table")
            continue;

        StringData ident = key.substr(idx + 1);
        if (ident == "sizeStorer")
            continue;

        all.push_back(ident.toString());
    }

    return all;
}
Example #13
0
/*
 * stats
 *	Dump the database/file statistics.
 */
void
stats(void)
{
	FILE *fp;
	WT_CURSOR *cursor;
	WT_SESSION *session;
	uint64_t v;
	int ret;
	const char *desc, *pval;
	char name[64];

	testutil_check(conn->open_session(conn, NULL, NULL, &session));

	if ((fp = fopen(FNAME_STAT, "w")) == NULL)
		testutil_die(errno, "fopen " FNAME_STAT);

	/* Connection statistics. */
	testutil_check(session->open_cursor(
	    session, "statistics:", NULL, NULL, &cursor));

	while ((ret = cursor->next(cursor)) == 0 &&
	    (ret = cursor->get_value(cursor, &desc, &pval, &v)) == 0)
		(void)fprintf(fp, "%s=%s\n", desc, pval);

	if (ret != WT_NOTFOUND)
		testutil_die(ret, "cursor.next");
	testutil_check(cursor->close(cursor));

	/* File statistics. */
	if (!multiple_files) {
		testutil_check(__wt_snprintf(
		    name, sizeof(name), "statistics:" FNAME, 0));
		testutil_check(session->open_cursor(
		    session, name, NULL, NULL, &cursor));

		while ((ret = cursor->next(cursor)) == 0 &&
		    (ret = cursor->get_value(cursor, &desc, &pval, &v)) == 0)
			(void)fprintf(fp, "%s=%s\n", desc, pval);

		if (ret != WT_NOTFOUND)
			testutil_die(ret, "cursor.next");
		testutil_check(cursor->close(cursor));

		testutil_check(session->close(session, NULL));
	}
	(void)fclose(fp);
}
Example #14
0
/*
 * __curindex_search --
 *	WT_CURSOR->search method for index cursors.
 */
static int
__curindex_search(WT_CURSOR *cursor)
{
	WT_CURSOR *child;
	WT_CURSOR_INDEX *cindex;
	WT_DECL_RET;
	WT_ITEM found_key;
	WT_SESSION_IMPL *session;
	int cmp;

	cindex = (WT_CURSOR_INDEX *)cursor;
	child = cindex->child;
	JOINABLE_CURSOR_API_CALL(cursor, session, search, NULL);

	/*
	 * We are searching using the application-specified key, which
	 * (usually) doesn't contain the primary key, so it is just a prefix of
	 * any matching index key.  Do a search_near, step to the next entry if
	 * we land on one that is too small, then check that the prefix
	 * matches.
	 */
	__wt_cursor_set_raw_key(child, &cursor->key);
	WT_ERR(child->search_near(child, &cmp));

	if (cmp < 0)
		WT_ERR(child->next(child));

	/*
	 * We expect partial matches, and want the smallest record with a key
	 * greater than or equal to the search key.
	 *
	 * If the key we find is shorter than the search key, it can't possibly
	 * match.
	 *
	 * The only way for the key to be exactly equal is if there is an index
	 * on the primary key, because otherwise the primary key columns will
	 * be appended to the index key, but we don't disallow that (odd) case.
	 */
	found_key = child->key;
	if (found_key.size < cursor->key.size)
		WT_ERR(WT_NOTFOUND);
	found_key.size = cursor->key.size;

	WT_ERR(__wt_compare(
	    session, cindex->index->collator, &cursor->key, &found_key, &cmp));
	if (cmp != 0) {
		ret = WT_NOTFOUND;
		goto err;
	}

	WT_ERR(__curindex_move(cindex));

	if (0) {
err:		F_CLR(cursor, WT_CURSTD_KEY_INT | WT_CURSTD_VALUE_INT);
	}

	API_END_RET(session, ret);
}
Example #15
0
int
util_backup(WT_SESSION *session, int argc, char *argv[])
{
	WT_CURSOR *cursor;
	WT_DECL_RET;
	int ch;
	char *config;
	const char *directory, *name;

	config = NULL;
	while ((ch = util_getopt(argc, argv, "t:")) != EOF)
		switch (ch) {
		case 't':
			if (append_target(util_optarg, &config))
				return (1);
			break;
		case '?':
		default:
			return (usage());
		}
	argc -= util_optind;
	argv += util_optind;

	if (argc != 1) {
		(void)usage();
		goto err;
	}
	directory = *argv;

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

	/* Copy the files. */
	while (
	    (ret = cursor->next(cursor)) == 0 &&
	    (ret = cursor->get_key(cursor, &name)) == 0)
		if ((ret = copy(name, directory)) != 0)
			goto err;
	if (ret == WT_NOTFOUND)
		ret = 0;

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

err:	if (config != NULL)
		free(config);
	if (cbuf != NULL)
		free(cbuf);

	return (ret);
}
    boost::optional<Record> next() final {
        if (_eof)
            return {};

        WT_CURSOR* c = _cursor->get();

        bool mustAdvance = true;
        if (_lastReturnedId.isNull() && !_forward && _rs._isCapped) {
            // In this case we need to seek to the highest visible record.
            const RecordId reverseCappedInitialSeekPoint =
                _readUntilForOplog.isNull() ? _rs.lowestCappedHiddenRecord() : _readUntilForOplog;

            if (!reverseCappedInitialSeekPoint.isNull()) {
                c->set_key(c, _makeKey(reverseCappedInitialSeekPoint));
                int cmp;
                int seekRet = WT_OP_CHECK(c->search_near(c, &cmp));
                if (seekRet == WT_NOTFOUND) {
                    _eof = true;
                    return {};
                }
                invariantWTOK(seekRet);

                // If we landed at or past the lowest hidden record, we must advance to be in
                // the visible range.
                mustAdvance = _rs.isCappedHidden(reverseCappedInitialSeekPoint)
                    ? (cmp >= 0)
                    : (cmp > 0);  // No longer hidden.
            }
        }

        if (mustAdvance) {
            // Nothing after the next line can throw WCEs.
            // Note that an unpositioned (or eof) WT_CURSOR returns the first/last entry in the
            // table when you call next/prev.
            int advanceRet = WT_OP_CHECK(_forward ? c->next(c) : c->prev(c));
            if (advanceRet == WT_NOTFOUND) {
                _eof = true;
                return {};
            }
            invariantWTOK(advanceRet);
        }

        int64_t key;
        invariantWTOK(c->get_key(c, &key));
        const RecordId id = _fromKey(key);

        if (!isVisible(id)) {
            _eof = true;
            return {};
        }

        WT_ITEM value;
        invariantWTOK(c->get_value(c, &value));

        _lastReturnedId = id;
        return {{id, {static_cast<const char*>(value.data), static_cast<int>(value.size)}}};
    }
Example #17
0
/*
 * __backup_all --
 *	Backup all objects in the database.
 */
static int
__backup_all(WT_SESSION_IMPL *session, WT_CURSOR_BACKUP *cb)
{
	WT_CONFIG_ITEM cval;
	WT_CURSOR *cursor;
	WT_DECL_RET;
	const char *key, *value;

	cursor = NULL;

	/*
	 * Open a cursor on the metadata file and copy all of the entries to
	 * the hot backup file.
	 */
	WT_ERR(__wt_metadata_cursor(session, NULL, &cursor));
	while ((ret = cursor->next(cursor)) == 0) {
		WT_ERR(cursor->get_key(cursor, &key));
		WT_ERR(cursor->get_value(cursor, &value));
		WT_ERR_TEST((fprintf(
		    cb->bfp, "%s\n%s\n", key, value) < 0), __wt_errno());

		/*
		 * While reading the metadata file, check there are no "sources"
		 * or "types" which can't support hot backup.  This checks for
		 * a data source that's non-standard, which can't be backed up,
		 * but is also sanity checking: if there's an entry backed by
		 * anything other than a file or lsm entry, we're confused.
		 */
		if ((ret = __wt_config_getones(
		    session, value, "type", &cval)) == 0 &&
		    !WT_PREFIX_MATCH_LEN(cval.str, cval.len, "file") &&
		    !WT_PREFIX_MATCH_LEN(cval.str, cval.len, "lsm"))
			WT_ERR_MSG(session, ENOTSUP,
			    "hot backup is not supported for objects of "
			    "type %.*s", (int)cval.len, cval.str);
		WT_ERR_NOTFOUND_OK(ret);
		if ((ret =__wt_config_getones(
		    session, value, "source", &cval)) == 0 &&
		    !WT_PREFIX_MATCH_LEN(cval.str, cval.len, "file:") &&
		    !WT_PREFIX_MATCH_LEN(cval.str, cval.len, "lsm:"))
			WT_ERR_MSG(session, ENOTSUP,
			    "hot backup is not supported for objects of "
			    "source %.*s", (int)cval.len, cval.str);
		WT_ERR_NOTFOUND_OK(ret);
	}
	WT_ERR_NOTFOUND_OK(ret);

	/* Build a list of the file objects that need to be copied. */
	WT_WITH_DHANDLE_LOCK(session,
	    ret = __wt_meta_btree_apply(
	    session, __backup_list_all_append, NULL));

err:	if (cursor != NULL)
		WT_TRET(cursor->close(cursor));
	return (ret);
}
    bool restore() final {
        if (!_cursor)
            _cursor.emplace(_rs.getURI(), _rs.tableId(), true, _txn);

        // This will ensure an active session exists, so any restored cursors will bind to it
        invariant(WiredTigerRecoveryUnit::get(_txn)->getSession(_txn) == _cursor->getSession());

        // If we've hit EOF, then this iterator is done and need not be restored.
        if (_eof)
            return true;

        if (_lastReturnedId.isNull())
            return true;

        WT_CURSOR* c = _cursor->get();
        c->set_key(c, _makeKey(_lastReturnedId));

        int cmp;
        int ret = WT_OP_CHECK(c->search_near(c, &cmp));
        if (ret == WT_NOTFOUND) {
            _eof = true;
            return !_rs._isCapped;
        }
        invariantWTOK(ret);

        if (cmp == 0)
            return true;  // Landed right where we left off.

        if (_rs._isCapped) {
            // Doc was deleted either by cappedDeleteAsNeeded() or cappedTruncateAfter().
            // It is important that we error out in this case so that consumers don't
            // silently get 'holes' when scanning capped collections. We don't make
            // this guarantee for normal collections so it is ok to skip ahead in that case.
            _eof = true;
            return false;
        }

        if (_forward && cmp > 0) {
            // We landed after where we were. Move back one so that next() will return this
            // document.
            ret = WT_OP_CHECK(c->prev(c));
        } else if (!_forward && cmp < 0) {
            // Do the opposite for reverse cursors.
            ret = WT_OP_CHECK(c->next(c));
        }
        if (ret != WT_NOTFOUND)
            invariantWTOK(ret);

        return true;
    }
Example #19
0
static int
run_child(const char *homedir, int op, int expect)
{
	WT_CONNECTION *conn;
	WT_CURSOR *cursor;
	WT_SESSION *session;
	int i, ret;
	const char *cfg;

	/*
	 * We expect the read-only database will allow the second read-only
	 * handle to succeed because no one can create or set the lock file.
	 */
	if (op == OP_READ)
		cfg = ENV_CONFIG_RD;
	else
		cfg = ENV_CONFIG_WR;
	if ((ret = wiredtiger_open(homedir, NULL, cfg, &conn)) == 0) {
		if (expect == EXPECT_ERR)
			testutil_die(
			    ret, "wiredtiger_open expected error, succeeded");
	} else {
		if (expect == EXPECT_SUCCESS)
			testutil_die(
			    ret, "wiredtiger_open expected success, error");
		/*
		 * If we expect an error and got one, we're done.
		 */
		return (0);
	}

	/*
	 * Make sure we can read the data.
	 */
	if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
		testutil_die(ret, "WT_CONNECTION:open_session");

	if ((ret =
	    session->open_cursor(session, uri, NULL, NULL, &cursor)) != 0)
		testutil_die(ret, "WT_SESSION.open_cursor: %s", uri);

	i = 0;
	while ((ret = cursor->next(cursor)) == 0)
		++i;
	if (i != MAX_KV)
		testutil_die(EPERM, "cursor walk");
	if ((ret = conn->close(conn, NULL)) != 0)
		testutil_die(ret, "conn_close");
	return (0);
}
Example #20
0
int main(void)
{
	/*! [access example connection] */
	WT_CONNECTION *conn;
	WT_CURSOR *cursor;
	WT_SESSION *session;
	const char *key, *value;
	int ret;

	if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0 ||
	    (ret = conn->open_session(conn, NULL, NULL, &session)) != 0) {
		fprintf(stderr, "Error connecting to %s: %s\n",
		    home, wiredtiger_strerror(ret));
		return (ret);
	}
	/*! [access example connection] */

	/*! [access example table create] */
	ret = session->create(session,
	    "table:access", "key_format=S,value_format=S");
	/*! [access example table create] */

	/*! [access example cursor open] */
	ret = session->open_cursor(session,
	    "table:access", NULL, NULL, &cursor);
	/*! [access example cursor open] */

	/*! [access example cursor insert] */
	cursor->set_key(cursor, "key1");	/* Insert a record. */
	cursor->set_value(cursor, "value1");
	ret = cursor->insert(cursor);
	/*! [access example cursor insert] */

	/*! [access example cursor list] */
	ret = cursor->reset(cursor);	        /* Restart the scan. */
	while ((ret = cursor->next(cursor)) == 0) {
		ret = cursor->get_key(cursor, &key);
		ret = cursor->get_value(cursor, &value);

		printf("Got record: %s : %s\n", key, value);
	}
	/*! [access example cursor list] */

	/*! [access example close] */
	ret = conn->close(conn, NULL);
	/*! [access example close] */

	return (ret);
}
Example #21
0
/*
 * process --
 *	Salvage, verify and dump the created file.
 */
void
process(void)
{
	FILE *fp;
	WT_CONNECTION *conn;
	WT_CURSOR *cursor;
	const char *key, *value;
	WT_SESSION *session;
	char config[100];

	/* Salvage. */
	config[0] = '\0';
	if (verbose)
		snprintf(config, sizeof(config),
		    "error_prefix=\"%s\",verbose=[salvage,verify],",
		    progname);
	strcat(config, "log=(enabled=false),");

	CHECK(wiredtiger_open(NULL, NULL, config, &conn) == 0);
	CHECK(conn->open_session(conn, NULL, NULL, &session) == 0);
	CHECK(session->salvage(session, "file:" SLVG, 0) == 0);
	CHECK(conn->close(conn, 0) == 0);

	/* Verify. */
	CHECK(wiredtiger_open(NULL, NULL, config, &conn) == 0);
	CHECK(conn->open_session(conn, NULL, NULL, &session) == 0);
	CHECK(session->verify(session, "file:" SLVG, 0) == 0);
	CHECK(conn->close(conn, 0) == 0);

	/* Dump. */
	CHECK((fp = fopen(DUMP, "w")) != NULL);
	CHECK(wiredtiger_open(NULL, NULL, config, &conn) == 0);
	CHECK(conn->open_session(conn, NULL, NULL, &session) == 0);
	CHECK(session->open_cursor(
	    session, "file:" SLVG, NULL, "dump=print", &cursor) == 0);
	while (cursor->next(cursor) == 0) {
		if (page_type == WT_PAGE_ROW_LEAF) {
			CHECK(cursor->get_key(cursor, &key) == 0);
			CHECK(fputs(key, fp) >= 0);
			CHECK(fputc('\n', fp) >= 0);
		}
		CHECK(cursor->get_value(cursor, &value) == 0);
		CHECK(fputs(value, fp) >= 0);
		CHECK(fputc('\n', fp) >= 0);
	}
	CHECK(conn->close(conn, 0) == 0);
	CHECK(fclose(fp) == 0);
}
Example #22
0
int
backup(WT_SESSION *session)
{
	char buf[1024];

	/*! [backup]*/
	WT_CURSOR *cursor;
	const char *filename;
	int ret;

	/* Create the backup directory. */
	ret = mkdir("/path/database.backup", 077);

	/* Open the backup data source. */
	ret = session->open_cursor(session, "backup:", NULL, NULL, &cursor);

	/* Copy the list of files. */
	while (
	    (ret = cursor->next(cursor)) == 0 &&
	    (ret = cursor->get_key(cursor, &filename)) == 0) {
		(void)snprintf(buf, sizeof(buf),
		    "cp /path/database/%s /path/database.backup/%s",
		    filename, filename);
		ret = system(buf);
	}
	if (ret == WT_NOTFOUND)
		ret = 0;
	if (ret != 0)
		fprintf(stderr, "%s: cursor next(backup:) failed: %s\n",
		    progname, session->strerror(session, ret));

	ret = cursor->close(cursor);
	/*! [backup]*/

	/*! [incremental backup]*/
	/* Open the backup data source for incremental backup. */
	ret = session->open_cursor(
	    session, "backup:", NULL, "target=(\"log:\")", &cursor);
	/*! [incremental backup]*/
	ret = cursor->close(cursor);

	/*! [backup of a checkpoint]*/
	ret = session->checkpoint(session, "drop=(from=June01),name=June01");
	/*! [backup of a checkpoint]*/

	return (ret);
}
Status WiredTigerRecordStore::truncate(OperationContext* txn) {
    WiredTigerCursor startWrap(_uri, _tableId, true, txn);
    WT_CURSOR* start = startWrap.get();
    int ret = WT_OP_CHECK(start->next(start));
    // Empty collections don't have anything to truncate.
    if (ret == WT_NOTFOUND) {
        return Status::OK();
    }
    invariantWTOK(ret);

    WT_SESSION* session = WiredTigerRecoveryUnit::get(txn)->getSession(txn)->getSession();
    invariantWTOK(WT_OP_CHECK(session->truncate(session, NULL, start, NULL, NULL)));
    _changeNumRecords(txn, -numRecords(txn));
    _increaseDataSize(txn, -dataSize(txn));

    return Status::OK();
}
Example #24
0
/*
 * __truncate_dsrc --
 *	WT_SESSION::truncate for a data-source without a truncate operation.
 */
static int
__truncate_dsrc(WT_SESSION_IMPL *session, const char *uri)
{
	WT_CURSOR *cursor;
	WT_DECL_RET;
	const char *cfg[2];

	/* Open a cursor and traverse the object, removing every entry. */
	cfg[0] = WT_CONFIG_BASE(session, session_open_cursor);
	cfg[1] = NULL;
	WT_RET(__wt_open_cursor(session, uri, NULL, cfg, &cursor));
	while ((ret = cursor->next(cursor)) == 0)
		WT_ERR(cursor->remove(cursor));
	WT_ERR_NOTFOUND_OK(ret);

err:	WT_TRET(cursor->close(cursor));
	return (ret);
}
Example #25
0
static void
take_full_backup(WT_SESSION *session, int i)
{
	WT_CURSOR *cursor;
	int j, ret;
	char buf[1024], h[256];
	const char *filename, *hdir;

	/*
	 * First time through we take a full backup into the incremental
	 * directories.  Otherwise only into the appropriate full directory.
	 */
	if (i != 0) {
		(void)snprintf(h, sizeof(h), "%s.%d", home_full, i);
		hdir = h;
	} else
		hdir = home_incr;
	error_check(
	    session->open_cursor(session, "backup:", NULL, NULL, &cursor));

	while ((ret = cursor->next(cursor)) == 0) {
		error_check(cursor->get_key(cursor, &filename));
		if (i == 0)
			/*
			 * Take a full backup into each incremental directory.
			 */
			for (j = 0; j < MAX_ITERATIONS; j++) {
				(void)snprintf(h, sizeof(h),
				    "%s.%d", home_incr, j);
				(void)snprintf(buf, sizeof(buf),
				    "cp %s/%s %s/%s",
				    home, filename, h, filename);
				error_check(system(buf));
			}
		else {
			(void)snprintf(h, sizeof(h), "%s.%d", home_full, i);
			(void)snprintf(buf, sizeof(buf), "cp %s/%s %s/%s",
			    home, filename, hdir, filename);
			error_check(system(buf));
		}
	}
	scan_end_check(ret == WT_NOTFOUND);
	error_check(cursor->close(cursor));
}
Example #26
0
static void
backup(WT_SESSION *session)
{
	char buf[1024];

	/*! [backup]*/
	WT_CURSOR *cursor;
	const char *filename;
	int ret;

	/* Create the backup directory. */
	error_check(mkdir("/path/database.backup", 077));

	/* Open the backup data source. */
	error_check(session->open_cursor(
	    session, "backup:", NULL, NULL, &cursor));

	/* Copy the list of files. */
	while ((ret = cursor->next(cursor)) == 0) {
		error_check(cursor->get_key(cursor, &filename));
		(void)snprintf(buf, sizeof(buf),
		    "cp /path/database/%s /path/database.backup/%s",
		    filename, filename);
		error_check(system(buf));
	}
	scan_end_check(ret == WT_NOTFOUND);

	error_check(cursor->close(cursor));
	/*! [backup]*/

	/*! [incremental backup]*/
	/* Open the backup data source for incremental backup. */
	error_check(session->open_cursor(
	    session, "backup:", NULL, "target=(\"log:\")", &cursor));
	/*! [incremental backup]*/
	error_check(cursor->close(cursor));

	/*! [backup of a checkpoint]*/
	error_check(session->checkpoint(
	    session, "drop=(from=June01),name=June01"));
	/*! [backup of a checkpoint]*/
}
Example #27
0
/*
 * __metadata_load_bulk --
 *	Create any bulk-loaded file stubs.
 */
static int
__metadata_load_bulk(WT_SESSION_IMPL *session)
{
	WT_CURSOR *cursor;
	WT_DECL_RET;
	uint32_t allocsize;
	bool exist;
	const char *filecfg[] = {
	    WT_CONFIG_BASE(session, file_meta), NULL, NULL };
	const char *key, *value;

	/*
	 * If a file was being bulk-loaded during the hot backup, it will appear
	 * in the metadata file, but the file won't exist.  Create on demand.
	 */
	WT_RET(__wt_metadata_cursor(session, &cursor));
	while ((ret = cursor->next(cursor)) == 0) {
		WT_ERR(cursor->get_key(cursor, &key));
		if (!WT_PREFIX_SKIP(key, "file:"))
			continue;

		/* If the file exists, it's all good. */
		WT_ERR(__wt_fs_exist(session, key, &exist));
		if (exist)
			continue;

		/*
		 * If the file doesn't exist, assume it's a bulk-loaded file;
		 * retrieve the allocation size and re-create the file.
		 */
		WT_ERR(cursor->get_value(cursor, &value));
		filecfg[1] = value;
		WT_ERR(__wt_direct_io_size_check(
		    session, filecfg, "allocation_size", &allocsize));
		WT_ERR(__wt_block_manager_create(session, key, allocsize));
	}
	WT_ERR_NOTFOUND_OK(ret);

err:	WT_TRET(__wt_metadata_cursor_release(session, &cursor));
	return (ret);
}
Example #28
0
/*
 * Read the index by year and print out who was in office that year.
 */
static void
read_index(WT_SESSION *session)
{
	WT_CURSOR *cursor;
	int i, ret;
	char *first_name, *last_name;
	uint16_t rec_year, term_end, term_start, year;

	year = 0;
	srand((unsigned int)getpid());
	error_check(session->open_cursor(
	    session, "index:presidents:term", NULL, NULL, &cursor));

	/*
	 * Pick 10 random years and read the data.
	 */
	for (i = 0; i < 10; i++) {
		year = (uint16_t)((rand() % YEAR_SPAN) + YEAR_BASE);
		printf("Year %" PRIu16 ":\n", year);
		cursor->set_key(cursor, year);
		error_check(cursor->search(cursor));
		error_check(cursor->get_key(cursor, &rec_year));
		error_check(cursor->get_value(cursor,
		    &last_name, &first_name, &term_start, &term_end));

		/* Report all presidents that served during the chosen year */
		ret = 0;
		while (term_start <= year &&
		    year <= term_end && year == rec_year) {
			printf("\t%s %s\n", first_name, last_name);
			if ((ret = cursor->next(cursor)) != 0)
				break;
			error_check(cursor->get_key(cursor, &rec_year));
			error_check(cursor->get_value(cursor,
			    &last_name, &first_name, &term_start, &term_end));
		}
		scan_end_check(ret == 0 || ret == WT_NOTFOUND);
	}

	error_check(cursor->close(cursor));
}
Example #29
0
int main(void)
{
	int ret;
	WT_CONNECTION *conn;
	WT_SESSION *session;
	WT_CURSOR *cursor;
	const char *key, *value;

	/*! [configure cache size] */
	if ((ret = wiredtiger_open(home, NULL,
	    "create,cache_size=500M", &conn)) != 0)
		fprintf(stderr, "Error connecting to %s: %s\n",
		    home, wiredtiger_strerror(ret));
	/*! [configure cache size] */

	/*! [create a table] */
	ret = conn->open_session(conn, NULL, NULL, &session);

	ret = session->create(session,
	    "table:access", "key_format=S,value_format=S");
	/*! [create a table] */

	/*! [transaction] */
	ret = session->begin_transaction(session, "priority=100,name=mytxn");

	ret = session->open_cursor(session, "config:", NULL, NULL, &cursor);

	while ((ret = cursor->next(cursor)) == 0) {
		cursor->get_key(cursor, &key);
		cursor->get_value(cursor, &value);
		printf("configuration value: %s = %s\n", key, value);
	}

	ret = session->commit_transaction(session, NULL);
	/*! [transaction] */

	ret = conn->close(conn, NULL);

	return (ret);
}
Example #30
0
/*! [thread scan] */
void *
scan_thread(void *arg)
{
	WT_SESSION *session;
	WT_CURSOR *cursor;
	const char *key, *value;
	int ret;

	ret = conn->open_session(conn, NULL, NULL, &session);
	ret = session->open_cursor(session, "table:access",
	    NULL, NULL, &cursor);

	/* Show all records. */
	while ((ret = cursor->next(cursor)) == 0) {
		ret = cursor->get_key(cursor, &key);
		ret = cursor->get_value(cursor, &value);

		printf("Got record: %s : %s\n", key, value);
	}

	return (arg);
}