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.
|
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 SavepointManager.Block |
lastActiveBlock
The most recently active block, before the currently active block
|
private static java.util.logging.Logger |
log
Logger
|
private SavepointManager.Block |
parentBlock
The current parent block, if any (will be
null at a full transaction block) |
private java.util.List<SQLRedo> |
redoable
The list of redoable insert, update, and delete SQL operations for NO-UNDO temp-tables
|
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 |
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) void |
lazilySetSavepoints()
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).
|
(package private) void |
noUndoBulkUpdate(SQLQuery query)
Create a redoable SQL operation for the bulk update of zero or more NO-UNDO records in
the database.
|
(package private) void |
noUndoDelete(java.lang.Class<? extends BaseRecord> dmoClass,
java.lang.Long id)
Create a redoable SQL operation for the deletion of a NO-UNDO record from the database.
|
(package private) void |
noUndoInsert(BaseRecord dmo)
Create a redoable SQL operation for the insertion of a NO-UNDO record into the database.
|
(package private) void |
noUndoUpdate(BaseRecord dmo)
Create a redoable SQL operation for the update of a NO-UNDO record in the database.
|
private void |
prepareBlock()
Prepare a new block and make it the active block.
|
void |
registerBlockHooks(TransactionManager.TransactionHelper txHelper,
boolean fullTx)
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 and any redoable operations
as active.
|
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, wait
entry, initFailure, weight
private static final java.util.logging.Logger log
private static final boolean debug
private final java.util.Deque<SavepointManager.Block> blocks
private final java.util.List<SQLRedo> redoable
private Session session
private SavepointManager.Block activeBlock
private SavepointManager.Block parentBlock
null
at a full transaction block)private SavepointManager.Block lastActiveBlock
public void registerBlockHooks(TransactionManager.TransactionHelper txHelper, boolean fullTx)
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.public void finished()
finished
in interface Finalizable
public void deleted()
deleted
in interface Finalizable
public void iterate()
iterate
in interface Finalizable
public void retry()
retry
in interface Finalizable
public void validate(boolean transaction, boolean aggressiveFlush)
validate
in interface Commitable
transaction
- Not used.aggressiveFlush
- Not used.public void commit(boolean transaction)
commit
in interface Commitable
transaction
- true
if the current block is a full transaction; false
if it is
a sub-transaction.public void rollback(boolean transaction)
rollback
in interface Commitable
transaction
- 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.void noUndoInsert(BaseRecord dmo)
dmo
- DMO which was updated.void noUndoUpdate(BaseRecord dmo)
dmo
- DMO which was updated.void noUndoDelete(java.lang.Class<? extends BaseRecord> dmoClass, java.lang.Long id)
dmoClass
- Implementation class of the DMO which was deleted.id
- Primary key of the record which was deleted.void noUndoBulkUpdate(SQLQuery query)
query
- SQL query which performed the original bulk operation.void lazilySetSavepoints() 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.
PersistenceException
private 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.