use of org.apache.ignite.internal.processors.cache.GridCacheEntryEx in project ignite by apache.
the class GridPartitionedGetFuture method localGet.
/**
* @param topVer Topology version.
* @param key Key.
* @param part Partition.
* @param locVals Local values.
* @return {@code True} if there is no need to further search value.
*/
private boolean localGet(AffinityTopologyVersion topVer, KeyCacheObject key, int part, Map<K, V> locVals) {
assert cctx.affinityNode() : this;
GridDhtCacheAdapter<K, V> cache = cache();
boolean readNoEntry = cctx.readNoEntry(expiryPlc, false);
boolean evt = !skipVals;
while (true) {
try {
boolean skipEntry = readNoEntry;
EntryGetResult getRes = null;
CacheObject v = null;
GridCacheVersion ver = null;
if (readNoEntry) {
CacheDataRow row = cctx.offheap().read(cctx, key);
if (row != null) {
long expireTime = row.expireTime();
if (expireTime == 0 || expireTime > U.currentTimeMillis()) {
v = row.value();
if (needVer)
ver = row.version();
if (evt) {
cctx.events().readEvent(key, null, row.value(), subjId, taskName, !deserializeBinary);
}
} else
skipEntry = false;
}
}
if (!skipEntry) {
GridCacheEntryEx entry = cache.entryEx(key);
// If our DHT cache do has value, then we peek it.
if (entry != null) {
boolean isNew = entry.isNewLocked();
if (needVer) {
getRes = entry.innerGetVersioned(null, null, /*update-metrics*/
false, /*event*/
evt, subjId, null, taskName, expiryPlc, !deserializeBinary, null);
if (getRes != null) {
v = getRes.value();
ver = getRes.version();
}
} else {
v = entry.innerGet(null, null, /*read-through*/
false, /*update-metrics*/
false, /*event*/
evt, subjId, null, taskName, expiryPlc, !deserializeBinary);
}
cache.context().evicts().touch(entry, topVer);
// Entry was not in memory or in swap, so we remove it from cache.
if (v == null) {
if (isNew && entry.markObsoleteIfEmpty(ver))
cache.removeEntry(entry);
}
}
}
if (v != null) {
cctx.addResult(locVals, key, v, skipVals, keepCacheObjects, deserializeBinary, true, getRes, ver, 0, 0, needVer);
return true;
}
boolean topStable = cctx.isReplicated() || topVer.equals(cctx.topology().lastTopologyChangeVersion());
// Entry not found, do not continue search if topology did not change and there is no store.
if (!cctx.readThroughConfigured() && (topStable || partitionOwned(part))) {
if (!skipVals && cctx.statisticsEnabled())
cache.metrics0().onRead(false);
return true;
}
return false;
} catch (GridCacheEntryRemovedException ignored) {
// No-op, will retry.
} catch (GridDhtInvalidPartitionException ignored) {
return false;
} catch (IgniteCheckedException e) {
onDone(e);
return true;
}
}
}
use of org.apache.ignite.internal.processors.cache.GridCacheEntryEx in project ignite by apache.
the class GridLocalAtomicCache method updateAllInternal.
/**
* Entry point for all public update methods (put, remove, invoke).
*
* @param op Operation.
* @param keys Keys.
* @param vals Values.
* @param invokeArgs Optional arguments for EntryProcessor.
* @param expiryPlc Expiry policy.
* @param retval Return value required flag.
* @param rawRetval Return {@code GridCacheReturn} instance.
* @param filter Cache entry filter.
* @param writeThrough Write through.
* @param readThrough Read through.
* @return Update result.
* @throws IgniteCheckedException If failed.
*/
@SuppressWarnings("unchecked")
private Object updateAllInternal(GridCacheOperation op, Collection<? extends K> keys, @Nullable Iterable<?> vals, @Nullable Object[] invokeArgs, @Nullable ExpiryPolicy expiryPlc, boolean retval, boolean rawRetval, CacheEntryPredicate filter, boolean writeThrough, boolean readThrough, boolean keepBinary) throws IgniteCheckedException {
if (keyCheck)
validateCacheKeys(keys);
if (op == DELETE)
ctx.checkSecurity(SecurityPermission.CACHE_REMOVE);
else
ctx.checkSecurity(SecurityPermission.CACHE_PUT);
String taskName = ctx.kernalContext().job().currentTaskName();
GridCacheVersion ver = ctx.versions().next();
UUID subjId = ctx.subjectIdPerCall(null);
CacheEntryPredicate[] filters = CU.filterArray(filter);
IgniteBiTuple<Boolean, ?> res = null;
CachePartialUpdateCheckedException err = null;
ctx.shared().database().checkpointReadLock();
try {
ctx.shared().database().ensureFreeSpace(ctx.dataRegion());
if (writeThrough && keys.size() > 1) {
return updateWithBatch(op, keys, vals, invokeArgs, expiryPlc, ver, filters, keepBinary, subjId, taskName);
}
Iterator<?> valsIter = vals != null ? vals.iterator() : null;
boolean intercept = ctx.config().getInterceptor() != null;
for (K key : keys) {
if (key == null)
throw new NullPointerException("Null key.");
Object val = valsIter != null ? valsIter.next() : null;
if (val == null && op != DELETE)
throw new NullPointerException("Null value.");
KeyCacheObject cacheKey = ctx.toCacheKeyObject(key);
if (op == UPDATE) {
val = ctx.toCacheObject(val);
ctx.validateKeyAndValue(cacheKey, (CacheObject) val);
} else if (op == TRANSFORM)
ctx.kernalContext().resource().inject(val, GridResourceIoc.AnnotationSet.ENTRY_PROCESSOR, ctx.name());
while (true) {
GridCacheEntryEx entry = null;
try {
entry = entryEx(cacheKey);
GridTuple3<Boolean, Object, EntryProcessorResult<Object>> t = entry.innerUpdateLocal(ver, val == null ? DELETE : op, val, invokeArgs, writeThrough, readThrough, retval, keepBinary, expiryPlc, true, true, filters, intercept, subjId, taskName);
if (op == TRANSFORM) {
if (t.get3() != null) {
Map<K, EntryProcessorResult> computedMap;
if (res == null) {
computedMap = U.newHashMap(keys.size());
res = new IgniteBiTuple<>(true, computedMap);
} else
computedMap = (Map<K, EntryProcessorResult>) res.get2();
computedMap.put(key, t.get3());
}
} else if (res == null)
res = new T2(t.get1(), t.get2());
// While.
break;
} catch (GridCacheEntryRemovedException ignored) {
if (log.isDebugEnabled())
log.debug("Got removed entry while updating (will retry): " + key);
entry = null;
} catch (IgniteCheckedException e) {
if (err == null)
err = partialUpdateException();
err.add(F.asList(key), e);
U.error(log, "Failed to update key : " + key, e);
break;
} finally {
if (entry != null)
ctx.evicts().touch(entry, ctx.affinity().affinityTopologyVersion());
}
}
}
} finally {
ctx.shared().database().checkpointReadUnlock();
}
if (err != null)
throw err;
Object ret = res == null ? null : rawRetval ? new GridCacheReturn(ctx, true, keepBinary, res.get2(), res.get1()) : (retval || op == TRANSFORM) ? res.get2() : res.get1();
if (op == TRANSFORM && ret == null)
ret = Collections.emptyMap();
return ret;
}
use of org.apache.ignite.internal.processors.cache.GridCacheEntryEx in project ignite by apache.
the class GridLocalAtomicCache method updatePartialBatch.
/**
* @param entries Entries to update.
* @param ver Cache version.
* @param writeVals Cache values.
* @param putMap Values to put.
* @param rmvKeys Keys to remove.
* @param expiryPlc Expiry policy.
* @param err Optional partial update exception.
* @param subjId Subject ID.
* @param taskName Task name.
* @return Partial update exception.
*/
@SuppressWarnings({ "unchecked", "ConstantConditions", "ForLoopReplaceableByForEach" })
@Nullable
private CachePartialUpdateCheckedException updatePartialBatch(List<GridCacheEntryEx> entries, final GridCacheVersion ver, @Nullable List<CacheObject> writeVals, @Nullable Map<KeyCacheObject, CacheObject> putMap, @Nullable Collection<KeyCacheObject> rmvKeys, @Nullable ExpiryPolicy expiryPlc, boolean keepBinary, @Nullable CachePartialUpdateCheckedException err, UUID subjId, String taskName) {
assert putMap == null ^ rmvKeys == null;
GridCacheOperation op;
CacheStorePartialUpdateException storeErr = null;
try {
if (putMap != null) {
try {
Map<? extends KeyCacheObject, IgniteBiTuple<? extends CacheObject, GridCacheVersion>> view = F.viewReadOnly(putMap, new C1<CacheObject, IgniteBiTuple<? extends CacheObject, GridCacheVersion>>() {
@Override
public IgniteBiTuple<? extends CacheObject, GridCacheVersion> apply(CacheObject val) {
return F.t(val, ver);
}
});
ctx.store().putAll(null, view);
} catch (CacheStorePartialUpdateException e) {
storeErr = e;
}
op = UPDATE;
} else {
try {
ctx.store().removeAll(null, rmvKeys);
} catch (CacheStorePartialUpdateException e) {
storeErr = e;
}
op = DELETE;
}
} catch (IgniteCheckedException e) {
if (err == null)
err = partialUpdateException();
err.add(putMap != null ? putMap.keySet() : rmvKeys, e);
return err;
}
boolean intercept = ctx.config().getInterceptor() != null;
for (int i = 0; i < entries.size(); i++) {
GridCacheEntryEx entry = entries.get(i);
assert entry.lockedByCurrentThread();
if (entry.obsolete() || (storeErr != null && storeErr.failedKeys().contains(entry.key().value(ctx.cacheObjectContext(), false))))
continue;
try {
// We are holding java-level locks on entries at this point.
CacheObject writeVal = op == UPDATE ? writeVals.get(i) : null;
assert writeVal != null || op == DELETE : "null write value found.";
GridTuple3<Boolean, Object, EntryProcessorResult<Object>> t = entry.innerUpdateLocal(ver, op, writeVal, null, false, false, false, keepBinary, expiryPlc, true, true, null, false, subjId, taskName);
if (intercept) {
if (op == UPDATE)
ctx.config().getInterceptor().onAfterPut(new CacheLazyEntry(ctx, entry.key(), writeVal, keepBinary));
else
ctx.config().getInterceptor().onAfterRemove(new CacheLazyEntry(ctx, entry.key(), t.get2(), keepBinary));
}
} catch (GridCacheEntryRemovedException ignore) {
assert false : "Entry cannot become obsolete while holding lock.";
} catch (IgniteCheckedException e) {
if (err == null)
err = partialUpdateException();
err.add(Collections.singleton(entry.key()), e);
}
}
return err;
}
use of org.apache.ignite.internal.processors.cache.GridCacheEntryEx in project ignite by apache.
the class GridLocalAtomicCache method lockEntries.
/**
* Acquires java-level locks on cache entries.
*
* @param keys Keys to lock.
* @return Collection of locked entries.
*/
private List<GridCacheEntryEx> lockEntries(Collection<? extends K> keys) {
List<GridCacheEntryEx> locked = new ArrayList<>(keys.size());
boolean nullKeys = false;
while (true) {
for (K key : keys) {
if (key == null) {
nullKeys = true;
break;
}
GridCacheEntryEx entry = entryEx(ctx.toCacheKeyObject(key));
locked.add(entry);
}
if (nullKeys)
break;
for (int i = 0; i < locked.size(); i++) {
GridCacheEntryEx entry = locked.get(i);
entry.lockEntry();
if (entry.obsolete()) {
// Unlock all locked.
for (int j = 0; j <= i; j++) locked.get(j).unlockEntry();
// Clear entries.
locked.clear();
// Retry.
break;
}
}
if (!locked.isEmpty())
return locked;
}
assert nullKeys;
AffinityTopologyVersion topVer = ctx.affinity().affinityTopologyVersion();
for (GridCacheEntryEx entry : locked) ctx.evicts().touch(entry, topVer);
throw new NullPointerException("Null key.");
}
use of org.apache.ignite.internal.processors.cache.GridCacheEntryEx in project ignite by apache.
the class GridLocalAtomicCache method updateWithBatch.
/**
* Updates entries using batched write-through.
*
* @param op Operation.
* @param keys Keys.
* @param vals Values.
* @param invokeArgs Optional arguments for EntryProcessor.
* @param expiryPlc Expiry policy.
* @param ver Cache version.
* @param filter Optional filter.
* @param subjId Subject ID.
* @param taskName Task name.
* @return Results map for invoke operation.
* @throws CachePartialUpdateCheckedException If update failed.
*/
@SuppressWarnings({ "ForLoopReplaceableByForEach", "unchecked" })
private Map<K, EntryProcessorResult> updateWithBatch(GridCacheOperation op, Collection<? extends K> keys, @Nullable Iterable<?> vals, @Nullable Object[] invokeArgs, @Nullable ExpiryPolicy expiryPlc, GridCacheVersion ver, @Nullable CacheEntryPredicate[] filter, boolean keepBinary, UUID subjId, String taskName) throws IgniteCheckedException {
List<GridCacheEntryEx> locked = lockEntries(keys);
try {
int size = locked.size();
Map<KeyCacheObject, CacheObject> putMap = null;
Collection<KeyCacheObject> rmvKeys = null;
List<CacheObject> writeVals = null;
Map<K, EntryProcessorResult> invokeResMap = op == TRANSFORM ? U.<K, EntryProcessorResult>newHashMap(size) : null;
List<GridCacheEntryEx> filtered = new ArrayList<>(size);
CachePartialUpdateCheckedException err = null;
Iterator<?> valsIter = vals != null ? vals.iterator() : null;
boolean intercept = ctx.config().getInterceptor() != null;
for (int i = 0; i < size; i++) {
GridCacheEntryEx entry = locked.get(i);
Object val = valsIter != null ? valsIter.next() : null;
if (val == null && op != DELETE)
throw new NullPointerException("Null value.");
try {
try {
if (!ctx.isAllLocked(entry, filter)) {
if (log.isDebugEnabled())
log.debug("Entry did not pass the filter (will skip write) [entry=" + entry + ", filter=" + Arrays.toString(filter) + ']');
continue;
}
} catch (IgniteCheckedException e) {
if (err == null)
err = partialUpdateException();
err.add(F.asList(entry.key()), e);
continue;
}
if (op == TRANSFORM) {
ctx.kernalContext().resource().inject(val, GridResourceIoc.AnnotationSet.ENTRY_PROCESSOR, ctx.name());
EntryProcessor<Object, Object, Object> entryProcessor = (EntryProcessor<Object, Object, Object>) val;
CacheObject old = entry.innerGet(null, null, /*read-through*/
true, /*update-metrics*/
true, /*event*/
true, subjId, entryProcessor, taskName, null, keepBinary);
Object oldVal = null;
CacheInvokeEntry<Object, Object> invokeEntry = new CacheInvokeEntry<>(entry.key(), old, entry.version(), keepBinary, entry);
CacheObject updated;
Object updatedVal = null;
CacheInvokeResult invokeRes = null;
boolean validation = false;
try {
Object computed = entryProcessor.process(invokeEntry, invokeArgs);
updatedVal = ctx.unwrapTemporary(invokeEntry.getValue());
updated = ctx.toCacheObject(updatedVal);
if (computed != null)
invokeRes = CacheInvokeResult.fromResult(ctx.unwrapTemporary(computed));
if (invokeEntry.modified()) {
validation = true;
ctx.validateKeyAndValue(entry.key(), updated);
}
} catch (Exception e) {
invokeRes = CacheInvokeResult.fromError(e);
updated = old;
if (validation) {
invokeResMap.put((K) entry.key().value(ctx.cacheObjectContext(), false), invokeRes);
continue;
}
}
if (invokeRes != null)
invokeResMap.put((K) entry.key().value(ctx.cacheObjectContext(), false), invokeRes);
if (updated == null) {
if (intercept) {
IgniteBiTuple<Boolean, ?> interceptorRes = ctx.config().getInterceptor().onBeforeRemove(new CacheLazyEntry(ctx, entry.key(), invokeEntry.key(), old, oldVal, keepBinary));
if (ctx.cancelRemove(interceptorRes))
continue;
}
// Update previous batch.
if (putMap != null) {
err = updatePartialBatch(filtered, ver, writeVals, putMap, null, expiryPlc, keepBinary, err, subjId, taskName);
putMap = null;
writeVals = null;
filtered = new ArrayList<>();
}
// Start collecting new batch.
if (rmvKeys == null)
rmvKeys = new ArrayList<>(size);
rmvKeys.add(entry.key());
} else {
if (intercept) {
Object interceptorVal = ctx.config().getInterceptor().onBeforePut(new CacheLazyEntry(ctx, entry.key(), invokeEntry.getKey(), old, oldVal, keepBinary), updatedVal);
if (interceptorVal == null)
continue;
updated = ctx.toCacheObject(ctx.unwrapTemporary(interceptorVal));
}
// Update previous batch.
if (rmvKeys != null) {
err = updatePartialBatch(filtered, ver, null, null, rmvKeys, expiryPlc, keepBinary, err, subjId, taskName);
rmvKeys = 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);
}
} else if (op == UPDATE) {
CacheObject cacheVal = ctx.toCacheObject(val);
if (intercept) {
CacheObject old = entry.innerGet(null, null, /*read-through*/
ctx.loadPreviousValue(), /*update-metrics*/
true, /*event*/
true, subjId, null, taskName, null, keepBinary);
Object interceptorVal = ctx.config().getInterceptor().onBeforePut(new CacheLazyEntry(ctx, entry.key(), old, keepBinary), val);
if (interceptorVal == null)
continue;
cacheVal = ctx.toCacheObject(ctx.unwrapTemporary(interceptorVal));
}
ctx.validateKeyAndValue(entry.key(), cacheVal);
if (putMap == null) {
putMap = new LinkedHashMap<>(size, 1.0f);
writeVals = new ArrayList<>(size);
}
putMap.put(entry.key(), cacheVal);
writeVals.add(cacheVal);
} else {
assert op == DELETE;
if (intercept) {
CacheObject old = entry.innerGet(null, null, /*read-through*/
ctx.loadPreviousValue(), /*update-metrics*/
true, /*event*/
true, subjId, null, taskName, null, keepBinary);
IgniteBiTuple<Boolean, ?> interceptorRes = ctx.config().getInterceptor().onBeforeRemove(new CacheLazyEntry(ctx, entry.key(), old, keepBinary));
if (ctx.cancelRemove(interceptorRes))
continue;
}
if (rmvKeys == null)
rmvKeys = new ArrayList<>(size);
rmvKeys.add(entry.key());
}
filtered.add(entry);
} catch (IgniteCheckedException e) {
if (err == null)
err = partialUpdateException();
err.add(F.asList(entry.key()), e);
} catch (GridCacheEntryRemovedException ignore) {
assert false : "Entry cannot become obsolete while holding lock.";
}
}
// Store final batch.
if (putMap != null || rmvKeys != null) {
err = updatePartialBatch(filtered, ver, writeVals, putMap, rmvKeys, expiryPlc, keepBinary, err, subjId, taskName);
} else
assert filtered.isEmpty();
if (err != null)
throw err;
return invokeResMap;
} finally {
unlockEntries(locked);
}
}
Aggregations