use of org.apache.ignite.internal.processors.cache.GridCacheReturn in project ignite by apache.
the class GridDhtAtomicCache method updateWithBatch.
/**
* Updates locked entries using batched write-through.
*
* @param node Sender 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 version.
* @param dhtFut Optional DHT future.
* @param replicate Whether replication is enabled.
* @param taskName Task name.
* @param expiry Expiry policy.
* @param sndPrevVal If {@code true} sends previous value to backups.
* @return Deleted entries.
* @throws GridCacheEntryRemovedException Should not be thrown.
*/
@SuppressWarnings("unchecked")
private UpdateBatchResult updateWithBatch(final ClusterNode node, final boolean hasNear, final GridNearAtomicAbstractUpdateRequest req, final GridNearAtomicUpdateResponse res, final List<GridDhtCacheEntry> locked, final GridCacheVersion ver, @Nullable GridDhtAtomicAbstractUpdateFuture dhtFut, final boolean replicate, final String taskName, @Nullable final IgniteCacheExpiryPolicy expiry, final boolean sndPrevVal) throws GridCacheEntryRemovedException {
// Cannot update in batches during DR due to possible conflicts.
assert !ctx.dr().receiveEnabled();
// Should not request return values for putAll.
assert !req.returnValue() || req.operation() == TRANSFORM;
if (!F.isEmpty(req.filter()) && ctx.loadPreviousValue()) {
try {
reloadIfNeeded(locked);
} catch (IgniteCheckedException e) {
res.addFailedKeys(req.keys(), e);
return new UpdateBatchResult();
}
}
int size = req.size();
Map<KeyCacheObject, CacheObject> putMap = null;
Map<KeyCacheObject, EntryProcessor<Object, Object, Object>> entryProcessorMap = null;
Collection<KeyCacheObject> rmvKeys = null;
List<CacheObject> writeVals = null;
UpdateBatchResult updRes = new UpdateBatchResult();
List<GridDhtCacheEntry> filtered = new ArrayList<>(size);
GridCacheOperation op = req.operation();
GridCacheReturn invokeRes = null;
int firstEntryIdx = 0;
boolean intercept = ctx.config().getInterceptor() != null;
for (int i = 0; i < locked.size(); i++) {
GridDhtCacheEntry entry = locked.get(i);
try {
if (!checkFilter(entry, req, res)) {
if (expiry != null && entry.hasValue()) {
long ttl = expiry.forAccess();
if (ttl != CU.TTL_NOT_CHANGED) {
entry.updateTtl(null, ttl);
expiry.ttlUpdated(entry.key(), entry.version(), entry.readers());
}
}
if (log.isDebugEnabled())
log.debug("Entry did not pass the filter (will skip write) [entry=" + entry + ", filter=" + Arrays.toString(req.filter()) + ", res=" + res + ']');
if (hasNear)
res.addSkippedIndex(i);
firstEntryIdx++;
continue;
}
if (op == TRANSFORM) {
EntryProcessor<Object, Object, Object> entryProcessor = req.entryProcessor(i);
CacheObject old = entry.innerGet(ver, null, /*read through*/
true, /*metrics*/
true, /*event*/
true, req.subjectId(), entryProcessor, taskName, null, req.keepBinary());
Object oldVal = null;
Object updatedVal = null;
CacheInvokeEntry<Object, Object> invokeEntry = new CacheInvokeEntry(entry.key(), old, entry.version(), req.keepBinary(), entry);
CacheObject updated;
try {
Object computed = entryProcessor.process(invokeEntry, req.invokeArguments());
if (computed != null) {
if (invokeRes == null)
invokeRes = new GridCacheReturn(node.isLocal());
computed = ctx.unwrapTemporary(computed);
invokeRes.addEntryProcessResult(ctx, entry.key(), invokeEntry.key(), computed, null, req.keepBinary());
}
if (!invokeEntry.modified())
continue;
updatedVal = ctx.unwrapTemporary(invokeEntry.getValue());
updated = ctx.toCacheObject(updatedVal);
} catch (Exception e) {
if (invokeRes == null)
invokeRes = new GridCacheReturn(node.isLocal());
invokeRes.addEntryProcessResult(ctx, entry.key(), invokeEntry.key(), null, e, req.keepBinary());
updated = old;
}
if (updated == null) {
if (intercept) {
CacheLazyEntry e = new CacheLazyEntry(ctx, entry.key(), invokeEntry.key(), old, oldVal, req.keepBinary());
IgniteBiTuple<Boolean, ?> interceptorRes = ctx.config().getInterceptor().onBeforeRemove(e);
if (ctx.cancelRemove(interceptorRes))
continue;
}
// Update previous batch.
if (putMap != null) {
dhtFut = updatePartialBatch(hasNear, firstEntryIdx, filtered, ver, node, writeVals, putMap, null, entryProcessorMap, dhtFut, req, res, replicate, updRes, taskName, expiry, sndPrevVal);
firstEntryIdx = i;
putMap = null;
writeVals = null;
entryProcessorMap = null;
filtered = new ArrayList<>();
}
// Start collecting new batch.
if (rmvKeys == null)
rmvKeys = new ArrayList<>(size);
rmvKeys.add(entry.key());
} else {
if (intercept) {
CacheLazyEntry e = new CacheLazyEntry(ctx, entry.key(), invokeEntry.key(), old, oldVal, req.keepBinary());
Object val = ctx.config().getInterceptor().onBeforePut(e, updatedVal);
if (val == null)
continue;
updated = ctx.toCacheObject(ctx.unwrapTemporary(val));
}
// Update previous batch.
if (rmvKeys != null) {
dhtFut = updatePartialBatch(hasNear, firstEntryIdx, filtered, ver, node, null, null, rmvKeys, entryProcessorMap, dhtFut, req, res, replicate, updRes, taskName, expiry, sndPrevVal);
firstEntryIdx = i;
rmvKeys = null;
entryProcessorMap = null;
filtered = new ArrayList<>();
}
if (putMap == null) {
putMap = new LinkedHashMap<>(size, 1.0f);
writeVals = new ArrayList<>(size);
}
putMap.put(entry.key(), updated);
writeVals.add(updated);
}
if (entryProcessorMap == null)
entryProcessorMap = new HashMap<>();
entryProcessorMap.put(entry.key(), entryProcessor);
} else if (op == UPDATE) {
CacheObject updated = req.value(i);
if (intercept) {
CacheObject old = entry.innerGet(null, null, /*read through*/
ctx.loadPreviousValue(), /*metrics*/
true, /*event*/
true, req.subjectId(), null, taskName, null, req.keepBinary());
Object val = ctx.config().getInterceptor().onBeforePut(new CacheLazyEntry(ctx, entry.key(), old, req.keepBinary()), ctx.unwrapBinaryIfNeeded(updated, req.keepBinary(), false));
if (val == null)
continue;
updated = ctx.toCacheObject(ctx.unwrapTemporary(val));
}
assert updated != null;
if (putMap == null) {
putMap = new LinkedHashMap<>(size, 1.0f);
writeVals = new ArrayList<>(size);
}
putMap.put(entry.key(), updated);
writeVals.add(updated);
} else {
assert op == DELETE;
if (intercept) {
CacheObject old = entry.innerGet(null, null, /*read through*/
ctx.loadPreviousValue(), /*metrics*/
true, /*event*/
true, req.subjectId(), null, taskName, null, req.keepBinary());
IgniteBiTuple<Boolean, ?> interceptorRes = ctx.config().getInterceptor().onBeforeRemove(new CacheLazyEntry(ctx, entry.key(), old, req.keepBinary()));
if (ctx.cancelRemove(interceptorRes))
continue;
}
if (rmvKeys == null)
rmvKeys = new ArrayList<>(size);
rmvKeys.add(entry.key());
}
filtered.add(entry);
} catch (IgniteCheckedException e) {
res.addFailedKey(entry.key(), e);
}
}
// Store final batch.
if (putMap != null || rmvKeys != null) {
dhtFut = updatePartialBatch(hasNear, firstEntryIdx, filtered, ver, node, writeVals, putMap, rmvKeys, entryProcessorMap, dhtFut, req, res, replicate, updRes, taskName, expiry, sndPrevVal);
} else
assert filtered.isEmpty();
updRes.dhtFuture(dhtFut);
updRes.invokeResult(invokeRes);
return updRes;
}
use of org.apache.ignite.internal.processors.cache.GridCacheReturn in project ignite by apache.
the class GridDhtAtomicCache method processCheckUpdateRequest.
/**
* @param nodeId Node ID.
* @param checkReq Request.
*/
private void processCheckUpdateRequest(UUID nodeId, GridNearAtomicCheckUpdateRequest checkReq) {
/*
* Message is processed in the same stripe, so primary already processed update request. It is possible
* response was not sent if operation result was empty. Near node will get original response or this one.
*/
GridNearAtomicUpdateResponse res = new GridNearAtomicUpdateResponse(ctx.cacheId(), nodeId, checkReq.futureId(), checkReq.partition(), false, false);
GridCacheReturn ret = new GridCacheReturn(false, true);
res.returnValue(ret);
sendNearUpdateReply(nodeId, res);
}
use of org.apache.ignite.internal.processors.cache.GridCacheReturn in project ignite by apache.
the class GridNearAtomicUpdateFuture method onNodeLeft.
/** {@inheritDoc} */
@Override
public boolean onNodeLeft(UUID nodeId) {
GridCacheReturn opRes0 = null;
CachePartialUpdateCheckedException err0 = null;
AffinityTopologyVersion remapTopVer0 = null;
boolean rcvAll = false;
List<GridNearAtomicCheckUpdateRequest> checkReqs = null;
long futId;
synchronized (this) {
if (!futureMapped())
return false;
futId = this.futId;
if (singleReq != null) {
if (singleReq.req.nodeId.equals(nodeId)) {
GridNearAtomicAbstractUpdateRequest req = singleReq.onPrimaryFail();
if (req != null) {
rcvAll = true;
GridNearAtomicUpdateResponse res = primaryFailedResponse(req);
singleReq.onPrimaryResponse(res, cctx);
onPrimaryError(req, res);
}
} else {
DhtLeftResult res = singleReq.onDhtNodeLeft(nodeId);
if (res == DhtLeftResult.DONE)
rcvAll = true;
else if (res == DhtLeftResult.ALL_RCVD_CHECK_PRIMARY)
checkReqs = Collections.singletonList(new GridNearAtomicCheckUpdateRequest(singleReq.req));
}
if (rcvAll) {
opRes0 = opRes;
err0 = err;
remapTopVer0 = onAllReceived();
}
} else {
if (mappings == null)
return false;
for (Map.Entry<UUID, PrimaryRequestState> e : mappings.entrySet()) {
assert e.getKey().equals(e.getValue().req.nodeId());
PrimaryRequestState reqState = e.getValue();
boolean reqDone = false;
if (e.getKey().equals(nodeId)) {
GridNearAtomicAbstractUpdateRequest req = reqState.onPrimaryFail();
if (req != null) {
reqDone = true;
GridNearAtomicUpdateResponse res = primaryFailedResponse(req);
reqState.onPrimaryResponse(res, cctx);
onPrimaryError(req, res);
}
} else {
DhtLeftResult res = reqState.onDhtNodeLeft(nodeId);
if (res == DhtLeftResult.DONE)
reqDone = true;
else if (res == DhtLeftResult.ALL_RCVD_CHECK_PRIMARY) {
if (checkReqs == null)
checkReqs = new ArrayList<>();
checkReqs.add(new GridNearAtomicCheckUpdateRequest(reqState.req));
}
}
if (reqDone) {
assert mappings.size() > resCnt : "[mappings=" + mappings.size() + ", cnt=" + resCnt + ']';
resCnt++;
if (mappings.size() == resCnt) {
rcvAll = true;
opRes0 = opRes;
err0 = err;
remapTopVer0 = onAllReceived();
break;
}
}
}
}
}
if (checkReqs != null) {
assert !rcvAll;
for (int i = 0; i < checkReqs.size(); i++) sendCheckUpdateRequest(checkReqs.get(i));
} else if (rcvAll)
finishUpdateFuture(opRes0, err0, remapTopVer0, futId);
return false;
}
use of org.apache.ignite.internal.processors.cache.GridCacheReturn in project ignite by apache.
the class GridNearAtomicUpdateFuture method checkDhtNodes.
private void checkDhtNodes(long futId) {
GridCacheReturn opRes0 = null;
CachePartialUpdateCheckedException err0 = null;
AffinityTopologyVersion remapTopVer0 = null;
List<GridNearAtomicCheckUpdateRequest> checkReqs = null;
boolean rcvAll = false;
synchronized (this) {
if (!checkFutureId(futId))
return;
if (singleReq != null) {
if (!singleReq.req.initMappingLocally())
return;
DhtLeftResult res = singleReq.checkDhtNodes(cctx);
if (res == DhtLeftResult.DONE) {
opRes0 = opRes;
err0 = err;
remapTopVer0 = onAllReceived();
} else if (res == DhtLeftResult.ALL_RCVD_CHECK_PRIMARY)
checkReqs = Collections.singletonList(new GridNearAtomicCheckUpdateRequest(singleReq.req));
else
return;
} else {
if (mappings != null) {
for (PrimaryRequestState reqState : mappings.values()) {
if (!reqState.req.initMappingLocally())
continue;
DhtLeftResult res = reqState.checkDhtNodes(cctx);
if (res == DhtLeftResult.DONE) {
assert mappings.size() > resCnt : "[mappings=" + mappings.size() + ", cnt=" + resCnt + ']';
resCnt++;
if (mappings.size() == resCnt) {
rcvAll = true;
opRes0 = opRes;
err0 = err;
remapTopVer0 = onAllReceived();
break;
}
} else if (res == DhtLeftResult.ALL_RCVD_CHECK_PRIMARY) {
if (checkReqs == null)
checkReqs = new ArrayList<>(mappings.size());
checkReqs.add(new GridNearAtomicCheckUpdateRequest(reqState.req));
}
}
} else
return;
}
}
if (checkReqs != null) {
assert !rcvAll;
for (int i = 0; i < checkReqs.size(); i++) sendCheckUpdateRequest(checkReqs.get(i));
} else if (rcvAll)
finishUpdateFuture(opRes0, err0, remapTopVer0, futId);
}
use of org.apache.ignite.internal.processors.cache.GridCacheReturn in project ignite by apache.
the class GridNearAtomicUpdateFuture method sendUpdateRequests.
/**
* Sends messages to remote nodes and updates local cache.
*
* @param mappings Mappings to send.
*/
private void sendUpdateRequests(Map<UUID, PrimaryRequestState> mappings) {
UUID locNodeId = cctx.localNodeId();
GridNearAtomicAbstractUpdateRequest locUpdate = null;
// Send messages to remote nodes first, then run local update.
for (PrimaryRequestState reqState : mappings.values()) {
GridNearAtomicAbstractUpdateRequest req = reqState.req;
if (locNodeId.equals(req.nodeId())) {
assert locUpdate == null : "Cannot have more than one local mapping [locUpdate=" + locUpdate + ", req=" + req + ']';
locUpdate = req;
} else {
try {
if (req.initMappingLocally() && reqState.dhtNodes.isEmpty()) {
reqState.dhtNodes = null;
req.needPrimaryResponse(true);
}
cctx.io().send(req.nodeId(), req, cctx.ioPolicy());
if (msgLog.isDebugEnabled()) {
msgLog.debug("Near update fut, sent request [futId=" + req.futureId() + ", node=" + req.nodeId() + ']');
}
} catch (IgniteCheckedException e) {
if (msgLog.isDebugEnabled()) {
msgLog.debug("Near update fut, failed to send request [futId=" + req.futureId() + ", node=" + req.nodeId() + ", err=" + e + ']');
}
onSendError(req, e);
}
}
}
if (locUpdate != null) {
cache.updateAllAsyncInternal(cctx.localNodeId(), locUpdate, new GridDhtAtomicCache.UpdateReplyClosure() {
@Override
public void apply(GridNearAtomicAbstractUpdateRequest req, GridNearAtomicUpdateResponse res) {
if (syncMode != FULL_ASYNC)
onPrimaryResponse(res.nodeId(), res, false);
else if (res.remapTopologyVersion() != null)
((GridDhtAtomicCache) cctx.cache()).remapToNewPrimary(req);
}
});
}
if (syncMode == FULL_ASYNC)
completeFuture(new GridCacheReturn(cctx, true, true, null, true), null, null);
}
Aggregations