Search in sources :

Example 1 with GridDhtTxLocal

use of org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxLocal in project ignite by apache.

the class IgniteTxHandler method finishDhtLocal.

/**
     * @param nodeId Node ID initiated commit.
     * @param locTx Optional local transaction.
     * @param req Finish request.
     * @return Finish future.
     */
private IgniteInternalFuture<IgniteInternalTx> finishDhtLocal(UUID nodeId, @Nullable GridNearTxLocal locTx, GridNearTxFinishRequest req) {
    GridCacheVersion dhtVer = ctx.tm().mappedVersion(req.version());
    GridDhtTxLocal tx = null;
    if (dhtVer == null) {
        if (log.isDebugEnabled())
            log.debug("Received transaction finish request for unknown near version (was lock explicit?): " + req);
    } else
        tx = ctx.tm().tx(dhtVer);
    if (tx != null)
        req.txState(tx.txState());
    if (tx == null && locTx != null && !req.commit()) {
        U.warn(log, "DHT local tx not found for near local tx rollback " + "[req=" + req + ", dhtVer=" + dhtVer + ", tx=" + locTx + ']');
        return null;
    }
    if (tx == null && !req.explicitLock()) {
        assert locTx == null : "DHT local tx should never be lost for near local tx: " + locTx;
        U.warn(txFinishMsgLog, "Received finish request for completed transaction (the message may be too late) [" + "txId=" + req.version() + ", dhtTxId=" + dhtVer + ", node=" + nodeId + ", commit=" + req.commit() + ']');
        // Always send finish response.
        GridCacheMessage res = new GridNearTxFinishResponse(req.partition(), req.version(), req.threadId(), req.futureId(), req.miniId(), new IgniteCheckedException("Transaction has been already completed."));
        try {
            ctx.io().send(nodeId, res, req.policy());
            if (txFinishMsgLog.isDebugEnabled()) {
                txFinishMsgLog.debug("Sent near finish response for completed tx [txId=" + req.version() + ", dhtTxId=" + dhtVer + ", node=" + nodeId + ']');
            }
        } catch (Throwable e) {
            // Double-check.
            if (ctx.discovery().node(nodeId) == null) {
                if (txFinishMsgLog.isDebugEnabled()) {
                    txFinishMsgLog.debug("Failed to send near finish response for completed tx, node failed [" + "txId=" + req.version() + ", dhtTxId=" + dhtVer + ", node=" + nodeId + ']');
                }
            } else {
                U.error(txFinishMsgLog, "Failed to send near finish response for completed tx, node failed [" + "txId=" + req.version() + ", dhtTxId=" + dhtVer + ", node=" + nodeId + ", req=" + req + ", res=" + res + ']', e);
            }
            if (e instanceof Error)
                throw (Error) e;
        }
        return null;
    }
    try {
        assert tx != null : "Transaction is null for near finish request [nodeId=" + nodeId + ", req=" + req + "]";
        assert req.syncMode() != null : req;
        tx.syncMode(req.syncMode());
        tx.nearFinishFutureId(req.futureId());
        tx.nearFinishMiniId(req.miniId());
        tx.storeEnabled(req.storeEnabled());
        if (req.commit()) {
            if (!tx.markFinalizing(USER_FINISH)) {
                if (log.isDebugEnabled())
                    log.debug("Will not finish transaction (it is handled by another thread): " + tx);
                return null;
            }
            IgniteInternalFuture<IgniteInternalTx> commitFut = tx.commitDhtLocalAsync();
            // Only for error logging.
            commitFut.listen(CU.errorLogger(log));
            return commitFut;
        } else {
            IgniteInternalFuture<IgniteInternalTx> rollbackFut = tx.rollbackDhtLocalAsync();
            // Only for error logging.
            rollbackFut.listen(CU.errorLogger(log));
            return rollbackFut;
        }
    } catch (Throwable e) {
        tx.commitError(e);
        tx.systemInvalidate(true);
        U.error(log, "Failed completing transaction [commit=" + req.commit() + ", tx=" + tx + ']', e);
        IgniteInternalFuture<IgniteInternalTx> res;
        IgniteInternalFuture<IgniteInternalTx> rollbackFut = tx.rollbackDhtLocalAsync();
        // Only for error logging.
        rollbackFut.listen(CU.errorLogger(log));
        res = rollbackFut;
        if (e instanceof Error)
            throw (Error) e;
        return res;
    }
}
Also used : GridCacheVersion(org.apache.ignite.internal.processors.cache.version.GridCacheVersion) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) GridDhtTxLocal(org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxLocal) IgniteInternalFuture(org.apache.ignite.internal.IgniteInternalFuture) GridCacheMessage(org.apache.ignite.internal.processors.cache.GridCacheMessage) GridNearTxFinishResponse(org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxFinishResponse)

Example 2 with GridDhtTxLocal

use of org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxLocal in project ignite by apache.

the class IgniteTxHandler method prepareNearTx.

/**
     * @param nearNodeId Near node ID that initiated transaction.
     * @param req Near prepare request.
     * @param locReq Local request flag.
     * @return Prepare future.
     */
public IgniteInternalFuture<GridNearTxPrepareResponse> prepareNearTx(final UUID nearNodeId, final GridNearTxPrepareRequest req, boolean locReq) {
    // Make sure not to provide Near entries to DHT cache.
    if (locReq)
        req.cloneEntries();
    ClusterNode nearNode = ctx.node(nearNodeId);
    if (nearNode == null) {
        if (txPrepareMsgLog.isDebugEnabled()) {
            txPrepareMsgLog.debug("Received near prepare from node that left grid (will ignore) [" + "txId=" + req.version() + ", node=" + nearNodeId + ']');
        }
        return null;
    }
    IgniteTxEntry firstEntry;
    try {
        IgniteTxEntry firstWrite = unmarshal(req.writes());
        IgniteTxEntry firstRead = unmarshal(req.reads());
        firstEntry = firstWrite != null ? firstWrite : firstRead;
    } catch (IgniteCheckedException e) {
        return new GridFinishedFuture<>(e);
    }
    assert firstEntry != null : req;
    GridDhtTxLocal tx = null;
    GridCacheVersion mappedVer = ctx.tm().mappedVersion(req.version());
    if (mappedVer != null) {
        tx = ctx.tm().tx(mappedVer);
        if (tx == null)
            U.warn(log, "Missing local transaction for mapped near version [nearVer=" + req.version() + ", mappedVer=" + mappedVer + ']');
        else {
            if (req.concurrency() == PESSIMISTIC)
                tx.nearFutureId(req.futureId());
        }
    } else {
        GridDhtPartitionTopology top = null;
        if (req.firstClientRequest()) {
            assert req.concurrency() == OPTIMISTIC : req;
            assert CU.clientNode(nearNode) : nearNode;
            top = firstEntry.context().topology();
            top.readLock();
        }
        try {
            if (top != null && needRemap(req.topologyVersion(), top.topologyVersion(), req)) {
                if (txPrepareMsgLog.isDebugEnabled()) {
                    txPrepareMsgLog.debug("Topology version mismatch for near prepare, need remap transaction [" + "txId=" + req.version() + ", node=" + nearNodeId + ", reqTopVer=" + req.topologyVersion() + ", locTopVer=" + top.topologyVersion() + ", req=" + req + ']');
                }
                GridNearTxPrepareResponse res = new GridNearTxPrepareResponse(req.partition(), req.version(), req.futureId(), req.miniId(), req.version(), req.version(), null, null, top.topologyVersion(), req.deployInfo() != null);
                try {
                    ctx.io().send(nearNodeId, res, req.policy());
                    if (txPrepareMsgLog.isDebugEnabled()) {
                        txPrepareMsgLog.debug("Sent remap response for near prepare [txId=" + req.version() + ", node=" + nearNodeId + ']');
                    }
                } catch (ClusterTopologyCheckedException ignored) {
                    if (txPrepareMsgLog.isDebugEnabled()) {
                        txPrepareMsgLog.debug("Failed to send remap response for near prepare, node failed [" + "txId=" + req.version() + ", node=" + nearNodeId + ']');
                    }
                } catch (IgniteCheckedException e) {
                    U.error(txPrepareMsgLog, "Failed to send remap response for near prepare " + "[txId=" + req.version() + ", node=" + nearNodeId + ", req=" + req + ']', e);
                }
                return new GridFinishedFuture<>(res);
            }
            tx = new GridDhtTxLocal(ctx, req.topologyVersion(), nearNode.id(), req.version(), req.futureId(), req.miniId(), req.threadId(), req.implicitSingle(), req.implicitSingle(), req.system(), req.explicitLock(), req.policy(), req.concurrency(), req.isolation(), req.timeout(), req.isInvalidate(), true, req.onePhaseCommit(), req.txSize(), req.transactionNodes(), req.subjectId(), req.taskNameHash());
            tx = ctx.tm().onCreated(null, tx);
            if (tx != null)
                tx.topologyVersion(req.topologyVersion());
            else
                U.warn(log, "Failed to create local transaction (was transaction rolled back?) [xid=" + req.version() + ", req=" + req + ']');
        } finally {
            if (tx != null)
                req.txState(tx.txState());
            if (top != null)
                top.readUnlock();
        }
    }
    if (tx != null) {
        req.txState(tx.txState());
        if (req.explicitLock())
            tx.explicitLock(true);
        tx.transactionNodes(req.transactionNodes());
        if (req.near())
            tx.nearOnOriginatingNode(true);
        if (req.onePhaseCommit()) {
            assert req.last() : req;
            tx.onePhaseCommit(true);
        }
        if (req.needReturnValue())
            tx.needReturnValue(true);
        IgniteInternalFuture<GridNearTxPrepareResponse> fut = tx.prepareAsync(req.reads(), req.writes(), req.dhtVersions(), req.messageId(), req.miniId(), req.transactionNodes(), req.last());
        if (tx.isRollbackOnly() && !tx.commitOnPrepare()) {
            if (tx.state() != TransactionState.ROLLED_BACK && tx.state() != TransactionState.ROLLING_BACK)
                tx.rollbackDhtLocalAsync();
        }
        final GridDhtTxLocal tx0 = tx;
        fut.listen(new CI1<IgniteInternalFuture<?>>() {

            @Override
            public void apply(IgniteInternalFuture<?> txFut) {
                try {
                    txFut.get();
                } catch (IgniteCheckedException e) {
                    // Just in case.
                    tx0.setRollbackOnly();
                    if (!X.hasCause(e, IgniteTxOptimisticCheckedException.class) && !X.hasCause(e, IgniteFutureCancelledException.class) && !ctx.kernalContext().isStopping())
                        U.error(log, "Failed to prepare DHT transaction: " + tx0, e);
                }
            }
        });
        return fut;
    } else
        return new GridFinishedFuture<>((GridNearTxPrepareResponse) null);
}
Also used : ClusterNode(org.apache.ignite.cluster.ClusterNode) GridDhtTxLocal(org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxLocal) GridDhtPartitionTopology(org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtPartitionTopology) IgniteInternalFuture(org.apache.ignite.internal.IgniteInternalFuture) IgniteTxOptimisticCheckedException(org.apache.ignite.internal.transactions.IgniteTxOptimisticCheckedException) GridFinishedFuture(org.apache.ignite.internal.util.future.GridFinishedFuture) GridCacheVersion(org.apache.ignite.internal.processors.cache.version.GridCacheVersion) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) GridNearTxPrepareResponse(org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxPrepareResponse) IgniteFutureCancelledException(org.apache.ignite.lang.IgniteFutureCancelledException) ClusterTopologyCheckedException(org.apache.ignite.internal.cluster.ClusterTopologyCheckedException)

Example 3 with GridDhtTxLocal

use of org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxLocal in project ignite by apache.

the class IgniteTxManager method txLocksInfo.

/**
     * @param txKeys Tx keys.
     * @return Transactions locks and nodes.
     */
private TxLocksResponse txLocksInfo(Collection<IgniteTxKey> txKeys) {
    TxLocksResponse res = new TxLocksResponse();
    Collection<IgniteInternalTx> txs = activeTransactions();
    for (IgniteInternalTx tx : txs) {
        boolean nearTxLoc = tx instanceof GridNearTxLocal;
        if (!(nearTxLoc || tx instanceof GridDhtTxLocal) || !hasKeys(tx, txKeys))
            continue;
        IgniteTxState state = tx.txState();
        assert state instanceof IgniteTxStateImpl || state instanceof IgniteTxImplicitSingleStateImpl;
        Collection<IgniteTxEntry> txEntries = state instanceof IgniteTxStateImpl ? ((IgniteTxStateImpl) state).allEntriesCopy() : state.allEntries();
        Set<IgniteTxKey> requestedKeys = null;
        // in order to reduce amount of requests to remote nodes.
        if (nearTxLoc) {
            if (tx.pessimistic()) {
                GridDhtColocatedLockFuture fut = (GridDhtColocatedLockFuture) mvccFuture(tx, GridDhtColocatedLockFuture.class);
                if (fut != null)
                    requestedKeys = fut.requestedKeys();
                GridNearLockFuture nearFut = (GridNearLockFuture) mvccFuture(tx, GridNearLockFuture.class);
                if (nearFut != null) {
                    Set<IgniteTxKey> nearRequestedKeys = nearFut.requestedKeys();
                    if (nearRequestedKeys != null) {
                        if (requestedKeys == null)
                            requestedKeys = nearRequestedKeys;
                        else
                            requestedKeys = nearRequestedKeys;
                    }
                }
            } else {
                GridNearOptimisticTxPrepareFuture fut = (GridNearOptimisticTxPrepareFuture) mvccFuture(tx, GridNearOptimisticTxPrepareFuture.class);
                if (fut != null)
                    requestedKeys = fut.requestedKeys();
            }
        }
        for (IgniteTxEntry txEntry : txEntries) {
            IgniteTxKey txKey = txEntry.txKey();
            if (res.txLocks(txKey) == null) {
                GridCacheMapEntry e = (GridCacheMapEntry) txEntry.cached();
                List<GridCacheMvccCandidate> locs = e.mvccAllLocal();
                if (locs != null) {
                    boolean owner = false;
                    for (GridCacheMvccCandidate loc : locs) {
                        if (!owner && loc.owner() && loc.tx())
                            owner = true;
                        if (// Skip all candidates in case when no tx that owns lock.
                        !owner)
                            break;
                        if (loc.tx()) {
                            UUID nearNodeId = loc.otherNodeId();
                            GridCacheVersion txId = loc.otherVersion();
                            TxLock txLock = new TxLock(txId == null ? loc.version() : txId, nearNodeId == null ? loc.nodeId() : nearNodeId, loc.threadId(), loc.owner() ? TxLock.OWNERSHIP_OWNER : TxLock.OWNERSHIP_CANDIDATE);
                            res.addTxLock(txKey, txLock);
                        }
                    }
                } else // Special case for optimal sequence of nodes processing.
                if (nearTxLoc && requestedKeys != null && requestedKeys.contains(txKey.key())) {
                    TxLock txLock = new TxLock(tx.nearXidVersion(), tx.nodeId(), tx.threadId(), TxLock.OWNERSHIP_REQUESTED);
                    res.addTxLock(txKey, txLock);
                } else
                    res.addKey(txKey);
            }
        }
    }
    return res;
}
Also used : GridDhtTxLocal(org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxLocal) GridNearTxLocal(org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal) GridNearLockFuture(org.apache.ignite.internal.processors.cache.distributed.near.GridNearLockFuture) GridCacheVersion(org.apache.ignite.internal.processors.cache.version.GridCacheVersion) GridDhtColocatedLockFuture(org.apache.ignite.internal.processors.cache.distributed.dht.colocated.GridDhtColocatedLockFuture) GridNearOptimisticTxPrepareFuture(org.apache.ignite.internal.processors.cache.distributed.near.GridNearOptimisticTxPrepareFuture) GridCacheMapEntry(org.apache.ignite.internal.processors.cache.GridCacheMapEntry) UUID(java.util.UUID) GridCacheMvccCandidate(org.apache.ignite.internal.processors.cache.GridCacheMvccCandidate)

Example 4 with GridDhtTxLocal

use of org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxLocal in project ignite by apache.

the class IgniteTxManager method commitIfPrepared.

/**
     * Commits transaction in case when node started transaction failed, but all related
     * transactions were prepared (invalidates transaction if it is not fully prepared).
     *
     * @param tx Transaction.
     * @param failedNodeIds Failed nodes IDs.
     */
public void commitIfPrepared(IgniteInternalTx tx, Set<UUID> failedNodeIds) {
    assert tx instanceof GridDhtTxLocal || tx instanceof GridDhtTxRemote : tx;
    assert !F.isEmpty(tx.transactionNodes()) : tx;
    assert tx.nearXidVersion() != null : tx;
    GridCacheTxRecoveryFuture fut = new GridCacheTxRecoveryFuture(cctx, tx, failedNodeIds, tx.transactionNodes());
    cctx.mvcc().addFuture(fut, fut.futureId());
    if (log.isDebugEnabled())
        log.debug("Checking optimistic transaction state on remote nodes [tx=" + tx + ", fut=" + fut + ']');
    fut.prepare();
}
Also used : GridDhtTxRemote(org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxRemote) GridDhtTxLocal(org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxLocal) GridCacheTxRecoveryFuture(org.apache.ignite.internal.processors.cache.distributed.GridCacheTxRecoveryFuture)

Example 5 with GridDhtTxLocal

use of org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxLocal in project ignite by apache.

the class IgniteTxManager method commitTx.

/**
     * Commits a transaction.
     *
     * @param tx Transaction to commit.
     * @throws IgniteCheckedException If failed.
     */
public void commitTx(IgniteInternalTx tx) throws IgniteCheckedException {
    assert tx != null;
    assert tx.state() == COMMITTING : "Invalid transaction state for commit from tm [state=" + tx.state() + ", expected=COMMITTING, tx=" + tx + ']';
    if (log.isDebugEnabled())
        log.debug("Committing from TM [locNodeId=" + cctx.localNodeId() + ", tx=" + tx + ']');
    /*
         * Note that write phase is handled by transaction adapter itself,
         * so we don't do it here.
         */
    Object committed0 = completedVersHashMap.get(tx.xidVersion());
    Boolean committed = committed0 != null && !committed0.equals(Boolean.FALSE);
    // 1. Make sure that committed version has been recorded.
    if (!(committed || tx.writeSet().isEmpty() || tx.isSystemInvalidate())) {
        uncommitTx(tx);
        tx.errorWhenCommitting();
        throw new IgniteCheckedException("Missing commit version (consider increasing " + IGNITE_MAX_COMPLETED_TX_COUNT + " system property) [ver=" + tx.xidVersion() + ", tx=" + tx.getClass().getSimpleName() + ']');
    }
    ConcurrentMap<GridCacheVersion, IgniteInternalTx> txIdMap = transactionMap(tx);
    if (txIdMap.remove(tx.xidVersion(), tx)) {
        // 2. Must process completed entries before unlocking!
        processCompletedEntries(tx);
        if (tx instanceof GridDhtTxLocal) {
            GridDhtTxLocal dhtTxLoc = (GridDhtTxLocal) tx;
            collectPendingVersions(dhtTxLoc);
        }
        // 4. Unlock write resources.
        unlockMultiple(tx, tx.writeEntries());
        // 5. Unlock read resources if required.
        if (unlockReadEntries(tx))
            unlockMultiple(tx, tx.readEntries());
        // 6. Notify evictions.
        notifyEvictions(tx);
        // 7. Remove obsolete entries from cache.
        removeObsolete(tx);
        // 8. Assign transaction number at the end of transaction.
        tx.endVersion(cctx.versions().next(tx.topologyVersion()));
        // 9. Remove from per-thread storage.
        clearThreadMap(tx);
        // 10. Unregister explicit locks.
        if (!tx.alternateVersions().isEmpty()) {
            for (GridCacheVersion ver : tx.alternateVersions()) idMap.remove(ver);
        }
        // 11. Remove Near-2-DHT mappings.
        if (tx instanceof GridCacheMappedVersion) {
            GridCacheVersion mapped = ((GridCacheMappedVersion) tx).mappedVersion();
            if (mapped != null)
                mappedVers.remove(mapped);
        }
        // 12. Clear context.
        resetContext();
        // 14. Update metrics.
        if (!tx.dht() && tx.local()) {
            if (!tx.system())
                cctx.txMetrics().onTxCommit();
            tx.txState().onTxEnd(cctx, tx, true);
        }
        if (slowTxWarnTimeout > 0 && tx.local() && U.currentTimeMillis() - tx.startTime() > slowTxWarnTimeout)
            U.warn(log, "Slow transaction detected [tx=" + tx + ", slowTxWarnTimeout=" + slowTxWarnTimeout + ']');
        if (log.isDebugEnabled())
            log.debug("Committed from TM [locNodeId=" + cctx.localNodeId() + ", tx=" + tx + ']');
    } else if (log.isDebugEnabled())
        log.debug("Did not commit from TM (was already committed): " + tx);
}
Also used : GridCacheVersion(org.apache.ignite.internal.processors.cache.version.GridCacheVersion) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) GridDhtTxLocal(org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxLocal) GridCacheMappedVersion(org.apache.ignite.internal.processors.cache.distributed.GridCacheMappedVersion)

Aggregations

GridDhtTxLocal (org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxLocal)5 GridCacheVersion (org.apache.ignite.internal.processors.cache.version.GridCacheVersion)4 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)3 IgniteInternalFuture (org.apache.ignite.internal.IgniteInternalFuture)2 UUID (java.util.UUID)1 ClusterNode (org.apache.ignite.cluster.ClusterNode)1 ClusterTopologyCheckedException (org.apache.ignite.internal.cluster.ClusterTopologyCheckedException)1 GridCacheMapEntry (org.apache.ignite.internal.processors.cache.GridCacheMapEntry)1 GridCacheMessage (org.apache.ignite.internal.processors.cache.GridCacheMessage)1 GridCacheMvccCandidate (org.apache.ignite.internal.processors.cache.GridCacheMvccCandidate)1 GridCacheMappedVersion (org.apache.ignite.internal.processors.cache.distributed.GridCacheMappedVersion)1 GridCacheTxRecoveryFuture (org.apache.ignite.internal.processors.cache.distributed.GridCacheTxRecoveryFuture)1 GridDhtPartitionTopology (org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtPartitionTopology)1 GridDhtTxRemote (org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxRemote)1 GridDhtColocatedLockFuture (org.apache.ignite.internal.processors.cache.distributed.dht.colocated.GridDhtColocatedLockFuture)1 GridNearLockFuture (org.apache.ignite.internal.processors.cache.distributed.near.GridNearLockFuture)1 GridNearOptimisticTxPrepareFuture (org.apache.ignite.internal.processors.cache.distributed.near.GridNearOptimisticTxPrepareFuture)1 GridNearTxFinishResponse (org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxFinishResponse)1 GridNearTxLocal (org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal)1 GridNearTxPrepareResponse (org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxPrepareResponse)1