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.

Reply via email to