use of org.apache.ignite.internal.processors.cache.CacheObject 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 dhtFut Optional DHT future.
* @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.
* @return Return value.
* @throws GridCacheEntryRemovedException Should be never thrown.
*/
private DhtAtomicUpdateResult updateSingle(ClusterNode nearNode, boolean hasNear, GridNearAtomicAbstractUpdateRequest req, GridNearAtomicUpdateResponse res, List<GridDhtCacheEntry> locked, GridCacheVersion ver, @Nullable GridDhtAtomicAbstractUpdateFuture dhtFut, boolean replicate, String taskName, @Nullable IgniteCacheExpiryPolicy expiry, boolean sndPrevVal) throws GridCacheEntryRemovedException {
GridCacheReturn retVal = null;
Collection<IgniteBiTuple<GridDhtCacheEntry, GridCacheVersion>> deleted = null;
AffinityTopologyVersion topVer = req.topologyVersion();
boolean intercept = ctx.config().getInterceptor() != null;
AffinityAssignment affAssignment = ctx.affinity().assignment(topVer);
// Avoid iterator creation.
for (int i = 0; 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, req.subjectId(), taskName, /*prevVal*/
null, /*updateCntr*/
null, dhtFut);
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());
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(), req.returnValue() ? ret : null, updRes.success());
}
}
} catch (IgniteCheckedException e) {
res.addFailedKey(k, e);
}
}
return new DhtAtomicUpdateResult(retVal, deleted, dhtFut);
}
use of org.apache.ignite.internal.processors.cache.CacheObject in project ignite by apache.
the class GridDhtAtomicCache method reloadIfNeeded.
/**
* @param entries Entries.
* @throws IgniteCheckedException If failed.
*/
private void reloadIfNeeded(final List<GridDhtCacheEntry> entries) throws IgniteCheckedException {
Map<KeyCacheObject, Integer> needReload = null;
for (int i = 0; i < entries.size(); i++) {
GridDhtCacheEntry entry = entries.get(i);
if (entry == null)
continue;
CacheObject val = entry.rawGet();
if (val == null) {
if (needReload == null)
needReload = new HashMap<>(entries.size(), 1.0f);
needReload.put(entry.key(), i);
}
}
if (needReload != null) {
final Map<KeyCacheObject, Integer> idxMap = needReload;
ctx.store().loadAll(null, needReload.keySet(), new CI2<KeyCacheObject, Object>() {
@Override
public void apply(KeyCacheObject k, Object v) {
Integer idx = idxMap.get(k);
if (idx != null) {
GridDhtCacheEntry entry = entries.get(idx);
try {
GridCacheVersion ver = entry.version();
entry.versionedValue(ctx.toCacheObject(v), null, ver, null, null);
} catch (GridCacheEntryRemovedException e) {
assert false : "Entry should not get obsolete while holding lock [entry=" + entry + ", e=" + e + ']';
} catch (IgniteCheckedException e) {
throw new IgniteException(e);
}
}
}
});
}
}
use of org.apache.ignite.internal.processors.cache.CacheObject in project ignite by apache.
the class GridDhtAtomicCache method processDhtAtomicUpdateRequest.
/**
* @param nodeId Sender node ID.
* @param req Dht atomic update request.
*/
private void processDhtAtomicUpdateRequest(UUID nodeId, GridDhtAtomicAbstractUpdateRequest req) {
assert Thread.currentThread().getName().startsWith("sys-stripe-") : Thread.currentThread().getName();
if (msgLog.isDebugEnabled()) {
msgLog.debug("Received DHT atomic update request [futId=" + req.futureId() + ", writeVer=" + req.writeVersion() + ", node=" + nodeId + ']');
}
assert req.partition() >= 0 : req;
GridCacheVersion ver = req.writeVersion();
GridDhtAtomicNearResponse nearRes = null;
if (req.nearNodeId() != null) {
nearRes = new GridDhtAtomicNearResponse(ctx.cacheId(), req.partition(), req.nearFutureId(), nodeId, req.flags());
}
boolean replicate = ctx.isDrEnabled();
boolean intercept = req.forceTransformBackups() && ctx.config().getInterceptor() != null;
String taskName = ctx.kernalContext().task().resolveTaskName(req.taskNameHash());
ctx.shared().database().checkpointReadLock();
try {
for (int i = 0; i < req.size(); i++) {
KeyCacheObject key = req.key(i);
try {
while (true) {
GridDhtCacheEntry entry = null;
try {
entry = entryExx(key);
CacheObject val = req.value(i);
CacheObject prevVal = req.previousValue(i);
EntryProcessor<Object, Object, Object> entryProcessor = req.entryProcessor(i);
Long updateIdx = req.updateCounter(i);
GridCacheOperation op = entryProcessor != null ? TRANSFORM : (val != null) ? UPDATE : DELETE;
long ttl = req.ttl(i);
long expireTime = req.conflictExpireTime(i);
GridCacheUpdateAtomicResult updRes = entry.innerUpdate(ver, nodeId, nodeId, op, op == TRANSFORM ? entryProcessor : val, op == TRANSFORM ? req.invokeArguments() : null, /*write-through*/
(ctx.store().isLocal() && !ctx.shared().localStorePrimaryOnly()) && writeThrough() && !req.skipStore(), /*read-through*/
false, /*retval*/
false, req.keepBinary(), /*expiry policy*/
null, /*event*/
true, /*metrics*/
true, /*primary*/
false, /*check version*/
!req.forceTransformBackups(), req.topologyVersion(), CU.empty0(), replicate ? DR_BACKUP : DR_NONE, ttl, expireTime, req.conflictVersion(i), false, intercept, req.subjectId(), taskName, prevVal, updateIdx, null);
if (updRes.removeVersion() != null)
ctx.onDeferredDelete(entry, updRes.removeVersion());
entry.onUnlock();
// While.
break;
} catch (GridCacheEntryRemovedException ignored) {
if (log.isDebugEnabled())
log.debug("Got removed entry while updating backup value (will retry): " + key);
entry = null;
} finally {
if (entry != null)
ctx.evicts().touch(entry, req.topologyVersion());
}
}
} catch (NodeStoppingException e) {
U.warn(log, "Failed to update key on backup (local node is stopping): " + key);
return;
} catch (GridDhtInvalidPartitionException ignored) {
// Ignore.
} catch (IgniteCheckedException | RuntimeException e) {
if (e instanceof RuntimeException && !X.hasCause(e, IgniteOutOfMemoryException.class))
throw (RuntimeException) e;
IgniteCheckedException err = new IgniteCheckedException("Failed to update key on backup node: " + key, e);
if (nearRes != null)
nearRes.addFailedKey(key, err);
U.error(log, "Failed to update key on backup node: " + key, e);
}
}
} finally {
ctx.shared().database().checkpointReadUnlock();
}
GridDhtAtomicUpdateResponse dhtRes = null;
if (req.nearSize() > 0) {
List<KeyCacheObject> nearEvicted;
if (isNearEnabled(ctx))
nearEvicted = ((GridNearAtomicCache<K, V>) near()).processDhtAtomicUpdateRequest(nodeId, req, nearRes);
else {
nearEvicted = new ArrayList<>(req.nearSize());
for (int i = 0; i < req.nearSize(); i++) nearEvicted.add(req.nearKey(i));
}
if (nearEvicted != null) {
dhtRes = new GridDhtAtomicUpdateResponse(ctx.cacheId(), req.partition(), req.futureId(), ctx.deploymentEnabled());
dhtRes.nearEvicted(nearEvicted);
}
}
try {
// TODO fire events only after successful fsync
if (ctx.shared().wal() != null)
ctx.shared().wal().fsync(null);
} catch (StorageException e) {
if (dhtRes != null)
dhtRes.onError(new IgniteCheckedException(e));
if (nearRes != null)
nearRes.onClassError(e);
} catch (IgniteCheckedException e) {
if (dhtRes != null)
dhtRes.onError(e);
if (nearRes != null)
nearRes.onClassError(e);
}
if (nearRes != null)
sendDhtNearResponse(req, nearRes);
if (dhtRes == null && req.replyWithoutDelay()) {
dhtRes = new GridDhtAtomicUpdateResponse(ctx.cacheId(), req.partition(), req.futureId(), ctx.deploymentEnabled());
}
if (dhtRes != null)
sendDhtPrimaryResponse(nodeId, req, dhtRes);
else
sendDeferredUpdateResponse(req.partition(), nodeId, req.futureId());
}
use of org.apache.ignite.internal.processors.cache.CacheObject in project ignite by apache.
the class GridNearAtomicFullUpdateRequest method addUpdateEntry.
/**
* {@inheritDoc}
*/
@Override
public void addUpdateEntry(KeyCacheObject key, @Nullable Object val, long conflictTtl, long conflictExpireTime, @Nullable GridCacheVersion conflictVer) {
EntryProcessor<Object, Object, Object> entryProcessor = null;
if (op == TRANSFORM) {
assert val instanceof EntryProcessor : val;
entryProcessor = (EntryProcessor<Object, Object, Object>) val;
}
assert val != null || op == DELETE;
keys.add(key);
if (entryProcessor != null) {
if (entryProcessors == null)
entryProcessors = new ArrayList<>(initSize);
entryProcessors.add(entryProcessor);
} else if (val != null) {
assert val instanceof CacheObject : val;
if (vals == null)
vals = new ArrayList<>(initSize);
vals.add((CacheObject) val);
}
// In case there is no conflict, do not create the list.
if (conflictVer != null) {
if (conflictVers == null) {
conflictVers = new ArrayList<>(initSize);
for (int i = 0; i < keys.size() - 1; i++) conflictVers.add(null);
}
conflictVers.add(conflictVer);
} else if (conflictVers != null)
conflictVers.add(null);
if (conflictTtl >= 0) {
if (conflictTtls == null) {
conflictTtls = new GridLongList(keys.size());
for (int i = 0; i < keys.size() - 1; i++) conflictTtls.add(CU.TTL_NOT_CHANGED);
}
conflictTtls.add(conflictTtl);
}
if (conflictExpireTime >= 0) {
if (conflictExpireTimes == null) {
conflictExpireTimes = new GridLongList(keys.size());
for (int i = 0; i < keys.size() - 1; i++) conflictExpireTimes.add(CU.EXPIRE_TIME_CALCULATE);
}
conflictExpireTimes.add(conflictExpireTime);
}
}
use of org.apache.ignite.internal.processors.cache.CacheObject in project ignite by apache.
the class GridNearAtomicUpdateFuture method mapUpdate.
/**
* @param topNodes Cache nodes.
* @param topVer Topology version.
* @param futId Future ID.
* @param remapKeys Keys to remap.
* @return Mapping.
* @throws Exception If failed.
*/
@SuppressWarnings("ForLoopReplaceableByForEach")
private Map<UUID, PrimaryRequestState> mapUpdate(Collection<ClusterNode> topNodes, AffinityTopologyVersion topVer, Long futId, @Nullable Collection<KeyCacheObject> remapKeys, boolean mappingKnown) throws Exception {
Iterator<?> it = null;
if (vals != null)
it = vals.iterator();
Iterator<GridCacheDrInfo> conflictPutValsIt = null;
if (conflictPutVals != null)
conflictPutValsIt = conflictPutVals.iterator();
Iterator<GridCacheVersion> conflictRmvValsIt = null;
if (conflictRmvVals != null)
conflictRmvValsIt = conflictRmvVals.iterator();
Map<UUID, PrimaryRequestState> pendingMappings = U.newHashMap(topNodes.size());
// Create mappings first, then send messages.
for (Object key : keys) {
if (key == null)
throw new NullPointerException("Null key.");
Object val;
GridCacheVersion conflictVer;
long conflictTtl;
long conflictExpireTime;
if (vals != null) {
val = it.next();
conflictVer = null;
conflictTtl = CU.TTL_NOT_CHANGED;
conflictExpireTime = CU.EXPIRE_TIME_CALCULATE;
if (val == null)
throw new NullPointerException("Null value.");
} else if (conflictPutVals != null) {
GridCacheDrInfo conflictPutVal = conflictPutValsIt.next();
val = conflictPutVal.valueEx();
conflictVer = conflictPutVal.version();
conflictTtl = conflictPutVal.ttl();
conflictExpireTime = conflictPutVal.expireTime();
} else if (conflictRmvVals != null) {
val = null;
conflictVer = conflictRmvValsIt.next();
conflictTtl = CU.TTL_NOT_CHANGED;
conflictExpireTime = CU.EXPIRE_TIME_CALCULATE;
} else {
val = null;
conflictVer = null;
conflictTtl = CU.TTL_NOT_CHANGED;
conflictExpireTime = CU.EXPIRE_TIME_CALCULATE;
}
if (val == null && op != GridCacheOperation.DELETE)
continue;
KeyCacheObject cacheKey = cctx.toCacheKeyObject(key);
if (remapKeys != null && !remapKeys.contains(cacheKey))
continue;
if (op != TRANSFORM) {
val = cctx.toCacheObject(val);
if (op == CREATE || op == UPDATE)
cctx.validateKeyAndValue(cacheKey, (CacheObject) val);
} else
val = EntryProcessorResourceInjectorProxy.wrap(cctx.kernalContext(), (EntryProcessor) val);
List<ClusterNode> nodes = cctx.affinity().nodesByKey(cacheKey, topVer);
if (F.isEmpty(nodes))
throw new ClusterTopologyServerNotFoundException("Failed to map keys for cache " + "(all partition nodes left the grid).");
ClusterNode primary = nodes.get(0);
boolean needPrimaryRes = !mappingKnown || primary.isLocal() || nearEnabled;
UUID nodeId = primary.id();
PrimaryRequestState mapped = pendingMappings.get(nodeId);
if (mapped == null) {
byte flags = GridNearAtomicAbstractUpdateRequest.flags(nearEnabled, topLocked, retval, mappingKnown, needPrimaryRes, skipStore, keepBinary, recovery);
GridNearAtomicFullUpdateRequest req = new GridNearAtomicFullUpdateRequest(cctx.cacheId(), nodeId, futId, topVer, syncMode, op, expiryPlc, invokeArgs, filter, subjId, taskNameHash, flags, cctx.deploymentEnabled(), keys.size());
mapped = new PrimaryRequestState(req, nodes, false);
pendingMappings.put(nodeId, mapped);
}
if (mapped.req.initMappingLocally())
mapped.addMapping(nodes);
mapped.req.addUpdateEntry(cacheKey, val, conflictTtl, conflictExpireTime, conflictVer);
}
return pendingMappings;
}
Aggregations