WiredTigerSession* WiredTigerRecoveryUnit::getSession(OperationContext* opCtx) { _ensureSession(); if (!_active) { _txnOpen(opCtx); } return _session; }
WiredTigerSession* WiredTigerRecoveryUnit::getSessionNoTxn() { _ensureSession(); WiredTigerSession* session = _session.get(); // Handling queued drops can be slow, which is not desired for internal operations like FTDC // sampling. Disable handling of queued drops for such sessions. session->dropQueuedIdentsAtSessionEndAllowed(false); return session; }
void WiredTigerRecoveryUnit::_txnOpen(OperationContext* opCtx) { invariant(!_active); _ensureSession(); WT_SESSION* s = _session->getSession(); if (_readFromMajorityCommittedSnapshot) { _majorityCommittedSnapshot = _sessionCache->snapshotManager().beginTransactionOnCommittedSnapshot(s); } else { invariantWTOK(s->begin_transaction(s, NULL)); } LOG(3) << "WT begin_transaction for snapshot id " << _mySnapshotId; _timer.reset(); _active = true; }
void WiredTigerRecoveryUnit::_txnOpen(OperationContext* opCtx) { invariant(!_active); _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* s = _session->getSession(); if (_readFromMajorityCommittedSnapshot) { _majorityCommittedSnapshot = _sessionCache->snapshotManager().beginTransactionOnCommittedSnapshot(s); } else { invariantWTOK(s->begin_transaction(s, NULL)); } LOG(3) << "WT begin_transaction for snapshot id " << _mySnapshotId; _active = true; }
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"); }
void MobileRecoveryUnit::_txnOpen(OperationContext* opCtx, bool readOnly) { invariant(!_active); RECOVERY_UNIT_TRACE() << " _txnOpen called with readOnly:" << (readOnly ? "TRUE" : "FALSE"); _ensureSession(opCtx); /* * Starting a transaction with the "BEGIN" statement doesn't take an immediate lock. * SQLite defers taking any locks until the database is first accessed. This creates the * possibility of having multiple transactions opened in parallel. All sessions except the * first to request the access get a database locked error. * However, "BEGIN IMMEDIATE" forces SQLite to take a lock immediately. If another session * tries to create a transaction in parallel, it receives a busy error and then retries. * Reads outside these explicit transactions proceed unaffected. */ // Check for correct locking at higher levels if (readOnly) { // Confirm that this reader has taken a shared lock if (!opCtx->lockState()->isLockHeldForMode( ResourceId(RESOURCE_GLOBAL, ResourceId::SINGLETON_GLOBAL), MODE_S)) { opCtx->lockState()->dump(); invariant(!"Reading without a shared lock"); } SqliteStatement::execQuery(_session.get(), "BEGIN"); } else { // Single writer allowed at a time, confirm a global write lock has been taken if (!opCtx->lockState()->isLockHeldForMode( ResourceId(RESOURCE_GLOBAL, ResourceId::SINGLETON_GLOBAL), MODE_X)) { opCtx->lockState()->dump(); invariant(!"Writing without an exclusive lock"); } SqliteStatement::execQuery(_session.get(), "BEGIN EXCLUSIVE"); } _isReadOnly = readOnly; _active = true; }
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; }
WiredTigerSession* WiredTigerRecoveryUnit::getSessionNoTxn(OperationContext* opCtx) { _ensureSession(); return _session.get(); }
MobileSession* MobileRecoveryUnit::getSessionNoTxn(OperationContext* opCtx) { _ensureSession(opCtx); return _session.get(); }
bool WiredTigerRecoveryUnit::waitUntilDurable() { _ensureSession(); _sessionCache->waitUntilDurable(_session); return true; }