1010import org .firebirdsql .gds .ng .TransactionState ;
1111import org .firebirdsql .gds .ng .listeners .DatabaseListener ;
1212import org .firebirdsql .jaybird .util .Cleaners ;
13+ import org .firebirdsql .jaybird .xca .FatalErrorHelper ;
1314import org .firebirdsql .jna .fbclient .FbClientLibrary ;
1415import org .firebirdsql .jna .fbclient .ISC_STATUS ;
1516import org .jspecify .annotations .Nullable ;
@@ -68,14 +69,16 @@ public IntByReference getJnaHandle() {
6869 @ Override
6970 public void commit () throws SQLException {
7071 try (LockCloseable ignored = withLock ()) {
71- final JnaDatabase db = getDatabase ();
72- db .checkConnected ();
72+ checkDbAttached ();
7373 switchState (TransactionState .COMMITTING );
7474 clientLibrary .isc_commit_transaction (statusVector , handle );
7575 processStatusVector ();
7676 switchState (TransactionState .COMMITTED );
77- cleanable . clean ();
77+ clean ();
7878 } catch (SQLException e ) {
79+ if (FatalErrorHelper .isBrokenConnection (e )) {
80+ forceAbortedUnknownState ();
81+ }
7982 exceptionListenerDispatcher .errorOccurred (e );
8083 throw e ;
8184 } finally {
@@ -86,14 +89,16 @@ public void commit() throws SQLException {
8689 @ Override
8790 public void rollback () throws SQLException {
8891 try (LockCloseable ignored = withLock ()) {
89- final JnaDatabase db = getDatabase ();
90- db .checkConnected ();
92+ checkDbAttached ();
9193 switchState (TransactionState .ROLLING_BACK );
9294 clientLibrary .isc_rollback_transaction (statusVector , handle );
9395 processStatusVector ();
9496 switchState (TransactionState .ROLLED_BACK );
95- cleanable . clean ();
97+ clean ();
9698 } catch (SQLException e ) {
99+ if (FatalErrorHelper .isBrokenConnection (e )) {
100+ forceAbortedUnknownState ();
101+ }
97102 exceptionListenerDispatcher .errorOccurred (e );
98103 throw e ;
99104 } finally {
@@ -105,8 +110,7 @@ public void rollback() throws SQLException {
105110 public void prepare (byte @ Nullable [] recoveryInformation ) throws SQLException {
106111 boolean noRecoveryInfo = recoveryInformation == null || recoveryInformation .length == 0 ;
107112 try (LockCloseable ignored = withLock ()) {
108- final JnaDatabase db = getDatabase ();
109- db .checkConnected ();
113+ checkDbAttached ();
110114 switchState (TransactionState .PREPARING );
111115 if (noRecoveryInfo ) {
112116 clientLibrary .isc_prepare_transaction (statusVector , handle );
@@ -117,6 +121,9 @@ public void prepare(byte @Nullable [] recoveryInformation) throws SQLException {
117121 processStatusVector ();
118122 switchState (TransactionState .PREPARED );
119123 } catch (SQLException e ) {
124+ if (FatalErrorHelper .isBrokenConnection (e )) {
125+ forceAbortedUnknownState ();
126+ }
120127 exceptionListenerDispatcher .errorOccurred (e );
121128 throw e ;
122129 } finally {
@@ -129,8 +136,7 @@ public byte[] getTransactionInfo(byte[] requestItems, int maxBufferLength) throw
129136 try {
130137 final ByteBuffer responseBuffer = ByteBuffer .allocateDirect (maxBufferLength );
131138 try (LockCloseable ignored = withLock ()) {
132- final JnaDatabase db = getDatabase ();
133- db .checkConnected ();
139+ checkDbAttached ();
134140 clientLibrary .isc_transaction_info (statusVector , handle , (short ) requestItems .length , requestItems ,
135141 (short ) maxBufferLength , responseBuffer );
136142 processStatusVector ();
@@ -148,6 +154,16 @@ private void processStatusVector() throws SQLException {
148154 getDatabase ().processStatusVector (statusVector , null );
149155 }
150156
157+ @ Override
158+ protected void forceAbortedUnknownState () {
159+ super .forceAbortedUnknownState ();
160+ clean ();
161+ }
162+
163+ private void clean () {
164+ cleanable .clean ();
165+ }
166+
151167 private static final class CleanupAction implements Runnable , DatabaseListener {
152168
153169 private final IntByReference handle ;
0 commit comments