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);
}
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);
}
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();
}
}
}
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);
}
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;
}
Aggregations