1 21 22 package org.apache.derby.jdbc; 23 24 25 import org.apache.derby.impl.jdbc.EmbedConnection; 26 import javax.transaction.xa.XAResource ; 27 import org.apache.derby.iapi.services.context.ContextImpl; 28 import org.apache.derby.iapi.services.context.ContextManager; 29 import org.apache.derby.iapi.error.ExceptionSeverity; 30 import org.apache.derby.iapi.error.StandardException; 31 import org.apache.derby.iapi.store.access.xa.XAXactId; 32 import org.apache.derby.iapi.reference.SQLState; 33 import java.util.HashMap ; 34 import javax.transaction.xa.XAException ; 35 36 38 final class XATransactionState extends ContextImpl { 39 40 41 final static int TRO_DEADLOCK = -2; 42 43 final static int TRO_FAIL = -1; 44 final static int T0_NOT_ASSOCIATED = 0; 45 final static int T1_ASSOCIATED = 1; 46 final static int TC_COMPLETED = 3; 49 final EmbedConnection conn; 50 final EmbedXAResource creatingResource; 51 private EmbedXAResource associatedResource; 53 final XAXactId xid; 54 61 HashMap suspendedList; 62 63 64 67 int associationState; 68 69 int rollbackOnlyCode; 70 71 72 75 boolean isPrepared; 76 77 XATransactionState(ContextManager cm, EmbedConnection conn, 78 EmbedXAResource resource, XAXactId xid) { 79 80 super(cm, "XATransactionState"); 81 this.conn = conn; 82 this.associatedResource = resource; 83 this.creatingResource = resource; 84 this.associationState = XATransactionState.T1_ASSOCIATED; 85 this.xid = xid; 86 87 } 88 89 public void cleanupOnError(Throwable t) { 90 91 if (t instanceof StandardException) { 92 93 StandardException se = (StandardException) t; 94 95 if (se.getSeverity() >= ExceptionSeverity.SESSION_SEVERITY) { 96 popMe(); 97 return; 98 } 99 100 if (se.getSeverity() == ExceptionSeverity.TRANSACTION_SEVERITY) { 101 102 synchronized (this) { 103 conn.setApplicationConnection(null); 105 notifyAll(); 106 associationState = TRO_FAIL; 107 if (SQLState.DEADLOCK.equals(se.getMessageId())) 108 rollbackOnlyCode = XAException.XA_RBDEADLOCK; 109 else if (SQLState.LOCK_TIMEOUT.equals(se.getMessageId())) 110 rollbackOnlyCode = XAException.XA_RBTIMEOUT; 111 else 112 rollbackOnlyCode = XAException.XA_RBOTHER; 113 } 114 } 115 } 116 } 117 118 void start(EmbedXAResource resource, int flags) throws XAException { 119 120 synchronized (this) { 121 if (associationState == XATransactionState.TRO_FAIL) 122 throw new XAException (rollbackOnlyCode); 123 124 boolean isSuspendedByResource = (suspendedList != null) && (suspendedList.get(resource) != null); 125 126 if (flags == XAResource.TMRESUME) { 127 if (!isSuspendedByResource) 128 throw new XAException (XAException.XAER_PROTO); 129 130 } else { 131 if (isSuspendedByResource) 133 throw new XAException (XAException.XAER_PROTO); 134 } 135 136 while (associationState == XATransactionState.T1_ASSOCIATED) { 137 138 try { 139 wait(); 140 } catch (InterruptedException ie) { 141 throw new XAException (XAException.XA_RETRY); 142 } 143 } 144 145 146 switch (associationState) { 147 case XATransactionState.T0_NOT_ASSOCIATED: 148 break; 149 150 case XATransactionState.TRO_FAIL: 151 throw new XAException (rollbackOnlyCode); 152 153 default: 154 throw new XAException (XAException.XAER_NOTA); 155 } 156 157 if (isPrepared) 158 throw new XAException (XAException.XAER_PROTO); 159 160 if (isSuspendedByResource) { 161 suspendedList.remove(resource); 162 } 163 164 associationState = XATransactionState.T1_ASSOCIATED; 165 associatedResource = resource; 166 } 167 } 168 169 boolean end(EmbedXAResource resource, int flags, 170 boolean endingCurrentXid) throws XAException { 171 172 boolean rollbackOnly = false; 173 synchronized (this) { 174 175 176 boolean isSuspendedByResource = (suspendedList != null) && (suspendedList.get(resource) != null); 177 178 if (!endingCurrentXid) { 179 while (associationState == XATransactionState.T1_ASSOCIATED) { 180 181 try { 182 wait(); 183 } catch (InterruptedException ie) { 184 throw new XAException (XAException.XA_RETRY); 185 } 186 } 187 } 188 189 switch (associationState) { 190 case XATransactionState.TC_COMPLETED: 191 throw new XAException (XAException.XAER_NOTA); 192 case XATransactionState.TRO_FAIL: 193 if (endingCurrentXid) 194 flags = XAResource.TMFAIL; 195 else 196 throw new XAException (rollbackOnlyCode); 197 } 198 199 boolean notify = false; 200 switch (flags) { 201 case XAResource.TMSUCCESS: 202 if (isSuspendedByResource) { 203 suspendedList.remove(resource); 204 } 205 else { 206 if (resource != associatedResource) 207 throw new XAException (XAException.XAER_PROTO); 208 209 associationState = XATransactionState.T0_NOT_ASSOCIATED; 210 associatedResource = null; 211 notify = true; 212 } 213 214 conn.setApplicationConnection(null); 215 break; 216 217 case XAResource.TMFAIL: 218 219 if (isSuspendedByResource) { 220 suspendedList.remove(resource); 221 } else { 222 if (resource != associatedResource) 223 throw new XAException (XAException.XAER_PROTO); 224 associatedResource = null; 225 } 226 227 if (associationState != XATransactionState.TRO_FAIL) { 228 associationState = XATransactionState.TRO_FAIL; 229 rollbackOnlyCode = XAException.XA_RBROLLBACK; 230 } 231 conn.setApplicationConnection(null); 232 notify = true; 233 rollbackOnly = true; 234 break; 235 236 case XAResource.TMSUSPEND: 237 if (isSuspendedByResource) 238 throw new XAException (XAException.XAER_PROTO); 239 240 if (resource != associatedResource) 241 throw new XAException (XAException.XAER_PROTO); 242 243 if (suspendedList == null) 244 suspendedList = new HashMap (); 245 suspendedList.put(resource, this); 246 247 associationState = XATransactionState.T0_NOT_ASSOCIATED; 248 associatedResource = null; 249 conn.setApplicationConnection(null); 250 notify = true; 251 252 break; 253 254 default: 255 throw new XAException (XAException.XAER_INVAL); 256 } 257 258 if (notify) 259 notifyAll(); 260 261 return rollbackOnly; 262 } 263 } 264 265 } 266 | Popular Tags |