So, who is osh? Osh, what's the problem with invalid XA resource
state?
Aaron
On Wed, 18 Oct 2000, jBoss CVS Development wrote:
> User: osh
> Date: 00/10/18 07:28:53
>
> Modified: src/main/org/jboss/tm TxCapsule.java
> Log:
> Fix for possible race on instance reuse.
> More trace information.
> Still outstanding: A problem with invalid XA resource state during
> XA resource calls.
>
> Revision Changes Path
> 1.15 +132 -36 jboss/src/main/org/jboss/tm/TxCapsule.java
>
> Index: TxCapsule.java
> ===================================================================
> RCS file: /products/cvs/ejboss/jboss/src/main/org/jboss/tm/TxCapsule.java,v
> retrieving revision 1.14
> retrieving revision 1.15
> diff -u -r1.14 -r1.15
> --- TxCapsule.java 2000/10/15 19:05:07 1.14
> +++ TxCapsule.java 2000/10/18 14:28:53 1.15
> @@ -43,7 +43,7 @@
> * @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
> * @author <a href="mailto:[EMAIL PROTECTED]">Ole Husgaard</a>
> *
> - * @version $Revision: 1.14 $
> + * @version $Revision: 1.15 $
> */
> class TxCapsule implements TimeoutTarget
> {
> @@ -87,6 +87,9 @@
> {
> xid = new XidImpl();
> this.tm = tm;
> +
> + if (trace)
> + Logger.debug("TxCapsule: Created new instance for tx=" + toString());
> }
>
> /**
> @@ -118,6 +121,9 @@
>
> start = System.currentTimeMillis();
> this.timeout = TimeoutFactory.createTimeout(start+timeout, this);
> +
> + if (trace)
> + Logger.debug("TxCapsule: Reused instance for tx=" + toString());
> }
>
> // Public --------------------------------------------------------
> @@ -130,7 +136,8 @@
> try {
> lock();
>
> - Logger.warning("Transaction " + toString() + " timed out.");
> + Logger.warning("Transaction " + toString() + " timed out." +
> + " status=" + getStringStatus(status));
>
> if (this.timeout == null)
> return; // Don't race with timeout cancellation.
> @@ -167,6 +174,7 @@
> rollbackResources();
> doAfterCompletion();
> gotHeuristic(null, XAException.XA_HEURRB);
> + instanceDone();
> return;
>
> case Status.STATUS_PREPARING:
> @@ -174,7 +182,8 @@
> return; // commit will fail
>
> default:
> - Logger.warning("TxCapsule: Unknown status at timeout.");
> + Logger.warning("TxCapsule: Unknown status at timeout, tx=" +
> + toString());
> return;
> }
> } finally {
> @@ -225,8 +234,8 @@
> lock();
>
> if (trace)
> - Logger.debug("TxCapsule.commit(): Entered, status=" +
> - getStringStatus(status));
> + Logger.debug("TxCapsule.commit(): Entered, tx=" + toString() +
> + " status=" + getStringStatus(status));
>
> switch (status) {
> case Status.STATUS_PREPARING:
> @@ -268,7 +277,8 @@
>
> if (trace)
> Logger.debug("TxCapsule.commit(): Before completion done, " +
> - "status=" + getStringStatus(status));
> + "tx=" + toString() +
> + " status=" + getStringStatus(status));
>
> endResources();
>
> @@ -309,8 +319,8 @@
> doAfterCompletion();
> cancelTimeout();
> instanceDone();
> - throw new RollbackException("Unable to commit, status=" +
> - getStringStatus(status));
> + throw new RollbackException("Unable to commit, tx=" + toString() +
> + " status=" + getStringStatus(status));
> }
>
> cancelTimeout();
> @@ -319,7 +329,8 @@
> checkHeuristics();
>
> if (trace)
> - Logger.debug("TxCapsule.commit(): Committed OK.");
> + Logger.debug("TxCapsule.commit(): Transaction " + toString() +
> + " committed OK.");
>
> } finally {
> unlock();
> @@ -340,8 +351,8 @@
> lock();
>
> if (trace)
> - Logger.debug("TxCapsule.rollback(): Entered, status=" +
> - getStringStatus(status));
> + Logger.debug("TxCapsule.rollback(): Entered, tx=" + toString() +
> + " status=" + getStringStatus(status));
>
> switch (status) {
> case Status.STATUS_ACTIVE:
> @@ -361,7 +372,9 @@
> status = Status.STATUS_MARKED_ROLLBACK;
> return; // commit() will do rollback.
> default:
> - throw new IllegalStateException("Cannot rollback(), status=" +
> + throw new IllegalStateException("Cannot rollback(), " +
> + "tx=" + toString() +
> + " status=" +
> getStringStatus(status));
> }
> } finally {
> @@ -383,8 +396,8 @@
> lock();
>
> if (trace)
> - Logger.debug("TxCapsule.setRollbackOnly(): Entered, status=" +
> - getStringStatus(status));
> + Logger.debug("TxCapsule.setRollbackOnly(): Entered, tx=" +
> + toString() + " status=" + getStringStatus(status));
>
> switch (status) {
> case Status.STATUS_ACTIVE:
> @@ -438,8 +451,8 @@
> lock();
>
> if (trace)
> - Logger.debug("TxCapsule.delistResource(): Entered, status=" +
> - getStringStatus(status));
> + Logger.debug("TxCapsule.delistResource(): Entered, tx=" +
> + toString() + " status=" + getStringStatus(status));
>
> int idx = findResource(xaRes);
>
> @@ -481,6 +494,8 @@
> }
> return true;
> } catch(XAException e) {
> + Logger.warning("XAException: tx=" + toString() + " errorCode=" +
> + getStringXAErrorCode(e.errorCode));
> Logger.exception(e);
> status = Status.STATUS_MARKED_ROLLBACK;
> return false;
> @@ -509,8 +524,8 @@
> lock();
>
> if (trace)
> - Logger.debug("TxCapsule.enlistResource(): Entered, status=" +
> - getStringStatus(status));
> + Logger.debug("TxCapsule.enlistResource(): Entered, tx=" +
> + toString() + " status=" + getStringStatus(status));
>
> switch (status) {
> case Status.STATUS_ACTIVE:
> @@ -569,6 +584,8 @@
> addResource(xaRes);
> return true;
> } catch(XAException e) {
> + Logger.warning("XAException: tx=" + toString() + " errorCode=" +
> + getStringXAErrorCode(e.errorCode));
> Logger.exception(e);
> return false;
> }
> @@ -603,7 +620,8 @@
>
> if (trace)
> Logger.debug("TxCapsule.registerSynchronization(): Entered, " +
> - "status=" + getStringStatus(status));
> + "tx=" + toString() +
> + " status=" + getStringStatus(status));
>
> switch (status) {
> case Status.STATUS_ACTIVE:
> @@ -796,15 +814,76 @@
> }
>
> /**
> + * Return a string representation of the given XA error code.
> + */
> + private String getStringXAErrorCode(int errorCode) {
> + switch (errorCode) {
> + case XAException.XA_HEURCOM:
> + return "XA_HEURCOM";
> + case XAException.XA_HEURHAZ:
> + return "XA_HEURHAZ";
> + case XAException.XA_HEURMIX:
> + return "XA_HEURMIX";
> + case XAException.XA_HEURRB:
> + return "XA_HEURRB";
> +
> + case XAException.XA_NOMIGRATE:
> + return "XA_NOMIGRATE";
> +
> + case XAException.XA_RBCOMMFAIL:
> + return "XA_RBCOMMFAIL";
> + case XAException.XA_RBDEADLOCK:
> + return "XA_RBDEADLOCK";
> + case XAException.XA_RBINTEGRITY:
> + return "XA_RBINTEGRITY";
> + case XAException.XA_RBOTHER:
> + return "XA_RBOTHER";
> + case XAException.XA_RBPROTO:
> + return "XA_RBPROTO";
> + case XAException.XA_RBROLLBACK:
> + return "XA_RBROLLBACK";
> + case XAException.XA_RBTIMEOUT:
> + return "XA_RBTIMEOUT";
> + case XAException.XA_RBTRANSIENT:
> + return "XA_RBTRANSIENT";
> +
> + case XAException.XA_RDONLY:
> + return "XA_RDONLY";
> + case XAException.XA_RETRY:
> + return "XA_RETRY";
> +
> + case XAException.XAER_ASYNC:
> + return "XAER_ASYNC";
> + case XAException.XAER_DUPID:
> + return "XAER_DUPID";
> + case XAException.XAER_INVAL:
> + return "XAER_INVAL";
> + case XAException.XAER_NOTA:
> + return "XAER_NOTA";
> + case XAException.XAER_OUTSIDE:
> + return "XAER_OUTSIDE";
> + case XAException.XAER_PROTO:
> + return "XAER_PROTO";
> + case XAException.XAER_RMERR:
> + return "XAER_RMERR";
> + case XAException.XAER_RMFAIL:
> + return "XAER_RMFAIL";
> +
> + default:
> + return "XA_UNKNOWN(" + errorCode + ")";
> + }
> + }
> +
> + /**
> * Lock this instance.
> */
> private synchronized void lock()
> {
> if (done)
> - throw new IllegalStateException("No transaction");
> + throw new IllegalStateException("Transaction has terminated");
>
> if (locked) {
> - Logger.warning("TxCapsule: Lock contention."); // Good for debugging.
> + Logger.warning("TxCapsule: Lock contention, tx=" + toString());
> Thread.currentThread().dumpStack();
>
> long myIncarnation = incarnationCount;
> @@ -813,11 +892,15 @@
> try {
> wait();
> } catch (InterruptedException ex) {}
> +
> + // MF FIXME: don't we need a notify() in this case?
> + // we need to release all the thread waiting on this lock
>
> - // MF FIXME: don't we need a notify() in this case?
> - // we need to release all the thread waiting on this lock
> + // OSH: notifyAll() is done in instanceDone()
> + // and notify() is done in unlock().
> +
> if (done || myIncarnation != incarnationCount)
> - throw new IllegalStateException("No transaction");
> + throw new IllegalStateException("Transaction has now terminated");
> }
> }
>
> @@ -829,8 +912,11 @@
> */
> private synchronized void unlock()
> {
> - if (!locked)
> - Logger.warning("TxCapsule: Unlocking, but not locked.");
> + if (!locked) {
> + Logger.warning("TxCapsule: Unlocking, but not locked, tx=" +
> + toString());
> + Logger.exception(new Exception("[Stack trace]"));
> + }
>
> locked = false;
>
> @@ -918,6 +1004,7 @@
> ") entered: " + xaRes.toString() +
> " flags=" + flags);
> unlock();
> + // OSH FIXME: resourceState could be incorrect during this callout.
> try {
> xaRes.start(xid, flags);
> } finally {
> @@ -935,17 +1022,18 @@
> private void endResource(XAResource xaRes, int flag)
> throws XAException
> {
> - Logger.debug("TxCapsule.endResource(" + xid.toString() +
> + Logger.debug("TxCapsule.endResource(" + xid.toString() +
> ") entered: " + xaRes.toString() +
> " flag=" + flag);
> unlock();
> + // OSH FIXME: resourceState could be incorrect during this callout.
> try {
> xaRes.end(xid, flag);
> } finally {
> lock();
> - Logger.debug("TxCapsule.endResource(" + xid.toString() +
> - ") leaving: " + xaRes.toString() +
> - " flag=" + flag);
> + Logger.debug("TxCapsule.endResource(" + xid.toString() +
> + ") leaving: " + xaRes.toString() +
> + " flag=" + flag);
> }
> }
>
> @@ -978,8 +1066,8 @@
> resourceState[i] = RS_ENDED;
> }
> } catch(XAException e) {
> - Logger.debug("endresources: XAException: " + e);
> - Logger.debug("endresources: XAException: errorCode=" + e.errorCode);
> + Logger.warning("XAException: tx=" + toString() + " errorCode=" +
> + getStringXAErrorCode(e.errorCode));
> Logger.exception(e);
> status = Status.STATUS_MARKED_ROLLBACK;
> }
> @@ -1061,6 +1149,8 @@
> unlock();
> resource.forget(xid);
> } catch (XAException e) {
> + Logger.warning("XAException at forget(): errorCode=" +
> + getStringXAErrorCode(e.errorCode));
> Logger.exception(e);
> } finally {
> lock();
> @@ -1107,6 +1197,10 @@
> */
> private void instanceDone()
> {
> + // Notify transaction fronts that we are done.
> + for (int i = 0; i < transactionCount; ++i)
> + transactions[i].setDone();
> +
> synchronized (this) {
> // Done with this incarnation.
> ++incarnationCount;
> @@ -1119,10 +1213,6 @@
> notifyAll();
> }
>
> - // Notify transaction fronts that we are done.
> - for (int i = 0; i < transactionCount; ++i)
> - transactions[i].setDone();
> -
> // Clear content of collections.
> syncCount = 0;
> transactionCount = 0;
> @@ -1193,6 +1283,8 @@
> status = Status.STATUS_MARKED_ROLLBACK;
> break;
> default:
> + Logger.warning("XAException: tx=" + toString() + " errorCode=" +
> + getStringXAErrorCode(e.errorCode));
> Logger.exception(e);
> if (status == Status.STATUS_PREPARING)
> status = Status.STATUS_MARKED_ROLLBACK;
> @@ -1240,6 +1332,8 @@
> gotHeuristic(resources[i], e.errorCode);
> break;
> default:
> + Logger.warning("XAException: tx=" + toString() + " errorCode=" +
> + getStringXAErrorCode(e.errorCode));
> Logger.exception(e);
> break;
> }
> @@ -1281,6 +1375,8 @@
> gotHeuristic(resources[i], e.errorCode);
> break;
> default:
> + Logger.warning("XAException: tx=" + toString() + " errorCode=" +
> + getStringXAErrorCode(e.errorCode));
> Logger.exception(e);
> break;
> }
>
>
>
>