void WiredTigerRecoveryUnit::_txnClose(bool commit) {
    invariant(_isActive(), toString(_state));
    WT_SESSION* s = _session->getSession();
    if (_timer) {
        const int transactionTime = _timer->millis();
        // `serverGlobalParams.slowMs` can be set to values <= 0. In those cases, give logging a
        // break.
        if (transactionTime >= std::max(1, serverGlobalParams.slowMS)) {
            LOG(kSlowTransactionSeverity) << "Slow WT transaction. Lifetime of SnapshotId "
                                          << _mySnapshotId << " was " << transactionTime << "ms";
        }
    }

    int wtRet;
    if (commit) {
        if (!_commitTimestamp.isNull()) {
            const std::string conf = "commit_timestamp=" + integerToHex(_commitTimestamp.asULL());
            invariantWTOK(s->timestamp_transaction(s, conf.c_str()));
            _isTimestamped = true;
        }

        wtRet = s->commit_transaction(s, nullptr);
        LOG(3) << "WT commit_transaction for snapshot id " << _mySnapshotId;
    } else {
        wtRet = s->rollback_transaction(s, nullptr);
        invariant(!wtRet);
        LOG(3) << "WT rollback_transaction for snapshot id " << _mySnapshotId;
    }

    if (_isTimestamped) {
        if (!_orderedCommit) {
            // We only need to update oplog visibility where commits can be out-of-order with
            // respect to their assigned optime and such commits might otherwise be visible.
            // This should happen only on primary nodes.
            _oplogManager->triggerJournalFlush();
        }
        _isTimestamped = false;
    }
    invariantWTOK(wtRet);

    invariant(!_lastTimestampSet || _commitTimestamp.isNull(),
              str::stream() << "Cannot have both a _lastTimestampSet and a "
                               "_commitTimestamp. _lastTimestampSet: "
                            << _lastTimestampSet->toString()
                            << ". _commitTimestamp: "
                            << _commitTimestamp.toString());

    // We reset the _lastTimestampSet between transactions. Since it is legal for one
    // transaction on a RecoveryUnit to call setTimestamp() and another to call
    // setCommitTimestamp().
    _lastTimestampSet = boost::none;

    _prepareTimestamp = Timestamp();
    _mySnapshotId = nextSnapshotId.fetchAndAdd(1);
    _isOplogReader = false;
    _orderedCommit = true;  // Default value is true; we assume all writes are ordered.
}
Status WiredTigerRecoveryUnit::setTimestamp(Timestamp timestamp) {
    _ensureSession();
    LOG(3) << "WT set timestamp of future write operations to " << timestamp;
    WT_SESSION* session = _session->getSession();
    invariant(_inUnitOfWork(), toString(_state));
    invariant(_prepareTimestamp.isNull());
    invariant(_commitTimestamp.isNull(),
              str::stream() << "Commit timestamp set to " << _commitTimestamp.toString()
                            << " and trying to set WUOW timestamp to "
                            << timestamp.toString());

    _lastTimestampSet = timestamp;

    // Starts the WT transaction associated with this session.
    getSession();

    const std::string conf = "commit_timestamp=" + integerToHex(timestamp.asULL());
    auto rc = session->timestamp_transaction(session, conf.c_str());
    if (rc == 0) {
        _isTimestamped = true;
    }
    return wtRCToStatus(rc, "timestamp_transaction");
}
示例#3
0
文件: ex_all.c 项目: ajdavis/mongo
static void
transaction_ops(WT_SESSION *session_arg)
{
	WT_CONNECTION *conn;
	WT_CURSOR *cursor;
	WT_SESSION *session;

	session = session_arg;
	conn = session->connection;

	/*! [transaction commit/rollback] */
	/*
	 * Cursors may be opened before or after the transaction begins, and in
	 * either case, subsequent operations are included in the transaction.
	 * Opening cursors before the transaction begins allows applications to
	 * cache cursors and use them for multiple operations.
	 */
	error_check(session->open_cursor(
	    session, "table:mytable", NULL, NULL, &cursor));
	error_check(session->begin_transaction(session, NULL));

	cursor->set_key(cursor, "key");
	cursor->set_value(cursor, "value");
	switch (cursor->update(cursor)) {
	case 0:					/* Update success */
		error_check(session->commit_transaction(session, NULL));
		/*
		 * If commit_transaction succeeds, cursors remain positioned; if
		 * commit_transaction fails, the transaction was rolled-back and
		 * and all cursors are reset.
		 */
		break;
	case WT_ROLLBACK:			/* Update conflict */
	default:				/* Other error */
		error_check(session->rollback_transaction(session, NULL));
		/* The rollback_transaction call resets all cursors. */
		break;
	}

	/*
	 * Cursors remain open and may be used for multiple transactions.
	 */
	/*! [transaction commit/rollback] */
	error_check(cursor->close(cursor));

	/*! [transaction isolation] */
	/* A single transaction configured for snapshot isolation. */
	error_check(session->open_cursor(
	    session, "table:mytable", NULL, NULL, &cursor));
	error_check(session->begin_transaction(session, "isolation=snapshot"));
	cursor->set_key(cursor, "some-key");
	cursor->set_value(cursor, "some-value");
	error_check(cursor->update(cursor));
	error_check(session->commit_transaction(session, NULL));
	/*! [transaction isolation] */

	{
	/*! [transaction prepare] */
	/*
	 * Prepare a transaction which guarantees a subsequent commit will
	 * succeed. Only commit and rollback are allowed on a transaction after
	 * it has been prepared.
	 */
	error_check(session->open_cursor(
	    session, "table:mytable", NULL, NULL, &cursor));
	error_check(session->begin_transaction(session, NULL));
	cursor->set_key(cursor, "key");
	cursor->set_value(cursor, "value");
	error_check(session->prepare_transaction(
	    session, "prepare_timestamp=2a"));
	error_check(session->commit_transaction(
	    session, "commit_timestamp=2b"));
	/*! [transaction prepare] */
	}

	/*! [session isolation configuration] */
	/* Open a session configured for read-uncommitted isolation. */
	error_check(conn->open_session(
	    conn, NULL, "isolation=read-uncommitted", &session));
	/*! [session isolation configuration] */

	/*! [session isolation re-configuration] */
	/* Re-configure a session for snapshot isolation. */
	error_check(session->reconfigure(session, "isolation=snapshot"));
	/*! [session isolation re-configuration] */

	error_check(session->close(session, NULL));
	session = session_arg;

	{
	/*! [transaction pinned range] */
	/* Check the transaction ID range pinned by the session handle. */
	uint64_t range;

	error_check(session->transaction_pinned_range(session, &range));
	/*! [transaction pinned range] */
	}

	error_check(session->begin_transaction(session, NULL));

	{
	/*! [query timestamp] */
	char timestamp_buf[2 * sizeof(uint64_t) + 1];

	/*! [transaction timestamp] */
	error_check(
	    session->timestamp_transaction(session, "commit_timestamp=2a"));
	/*! [transaction timestamp] */

	error_check(session->commit_transaction(session, NULL));

	error_check(conn->query_timestamp(
	    conn, timestamp_buf, "get=all_committed"));
	/*! [query timestamp] */
	}

	/*! [set commit timestamp] */
	error_check(conn->set_timestamp(conn, "commit_timestamp=2a"));
	/*! [set commit timestamp] */

	/*! [set oldest timestamp] */
	error_check(conn->set_timestamp(conn, "oldest_timestamp=2a"));
	/*! [set oldest timestamp] */

	/*! [set stable timestamp] */
	error_check(conn->set_timestamp(conn, "stable_timestamp=2a"));
	/*! [set stable timestamp] */

	/*! [rollback to stable] */
	error_check(conn->rollback_to_stable(conn, NULL));
	/*! [rollback to stable] */
}