In looking at how to solve DERBY-2380 I've been looking closely at the
DependencyManager. It handles the rollback of a statement or transaction
in two different and not obviously related ways. One is to add
dependency information into the statement context and have the statement
context remove them from the dependency manager on statement (and
transaction) rollback. Then a different mechanism is used for a
transaction rollback in some situations where a invalidate "message" is
sent with action rollback.
Then I happened to notice that the new LOB locator (?) work has added a
call to clearLOBMapping() call to every commit() and rollback() in
EmbedConnection.
Then GenericLanguageConnection also has a collection of work it performs
in its doRollback() and doCommit() methods, such as dropping temp tables
etc.
This all seems somewhat haphazard and prone to bugs, for example most of
the rollback actions in the LCC are prior to the store commit, but the
clearLOBMapping() is after the store commit. Other possibilities are the
cleanup only been added to rollback and not commit, or vice versa, or
even not being added for XA transactions, which may be the case for
clearLOBMapping.
This approach also imposes a performance penalty on all transactions,
even if they do no LOB or temp table work for example. And that
performance will degrade over time as more actions are added.
I was wondering if a callback system might be better. The LCC would
provide an api where objects could be added and have methods called on
rollback, commit or statement rollback. This then would make the
commit/rollback methods very clean, and ensure that the object was
notified in all situations, rather than relying on the coder to add in
all the various locations. Performance should be better as if there are
no LOBs or temp tables (or whatever) then the list would be empty rather
than having to explicit check that each type (LOBs, temp tables, log
statement text, DDL transaction) has no cleanup action to perform.
The object that would be added to the callback list would implement some
interface, maybe something like:
interface CommitAction
{
// called when a transaction is about to be rolled back
// (before the store executes it physical rollback)
void preRollback() throws StandardException;
// called when a transaction is about to be committed
// (before the store executes it commit (force of log records))
void preCommit() throws StandardException;
// to support statement/savepoint rollback.
void preSavepointRollback() throws StandardException;
}
That's to give a general idea, it probably would go through several
iterations, e.g. return boolean to indicate if remove from list?
Also the behaviour of this callback scheme should be carefully defined
up front, e.g. is order guaranteed, what happens if an exception is
thrown by a preCommit(), which methods are called & when, when is the
object removed, etc.
This could be added incrementally, the framework first and the callback
logic and then retrofitting the various end transaction actions that
exist today to use the callback mechanism.
Thoughts, comments?
Dan.
PS. not sure if it will help me with DEBRY-2380, but it would clean up
the dependency manager, which would be a help.