Search in sources :

Example 1 with GridDrType

use of org.apache.ignite.internal.processors.dr.GridDrType 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() ? 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 (cctx.wal() != null && !writeEntries().isEmpty() && op != NOOP && op != RELOAD && op != READ)
                                    ptr = cctx.wal().log(new DataRecord(new DataEntry(cacheCtx.cacheId(), txEntry.key(), val, op, nearXidVersion(), writeVersion(), 0, txEntry.key().partition(), txEntry.updateCounter())));
                                if (op == CREATE || op == UPDATE) {
                                    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 (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 (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) {
                                    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 {
                        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);
                        U.error(log, "Heuristic transaction failure.", err);
                        COMMIT_ERR_UPD.compareAndSet(this, null, err);
                        state(UNKNOWN);
                        try {
                            // Courtesy to minimize damage.
                            uncommit();
                        } 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.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) 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) StorageException(org.apache.ignite.internal.pagemem.wal.StorageException)

Aggregations

UUID (java.util.UUID)1 Duration (javax.cache.expiry.Duration)1 ExpiryPolicy (javax.cache.expiry.ExpiryPolicy)1 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)1 StorageException (org.apache.ignite.internal.pagemem.wal.StorageException)1 WALPointer (org.apache.ignite.internal.pagemem.wal.WALPointer)1 DataEntry (org.apache.ignite.internal.pagemem.wal.record.DataEntry)1 DataRecord (org.apache.ignite.internal.pagemem.wal.record.DataRecord)1 AffinityTopologyVersion (org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion)1 CacheObject (org.apache.ignite.internal.processors.cache.CacheObject)1 GridCacheContext (org.apache.ignite.internal.processors.cache.GridCacheContext)1 GridCacheEntryEx (org.apache.ignite.internal.processors.cache.GridCacheEntryEx)1 GridCacheEntryRemovedException (org.apache.ignite.internal.processors.cache.GridCacheEntryRemovedException)1 GridCacheOperation (org.apache.ignite.internal.processors.cache.GridCacheOperation)1 GridCacheUpdateTxResult (org.apache.ignite.internal.processors.cache.GridCacheUpdateTxResult)1 IgniteCacheExpiryPolicy (org.apache.ignite.internal.processors.cache.IgniteCacheExpiryPolicy)1 KeyCacheObject (org.apache.ignite.internal.processors.cache.KeyCacheObject)1 GridCacheVersion (org.apache.ignite.internal.processors.cache.version.GridCacheVersion)1 GridCacheVersionConflictContext (org.apache.ignite.internal.processors.cache.version.GridCacheVersionConflictContext)1 GridDrType (org.apache.ignite.internal.processors.dr.GridDrType)1