/** {@inheritDoc} */
  @Override
  protected void remove(Object key) throws CacheException {
    try {
      TxContext ctx = txCtx.get();

      if (ctx != null) cache.removex(key);
    } catch (GridException e) {
      rollbackCurrentTx();

      throw new CacheException(e);
    }
  }
  /** {@inheritDoc} */
  @Override
  protected void unlock(Object key, SoftLock lock) throws CacheException {
    try {
      TxContext ctx = txCtx.get();

      if (ctx != null) unlock(ctx, key);
    } catch (GridException e) {
      rollbackCurrentTx();

      throw new CacheException(e);
    }
  }
  /** Roll backs current transaction. */
  private void rollbackCurrentTx() {
    try {
      TxContext ctx = txCtx.get();

      if (ctx != null) {
        txCtx.remove();

        GridCacheTx tx = cache.tx();

        if (tx != null) tx.rollback();
      }
    } catch (GridException e) {
      log.error("Failed to rollback cache transaction.", e);
    }
  }
  /** {@inheritDoc} */
  @Override
  protected SoftLock lock(Object key) throws CacheException {
    try {
      TxContext ctx = txCtx.get();

      if (ctx == null) txCtx.set(ctx = new TxContext());

      lockKey(key);

      ctx.locked(key);

      return null;
    } catch (GridException e) {
      rollbackCurrentTx();

      throw new CacheException(e);
    }
  }
  /** {@inheritDoc} */
  @Override
  protected boolean afterUpdate(Object key, Object val, SoftLock lock) throws CacheException {
    try {
      TxContext ctx = txCtx.get();

      if (ctx != null) {
        cache.putx(key, val);

        unlock(ctx, key);

        return true;
      }

      return false;
    } catch (GridException e) {
      rollbackCurrentTx();

      throw new CacheException(e);
    }
  }