Subject | Re: [Firebird-Java] reuse of connection after failure. |
---|---|
Author | Andrew Goedhart |
Post date | 2007-03-15T08:57:30Z |
Just a general comment. The transaction in this case is not on the connection being closed, but on the temporary connection being used to attempt to recover a transaction in limbo during an XA rollback request. The Jaybird driver is closing the temporary connection in a finally of the tryCompleteInLimboTransaction() method shown below. (see 1. >>>>) The code looks as though it is attempting to commit any active transaction on the temporary connection. It then calls destroy. The fact that Firebird is returning the error means that the connection is active. It looks as though something goes badly wrong in the recover and that the connection throws an exception in the commit or the connection looses its knowledge of the active transaction, because the first time it knows of the transaction is after firebird returned the error( see 2. >>>>). The destroy method checks for active transactions and it does not fail there (see 3).
1.) private void tryCompleteInLimboTransaction(GDS gds, Xid xid, boolean commit)
throws XAException {
try {
FBManagedConnection tempMc = null;
FirebirdLocalTransaction tempLocalTx = null;
try {
tempMc = new FBManagedConnection(null, null, this);
tempLocalTx = (FirebirdLocalTransaction) tempMc.getLocalTransaction();
tempLocalTx.begin();
...
... } finally {
try {
if (tempLocalTx != null && tempLocalTx.inTransaction())
tempLocalTx.commit();
} finally {
}
2.) public void iscDetachDatabase(IscDbHandle db_handle) throws GDSException {
boolean debug = log != null && log.isDebugEnabled();
isc_db_handle_impl db = (isc_db_handle_impl) db_handle;
if (db == null) {
throw new GDSException(ISCConstants.isc_bad_db_handle);
}
synchronized (db) {
try {
if (db.eventCoordinator != null){
db.eventCoordinator.close();
}
if (debug)
log.debug("op_detach ");
db.out.writeInt(op_detach);
db.out.writeInt(db.getRdb_id());
db.out.flush();
if (debug)
log.debug("sent");
throw new GDSException(ISCConstants.isc_network_error);
} finally {
try {
disconnect(db);
} catch (IOException ex2) {
throw new GDSException(ISCConstants.isc_network_error);
}
} // end of finally
}
}
3.) if (gdsHelper.inTransaction())
throw new java.lang.IllegalStateException(
"Can't destroy managed connection with active transaction");
My guess if I look through my code is that we where trying to rollback an already finished transaction, but I am not 100% certain that this is the case.
Andrew
1.) private void tryCompleteInLimboTransaction(GDS gds, Xid xid, boolean commit)
throws XAException {
try {
FBManagedConnection tempMc = null;
FirebirdLocalTransaction tempLocalTx = null;
try {
tempMc = new FBManagedConnection(null, null, this);
tempLocalTx = (FirebirdLocalTransaction) tempMc.getLocalTransaction();
tempLocalTx.begin();
...
... } finally {
try {
if (tempLocalTx != null && tempLocalTx.inTransaction())
tempLocalTx.commit();
} finally {
>>>>>>>> if (tempMc != null) tempMc.destroy();}
}
2.) public void iscDetachDatabase(IscDbHandle db_handle) throws GDSException {
boolean debug = log != null && log.isDebugEnabled();
isc_db_handle_impl db = (isc_db_handle_impl) db_handle;
if (db == null) {
throw new GDSException(ISCConstants.isc_bad_db_handle);
}
synchronized (db) {
try {
if (db.eventCoordinator != null){
db.eventCoordinator.close();
}
if (debug)
log.debug("op_detach ");
db.out.writeInt(op_detach);
db.out.writeInt(db.getRdb_id());
db.out.flush();
if (debug)
log.debug("sent");
>>>>>>>>>> receiveResponse(db, -1);} catch (IOException ex) {
throw new GDSException(ISCConstants.isc_network_error);
} finally {
try {
disconnect(db);
} catch (IOException ex2) {
throw new GDSException(ISCConstants.isc_network_error);
}
} // end of finally
}
}
3.) if (gdsHelper.inTransaction())
throw new java.lang.IllegalStateException(
"Can't destroy managed connection with active transaction");
My guess if I look through my code is that we where trying to rollback an already finished transaction, but I am not 100% certain that this is the case.
Andrew