WiredTigerSession* WiredTigerRecoveryUnit::getSession() { if (!_isActive()) { _txnOpen(); _setState(_inUnitOfWork() ? State::kActive : State::kActiveNotInUnitOfWork); } return _session.get(); }
void WiredTigerRecoveryUnit::_abort() { try { bool notifyDone = !_prepareTimestamp.isNull(); if (_session && _isActive()) { _txnClose(false); } _setState(State::kAborting); if (MONGO_FAIL_POINT(WTAlwaysNotifyPrepareConflictWaiters)) { notifyDone = true; } if (notifyDone) { _sessionCache->notifyPreparedUnitOfWorkHasCommittedOrAborted(); } for (Changes::const_reverse_iterator it = _changes.rbegin(), end = _changes.rend(); it != end; ++it) { Change* change = it->get(); LOG(2) << "CUSTOM ROLLBACK " << redact(demangleName(typeid(*change))); change->rollback(); } _changes.clear(); } catch (...) { std::terminate(); } _setState(State::kInactive); }
void WiredTigerRecoveryUnit::assertInActiveTxn() const { if (_isActive()) { return; } severe() << "Recovery unit is not active. Current state: " << toString(_state); fassertFailed(28575); }
void WiredTigerRecoveryUnit::_commit() { // Since we cannot have both a _lastTimestampSet and a _commitTimestamp, we set the // commit time as whichever is non-empty. If both are empty, then _lastTimestampSet will // be boost::none and we'll set the commit time to that. auto commitTime = _commitTimestamp.isNull() ? _lastTimestampSet : _commitTimestamp; try { bool notifyDone = !_prepareTimestamp.isNull(); if (_session && _isActive()) { _txnClose(true); } _setState(State::kCommitting); if (MONGO_FAIL_POINT(WTAlwaysNotifyPrepareConflictWaiters)) { notifyDone = true; } if (notifyDone) { _sessionCache->notifyPreparedUnitOfWorkHasCommittedOrAborted(); } for (Changes::const_iterator it = _changes.begin(), end = _changes.end(); it != end; ++it) { (*it)->commit(commitTime); } _changes.clear(); } catch (...) { std::terminate(); } _setState(State::kInactive); }
void WiredTigerRecoveryUnit::abandonSnapshot() { invariant(!_inUnitOfWork(), toString(_state)); if (_isActive()) { // Can't be in a WriteUnitOfWork, so safe to rollback _txnClose(false); } _setState(State::kInactive); }
void WiredTigerRecoveryUnit::beginUnitOfWork(OperationContext* opCtx) { invariant(!_inUnitOfWork(), toString(_state)); invariant(!_isCommittingOrAborting(), str::stream() << "cannot begin unit of work while commit or rollback handlers are " "running: " << toString(_state)); _setState(_isActive() ? State::kActive : State::kInactiveInUnitOfWork); }
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. }
void WiredTigerRecoveryUnit::setTimestampReadSource(ReadSource readSource, boost::optional<Timestamp> provided) { LOG(3) << "setting timestamp read source: " << static_cast<int>(readSource) << ", provided timestamp: " << ((provided) ? provided->toString() : "none"); invariant(!_isActive() || _timestampReadSource == readSource, str::stream() << "Current state: " << toString(_state) << ". Invalid internal state while setting timestamp read source: " << static_cast<int>(readSource) << ", provided timestamp: " << (provided ? provided->toString() : "none")); invariant(!provided == (readSource != ReadSource::kProvided)); invariant(!(provided && provided->isNull())); _timestampReadSource = readSource; _readAtTimestamp = (provided) ? *provided : Timestamp(); }
void GUIElementBase::_registerChildElement(GUIElementBase* element) { assert(!element->_isDestroyed()); GUIElementBase* parentElement = element->_getParent(); if(parentElement != nullptr) { parentElement->_unregisterChildElement(element); } element->_setParent(this); mChildren.push_back(element); element->_setActive(_isActive()); element->_setVisible(_isVisible()); element->_setDisabled(_isDisabled()); _markLayoutAsDirty(); }
void GUILayout::insertElement(UINT32 idx, GUIElementBase* element) { if(idx > (UINT32)mChildren.size()) BS_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx) + ". Valid range: 0 .. " + toString((UINT32)mChildren.size())); if (element->_isDestroyed()) return; GUIElementBase* parentElement = element->_getParent(); if(parentElement != nullptr) { parentElement->_unregisterChildElement(element); } element->_setParent(this); mChildren.insert(mChildren.begin() + idx, element); element->_setActive(_isActive()); element->_setVisible(_isVisible()); element->_setDisabled(_isDisabled()); _markLayoutAsDirty(); }
void GUIElementBase::setVisible(bool visible) { // No visibility states matter if object is not active if (!_isActive()) return; bool visibleSelf = (mFlags & GUIElem_HiddenSelf) == 0; if (visibleSelf != visible) { // If making an element visible make sure to mark layout as dirty, as we didn't track any dirty flags while the element was inactive if (!visible) { mFlags |= GUIElem_HiddenSelf; _setVisible(false); } else { mFlags &= ~GUIElem_HiddenSelf; if (mParentElement == nullptr || mParentElement->_isVisible()) _setVisible(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; }