use of org.apache.ignite.internal.processors.cache.GridCacheEntryInfo in project ignite by apache.
the class GridPartitionedGetFuture method map.
/**
* @param keys Keys.
* @param mapped Mappings to check for duplicates.
* @param topVer Topology version on which keys should be mapped.
*/
private void map(Collection<KeyCacheObject> keys, Map<ClusterNode, LinkedHashMap<KeyCacheObject, Boolean>> mapped, AffinityTopologyVersion topVer) {
Collection<ClusterNode> cacheNodes = CU.affinityNodes(cctx, topVer);
if (cacheNodes.isEmpty()) {
onDone(new ClusterTopologyServerNotFoundException("Failed to map keys for cache " + "(all partition nodes left the grid) [topVer=" + topVer + ", cache=" + cctx.name() + ']'));
return;
}
GridDhtTopologyFuture topFut = cctx.shared().exchange().lastFinishedFuture();
Throwable err = topFut != null ? topFut.validateCache(cctx, recovery, true, null, keys) : null;
if (err != null) {
onDone(err);
return;
}
Map<ClusterNode, LinkedHashMap<KeyCacheObject, Boolean>> mappings = U.newHashMap(cacheNodes.size());
final int keysSize = keys.size();
Map<K, V> locVals = U.newHashMap(keysSize);
boolean hasRmtNodes = false;
// Assign keys to primary nodes.
for (KeyCacheObject key : keys) hasRmtNodes |= map(key, mappings, locVals, topVer, mapped);
if (isDone())
return;
if (!locVals.isEmpty())
add(new GridFinishedFuture<>(locVals));
if (hasRmtNodes) {
if (!trackable) {
trackable = true;
cctx.mvcc().addFuture(this, futId);
}
}
// Create mini futures.
for (Map.Entry<ClusterNode, LinkedHashMap<KeyCacheObject, Boolean>> entry : mappings.entrySet()) {
final ClusterNode n = entry.getKey();
final LinkedHashMap<KeyCacheObject, Boolean> mappedKeys = entry.getValue();
assert !mappedKeys.isEmpty();
// If this is the primary or backup node for the keys.
if (n.isLocal()) {
final GridDhtFuture<Collection<GridCacheEntryInfo>> fut = cache().getDhtAsync(n.id(), -1, mappedKeys, readThrough, topVer, subjId, taskName == null ? 0 : taskName.hashCode(), expiryPlc, skipVals, recovery);
final Collection<Integer> invalidParts = fut.invalidPartitions();
if (!F.isEmpty(invalidParts)) {
Collection<KeyCacheObject> remapKeys = new ArrayList<>(keysSize);
for (KeyCacheObject key : keys) {
if (key != null && invalidParts.contains(cctx.affinity().partition(key)))
remapKeys.add(key);
}
AffinityTopologyVersion updTopVer = cctx.discovery().topologyVersionEx();
assert updTopVer.compareTo(topVer) > 0 : "Got invalid partitions for local node but topology version did " + "not change [topVer=" + topVer + ", updTopVer=" + updTopVer + ", invalidParts=" + invalidParts + ']';
// Remap recursively.
map(remapKeys, mappings, updTopVer);
}
// Add new future.
add(fut.chain(new C1<IgniteInternalFuture<Collection<GridCacheEntryInfo>>, Map<K, V>>() {
@Override
public Map<K, V> apply(IgniteInternalFuture<Collection<GridCacheEntryInfo>> fut) {
try {
return createResultMap(fut.get());
} catch (Exception e) {
U.error(log, "Failed to get values from dht cache [fut=" + fut + "]", e);
onDone(e);
return Collections.emptyMap();
}
}
}));
} else {
MiniFuture fut = new MiniFuture(n, mappedKeys, topVer);
GridCacheMessage req = new GridNearGetRequest(cctx.cacheId(), futId, fut.futureId(), null, mappedKeys, readThrough, topVer, subjId, taskName == null ? 0 : taskName.hashCode(), expiryPlc != null ? expiryPlc.forCreate() : -1L, expiryPlc != null ? expiryPlc.forAccess() : -1L, skipVals, cctx.deploymentEnabled(), recovery);
// Append new future.
add(fut);
try {
cctx.io().send(n, req, cctx.ioPolicy());
} catch (IgniteCheckedException e) {
// Fail the whole thing.
if (e instanceof ClusterTopologyCheckedException)
fut.onNodeLeft((ClusterTopologyCheckedException) e);
else
fut.onResult(e);
}
}
}
}
use of org.apache.ignite.internal.processors.cache.GridCacheEntryInfo in project ignite by apache.
the class GridDhtGetFuture method getAsync.
/**
* @param keys Keys to get.
* @return Future for local get.
*/
@SuppressWarnings({ "unchecked", "IfMayBeConditional" })
private IgniteInternalFuture<Collection<GridCacheEntryInfo>> getAsync(final Map<KeyCacheObject, Boolean> keys) {
if (F.isEmpty(keys))
return new GridFinishedFuture<Collection<GridCacheEntryInfo>>(Collections.<GridCacheEntryInfo>emptyList());
String taskName0 = cctx.kernalContext().job().currentTaskName();
if (taskName0 == null)
taskName0 = cctx.kernalContext().task().resolveTaskName(taskNameHash);
final String taskName = taskName0;
GridCompoundFuture<Boolean, Boolean> txFut = null;
ClusterNode readerNode = cctx.discovery().node(reader);
ReaderArguments readerArgs = null;
if (readerNode != null && !readerNode.isLocal() && cctx.discovery().cacheNearNode(readerNode, cctx.name())) {
for (Map.Entry<KeyCacheObject, Boolean> k : keys.entrySet()) {
while (true) {
GridDhtCacheEntry e = cache().entryExx(k.getKey(), topVer);
try {
if (e.obsolete())
continue;
boolean addReader = (!e.deleted() && k.getValue() && !skipVals);
if (addReader) {
e.unswap(false);
// we have to add reader again later.
if (readerArgs == null)
readerArgs = new ReaderArguments(reader, msgId, topVer);
}
// Register reader. If there are active transactions for this entry,
// then will wait for their completion before proceeding.
// TODO: IGNITE-3498:
// TODO: What if any transaction we wait for actually removes this entry?
// TODO: In this case seems like we will be stuck with untracked near entry.
// TODO: To fix, check that reader is contained in the list of readers once
// TODO: again after the returned future completes - if not, try again.
IgniteInternalFuture<Boolean> f = addReader ? e.addReader(reader, msgId, topVer) : null;
if (f != null) {
if (txFut == null)
txFut = new GridCompoundFuture<>(CU.boolReducer());
txFut.add(f);
}
break;
} catch (IgniteCheckedException err) {
return new GridFinishedFuture<>(err);
} catch (GridCacheEntryRemovedException ignore) {
if (log.isDebugEnabled())
log.debug("Got removed entry when getting a DHT value: " + e);
} finally {
cctx.evicts().touch(e, topVer);
}
}
}
if (txFut != null)
txFut.markInitialized();
}
IgniteInternalFuture<Map<KeyCacheObject, EntryGetResult>> fut;
if (txFut == null || txFut.isDone()) {
fut = cache().getDhtAllAsync(keys.keySet(), readerArgs, readThrough, subjId, taskName, expiryPlc, skipVals, /*can remap*/
true, recovery);
} else {
final ReaderArguments args = readerArgs;
// If we are here, then there were active transactions for some entries
// when we were adding the reader. In that case we must wait for those
// transactions to complete.
fut = new GridEmbeddedFuture<>(txFut, new C2<Boolean, Exception, IgniteInternalFuture<Map<KeyCacheObject, EntryGetResult>>>() {
@Override
public IgniteInternalFuture<Map<KeyCacheObject, EntryGetResult>> apply(Boolean b, Exception e) {
if (e != null)
throw new GridClosureException(e);
return cache().getDhtAllAsync(keys.keySet(), args, readThrough, subjId, taskName, expiryPlc, skipVals, /*can remap*/
true, recovery);
}
});
}
if (fut.isDone()) {
if (fut.error() != null)
onDone(fut.error());
else
return new GridFinishedFuture<>(toEntryInfos(fut.result()));
}
return new GridEmbeddedFuture<>(new C2<Map<KeyCacheObject, EntryGetResult>, Exception, Collection<GridCacheEntryInfo>>() {
@Override
public Collection<GridCacheEntryInfo> apply(Map<KeyCacheObject, EntryGetResult> map, Exception e) {
if (e != null) {
onDone(e);
return Collections.emptyList();
} else
return toEntryInfos(map);
}
}, fut);
}
use of org.apache.ignite.internal.processors.cache.GridCacheEntryInfo in project ignite by apache.
the class GridDhtGetFuture method toEntryInfos.
/**
* @param map Map to convert.
* @return List of infos.
*/
private Collection<GridCacheEntryInfo> toEntryInfos(Map<KeyCacheObject, EntryGetResult> map) {
if (map.isEmpty())
return Collections.emptyList();
Collection<GridCacheEntryInfo> infos = new ArrayList<>(map.size());
for (Map.Entry<KeyCacheObject, EntryGetResult> entry : map.entrySet()) {
EntryGetResult val = entry.getValue();
assert val != null;
GridCacheEntryInfo info = new GridCacheEntryInfo();
info.cacheId(cctx.cacheId());
info.key(entry.getKey());
info.value(skipVals ? null : (CacheObject) val.value());
info.version(val.version());
info.expireTime(val.expireTime());
info.ttl(val.ttl());
infos.add(info);
}
return infos;
}
use of org.apache.ignite.internal.processors.cache.GridCacheEntryInfo in project ignite by apache.
the class GridPartitionedSingleGetFuture method map.
/**
* @param topVer Topology version.
*/
@SuppressWarnings("unchecked")
private void map(AffinityTopologyVersion topVer) {
ClusterNode node = mapKeyToNode(topVer);
if (node == null) {
assert isDone() : this;
return;
}
if (isDone())
return;
if (node.isLocal()) {
Map<KeyCacheObject, Boolean> map = Collections.singletonMap(key, false);
final GridDhtFuture<Collection<GridCacheEntryInfo>> fut = cctx.dht().getDhtAsync(node.id(), -1, map, readThrough, topVer, subjId, taskName == null ? 0 : taskName.hashCode(), expiryPlc, skipVals, recovery);
final Collection<Integer> invalidParts = fut.invalidPartitions();
if (!F.isEmpty(invalidParts)) {
AffinityTopologyVersion updTopVer = cctx.discovery().topologyVersionEx();
assert updTopVer.compareTo(topVer) > 0 : "Got invalid partitions for local node but topology " + "version did not change [topVer=" + topVer + ", updTopVer=" + updTopVer + ", invalidParts=" + invalidParts + ']';
// Remap recursively.
map(updTopVer);
} else {
fut.listen(new CI1<IgniteInternalFuture<Collection<GridCacheEntryInfo>>>() {
@Override
public void apply(IgniteInternalFuture<Collection<GridCacheEntryInfo>> fut) {
try {
Collection<GridCacheEntryInfo> infos = fut.get();
assert F.isEmpty(infos) || infos.size() == 1 : infos;
setResult(F.first(infos));
} catch (Exception e) {
U.error(log, "Failed to get values from dht cache [fut=" + fut + "]", e);
onDone(e);
}
}
});
}
} else {
synchronized (this) {
assert this.node == null;
this.topVer = topVer;
this.node = node;
}
if (!trackable) {
trackable = true;
cctx.mvcc().addFuture(this, futId);
}
GridCacheMessage req = new GridNearSingleGetRequest(cctx.cacheId(), futId.localId(), key, readThrough, topVer, subjId, taskName == null ? 0 : taskName.hashCode(), expiryPlc != null ? expiryPlc.forCreate() : -1L, expiryPlc != null ? expiryPlc.forAccess() : -1L, skipVals, /*add reader*/
false, needVer, cctx.deploymentEnabled(), recovery);
try {
cctx.io().send(node, req, cctx.ioPolicy());
} catch (IgniteCheckedException e) {
if (e instanceof ClusterTopologyCheckedException)
onNodeLeft(node.id());
else
onDone(e);
}
}
}
use of org.apache.ignite.internal.processors.cache.GridCacheEntryInfo in project ignite by apache.
the class GridDhtCacheAdapter method processNearGetRequest.
/**
* @param nodeId Node ID.
* @param req Get request.
*/
protected void processNearGetRequest(final UUID nodeId, final GridNearGetRequest req) {
assert ctx.affinityNode();
assert !req.reload() : req;
final CacheExpiryPolicy expiryPlc = CacheExpiryPolicy.fromRemote(req.createTtl(), req.accessTtl());
IgniteInternalFuture<Collection<GridCacheEntryInfo>> fut = getDhtAsync(nodeId, req.messageId(), req.keys(), req.readThrough(), req.topologyVersion(), req.subjectId(), req.taskNameHash(), expiryPlc, req.skipValues(), req.recovery());
fut.listen(new CI1<IgniteInternalFuture<Collection<GridCacheEntryInfo>>>() {
@Override
public void apply(IgniteInternalFuture<Collection<GridCacheEntryInfo>> f) {
GridNearGetResponse res = new GridNearGetResponse(ctx.cacheId(), req.futureId(), req.miniId(), req.version(), req.deployInfo() != null);
GridDhtFuture<Collection<GridCacheEntryInfo>> fut = (GridDhtFuture<Collection<GridCacheEntryInfo>>) f;
try {
Collection<GridCacheEntryInfo> entries = fut.get();
res.entries(entries);
} catch (NodeStoppingException ignored) {
return;
} catch (IgniteCheckedException e) {
U.error(log, "Failed processing get request: " + req, e);
res.error(e);
}
if (!F.isEmpty(fut.invalidPartitions()))
res.invalidPartitions(fut.invalidPartitions(), ctx.shared().exchange().readyAffinityVersion());
else
res.invalidPartitions(fut.invalidPartitions(), req.topologyVersion());
try {
ctx.io().send(nodeId, res, ctx.ioPolicy());
} catch (IgniteCheckedException e) {
U.error(log, "Failed to send get response to node (is node still alive?) [nodeId=" + nodeId + ",req=" + req + ", res=" + res + ']', e);
}
sendTtlUpdateRequest(expiryPlc);
}
});
}
Aggregations