예제 #1
0
  public boolean restore_state(InputObjectState os, int t) {
    boolean res = false;

    try {
      _heuristic = os.unpackInt();
      _committed = os.unpackBoolean();

      _tranID = XidImple.unpack(os);

      _theXAResource = null;
      _recoveryObject = null;

      if (os.unpackInt() == RecoverableXAConnection.OBJECT_RECOVERY) {
        _productName = os.unpackString();
        _productVersion = os.unpackString();
        _jndiName = os.unpackString();

        boolean haveXAResource = os.unpackBoolean();

        if (haveXAResource) {
          try {
            // Read the classname of the serialized XAResource
            String className = os.unpackString();

            byte[] b = os.unpackBytes();

            ByteArrayInputStream s = new ByteArrayInputStream(b);
            ObjectInputStream o = new ObjectInputStream(s);

            // Give the list of deserializers a chance to deserialize the record
            boolean deserialized = false;
            Iterator<SerializableXAResourceDeserializer> iterator =
                getXAResourceDeserializers().iterator();
            while (iterator.hasNext()) {
              SerializableXAResourceDeserializer proxyXAResourceDeserializer = iterator.next();
              if (proxyXAResourceDeserializer.canDeserialze(className)) {
                _theXAResource = proxyXAResourceDeserializer.deserialze(o);
                deserialized = true;
                break;
              }
            }

            // Give it a go ourselves
            if (!deserialized) {
              _theXAResource = (XAResource) o.readObject();
            }
            o.close();

            if (jtaLogger.logger.isTraceEnabled()) {
              jtaLogger.logger.trace("XAResourceRecord.restore_state - XAResource de-serialized");
            }
          } catch (Exception ex) {
            // not serializable in the first place!

            jtaLogger.i18NLogger.warn_resources_arjunacore_restorestate(ex);

            return false;
          }
        } else {
          /*
           * Lookup new XAResource via XARecoveryModule if possible.
           */

          _theXAResource = getNewXAResource();

          if (_theXAResource == null) {
            jtaLogger.i18NLogger.warn_resources_arjunacore_norecoveryxa(toString());

            /*
             * Don't prevent tx from activating because there may be
             * other participants that can still recover. Plus, we will
             * try to get a new XAResource later for this instance.
             */

            res = true;
          }
        }
      } else {
        String creatorName = os.unpackString();

        _recoveryObject =
            ClassloadingUtility.loadAndInstantiateClass(
                RecoverableXAConnection.class, creatorName, null);
        if (_recoveryObject == null) {
          throw new ClassNotFoundException();
        }

        _recoveryObject.unpackFrom(os);
        _theXAResource = _recoveryObject.getResource();

        if (jtaLogger.logger.isTraceEnabled()) {
          jtaLogger.logger.trace(
              "XAResourceRecord.restore_state - XAResource got from " + creatorName);
        }
      }

      res = true;
    } catch (Exception e) {
      jtaLogger.i18NLogger.warn_resources_arjunacore_restorestateerror(
          _theXAResource.toString(), XAHelper.xidToString(_tranID), e);

      res = false;
    }

    if (res) res = super.restore_state(os, t);

    return res;
  }
예제 #2
0
  public boolean save_state(OutputObjectState os, int t) {
    boolean res = false;

    try {
      os.packInt(_heuristic);
      os.packBoolean(_committed);

      /*
       * Since we don't know what type of Xid we are using, leave it up to
       * XID to pack.
       */

      XidImple.pack(os, _tranID);

      /*
       * If no recovery object set then rely upon object serialisation!
       */

      if (_recoveryObject == null) {
        os.packInt(RecoverableXAConnection.OBJECT_RECOVERY);

        os.packString(_productName);
        os.packString(_productVersion);
        os.packString(_jndiName);

        if (_theXAResource instanceof Serializable) {
          try {
            ByteArrayOutputStream s = new ByteArrayOutputStream();
            ObjectOutputStream o = new ObjectOutputStream(s);

            o.writeObject(_theXAResource);
            o.close();

            os.packBoolean(true);
            String name = _theXAResource.getClass().getName();
            os.packString(name);

            os.packBytes(s.toByteArray());
          } catch (NotSerializableException ex) {
            jtaLogger.i18NLogger.warn_resources_arjunacore_savestate();

            return false;
          }
        } else {
          // have to rely upon XAResource.recover!

          os.packBoolean(false);
        }
      } else {
        os.packInt(RecoverableXAConnection.AUTO_RECOVERY);
        os.packString(_recoveryObject.getClass().getName());

        _recoveryObject.packInto(os);
      }

      res = true;
    } catch (Exception e) {
      jtaLogger.i18NLogger.warn_resources_arjunacore_savestateerror(
          _theXAResource.toString(), XAHelper.xidToString(_tranID), e);

      res = false;
    }

    if (res) res = super.save_state(os, t);

    return res;
  }
예제 #3
0
  /**
   * For commit_one_phase we can do whatever we want since the transaction outcome is whatever we
   * want. Therefore, we do not need to save any additional recoverable state, such as a reference
   * to the transaction coordinator, since it will not have an intentions list anyway.
   */
  public int topLevelOnePhaseCommit() {
    if (jtaLogger.logger.isTraceEnabled()) {
      jtaLogger.logger.trace("XAResourceRecord.topLevelOnePhaseCommit for " + this);
    }

    boolean commit = true;

    if (_tranID == null) {
      jtaLogger.i18NLogger.warn_resources_arjunacore_opcnulltx("XAResourceRecord.1pc");

      return TwoPhaseOutcome.ONE_PHASE_ERROR; // rolled back!!
    } else {
      if (_theXAResource != null) {
        if (_heuristic != TwoPhaseOutcome.FINISH_OK) return _heuristic;

        XAException endHeuristic = null;
        XAException endRBOnly = null;

        try {
          /*
           * TODO in Oracle the end is not needed. Is this common
           * across other RMs?
           */

          if (endAssociation()) {
            _theXAResource.end(_tranID, XAResource.TMSUCCESS);
          }
        } catch (XAException e1) {
          /*
           * Now it's not legal to return a heuristic from end, but
           * apparently Oracle does (http://jira.jboss.com/jira/browse/JBTM-343)
           * Since this is 1PC we can call forget: the outcome of the
           * transaction is the outcome of the participant.
           */

          switch (e1.errorCode) {
            case XAException.XA_HEURHAZ:
            case XAException.XA_HEURMIX:
            case XAException.XA_HEURCOM:
            case XAException.XA_HEURRB:
              endHeuristic = e1;
              break;
            case XAException.XA_RBROLLBACK:
            case XAException.XA_RBCOMMFAIL:
            case XAException.XA_RBDEADLOCK:
            case XAException.XA_RBINTEGRITY:
            case XAException.XA_RBOTHER:
            case XAException.XA_RBPROTO:
            case XAException.XA_RBTIMEOUT:
            case XAException.XA_RBTRANSIENT:
              /*
               * Has been marked as rollback-only. We still
               * need to call rollback.
               */

              endRBOnly = e1;
              commit = false;
              break;
            case XAException.XAER_RMERR:
            case XAException.XAER_NOTA:
            case XAException.XAER_PROTO:
            case XAException.XAER_INVAL:
            case XAException.XAER_RMFAIL:
            default:
              {
                jtaLogger.i18NLogger.warn_resources_arjunacore_opcerror(
                    XAHelper.xidToString(_tranID),
                    _theXAResource.toString(),
                    XAHelper.printXAErrorCode(e1),
                    e1);

                removeConnection();

                return TwoPhaseOutcome.FINISH_ERROR;
              }
          }
        } catch (RuntimeException e) {
          jtaLogger.i18NLogger.warn_resources_arjunacore_opcerror(
              XAHelper.xidToString(_tranID), _theXAResource.toString(), "-", e);

          throw e;
        }

        try {
          /*
           * Not strictly necessary since calling commit will
           * do the rollback if end failed as above.
           */

          if (endHeuristic
              != null) // catch those RMs that terminate in end rather than follow the spec
          throw endHeuristic;

          if (commit) _theXAResource.commit(_tranID, true);
          else {
            _theXAResource.rollback(_tranID);
            throw endRBOnly;
          }
        } catch (XAException e1) {
          jtaLogger.i18NLogger.warn_resources_arjunacore_opcerror(
              XAHelper.xidToString(_tranID),
              _theXAResource.toString(),
              XAHelper.printXAErrorCode(e1),
              e1);

          /*
           * XA_HEURHAZ, XA_HEURCOM, XA_HEURRB, XA_HEURMIX,
           * XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or
           * XAER_PROTO. XA_RB*
           */

          switch (e1.errorCode) {
            case XAException.XA_HEURHAZ:
            case XAException.XA_HEURMIX:
              return TwoPhaseOutcome.HEURISTIC_HAZARD;
            case XAException.XA_HEURCOM:
              forget();
              break;
            case XAException.XA_HEURRB:
              forget();
              return TwoPhaseOutcome.ONE_PHASE_ERROR;
            case XAException.XA_RBROLLBACK:
            case XAException.XA_RBCOMMFAIL:
            case XAException.XA_RBDEADLOCK:
            case XAException.XA_RBINTEGRITY:
            case XAException.XA_RBOTHER:
            case XAException.XA_RBPROTO:
            case XAException.XA_RBTIMEOUT:
            case XAException.XA_RBTRANSIENT:
            case XAException.XAER_RMERR:
              return TwoPhaseOutcome.ONE_PHASE_ERROR;
            case XAException.XAER_NOTA:
              return TwoPhaseOutcome
                  .HEURISTIC_HAZARD; // something committed or rolled back without asking us!
            case XAException.XAER_INVAL: // resource manager failed, did it rollback?
              return TwoPhaseOutcome.HEURISTIC_HAZARD;
            case XAException.XA_RETRY: // XA does not allow this to be thrown for 1PC!
            case XAException.XAER_PROTO:
              return TwoPhaseOutcome.ONE_PHASE_ERROR; // assume rollback
            case XAException.XAER_RMFAIL:
            default:
              _committed = true; // will cause log to be rewritten
              return TwoPhaseOutcome.FINISH_ERROR; // recovery should retry
          }
        } catch (Exception e2) {
          jtaLogger.i18NLogger.warn_resources_arjunacore_opcerror(
              XAHelper.xidToString(_tranID), _theXAResource.toString(), "-", e2);

          return TwoPhaseOutcome.FINISH_ERROR;
        } finally {
          removeConnection();
        }
      } else return TwoPhaseOutcome.ONE_PHASE_ERROR;
    }

    if (commit) return TwoPhaseOutcome.FINISH_OK;
    else return TwoPhaseOutcome.FINISH_ERROR;
  }
예제 #4
0
  public int topLevelCommit() {
    if (jtaLogger.logger.isTraceEnabled()) {
      jtaLogger.logger.trace("XAResourceRecord.topLevelCommit for " + this);
    }

    if (!_prepared) return TwoPhaseOutcome.NOT_PREPARED;

    if (_tranID == null) {
      jtaLogger.i18NLogger.warn_resources_arjunacore_commitnulltx("XAResourceRecord.commit");

      return TwoPhaseOutcome.FINISH_ERROR;
    } else {
      if (_theXAResource == null) _theXAResource = getNewXAResource();

      if (_theXAResource != null) {
        if (_heuristic != TwoPhaseOutcome.FINISH_OK) return _heuristic;

        /*
         * No need for end call here since we can only get to this
         * point by going through prepare.
         */

        try {
          _theXAResource.commit(_tranID, false);
        } catch (XAException e1) {
          if (notAProblem(e1, true)) {
            // some other thread got there first (probably)
          } else {
            jtaLogger.i18NLogger.warn_resources_arjunacore_commitxaerror(
                XAHelper.xidToString(_tranID),
                _theXAResource.toString(),
                XAHelper.printXAErrorCode(e1),
                e1);

            /*
             * XA_HEURHAZ, XA_HEURCOM, XA_HEURRB, XA_HEURMIX,
             * XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or
             * XAER_PROTO.
             */

            switch (e1.errorCode) {
              case XAException.XA_HEURHAZ:
                return TwoPhaseOutcome.HEURISTIC_HAZARD;
              case XAException.XA_HEURCOM: // what about forget?
                // OTS doesn't support
                // this code here.
                break;
              case XAException.XA_HEURRB:
              case XAException
                  .XA_RBROLLBACK: // could really do with an ABORTED status in TwoPhaseOutcome to
                                  // differentiate
              case XAException.XA_RBCOMMFAIL:
              case XAException.XA_RBDEADLOCK:
              case XAException.XA_RBINTEGRITY:
              case XAException.XA_RBOTHER:
              case XAException.XA_RBPROTO:
              case XAException.XA_RBTIMEOUT:
              case XAException.XA_RBTRANSIENT:
              case XAException.XAER_RMERR:
              case XAException.XAER_PROTO: // XA spec implies rollback
                return TwoPhaseOutcome.HEURISTIC_ROLLBACK;
              case XAException.XA_HEURMIX:
                return TwoPhaseOutcome.HEURISTIC_MIXED;
              case XAException.XAER_NOTA:
                if (_recovered) break; // committed previously and recovery completed
                else
                  return TwoPhaseOutcome.HEURISTIC_HAZARD; // something terminated the transaction!
              case XAException.XA_RETRY:
              case XAException.XAER_RMFAIL:
                _committed = true; // will cause log to be rewritten

                /*
                 * Could do timeout retry here, but that could cause other resources in the list to go down the
                 * heuristic path (some are far too keen to do this). Fail and let recovery retry. Meanwhile
                 * the coordinator will continue to commit the other resources immediately.
                 */
                return TwoPhaseOutcome.FINISH_ERROR;
              case XAException.XAER_INVAL: // resource manager failed, did it rollback?
              default:
                return TwoPhaseOutcome.HEURISTIC_HAZARD;
            }
          }
        } catch (Exception e2) {
          jtaLogger.i18NLogger.warn_resources_arjunacore_commitxaerror(
              XAHelper.xidToString(_tranID), _theXAResource.toString(), "-", e2);

          return TwoPhaseOutcome.FINISH_ERROR;
        } finally {
          removeConnection();
        }
      } else {
        jtaLogger.i18NLogger.warn_resources_arjunacore_noresource(XAHelper.xidToString(_tranID));

        if (XAResourceRecord._assumedComplete) {
          jtaLogger.i18NLogger.info_resources_arjunacore_assumecomplete(
              XAHelper.xidToString(_tranID));

          return TwoPhaseOutcome.FINISH_OK;
        } else return TwoPhaseOutcome.FINISH_ERROR;
      }
    }

    return TwoPhaseOutcome.FINISH_OK;
  }
예제 #5
0
  public int topLevelAbort() {
    if (jtaLogger.logger.isTraceEnabled()) {
      jtaLogger.logger.trace("XAResourceRecord.topLevelAbort for " + this);
    }

    if (!_valid) return TwoPhaseOutcome.FINISH_ERROR;

    if (_theTransaction != null
        && _theTransaction.getXAResourceState(_theXAResource) == TxInfo.OPTIMIZED_ROLLBACK) {
      /*
       * Already rolledback during delist.
       */

      return TwoPhaseOutcome.FINISH_OK;
    }

    if (_tranID == null) {
      jtaLogger.i18NLogger.warn_resources_arjunacore_rollbacknulltx("XAResourceRecord.rollback");

      return TwoPhaseOutcome.FINISH_ERROR;
    } else {
      if (_theXAResource == null) _theXAResource = getNewXAResource();

      if (_theXAResource != null) {
        if (_heuristic != TwoPhaseOutcome.FINISH_OK) return _heuristic;

        try {
          if (!_prepared) {
            if (endAssociation()) {
              _theXAResource.end(_tranID, XAResource.TMSUCCESS);
            }
          }
        } catch (XAException e1) {
          if ((e1.errorCode >= XAException.XA_RBBASE) && (e1.errorCode < XAException.XA_RBEND)) {
            /*
             * Has been marked as rollback-only. We still
             * need to call rollback.
             */
          } else {
            jtaLogger.i18NLogger.warn_resources_arjunacore_rollbackerror(
                XAHelper.xidToString(_tranID),
                _theXAResource.toString(),
                XAHelper.printXAErrorCode(e1),
                e1);

            removeConnection();

            return TwoPhaseOutcome.FINISH_ERROR;
          }
        } catch (RuntimeException e) {
          jtaLogger.i18NLogger.warn_resources_arjunacore_rollbackerror(
              XAHelper.xidToString(_tranID), _theXAResource.toString(), "-", e);

          throw e;
        }

        try {
          _theXAResource.rollback(_tranID);
        } catch (XAException e1) {
          if (notAProblem(e1, false)) {
            // some other thread got there first (probably)
          } else {
            jtaLogger.i18NLogger.warn_resources_arjunacore_rollbackerror(
                XAHelper.xidToString(_tranID),
                _theXAResource.toString(),
                XAHelper.printXAErrorCode(e1),
                e1);

            switch (e1.errorCode) {
              case XAException.XAER_RMERR:
                if (!_prepared) break; // just do the finally block
              case XAException.XA_HEURHAZ:
                return TwoPhaseOutcome.HEURISTIC_HAZARD;
              case XAException.XA_HEURCOM:
                return TwoPhaseOutcome.HEURISTIC_COMMIT;
              case XAException.XA_HEURMIX:
                return TwoPhaseOutcome.HEURISTIC_MIXED;
              case XAException.XAER_NOTA:
                if (_recovered) break; // rolled back previously and recovery completed
              case XAException.XA_HEURRB: // forget?
              case XAException.XA_RBROLLBACK:
              case XAException.XA_RBEND:
              case XAException.XA_RBCOMMFAIL:
              case XAException.XA_RBDEADLOCK:
              case XAException.XA_RBINTEGRITY:
              case XAException.XA_RBOTHER:
              case XAException.XA_RBPROTO:
              case XAException.XA_RBTIMEOUT:
                break;
              default:
                return TwoPhaseOutcome.FINISH_ERROR;
            }
          }
        } catch (Exception e2) {
          jtaLogger.i18NLogger.warn_resources_arjunacore_rollbackerror(
              XAHelper.xidToString(_tranID), _theXAResource.toString(), "-", e2);

          return TwoPhaseOutcome.FINISH_ERROR;
        } finally {
          if (!_prepared) removeConnection();
        }
      } else {
        jtaLogger.i18NLogger.warn_resources_arjunacore_noresource(XAHelper.xidToString(_tranID));

        if (XAResourceRecord._assumedComplete) {
          jtaLogger.i18NLogger.info_resources_arjunacore_assumecomplete(
              XAHelper.xidToString(_tranID));

          return TwoPhaseOutcome.FINISH_OK;
        } else return TwoPhaseOutcome.FINISH_ERROR;
      }
    }

    return TwoPhaseOutcome.FINISH_OK;
  }
예제 #6
0
  public int topLevelPrepare() {
    if (jtaLogger.logger.isTraceEnabled()) {
      jtaLogger.logger.trace("XAResourceRecord.topLevelPrepare for " + this);
    }

    if (!_valid || (_theXAResource == null) || (_tranID == null)) {
      jtaLogger.i18NLogger.warn_resources_arjunacore_preparenulltx("XAResourceRecord.prepare");

      removeConnection();

      return TwoPhaseOutcome.PREPARE_NOTOK;
    }

    try {
      if (endAssociation()) {
        _theXAResource.end(_tranID, XAResource.TMSUCCESS);
      }

      _prepared = true;

      if (_theXAResource.prepare(_tranID) == XAResource.XA_RDONLY) {
        if (TxControl.isReadonlyOptimisation()) {
          // we won't be called again, so we need to tidy up now
          removeConnection();
        }

        return TwoPhaseOutcome.PREPARE_READONLY;
      } else return TwoPhaseOutcome.PREPARE_OK;
    } catch (XAException e1) {
      jtaLogger.i18NLogger.warn_resources_arjunacore_preparefailed(
          XAHelper.xidToString(_tranID),
          _theXAResource.toString(),
          XAHelper.printXAErrorCode(e1),
          e1);

      /*
       * XA_RB*, XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or
       * XAER_PROTO.
       */

      if (_rollbackOptimization) // won't have rollback called on it
      removeConnection();

      switch (e1.errorCode) {
        case XAException.XAER_RMERR:
        case XAException.XAER_RMFAIL:
        case XAException.XA_RBROLLBACK:
        case XAException.XA_RBEND:
        case XAException.XA_RBCOMMFAIL:
        case XAException.XA_RBDEADLOCK:
        case XAException.XA_RBINTEGRITY:
        case XAException.XA_RBOTHER:
        case XAException.XA_RBPROTO:
        case XAException.XA_RBTIMEOUT:
        case XAException.XAER_INVAL:
        case XAException.XAER_PROTO:
        case XAException
            .XAER_NOTA: // resource may have arbitrarily rolled back (shouldn't, but ...)
          return TwoPhaseOutcome.PREPARE_NOTOK; // will not call rollback
        default:
          return TwoPhaseOutcome
              .HEURISTIC_HAZARD; // we're not really sure (shouldn't get here though).
      }
    } catch (Exception e2) {
      jtaLogger.i18NLogger.warn_resources_arjunacore_preparefailed(
          XAHelper.xidToString(_tranID), _theXAResource.toString(), "-", e2);

      if (_rollbackOptimization) // won't have rollback called on it
      removeConnection();

      return TwoPhaseOutcome.PREPARE_NOTOK;
    }
  }