public class SavepointManager extends java.lang.Object implements Commitable, Finalizable, DmoState
An instance of this class is created when an application block with a full transaction
property is executed. If and when an associated database transaction is created, the SavepointManager instance is installed in the active database session. The instantiation of
this class and the creation of a database transaction do not necessarily have to occur
simultaneously. In fact, a database transaction may not be created at all. A database-level
transaction is only begun the first time a record buffer for the associated database is used
(i.e., its scope is opened). This lazy creation of a database transaction is intended to
prevent the overhead of creating unused database transactions every time an application-level
transaction is opened.
When created at an application full transaction, this object is registered for Commitable and Finalizable callbacks. It must again be registered for these callbacks at each sub-transaction
block encountered. The registration for these callbacks is the responsibility of the BufferManager. It is also the BufferManager
which determines when a database transaction needs to be opened.
When a database transaction is opened and the savepoint manager installed in the session, the
latter needs to be activated with a call to setSession(Session). Once activated, this
object will track any changes made to DMOs, lazily creating savepoints as necessary when a change
is made. It will track application persistence state which needs to be kept in sync with database
create, update, and delete activity. The lazy creation of savepoints only when a change has been
made prevents round trips to the database to set and release savepoints, if there is no database
activity to be rolled back in a given subtransaction block.
Undoable and NO-UNDO operations are treated differently. For the former, this class ensures that the state of in-memory records is left in the state they were in at the time a rolled-back block was entered, while rolling back a corresponding savepoint in the database. For the latter, this class ensures that any rollback of NO-UNDO changes at the database is negated, by re-applying any SQL operations which were rolled back at the database, after the sub-transaction or full transaction completes.
| Modifier and Type | Class and Description |
|---|---|
private static class |
SavepointManager.Block
Block state corresponding with full and sub-transactions, for the purpose of tracking updated records
and their states.
|
static interface |
SavepointManager.PersistenceCode
Allows to execute a piece of code which may throw a
PersistenceException by a foreign object. |
| Modifier and Type | Field and Description |
|---|---|
private SavepointManager.Block |
activeBlock
State of the transaction block which currently is active, if any
|
private java.util.Deque<SavepointManager.Block> |
blocks
Stack of block states which coincide with transaction block scopes
|
private static boolean |
debug
Debug logging level
|
private static CentralLogger |
log
Logger
|
private SavepointManager.Block |
parentBlock
The current parent block, if any (will be
null at a full transaction block) |
private Session |
session
Database session used for savepoint processing
|
| Constructor and Description |
|---|
SavepointManager()
Default constructor.
|
| Modifier and Type | Method and Description |
|---|---|
private void |
cleanupBlock()
End of block processing, which entails discarding the currently active block, re-applying any rolled
back changes to a NO-UNDO temporary table, and reactivating the parent block, if any, for further
processing.
|
void |
commit(boolean transaction)
Commit the active block, which entails releasing any savepoint and rolling up tracked
resources.
|
private void |
debug(java.lang.String message)
Log a debug message if FINE logging is enabled for this class.
|
void |
deleted()
No-op delete hook.
|
void |
deregisterGlobalBlockHooks(TransactionManager.TransactionHelper txHelper)
Deregister the current instance from the transaction manager.
|
void |
finished()
The block has finished.
|
(package private) int |
getTxNestingLevel()
Get the zero-based transaction block nesting level, where 0 indicates the current block is a full
transaction block, 1 indicates the current block is the first level of nested subtransaction, and so
on.
|
void |
iterate()
Prepare to iterate through another pass of a looping block.
|
(package private) SavepointManager.PersistenceCode |
lazilySetSavepoints(boolean exceptLast)
Set a savepoint in the active block and in every previous block which has not yet had one set,
except for the outermost (which represents the full transaction block).
|
private void |
prepareBlock()
Prepare a new block and make it the active block.
|
void |
registerBlockHooks(TransactionManager.TransactionHelper txHelper,
boolean fullTx,
int blockDepth)
Register for transaction manager notifications for the current block.
|
void |
retry()
Retry a block after handling a condition.
|
void |
rollback(boolean transaction)
Roll back the active block, which entails rolling back any savepoint, rolling up tracked
resources, and marking any tracked undoable records as stale.
|
private void |
setSavepoint(SavepointManager.Block block)
Set a new savepoint in the database and associate it with the given block.
|
(package private) void |
setSession(Session session)
Install the given session into this savepoint manager.
|
(package private) void |
trackUndoable(BaseRecord dmo)
Begin tracking an undoable record as needing savepoint processing.
|
void |
validate(boolean transaction,
boolean aggressiveFlush)
No-op validation hook.
|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitentry, initFailure, weightprivate static final CentralLogger log
private static final boolean debug
private final java.util.Deque<SavepointManager.Block> blocks
private Session session
private SavepointManager.Block activeBlock
private SavepointManager.Block parentBlock
null at a full transaction block)public void registerBlockHooks(TransactionManager.TransactionHelper txHelper, boolean fullTx, int blockDepth)
We register for Finalizable and Commitable notifications.
txHelper - Transaction manager helper object with which we register for notifications.fullTx - true if this is a full-transaction.blockDepth - zero-based depth of target block, starting from the outermost block. 0 indicates
the global block.public void deregisterGlobalBlockHooks(TransactionManager.TransactionHelper txHelper)
TxWrapper instance that created the current instance is cleaned up and the transaction
is initiated by TRANSACTION-MODE AUTO, the Finalizable is removed from the global block.txHelper - Transaction manager helper object with which we register for notifications.public void finished()
finished in interface Finalizablepublic void deleted()
deleted in interface Finalizablepublic void iterate()
iterate in interface Finalizablepublic void retry()
retry in interface Finalizablepublic void validate(boolean transaction,
boolean aggressiveFlush)
validate in interface Commitabletransaction - Not used.aggressiveFlush - Not used.public void commit(boolean transaction)
commit in interface Commitabletransaction - true if the current block is a full transaction; false if it is
a sub-transaction.public void rollback(boolean transaction)
rollback in interface Commitabletransaction - true if the current block is a full transaction; false if it is
a sub-transaction.void setSession(Session session)
session - Database session used for savepoint processing.int getTxNestingLevel()
void trackUndoable(BaseRecord dmo) throws PersistenceException
A record is tracked when a change (create/update/delete) has been made to it and that change has been persisted to the database.
dmo - Record to be tracked.PersistenceException - if there is an error lazily setting savepoints in the active block and any ancestor
blocks which do not yet have savepoints assigned.SavepointManager.PersistenceCode lazilySetSavepoints(boolean exceptLast) throws PersistenceException
We do this lazily, when an actual change is made, rather than as each block is created. This avoids setting "empty" savepoints which never contain updates, thereby preventing many unnecessary round trips to the database.
exceptLast - If true, do not set up the very last block, instead return a lambda code which is
prepared to do that. This allows a complete intermediary, short-leved sub-transaction to be
executed before the savepoint for this blolck to be set up.PersistenceCode implementation which will set up the last block with a savepoint.PersistenceExceptionprivate void prepareBlock()
private void cleanupBlock()
private void setSavepoint(SavepointManager.Block block) throws PersistenceException
block - Block with which the savepoint is associated.PersistenceException - if there is a database error setting the savepoint.private void debug(java.lang.String message)
message - Message text.