Search in sources :

Example 51 with GridCacheContext

use of org.apache.ignite.internal.processors.cache.GridCacheContext in project ignite by apache.

the class IgniteTxLocalAdapter method userCommit.

/**
 * {@inheritDoc}
 */
@SuppressWarnings({ "CatchGenericClass" })
@Override
public void userCommit() throws IgniteCheckedException {
    TransactionState state = state();
    if (state != COMMITTING) {
        if (remainingTime() == -1)
            throw new IgniteTxTimeoutCheckedException("Transaction timed out: " + this);
        setRollbackOnly();
        throw new IgniteCheckedException("Invalid transaction state for commit [state=" + state + ", tx=" + this + ']');
    }
    checkValid();
    Collection<IgniteTxEntry> commitEntries = (near() || cctx.snapshot().needTxReadLogging()) ? allEntries() : writeEntries();
    boolean empty = F.isEmpty(commitEntries);
    // locks on backup nodes.
    if (!empty || colocated())
        cctx.tm().addCommittedTx(this);
    if (!empty) {
        batchStoreCommit(writeEntries());
        WALPointer ptr = null;
        cctx.database().checkpointReadLock();
        try {
            cctx.tm().txContext(this);
            AffinityTopologyVersion topVer = topologyVersion();
            /*
                 * Commit to cache. Note that for 'near' transaction we loop through all the entries.
                 */
            for (IgniteTxEntry txEntry : commitEntries) {
                GridCacheContext cacheCtx = txEntry.context();
                GridDrType drType = cacheCtx.isDrEnabled() ? DR_PRIMARY : DR_NONE;
                UUID nodeId = txEntry.nodeId() == null ? this.nodeId : txEntry.nodeId();
                try {
                    while (true) {
                        try {
                            GridCacheEntryEx cached = txEntry.cached();
                            // transaction manager to make sure locks are held.
                            if (!evictNearEntry(txEntry, false)) {
                                if (cacheCtx.isNear() && cacheCtx.dr().receiveEnabled()) {
                                    cached.markObsolete(xidVer);
                                    break;
                                }
                                if (cached.detached())
                                    break;
                                GridCacheEntryEx nearCached = null;
                                boolean metrics = true;
                                if (updateNearCache(cacheCtx, txEntry.key(), topVer))
                                    nearCached = cacheCtx.dht().near().peekEx(txEntry.key());
                                else if (cacheCtx.isNear() && txEntry.locallyMapped())
                                    metrics = false;
                                boolean evt = !isNearLocallyMapped(txEntry, false);
                                if (!F.isEmpty(txEntry.entryProcessors()) || !F.isEmpty(txEntry.filters()))
                                    txEntry.cached().unswap(false);
                                IgniteBiTuple<GridCacheOperation, CacheObject> res = applyTransformClosures(txEntry, true, null);
                                GridCacheVersion dhtVer = null;
                                // backup remote transaction completes.
                                if (cacheCtx.isNear()) {
                                    if (txEntry.op() == CREATE || txEntry.op() == UPDATE || txEntry.op() == DELETE || txEntry.op() == TRANSFORM)
                                        dhtVer = txEntry.dhtVersion();
                                    if ((txEntry.op() == CREATE || txEntry.op() == UPDATE) && txEntry.conflictExpireTime() == CU.EXPIRE_TIME_CALCULATE) {
                                        ExpiryPolicy expiry = cacheCtx.expiryForTxEntry(txEntry);
                                        if (expiry != null) {
                                            txEntry.cached().unswap(false);
                                            Duration duration = cached.hasValue() ? expiry.getExpiryForUpdate() : expiry.getExpiryForCreation();
                                            txEntry.ttl(CU.toTtl(duration));
                                        }
                                    }
                                }
                                GridCacheOperation op = res.get1();
                                CacheObject val = res.get2();
                                // Deal with conflicts.
                                GridCacheVersion explicitVer = txEntry.conflictVersion() != null ? txEntry.conflictVersion() : writeVersion();
                                if ((op == CREATE || op == UPDATE) && txEntry.conflictExpireTime() == CU.EXPIRE_TIME_CALCULATE) {
                                    ExpiryPolicy expiry = cacheCtx.expiryForTxEntry(txEntry);
                                    if (expiry != null) {
                                        Duration duration = cached.hasValue() ? expiry.getExpiryForUpdate() : expiry.getExpiryForCreation();
                                        long ttl = CU.toTtl(duration);
                                        txEntry.ttl(ttl);
                                        if (ttl == CU.TTL_ZERO)
                                            op = DELETE;
                                    }
                                }
                                boolean conflictNeedResolve = cacheCtx.conflictNeedResolve();
                                GridCacheVersionConflictContext<?, ?> conflictCtx = null;
                                if (conflictNeedResolve) {
                                    IgniteBiTuple<GridCacheOperation, GridCacheVersionConflictContext> conflictRes = conflictResolve(op, txEntry, val, explicitVer, cached);
                                    assert conflictRes != null;
                                    conflictCtx = conflictRes.get2();
                                    if (conflictCtx.isUseOld())
                                        op = NOOP;
                                    else if (conflictCtx.isUseNew()) {
                                        txEntry.ttl(conflictCtx.ttl());
                                        txEntry.conflictExpireTime(conflictCtx.expireTime());
                                    } else {
                                        assert conflictCtx.isMerge();
                                        op = conflictRes.get1();
                                        val = txEntry.context().toCacheObject(conflictCtx.mergeValue());
                                        explicitVer = writeVersion();
                                        txEntry.ttl(conflictCtx.ttl());
                                        txEntry.conflictExpireTime(conflictCtx.expireTime());
                                    }
                                } else
                                    // Nullify explicit version so that innerSet/innerRemove will work as usual.
                                    explicitVer = null;
                                if (sndTransformedVals || conflictNeedResolve) {
                                    assert sndTransformedVals && cacheCtx.isReplicated() || conflictNeedResolve;
                                    txEntry.value(val, true, false);
                                    txEntry.op(op);
                                    txEntry.entryProcessors(null);
                                    txEntry.conflictVersion(explicitVer);
                                }
                                if (dhtVer == null)
                                    dhtVer = explicitVer != null ? explicitVer : writeVersion();
                                if (op == CREATE || op == UPDATE) {
                                    assert val != null : txEntry;
                                    GridCacheUpdateTxResult updRes = cached.innerSet(this, eventNodeId(), txEntry.nodeId(), val, false, false, txEntry.ttl(), evt, metrics, txEntry.keepBinary(), txEntry.hasOldValue(), txEntry.oldValue(), topVer, null, cached.detached() ? DR_NONE : drType, txEntry.conflictExpireTime(), cached.isNear() ? null : explicitVer, CU.subjectId(this, cctx), resolveTaskName(), dhtVer, null);
                                    if (updRes.success())
                                        txEntry.updateCounter(updRes.updatePartitionCounter());
                                    if (updRes.loggedPointer() != null)
                                        ptr = updRes.loggedPointer();
                                    if (nearCached != null && updRes.success()) {
                                        nearCached.innerSet(null, eventNodeId(), nodeId, val, false, false, txEntry.ttl(), false, metrics, txEntry.keepBinary(), txEntry.hasOldValue(), txEntry.oldValue(), topVer, CU.empty0(), DR_NONE, txEntry.conflictExpireTime(), null, CU.subjectId(this, cctx), resolveTaskName(), dhtVer, null);
                                    }
                                } else if (op == DELETE) {
                                    GridCacheUpdateTxResult updRes = cached.innerRemove(this, eventNodeId(), txEntry.nodeId(), false, evt, metrics, txEntry.keepBinary(), txEntry.hasOldValue(), txEntry.oldValue(), topVer, null, cached.detached() ? DR_NONE : drType, cached.isNear() ? null : explicitVer, CU.subjectId(this, cctx), resolveTaskName(), dhtVer, null);
                                    if (updRes.success())
                                        txEntry.updateCounter(updRes.updatePartitionCounter());
                                    if (updRes.loggedPointer() != null)
                                        ptr = updRes.loggedPointer();
                                    if (nearCached != null && updRes.success()) {
                                        nearCached.innerRemove(null, eventNodeId(), nodeId, false, false, metrics, txEntry.keepBinary(), txEntry.hasOldValue(), txEntry.oldValue(), topVer, CU.empty0(), DR_NONE, null, CU.subjectId(this, cctx), resolveTaskName(), dhtVer, null);
                                    }
                                } else if (op == RELOAD) {
                                    cached.innerReload();
                                    if (nearCached != null)
                                        nearCached.innerReload();
                                } else if (op == READ) {
                                    CacheGroupContext grp = cacheCtx.group();
                                    if (grp.persistenceEnabled() && grp.walEnabled() && cctx.snapshot().needTxReadLogging()) {
                                        ptr = cctx.wal().log(new DataRecord(new DataEntry(cacheCtx.cacheId(), txEntry.key(), val, op, nearXidVersion(), writeVersion(), 0, txEntry.key().partition(), txEntry.updateCounter())));
                                    }
                                    ExpiryPolicy expiry = cacheCtx.expiryForTxEntry(txEntry);
                                    if (expiry != null) {
                                        Duration duration = expiry.getExpiryForAccess();
                                        if (duration != null)
                                            cached.updateTtl(null, CU.toTtl(duration));
                                    }
                                    if (log.isDebugEnabled())
                                        log.debug("Ignoring READ entry when committing: " + txEntry);
                                } else {
                                    assert ownsLock(txEntry.cached()) : "Transaction does not own lock for group lock entry during  commit [tx=" + this + ", txEntry=" + txEntry + ']';
                                    if (conflictCtx == null || !conflictCtx.isUseOld()) {
                                        if (txEntry.ttl() != CU.TTL_NOT_CHANGED)
                                            cached.updateTtl(null, txEntry.ttl());
                                    }
                                    if (log.isDebugEnabled())
                                        log.debug("Ignoring NOOP entry when committing: " + txEntry);
                                }
                            }
                            // if an entry is obsolete).
                            if (txEntry.op() != READ)
                                checkCommitLocks(cached);
                            // Break out of while loop.
                            break;
                        }// If entry cached within transaction got removed.
                         catch (GridCacheEntryRemovedException ignored) {
                            if (log.isDebugEnabled())
                                log.debug("Got removed entry during transaction commit (will retry): " + txEntry);
                            txEntry.cached(entryEx(cacheCtx, txEntry.txKey(), topologyVersion()));
                        }
                    }
                } catch (Throwable ex) {
                    // We are about to initiate transaction rollback when tx has started to committing.
                    // Need to remove version from committed list.
                    cctx.tm().removeCommittedTx(this);
                    if (X.hasCause(ex, GridCacheIndexUpdateException.class) && cacheCtx.cache().isMongoDataCache()) {
                        if (log.isDebugEnabled())
                            log.debug("Failed to update mongo document index (transaction entry will " + "be ignored): " + txEntry);
                        // Set operation to NOOP.
                        txEntry.op(NOOP);
                        errorWhenCommitting();
                        throw ex;
                    } else {
                        boolean nodeStopping = X.hasCause(ex, NodeStoppingException.class);
                        IgniteCheckedException err = new IgniteTxHeuristicCheckedException("Failed to locally write to cache " + "(all transaction entries will be invalidated, however there was a window when " + "entries for this transaction were visible to others): " + this, ex);
                        if (nodeStopping) {
                            U.warn(log, "Failed to commit transaction, node is stopping " + "[tx=" + this + ", err=" + ex + ']');
                        } else
                            U.error(log, "Heuristic transaction failure.", err);
                        COMMIT_ERR_UPD.compareAndSet(this, null, err);
                        state(UNKNOWN);
                        try {
                            // Courtesy to minimize damage.
                            uncommit(nodeStopping);
                        } catch (Throwable ex1) {
                            U.error(log, "Failed to uncommit transaction: " + this, ex1);
                            if (ex1 instanceof Error)
                                throw ex1;
                        }
                        if (ex instanceof Error)
                            throw ex;
                        throw err;
                    }
                }
            }
            if (ptr != null && !cctx.tm().logTxRecords())
                cctx.wal().fsync(ptr);
        } catch (StorageException e) {
            throw new IgniteCheckedException("Failed to log transaction record " + "(transaction will be rolled back): " + this, e);
        } finally {
            cctx.database().checkpointReadUnlock();
            cctx.tm().resetContext();
        }
    }
    // Do not unlock transaction entries if one-phase commit.
    if (!onePhaseCommit()) {
        if (DONE_FLAG_UPD.compareAndSet(this, 0, 1)) {
            // Unlock all locks.
            cctx.tm().commitTx(this);
            boolean needsCompletedVersions = needsCompletedVersions();
            assert !needsCompletedVersions || completedBase != null;
            assert !needsCompletedVersions || committedVers != null;
            assert !needsCompletedVersions || rolledbackVers != null;
        }
    }
}
Also used : TransactionState(org.apache.ignite.transactions.TransactionState) NodeStoppingException(org.apache.ignite.internal.NodeStoppingException) IgniteTxHeuristicCheckedException(org.apache.ignite.internal.transactions.IgniteTxHeuristicCheckedException) DataEntry(org.apache.ignite.internal.pagemem.wal.record.DataEntry) GridCacheVersion(org.apache.ignite.internal.processors.cache.version.GridCacheVersion) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) IgniteCacheExpiryPolicy(org.apache.ignite.internal.processors.cache.IgniteCacheExpiryPolicy) ExpiryPolicy(javax.cache.expiry.ExpiryPolicy) GridCacheEntryRemovedException(org.apache.ignite.internal.processors.cache.GridCacheEntryRemovedException) CacheObject(org.apache.ignite.internal.processors.cache.CacheObject) KeyCacheObject(org.apache.ignite.internal.processors.cache.KeyCacheObject) DataRecord(org.apache.ignite.internal.pagemem.wal.record.DataRecord) UUID(java.util.UUID) WALPointer(org.apache.ignite.internal.pagemem.wal.WALPointer) GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext) AffinityTopologyVersion(org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion) Duration(javax.cache.expiry.Duration) GridCacheVersionConflictContext(org.apache.ignite.internal.processors.cache.version.GridCacheVersionConflictContext) GridCacheEntryEx(org.apache.ignite.internal.processors.cache.GridCacheEntryEx) GridDrType(org.apache.ignite.internal.processors.dr.GridDrType) GridCacheUpdateTxResult(org.apache.ignite.internal.processors.cache.GridCacheUpdateTxResult) IgniteTxTimeoutCheckedException(org.apache.ignite.internal.transactions.IgniteTxTimeoutCheckedException) GridCacheOperation(org.apache.ignite.internal.processors.cache.GridCacheOperation) CacheGroupContext(org.apache.ignite.internal.processors.cache.CacheGroupContext) StorageException(org.apache.ignite.internal.pagemem.wal.StorageException)

Example 52 with GridCacheContext

use of org.apache.ignite.internal.processors.cache.GridCacheContext in project ignite by apache.

the class IgniteTxRemoteStateImpl method unwindEvicts.

/**
 * {@inheritDoc}
 */
@Override
public void unwindEvicts(GridCacheSharedContext cctx) {
    assert readMap == null || readMap.isEmpty();
    int singleCacheId = 0;
    Set<Integer> cacheIds = null;
    for (IgniteTxKey writeKey : writeMap.keySet()) {
        int cacheId = writeKey.cacheId();
        assert cacheId != 0;
        // Have we already notified this cache?
        if (cacheId == singleCacheId || cacheIds != null && !cacheIds.add(cacheId))
            continue;
        if (singleCacheId == 0)
            singleCacheId = cacheId;
        else if (cacheIds == null) {
            cacheIds = new HashSet<>(2);
            cacheIds.add(cacheId);
        }
        GridCacheContext ctx = cctx.cacheContext(cacheId);
        if (ctx != null)
            CU.unwindEvicts(ctx);
    }
}
Also used : GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext) HashSet(java.util.HashSet)

Example 53 with GridCacheContext

use of org.apache.ignite.internal.processors.cache.GridCacheContext in project ignite by apache.

the class IgniteTxRemoteStateImpl method invalidPartition.

/**
 * {@inheritDoc}
 */
@Override
public void invalidPartition(int part) {
    if (writeMap != null) {
        for (Iterator<IgniteTxEntry> it = writeMap.values().iterator(); it.hasNext(); ) {
            IgniteTxEntry e = it.next();
            GridCacheContext cacheCtx = e.context();
            GridCacheEntryEx cached = e.cached();
            if (cached != null) {
                if (cached.partition() == part)
                    it.remove();
            } else if (cacheCtx.affinity().partition(e.key()) == part)
                it.remove();
        }
    }
}
Also used : GridCacheEntryEx(org.apache.ignite.internal.processors.cache.GridCacheEntryEx) GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext)

Example 54 with GridCacheContext

use of org.apache.ignite.internal.processors.cache.GridCacheContext in project ignite by apache.

the class IgniteTxStateImpl method validateTopology.

/**
 * {@inheritDoc}
 */
@Override
public IgniteCheckedException validateTopology(GridCacheSharedContext cctx, boolean read, GridDhtTopologyFuture topFut) {
    Map<Integer, Set<KeyCacheObject>> keysByCacheId = new HashMap<>();
    for (IgniteTxKey key : txMap.keySet()) {
        Set<KeyCacheObject> set = keysByCacheId.get(key.cacheId());
        if (set == null)
            keysByCacheId.put(key.cacheId(), set = new HashSet<>());
        set.add(key.key());
    }
    StringBuilder invalidCaches = null;
    for (Map.Entry<Integer, Set<KeyCacheObject>> e : keysByCacheId.entrySet()) {
        int cacheId = e.getKey();
        GridCacheContext ctx = cctx.cacheContext(cacheId);
        assert ctx != null : cacheId;
        Throwable err = topFut.validateCache(ctx, recovery != null && recovery, read, null, e.getValue());
        if (err != null) {
            if (invalidCaches != null)
                invalidCaches.append(", ");
            else
                invalidCaches = new StringBuilder();
            invalidCaches.append(U.maskName(ctx.name()));
        }
    }
    if (invalidCaches != null) {
        return new IgniteCheckedException("Failed to perform cache operation (cache topology is not valid): " + invalidCaches);
    }
    for (int i = 0; i < activeCacheIds.size(); i++) {
        int cacheId = activeCacheIds.get(i);
        GridCacheContext<?, ?> cacheCtx = cctx.cacheContext(cacheId);
        if (CU.affinityNodes(cacheCtx, topFut.topologyVersion()).isEmpty()) {
            return new ClusterTopologyServerNotFoundException("Failed to map keys for cache (all " + "partition nodes left the grid): " + cacheCtx.name());
        }
    }
    return null;
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext) HashMap(java.util.HashMap) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) ClusterTopologyServerNotFoundException(org.apache.ignite.internal.cluster.ClusterTopologyServerNotFoundException) HashMap(java.util.HashMap) Map(java.util.Map) KeyCacheObject(org.apache.ignite.internal.processors.cache.KeyCacheObject)

Example 55 with GridCacheContext

use of org.apache.ignite.internal.processors.cache.GridCacheContext in project ignite by apache.

the class IgniteTxStateImpl method unwindEvicts.

/**
 * {@inheritDoc}
 */
@Override
public void unwindEvicts(GridCacheSharedContext cctx) {
    for (int i = 0; i < activeCacheIds.size(); i++) {
        int cacheId = activeCacheIds.get(i);
        GridCacheContext ctx = cctx.cacheContext(cacheId);
        if (ctx != null)
            CU.unwindEvicts(ctx);
    }
}
Also used : GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext)

Aggregations

GridCacheContext (org.apache.ignite.internal.processors.cache.GridCacheContext)147 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)37 GridCacheEntryRemovedException (org.apache.ignite.internal.processors.cache.GridCacheEntryRemovedException)22 HashMap (java.util.HashMap)21 ClusterNode (org.apache.ignite.cluster.ClusterNode)20 Map (java.util.Map)19 UUID (java.util.UUID)18 KeyCacheObject (org.apache.ignite.internal.processors.cache.KeyCacheObject)18 GridCacheEntryEx (org.apache.ignite.internal.processors.cache.GridCacheEntryEx)16 ArrayList (java.util.ArrayList)15 IgniteException (org.apache.ignite.IgniteException)14 CacheObject (org.apache.ignite.internal.processors.cache.CacheObject)14 List (java.util.List)13 AffinityTopologyVersion (org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion)13 GridCacheVersion (org.apache.ignite.internal.processors.cache.version.GridCacheVersion)13 ClusterTopologyCheckedException (org.apache.ignite.internal.cluster.ClusterTopologyCheckedException)11 ConcurrentMap (java.util.concurrent.ConcurrentMap)10 IgniteTxEntry (org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry)10 GridCacheEntryInfo (org.apache.ignite.internal.processors.cache.GridCacheEntryInfo)9 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)8