use of org.apache.ignite.internal.processors.cache.GridCacheReturn in project ignite by apache.
the class GridDhtAtomicCache method update.
/**
* @param node Node.
* @param locked Entries.
* @param req Request.
* @param res Response.
* @param dhtUpdRes DHT update result
* @param taskName Task name.
* @return Operation result.
* @throws GridCacheEntryRemovedException If got obsolete entry.
*/
private DhtAtomicUpdateResult update(ClusterNode node, List<GridDhtCacheEntry> locked, GridNearAtomicAbstractUpdateRequest req, GridNearAtomicUpdateResponse res, DhtAtomicUpdateResult dhtUpdRes, String taskName) throws GridCacheEntryRemovedException {
GridDhtPartitionTopology top = topology();
boolean hasNear = req.nearCache();
// Assign next version for update inside entries lock.
GridCacheVersion ver = dhtUpdRes.dhtFuture() != null ? /*retry*/
dhtUpdRes.dhtFuture().writeVer : nextVersion();
if (hasNear)
res.nearVersion(ver);
if (msgLog.isDebugEnabled()) {
msgLog.debug("Assigned update version [futId=" + req.futureId() + ", writeVer=" + ver + ']');
}
assert ver != null : "Got null version for update request: " + req;
boolean sndPrevVal = !top.rebalanceFinished(req.topologyVersion());
if (dhtUpdRes.dhtFuture() == null)
dhtUpdRes.dhtFuture(createDhtFuture(ver, req));
IgniteCacheExpiryPolicy expiry = expiryPolicy(req.expiry());
GridCacheReturn retVal = null;
if (// Several keys ...
req.size() > 1 && writeThrough() && // and store is enabled ...
!req.skipStore() && // and this is not local store ...
!ctx.store().isLocal() && // (conflict resolver should be used for local store)
!// and no DR.
ctx.dr().receiveEnabled()) {
// This method can only be used when there are no replicated entries in the batch.
updateWithBatch(node, hasNear, req, res, locked, ver, ctx.isDrEnabled(), taskName, expiry, sndPrevVal, dhtUpdRes);
if (req.operation() == TRANSFORM)
retVal = dhtUpdRes.returnValue();
} else {
updateSingle(node, hasNear, req, res, locked, ver, ctx.isDrEnabled(), taskName, expiry, sndPrevVal, dhtUpdRes);
retVal = dhtUpdRes.returnValue();
}
GridDhtAtomicAbstractUpdateFuture dhtFut = dhtUpdRes.dhtFuture();
if (retVal == null)
retVal = new GridCacheReturn(ctx, node.isLocal(), true, null, null, true);
res.returnValue(retVal);
if (dhtFut != null) {
if (req.writeSynchronizationMode() == PRIMARY_SYNC && // To avoid deadlock disable back-pressure for sender data node.
!ctx.discovery().cacheGroupAffinityNode(node, ctx.groupId()) && !dhtFut.isDone()) {
final IgniteRunnable tracker = GridNioBackPressureControl.threadTracker();
if (tracker instanceof GridNioMessageTracker) {
((GridNioMessageTracker) tracker).onMessageReceived();
dhtFut.listen(new IgniteInClosure<IgniteInternalFuture<Void>>() {
@Override
public void apply(IgniteInternalFuture<Void> fut) {
((GridNioMessageTracker) tracker).onMessageProcessed();
}
});
}
}
ctx.mvcc().addAtomicFuture(dhtFut.id(), dhtFut);
}
dhtUpdRes.expiryPolicy(expiry);
return dhtUpdRes;
}
use of org.apache.ignite.internal.processors.cache.GridCacheReturn in project ignite by apache.
the class GridDhtColocatedCache method lockAllAsync0.
/**
* @param cacheCtx Cache context.
* @param tx Started colocated transaction (if any).
* @param threadId Thread ID.
* @param ver Lock version.
* @param topVer Topology version.
* @param keys Mapped keys.
* @param txRead Tx read.
* @param retval Return value flag.
* @param timeout Lock timeout.
* @param createTtl TTL for create operation.
* @param accessTtl TTL for read operation.
* @param filter filter Optional filter.
* @param skipStore Skip store flag.
* @return Lock future.
*/
private IgniteInternalFuture<Exception> lockAllAsync0(GridCacheContext<?, ?> cacheCtx, @Nullable final GridNearTxLocal tx, long threadId, final GridCacheVersion ver, AffinityTopologyVersion topVer, final Collection<KeyCacheObject> keys, final boolean txRead, boolean retval, final long timeout, final long createTtl, final long accessTtl, @Nullable final CacheEntryPredicate[] filter, boolean skipStore, boolean keepBinary) {
int cnt = keys.size();
if (tx == null) {
GridDhtLockFuture fut = new GridDhtLockFuture(ctx, ctx.localNodeId(), ver, topVer, cnt, txRead, retval, timeout, tx, threadId, createTtl, accessTtl, filter, skipStore, keepBinary);
// Add before mapping.
if (!ctx.mvcc().addFuture(fut))
throw new IllegalStateException("Duplicate future ID: " + fut);
boolean timedout = false;
for (KeyCacheObject key : keys) {
if (timedout)
break;
while (true) {
GridDhtCacheEntry entry = entryExx(key, topVer);
try {
fut.addEntry(key == null ? null : entry);
if (fut.isDone())
timedout = true;
break;
} catch (GridCacheEntryRemovedException ignore) {
if (log.isDebugEnabled())
log.debug("Got removed entry when adding lock (will retry): " + entry);
} catch (GridDistributedLockCancelledException e) {
if (log.isDebugEnabled())
log.debug("Failed to add entry [err=" + e + ", entry=" + entry + ']');
fut.onError(e);
return new GridDhtFinishedFuture<>(e);
}
}
}
// This will send remote messages.
fut.map();
return new GridDhtEmbeddedFuture<>(new C2<Boolean, Exception, Exception>() {
@Override
public Exception apply(Boolean b, Exception e) {
if (e != null)
e = U.unwrap(e);
else if (!b)
e = new GridCacheLockTimeoutException(ver);
return e;
}
}, fut);
} else {
// Handle implicit locks for pessimistic transactions.
ctx.tm().txContext(tx);
if (log.isDebugEnabled())
log.debug("Performing colocated lock [tx=" + tx + ", keys=" + keys + ']');
IgniteInternalFuture<GridCacheReturn> txFut = tx.lockAllAsync(cacheCtx, keys, retval, txRead, createTtl, accessTtl, skipStore, keepBinary);
return new GridDhtEmbeddedFuture<>(new C2<GridCacheReturn, Exception, Exception>() {
@Override
public Exception apply(GridCacheReturn ret, Exception e) {
if (e != null)
e = U.unwrap(e);
assert !tx.empty();
return e;
}
}, txFut);
}
}
use of org.apache.ignite.internal.processors.cache.GridCacheReturn in project ignite by apache.
the class GridDhtAtomicCache method updateSingle.
/**
* Updates locked entries one-by-one.
*
* @param nearNode Originating node.
* @param hasNear {@code True} if originating node has near cache.
* @param req Update request.
* @param res Update response.
* @param locked Locked entries.
* @param ver Assigned update version.
* @param replicate Whether DR is enabled for that cache.
* @param taskName Task name.
* @param expiry Expiry policy.
* @param sndPrevVal If {@code true} sends previous value to backups.
* @param dhtUpdRes Dht update result
* @throws GridCacheEntryRemovedException Should be never thrown.
*/
private void updateSingle(ClusterNode nearNode, boolean hasNear, GridNearAtomicAbstractUpdateRequest req, GridNearAtomicUpdateResponse res, List<GridDhtCacheEntry> locked, GridCacheVersion ver, boolean replicate, String taskName, @Nullable IgniteCacheExpiryPolicy expiry, boolean sndPrevVal, DhtAtomicUpdateResult dhtUpdRes) throws GridCacheEntryRemovedException {
GridCacheReturn retVal = dhtUpdRes.returnValue();
GridDhtAtomicAbstractUpdateFuture dhtFut = dhtUpdRes.dhtFuture();
Collection<IgniteBiTuple<GridDhtCacheEntry, GridCacheVersion>> deleted = dhtUpdRes.deleted();
AffinityTopologyVersion topVer = req.topologyVersion();
boolean intercept = ctx.config().getInterceptor() != null;
AffinityAssignment affAssignment = ctx.affinity().assignment(topVer);
// Avoid iterator creation.
for (int i = dhtUpdRes.processedEntriesCount(); i < req.size(); i++) {
KeyCacheObject k = req.key(i);
GridCacheOperation op = req.operation();
// No GridCacheEntryRemovedException can be thrown.
try {
GridDhtCacheEntry entry = locked.get(i);
GridCacheVersion newConflictVer = req.conflictVersion(i);
long newConflictTtl = req.conflictTtl(i);
long newConflictExpireTime = req.conflictExpireTime(i);
assert !(newConflictVer instanceof GridCacheVersionEx) : newConflictVer;
Object writeVal = op == TRANSFORM ? req.entryProcessor(i) : req.writeValue(i);
// Get readers before innerUpdate (reader cleared after remove).
GridDhtCacheEntry.ReaderId[] readers = entry.readersLocked();
GridCacheUpdateAtomicResult updRes = entry.innerUpdate(ver, nearNode.id(), locNodeId, op, writeVal, req.invokeArguments(), writeThrough() && !req.skipStore(), !req.skipStore(), sndPrevVal || req.returnValue(), req.keepBinary(), expiry, /*event*/
true, /*metrics*/
true, /*primary*/
true, /*verCheck*/
false, topVer, req.filter(), replicate ? DR_PRIMARY : DR_NONE, newConflictTtl, newConflictExpireTime, newConflictVer, /*conflictResolve*/
true, intercept, taskName, /*prevVal*/
null, /*updateCntr*/
null, dhtFut, false);
if (dhtFut != null) {
if (updRes.sendToDht()) {
// Send to backups even in case of remove-remove scenarios.
GridCacheVersionConflictContext<?, ?> conflictCtx = updRes.conflictResolveResult();
if (conflictCtx == null)
newConflictVer = null;
else if (conflictCtx.isMerge())
// Conflict version is discarded in case of merge.
newConflictVer = null;
EntryProcessor<Object, Object, Object> entryProcessor = null;
dhtFut.addWriteEntry(affAssignment, entry, updRes.newValue(), entryProcessor, updRes.newTtl(), updRes.conflictExpireTime(), newConflictVer, sndPrevVal, updRes.oldValue(), updRes.updateCounter(), op);
if (readers != null)
dhtFut.addNearWriteEntries(nearNode, readers, entry, updRes.newValue(), entryProcessor, updRes.newTtl(), updRes.conflictExpireTime());
} else {
if (log.isDebugEnabled())
log.debug("Entry did not pass the filter or conflict resolution (will skip write) " + "[entry=" + entry + ", filter=" + Arrays.toString(req.filter()) + ']');
}
}
if (hasNear) {
if (updRes.sendToDht()) {
if (!ctx.affinity().partitionBelongs(nearNode, entry.partition(), topVer)) {
// If put the same value as in request then do not need to send it back.
if (op == TRANSFORM || writeVal != updRes.newValue()) {
res.addNearValue(i, updRes.newValue(), updRes.newTtl(), updRes.conflictExpireTime());
} else
res.addNearTtl(i, updRes.newTtl(), updRes.conflictExpireTime());
if (updRes.newValue() != null) {
IgniteInternalFuture<Boolean> f = entry.addReader(nearNode.id(), req.messageId(), topVer);
assert f == null : f;
}
} else if (GridDhtCacheEntry.ReaderId.contains(readers, nearNode.id())) {
// Reader became primary or backup.
entry.removeReader(nearNode.id(), req.messageId());
} else
res.addSkippedIndex(i);
} else
res.addSkippedIndex(i);
}
if (updRes.removeVersion() != null) {
if (deleted == null)
deleted = new ArrayList<>(req.size());
deleted.add(F.t(entry, updRes.removeVersion()));
}
if (op == TRANSFORM) {
assert !req.returnValue();
IgniteBiTuple<Object, Exception> compRes = updRes.computedResult();
if (compRes != null && (compRes.get1() != null || compRes.get2() != null)) {
if (retVal == null)
retVal = new GridCacheReturn(nearNode.isLocal());
retVal.addEntryProcessResult(ctx, k, null, compRes.get1(), compRes.get2(), req.keepBinary());
}
} else {
// Create only once.
if (retVal == null) {
CacheObject ret = updRes.oldValue();
retVal = new GridCacheReturn(ctx, nearNode.isLocal(), req.keepBinary(), U.deploymentClassLoader(ctx.kernalContext(), U.contextDeploymentClassLoaderId(ctx.kernalContext())), req.returnValue() ? ret : null, updRes.success());
}
}
} catch (IgniteCheckedException e) {
res.addFailedKey(k, e);
}
dhtUpdRes.processedEntriesCount(i + 1);
}
dhtUpdRes.returnValue(retVal);
dhtUpdRes.deleted(deleted);
dhtUpdRes.dhtFuture(dhtFut);
}
use of org.apache.ignite.internal.processors.cache.GridCacheReturn in project ignite by apache.
the class GridNearAtomicSingleUpdateFuture method onPrimaryResponse.
/**
* {@inheritDoc}
*/
@Override
public void onPrimaryResponse(UUID nodeId, GridNearAtomicUpdateResponse res, boolean nodeErr) {
GridNearAtomicAbstractUpdateRequest req;
AffinityTopologyVersion remapTopVer0;
GridCacheReturn opRes0 = null;
CachePartialUpdateCheckedException err0 = null;
synchronized (this) {
if (!checkFutureId(res.futureId()))
return;
req = reqState.processPrimaryResponse(nodeId, res);
if (req == null)
return;
boolean remapKey = res.remapTopologyVersion() != null;
if (remapKey) {
assert !req.topologyVersion().equals(res.remapTopologyVersion());
assert remapTopVer == null : remapTopVer;
remapTopVer = res.remapTopologyVersion();
} else if (res.error() != null)
onPrimaryError(req, res);
else {
GridCacheReturn ret = res.returnValue();
if (op == TRANSFORM) {
if (ret != null) {
assert ret.value() == null || ret.value() instanceof Map : ret.value();
if (ret.value() != null) {
if (opRes != null)
opRes.mergeEntryProcessResults(ret);
else
opRes = ret;
}
}
} else
opRes = ret;
assert reqState != null;
if (!reqState.onPrimaryResponse(res, cctx))
return;
}
remapTopVer0 = onAllReceived();
if (remapTopVer0 == null) {
err0 = err;
opRes0 = opRes;
}
}
if (res.error() != null && res.failedKeys() == null) {
completeFuture(null, res.error(), res.futureId());
return;
}
if (remapTopVer0 != null) {
waitAndRemap(remapTopVer0);
return;
}
if (nearEnabled && !nodeErr)
updateNear(req, res);
completeFuture(opRes0, err0, res.futureId());
}
use of org.apache.ignite.internal.processors.cache.GridCacheReturn in project ignite by apache.
the class GridNearAtomicSingleUpdateFuture method map.
/**
* {@inheritDoc}
*/
@Override
protected void map(AffinityTopologyVersion topVer) {
long futId = cctx.mvcc().nextAtomicId();
Exception err = null;
PrimaryRequestState reqState0 = null;
try {
reqState0 = mapSingleUpdate(topVer, futId);
synchronized (this) {
assert topVer.topologyVersion() > 0 : topVer;
assert this.topVer == AffinityTopologyVersion.ZERO : this;
this.topVer = topVer;
this.futId = futId;
reqState = reqState0;
}
if (storeFuture() && !cctx.mvcc().addAtomicFuture(futId, this)) {
assert isDone();
return;
}
} catch (Exception e) {
err = e;
}
if (err != null) {
completeFuture(null, err, futId);
return;
}
// Optimize mapping for single key.
sendSingleRequest(reqState0.req.nodeId(), reqState0.req);
if (syncMode == FULL_ASYNC) {
completeFuture(new GridCacheReturn(cctx, true, true, null, null, true), null, null);
return;
}
if (reqState0.req.initMappingLocally() && (cctx.discovery().topologyVersion() != topVer.topologyVersion()))
checkDhtNodes(futId);
}
Aggregations