Search in sources :

Example 6 with GridNearCacheEntry

use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheEntry in project ignite by apache.

the class GridDistributedTxRemoteAdapter method commitIfLocked.

/**
     * @throws IgniteCheckedException If commit failed.
     */
@SuppressWarnings({ "CatchGenericClass" })
private void commitIfLocked() throws IgniteCheckedException {
    if (state() == COMMITTING) {
        for (IgniteTxEntry txEntry : writeEntries()) {
            assert txEntry != null : "Missing transaction entry for tx: " + this;
            while (true) {
                GridCacheEntryEx entry = txEntry.cached();
                assert entry != null : "Missing cached entry for transaction entry: " + txEntry;
                try {
                    GridCacheVersion ver = txEntry.explicitVersion() != null ? txEntry.explicitVersion() : xidVer;
                    // If locks haven't been acquired yet, keep waiting.
                    if (!entry.lockedBy(ver)) {
                        if (log.isDebugEnabled())
                            log.debug("Transaction does not own lock for entry (will wait) [entry=" + entry + ", tx=" + this + ']');
                        return;
                    }
                    // While.
                    break;
                } catch (GridCacheEntryRemovedException ignore) {
                    if (log.isDebugEnabled())
                        log.debug("Got removed entry while committing (will retry): " + txEntry);
                    txEntry.cached(txEntry.context().cache().entryEx(txEntry.key(), topologyVersion()));
                }
            }
        }
        // Only one thread gets to commit.
        if (COMMIT_ALLOWED_UPD.compareAndSet(this, 0, 1)) {
            IgniteCheckedException err = null;
            Map<IgniteTxKey, IgniteTxEntry> writeMap = txState.writeMap();
            GridCacheReturnCompletableWrapper wrapper = null;
            if (!F.isEmpty(writeMap)) {
                GridCacheReturn ret = null;
                if (!near() && !local() && onePhaseCommit()) {
                    if (needReturnValue()) {
                        ret = new GridCacheReturn(null, cctx.localNodeId().equals(otherNodeId()), true, null, true);
                        // Originating node.
                        UUID origNodeId = otherNodeId();
                        cctx.tm().addCommittedTxReturn(this, wrapper = new GridCacheReturnCompletableWrapper(!cctx.localNodeId().equals(origNodeId) ? origNodeId : null));
                    } else
                        cctx.tm().addCommittedTx(this, this.nearXidVersion(), null);
                }
                // Register this transaction as completed prior to write-phase to
                // ensure proper lock ordering for removed entries.
                cctx.tm().addCommittedTx(this);
                AffinityTopologyVersion topVer = topologyVersion();
                WALPointer ptr = null;
                cctx.database().checkpointReadLock();
                try {
                    Collection<IgniteTxEntry> entries = near() ? allEntries() : writeEntries();
                    List<DataEntry> dataEntries = null;
                    batchStoreCommit(writeMap().values());
                    try {
                        // Node that for near transactions we grab all entries.
                        for (IgniteTxEntry txEntry : entries) {
                            GridCacheContext cacheCtx = txEntry.context();
                            boolean replicate = cacheCtx.isDrEnabled();
                            try {
                                while (true) {
                                    try {
                                        GridCacheEntryEx cached = txEntry.cached();
                                        if (cached == null)
                                            txEntry.cached(cached = cacheCtx.cache().entryEx(txEntry.key(), topologyVersion()));
                                        if (near() && cacheCtx.dr().receiveEnabled()) {
                                            cached.markObsolete(xidVer);
                                            break;
                                        }
                                        GridNearCacheEntry nearCached = null;
                                        if (updateNearCache(cacheCtx, txEntry.key(), topVer))
                                            nearCached = cacheCtx.dht().near().peekExx(txEntry.key());
                                        if (!F.isEmpty(txEntry.entryProcessors()))
                                            txEntry.cached().unswap(false);
                                        IgniteBiTuple<GridCacheOperation, CacheObject> res = applyTransformClosures(txEntry, false, ret);
                                        GridCacheOperation op = res.get1();
                                        CacheObject val = res.get2();
                                        GridCacheVersion explicitVer = txEntry.conflictVersion();
                                        if (explicitVer == null)
                                            explicitVer = writeVersion();
                                        if (txEntry.ttl() == CU.TTL_ZERO)
                                            op = DELETE;
                                        boolean conflictNeedResolve = cacheCtx.conflictNeedResolve();
                                        GridCacheVersionConflictContext conflictCtx = null;
                                        if (conflictNeedResolve) {
                                            IgniteBiTuple<GridCacheOperation, GridCacheVersionConflictContext> drRes = conflictResolve(op, txEntry, val, explicitVer, cached);
                                            assert drRes != null;
                                            conflictCtx = drRes.get2();
                                            if (conflictCtx.isUseOld())
                                                op = NOOP;
                                            else if (conflictCtx.isUseNew()) {
                                                txEntry.ttl(conflictCtx.ttl());
                                                txEntry.conflictExpireTime(conflictCtx.expireTime());
                                            } else if (conflictCtx.isMerge()) {
                                                op = drRes.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;
                                        GridCacheVersion dhtVer = cached.isNear() ? writeVersion() : null;
                                        if (!near() && cctx.wal() != null && op != NOOP && op != RELOAD && op != READ) {
                                            if (dataEntries == null)
                                                dataEntries = new ArrayList<>(entries.size());
                                            dataEntries.add(new DataEntry(cacheCtx.cacheId(), txEntry.key(), val, op, nearXidVersion(), writeVersion(), 0, txEntry.key().partition(), txEntry.updateCounter()));
                                        }
                                        if (op == CREATE || op == UPDATE) {
                                            // Invalidate only for near nodes (backups cannot be invalidated).
                                            if (isSystemInvalidate() || (isInvalidate() && cacheCtx.isNear()))
                                                cached.innerRemove(this, eventNodeId(), nodeId, false, true, true, txEntry.keepBinary(), txEntry.hasOldValue(), txEntry.oldValue(), topVer, null, replicate ? DR_BACKUP : DR_NONE, near() ? null : explicitVer, CU.subjectId(this, cctx), resolveTaskName(), dhtVer, txEntry.updateCounter());
                                            else {
                                                cached.innerSet(this, eventNodeId(), nodeId, val, false, false, txEntry.ttl(), true, true, txEntry.keepBinary(), txEntry.hasOldValue(), txEntry.oldValue(), topVer, null, replicate ? DR_BACKUP : DR_NONE, txEntry.conflictExpireTime(), near() ? null : explicitVer, CU.subjectId(this, cctx), resolveTaskName(), dhtVer, txEntry.updateCounter());
                                                // Keep near entry up to date.
                                                if (nearCached != null) {
                                                    CacheObject val0 = cached.valueBytes();
                                                    nearCached.updateOrEvict(xidVer, val0, cached.expireTime(), cached.ttl(), nodeId, topVer);
                                                }
                                            }
                                        } else if (op == DELETE) {
                                            cached.innerRemove(this, eventNodeId(), nodeId, false, true, true, txEntry.keepBinary(), txEntry.hasOldValue(), txEntry.oldValue(), topVer, null, replicate ? DR_BACKUP : DR_NONE, near() ? null : explicitVer, CU.subjectId(this, cctx), resolveTaskName(), dhtVer, txEntry.updateCounter());
                                            // Keep near entry up to date.
                                            if (nearCached != null)
                                                nearCached.updateOrEvict(xidVer, null, 0, 0, nodeId, topVer);
                                        } else if (op == RELOAD) {
                                            CacheObject reloaded = cached.innerReload();
                                            if (nearCached != null) {
                                                nearCached.innerReload();
                                                nearCached.updateOrEvict(cached.version(), reloaded, cached.expireTime(), cached.ttl(), nodeId, topVer);
                                            }
                                        } else if (op == READ) {
                                            assert near();
                                            if (log.isDebugEnabled())
                                                log.debug("Ignoring READ entry when committing: " + txEntry);
                                        } else // No-op.
                                        {
                                            if (conflictCtx == null || !conflictCtx.isUseOld()) {
                                                if (txEntry.ttl() != CU.TTL_NOT_CHANGED)
                                                    cached.updateTtl(null, txEntry.ttl());
                                                if (nearCached != null) {
                                                    CacheObject val0 = cached.valueBytes();
                                                    nearCached.updateOrEvict(xidVer, val0, cached.expireTime(), cached.ttl(), nodeId, topVer);
                                                }
                                            }
                                        }
                                        // that if we replaced removed entries.
                                        assert txEntry.op() == READ || onePhaseCommit() || // and we simply allow the commit to proceed.
                                        !cached.hasLockCandidateUnsafe(xidVer) || cached.lockedByUnsafe(xidVer) : "Transaction does not own lock for commit [entry=" + cached + ", tx=" + this + ']';
                                        // Break out of while loop.
                                        break;
                                    } catch (GridCacheEntryRemovedException ignored) {
                                        if (log.isDebugEnabled())
                                            log.debug("Attempting to commit a removed entry (will retry): " + txEntry);
                                        // Renew cached entry.
                                        txEntry.cached(cacheCtx.cache().entryEx(txEntry.key(), topologyVersion()));
                                    }
                                }
                            } catch (Throwable ex) {
                                // In case of error, we still make the best effort to commit,
                                // as there is no way to rollback at this point.
                                err = new IgniteTxHeuristicCheckedException("Commit produced a runtime exception " + "(all transaction entries will be invalidated): " + CU.txString(this), ex);
                                U.error(log, "Commit failed.", err);
                                uncommit();
                                state(UNKNOWN);
                                if (ex instanceof Error)
                                    throw (Error) ex;
                            }
                        }
                        if (!near() && cctx.wal() != null)
                            cctx.wal().log(new DataRecord(dataEntries));
                        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();
                    }
                } finally {
                    if (wrapper != null)
                        wrapper.initialize(ret);
                }
            }
            if (err != null) {
                state(UNKNOWN);
                throw err;
            }
            cctx.tm().commitTx(this);
            state(COMMITTED);
        }
    }
}
Also used : ArrayList(java.util.ArrayList) 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) 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) IgniteTxEntry(org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry) GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext) GridCacheReturn(org.apache.ignite.internal.processors.cache.GridCacheReturn) AffinityTopologyVersion(org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion) GridCacheVersionConflictContext(org.apache.ignite.internal.processors.cache.version.GridCacheVersionConflictContext) GridCacheEntryEx(org.apache.ignite.internal.processors.cache.GridCacheEntryEx) GridNearCacheEntry(org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheEntry) IgniteTxKey(org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey) GridCacheOperation(org.apache.ignite.internal.processors.cache.GridCacheOperation) GridCacheReturnCompletableWrapper(org.apache.ignite.internal.processors.cache.GridCacheReturnCompletableWrapper) StorageException(org.apache.ignite.internal.pagemem.wal.StorageException)

Example 7 with GridNearCacheEntry

use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheEntry in project ignite by apache.

the class IgniteTxManager method removeObsolete.

/**
     * @param tx Transaction.
     */
private void removeObsolete(IgniteInternalTx tx) {
    Collection<IgniteTxEntry> entries = tx.local() ? tx.allEntries() : tx.writeEntries();
    for (IgniteTxEntry entry : entries) {
        GridCacheEntryEx cached = entry.cached();
        GridCacheContext cacheCtx = entry.context();
        if (cached == null)
            cached = cacheCtx.cache().peekEx(entry.key());
        if (cached.detached())
            continue;
        try {
            if (cached.obsolete() || cached.markObsoleteIfEmpty(tx.xidVersion()))
                cacheCtx.cache().removeEntry(cached);
            if (!tx.near() && isNearEnabled(cacheCtx)) {
                GridNearCacheAdapter near = cacheCtx.isNear() ? cacheCtx.near() : cacheCtx.dht().near();
                GridNearCacheEntry e = near.peekExx(entry.key());
                if (e != null && e.markObsoleteIfEmpty(tx.xidVersion()))
                    near.removeEntry(e);
            }
        } catch (IgniteCheckedException e) {
            U.error(log, "Failed to remove obsolete entry from cache: " + cached, e);
        }
    }
}
Also used : GridCacheEntryEx(org.apache.ignite.internal.processors.cache.GridCacheEntryEx) GridNearCacheEntry(org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheEntry) GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) GridNearCacheAdapter(org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheAdapter)

Example 8 with GridNearCacheEntry

use of org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheEntry in project ignite by apache.

the class GridCacheVersionMultinodeTest method checkEntryVersion.

/**
     * @param key Key.
     * @throws Exception If failed.
     */
private void checkEntryVersion(String key) throws Exception {
    GridCacheVersion ver = null;
    boolean verified = false;
    for (int i = 0; i < gridCount(); i++) {
        IgniteKernal grid = (IgniteKernal) grid(i);
        GridCacheAdapter<Object, Object> cache = grid.context().cache().internalCache(DEFAULT_CACHE_NAME);
        GridCacheEntryEx e;
        if (cache.affinity().isPrimaryOrBackup(grid.localNode(), key)) {
            if (cache instanceof GridNearCacheAdapter)
                cache = ((GridNearCacheAdapter<Object, Object>) cache).dht();
            e = cache.entryEx(key);
            e.unswap();
            assertNotNull(e.rawGet());
        } else
            e = cache.peekEx(key);
        if (e != null) {
            if (ver != null) {
                assertEquals("Non-equal versions for key: " + key, ver, e instanceof GridNearCacheEntry ? ((GridNearCacheEntry) e).dhtVersion() : e.version());
                verified = true;
            } else
                ver = e instanceof GridNearCacheEntry ? ((GridNearCacheEntry) e).dhtVersion() : e.version();
        }
    }
    assertTrue(verified);
}
Also used : IgniteKernal(org.apache.ignite.internal.IgniteKernal) GridCacheVersion(org.apache.ignite.internal.processors.cache.version.GridCacheVersion) GridNearCacheEntry(org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheEntry) GridNearCacheAdapter(org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheAdapter)

Aggregations

GridNearCacheEntry (org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheEntry)8 GridCacheVersion (org.apache.ignite.internal.processors.cache.version.GridCacheVersion)5 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)3 GridCacheEntryEx (org.apache.ignite.internal.processors.cache.GridCacheEntryEx)3 GridNearCacheAdapter (org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheAdapter)3 IgniteKernal (org.apache.ignite.internal.IgniteKernal)2 GridCacheAdapter (org.apache.ignite.internal.processors.cache.GridCacheAdapter)2 GridCacheContext (org.apache.ignite.internal.processors.cache.GridCacheContext)2 ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 HashSet (java.util.HashSet)1 Set (java.util.Set)1 UUID (java.util.UUID)1 TimeoutException (java.util.concurrent.TimeoutException)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 CacheException (javax.cache.CacheException)1 Ignite (org.apache.ignite.Ignite)1 IgniteCache (org.apache.ignite.IgniteCache)1 IgniteException (org.apache.ignite.IgniteException)1 CacheConfiguration (org.apache.ignite.configuration.CacheConfiguration)1