Search in sources :

Example 16 with WALPointer

use of org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer in project ignite by apache.

the class CdcCacheVersionTest method testConflictVersionWritten.

/**
 * Test that conflict version is writtern to WAL.
 */
@Test
public void testConflictVersionWritten() throws Exception {
    walProvider = (ctx) -> new FileWriteAheadLogManager(ctx) {

        @Override
        public WALPointer log(WALRecord rec) throws IgniteCheckedException {
            if (rec.type() != DATA_RECORD_V2)
                return super.log(rec);
            DataRecord dataRec = (DataRecord) rec;
            for (int i = 0; i < dataRec.entryCount(); i++) {
                DataEntry dataEntry = dataRec.writeEntries().get(i);
                assertEquals(CU.cacheId(DEFAULT_CACHE_NAME), dataEntry.cacheId());
                assertEquals(DFLT_CLUSTER_ID, dataEntry.writeVersion().dataCenterId());
                assertNotNull(dataEntry.writeVersion().conflictVersion());
                assertEquals(OTHER_CLUSTER_ID, dataEntry.writeVersion().conflictVersion().dataCenterId());
                walRecCheckedCntr.incrementAndGet();
            }
            return super.log(rec);
        }
    };
    conflictResolutionMgrSupplier = () -> new CacheVersionConflictResolver() {

        @Override
        public <K1, V1> GridCacheVersionConflictContext<K1, V1> resolve(CacheObjectValueContext ctx, GridCacheVersionedEntryEx<K1, V1> oldEntry, GridCacheVersionedEntryEx<K1, V1> newEntry, boolean atomicVerComparator) {
            GridCacheVersionConflictContext<K1, V1> res = new GridCacheVersionConflictContext<>(ctx, oldEntry, newEntry);
            res.useNew();
            assertEquals(OTHER_CLUSTER_ID, newEntry.version().dataCenterId());
            if (!oldEntry.isStartVersion())
                assertEquals(OTHER_CLUSTER_ID, oldEntry.version().dataCenterId());
            conflictCheckedCntr.incrementAndGet();
            return res;
        }

        @Override
        public String toString() {
            return "TestCacheConflictResolutionManager";
        }
    };
    startGrids(gridCnt);
    IgniteEx cli = startClientGrid(gridCnt);
    for (int i = 0; i < gridCnt; i++) {
        grid(i).context().cache().context().versions().dataCenterId(DFLT_CLUSTER_ID);
        assertEquals(DFLT_CLUSTER_ID, grid(i).context().metric().registry(CACHE_METRICS).<IntMetric>findMetric(DATA_VER_CLUSTER_ID).value());
    }
    cli.cluster().state(ACTIVE);
    IgniteCache<Integer, User> cache = cli.getOrCreateCache(new CacheConfiguration<Integer, User>(DEFAULT_CACHE_NAME).setCacheMode(cacheMode).setAtomicityMode(atomicityMode).setBackups(Integer.MAX_VALUE));
    if (atomicityMode == ATOMIC)
        putRemoveCheck(cli, cache, null, null);
    else {
        // Check operations for transaction cache without explicit transaction.
        putRemoveCheck(cli, cache, null, null);
        // Check operations for transaction cache with explicit transaction in all modes.
        for (TransactionConcurrency concurrency : TransactionConcurrency.values()) for (TransactionIsolation isolation : TransactionIsolation.values()) putRemoveCheck(cli, cache, concurrency, isolation);
    }
    for (int i = 0; i < gridCnt; i++) {
        boolean dfltCacheFound = false;
        assertFalse(grid(i).context().clientNode());
        SystemView<CacheView> caches = grid(i).context().systemView().view(CACHES_VIEW);
        for (CacheView v : caches) {
            if (v.cacheName().equals(DEFAULT_CACHE_NAME)) {
                assertEquals(v.conflictResolver(), "TestCacheConflictResolutionManager");
                dfltCacheFound = true;
            } else
                assertNull(v.conflictResolver());
        }
        assertTrue(dfltCacheFound);
    }
}
Also used : WALRecord(org.apache.ignite.internal.pagemem.wal.record.WALRecord) TransactionIsolation(org.apache.ignite.transactions.TransactionIsolation) DataEntry(org.apache.ignite.internal.pagemem.wal.record.DataEntry) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) CacheView(org.apache.ignite.spi.systemview.view.CacheView) CacheObjectValueContext(org.apache.ignite.internal.processors.cache.CacheObjectValueContext) DataRecord(org.apache.ignite.internal.pagemem.wal.record.DataRecord) WALPointer(org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer) IntMetric(org.apache.ignite.spi.metric.IntMetric) CacheConfiguration(org.apache.ignite.configuration.CacheConfiguration) CacheVersionConflictResolver(org.apache.ignite.internal.processors.cache.version.CacheVersionConflictResolver) GridCacheVersionConflictContext(org.apache.ignite.internal.processors.cache.version.GridCacheVersionConflictContext) TransactionConcurrency(org.apache.ignite.transactions.TransactionConcurrency) IgniteEx(org.apache.ignite.internal.IgniteEx) FileWriteAheadLogManager(org.apache.ignite.internal.processors.cache.persistence.wal.FileWriteAheadLogManager) Test(org.junit.Test)

Example 17 with WALPointer

use of org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer in project ignite by apache.

the class AbstractCdcTest method createCdc.

/**
 */
protected CdcMain createCdc(CdcConsumer cnsmr, IgniteConfiguration cfg, CountDownLatch latch, GridAbsPredicate... conditions) {
    CdcConfiguration cdcCfg = new CdcConfiguration();
    cdcCfg.setConsumer(cnsmr);
    cdcCfg.setKeepBinary(keepBinary());
    cdcCfg.setMetricExporterSpi(metricExporters());
    return new CdcMain(cfg, null, cdcCfg) {

        @Override
        protected CdcConsumerState createState(Path stateDir) {
            return new CdcConsumerState(stateDir) {

                @Override
                public void save(WALPointer ptr) throws IOException {
                    super.save(ptr);
                    if (!F.isEmpty(conditions)) {
                        for (GridAbsPredicate p : conditions) {
                            if (!p.apply())
                                return;
                        }
                        latch.countDown();
                    }
                }
            };
        }
    };
}
Also used : Path(java.nio.file.Path) CdcConsumerState(org.apache.ignite.internal.cdc.CdcConsumerState) GridAbsPredicate(org.apache.ignite.internal.util.lang.GridAbsPredicate) CdcMain(org.apache.ignite.internal.cdc.CdcMain) WALPointer(org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer)

Example 18 with WALPointer

use of org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer in project ignite by apache.

the class GridCacheMapEntry method innerRemove.

/**
 * {@inheritDoc}
 */
@Override
public final GridCacheUpdateTxResult innerRemove(@Nullable IgniteInternalTx tx, UUID evtNodeId, UUID affNodeId, boolean retval, boolean evt, boolean metrics, boolean keepBinary, boolean oldValPresent, @Nullable CacheObject oldVal, AffinityTopologyVersion topVer, CacheEntryPredicate[] filter, GridDrType drType, @Nullable GridCacheVersion explicitVer, String taskName, @Nullable GridCacheVersion dhtVer, @Nullable Long updateCntr) throws IgniteCheckedException, GridCacheEntryRemovedException {
    assert cctx.transactional();
    CacheObject old;
    GridCacheVersion newVer;
    final boolean valid = valid(tx != null ? tx.topologyVersion() : topVer);
    // Lock should be held by now.
    if (!cctx.isAll(this, filter))
        return new GridCacheUpdateTxResult(false);
    GridCacheVersion obsoleteVer = null;
    boolean intercept = cctx.config().getInterceptor() != null;
    IgniteBiTuple<Boolean, Object> interceptRes = null;
    CacheLazyEntry entry0 = null;
    long updateCntr0;
    WALPointer logPtr = null;
    boolean deferred;
    boolean marked = false;
    lockListenerReadLock();
    lockEntry();
    try {
        checkObsolete();
        if (isNear()) {
            assert dhtVer != null;
            // It is possible that 'get' could load more recent value.
            if (!((GridNearCacheEntry) this).recordDhtVersion(dhtVer))
                return new GridCacheUpdateTxResult(false, logPtr);
        }
        assert tx == null || (!tx.local() && tx.onePhaseCommit()) || tx.ownsLock(this) : "Transaction does not own lock for remove[entry=" + this + ", tx=" + tx + ']';
        boolean startVer = isStartVersion();
        newVer = explicitVer != null ? explicitVer : tx == null ? nextVersion() : tx.writeVersion();
        boolean internal = isInternal() || !context().userCache();
        Map<UUID, CacheContinuousQueryListener> lsnrCol = notifyContinuousQueries() ? cctx.continuousQueries().updateListeners(internal, false) : null;
        if (startVer && (retval || intercept || lsnrCol != null))
            unswap();
        old = oldValPresent ? oldVal : val;
        if (intercept)
            intercept = !skipInterceptor(explicitVer);
        if (intercept) {
            entry0 = new CacheLazyEntry(cctx, key, old, keepBinary);
            interceptRes = cctx.config().getInterceptor().onBeforeRemove(entry0);
            if (cctx.cancelRemove(interceptRes)) {
                CacheObject ret = cctx.toCacheObject(cctx.unwrapTemporary(interceptRes.get2()));
                return new GridCacheUpdateTxResult(false, logPtr);
            }
        }
        removeValue();
        update(null, 0, 0, newVer, true);
        if (cctx.deferredDelete() && !detached() && !isInternal()) {
            if (!deletedUnlocked()) {
                deletedUnlocked(true);
                if (tx != null) {
                    GridCacheMvcc mvcc = mvccExtras();
                    if (mvcc == null || mvcc.isEmpty(tx.xidVersion()))
                        clearReaders();
                    else {
                        // Optimize memory usage - do not allocate additional array.
                        List<GridCacheMvccCandidate> locs = mvcc.localCandidatesNoCopy(false);
                        GridCacheVersion txVer = tx.xidVersion();
                        UUID originatingNodeId = tx.originatingNodeId();
                        boolean hasOriginatingNodeId = false;
                        for (GridCacheMvccCandidate c : locs) {
                            if (c.reentry() || Objects.equals(c.version(), txVer))
                                continue;
                            if (Objects.equals(c.otherNodeId(), originatingNodeId)) {
                                hasOriginatingNodeId = true;
                                break;
                            }
                        }
                        // Remove reader only if there are no other active transactions from it.
                        if (!hasOriginatingNodeId)
                            clearReader(originatingNodeId);
                    }
                }
            }
        }
        updateCntr0 = nextPartitionCounter(tx, updateCntr);
        if (tx != null && cctx.group().persistenceEnabled() && cctx.group().walEnabled())
            logPtr = logTxUpdate(tx, null, addConflictVersion(tx.writeVersion(), newVer), 0, updateCntr0);
        drReplicate(drType, null, newVer, topVer);
        if (metrics && cctx.statisticsEnabled()) {
            cctx.cache().metrics0().onRemove();
            T2<GridCacheOperation, CacheObject> entryProcRes = tx.entry(txKey()).entryProcessorCalculatedValue();
            if (entryProcRes != null && DELETE.equals(entryProcRes.get1()))
                cctx.cache().metrics0().onInvokeRemove(old != null);
        }
        if (tx == null)
            obsoleteVer = newVer;
        else {
            // Only delete entry if the lock is not explicit.
            if (lockedBy(tx.xidVersion()))
                obsoleteVer = tx.xidVersion();
            else if (log.isDebugEnabled())
                log.debug("Obsolete version was not set because lock was explicit: " + this);
        }
        if (evt && newVer != null && cctx.events().isRecordable(EVT_CACHE_OBJECT_REMOVED)) {
            CacheObject evtOld = cctx.unwrapTemporary(old);
            cctx.events().addEvent(partition(), key, evtNodeId, tx, null, newVer, EVT_CACHE_OBJECT_REMOVED, null, false, evtOld, evtOld != null || hasValueUnlocked(), null, taskName, keepBinary);
        }
        if (lsnrCol != null) {
            cctx.continuousQueries().onEntryUpdated(lsnrCol, key, null, old, internal, partition(), tx.local(), false, updateCntr0, null, topVer);
        }
        deferred = cctx.deferredDelete() && !detached();
        if (intercept)
            entry0.updateCounter(updateCntr0);
        if (!deferred) {
            // If entry is still removed.
            assert newVer == ver;
            if (obsoleteVer == null || !(marked = markObsolete0(obsoleteVer, true, null))) {
                if (log.isDebugEnabled())
                    log.debug("Entry could not be marked obsolete (it is still used): " + this);
            } else {
                recordNodeId(affNodeId, topVer);
                if (log.isDebugEnabled())
                    log.debug("Entry was marked obsolete: " + this);
            }
        }
    } finally {
        unlockEntry();
        unlockListenerReadLock();
    }
    if (marked) {
        assert !deferred;
        onMarkedObsolete();
    }
    onUpdateFinished(updateCntr0);
    if (intercept)
        cctx.config().getInterceptor().onAfterRemove(entry0);
    if (valid)
        return new GridCacheUpdateTxResult(true, updateCntr0, logPtr);
    else
        return new GridCacheUpdateTxResult(false, logPtr);
}
Also used : GridCacheVersion(org.apache.ignite.internal.processors.cache.version.GridCacheVersion) CacheContinuousQueryListener(org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryListener) UUID(java.util.UUID) WALPointer(org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer)

Example 19 with WALPointer

use of org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer in project ignite by apache.

the class GridCacheMapEntry method mvccLock.

/**
 * {@inheritDoc}
 */
@Override
public GridCacheUpdateTxResult mvccLock(GridDhtTxLocalAdapter tx, MvccSnapshot mvccVer) throws GridCacheEntryRemovedException, IgniteCheckedException {
    assert tx != null;
    assert mvccVer != null;
    final boolean valid = valid(tx.topologyVersion());
    final GridCacheVersion newVer;
    WALPointer logPtr = null;
    lockEntry();
    try {
        checkObsolete();
        newVer = tx.writeVersion();
        assert newVer != null : "Failed to get write version for tx: " + tx;
        assert tx.local();
        MvccUpdateResult res = cctx.offheap().mvccLock(this, mvccVer);
        assert res != null;
        if (res.resultType() == ResultType.VERSION_MISMATCH)
            throw serializationError();
        else if (res.resultType() == ResultType.LOCKED) {
            unlockEntry();
            MvccVersion lockVer = res.resultVersion();
            GridFutureAdapter<GridCacheUpdateTxResult> resFut = new GridFutureAdapter<>();
            IgniteInternalFuture<?> lockFut = cctx.kernalContext().coordinators().waitForLock(cctx, mvccVer, lockVer);
            lockFut.listen(new MvccAcquireLockListener(tx, this, mvccVer, resFut));
            return new GridCacheUpdateTxResult(false, resFut);
        }
    } finally {
        if (lockedByCurrentThread()) {
            unlockEntry();
            cctx.evicts().touch(this);
        }
    }
    onUpdateFinished(0L);
    return new GridCacheUpdateTxResult(valid, logPtr);
}
Also used : GridCacheVersion(org.apache.ignite.internal.processors.cache.version.GridCacheVersion) MvccVersion(org.apache.ignite.internal.processors.cache.mvcc.MvccVersion) MvccUpdateResult(org.apache.ignite.internal.processors.cache.tree.mvcc.data.MvccUpdateResult) GridFutureAdapter(org.apache.ignite.internal.util.future.GridFutureAdapter) IgniteInternalFuture(org.apache.ignite.internal.IgniteInternalFuture) WALPointer(org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer)

Example 20 with WALPointer

use of org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer in project ignite by apache.

the class GridCacheMapEntry method innerSet.

/**
 * {@inheritDoc}
 */
@Override
public final GridCacheUpdateTxResult innerSet(@Nullable IgniteInternalTx tx, UUID evtNodeId, UUID affNodeId, CacheObject val, boolean writeThrough, boolean retval, long ttl, boolean evt, boolean metrics, boolean keepBinary, boolean oldValPresent, @Nullable CacheObject oldVal, AffinityTopologyVersion topVer, CacheEntryPredicate[] filter, GridDrType drType, long drExpireTime, @Nullable GridCacheVersion explicitVer, String taskName, @Nullable GridCacheVersion dhtVer, @Nullable Long updateCntr) throws IgniteCheckedException, GridCacheEntryRemovedException {
    CacheObject old;
    final boolean valid = valid(tx != null ? tx.topologyVersion() : topVer);
    // Lock should be held by now.
    if (!cctx.isAll(this, filter))
        return new GridCacheUpdateTxResult(false);
    final GridCacheVersion newVer;
    boolean intercept = cctx.config().getInterceptor() != null;
    Object key0 = null;
    Object val0 = null;
    WALPointer logPtr = null;
    long updateCntr0;
    ensureFreeSpace();
    lockListenerReadLock();
    lockEntry();
    try {
        checkObsolete();
        if (isNear()) {
            assert dhtVer != null;
            // It is possible that 'get' could load more recent value.
            if (!((GridNearCacheEntry) this).recordDhtVersion(dhtVer))
                return new GridCacheUpdateTxResult(false, logPtr);
        }
        assert tx == null || (!tx.local() && tx.onePhaseCommit()) || tx.ownsLock(this) : "Transaction does not own lock for update [entry=" + this + ", tx=" + tx + ']';
        // Load and remove from swap if it is new.
        boolean startVer = isStartVersion();
        boolean internal = isInternal() || !context().userCache();
        Map<UUID, CacheContinuousQueryListener> lsnrCol = notifyContinuousQueries() ? cctx.continuousQueries().updateListeners(internal, false) : null;
        if (startVer && (retval || intercept || lsnrCol != null))
            unswap(retval);
        newVer = explicitVer != null ? explicitVer : tx == null ? nextVersion() : tx.writeVersion();
        assert newVer != null : "Failed to get write version for tx: " + tx;
        old = oldValPresent ? oldVal : this.val;
        if (intercept)
            intercept = !skipInterceptor(explicitVer);
        if (intercept) {
            val0 = cctx.unwrapBinaryIfNeeded(val, keepBinary, false, null);
            CacheLazyEntry e = new CacheLazyEntry(cctx, key, old, keepBinary);
            key0 = e.key();
            Object interceptorVal = cctx.config().getInterceptor().onBeforePut(e, val0);
            if (interceptorVal == null)
                return new GridCacheUpdateTxResult(false, logPtr);
            else if (interceptorVal != val0)
                val0 = cctx.unwrapTemporary(interceptorVal);
            val = cctx.toCacheObject(val0);
        }
        // Determine new ttl and expire time.
        long expireTime;
        if (drExpireTime >= 0) {
            assert ttl >= 0 : ttl;
            expireTime = drExpireTime;
        } else {
            if (ttl == -1L) {
                ttl = ttlExtras();
                expireTime = expireTimeExtras();
            } else
                expireTime = CU.toExpireTime(ttl);
        }
        assert ttl >= 0 : ttl;
        assert expireTime >= 0 : expireTime;
        // Detach value before index update.
        val = cctx.kernalContext().cacheObjects().prepareForCache(val, cctx);
        assert val != null;
        storeValue(val, expireTime, newVer);
        if (cctx.deferredDelete() && deletedUnlocked() && !isInternal() && !detached())
            deletedUnlocked(false);
        updateCntr0 = nextPartitionCounter(tx, updateCntr);
        if (tx != null && cctx.group().persistenceEnabled() && cctx.group().walEnabled())
            logPtr = logTxUpdate(tx, val, addConflictVersion(tx.writeVersion(), newVer), expireTime, updateCntr0);
        update(val, expireTime, ttl, newVer, true);
        drReplicate(drType, val, newVer, topVer);
        recordNodeId(affNodeId, topVer);
        if (metrics && cctx.statisticsEnabled() && tx != null) {
            cctx.cache().metrics0().onWrite();
            IgniteTxEntry txEntry = tx.entry(txKey());
            if (txEntry != null) {
                T2<GridCacheOperation, CacheObject> entryProcRes = txEntry.entryProcessorCalculatedValue();
                if (entryProcRes != null && UPDATE.equals(entryProcRes.get1()))
                    cctx.cache().metrics0().onInvokeUpdate(old != null);
            }
        }
        if (evt && newVer != null && cctx.events().isRecordable(EVT_CACHE_OBJECT_PUT)) {
            CacheObject evtOld = cctx.unwrapTemporary(old);
            cctx.events().addEvent(partition(), key, evtNodeId, tx, null, newVer, EVT_CACHE_OBJECT_PUT, val, val != null, evtOld, evtOld != null || hasValueUnlocked(), null, taskName, keepBinary);
        }
        if (lsnrCol != null) {
            cctx.continuousQueries().onEntryUpdated(lsnrCol, key, val, old, internal, partition(), tx.local(), false, updateCntr0, null, topVer);
        }
    } finally {
        unlockEntry();
        unlockListenerReadLock();
    }
    onUpdateFinished(updateCntr0);
    if (log.isDebugEnabled())
        log.debug("Updated cache entry [val=" + val + ", old=" + old + ", entry=" + this + ']');
    // value will be handled by current transaction.
    if (writeThrough)
        cctx.store().put(tx, key, val, newVer);
    if (intercept)
        cctx.config().getInterceptor().onAfterPut(new CacheLazyEntry(cctx, key, key0, val, val0, keepBinary, updateCntr0));
    updatePlatformCache(val, topVer);
    return valid ? new GridCacheUpdateTxResult(true, updateCntr0, logPtr) : new GridCacheUpdateTxResult(false, logPtr);
}
Also used : IgniteTxEntry(org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry) GridCacheVersion(org.apache.ignite.internal.processors.cache.version.GridCacheVersion) CacheContinuousQueryListener(org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryListener) UUID(java.util.UUID) WALPointer(org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer)

Aggregations

WALPointer (org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer)122 WALRecord (org.apache.ignite.internal.pagemem.wal.record.WALRecord)44 Test (org.junit.Test)41 IgniteEx (org.apache.ignite.internal.IgniteEx)38 WALIterator (org.apache.ignite.internal.pagemem.wal.WALIterator)36 GridCommonAbstractTest (org.apache.ignite.testframework.junits.common.GridCommonAbstractTest)30 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)27 CheckpointRecord (org.apache.ignite.internal.pagemem.wal.record.CheckpointRecord)24 IgniteWriteAheadLogManager (org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager)23 DataRecord (org.apache.ignite.internal.pagemem.wal.record.DataRecord)23 ArrayList (java.util.ArrayList)20 IgniteWalIteratorFactory (org.apache.ignite.internal.processors.cache.persistence.wal.reader.IgniteWalIteratorFactory)20 FullPageId (org.apache.ignite.internal.pagemem.FullPageId)19 DataEntry (org.apache.ignite.internal.pagemem.wal.record.DataEntry)19 PageSnapshot (org.apache.ignite.internal.pagemem.wal.record.PageSnapshot)19 File (java.io.File)18 T2 (org.apache.ignite.internal.util.typedef.T2)16 ByteBuffer (java.nio.ByteBuffer)15 UUID (java.util.UUID)15 IOException (java.io.IOException)14