use of javax.cache.processor.EntryProcessor in project ignite by apache.
the class IgniteTxEntry method applyEntryProcessors.
/**
* @param cacheVal Value.
* @return New value.
*/
@SuppressWarnings("unchecked")
public CacheObject applyEntryProcessors(CacheObject cacheVal) {
GridCacheVersion ver;
try {
ver = entry.version();
} catch (GridCacheEntryRemovedException ignore) {
assert tx == null || tx.optimistic() : tx;
ver = null;
}
Object val = null;
Object keyVal = null;
for (T2<EntryProcessor<Object, Object, Object>, Object[]> t : entryProcessors()) {
IgniteThread.onEntryProcessorEntered(true);
try {
CacheInvokeEntry<Object, Object> invokeEntry = new CacheInvokeEntry(key, keyVal, cacheVal, val, ver, keepBinary(), cached());
EntryProcessor processor = t.get1();
processor.process(invokeEntry, t.get2());
val = invokeEntry.getValue();
keyVal = invokeEntry.key();
} catch (Exception ignore) {
// No-op.
} finally {
IgniteThread.onEntryProcessorLeft();
}
}
return ctx.toCacheObject(val);
}
use of javax.cache.processor.EntryProcessor in project ignite by apache.
the class GridDhtTxAbstractEnlistFuture method continueLoop.
/**
* Iterates over iterator, applies changes locally and sends it on backups.
*
* @param ignoreCntr {@code True} if need to ignore skip counter.
*/
private void continueLoop(boolean ignoreCntr) {
if (isDone() || (!ignoreCntr && (SKIP_UPD.getAndIncrement(this) != 0)))
return;
GridDhtCacheAdapter cache = cctx.dhtCache();
EnlistOperation op = it.operation();
AffinityTopologyVersion topVer = tx.topologyVersionSnapshot();
try {
while (true) {
int curPart = -1;
List<ClusterNode> backups = null;
while (hasNext0()) {
Object cur = next0();
KeyCacheObject key = toKey(op, cur);
if (curPart != key.partition())
backups = backupNodes(curPart = key.partition());
assert backups != null;
if (!ensureFreeSlot(key, backups)) {
// Can't advance further at the moment.
peek = cur;
it.beforeDetach();
break;
}
GridDhtCacheEntry entry = cache.entryExx(key);
if (log.isDebugEnabled())
log.debug("Adding entry: " + entry);
assert !entry.detached();
CacheObject val = op.isDeleteOrLock() || op.isInvoke() ? null : cctx.toCacheObject(((IgniteBiTuple) cur).getValue());
GridInvokeValue invokeVal = null;
EntryProcessor entryProc = null;
Object[] invokeArgs = null;
if (op.isInvoke()) {
assert needResult();
invokeVal = (GridInvokeValue) ((IgniteBiTuple) cur).getValue();
entryProc = invokeVal.entryProcessor();
invokeArgs = invokeVal.invokeArgs();
}
assert entryProc != null || !op.isInvoke();
boolean needOldVal = tx.txState().useMvccCaching(cctx.cacheId());
GridCacheUpdateTxResult res;
while (true) {
cctx.shared().database().checkpointReadLock();
try {
switch(op) {
case DELETE:
res = entry.mvccRemove(tx, cctx.localNodeId(), topVer, mvccSnapshot, isMoving(key.partition(), backups), needOldVal, filter, needResult());
break;
case INSERT:
case TRANSFORM:
case UPSERT:
case UPDATE:
res = entry.mvccSet(tx, cctx.localNodeId(), val, entryProc, invokeArgs, 0, topVer, mvccSnapshot, op.cacheOperation(), isMoving(key.partition(), backups), op.noCreate(), needOldVal, filter, needResult(), keepBinary);
break;
case LOCK:
res = entry.mvccLock(tx, mvccSnapshot);
break;
default:
throw new IgniteSQLException("Cannot acquire lock for operation [op= " + op + "]" + "Operation is unsupported at the moment ", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
break;
} catch (GridCacheEntryRemovedException ignored) {
entry = cache.entryExx(entry.key(), topVer);
} finally {
cctx.shared().database().checkpointReadUnlock();
}
}
IgniteInternalFuture<GridCacheUpdateTxResult> updateFut = res.updateFuture();
final Message val0 = invokeVal != null ? invokeVal : val;
if (updateFut != null) {
if (updateFut.isDone())
res = updateFut.get();
else {
GridDhtCacheEntry entry0 = entry;
List<ClusterNode> backups0 = backups;
it.beforeDetach();
updateFut.listen(new CI1<IgniteInternalFuture<GridCacheUpdateTxResult>>() {
@Override
public void apply(IgniteInternalFuture<GridCacheUpdateTxResult> fut) {
try {
tx.incrementLockCounter();
processEntry(entry0, op, fut.get(), val0, backups0);
continueLoop(true);
} catch (Throwable e) {
onDone(e);
}
}
});
// Can't move further. Exit loop without decrementing the counter.
return;
}
}
tx.incrementLockCounter();
processEntry(entry, op, res, val0, backups);
}
if (!hasNext0()) {
if (!F.isEmpty(batches)) {
// Flush incomplete batches.
// Need to skip batches for nodes where first request (contains tx info) is still in-flight.
// Otherwise, the regular enlist request (without tx info) may beat it to the primary node.
Iterator<Map.Entry<UUID, Batch>> it = batches.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<UUID, Batch> e = it.next();
ConcurrentMap<Integer, Batch> pending0 = pending == null ? null : pending.get(e.getKey());
if (pending0 == null || !pending0.containsKey(FIRST_BATCH_ID)) {
it.remove();
sendBatch(e.getValue());
}
}
}
if (noPendingRequests()) {
onDone(result0());
return;
}
}
if (SKIP_UPD.decrementAndGet(this) == 0)
break;
skipCntr = 1;
}
} catch (Throwable e) {
onDone(e);
if (e instanceof Error)
throw (Error) e;
}
}
use of javax.cache.processor.EntryProcessor in project ignite by apache.
the class GridCacheGetAndTransformStoreAbstractTest method testGetAndTransform.
/**
* @throws Exception If failed.
*/
@Test
public void testGetAndTransform() throws Exception {
final AtomicBoolean finish = new AtomicBoolean();
try {
startGrid(0);
startGrid(1);
startGrid(2);
final Processor entryProcessor = new Processor();
IgniteInternalFuture<?> fut = multithreadedAsync(new Callable<Object>() {
@Override
public Object call() throws Exception {
IgniteCache<Integer, String> c = jcache(ThreadLocalRandom.current().nextInt(3));
while (!finish.get() && !Thread.currentThread().isInterrupted()) {
c.get(ThreadLocalRandom.current().nextInt(100));
c.put(ThreadLocalRandom.current().nextInt(100), "s");
c.invoke(ThreadLocalRandom.current().nextInt(100), entryProcessor);
}
return null;
}
}, 20);
Thread.sleep(15_000);
finish.set(true);
fut.get();
} finally {
stopGrid(0);
stopGrid(1);
stopGrid(2);
while (jcache().localSize() != 0) jcache().clear();
}
}
use of javax.cache.processor.EntryProcessor in project ignite by apache.
the class GridNearTxLocal method putAllAsync0.
/**
* Internal method for all put and transform operations. Only one of {@code map}, {@code transformMap}
* maps must be non-null.
*
* @param cacheCtx Context.
* @param map Key-value map to store.
* @param invokeMap Invoke map.
* @param invokeArgs Optional arguments for EntryProcessor.
* @param drMap DR map.
* @param retval Key-transform value map to store.
* @return Operation future.
*/
@SuppressWarnings("unchecked")
private <K, V> IgniteInternalFuture putAllAsync0(final GridCacheContext cacheCtx, @Nullable AffinityTopologyVersion entryTopVer, @Nullable Map<? extends K, ? extends V> map, @Nullable Map<? extends K, ? extends EntryProcessor<K, V, Object>> invokeMap, @Nullable final Object[] invokeArgs, @Nullable Map<KeyCacheObject, GridCacheDrInfo> drMap, final boolean retval) {
if (cacheCtx.mvccEnabled())
return mvccPutAllAsync0(cacheCtx, map, invokeMap, invokeArgs, retval, null);
try {
beforePut(cacheCtx, retval, false);
} catch (IgniteCheckedException e) {
return new GridFinishedFuture(e);
}
final CacheOperationContext opCtx = cacheCtx.operationContextPerCall();
final Byte dataCenterId;
if (opCtx != null && opCtx.hasDataCenterId()) {
assert drMap == null : drMap;
assert map != null || invokeMap != null;
dataCenterId = opCtx.dataCenterId();
} else
dataCenterId = null;
// Cached entry may be passed only from entry wrapper.
final Map<?, ?> map0 = map;
final Map<?, EntryProcessor<K, V, Object>> invokeMap0 = (Map<K, EntryProcessor<K, V, Object>>) invokeMap;
if (log.isDebugEnabled())
log.debug("Called putAllAsync(...) [tx=" + this + ", map=" + map0 + ", retval=" + retval + "]");
assert map0 != null || invokeMap0 != null;
final GridCacheReturn ret = new GridCacheReturn(localResult(), false);
if (F.isEmpty(map0) && F.isEmpty(invokeMap0)) {
if (implicit())
try {
commit();
} catch (IgniteCheckedException e) {
return new GridFinishedFuture<>(e);
}
return new GridFinishedFuture<>(ret.success(true));
}
try {
Set<?> keySet = map0 != null ? map0.keySet() : invokeMap0.keySet();
final Collection<KeyCacheObject> enlisted = new ArrayList<>(keySet.size());
final boolean keepBinary = opCtx != null && opCtx.isKeepBinary();
final IgniteInternalFuture<Void> loadFut = enlistWrite(cacheCtx, entryTopVer, keySet, opCtx != null ? opCtx.expiry() : null, map0, invokeMap0, invokeArgs, retval, false, CU.filterArray(null), ret, enlisted, drMap, null, opCtx != null && opCtx.skipStore(), false, keepBinary, opCtx != null && opCtx.recovery(), dataCenterId);
try {
loadFut.get();
} catch (IgniteCheckedException e) {
return new GridFinishedFuture(e);
}
long timeout = remainingTime();
if (timeout == -1)
return new GridFinishedFuture<>(timeoutException());
if (isRollbackOnly())
return new GridFinishedFuture<>(rollbackException());
if (pessimistic()) {
if (log.isDebugEnabled())
log.debug("Before acquiring transaction lock for put on keys: " + enlisted);
IgniteInternalFuture<Boolean> fut = cacheCtx.cache().txLockAsync(enlisted, timeout, this, // Needed to force load from store.
invokeMap != null, /*read*/
retval, isolation, isInvalidate(), -1L, -1L);
PLC1<GridCacheReturn> plc1 = new PLC1<GridCacheReturn>(ret) {
@Override
public GridCacheReturn postLock(GridCacheReturn ret) throws IgniteCheckedException {
if (log.isDebugEnabled())
log.debug("Acquired transaction lock for put on keys: " + enlisted);
postLockWrite(cacheCtx, enlisted, ret, /*remove*/
false, retval, /*read*/
false, -1L, CU.filterArray(null), /*computeInvoke*/
true);
return ret;
}
};
if (fut.isDone()) {
try {
return nonInterruptable(plc1.apply(fut.get(), null));
} catch (GridClosureException e) {
return new GridFinishedFuture<>(e.unwrap());
} catch (IgniteCheckedException e) {
try {
return nonInterruptable(plc1.apply(false, e));
} catch (Exception e1) {
return new GridFinishedFuture<>(e1);
}
}
} else {
return nonInterruptable(new GridEmbeddedFuture<>(fut, plc1));
}
} else
return optimisticPutFuture(cacheCtx, loadFut, ret, keepBinary);
} catch (RuntimeException e) {
onException();
throw e;
}
}
use of javax.cache.processor.EntryProcessor in project ignite by apache.
the class GridNearTxLocal method enlistWrite.
/**
* Internal routine for <tt>putAll(..)</tt>
*
* @param cacheCtx Cache context.
* @param keys Keys to enlist.
* @param expiryPlc Explicitly specified expiry policy for entry.
* @param lookup Value lookup map ({@code null} for remove).
* @param invokeMap Map with entry processors for invoke operation.
* @param invokeArgs Optional arguments for EntryProcessor.
* @param retval Flag indicating whether a value should be returned.
* @param lockOnly If {@code true}, then entry will be enlisted as noop.
* @param filter User filters.
* @param ret Return value.
* @param enlisted Collection of keys enlisted into this transaction.
* @param drPutMap DR put map (optional).
* @param drRmvMap DR remove map (optional).
* @param skipStore Skip store flag.
* @param singleRmv {@code True} for single key remove operation ({@link Cache#remove(Object)}.
* @param keepBinary Keep binary flag.
* @param recovery Recovery flag.
* @param dataCenterId Optional data center ID.
* @return Future for enlisting writes.
*/
private <K, V> IgniteInternalFuture<Void> enlistWrite(final GridCacheContext cacheCtx, @Nullable AffinityTopologyVersion entryTopVer, Collection<?> keys, @Nullable ExpiryPolicy expiryPlc, @Nullable Map<?, ?> lookup, @Nullable Map<?, EntryProcessor<K, V, Object>> invokeMap, @Nullable Object[] invokeArgs, final boolean retval, boolean lockOnly, final CacheEntryPredicate[] filter, final GridCacheReturn ret, Collection<KeyCacheObject> enlisted, @Nullable Map<KeyCacheObject, GridCacheDrInfo> drPutMap, @Nullable Map<KeyCacheObject, GridCacheVersion> drRmvMap, boolean skipStore, final boolean singleRmv, final boolean keepBinary, final boolean recovery, Byte dataCenterId) {
assert retval || invokeMap == null;
try (TraceSurroundings ignored2 = MTC.support(context().kernalContext().tracing().create(TX_NEAR_ENLIST_WRITE, MTC.span()))) {
GridFutureAdapter<Void> enlistFut = new GridFutureAdapter<>();
if (!updateLockFuture(null, enlistFut))
return finishFuture(enlistFut, timedOut() ? timeoutException() : rollbackException(), false);
try {
addActiveCache(cacheCtx, recovery);
} catch (IgniteCheckedException e) {
return finishFuture(enlistFut, e, false);
}
boolean rmv = lookup == null && invokeMap == null;
final boolean hasFilters = !F.isEmptyOrNulls(filter) && !F.isAlwaysTrue(filter);
final boolean needVal = singleRmv || retval || hasFilters;
final boolean needReadVer = needVal && (serializable() && optimistic());
try {
// Set transform flag for transaction.
if (invokeMap != null)
transform = true;
Set<KeyCacheObject> missedForLoad = null;
for (Object key : keys) {
if (isRollbackOnly())
return finishFuture(enlistFut, timedOut() ? timeoutException() : rollbackException(), false);
if (key == null) {
rollback();
throw new NullPointerException("Null key.");
}
Object val = rmv || lookup == null ? null : lookup.get(key);
EntryProcessor entryProcessor = invokeMap == null ? null : invokeMap.get(key);
GridCacheVersion drVer;
long drTtl;
long drExpireTime;
if (drPutMap != null) {
GridCacheDrInfo info = drPutMap.get(key);
assert info != null;
drVer = info.version();
drTtl = info.ttl();
drExpireTime = info.expireTime();
} else if (drRmvMap != null) {
assert drRmvMap.get(key) != null;
drVer = drRmvMap.get(key);
drTtl = -1L;
drExpireTime = -1L;
} else if (dataCenterId != null) {
drVer = cacheCtx.cache().nextVersion(dataCenterId);
drTtl = -1L;
drExpireTime = -1L;
} else {
drVer = null;
drTtl = -1L;
drExpireTime = -1L;
}
if (!rmv && val == null && entryProcessor == null) {
setRollbackOnly();
throw new NullPointerException("Null value.");
}
KeyCacheObject cacheKey = cacheCtx.toCacheKeyObject(key);
boolean loadMissed = enlistWriteEntry(cacheCtx, entryTopVer, cacheKey, val, entryProcessor, invokeArgs, expiryPlc, retval, lockOnly, filter, drVer, drTtl, drExpireTime, ret, enlisted, skipStore, singleRmv, hasFilters, needVal, needReadVer, keepBinary, recovery);
if (loadMissed) {
if (missedForLoad == null)
missedForLoad = new HashSet<>();
missedForLoad.add(cacheKey);
}
}
if (missedForLoad != null) {
AffinityTopologyVersion topVer = topologyVersionSnapshot();
if (topVer == null)
topVer = entryTopVer;
IgniteInternalFuture<Void> loadFut = loadMissing(cacheCtx, topVer != null ? topVer : topologyVersion(), missedForLoad, filter, ret, needReadVer, singleRmv, hasFilters, /*read through*/
(invokeMap != null || cacheCtx.config().isLoadPreviousValue()) && !skipStore, retval, keepBinary, recovery, expiryPlc);
loadFut.listen(new IgniteInClosure<IgniteInternalFuture<Void>>() {
@Override
public void apply(IgniteInternalFuture<Void> fut) {
try {
fut.get();
finishFuture(enlistFut, null, true);
} catch (IgniteCheckedException e) {
finishFuture(enlistFut, e, true);
}
}
});
return enlistFut;
}
return finishFuture(enlistFut, null, true);
} catch (IgniteCheckedException e) {
return finishFuture(enlistFut, e, true);
}
}
}
Aggregations