Search in sources :

Example 1 with CacheContinuousQueryListener

use of org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryListener 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 2 with CacheContinuousQueryListener

use of org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryListener 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)

Example 3 with CacheContinuousQueryListener

use of org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryListener in project ignite by apache.

the class MvccCachingManager method onTxFinished.

/**
 * @param tx Transaction.
 * @param commit {@code True} if commit.
 */
public void onTxFinished(IgniteInternalTx tx, boolean commit) throws IgniteCheckedException {
    if (log.isDebugEnabled())
        log.debug("Transaction finished: [commit=" + commit + ", tx=" + tx + ']');
    if (tx.system() || tx.internal() || tx.mvccSnapshot() == null)
        return;
    cntrs.remove(new TxKey(tx.mvccSnapshot().coordinatorVersion(), tx.mvccSnapshot().counter()));
    EnlistBuffer buf = enlistCache.remove(tx.xidVersion());
    Map<Integer, Map<KeyCacheObject, MvccTxEntry>> allCached = buf == null ? null : buf.getCached();
    TxCounters txCntrs = tx.txCounters(false);
    Collection<PartitionUpdateCountersMessage> cntrsColl = txCntrs == null ? null : txCntrs.updateCounters();
    if (txCntrs == null || F.isEmpty(cntrsColl))
        return;
    GridIntList cacheIds = tx.txState().cacheIds();
    assert cacheIds != null;
    for (int i = 0; i < cacheIds.size(); i++) {
        int cacheId = cacheIds.get(i);
        GridCacheContext ctx0 = cctx.cacheContext(cacheId);
        assert ctx0 != null;
        ctx0.group().listenerLock().readLock().lock();
        try {
            boolean hasListeners = ctx0.hasContinuousQueryListeners(tx);
            boolean drEnabled = ctx0.isDrEnabled();
            if (!hasListeners && !drEnabled)
                // There are no listeners to notify.
                continue;
            // Get cached entries for the given cache.
            Map<KeyCacheObject, MvccTxEntry> cached = allCached == null ? null : allCached.get(cacheId);
            Map<Integer, Map<Integer, T2<AtomicLong, Long>>> cntrsMap = countersPerPartition(cntrsColl);
            Map<Integer, T2<AtomicLong, Long>> cntrPerCache = cntrsMap.get(cacheId);
            if (F.isEmpty(cntrPerCache))
                // No updates were made for this cache.
                continue;
            boolean fakeEntries = false;
            if (F.isEmpty(cached)) {
                if (log.isDebugEnabled())
                    log.debug("Transaction updates were not cached fully (this can happen when listener started" + " during the transaction execution). [tx=" + tx + ']');
                if (hasListeners) {
                    // Create fake update entries if we have CQ listeners.
                    cached = createFakeCachedEntries(cntrPerCache, tx, cacheId);
                    fakeEntries = true;
                } else
                    // Nothing to do further if tx is not cached entirely and there are no any CQ listeners.
                    continue;
            }
            if (F.isEmpty(cached))
                continue;
            // Feed CQ & DR with entries.
            for (Map.Entry<KeyCacheObject, MvccTxEntry> entry : cached.entrySet()) {
                MvccTxEntry e = entry.getValue();
                assert e.key().partition() != -1;
                assert cntrPerCache != null;
                assert e.cacheId() == cacheId;
                T2<AtomicLong, Long> cntr = cntrPerCache.get(e.key().partition());
                long resCntr = cntr.getKey().incrementAndGet();
                assert resCntr <= cntr.getValue();
                e.updateCounter(resCntr);
                if (ctx0.group().sharedGroup()) {
                    ctx0.group().onPartitionCounterUpdate(cacheId, e.key().partition(), resCntr, tx.topologyVersion(), tx.local());
                }
                if (log.isDebugEnabled())
                    log.debug("Process cached entry:" + e);
                // DR
                if (ctx0.isDrEnabled() && !fakeEntries) {
                    ctx0.dr().replicate(e.key(), e.value(), e.ttl(), e.expireTime(), e.version(), tx.local() ? DR_PRIMARY : DR_BACKUP, e.topologyVersion());
                }
                // CQ
                CacheContinuousQueryManager contQryMgr = ctx0.continuousQueries();
                if (ctx0.continuousQueries().notifyContinuousQueries(tx)) {
                    Map<UUID, CacheContinuousQueryListener> lsnrCol = continuousQueryListeners(ctx0, tx);
                    if (!F.isEmpty(lsnrCol)) {
                        contQryMgr.onEntryUpdated(lsnrCol, e.key(), // Force skip update counter if rolled back.
                        commit ? e.value() : null, // Force skip update counter if rolled back.
                        commit ? e.oldValue() : null, false, e.key().partition(), tx.local(), false, e.updateCounter(), null, e.topologyVersion());
                    }
                }
            }
        } finally {
            ctx0.group().listenerLock().readLock().unlock();
        }
    }
}
Also used : TxKey(org.apache.ignite.internal.processors.cache.mvcc.txlog.TxKey) CacheContinuousQueryManager(org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryManager) CacheContinuousQueryListener(org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryListener) PartitionUpdateCountersMessage(org.apache.ignite.internal.processors.cache.distributed.dht.PartitionUpdateCountersMessage) UUID(java.util.UUID) T2(org.apache.ignite.internal.util.typedef.T2) KeyCacheObject(org.apache.ignite.internal.processors.cache.KeyCacheObject) TxCounters(org.apache.ignite.internal.processors.cache.transactions.TxCounters) GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext) GridIntList(org.apache.ignite.internal.util.GridIntList) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicLong(java.util.concurrent.atomic.AtomicLong) AtomicLong(java.util.concurrent.atomic.AtomicLong) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) TreeMap(java.util.TreeMap) SortedMap(java.util.SortedMap)

Example 4 with CacheContinuousQueryListener

use of org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryListener in project ignite by apache.

the class GridCacheMapEntry method innerUpdateLocal.

/**
 * {@inheritDoc}
 */
@SuppressWarnings("unchecked")
@Override
public GridTuple3<Boolean, Object, EntryProcessorResult<Object>> innerUpdateLocal(GridCacheVersion ver, GridCacheOperation op, @Nullable Object writeObj, @Nullable Object[] invokeArgs, boolean writeThrough, boolean readThrough, boolean retval, boolean keepBinary, @Nullable ExpiryPolicy expiryPlc, boolean evt, boolean metrics, @Nullable CacheEntryPredicate[] filter, boolean intercept, @Nullable UUID subjId, String taskName) throws IgniteCheckedException, GridCacheEntryRemovedException {
    assert cctx.isLocal() && cctx.atomic();
    CacheObject old;
    boolean res = true;
    IgniteBiTuple<Boolean, ?> interceptorRes = null;
    EntryProcessorResult<Object> invokeRes = null;
    lockEntry();
    try {
        boolean internal = isInternal() || !context().userCache();
        Map<UUID, CacheContinuousQueryListener> lsnrCol = cctx.continuousQueries().updateListeners(internal, false);
        boolean needVal = retval || intercept || op == GridCacheOperation.TRANSFORM || !F.isEmpty(filter) || lsnrCol != null;
        checkObsolete();
        CacheDataRow oldRow = null;
        // Load and remove from swap if it is new.
        if (isNew())
            oldRow = unswap(null, false);
        old = val;
        boolean readFromStore = false;
        Object old0 = null;
        if (readThrough && needVal && old == null && (cctx.readThrough() && (op == GridCacheOperation.TRANSFORM || cctx.loadPreviousValue()))) {
            old0 = readThrough(null, key, false, subjId, taskName);
            old = cctx.toCacheObject(old0);
            long ttl = CU.TTL_ETERNAL;
            long expireTime = CU.EXPIRE_TIME_ETERNAL;
            if (expiryPlc != null && old != null) {
                ttl = CU.toTtl(expiryPlc.getExpiryForCreation());
                if (ttl == CU.TTL_ZERO) {
                    ttl = CU.TTL_MINIMUM;
                    expireTime = CU.expireTimeInPast();
                } else if (ttl == CU.TTL_NOT_CHANGED)
                    ttl = CU.TTL_ETERNAL;
                else
                    expireTime = CU.toExpireTime(ttl);
            }
            // Detach value before index update.
            old = cctx.kernalContext().cacheObjects().prepareForCache(old, cctx);
            if (old != null)
                storeValue(old, expireTime, ver, oldRow);
            else
                removeValue();
            update(old, expireTime, ttl, ver, true);
        }
        // Apply metrics.
        if (metrics && cctx.statisticsEnabled() && needVal) {
            // PutIfAbsent methods mustn't update hit/miss statistics
            if (op != GridCacheOperation.UPDATE || F.isEmpty(filter) || !cctx.putIfAbsentFilter(filter))
                cctx.cache().metrics0().onRead(old != null);
        }
        // Check filter inside of synchronization.
        if (!F.isEmpty(filter)) {
            boolean pass = cctx.isAllLocked(this, filter);
            if (!pass) {
                if (expiryPlc != null && !readFromStore && !cctx.putIfAbsentFilter(filter) && hasValueUnlocked())
                    updateTtl(expiryPlc);
                Object val = retval ? cctx.cacheObjectContext().unwrapBinaryIfNeeded(CU.value(old, cctx, false), keepBinary, false) : null;
                return new T3<>(false, val, null);
            }
        }
        String transformCloClsName = null;
        CacheObject updated;
        Object key0 = null;
        Object updated0 = null;
        // Calculate new value.
        if (op == GridCacheOperation.TRANSFORM) {
            transformCloClsName = EntryProcessorResourceInjectorProxy.unwrap(writeObj).getClass().getName();
            EntryProcessor<Object, Object, ?> entryProcessor = (EntryProcessor<Object, Object, ?>) writeObj;
            assert entryProcessor != null;
            CacheInvokeEntry<Object, Object> entry = new CacheInvokeEntry<>(key, old, version(), keepBinary, this);
            try {
                Object computed = entryProcessor.process(entry, invokeArgs);
                if (entry.modified()) {
                    updated0 = cctx.unwrapTemporary(entry.getValue());
                    updated = cctx.toCacheObject(updated0);
                    if (// no validation for remove case
                    updated != null)
                        cctx.validateKeyAndValue(key, updated);
                } else
                    updated = old;
                key0 = entry.key();
                invokeRes = computed != null ? CacheInvokeResult.fromResult(cctx.unwrapTemporary(computed)) : null;
            } catch (Exception e) {
                updated = old;
                invokeRes = CacheInvokeResult.fromError(e);
            }
            if (!entry.modified()) {
                if (expiryPlc != null && !readFromStore && hasValueUnlocked())
                    updateTtl(expiryPlc);
                return new GridTuple3<>(false, null, invokeRes);
            }
        } else
            updated = (CacheObject) writeObj;
        op = updated == null ? GridCacheOperation.DELETE : GridCacheOperation.UPDATE;
        if (intercept) {
            CacheLazyEntry e;
            if (op == GridCacheOperation.UPDATE) {
                updated0 = value(updated0, updated, keepBinary, false);
                e = new CacheLazyEntry(cctx, key, key0, old, old0, keepBinary);
                Object interceptorVal = cctx.config().getInterceptor().onBeforePut(e, updated0);
                if (interceptorVal == null)
                    return new GridTuple3<>(false, cctx.unwrapTemporary(value(old0, old, keepBinary, false)), invokeRes);
                else {
                    updated0 = cctx.unwrapTemporary(interceptorVal);
                    updated = cctx.toCacheObject(updated0);
                }
            } else {
                e = new CacheLazyEntry(cctx, key, key0, old, old0, keepBinary);
                interceptorRes = cctx.config().getInterceptor().onBeforeRemove(e);
                if (cctx.cancelRemove(interceptorRes))
                    return new GridTuple3<>(false, cctx.unwrapTemporary(interceptorRes.get2()), invokeRes);
            }
            key0 = e.key();
            old0 = e.value();
        }
        boolean hadVal = hasValueUnlocked();
        long ttl = CU.TTL_ETERNAL;
        long expireTime = CU.EXPIRE_TIME_ETERNAL;
        if (op == GridCacheOperation.UPDATE) {
            if (expiryPlc != null) {
                ttl = CU.toTtl(hadVal ? expiryPlc.getExpiryForUpdate() : expiryPlc.getExpiryForCreation());
                if (ttl == CU.TTL_NOT_CHANGED) {
                    ttl = ttlExtras();
                    expireTime = expireTimeExtras();
                } else if (ttl != CU.TTL_ZERO)
                    expireTime = CU.toExpireTime(ttl);
            } else {
                ttl = ttlExtras();
                expireTime = expireTimeExtras();
            }
        }
        if (ttl == CU.TTL_ZERO)
            op = GridCacheOperation.DELETE;
        // Try write-through.
        if (op == GridCacheOperation.UPDATE) {
            // Detach value before index update.
            updated = cctx.kernalContext().cacheObjects().prepareForCache(updated, cctx);
            if (writeThrough)
                // Must persist inside synchronization in non-tx mode.
                cctx.store().put(null, key, updated, ver);
            storeValue(updated, expireTime, ver, oldRow);
            assert ttl != CU.TTL_ZERO;
            update(updated, expireTime, ttl, ver, true);
            if (evt) {
                CacheObject evtOld = null;
                if (transformCloClsName != null && cctx.events().isRecordable(EVT_CACHE_OBJECT_READ)) {
                    evtOld = cctx.unwrapTemporary(old);
                    cctx.events().addEvent(partition(), key, cctx.localNodeId(), null, (GridCacheVersion) null, EVT_CACHE_OBJECT_READ, evtOld, evtOld != null || hadVal, evtOld, evtOld != null || hadVal, subjId, transformCloClsName, taskName, keepBinary);
                }
                if (cctx.events().isRecordable(EVT_CACHE_OBJECT_PUT)) {
                    if (evtOld == null)
                        evtOld = cctx.unwrapTemporary(old);
                    cctx.events().addEvent(partition(), key, cctx.localNodeId(), null, (GridCacheVersion) null, EVT_CACHE_OBJECT_PUT, updated, updated != null, evtOld, evtOld != null || hadVal, subjId, null, taskName, keepBinary);
                }
            }
        } else {
            if (writeThrough)
                // Must persist inside synchronization in non-tx mode.
                cctx.store().remove(null, key);
            removeValue();
            update(null, CU.TTL_ETERNAL, CU.EXPIRE_TIME_ETERNAL, ver, true);
            if (evt) {
                CacheObject evtOld = null;
                if (transformCloClsName != null && cctx.events().isRecordable(EVT_CACHE_OBJECT_READ))
                    cctx.events().addEvent(partition(), key, cctx.localNodeId(), null, (GridCacheVersion) null, EVT_CACHE_OBJECT_READ, evtOld, evtOld != null || hadVal, evtOld, evtOld != null || hadVal, subjId, transformCloClsName, taskName, keepBinary);
                if (cctx.events().isRecordable(EVT_CACHE_OBJECT_REMOVED)) {
                    if (evtOld == null)
                        evtOld = cctx.unwrapTemporary(old);
                    cctx.events().addEvent(partition(), key, cctx.localNodeId(), null, (GridCacheVersion) null, EVT_CACHE_OBJECT_REMOVED, null, false, evtOld, evtOld != null || hadVal, subjId, null, taskName, keepBinary);
                }
            }
            res = hadVal;
        }
        if (res)
            updateMetrics(op, metrics);
        if (lsnrCol != null) {
            long updateCntr = nextPartitionCounter(AffinityTopologyVersion.NONE, true, null);
            cctx.continuousQueries().onEntryUpdated(lsnrCol, key, val, old, internal, partition(), true, false, updateCntr, null, AffinityTopologyVersion.NONE);
            onUpdateFinished(updateCntr);
        }
        cctx.dataStructures().onEntryUpdated(key, op == GridCacheOperation.DELETE, keepBinary);
        if (intercept) {
            if (op == GridCacheOperation.UPDATE)
                cctx.config().getInterceptor().onAfterPut(new CacheLazyEntry(cctx, key, key0, updated, updated0, keepBinary, 0L));
            else
                cctx.config().getInterceptor().onAfterRemove(new CacheLazyEntry(cctx, key, key0, old, old0, keepBinary, 0L));
        }
    } finally {
        unlockEntry();
    }
    return new GridTuple3<>(res, cctx.unwrapTemporary(interceptorRes != null ? interceptorRes.get2() : cctx.cacheObjectContext().unwrapBinaryIfNeeded(old, keepBinary, false)), invokeRes);
}
Also used : CacheDataRow(org.apache.ignite.internal.processors.cache.persistence.CacheDataRow) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) IgniteException(org.apache.ignite.IgniteException) StorageException(org.apache.ignite.internal.pagemem.wal.StorageException) GridClosureException(org.apache.ignite.internal.util.lang.GridClosureException) GridTuple3(org.apache.ignite.internal.util.lang.GridTuple3) CacheContinuousQueryListener(org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryListener) EntryProcessor(javax.cache.processor.EntryProcessor) GridCacheVersion(org.apache.ignite.internal.processors.cache.version.GridCacheVersion) UUID(java.util.UUID) T3(org.apache.ignite.internal.util.typedef.T3)

Example 5 with CacheContinuousQueryListener

use of org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryListener in project ignite by apache.

the class GridCacheMapEntry method innerUpdate.

/**
 * {@inheritDoc}
 */
@SuppressWarnings("unchecked")
@Override
public GridCacheUpdateAtomicResult innerUpdate(final GridCacheVersion newVer, final UUID evtNodeId, final UUID affNodeId, final GridCacheOperation op, @Nullable final Object writeObj, @Nullable final Object[] invokeArgs, final boolean writeThrough, final boolean readThrough, final boolean retval, final boolean keepBinary, @Nullable final IgniteCacheExpiryPolicy expiryPlc, final boolean evt, final boolean metrics, final boolean primary, final boolean verCheck, final AffinityTopologyVersion topVer, @Nullable final CacheEntryPredicate[] filter, final GridDrType drType, final long explicitTtl, final long explicitExpireTime, @Nullable final GridCacheVersion conflictVer, final boolean conflictResolve, final boolean intercept, final String taskName, @Nullable final CacheObject prevVal, @Nullable final Long updateCntr, @Nullable final GridDhtAtomicAbstractUpdateFuture fut, boolean transformOp) throws IgniteCheckedException, GridCacheEntryRemovedException, GridClosureException {
    assert cctx.atomic() && !detached();
    AtomicCacheUpdateClosure c;
    if (!primary && !isNear())
        ensureFreeSpace();
    lockListenerReadLock();
    lockEntry();
    try {
        checkObsolete();
        boolean internal = isInternal() || !context().userCache();
        Map<UUID, CacheContinuousQueryListener> lsnrs = cctx.continuousQueries().updateListeners(internal, false);
        boolean needVal = lsnrs != null || intercept || retval || op == GridCacheOperation.TRANSFORM || !F.isEmptyOrNulls(filter);
        // Possibly read value from store.
        boolean readFromStore = readThrough && needVal && (cctx.readThrough() && (op == GridCacheOperation.TRANSFORM || cctx.loadPreviousValue()));
        c = new AtomicCacheUpdateClosure(this, topVer, newVer, op, writeObj, invokeArgs, readFromStore, writeThrough, keepBinary, expiryPlc, primary, verCheck, filter, explicitTtl, explicitExpireTime, conflictVer, conflictResolve, intercept, updateCntr, cctx.disableTriggeringCacheInterceptorOnConflict());
        key.valueBytes(cctx.cacheObjectContext());
        if (isNear()) {
            CacheDataRow dataRow = val != null ? new CacheDataRowAdapter(key, val, ver, expireTimeExtras()) : null;
            c.call(dataRow);
        } else
            cctx.offheap().invoke(cctx, key, localPartition(), c);
        GridCacheUpdateAtomicResult updateRes = c.updateRes;
        assert updateRes != null : c;
        // We should ignore expired old row. Expired oldRow instance is needed for correct row replacement\deletion only.
        CacheObject oldVal = c.oldRow != null && !c.oldRowExpiredFlag ? c.oldRow.value() : null;
        CacheObject updateVal = null;
        GridCacheVersion updateVer = c.newVer;
        boolean updateMetrics = metrics && cctx.statisticsEnabled();
        // Apply metrics.
        if (updateMetrics && updateRes.outcome().updateReadMetrics() && needVal)
            cctx.cache().metrics0().onRead(oldVal != null);
        if (updateMetrics && INVOKE_NO_OP.equals(updateRes.outcome()) && (transformOp || updateRes.transformed()))
            cctx.cache().metrics0().onReadOnlyInvoke(oldVal != null);
        else if (updateMetrics && REMOVE_NO_VAL.equals(updateRes.outcome()) && (transformOp || updateRes.transformed()))
            cctx.cache().metrics0().onInvokeRemove(oldVal != null);
        switch(updateRes.outcome()) {
            case VERSION_CHECK_FAILED:
                {
                    if (!cctx.isNear()) {
                        CacheObject evtVal;
                        if (op == GridCacheOperation.TRANSFORM) {
                            EntryProcessor<Object, Object, ?> entryProcessor = (EntryProcessor<Object, Object, ?>) writeObj;
                            CacheInvokeEntry<Object, Object> entry = new CacheInvokeEntry<>(key, prevVal, version(), keepBinary, this);
                            IgniteThread.onEntryProcessorEntered(true);
                            try {
                                entryProcessor.process(entry, invokeArgs);
                                evtVal = entry.modified() ? cctx.toCacheObject(cctx.unwrapTemporary(entry.getValue())) : prevVal;
                            } catch (Exception ignore) {
                                evtVal = prevVal;
                            } finally {
                                IgniteThread.onEntryProcessorLeft();
                            }
                        } else
                            evtVal = (CacheObject) writeObj;
                        assert !primary && updateCntr != null;
                        onUpdateFinished(updateCntr);
                        cctx.continuousQueries().onEntryUpdated(key, evtVal, prevVal, isInternal() || !context().userCache(), partition(), primary, false, updateCntr, null, topVer);
                    }
                    return updateRes;
                }
            case CONFLICT_USE_OLD:
            case FILTER_FAILED:
            case INVOKE_NO_OP:
            case INTERCEPTOR_CANCEL:
                return updateRes;
        }
        assert updateRes.outcome() == UpdateOutcome.SUCCESS || updateRes.outcome() == UpdateOutcome.REMOVE_NO_VAL;
        CacheObject evtOld = null;
        if (evt && op == TRANSFORM && cctx.events().isRecordable(EVT_CACHE_OBJECT_READ)) {
            assert writeObj instanceof EntryProcessor : writeObj;
            evtOld = cctx.unwrapTemporary(oldVal);
            Object transformClo = EntryProcessorResourceInjectorProxy.unwrap(writeObj);
            cctx.events().addEvent(partition(), key, evtNodeId, null, null, updateVer, EVT_CACHE_OBJECT_READ, evtOld, evtOld != null, evtOld, evtOld != null, transformClo.getClass().getName(), taskName, keepBinary);
        }
        if (c.op == UPDATE) {
            updateVal = val;
            assert updateVal != null : c;
            drReplicate(drType, updateVal, updateVer, topVer);
            recordNodeId(affNodeId, topVer);
            if (evt && cctx.events().isRecordable(EVT_CACHE_OBJECT_PUT)) {
                if (evtOld == null)
                    evtOld = cctx.unwrapTemporary(oldVal);
                cctx.events().addEvent(partition(), key, evtNodeId, null, null, updateVer, EVT_CACHE_OBJECT_PUT, updateVal, true, evtOld, evtOld != null, null, taskName, keepBinary);
            }
        } else {
            assert c.op == DELETE : c.op;
            clearReaders();
            drReplicate(drType, null, updateVer, topVer);
            recordNodeId(affNodeId, topVer);
            if (evt && cctx.events().isRecordable(EVT_CACHE_OBJECT_REMOVED)) {
                if (evtOld == null)
                    evtOld = cctx.unwrapTemporary(oldVal);
                cctx.events().addEvent(partition(), key, evtNodeId, null, null, updateVer, EVT_CACHE_OBJECT_REMOVED, null, false, evtOld, evtOld != null, null, taskName, keepBinary);
            }
        }
        if (updateRes.success())
            updateMetrics(c.op, metrics, transformOp || updateRes.transformed(), oldVal != null);
        // Continuous query filter should be perform under lock.
        if (lsnrs != null) {
            CacheObject evtVal = cctx.unwrapTemporary(updateVal);
            CacheObject evtOldVal = cctx.unwrapTemporary(oldVal);
            cctx.continuousQueries().onEntryUpdated(lsnrs, key, evtVal, evtOldVal, internal, partition(), primary, false, c.updateRes.updateCounter(), fut, topVer);
        }
        if (intercept && c.wasIntercepted) {
            assert c.op == UPDATE || c.op == DELETE : c.op;
            Cache.Entry<?, ?> entry = new CacheLazyEntry<>(cctx, key, null, c.op == UPDATE ? updateVal : oldVal, null, keepBinary, c.updateRes.updateCounter());
            if (c.op == UPDATE)
                cctx.config().getInterceptor().onAfterPut(entry);
            else
                cctx.config().getInterceptor().onAfterRemove(entry);
        }
        updatePlatformCache(c.op == UPDATE ? updateVal : null, topVer);
    } finally {
        unlockEntry();
        unlockListenerReadLock();
    }
    onUpdateFinished(c.updateRes.updateCounter());
    return c.updateRes;
}
Also used : CacheDataRow(org.apache.ignite.internal.processors.cache.persistence.CacheDataRow) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) IgniteTxSerializationCheckedException(org.apache.ignite.internal.transactions.IgniteTxSerializationCheckedException) StorageException(org.apache.ignite.internal.processors.cache.persistence.StorageException) IgniteException(org.apache.ignite.IgniteException) UnregisteredClassException(org.apache.ignite.internal.UnregisteredClassException) NodeStoppingException(org.apache.ignite.internal.NodeStoppingException) UnregisteredBinaryTypeException(org.apache.ignite.internal.UnregisteredBinaryTypeException) IgniteTxDuplicateKeyCheckedException(org.apache.ignite.internal.transactions.IgniteTxDuplicateKeyCheckedException) GridClosureException(org.apache.ignite.internal.util.lang.GridClosureException) CacheContinuousQueryListener(org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryListener) GridCacheVersion(org.apache.ignite.internal.processors.cache.version.GridCacheVersion) EntryProcessor(javax.cache.processor.EntryProcessor) CacheDataRowAdapter(org.apache.ignite.internal.processors.cache.persistence.CacheDataRowAdapter) UUID(java.util.UUID) Cache(javax.cache.Cache) IgniteCache(org.apache.ignite.IgniteCache)

Aggregations

UUID (java.util.UUID)5 CacheContinuousQueryListener (org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryListener)5 GridCacheVersion (org.apache.ignite.internal.processors.cache.version.GridCacheVersion)4 EntryProcessor (javax.cache.processor.EntryProcessor)2 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)2 IgniteException (org.apache.ignite.IgniteException)2 CacheDataRow (org.apache.ignite.internal.processors.cache.persistence.CacheDataRow)2 WALPointer (org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer)2 GridClosureException (org.apache.ignite.internal.util.lang.GridClosureException)2 HashMap (java.util.HashMap)1 LinkedHashMap (java.util.LinkedHashMap)1 Map (java.util.Map)1 SortedMap (java.util.SortedMap)1 TreeMap (java.util.TreeMap)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 AtomicLong (java.util.concurrent.atomic.AtomicLong)1 Cache (javax.cache.Cache)1 IgniteCache (org.apache.ignite.IgniteCache)1 NodeStoppingException (org.apache.ignite.internal.NodeStoppingException)1