Timestamp WiredTigerSnapshotManager::beginTransactionOnLocalSnapshot( WT_SESSION* session, IgnorePrepared ignorePrepared, RoundUpPreparedTimestamps roundUpPreparedTimestamps) const { WiredTigerBeginTxnBlock txnOpen(session, ignorePrepared, roundUpPreparedTimestamps); stdx::lock_guard<stdx::mutex> lock(_localSnapshotMutex); invariant(_localSnapshot); LOG(3) << "begin_transaction on local snapshot " << _localSnapshot.get().toString(); auto status = txnOpen.setReadSnapshot(_localSnapshot.get()); fassert(50775, status); txnOpen.done(); return *_localSnapshot; }
Timestamp WiredTigerSnapshotManager::beginTransactionOnCommittedSnapshot( WT_SESSION* session, IgnorePrepared ignorePrepared, RoundUpPreparedTimestamps roundUpPreparedTimestamps) const { WiredTigerBeginTxnBlock txnOpen(session, ignorePrepared, roundUpPreparedTimestamps); stdx::lock_guard<stdx::mutex> lock(_committedSnapshotMutex); uassert(ErrorCodes::ReadConcernMajorityNotAvailableYet, "Committed view disappeared while running operation", _committedSnapshot); auto status = txnOpen.setReadSnapshot(_committedSnapshot.get()); fassert(30635, status); txnOpen.done(); return *_committedSnapshot; }
Timestamp WiredTigerRecoveryUnit::_beginTransactionAtAllCommittedTimestamp(WT_SESSION* session) { WiredTigerBeginTxnBlock txnOpen(session, _ignorePrepared); Timestamp txnTimestamp = Timestamp(_oplogManager->fetchAllCommittedValue(session->connection)); auto status = txnOpen.setTimestamp(txnTimestamp, WiredTigerBeginTxnBlock::RoundToOldest::kRound); fassert(50948, status); // Since this is not in a critical section, we might have rounded to oldest between // calling getAllCommitted and setTimestamp. We need to get the actual read timestamp we // used. char buf[(2 * 8 /*bytes in hex*/) + 1 /*nul terminator*/]; auto wtstatus = session->query_timestamp(session, buf, "get=read"); invariantWTOK(wtstatus); uint64_t read_timestamp; fassert(50949, parseNumberFromStringWithBase(buf, 16, &read_timestamp)); txnOpen.done(); return Timestamp(read_timestamp); }
void WiredTigerRecoveryUnit::_txnOpen() { invariant(!_isActive(), toString(_state)); invariant(!_isCommittingOrAborting(), str::stream() << "commit or rollback handler reopened transaction: " << toString(_state)); _ensureSession(); // Only start a timer for transaction's lifetime if we're going to log it. if (shouldLog(kSlowTransactionSeverity)) { _timer.reset(new Timer()); } WT_SESSION* session = _session->getSession(); switch (_timestampReadSource) { case ReadSource::kUnset: case ReadSource::kNoTimestamp: { WiredTigerBeginTxnBlock txnOpen(session, _ignorePrepared); if (_isOplogReader) { auto status = txnOpen.setTimestamp(Timestamp(_oplogManager->getOplogReadTimestamp()), WiredTigerBeginTxnBlock::RoundToOldest::kRound); fassert(50771, status); } txnOpen.done(); break; } case ReadSource::kMajorityCommitted: { // We reset _majorityCommittedSnapshot to the actual read timestamp used when the // transaction was started. _majorityCommittedSnapshot = _sessionCache->snapshotManager().beginTransactionOnCommittedSnapshot( session, _ignorePrepared); break; } case ReadSource::kLastApplied: { if (_sessionCache->snapshotManager().getLocalSnapshot()) { _readAtTimestamp = _sessionCache->snapshotManager().beginTransactionOnLocalSnapshot( session, _ignorePrepared); } else { WiredTigerBeginTxnBlock(session, _ignorePrepared).done(); } break; } case ReadSource::kAllCommittedSnapshot: { if (_readAtTimestamp.isNull()) { _readAtTimestamp = _beginTransactionAtAllCommittedTimestamp(session); break; } // Intentionally continue to the next case to read at the _readAtTimestamp. } case ReadSource::kLastAppliedSnapshot: { // Only ever read the last applied timestamp once, and continue reusing it for // subsequent transactions. if (_readAtTimestamp.isNull()) { _readAtTimestamp = _sessionCache->snapshotManager().beginTransactionOnLocalSnapshot( session, _ignorePrepared); break; } // Intentionally continue to the next case to read at the _readAtTimestamp. } case ReadSource::kProvided: { WiredTigerBeginTxnBlock txnOpen(session, _ignorePrepared); auto status = txnOpen.setTimestamp(_readAtTimestamp); if (!status.isOK() && status.code() == ErrorCodes::BadValue) { uasserted(ErrorCodes::SnapshotTooOld, str::stream() << "Read timestamp " << _readAtTimestamp.toString() << " is older than the oldest available timestamp."); } uassertStatusOK(status); txnOpen.done(); break; } } LOG(3) << "WT begin_transaction for snapshot id " << _mySnapshotId; }