Package com.arjuna.ats.jta.xa

Examples of com.arjuna.ats.jta.xa.XAModifier


      throw new IllegalStateException(
          jtaLogger.logMesg
              .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.inactive"));
    }

    XAModifier theModifier = null;

    if (params != null)
    {
      if (params.length >= XAMODIFIER + 1)
      {
        if (params[XAMODIFIER] instanceof XAModifier)
        {
          theModifier = (XAModifier) params[XAMODIFIER];
        }
      }
    }

    try
    {
      /*
       * For each transaction we maintain a list of resources registered
       * with it. Each element on this list also contains a list of
       * threads which have registered this resource, and what their XID
       * was for that registration.
       */

      TxInfo info = null;

      /*
       * Have we seen this specific resource instance before? Do this
       * trawl first before checking the RM instance later. Saves time.
       */

      try
      {
        synchronized (this)
        {
          info = (TxInfo) _resources.get(xaRes);

          if (info == null)
          {
            /*
             * Null info means it's not in the main resources list,
             * but may be in the duplicates.
             */

            info = (TxInfo) _duplicateResources.get(xaRes);
          }
        }

        if (info != null)
        {
          switch (info.getState())
          {
          case TxInfo.ASSOCIATION_SUSPENDED:
          {
            /*
             * Have seen resource before, so do a resume. The
             * Resource instance will still be registered with the
             * transaction though.
             */

            int xaStartResume = ((theModifier == null) ? XAResource.TMRESUME
                : theModifier
                    .xaStartParameters(XAResource.TMRESUME));

            xaRes.start(info.xid(), xaStartResume);

            info.setState(TxInfo.ASSOCIATED);

            synchronized (this)
            {
              _suspendCount--;
            }

            return true; // already registered resource with this
            // transaction!
          }
          case TxInfo.ASSOCIATED:
          {
            /*
             * Already active on this transaction.
             */

            return true;
          }
          case TxInfo.NOT_ASSOCIATED:
          {
            /*
             * Resource was associated, but was presumably delisted.
             */

            int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
                : theModifier
                    .xaStartParameters(XAResource.TMJOIN));

            xaRes.start(info.xid(), xaStartJoin);

            info.setState(TxInfo.ASSOCIATED);

            return true;
          }
          default:
          {
            // Note: this exception will be caught by our catch
            // block

            throw new IllegalStateException(
                "TransactionImple.enlistResource - "
                    + jtaLogger.logMesg
                        .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.illresstate")
                    + ":" + info.getState());
          }
          }
        }
      }
      catch (IllegalStateException ex)
      {
        throw ex; // we threw it in the first place
      }
      catch (XAException exp)
      {
        if (info != null)
          info.setState(TxInfo.FAILED);

        if (jtaLogger.loggerI18N.isWarnEnabled())
        {
          jtaLogger.loggerI18N
              .warn(
                  "com.arjuna.ats.internal.jta.transaction.arjunacore.enlisterror",
                  new Object[]
                  { "TransactionImple.enlistResource",
                      XAHelper.printXAErrorCode(exp) });
        }

        return false;
      }

      // if (threadIsActive(xaRes))
      // return true; // this thread has already registered a resource for
      // this db

      /*
       * We definitely haven't seen this specific resource instance
       * before, but that doesn't mean that we haven't seen the RM it is
       * connected to.
       */

      Xid xid = null;
      TxInfo existingRM = isNewRM(xaRes);

      if (existingRM == null)
      {
        /*
         * New RM, so create xid with new branch.
         */

        boolean branchRequired = true;

        synchronized (this)
        {
          if (_resources.size() == 0)// first ever, so no need for
          // branch
          {
            // branchRequired = false;
            branchRequired = true;
          }
        }

        xid = createXid(branchRequired, theModifier);

        boolean associatedWork = false;
        int retry = 20;

        /*
         * If another process has (or is about to) create the same
         * transaction association then we will probably get a failure
         * during start with XAER_DUPID. We know this must be due to
         * another server, since we keep track of our own registrations.
         * So, if this happens we create a new transaction branch and
         * try again.
         *
         * To save time we could always just create branches by default.
         *
         * Is there a benefit to a zero branch?
         */

        while (!associatedWork)
        {
          try
          {
            if (_xaTransactionTimeoutEnabled)
            {
              int timeout = _theTransaction.getTimeout();

              if (timeout > 0)
              {
                try
                {
                  xaRes.setTransactionTimeout(timeout);
                }
                catch (XAException te)
                {
                  if (jtaLogger.loggerI18N.isWarnEnabled())
                  {
                    jtaLogger.loggerI18N
                        .warn(
                            "com.arjuna.ats.internal.jta.transaction.arjunacore.timeouterror",
                            new Object[]
                            {
                                "TransactionImple.enlistResource",
                                XAHelper
                                    .printXAErrorCode(te),
                                xid });
                  }
                }
              }
            }

            int xaStartNormal = ((theModifier == null) ? XAResource.TMNOFLAGS
                : theModifier
                    .xaStartParameters(XAResource.TMNOFLAGS));

            xaRes.start(xid, xaStartNormal);

            associatedWork = true;

            _resources.put(xaRes, new TxInfo(xid));
          }
          catch (XAException e)
          {
            // transaction already created by another server

            if ((e.errorCode == XAException.XAER_DUPID)
                || (e.errorCode == XAException.XAER_RMERR))
            {
              if (retry > 0)
                xid = createXid(true, theModifier);

              retry--;
            }
            else
            {
              /*
               * Can't do start, so set transaction to rollback
               * only.
               */

              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw e;
            }

            if (retry < 0)
            {
              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw new javax.transaction.SystemException(
                  "TransactionImple.enlistResource - XAResource.start "
                      + jtaLogger.logMesg
                          .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.couldnotregister")
                      + ": " + xid);
            }
          }
        }
      }
      else
      {
        /*
         * Have seen this RM before, so ignore this instance. The first
         * registered RM instance will be used to drive the transaction
         * completion. We add it to the duplicateResource list so we can
         * delist it correctly later though.
         */

        /*
         * Re-create xid.
         */

        xid = existingRM.xid();

        try
        {
          int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
              : theModifier.xaStartParameters(XAResource.TMJOIN));

          xaRes.start(xid, xaStartJoin);
        }
        catch (XAException ex)
        {
View Full Code Here


      throw new IllegalStateException(
          jtaLogger.logMesg
              .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.inactive"));
    }

    XAModifier theModifier = null;

    if (params != null)
    {
      if (params.length >= XAMODIFIER + 1)
      {
        if (params[XAMODIFIER] instanceof XAModifier)
        {
          theModifier = (XAModifier) params[XAMODIFIER];
        }
      }
    }

    try
    {
      /*
       * For each transaction we maintain a list of resources registered
       * with it. Each element on this list also contains a list of
       * threads which have registered this resource, and what their XID
       * was for that registration.
       */

      TxInfo info = null;

      /*
       * Have we seen this specific resource instance before? Do this
       * trawl first before checking the RM instance later. Saves time.
       */

      try
      {
        synchronized (this)
        {
          info = (TxInfo) _resources.get(xaRes);

          if (info == null)
          {
            /*
             * Null info means it's not in the main resources list,
             * but may be in the duplicates.
             */

            info = (TxInfo) _duplicateResources.get(xaRes);
          }
        }

        if (info != null)
        {
          switch (info.getState())
          {
          case TxInfo.ASSOCIATION_SUSPENDED:
          {
            /*
             * Have seen resource before, so do a resume. The
             * Resource instance will still be registered with the
             * transaction though.
             */

            int xaStartResume = ((theModifier == null) ? XAResource.TMRESUME
                : theModifier
                    .xaStartParameters(XAResource.TMRESUME));

            xaRes.start(info.xid(), xaStartResume);

            info.setState(TxInfo.ASSOCIATED);

            synchronized (this)
            {
              _suspendCount--;
            }

            return true; // already registered resource with this
            // transaction!
          }
          case TxInfo.ASSOCIATED:
          {
            /*
             * Already active on this transaction.
             */

            return true;
          }
          case TxInfo.NOT_ASSOCIATED:
          {
            /*
             * Resource was associated, but was presumably delisted.
             */

            int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
                : theModifier
                    .xaStartParameters(XAResource.TMJOIN));

            xaRes.start(info.xid(), xaStartJoin);

            info.setState(TxInfo.ASSOCIATED);

            return true;
          }
          default:
          {
            // Note: this exception will be caught by our catch
            // block

            throw new IllegalStateException(
                "TransactionImple.enlistResource - "
                    + jtaLogger.logMesg
                        .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.illresstate")
                    + ":" + info.getState());
          }
          }
        }
      }
      catch (IllegalStateException ex)
      {
        throw ex; // we threw it in the first place
      }
      catch (XAException exp)
      {
        if (info != null)
          info.setState(TxInfo.FAILED);

        if (jtaLogger.loggerI18N.isWarnEnabled())
        {
          jtaLogger.loggerI18N
              .warn(
                  "com.arjuna.ats.internal.jta.transaction.arjunacore.enlisterror",
                  new Object[]
                  { "TransactionImple.enlistResource",
                      XAHelper.printXAErrorCode(exp) });
        }

        return false;
      }

      // if (threadIsActive(xaRes))
      // return true; // this thread has already registered a resource for
      // this db

      /*
       * We definitely haven't seen this specific resource instance
       * before, but that doesn't mean that we haven't seen the RM it is
       * connected to.
       */

      Xid xid = null;
      TxInfo existingRM = isNewRM(xaRes);

      if (existingRM == null)
      {
        /*
         * New RM, so create xid with new branch.
         */

        boolean branchRequired = true;

        synchronized (this)
        {
          if (_resources.size() == 0)// first ever, so no need for
          // branch
          {
            // branchRequired = false;
            branchRequired = true;
          }
        }

        xid = createXid(branchRequired, theModifier);

        boolean associatedWork = false;
        int retry = 20;

        /*
         * If another process has (or is about to) create the same
         * transaction association then we will probably get a failure
         * during start with XAER_DUPID. We know this must be due to
         * another server, since we keep track of our own registrations.
         * So, if this happens we create a new transaction branch and
         * try again.
         *
         * To save time we could always just create branches by default.
         *
         * Is there a benefit to a zero branch?
         */

        while (!associatedWork)
        {
          try
          {
            if (_xaTransactionTimeoutEnabled)
            {
              int timeout = _theTransaction.getTimeout();

              if (timeout > 0)
              {
                try
                {
                  xaRes.setTransactionTimeout(timeout);
                }
                catch (XAException te)
                {
                  if (jtaLogger.loggerI18N.isWarnEnabled())
                  {
                    jtaLogger.loggerI18N
                        .warn(
                            "com.arjuna.ats.internal.jta.transaction.arjunacore.timeouterror",
                            new Object[]
                            {
                                "TransactionImple.enlistResource",
                                XAHelper
                                    .printXAErrorCode(te),
                                xid });
                  }
                }
              }
            }

            int xaStartNormal = ((theModifier == null) ? XAResource.TMNOFLAGS
                : theModifier
                    .xaStartParameters(XAResource.TMNOFLAGS));


                        // Pay attention now, this bit is hairy. We need to add a new AbstractRecord (XAResourceRecord)
                        // to the BasicAction, which will thereafter drive its completion. However, the transaction
                        // core is not directly XA aware, so it's our job to start the XAResource. Problem is, if
                        // adding the record fails, BasicAction will never end the resource via the XAResourceRecord,
                        // so we must do so directly.  start may fail due to dupl xid or other reason, and transactions
                        // may rollback async, for which reasons we can't call add before start.
                        // The xid will change on each pass of the loop, so we need to create a new record on each pass.
                        // The creation will fail in the case of multiple last resources being disallowed, in which
                        // case we don't call start on the resource at all. see JBTM-362 and JBTM-363
                        AbstractRecord abstractRecord = createRecord(xaRes, params, xid);
                        if(abstractRecord != null) {
                            xaRes.start(xid, xaStartNormal);
                            if(_theTransaction.add(abstractRecord) == AddOutcome.AR_ADDED) {
                                _resources.put(xaRes, new TxInfo(xid));
                                return true; // dive out, no need to set associatedWork = true;
                            } else {
                                // we called start on the resource, but _theTransaction did not accept it.
                                // we therefore have a mess which we must now clean up by ensuring the start is undone:
                                abstractRecord.topLevelAbort();
                            }
                        }

                        // if we get to here, something other than a failure of xaRes.start probably went wrong.
                        // so we don't loop and retry, we just give up.
                        markRollbackOnly();
                        return false;

          }
          catch (XAException e)
          {
            // transaction already created by another server

            if ((e.errorCode == XAException.XAER_DUPID)
                || (e.errorCode == XAException.XAER_RMERR))
            {
              if (retry > 0)
                xid = createXid(true, theModifier);

              retry--;
            }
            else
            {
              /*
               * Can't do start, so set transaction to rollback
               * only.
               */

              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw e;
            }

            if (retry < 0)
            {
              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw new javax.transaction.SystemException(
                  "TransactionImple.enlistResource - XAResource.start "
                      + jtaLogger.logMesg
                          .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.couldnotregister")
                      + ": " + xid);
            }
          }
        }
      }
      else
      {
        /*
         * Have seen this RM before, so ignore this instance. The first
         * registered RM instance will be used to drive the transaction
         * completion. We add it to the duplicateResource list so we can
         * delist it correctly later though.
         */

        /*
         * Re-create xid.
         */

        xid = existingRM.xid();

        try
        {
          int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
              : theModifier.xaStartParameters(XAResource.TMJOIN));

          xaRes.start(xid, xaStartJoin);
        }
        catch (XAException ex)
        {
View Full Code Here

      throw new IllegalStateException(
          jtaLogger.logMesg
              .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.inactive"));
    }

    XAModifier theModifier = null;

    if (params != null)
    {
      if (params.length >= XAMODIFIER + 1)
      {
        if (params[XAMODIFIER] instanceof XAModifier)
        {
          theModifier = (XAModifier) params[XAMODIFIER];
        }
      }
    }

    try
    {
      /*
       * For each transaction we maintain a list of resources registered
       * with it. Each element on this list also contains a list of
       * threads which have registered this resource, and what their XID
       * was for that registration.
       */

      TxInfo info = null;

      /*
       * Have we seen this specific resource instance before? Do this
       * trawl first before checking the RM instance later. Saves time.
       */

      try
      {
        synchronized (this)
        {
          info = (TxInfo) _resources.get(xaRes);

          if (info == null)
          {
            /*
             * Null info means it's not in the main resources list,
             * but may be in the duplicates.
             */

            info = (TxInfo) _duplicateResources.get(xaRes);
          }
        }

        if (info != null)
        {
          switch (info.getState())
          {
          case TxInfo.ASSOCIATION_SUSPENDED:
          {
            /*
             * Have seen resource before, so do a resume. The
             * Resource instance will still be registered with the
             * transaction though.
             */

            int xaStartResume = ((theModifier == null) ? XAResource.TMRESUME
                : theModifier
                    .xaStartParameters(XAResource.TMRESUME));

            xaRes.start(info.xid(), xaStartResume);

            info.setState(TxInfo.ASSOCIATED);

            synchronized (this)
            {
              _suspendCount--;
            }

            return true; // already registered resource with this
            // transaction!
          }
          case TxInfo.ASSOCIATED:
          {
            /*
             * Already active on this transaction.
             */

            return true;
          }
          case TxInfo.NOT_ASSOCIATED:
          {
            /*
             * Resource was associated, but was presumably delisted.
             */

            int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
                : theModifier
                    .xaStartParameters(XAResource.TMJOIN));

            xaRes.start(info.xid(), xaStartJoin);

            info.setState(TxInfo.ASSOCIATED);

            return true;
          }
          default:
          {
            // Note: this exception will be caught by our catch
            // block

            throw new IllegalStateException(
                "TransactionImple.enlistResource - "
                    + jtaLogger.logMesg
                        .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.illresstate")
                    + ":" + info.getState());
          }
          }
        }
      }
      catch (IllegalStateException ex)
      {
        throw ex; // we threw it in the first place
      }
      catch (XAException exp)
      {
        if (info != null)
          info.setState(TxInfo.FAILED);

        if (jtaLogger.loggerI18N.isWarnEnabled())
        {
          jtaLogger.loggerI18N
              .warn(
                  "com.arjuna.ats.internal.jta.transaction.arjunacore.enlisterror",
                  new Object[]
                  { "TransactionImple.enlistResource",
                      XAHelper.printXAErrorCode(exp) });
        }

        return false;
      }

      // if (threadIsActive(xaRes))
      // return true; // this thread has already registered a resource for
      // this db

      /*
       * We definitely haven't seen this specific resource instance
       * before, but that doesn't mean that we haven't seen the RM it is
       * connected to.
       */

      Xid xid = null;
      TxInfo existingRM = isNewRM(xaRes);

      if (existingRM == null)
      {
        /*
         * New RM, so create xid with new branch.
         */

        boolean branchRequired = true;

        synchronized (this)
        {
          if (_resources.size() == 0)// first ever, so no need for
          // branch
          {
            // branchRequired = false;
            branchRequired = true;
          }
        }

        xid = createXid(branchRequired, theModifier);

        boolean associatedWork = false;
        int retry = 20;

        /*
         * If another process has (or is about to) create the same
         * transaction association then we will probably get a failure
         * during start with XAER_DUPID. We know this must be due to
         * another server, since we keep track of our own registrations.
         * So, if this happens we create a new transaction branch and
         * try again.
         *
         * To save time we could always just create branches by default.
         *
         * Is there a benefit to a zero branch?
         */

        while (!associatedWork)
        {
          try
          {
            if (_xaTransactionTimeoutEnabled)
            {
              int timeout = _theTransaction.getTimeout();

              if (timeout > 0)
              {
                try
                {
                  xaRes.setTransactionTimeout(timeout);
                }
                catch (XAException te)
                {
                  if (jtaLogger.loggerI18N.isWarnEnabled())
                  {
                    jtaLogger.loggerI18N
                        .warn(
                            "com.arjuna.ats.internal.jta.transaction.arjunacore.timeouterror",
                            new Object[]
                            {
                                "TransactionImple.enlistResource",
                                XAHelper
                                    .printXAErrorCode(te),
                                xid });
                  }
                }
              }
            }

            int xaStartNormal = ((theModifier == null) ? XAResource.TMNOFLAGS
                : theModifier
                    .xaStartParameters(XAResource.TMNOFLAGS));


                        // Pay attention now, this bit is hairy. We need to add a new AbstractRecord (XAResourceRecord)
                        // to the BasicAction, which will thereafter drive its completion. However, the transaction
                        // core is not directly XA aware, so it's our job to start the XAResource. Problem is, if
                        // adding the record fails, BasicAction will never end the resource via the XAResourceRecord,
                        // so we must do so directly.  start may fail due to dupl xid or other reason, and transactions
                        // may rollback async, for which reasons we can't call add before start.
                        // The xid will change on each pass of the loop, so we need to create a new record on each pass.
                        // The creation will fail in the case of multiple last resources being disallowed, in which
                        // case we don't call start on the resource at all. see JBTM-362 and JBTM-363
                        AbstractRecord abstractRecord = createRecord(xaRes, params, xid);
                        if(abstractRecord != null) {
                            xaRes.start(xid, xaStartNormal);
                            if(_theTransaction.add(abstractRecord) == AddOutcome.AR_ADDED) {
                                _resources.put(xaRes, new TxInfo(xid));
                                return true; // dive out, no need to set associatedWork = true;
                            } else {
                                // we called start on the resource, but _theTransaction did not accept it.
                                // we therefore have a mess which we must now clean up by ensuring the start is undone:
                                abstractRecord.topLevelAbort();
                            }
                        }

                        // if we get to here, something other than a failure of xaRes.start probably went wrong.
                        // so we don't loop and retry, we just give up.
                        markRollbackOnly();
                        return false;

          }
          catch (XAException e)
          {
            // transaction already created by another server

            if ((e.errorCode == XAException.XAER_DUPID)
                || (e.errorCode == XAException.XAER_RMERR))
            {
              if (retry > 0)
                xid = createXid(true, theModifier);

              retry--;
            }
            else
            {
              /*
               * Can't do start, so set transaction to rollback
               * only.
               */

              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw e;
            }

            if (retry < 0)
            {
              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw new javax.transaction.SystemException(
                  "TransactionImple.enlistResource - XAResource.start "
                      + jtaLogger.logMesg
                          .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.couldnotregister")
                      + ": " + xid);
            }
          }
        }
      }
      else
      {
        /*
         * Have seen this RM before, so ignore this instance. The first
         * registered RM instance will be used to drive the transaction
         * completion. We add it to the duplicateResource list so we can
         * delist it correctly later though.
         */

        /*
         * Re-create xid.
         */

        xid = existingRM.xid();

        try
        {
          int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
              : theModifier.xaStartParameters(XAResource.TMJOIN));

          xaRes.start(xid, xaStartJoin);
        }
        catch (XAException ex)
        {
View Full Code Here

      throw new IllegalStateException(
          jtaLogger.logMesg
              .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.inactive"));
    }

    XAModifier theModifier = null;

    if (params != null)
    {
      if (params.length >= XAMODIFIER + 1)
      {
        if (params[XAMODIFIER] instanceof XAModifier)
        {
          theModifier = (XAModifier) params[XAMODIFIER];
        }
      }
    }

    try
    {
      /*
       * For each transaction we maintain a list of resources registered
       * with it. Each element on this list also contains a list of
       * threads which have registered this resource, and what their XID
       * was for that registration.
       */

      TxInfo info = null;

      /*
       * Have we seen this specific resource instance before? Do this
       * trawl first before checking the RM instance later. Saves time.
       */

      try
      {
        synchronized (this)
        {
          info = (TxInfo) _resources.get(xaRes);

          if (info == null)
          {
            /*
             * Null info means it's not in the main resources list,
             * but may be in the duplicates.
             */

            info = (TxInfo) _duplicateResources.get(xaRes);
          }
        }

        if (info != null)
        {
          switch (info.getState())
          {
          case TxInfo.ASSOCIATION_SUSPENDED:
          {
            /*
             * Have seen resource before, so do a resume. The
             * Resource instance will still be registered with the
             * transaction though.
             */

            int xaStartResume = ((theModifier == null) ? XAResource.TMRESUME
                : theModifier
                    .xaStartParameters(XAResource.TMRESUME));

            xaRes.start(info.xid(), xaStartResume);

            info.setState(TxInfo.ASSOCIATED);

            synchronized (this)
            {
              _suspendCount--;
            }

            return true; // already registered resource with this
            // transaction!
          }
          case TxInfo.ASSOCIATED:
          {
            /*
             * Already active on this transaction.
             */

            return true;
          }
          case TxInfo.NOT_ASSOCIATED:
          {
            /*
             * Resource was associated, but was presumably delisted.
             */

            int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
                : theModifier
                    .xaStartParameters(XAResource.TMJOIN));

            xaRes.start(info.xid(), xaStartJoin);

            info.setState(TxInfo.ASSOCIATED);

            return true;
          }
          default:
          {
            // Note: this exception will be caught by our catch
            // block

            throw new IllegalStateException(
                "TransactionImple.enlistResource - "
                    + jtaLogger.logMesg
                        .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.illresstate")
                    + ":" + info.getState());
          }
          }
        }
      }
      catch (IllegalStateException ex)
      {
        throw ex; // we threw it in the first place
      }
      catch (XAException exp)
      {
        if (info != null)
          info.setState(TxInfo.FAILED);

        if (jtaLogger.loggerI18N.isWarnEnabled())
        {
          jtaLogger.loggerI18N
              .warn(
                  "com.arjuna.ats.internal.jta.transaction.arjunacore.enlisterror",
                  new Object[]
                  { "TransactionImple.enlistResource",
                      XAHelper.printXAErrorCode(exp) });
        }

        return false;
      }

      // if (threadIsActive(xaRes))
      // return true; // this thread has already registered a resource for
      // this db

      /*
       * We definitely haven't seen this specific resource instance
       * before, but that doesn't mean that we haven't seen the RM it is
       * connected to.
       */

      Xid xid = null;
      TxInfo existingRM = isNewRM(xaRes);

      if (existingRM == null)
      {
        /*
         * New RM, so create xid with new branch.
         */

        boolean branchRequired = true;

        synchronized (this)
        {
          if (_resources.size() == 0)// first ever, so no need for
          // branch
          {
            // branchRequired = false;
            branchRequired = true;
          }
        }

        xid = createXid(branchRequired, theModifier);

        boolean associatedWork = false;
        int retry = 20;

        /*
         * If another process has (or is about to) create the same
         * transaction association then we will probably get a failure
         * during start with XAER_DUPID. We know this must be due to
         * another server, since we keep track of our own registrations.
         * So, if this happens we create a new transaction branch and
         * try again.
         *
         * To save time we could always just create branches by default.
         *
         * Is there a benefit to a zero branch?
         */

        while (!associatedWork)
        {
          try
          {
            if (_xaTransactionTimeoutEnabled)
            {
              int timeout = _theTransaction.getTimeout();

              if (timeout > 0)
              {
                try
                {
                  xaRes.setTransactionTimeout(timeout);
                }
                catch (XAException te)
                {
                  if (jtaLogger.loggerI18N.isWarnEnabled())
                  {
                    jtaLogger.loggerI18N
                        .warn(
                            "com.arjuna.ats.internal.jta.transaction.arjunacore.timeouterror",
                            new Object[]
                            {
                                "TransactionImple.enlistResource",
                                XAHelper
                                    .printXAErrorCode(te),
                                xid }, te);
                  }
                }
              }
            }

            int xaStartNormal = ((theModifier == null) ? XAResource.TMNOFLAGS
                : theModifier
                    .xaStartParameters(XAResource.TMNOFLAGS));


                        // Pay attention now, this bit is hairy. We need to add a new AbstractRecord (XAResourceRecord)
                        // to the BasicAction, which will thereafter drive its completion. However, the transaction
                        // core is not directly XA aware, so it's our job to start the XAResource. Problem is, if
                        // adding the record fails, BasicAction will never end the resource via the XAResourceRecord,
                        // so we must do so directly.  start may fail due to dupl xid or other reason, and transactions
                        // may rollback async, for which reasons we can't call add before start.
                        // The xid will change on each pass of the loop, so we need to create a new record on each pass.
                        // The creation will fail in the case of multiple last resources being disallowed, in which
                        // case we don't call start on the resource at all. see JBTM-362 and JBTM-363
                        AbstractRecord abstractRecord = createRecord(xaRes, params, xid);
                        if(abstractRecord != null) {
                            xaRes.start(xid, xaStartNormal);
                            if(_theTransaction.add(abstractRecord) == AddOutcome.AR_ADDED) {
                                _resources.put(xaRes, new TxInfo(xid));
                                return true; // dive out, no need to set associatedWork = true;
                            } else {
                                // we called start on the resource, but _theTransaction did not accept it.
                                // we therefore have a mess which we must now clean up by ensuring the start is undone:
                                abstractRecord.topLevelAbort();
                            }
                        }

                        // if we get to here, something other than a failure of xaRes.start probably went wrong.
                        // so we don't loop and retry, we just give up.
                        markRollbackOnly();
                        return false;

          }
          catch (XAException e)
          {
            // transaction already created by another server

            if ((e.errorCode == XAException.XAER_DUPID)
                || (e.errorCode == XAException.XAER_RMERR))
            {
              if (retry > 0)
                xid = createXid(true, theModifier);

              retry--;
            }
            else
            {
              /*
               * Can't do start, so set transaction to rollback
               * only.
               */

              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw e;
            }

            if (retry < 0)
            {
              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw new javax.transaction.SystemException(
                  "TransactionImple.enlistResource - XAResource.start "
                      + jtaLogger.logMesg
                          .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.couldnotregister")
                      + ": " + xid);
            }
          }
        }
      }
      else
      {
        /*
         * Have seen this RM before, so ignore this instance. The first
         * registered RM instance will be used to drive the transaction
         * completion. We add it to the duplicateResource list so we can
         * delist it correctly later though.
         */

        /*
         * Re-create xid.
         */

        xid = existingRM.xid();

        try
        {
          int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
              : theModifier.xaStartParameters(XAResource.TMJOIN));

          xaRes.start(xid, xaStartJoin);
        }
        catch (XAException ex)
        {
View Full Code Here

/*  550 */       break;
/*      */     default:
/*  552 */       throw new IllegalStateException(jtaLogger.logMesg.getString("com.arjuna.ats.internal.jta.transaction.arjunacore.inactive"));
/*      */     }
/*      */
/*  557 */     XAModifier theModifier = null;
/*      */
/*  559 */     if (params != null)
/*      */     {
/*  561 */       if (params.length >= 2)
/*      */       {
/*  563 */         if ((params[1] instanceof XAModifier))
/*      */         {
/*  565 */           theModifier = (XAModifier)params[1];
/*      */         }
/*      */
/*      */       }
/*      */
/*      */     }
/*      */
/*      */     try
/*      */     {
/*  579 */       TxInfo info = null;
/*      */       try
/*      */       {
/*  588 */         synchronized (this)
/*      */         {
/*  590 */           info = (TxInfo)this._resources.get(xaRes);
/*      */
/*  592 */           if (info == null)
/*      */           {
/*  599 */             info = (TxInfo)this._duplicateResources.get(xaRes);
/*      */           }
/*      */         }
/*      */
/*  603 */         if (info != null)
/*      */         {
/*  605 */           switch (info.getState())
/*      */           {
/*      */           case 2:
/*  615 */             int xaStartResume = theModifier == null ? 134217728 : theModifier.xaStartParameters(134217728);
/*      */
/*  619 */             xaRes.start(info.xid(), xaStartResume);
/*      */
/*  621 */             info.setState(0);
/*      */
/*  623 */             synchronized (this)
/*      */             {
/*  625 */               this._suspendCount -= 1;
/*      */             }
/*      */
/*  628 */             return true;
/*      */           case 0:
/*  637 */             return true;
/*      */           case 1:
/*  645 */             int xaStartJoin = theModifier == null ? 2097152 : theModifier.xaStartParameters(2097152);
/*      */
/*  649 */             xaRes.start(info.xid(), xaStartJoin);
/*      */
/*  651 */             info.setState(0);
/*      */
/*  653 */             return true;
/*      */           }
/*      */
/*  660 */           throw new IllegalStateException("TransactionImple.enlistResource - " + jtaLogger.logMesg.getString("com.arjuna.ats.internal.jta.transaction.arjunacore.illresstate") + ":" + info.getState());
/*      */         }
/*      */
/*      */       }
/*      */       catch (IllegalStateException ex)
/*      */       {
/*  671 */         throw ex;
/*      */       }
/*      */       catch (XAException exp)
/*      */       {
/*  675 */         if (info != null) {
/*  676 */           info.setState(3);
/*      */         }
/*  678 */         if (jtaLogger.loggerI18N.isWarnEnabled())
/*      */         {
/*  680 */           jtaLogger.loggerI18N.warn("com.arjuna.ats.internal.jta.transaction.arjunacore.enlisterror", new Object[] { "TransactionImple.enlistResource", XAHelper.printXAErrorCode(exp) });
/*      */         }
/*      */
/*  688 */         return false;
/*      */       }
/*      */
/*  701 */       Xid xid = null;
/*  702 */       TxInfo existingRM = isNewRM(xaRes);
/*      */
/*  704 */       if (existingRM == null)
/*      */       {
/*  710 */         boolean branchRequired = true;
/*      */
/*  712 */         synchronized (this)
/*      */         {
/*  714 */           if (this._resources.size() == 0)
/*      */           {
/*  718 */             branchRequired = true;
/*      */           }
/*      */         }
/*      */
/*  722 */         xid = createXid(branchRequired, theModifier);
/*      */
/*  724 */         boolean associatedWork = false;
/*  725 */         int retry = 20;
/*      */
/*  740 */         while (!associatedWork)
/*      */         {
/*      */           try
/*      */           {
/*  744 */             if (this._xaTransactionTimeoutEnabled)
/*      */             {
/*  746 */               int timeout = this._theTransaction.getTimeout();
/*      */
/*  748 */               if (timeout > 0)
/*      */               {
/*      */                 try
/*      */                 {
/*  752 */                   xaRes.setTransactionTimeout(timeout);
/*      */                 }
/*      */                 catch (XAException te)
/*      */                 {
/*  756 */                   if (jtaLogger.loggerI18N.isWarnEnabled())
/*      */                   {
/*  758 */                     jtaLogger.loggerI18N.warn("com.arjuna.ats.internal.jta.transaction.arjunacore.timeouterror", new Object[] { "TransactionImple.enlistResource", XAHelper.printXAErrorCode(te), xid });
/*      */                   }
/*      */
/*      */                 }
/*      */
/*      */               }
/*      */
/*      */             }
/*      */
/*  772 */             int xaStartNormal = theModifier == null ? 0 : theModifier.xaStartParameters(0);
/*      */
/*  776 */             xaRes.start(xid, xaStartNormal);
/*      */
/*  778 */             associatedWork = true;
/*      */
/*  780 */             this._resources.put(xaRes, new TxInfo(xid));
/*      */           }
/*      */           catch (XAException e)
/*      */           {
/*  786 */             if ((e.errorCode == -8) || (e.errorCode == -3))
/*      */             {
/*  789 */               if (retry > 0) {
/*  790 */                 xid = createXid(true, theModifier);
/*      */               }
/*  792 */               retry--;
/*      */             }
/*      */             else
/*      */             {
/*  801 */               if (jtaLogger.loggerI18N.isWarnEnabled())
/*      */               {
/*  803 */                 jtaLogger.loggerI18N.warn("com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror", new Object[] { "TransactionImple.enlistResource", XAHelper.printXAErrorCode(e), xid });
/*      */               }
/*      */
/*  814 */               markRollbackOnly();
/*      */
/*  816 */               throw e;
/*      */             }
/*      */           }
/*  819 */           if (retry < 0)
/*      */           {
/*  821 */             if (jtaLogger.loggerI18N.isWarnEnabled())
/*      */             {
/*  823 */               jtaLogger.loggerI18N.warn("com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror", new Object[] { "TransactionImple.enlistResource", XAHelper.printXAErrorCode(e), xid });
/*      */             }
/*      */
/*  834 */             markRollbackOnly();
/*      */
/*  836 */             throw new SystemException("TransactionImple.enlistResource - XAResource.start " + jtaLogger.logMesg.getString("com.arjuna.ats.internal.jta.transaction.arjunacore.couldnotregister") + ": " + xid);
/*      */           }
/*      */
/*      */         }
/*      */
/*      */       }
/*      */       else
/*      */       {
/*  858 */         xid = existingRM.xid();
/*      */         try
/*      */         {
/*  862 */           int xaStartJoin = theModifier == null ? 2097152 : theModifier.xaStartParameters(2097152);
/*      */
/*  865 */           xaRes.start(xid, xaStartJoin);
/*      */         }
/*      */         catch (XAException ex)
/*      */         {
View Full Code Here

      throw new IllegalStateException(
          jtaLogger.logMesg
              .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.inactive"));
    }

    XAModifier theModifier = null;

    if (params != null)
    {
      if (params.length >= XAMODIFIER + 1)
      {
        if (params[XAMODIFIER] instanceof XAModifier)
        {
          theModifier = (XAModifier) params[XAMODIFIER];
        }
      }
    }

    try
    {
      /*
       * For each transaction we maintain a list of resources registered
       * with it. Each element on this list also contains a list of
       * threads which have registered this resource, and what their XID
       * was for that registration.
       */

      TxInfo info = null;

      /*
       * Have we seen this specific resource instance before? Do this
       * trawl first before checking the RM instance later. Saves time.
       */

      try
      {
        synchronized (this)
        {
          info = (TxInfo) _resources.get(xaRes);

          if (info == null)
          {
            /*
             * Null info means it's not in the main resources list,
             * but may be in the duplicates.
             */

            info = (TxInfo) _duplicateResources.get(xaRes);
          }
        }

        if (info != null)
        {
          switch (info.getState())
          {
          case TxInfo.ASSOCIATION_SUSPENDED:
          {
            /*
             * Have seen resource before, so do a resume. The
             * Resource instance will still be registered with the
             * transaction though.
             */

            int xaStartResume = ((theModifier == null) ? XAResource.TMRESUME
                : theModifier
                    .xaStartParameters(XAResource.TMRESUME));

            xaRes.start(info.xid(), xaStartResume);

            info.setState(TxInfo.ASSOCIATED);

            synchronized (this)
            {
              _suspendCount--;
            }

            return true; // already registered resource with this
            // transaction!
          }
          case TxInfo.ASSOCIATED:
          {
            /*
             * Already active on this transaction.
             */

            return true;
          }
          case TxInfo.NOT_ASSOCIATED:
          {
            /*
             * Resource was associated, but was presumably delisted.
             */

            int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
                : theModifier
                    .xaStartParameters(XAResource.TMJOIN));

            xaRes.start(info.xid(), xaStartJoin);

            info.setState(TxInfo.ASSOCIATED);

            return true;
          }
          default:
          {
            // Note: this exception will be caught by our catch
            // block

            throw new IllegalStateException(
                "TransactionImple.enlistResource - "
                    + jtaLogger.logMesg
                        .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.illresstate")
                    + ":" + info.getState());
          }
          }
        }
      }
      catch (IllegalStateException ex)
      {
        throw ex; // we threw it in the first place
      }
      catch (XAException exp)
      {
        if (info != null)
          info.setState(TxInfo.FAILED);

        if (jtaLogger.loggerI18N.isWarnEnabled())
        {
          jtaLogger.loggerI18N
              .warn(
                  "com.arjuna.ats.internal.jta.transaction.arjunacore.enlisterror",
                  new Object[]
                  { "TransactionImple.enlistResource",
                      XAHelper.printXAErrorCode(exp) });
        }

        return false;
      }

      // if (threadIsActive(xaRes))
      // return true; // this thread has already registered a resource for
      // this db

      /*
       * We definitely haven't seen this specific resource instance
       * before, but that doesn't mean that we haven't seen the RM it is
       * connected to.
       */

      Xid xid = null;
      TxInfo existingRM = isNewRM(xaRes);

      if (existingRM == null)
      {
        /*
         * New RM, so create xid with new branch.
         */

        boolean branchRequired = true;

        synchronized (this)
        {
          if (_resources.size() == 0)// first ever, so no need for
          // branch
          {
            // branchRequired = false;
            branchRequired = true;
          }
        }

        xid = createXid(branchRequired, theModifier);

        boolean associatedWork = false;
        int retry = 20;

        /*
         * If another process has (or is about to) create the same
         * transaction association then we will probably get a failure
         * during start with XAER_DUPID. We know this must be due to
         * another server, since we keep track of our own registrations.
         * So, if this happens we create a new transaction branch and
         * try again.
         *
         * To save time we could always just create branches by default.
         *
         * Is there a benefit to a zero branch?
         */

        while (!associatedWork)
        {
          try
          {
            if (_xaTransactionTimeoutEnabled)
            {
              int timeout = _theTransaction.getTimeout();

              if (timeout > 0)
              {
                try
                {
                  xaRes.setTransactionTimeout(timeout);
                }
                catch (XAException te)
                {
                  if (jtaLogger.loggerI18N.isWarnEnabled())
                  {
                    jtaLogger.loggerI18N
                        .warn(
                            "com.arjuna.ats.internal.jta.transaction.arjunacore.timeouterror",
                            new Object[]
                            {
                                "TransactionImple.enlistResource",
                                XAHelper
                                    .printXAErrorCode(te),
                                xid });
                  }
                }
              }
            }

            int xaStartNormal = ((theModifier == null) ? XAResource.TMNOFLAGS
                : theModifier
                    .xaStartParameters(XAResource.TMNOFLAGS));


                        // Pay attention now, this bit is hairy. We need to add a new AbstractRecord (XAResourceRecord)
                        // to the BasicAction, which will thereafter drive its completion. However, the transaction
                        // core is not directly XA aware, so it's our job to start the XAResource. Problem is, if
                        // adding the record fails, BasicAction will never end the resource via the XAResourceRecord,
                        // so we must do so directly.  start may fail due to dupl xid or other reason, and transactions
                        // may rollback async, for which reasons we can't call add before start.
                        // The xid will change on each pass of the loop, so we need to create a new record on each pass.
                        // The creation will fail in the case of multiple last resources being disallowed, in which
                        // case we don't call start on the resource at all. see JBTM-362 and JBTM-363
                        AbstractRecord abstractRecord = createRecord(xaRes, params, xid);
                        if(abstractRecord != null) {
                            xaRes.start(xid, xaStartNormal);
                            if(_theTransaction.add(abstractRecord) == AddOutcome.AR_ADDED) {
                                _resources.put(xaRes, new TxInfo(xid));
                                return true; // dive out, no need to set associatedWork = true;
                            } else {
                                // we called start on the resource, but _theTransaction did not accept it.
                                // we therefore have a mess which we must now clean up by ensuring the start is undone:
                                abstractRecord.topLevelAbort();
                            }
                        }

                        // if we get to here, something other than a failure of xaRes.start probably went wrong.
                        // so we don't loop and retry, we just give up.
                        markRollbackOnly();
                        return false;

          }
          catch (XAException e)
          {
            // transaction already created by another server

            if ((e.errorCode == XAException.XAER_DUPID)
                || (e.errorCode == XAException.XAER_RMERR))
            {
              if (retry > 0)
                xid = createXid(true, theModifier);

              retry--;
            }
            else
            {
              /*
               * Can't do start, so set transaction to rollback
               * only.
               */

              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw e;
            }

            if (retry < 0)
            {
              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw new javax.transaction.SystemException(
                  "TransactionImple.enlistResource - XAResource.start "
                      + jtaLogger.logMesg
                          .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.couldnotregister")
                      + ": " + xid);
            }
          }
        }
      }
      else
      {
        /*
         * Have seen this RM before, so ignore this instance. The first
         * registered RM instance will be used to drive the transaction
         * completion. We add it to the duplicateResource list so we can
         * delist it correctly later though.
         */

        /*
         * Re-create xid.
         */

        xid = existingRM.xid();

        try
        {
          int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
              : theModifier.xaStartParameters(XAResource.TMJOIN));

          xaRes.start(xid, xaStartJoin);
        }
        catch (XAException ex)
        {
View Full Code Here

      throw new IllegalStateException(
          jtaLogger.logMesg
              .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.inactive"));
    }

    XAModifier theModifier = null;

    if (params != null)
    {
      if (params.length >= XAMODIFIER + 1)
      {
        if (params[XAMODIFIER] instanceof XAModifier)
        {
          theModifier = (XAModifier) params[XAMODIFIER];
        }
      }
    }

    try
    {
      /*
       * For each transaction we maintain a list of resources registered
       * with it. Each element on this list also contains a list of
       * threads which have registered this resource, and what their XID
       * was for that registration.
       */

      TxInfo info = null;

      /*
       * Have we seen this specific resource instance before? Do this
       * trawl first before checking the RM instance later. Saves time.
       */

      try
      {
        synchronized (this)
        {
          info = (TxInfo) _resources.get(xaRes);

          if (info == null)
          {
            /*
             * Null info means it's not in the main resources list,
             * but may be in the duplicates.
             */

            info = (TxInfo) _duplicateResources.get(xaRes);
          }
        }

        if (info != null)
        {
          switch (info.getState())
          {
          case TxInfo.ASSOCIATION_SUSPENDED:
          {
            /*
             * Have seen resource before, so do a resume. The
             * Resource instance will still be registered with the
             * transaction though.
             */

            int xaStartResume = ((theModifier == null) ? XAResource.TMRESUME
                : theModifier
                    .xaStartParameters(XAResource.TMRESUME));

            xaRes.start(info.xid(), xaStartResume);

            info.setState(TxInfo.ASSOCIATED);

            synchronized (this)
            {
              _suspendCount--;
            }

            return true; // already registered resource with this
            // transaction!
          }
          case TxInfo.ASSOCIATED:
          {
            /*
             * Already active on this transaction.
             */

            return true;
          }
          case TxInfo.NOT_ASSOCIATED:
          {
            /*
             * Resource was associated, but was presumably delisted.
             */

            int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
                : theModifier
                    .xaStartParameters(XAResource.TMJOIN));

            xaRes.start(info.xid(), xaStartJoin);

            info.setState(TxInfo.ASSOCIATED);

            return true;
          }
          default:
          {
            // Note: this exception will be caught by our catch
            // block

            throw new IllegalStateException(
                "TransactionImple.enlistResource - "
                    + jtaLogger.logMesg
                        .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.illresstate")
                    + ":" + info.getState());
          }
          }
        }
      }
      catch (IllegalStateException ex)
      {
        throw ex; // we threw it in the first place
      }
      catch (XAException exp)
      {
        if (info != null)
          info.setState(TxInfo.FAILED);

        if (jtaLogger.loggerI18N.isWarnEnabled())
        {
          jtaLogger.loggerI18N
              .warn(
                  "com.arjuna.ats.internal.jta.transaction.arjunacore.enlisterror",
                  new Object[]
                  { "TransactionImple.enlistResource",
                      XAHelper.printXAErrorCode(exp) });
        }

        return false;
      }

      // if (threadIsActive(xaRes))
      // return true; // this thread has already registered a resource for
      // this db

      /*
       * We definitely haven't seen this specific resource instance
       * before, but that doesn't mean that we haven't seen the RM it is
       * connected to.
       */

      Xid xid = null;
      TxInfo existingRM = isNewRM(xaRes);

      if (existingRM == null)
      {
        /*
         * New RM, so create xid with new branch.
         */

        boolean branchRequired = true;

        synchronized (this)
        {
          if (_resources.size() == 0)// first ever, so no need for
          // branch
          {
            // branchRequired = false;
            branchRequired = true;
          }
        }

        xid = createXid(branchRequired, theModifier);

        boolean associatedWork = false;
        int retry = 20;

        /*
         * If another process has (or is about to) create the same
         * transaction association then we will probably get a failure
         * during start with XAER_DUPID. We know this must be due to
         * another server, since we keep track of our own registrations.
         * So, if this happens we create a new transaction branch and
         * try again.
         *
         * To save time we could always just create branches by default.
         *
         * Is there a benefit to a zero branch?
         */

        while (!associatedWork)
        {
          try
          {
            if (_xaTransactionTimeoutEnabled)
            {
              int timeout = _theTransaction.getTimeout();

              if (timeout > 0)
              {
                try
                {
                  xaRes.setTransactionTimeout(timeout);
                }
                catch (XAException te)
                {
                  if (jtaLogger.loggerI18N.isWarnEnabled())
                  {
                    jtaLogger.loggerI18N
                        .warn(
                            "com.arjuna.ats.internal.jta.transaction.arjunacore.timeouterror",
                            new Object[]
                            {
                                "TransactionImple.enlistResource",
                                XAHelper
                                    .printXAErrorCode(te),
                                xid });
                  }
                }
              }
            }

            int xaStartNormal = ((theModifier == null) ? XAResource.TMNOFLAGS
                : theModifier
                    .xaStartParameters(XAResource.TMNOFLAGS));


                        // Pay attention now, this bit is hairy. We need to add a new AbstractRecord (XAResourceRecord)
                        // to the BasicAction, which will thereafter drive its completion. However, the transaction
                        // core is not directly XA aware, so it's our job to start the XAResource. Problem is, if
                        // adding the record fails, BasicAction will never end the resource via the XAResourceRecord,
                        // so we must do so directly.  start may fail due to dupl xid or other reason, and transactions
                        // may rollback async, for which reasons we can't call add before start.
                        // The xid will change on each pass of the loop, so we need to create a new record on each pass.
                        // The add will fail in the case of multiple last resources being disallowed
                        // see JBTM-362 and JBTM-363
                        AbstractRecord abstractRecord = createRecord(xaRes, params, xid);
                        if(abstractRecord != null) {
                            xaRes.start(xid, xaStartNormal);
                            if(_theTransaction.add(abstractRecord) == AddOutcome.AR_ADDED) {
                                _resources.put(xaRes, new TxInfo(xid));
                                return true; // dive out, no need to set associatedWork = true;
                            } else {
                                // we called start on the resource, but _theTransaction did not accept it.
                                // we therefore have a mess which we must now clean up by ensuring the start is undone:
                                abstractRecord.topLevelAbort();
                            }
                        }

                        // if we get to here, something other than a failure of xaRes.start probably went wrong.
                        // so we don't loop and retry, we just give up.
                        markRollbackOnly();
                        return false;

          }
          catch (XAException e)
          {
            // transaction already created by another server

            if ((e.errorCode == XAException.XAER_DUPID)
                || (e.errorCode == XAException.XAER_RMERR))
            {
              if (retry > 0)
                xid = createXid(true, theModifier);

              retry--;
            }
            else
            {
              /*
               * Can't do start, so set transaction to rollback
               * only.
               */

              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw e;
            }

            if (retry < 0)
            {
              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw new javax.transaction.SystemException(
                  "TransactionImple.enlistResource - XAResource.start "
                      + jtaLogger.logMesg
                          .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.couldnotregister")
                      + ": " + xid);
            }
          }
        }
      }
      else
      {
        /*
         * Have seen this RM before, so ignore this instance. The first
         * registered RM instance will be used to drive the transaction
         * completion. We add it to the duplicateResource list so we can
         * delist it correctly later though.
         */

        /*
         * Re-create xid.
         */

        xid = existingRM.xid();

        try
        {
          int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
              : theModifier.xaStartParameters(XAResource.TMJOIN));

          xaRes.start(xid, xaStartJoin);
        }
        catch (XAException ex)
        {
View Full Code Here

      throw new IllegalStateException(
          jtaLogger.logMesg
              .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.inactive"));
    }

    XAModifier theModifier = null;

    if (params != null)
    {
      if (params.length >= XAMODIFIER + 1)
      {
        if (params[XAMODIFIER] instanceof XAModifier)
        {
          theModifier = (XAModifier) params[XAMODIFIER];
        }
      }
    }

    try
    {
      /*
       * For each transaction we maintain a list of resources registered
       * with it. Each element on this list also contains a list of
       * threads which have registered this resource, and what their XID
       * was for that registration.
       */

      TxInfo info = null;

      /*
       * Have we seen this specific resource instance before? Do this
       * trawl first before checking the RM instance later. Saves time.
       */

      try
      {
        synchronized (this)
        {
          info = (TxInfo) _resources.get(xaRes);

          if (info == null)
          {
            /*
             * Null info means it's not in the main resources list,
             * but may be in the duplicates.
             */

            info = (TxInfo) _duplicateResources.get(xaRes);
          }
        }

        if (info != null)
        {
          switch (info.getState())
          {
          case TxInfo.ASSOCIATION_SUSPENDED:
          {
            /*
             * Have seen resource before, so do a resume. The
             * Resource instance will still be registered with the
             * transaction though.
             */

            int xaStartResume = ((theModifier == null) ? XAResource.TMRESUME
                : theModifier
                    .xaStartParameters(XAResource.TMRESUME));

            xaRes.start(info.xid(), xaStartResume);

            info.setState(TxInfo.ASSOCIATED);

            synchronized (this)
            {
              _suspendCount--;
            }

            return true; // already registered resource with this
            // transaction!
          }
          case TxInfo.ASSOCIATED:
          {
            /*
             * Already active on this transaction.
             */

            return true;
          }
          case TxInfo.NOT_ASSOCIATED:
          {
            /*
             * Resource was associated, but was presumably delisted.
             */

            int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
                : theModifier
                    .xaStartParameters(XAResource.TMJOIN));

            xaRes.start(info.xid(), xaStartJoin);

            info.setState(TxInfo.ASSOCIATED);

            return true;
          }
          default:
          {
            // Note: this exception will be caught by our catch
            // block

            throw new IllegalStateException(
                "TransactionImple.enlistResource - "
                    + jtaLogger.logMesg
                        .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.illresstate")
                    + ":" + info.getState());
          }
          }
        }
      }
      catch (IllegalStateException ex)
      {
        throw ex; // we threw it in the first place
      }
      catch (XAException exp)
      {
        if (info != null)
          info.setState(TxInfo.FAILED);

        if (jtaLogger.loggerI18N.isWarnEnabled())
        {
          jtaLogger.loggerI18N
              .warn(
                  "com.arjuna.ats.internal.jta.transaction.arjunacore.enlisterror",
                  new Object[]
                  { "TransactionImple.enlistResource",
                      XAHelper.printXAErrorCode(exp) });
        }

        return false;
      }

      // if (threadIsActive(xaRes))
      // return true; // this thread has already registered a resource for
      // this db

      /*
       * We definitely haven't seen this specific resource instance
       * before, but that doesn't mean that we haven't seen the RM it is
       * connected to.
       */

      Xid xid = null;
      TxInfo existingRM = isNewRM(xaRes);

      if (existingRM == null)
      {
        /*
         * New RM, so create xid with new branch.
         */

        boolean branchRequired = true;

        synchronized (this)
        {
          if (_resources.size() == 0)// first ever, so no need for
          // branch
          {
            // branchRequired = false;
            branchRequired = true;
          }
        }

        xid = createXid(branchRequired, theModifier);

        boolean associatedWork = false;
        int retry = 20;

        /*
         * If another process has (or is about to) create the same
         * transaction association then we will probably get a failure
         * during start with XAER_DUPID. We know this must be due to
         * another server, since we keep track of our own registrations.
         * So, if this happens we create a new transaction branch and
         * try again.
         *
         * To save time we could always just create branches by default.
         *
         * Is there a benefit to a zero branch?
         */

        while (!associatedWork)
        {
          try
          {
            if (_xaTransactionTimeoutEnabled)
            {
              int timeout = _theTransaction.getTimeout();

              if (timeout > 0)
              {
                try
                {
                  xaRes.setTransactionTimeout(timeout);
                }
                catch (XAException te)
                {
                  if (jtaLogger.loggerI18N.isWarnEnabled())
                  {
                    jtaLogger.loggerI18N
                        .warn(
                            "com.arjuna.ats.internal.jta.transaction.arjunacore.timeouterror",
                            new Object[]
                            {
                                "TransactionImple.enlistResource",
                                XAHelper
                                    .printXAErrorCode(te),
                                xid });
                  }
                }
              }
            }

            int xaStartNormal = ((theModifier == null) ? XAResource.TMNOFLAGS
                : theModifier
                    .xaStartParameters(XAResource.TMNOFLAGS));


                        // Pay attention now, this bit is hairy. We need to add a new AbstractRecord (XAResourceRecord)
                        // to the BasicAction, which will thereafter drive its completion. However, the transaction
                        // core is not directly XA aware, so it's our job to start the XAResource. Problem is, if
                        // adding the record fails, BasicAction will never end the resource via the XAResourceRecord,
                        // so we must do so directly.  start may fail due to dupl xid or other reason, and transactions
                        // may rollback async, for which reasons we can't call add before start.
                        // The xid will change on each pass of the loop, so we need to create a new record on each pass.
                        // The creation will fail in the case of multiple last resources being disallowed, in which
                        // case we don't call start on the resource at all. see JBTM-362 and JBTM-363
                        AbstractRecord abstractRecord = createRecord(xaRes, params, xid);
                        if(abstractRecord != null) {
                            xaRes.start(xid, xaStartNormal);
                            if(_theTransaction.add(abstractRecord) == AddOutcome.AR_ADDED) {
                                _resources.put(xaRes, new TxInfo(xid));
                                return true; // dive out, no need to set associatedWork = true;
                            } else {
                                // we called start on the resource, but _theTransaction did not accept it.
                                // we therefore have a mess which we must now clean up by ensuring the start is undone:
                                abstractRecord.topLevelAbort();
                            }
                        }

                        // if we get to here, something other than a failure of xaRes.start probably went wrong.
                        // so we don't loop and retry, we just give up.
                        markRollbackOnly();
                        return false;

          }
          catch (XAException e)
          {
            // transaction already created by another server

            if ((e.errorCode == XAException.XAER_DUPID)
                || (e.errorCode == XAException.XAER_RMERR))
            {
              if (retry > 0)
                xid = createXid(true, theModifier);

              retry--;
            }
            else
            {
              /*
               * Can't do start, so set transaction to rollback
               * only.
               */

              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw e;
            }

            if (retry < 0)
            {
              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw new javax.transaction.SystemException(
                  "TransactionImple.enlistResource - XAResource.start "
                      + jtaLogger.logMesg
                          .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.couldnotregister")
                      + ": " + xid);
            }
          }
        }
      }
      else
      {
        /*
         * Have seen this RM before, so ignore this instance. The first
         * registered RM instance will be used to drive the transaction
         * completion. We add it to the duplicateResource list so we can
         * delist it correctly later though.
         */

        /*
         * Re-create xid.
         */

        xid = existingRM.xid();

        try
        {
          int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
              : theModifier.xaStartParameters(XAResource.TMJOIN));

          xaRes.start(xid, xaStartJoin);
        }
        catch (XAException ex)
        {
View Full Code Here

      throw new IllegalStateException(
          jtaLogger.logMesg
              .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.inactive"));
    }

    XAModifier theModifier = null;

    if (params != null)
    {
      if (params.length >= XAMODIFIER + 1)
      {
        if (params[XAMODIFIER] instanceof XAModifier)
        {
          theModifier = (XAModifier) params[XAMODIFIER];
        }
      }
    }

    try
    {
      /*
       * For each transaction we maintain a list of resources registered
       * with it. Each element on this list also contains a list of
       * threads which have registered this resource, and what their XID
       * was for that registration.
       */

      TxInfo info = null;

      /*
       * Have we seen this specific resource instance before? Do this
       * trawl first before checking the RM instance later. Saves time.
       */

      try
      {
        synchronized (this)
        {
          info = (TxInfo) _resources.get(xaRes);

          if (info == null)
          {
            /*
             * Null info means it's not in the main resources list,
             * but may be in the duplicates.
             */

            info = (TxInfo) _duplicateResources.get(xaRes);
          }
        }

        if (info != null)
        {
          switch (info.getState())
          {
          case TxInfo.ASSOCIATION_SUSPENDED:
          {
            /*
             * Have seen resource before, so do a resume. The
             * Resource instance will still be registered with the
             * transaction though.
             */

            int xaStartResume = ((theModifier == null) ? XAResource.TMRESUME
                : theModifier
                    .xaStartParameters(XAResource.TMRESUME));

            xaRes.start(info.xid(), xaStartResume);

            info.setState(TxInfo.ASSOCIATED);

            synchronized (this)
            {
              _suspendCount--;
            }

            return true; // already registered resource with this
            // transaction!
          }
          case TxInfo.ASSOCIATED:
          {
            /*
             * Already active on this transaction.
             */

            return true;
          }
          case TxInfo.NOT_ASSOCIATED:
          {
            /*
             * Resource was associated, but was presumably delisted.
             */

            int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
                : theModifier
                    .xaStartParameters(XAResource.TMJOIN));

            xaRes.start(info.xid(), xaStartJoin);

            info.setState(TxInfo.ASSOCIATED);

            return true;
          }
          default:
          {
            // Note: this exception will be caught by our catch
            // block

            throw new IllegalStateException(
                "TransactionImple.enlistResource - "
                    + jtaLogger.logMesg
                        .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.illresstate")
                    + ":" + info.getState());
          }
          }
        }
      }
      catch (IllegalStateException ex)
      {
        throw ex; // we threw it in the first place
      }
      catch (XAException exp)
      {
        if (info != null)
          info.setState(TxInfo.FAILED);

        if (jtaLogger.loggerI18N.isWarnEnabled())
        {
          jtaLogger.loggerI18N
              .warn(
                  "com.arjuna.ats.internal.jta.transaction.arjunacore.enlisterror",
                  new Object[]
                  { "TransactionImple.enlistResource",
                      XAHelper.printXAErrorCode(exp) });
        }

        return false;
      }

      // if (threadIsActive(xaRes))
      // return true; // this thread has already registered a resource for
      // this db

      /*
       * We definitely haven't seen this specific resource instance
       * before, but that doesn't mean that we haven't seen the RM it is
       * connected to.
       */

      Xid xid = null;
      TxInfo existingRM = isNewRM(xaRes);

      if (existingRM == null)
      {
        /*
         * New RM, so create xid with new branch.
         */

        boolean branchRequired = true;

        synchronized (this)
        {
          if (_resources.size() == 0)// first ever, so no need for
          // branch
          {
            // branchRequired = false;
            branchRequired = true;
          }
        }

        xid = createXid(branchRequired, theModifier);

        boolean associatedWork = false;
        int retry = 20;

        /*
         * If another process has (or is about to) create the same
         * transaction association then we will probably get a failure
         * during start with XAER_DUPID. We know this must be due to
         * another server, since we keep track of our own registrations.
         * So, if this happens we create a new transaction branch and
         * try again.
         *
         * To save time we could always just create branches by default.
         *
         * Is there a benefit to a zero branch?
         */

        while (!associatedWork)
        {
          try
          {
            if (_xaTransactionTimeoutEnabled)
            {
              int timeout = _theTransaction.getTimeout();

              if (timeout > 0)
              {
                try
                {
                  xaRes.setTransactionTimeout(timeout);
                }
                catch (XAException te)
                {
                  if (jtaLogger.loggerI18N.isWarnEnabled())
                  {
                    jtaLogger.loggerI18N
                        .warn(
                            "com.arjuna.ats.internal.jta.transaction.arjunacore.timeouterror",
                            new Object[]
                            {
                                "TransactionImple.enlistResource",
                                XAHelper
                                    .printXAErrorCode(te),
                                xid });
                  }
                }
              }
            }

            int xaStartNormal = ((theModifier == null) ? XAResource.TMNOFLAGS
                : theModifier
                    .xaStartParameters(XAResource.TMNOFLAGS));


                        // Pay attention now, this bit is hairy. We need to add a new AbstractRecord (XAResourceRecord)
                        // to the BasicAction, which will thereafter drive its completion. However, the transaction
                        // core is not directly XA aware, so it's our job to start the XAResource. Problem is, if
                        // adding the record fails, BasicAction will never end the resource via the XAResourceRecord,
                        // so we must do so directly.  start may fail due to dupl xid or other reason, and transactions
                        // may rollback async, for which reasons we can't call add before start.
                        // The xid will change on each pass of the loop, so we need to create a new record on each pass.
                        // The creation will fail in the case of multiple last resources being disallowed, in which
                        // case we don't call start on the resource at all. see JBTM-362 and JBTM-363
                        AbstractRecord abstractRecord = createRecord(xaRes, params, xid);
                        if(abstractRecord != null) {
                            xaRes.start(xid, xaStartNormal);
                            if(_theTransaction.add(abstractRecord) == AddOutcome.AR_ADDED) {
                                _resources.put(xaRes, new TxInfo(xid));
                                return true; // dive out, no need to set associatedWork = true;
                            } else {
                                // we called start on the resource, but _theTransaction did not accept it.
                                // we therefore have a mess which we must now clean up by ensuring the start is undone:
                                abstractRecord.topLevelAbort();
                            }
                        }

                        // if we get to here, something other than a failure of xaRes.start probably went wrong.
                        // so we don't loop and retry, we just give up.
                        markRollbackOnly();
                        return false;

          }
          catch (XAException e)
          {
            // transaction already created by another server

            if ((e.errorCode == XAException.XAER_DUPID)
                || (e.errorCode == XAException.XAER_RMERR))
            {
              if (retry > 0)
                xid = createXid(true, theModifier);

              retry--;
            }
            else
            {
              /*
               * Can't do start, so set transaction to rollback
               * only.
               */

              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw e;
            }

            if (retry < 0)
            {
              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw new javax.transaction.SystemException(
                  "TransactionImple.enlistResource - XAResource.start "
                      + jtaLogger.logMesg
                          .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.couldnotregister")
                      + ": " + xid);
            }
          }
        }
      }
      else
      {
        /*
         * Have seen this RM before, so ignore this instance. The first
         * registered RM instance will be used to drive the transaction
         * completion. We add it to the duplicateResource list so we can
         * delist it correctly later though.
         */

        /*
         * Re-create xid.
         */

        xid = existingRM.xid();

        try
        {
          int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
              : theModifier.xaStartParameters(XAResource.TMJOIN));

          xaRes.start(xid, xaStartJoin);
        }
        catch (XAException ex)
        {
View Full Code Here

      throw new IllegalStateException(
          jtaLogger.logMesg
              .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.inactive"));
    }

    XAModifier theModifier = null;

    if (params != null)
    {
      if (params.length >= XAMODIFIER + 1)
      {
        if (params[XAMODIFIER] instanceof XAModifier)
        {
          theModifier = (XAModifier) params[XAMODIFIER];
        }
      }
    }

    try
    {
      /*
       * For each transaction we maintain a list of resources registered
       * with it. Each element on this list also contains a list of
       * threads which have registered this resource, and what their XID
       * was for that registration.
       */

      TxInfo info = null;

      /*
       * Have we seen this specific resource instance before? Do this
       * trawl first before checking the RM instance later. Saves time.
       */

      try
      {
        synchronized (this)
        {
          info = (TxInfo) _resources.get(xaRes);

          if (info == null)
          {
            /*
             * Null info means it's not in the main resources list,
             * but may be in the duplicates.
             */

            info = (TxInfo) _duplicateResources.get(xaRes);
          }
        }

        if (info != null)
        {
          switch (info.getState())
          {
          case TxInfo.ASSOCIATION_SUSPENDED:
          {
            /*
             * Have seen resource before, so do a resume. The
             * Resource instance will still be registered with the
             * transaction though.
             */

            int xaStartResume = ((theModifier == null) ? XAResource.TMRESUME
                : theModifier
                    .xaStartParameters(XAResource.TMRESUME));

            xaRes.start(info.xid(), xaStartResume);

            info.setState(TxInfo.ASSOCIATED);

            synchronized (this)
            {
              _suspendCount--;
            }

            return true; // already registered resource with this
            // transaction!
          }
          case TxInfo.ASSOCIATED:
          {
            /*
             * Already active on this transaction.
             */

            return true;
          }
          case TxInfo.NOT_ASSOCIATED:
          {
            /*
             * Resource was associated, but was presumably delisted.
             */

            int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
                : theModifier
                    .xaStartParameters(XAResource.TMJOIN));

            xaRes.start(info.xid(), xaStartJoin);

            info.setState(TxInfo.ASSOCIATED);

            return true;
          }
          default:
          {
            // Note: this exception will be caught by our catch
            // block

            throw new IllegalStateException(
                "TransactionImple.enlistResource - "
                    + jtaLogger.logMesg
                        .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.illresstate")
                    + ":" + info.getState());
          }
          }
        }
      }
      catch (IllegalStateException ex)
      {
        throw ex; // we threw it in the first place
      }
      catch (XAException exp)
      {
        if (info != null)
          info.setState(TxInfo.FAILED);

        if (jtaLogger.loggerI18N.isWarnEnabled())
        {
          jtaLogger.loggerI18N
              .warn(
                  "com.arjuna.ats.internal.jta.transaction.arjunacore.enlisterror",
                  new Object[]
                  { "TransactionImple.enlistResource",
                      XAHelper.printXAErrorCode(exp) });
        }

        return false;
      }

      // if (threadIsActive(xaRes))
      // return true; // this thread has already registered a resource for
      // this db

      /*
       * We definitely haven't seen this specific resource instance
       * before, but that doesn't mean that we haven't seen the RM it is
       * connected to.
       */

      Xid xid = null;
      TxInfo existingRM = isNewRM(xaRes);

      if (existingRM == null)
      {
        /*
         * New RM, so create xid with new branch.
         */

        boolean branchRequired = true;

        synchronized (this)
        {
          if (_resources.size() == 0)// first ever, so no need for
          // branch
          {
            // branchRequired = false;
            branchRequired = true;
          }
        }

        xid = createXid(branchRequired, theModifier);

        boolean associatedWork = false;
        int retry = 20;

        /*
         * If another process has (or is about to) create the same
         * transaction association then we will probably get a failure
         * during start with XAER_DUPID. We know this must be due to
         * another server, since we keep track of our own registrations.
         * So, if this happens we create a new transaction branch and
         * try again.
         *
         * To save time we could always just create branches by default.
         *
         * Is there a benefit to a zero branch?
         */

        while (!associatedWork)
        {
          try
          {
            if (_xaTransactionTimeoutEnabled)
            {
              int timeout = _theTransaction.getTimeout();

              if (timeout > 0)
              {
                try
                {
                  xaRes.setTransactionTimeout(timeout);
                }
                catch (XAException te)
                {
                  if (jtaLogger.loggerI18N.isWarnEnabled())
                  {
                    jtaLogger.loggerI18N
                        .warn(
                            "com.arjuna.ats.internal.jta.transaction.arjunacore.timeouterror",
                            new Object[]
                            {
                                "TransactionImple.enlistResource",
                                XAHelper
                                    .printXAErrorCode(te),
                                xid });
                  }
                }
              }
            }

            int xaStartNormal = ((theModifier == null) ? XAResource.TMNOFLAGS
                : theModifier
                    .xaStartParameters(XAResource.TMNOFLAGS));


                        // Pay attention now, this bit is hairy. We need to add a new AbstractRecord (XAResourceRecord)
                        // to the BasicAction, which will thereafter drive its completion. However, the transaction
                        // core is not directly XA aware, so it's our job to start the XAResource. Problem is, if
                        // adding the record fails, BasicAction will never end the resource via the XAResourceRecord,
                        // so we must do so directly.  start may fail due to dupl xid or other reason, and transactions
                        // may rollback async, for which reasons we can't call add before start.
                        // The xid will change on each pass of the loop, so we need to create a new record on each pass.
                        // The creation will fail in the case of multiple last resources being disallowed, in which
                        // case we don't call start on the resource at all. see JBTM-362 and JBTM-363
                        AbstractRecord abstractRecord = createRecord(xaRes, params, xid);
                        if(abstractRecord != null) {
                            xaRes.start(xid, xaStartNormal);
                            if(_theTransaction.add(abstractRecord) == AddOutcome.AR_ADDED) {
                                _resources.put(xaRes, new TxInfo(xid));
                                return true; // dive out, no need to set associatedWork = true;
                            } else {
                                // we called start on the resource, but _theTransaction did not accept it.
                                // we therefore have a mess which we must now clean up by ensuring the start is undone:
                                abstractRecord.topLevelAbort();
                            }
                        }

                        // if we get to here, something other than a failure of xaRes.start probably went wrong.
                        // so we don't loop and retry, we just give up.
                        markRollbackOnly();
                        return false;

          }
          catch (XAException e)
          {
            // transaction already created by another server

            if ((e.errorCode == XAException.XAER_DUPID)
                || (e.errorCode == XAException.XAER_RMERR))
            {
              if (retry > 0)
                xid = createXid(true, theModifier);

              retry--;
            }
            else
            {
              /*
               * Can't do start, so set transaction to rollback
               * only.
               */

              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw e;
            }

            if (retry < 0)
            {
              if (jtaLogger.loggerI18N.isWarnEnabled())
              {
                jtaLogger.loggerI18N
                    .warn(
                        "com.arjuna.ats.internal.jta.transaction.arjunacore.enliststarterror",
                        new Object[]
                        {
                            "TransactionImple.enlistResource",
                            XAHelper
                                .printXAErrorCode(e),
                            xid });
              }

              markRollbackOnly();

              throw new javax.transaction.SystemException(
                  "TransactionImple.enlistResource - XAResource.start "
                      + jtaLogger.logMesg
                          .getString("com.arjuna.ats.internal.jta.transaction.arjunacore.couldnotregister")
                      + ": " + xid);
            }
          }
        }
      }
      else
      {
        /*
         * Have seen this RM before, so ignore this instance. The first
         * registered RM instance will be used to drive the transaction
         * completion. We add it to the duplicateResource list so we can
         * delist it correctly later though.
         */

        /*
         * Re-create xid.
         */

        xid = existingRM.xid();

        try
        {
          int xaStartJoin = ((theModifier == null) ? XAResource.TMJOIN
              : theModifier.xaStartParameters(XAResource.TMJOIN));

          xaRes.start(xid, xaStartJoin);
        }
        catch (XAException ex)
        {
View Full Code Here

TOP

Related Classes of com.arjuna.ats.jta.xa.XAModifier

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.