public boolean restore_state(InputObjectState os, int t) { boolean res = false; try { _heuristic = os.unpackInt(); _committed = os.unpackBoolean(); _tranID = XidImple.unpack(os); _theXAResource = null; _recoveryObject = null; if (os.unpackInt() == RecoverableXAConnection.OBJECT_RECOVERY) { _productName = os.unpackString(); _productVersion = os.unpackString(); _jndiName = os.unpackString(); boolean haveXAResource = os.unpackBoolean(); if (haveXAResource) { try { // Read the classname of the serialized XAResource String className = os.unpackString(); byte[] b = os.unpackBytes(); ByteArrayInputStream s = new ByteArrayInputStream(b); ObjectInputStream o = new ObjectInputStream(s); // Give the list of deserializers a chance to deserialize the record boolean deserialized = false; Iterator<SerializableXAResourceDeserializer> iterator = getXAResourceDeserializers().iterator(); while (iterator.hasNext()) { SerializableXAResourceDeserializer proxyXAResourceDeserializer = iterator.next(); if (proxyXAResourceDeserializer.canDeserialze(className)) { _theXAResource = proxyXAResourceDeserializer.deserialze(o); deserialized = true; break; } } // Give it a go ourselves if (!deserialized) { _theXAResource = (XAResource) o.readObject(); } o.close(); if (jtaLogger.logger.isTraceEnabled()) { jtaLogger.logger.trace("XAResourceRecord.restore_state - XAResource de-serialized"); } } catch (Exception ex) { // not serializable in the first place! jtaLogger.i18NLogger.warn_resources_arjunacore_restorestate(ex); return false; } } else { /* * Lookup new XAResource via XARecoveryModule if possible. */ _theXAResource = getNewXAResource(); if (_theXAResource == null) { jtaLogger.i18NLogger.warn_resources_arjunacore_norecoveryxa(toString()); /* * Don't prevent tx from activating because there may be * other participants that can still recover. Plus, we will * try to get a new XAResource later for this instance. */ res = true; } } } else { String creatorName = os.unpackString(); _recoveryObject = ClassloadingUtility.loadAndInstantiateClass( RecoverableXAConnection.class, creatorName, null); if (_recoveryObject == null) { throw new ClassNotFoundException(); } _recoveryObject.unpackFrom(os); _theXAResource = _recoveryObject.getResource(); if (jtaLogger.logger.isTraceEnabled()) { jtaLogger.logger.trace( "XAResourceRecord.restore_state - XAResource got from " + creatorName); } } res = true; } catch (Exception e) { jtaLogger.i18NLogger.warn_resources_arjunacore_restorestateerror( _theXAResource.toString(), XAHelper.xidToString(_tranID), e); res = false; } if (res) res = super.restore_state(os, t); return res; }
public boolean save_state(OutputObjectState os, int t) { boolean res = false; try { os.packInt(_heuristic); os.packBoolean(_committed); /* * Since we don't know what type of Xid we are using, leave it up to * XID to pack. */ XidImple.pack(os, _tranID); /* * If no recovery object set then rely upon object serialisation! */ if (_recoveryObject == null) { os.packInt(RecoverableXAConnection.OBJECT_RECOVERY); os.packString(_productName); os.packString(_productVersion); os.packString(_jndiName); if (_theXAResource instanceof Serializable) { try { ByteArrayOutputStream s = new ByteArrayOutputStream(); ObjectOutputStream o = new ObjectOutputStream(s); o.writeObject(_theXAResource); o.close(); os.packBoolean(true); String name = _theXAResource.getClass().getName(); os.packString(name); os.packBytes(s.toByteArray()); } catch (NotSerializableException ex) { jtaLogger.i18NLogger.warn_resources_arjunacore_savestate(); return false; } } else { // have to rely upon XAResource.recover! os.packBoolean(false); } } else { os.packInt(RecoverableXAConnection.AUTO_RECOVERY); os.packString(_recoveryObject.getClass().getName()); _recoveryObject.packInto(os); } res = true; } catch (Exception e) { jtaLogger.i18NLogger.warn_resources_arjunacore_savestateerror( _theXAResource.toString(), XAHelper.xidToString(_tranID), e); res = false; } if (res) res = super.save_state(os, t); return res; }
/** * For commit_one_phase we can do whatever we want since the transaction outcome is whatever we * want. Therefore, we do not need to save any additional recoverable state, such as a reference * to the transaction coordinator, since it will not have an intentions list anyway. */ public int topLevelOnePhaseCommit() { if (jtaLogger.logger.isTraceEnabled()) { jtaLogger.logger.trace("XAResourceRecord.topLevelOnePhaseCommit for " + this); } boolean commit = true; if (_tranID == null) { jtaLogger.i18NLogger.warn_resources_arjunacore_opcnulltx("XAResourceRecord.1pc"); return TwoPhaseOutcome.ONE_PHASE_ERROR; // rolled back!! } else { if (_theXAResource != null) { if (_heuristic != TwoPhaseOutcome.FINISH_OK) return _heuristic; XAException endHeuristic = null; XAException endRBOnly = null; try { /* * TODO in Oracle the end is not needed. Is this common * across other RMs? */ if (endAssociation()) { _theXAResource.end(_tranID, XAResource.TMSUCCESS); } } catch (XAException e1) { /* * Now it's not legal to return a heuristic from end, but * apparently Oracle does (http://jira.jboss.com/jira/browse/JBTM-343) * Since this is 1PC we can call forget: the outcome of the * transaction is the outcome of the participant. */ switch (e1.errorCode) { case XAException.XA_HEURHAZ: case XAException.XA_HEURMIX: case XAException.XA_HEURCOM: case XAException.XA_HEURRB: endHeuristic = e1; break; case XAException.XA_RBROLLBACK: case XAException.XA_RBCOMMFAIL: case XAException.XA_RBDEADLOCK: case XAException.XA_RBINTEGRITY: case XAException.XA_RBOTHER: case XAException.XA_RBPROTO: case XAException.XA_RBTIMEOUT: case XAException.XA_RBTRANSIENT: /* * Has been marked as rollback-only. We still * need to call rollback. */ endRBOnly = e1; commit = false; break; case XAException.XAER_RMERR: case XAException.XAER_NOTA: case XAException.XAER_PROTO: case XAException.XAER_INVAL: case XAException.XAER_RMFAIL: default: { jtaLogger.i18NLogger.warn_resources_arjunacore_opcerror( XAHelper.xidToString(_tranID), _theXAResource.toString(), XAHelper.printXAErrorCode(e1), e1); removeConnection(); return TwoPhaseOutcome.FINISH_ERROR; } } } catch (RuntimeException e) { jtaLogger.i18NLogger.warn_resources_arjunacore_opcerror( XAHelper.xidToString(_tranID), _theXAResource.toString(), "-", e); throw e; } try { /* * Not strictly necessary since calling commit will * do the rollback if end failed as above. */ if (endHeuristic != null) // catch those RMs that terminate in end rather than follow the spec throw endHeuristic; if (commit) _theXAResource.commit(_tranID, true); else { _theXAResource.rollback(_tranID); throw endRBOnly; } } catch (XAException e1) { jtaLogger.i18NLogger.warn_resources_arjunacore_opcerror( XAHelper.xidToString(_tranID), _theXAResource.toString(), XAHelper.printXAErrorCode(e1), e1); /* * XA_HEURHAZ, XA_HEURCOM, XA_HEURRB, XA_HEURMIX, * XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or * XAER_PROTO. XA_RB* */ switch (e1.errorCode) { case XAException.XA_HEURHAZ: case XAException.XA_HEURMIX: return TwoPhaseOutcome.HEURISTIC_HAZARD; case XAException.XA_HEURCOM: forget(); break; case XAException.XA_HEURRB: forget(); return TwoPhaseOutcome.ONE_PHASE_ERROR; case XAException.XA_RBROLLBACK: case XAException.XA_RBCOMMFAIL: case XAException.XA_RBDEADLOCK: case XAException.XA_RBINTEGRITY: case XAException.XA_RBOTHER: case XAException.XA_RBPROTO: case XAException.XA_RBTIMEOUT: case XAException.XA_RBTRANSIENT: case XAException.XAER_RMERR: return TwoPhaseOutcome.ONE_PHASE_ERROR; case XAException.XAER_NOTA: return TwoPhaseOutcome .HEURISTIC_HAZARD; // something committed or rolled back without asking us! case XAException.XAER_INVAL: // resource manager failed, did it rollback? return TwoPhaseOutcome.HEURISTIC_HAZARD; case XAException.XA_RETRY: // XA does not allow this to be thrown for 1PC! case XAException.XAER_PROTO: return TwoPhaseOutcome.ONE_PHASE_ERROR; // assume rollback case XAException.XAER_RMFAIL: default: _committed = true; // will cause log to be rewritten return TwoPhaseOutcome.FINISH_ERROR; // recovery should retry } } catch (Exception e2) { jtaLogger.i18NLogger.warn_resources_arjunacore_opcerror( XAHelper.xidToString(_tranID), _theXAResource.toString(), "-", e2); return TwoPhaseOutcome.FINISH_ERROR; } finally { removeConnection(); } } else return TwoPhaseOutcome.ONE_PHASE_ERROR; } if (commit) return TwoPhaseOutcome.FINISH_OK; else return TwoPhaseOutcome.FINISH_ERROR; }
public int topLevelCommit() { if (jtaLogger.logger.isTraceEnabled()) { jtaLogger.logger.trace("XAResourceRecord.topLevelCommit for " + this); } if (!_prepared) return TwoPhaseOutcome.NOT_PREPARED; if (_tranID == null) { jtaLogger.i18NLogger.warn_resources_arjunacore_commitnulltx("XAResourceRecord.commit"); return TwoPhaseOutcome.FINISH_ERROR; } else { if (_theXAResource == null) _theXAResource = getNewXAResource(); if (_theXAResource != null) { if (_heuristic != TwoPhaseOutcome.FINISH_OK) return _heuristic; /* * No need for end call here since we can only get to this * point by going through prepare. */ try { _theXAResource.commit(_tranID, false); } catch (XAException e1) { if (notAProblem(e1, true)) { // some other thread got there first (probably) } else { jtaLogger.i18NLogger.warn_resources_arjunacore_commitxaerror( XAHelper.xidToString(_tranID), _theXAResource.toString(), XAHelper.printXAErrorCode(e1), e1); /* * XA_HEURHAZ, XA_HEURCOM, XA_HEURRB, XA_HEURMIX, * XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or * XAER_PROTO. */ switch (e1.errorCode) { case XAException.XA_HEURHAZ: return TwoPhaseOutcome.HEURISTIC_HAZARD; case XAException.XA_HEURCOM: // what about forget? // OTS doesn't support // this code here. break; case XAException.XA_HEURRB: case XAException .XA_RBROLLBACK: // could really do with an ABORTED status in TwoPhaseOutcome to // differentiate case XAException.XA_RBCOMMFAIL: case XAException.XA_RBDEADLOCK: case XAException.XA_RBINTEGRITY: case XAException.XA_RBOTHER: case XAException.XA_RBPROTO: case XAException.XA_RBTIMEOUT: case XAException.XA_RBTRANSIENT: case XAException.XAER_RMERR: case XAException.XAER_PROTO: // XA spec implies rollback return TwoPhaseOutcome.HEURISTIC_ROLLBACK; case XAException.XA_HEURMIX: return TwoPhaseOutcome.HEURISTIC_MIXED; case XAException.XAER_NOTA: if (_recovered) break; // committed previously and recovery completed else return TwoPhaseOutcome.HEURISTIC_HAZARD; // something terminated the transaction! case XAException.XA_RETRY: case XAException.XAER_RMFAIL: _committed = true; // will cause log to be rewritten /* * Could do timeout retry here, but that could cause other resources in the list to go down the * heuristic path (some are far too keen to do this). Fail and let recovery retry. Meanwhile * the coordinator will continue to commit the other resources immediately. */ return TwoPhaseOutcome.FINISH_ERROR; case XAException.XAER_INVAL: // resource manager failed, did it rollback? default: return TwoPhaseOutcome.HEURISTIC_HAZARD; } } } catch (Exception e2) { jtaLogger.i18NLogger.warn_resources_arjunacore_commitxaerror( XAHelper.xidToString(_tranID), _theXAResource.toString(), "-", e2); return TwoPhaseOutcome.FINISH_ERROR; } finally { removeConnection(); } } else { jtaLogger.i18NLogger.warn_resources_arjunacore_noresource(XAHelper.xidToString(_tranID)); if (XAResourceRecord._assumedComplete) { jtaLogger.i18NLogger.info_resources_arjunacore_assumecomplete( XAHelper.xidToString(_tranID)); return TwoPhaseOutcome.FINISH_OK; } else return TwoPhaseOutcome.FINISH_ERROR; } } return TwoPhaseOutcome.FINISH_OK; }
public int topLevelAbort() { if (jtaLogger.logger.isTraceEnabled()) { jtaLogger.logger.trace("XAResourceRecord.topLevelAbort for " + this); } if (!_valid) return TwoPhaseOutcome.FINISH_ERROR; if (_theTransaction != null && _theTransaction.getXAResourceState(_theXAResource) == TxInfo.OPTIMIZED_ROLLBACK) { /* * Already rolledback during delist. */ return TwoPhaseOutcome.FINISH_OK; } if (_tranID == null) { jtaLogger.i18NLogger.warn_resources_arjunacore_rollbacknulltx("XAResourceRecord.rollback"); return TwoPhaseOutcome.FINISH_ERROR; } else { if (_theXAResource == null) _theXAResource = getNewXAResource(); if (_theXAResource != null) { if (_heuristic != TwoPhaseOutcome.FINISH_OK) return _heuristic; try { if (!_prepared) { if (endAssociation()) { _theXAResource.end(_tranID, XAResource.TMSUCCESS); } } } catch (XAException e1) { if ((e1.errorCode >= XAException.XA_RBBASE) && (e1.errorCode < XAException.XA_RBEND)) { /* * Has been marked as rollback-only. We still * need to call rollback. */ } else { jtaLogger.i18NLogger.warn_resources_arjunacore_rollbackerror( XAHelper.xidToString(_tranID), _theXAResource.toString(), XAHelper.printXAErrorCode(e1), e1); removeConnection(); return TwoPhaseOutcome.FINISH_ERROR; } } catch (RuntimeException e) { jtaLogger.i18NLogger.warn_resources_arjunacore_rollbackerror( XAHelper.xidToString(_tranID), _theXAResource.toString(), "-", e); throw e; } try { _theXAResource.rollback(_tranID); } catch (XAException e1) { if (notAProblem(e1, false)) { // some other thread got there first (probably) } else { jtaLogger.i18NLogger.warn_resources_arjunacore_rollbackerror( XAHelper.xidToString(_tranID), _theXAResource.toString(), XAHelper.printXAErrorCode(e1), e1); switch (e1.errorCode) { case XAException.XAER_RMERR: if (!_prepared) break; // just do the finally block case XAException.XA_HEURHAZ: return TwoPhaseOutcome.HEURISTIC_HAZARD; case XAException.XA_HEURCOM: return TwoPhaseOutcome.HEURISTIC_COMMIT; case XAException.XA_HEURMIX: return TwoPhaseOutcome.HEURISTIC_MIXED; case XAException.XAER_NOTA: if (_recovered) break; // rolled back previously and recovery completed case XAException.XA_HEURRB: // forget? case XAException.XA_RBROLLBACK: case XAException.XA_RBEND: case XAException.XA_RBCOMMFAIL: case XAException.XA_RBDEADLOCK: case XAException.XA_RBINTEGRITY: case XAException.XA_RBOTHER: case XAException.XA_RBPROTO: case XAException.XA_RBTIMEOUT: break; default: return TwoPhaseOutcome.FINISH_ERROR; } } } catch (Exception e2) { jtaLogger.i18NLogger.warn_resources_arjunacore_rollbackerror( XAHelper.xidToString(_tranID), _theXAResource.toString(), "-", e2); return TwoPhaseOutcome.FINISH_ERROR; } finally { if (!_prepared) removeConnection(); } } else { jtaLogger.i18NLogger.warn_resources_arjunacore_noresource(XAHelper.xidToString(_tranID)); if (XAResourceRecord._assumedComplete) { jtaLogger.i18NLogger.info_resources_arjunacore_assumecomplete( XAHelper.xidToString(_tranID)); return TwoPhaseOutcome.FINISH_OK; } else return TwoPhaseOutcome.FINISH_ERROR; } } return TwoPhaseOutcome.FINISH_OK; }
public int topLevelPrepare() { if (jtaLogger.logger.isTraceEnabled()) { jtaLogger.logger.trace("XAResourceRecord.topLevelPrepare for " + this); } if (!_valid || (_theXAResource == null) || (_tranID == null)) { jtaLogger.i18NLogger.warn_resources_arjunacore_preparenulltx("XAResourceRecord.prepare"); removeConnection(); return TwoPhaseOutcome.PREPARE_NOTOK; } try { if (endAssociation()) { _theXAResource.end(_tranID, XAResource.TMSUCCESS); } _prepared = true; if (_theXAResource.prepare(_tranID) == XAResource.XA_RDONLY) { if (TxControl.isReadonlyOptimisation()) { // we won't be called again, so we need to tidy up now removeConnection(); } return TwoPhaseOutcome.PREPARE_READONLY; } else return TwoPhaseOutcome.PREPARE_OK; } catch (XAException e1) { jtaLogger.i18NLogger.warn_resources_arjunacore_preparefailed( XAHelper.xidToString(_tranID), _theXAResource.toString(), XAHelper.printXAErrorCode(e1), e1); /* * XA_RB*, XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or * XAER_PROTO. */ if (_rollbackOptimization) // won't have rollback called on it removeConnection(); switch (e1.errorCode) { case XAException.XAER_RMERR: case XAException.XAER_RMFAIL: case XAException.XA_RBROLLBACK: case XAException.XA_RBEND: case XAException.XA_RBCOMMFAIL: case XAException.XA_RBDEADLOCK: case XAException.XA_RBINTEGRITY: case XAException.XA_RBOTHER: case XAException.XA_RBPROTO: case XAException.XA_RBTIMEOUT: case XAException.XAER_INVAL: case XAException.XAER_PROTO: case XAException .XAER_NOTA: // resource may have arbitrarily rolled back (shouldn't, but ...) return TwoPhaseOutcome.PREPARE_NOTOK; // will not call rollback default: return TwoPhaseOutcome .HEURISTIC_HAZARD; // we're not really sure (shouldn't get here though). } } catch (Exception e2) { jtaLogger.i18NLogger.warn_resources_arjunacore_preparefailed( XAHelper.xidToString(_tranID), _theXAResource.toString(), "-", e2); if (_rollbackOptimization) // won't have rollback called on it removeConnection(); return TwoPhaseOutcome.PREPARE_NOTOK; } }