/**
   * @param nodeId Node ID.
   * @param res Response.
   */
  private void processPrepareResponse(UUID nodeId, GridNearTxPrepareResponse<K, V> res) {
    GridNearTxPrepareFuture<K, V> fut =
        (GridNearTxPrepareFuture<K, V>)
            ctx.mvcc().<GridCacheTxEx<K, V>>future(res.version().id(), res.futureId());

    if (fut == null) {
      if (log.isDebugEnabled())
        log.debug(
            "Failed to find future for prepare response [sender=" + nodeId + ", res=" + res + ']');

      return;
    }

    fut.onResult(nodeId, res);
  }
Beispiel #2
0
  /** {@inheritDoc} */
  @Override
  public void rollback() throws GridException {
    GridNearTxPrepareFuture<K, V> prepFut = this.prepFut.get();

    GridNearTxFinishFuture<K, V> fut = rollbackFut.get();

    if (fut == null
        && !rollbackFut.compareAndSet(
            null, fut = new GridNearTxFinishFuture<K, V>(cctx, this, false))) {
      rollbackFut.get();

      return;
    }

    try {
      cctx.mvcc().addFuture(fut);

      if (prepFut == null) {
        finish(false);

        fut.finish();
      } else {
        prepFut.listenAsync(
            new CI1<GridFuture<GridCacheTxEx<K, V>>>() {
              @Override
              public void apply(GridFuture<GridCacheTxEx<K, V>> f) {
                try {
                  // Check for errors in prepare future.
                  f.get();
                } catch (GridException e) {
                  if (log.isDebugEnabled())
                    log.debug("Got optimistic tx failure [tx=" + this + ", err=" + e + ']');
                }

                try {
                  finish(false);

                  rollbackFut.get().finish();
                } catch (GridException e) {
                  U.error(log, "Failed to gracefully rollback transaction: " + this, e);

                  rollbackFut.get().onError(e);
                }
              }
            });
      }

      // TODO: Rollback Async?
      fut.get();
    } catch (Error e) {
      U.addLastCause(e, commitErr.get());

      throw e;
    } catch (RuntimeException e) {
      U.addLastCause(e, commitErr.get());

      throw e;
    } catch (GridException e) {
      U.addLastCause(e, commitErr.get());

      throw e;
    } finally {
      cctx.tm().txContextReset();
      cctx.near().dht().context().tm().txContextReset();
    }
  }
Beispiel #3
0
  /** {@inheritDoc} */
  @Override
  public GridFuture<GridCacheTxEx<K, V>> prepareAsync() {
    GridNearTxPrepareFuture<K, V> fut = prepFut.get();

    if (fut == null) {
      // Future must be created before any exception can be thrown.
      if (!prepFut.compareAndSet(null, fut = new GridNearTxPrepareFuture<K, V>(cctx, this)))
        return prepFut.get();
    } else
      // Prepare was called explicitly.
      return fut;

    if (!state(PREPARING)) {
      if (setRollbackOnly()) {
        if (timedOut())
          fut.onError(
              new GridCacheTxTimeoutException(
                  "Transaction timed out and was rolled back: " + this));
        else
          fut.onError(
              new GridException(
                  "Invalid transaction state for prepare [state="
                      + state()
                      + ", tx="
                      + this
                      + ']'));
      } else
        fut.onError(
            new GridCacheTxRollbackException(
                "Invalid transaction state for prepare [state=" + state() + ", tx=" + this + ']'));

      return fut;
    }

    // For pessimistic mode we don't distribute prepare request.
    if (pessimistic()) {
      try {
        userPrepare();

        if (!state(PREPARED)) {
          setRollbackOnly();

          fut.onError(
              new GridException(
                  "Invalid transaction state for commit [state=" + state() + ", tx=" + this + ']'));

          return fut;
        }

        fut.complete();

        return fut;
      } catch (GridException e) {
        fut.onError(e);

        return fut;
      }
    }

    try {
      cctx.topology().readLock();

      try {
        topologyVersion(cctx.topology().topologyVersion());

        userPrepare();
      } finally {
        cctx.topology().readUnlock();
      }

      // This will attempt to locally commit
      // EVENTUALLY CONSISTENT transactions.
      fut.onPreparedEC();

      // Make sure to add future before calling prepare.
      cctx.mvcc().addFuture(fut);

      fut.prepare();
    } catch (GridCacheTxTimeoutException e) {
      fut.onError(e);
    } catch (GridCacheTxOptimisticException e) {
      fut.onError(e);
    } catch (GridException e) {
      setRollbackOnly();

      String msg = "Failed to prepare transaction (will attempt rollback): " + this;

      log.error(msg, e);

      try {
        rollback();
      } catch (GridException e1) {
        U.error(log, "Failed to rollback transaction: " + this, e1);
      }

      fut.onError(new GridCacheTxRollbackException(msg, e));
    }

    return fut;
  }
Beispiel #4
0
  /** {@inheritDoc} */
  @Override
  public boolean onOwnerChanged(GridCacheEntryEx<K, V> entry, GridCacheMvccCandidate<K> owner) {
    GridNearTxPrepareFuture<K, V> fut = prepFut.get();

    return fut != null && fut.onOwnerChanged(entry, owner);
  }