void CmdInterpreter::visit(ProxyCmdRollback &cmd) { TxnHandle *pTxnHandle = getTxnHandle(cmd.getTxnHandle()); SharedDatabase pDb = pTxnHandle->pDb; // block checkpoints during this method bool txnBlocksCheckpoint = !pTxnHandle->readOnly && pDb->shouldForceTxns(); SXMutexSharedGuard actionMutexGuard( pDb->getCheckpointThread()->getActionMutex()); if (pDb->areSnapshotsEnabled()) { SnapshotRandomAllocationSegment *pSegment = SegmentFactory::dynamicCast<SnapshotRandomAllocationSegment *>( pTxnHandle->pSnapshotSegment); pSegment->rollbackChanges(); } if (cmd.getSvptHandle()) { SavepointId svptId = getSavepointId(cmd.getSvptHandle()); pTxnHandle->pTxn->rollback(&svptId); } else { pTxnHandle->pTxn->rollback(); deleteAndNullify(pTxnHandle); if (txnBlocksCheckpoint && !pDb->areSnapshotsEnabled()) { // Implement rollback by simulating crash recovery, // reverting all pages modified by transaction. No need // to do this when snapshots are in use because no permanent // pages were modified. pDb->recoverOnline(); } } }
void CmdInterpreter::visit(ProxyCmdCommit &cmd) { TxnHandle *pTxnHandle = getTxnHandle(cmd.getTxnHandle()); SharedDatabase pDb = pTxnHandle->pDb; // block checkpoints during this method bool txnBlocksCheckpoint = !pTxnHandle->readOnly && pDb->shouldForceTxns(); SXMutexSharedGuard actionMutexGuard( pDb->getCheckpointThread()->getActionMutex()); if (pDb->areSnapshotsEnabled()) { // Commit the current txn, and start a new one so the versioned // pages that we're now going to commit will be marked with a txnId // corresponding to the time of the commit. At present, those pages // are marked with a txnId corresponding to the start of the txn. pTxnHandle->pTxn->commit(); pTxnHandle->pTxn = pDb->getTxnLog()->newLogicalTxn(pDb->getCache()); SnapshotRandomAllocationSegment *pSnapshotSegment = SegmentFactory::dynamicCast<SnapshotRandomAllocationSegment *>( pTxnHandle->pSnapshotSegment); TxnId commitTxnId = pTxnHandle->pTxn->getTxnId(); pSnapshotSegment->commitChanges(commitTxnId); // Flush pages associated with the snapshot segment. Note that we // don't need to flush the underlying versioned segment first since // the snapshot pages are all new and therefore, are never logged. // Pages in the underlying versioned segment will be flushed in the // requestCheckpoint call further below. Also note that the // checkpoint is not initiated through the dynamically cast segment // to ensure that the command is traced if tracing is turned on. if (txnBlocksCheckpoint) { pTxnHandle->pSnapshotSegment->checkpoint(CHECKPOINT_FLUSH_ALL); } } if (cmd.getSvptHandle()) { SavepointId svptId = getSavepointId(cmd.getSvptHandle()); pTxnHandle->pTxn->commitSavepoint(svptId); } else { pTxnHandle->pTxn->commit(); deleteAndNullify(pTxnHandle); if (txnBlocksCheckpoint) { // release the checkpoint lock acquired above actionMutexGuard.unlock(); // force a checkpoint now to flush all data modified by transaction // to disk; wait for it to complete before reporting the // transaction as committed pDb->requestCheckpoint(CHECKPOINT_FLUSH_ALL, false); } } }