use of org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey in project ignite by apache.
the class GridDhtColocatedLockFuture method map0.
/**
* @param keys Keys to map.
* @param remap Remap flag.
* @param topLocked Topology locked flag.
* @throws IgniteCheckedException If mapping failed.
*/
private synchronized void map0(Collection<KeyCacheObject> keys, boolean remap, boolean topLocked) throws IgniteCheckedException {
AffinityTopologyVersion topVer = this.topVer;
assert topVer != null;
assert topVer.topologyVersion() > 0;
if (CU.affinityNodes(cctx, topVer).isEmpty()) {
onDone(new ClusterTopologyServerNotFoundException("Failed to map keys for cache " + "(all partition nodes left the grid): " + cctx.name()));
return;
}
boolean clientNode = cctx.kernalContext().clientNode();
assert !remap || (clientNode && (tx == null || !tx.hasRemoteLocks()));
// First assume this node is primary for all keys passed in.
if (!clientNode && mapAsPrimary(keys, topVer))
return;
mappings = new ArrayDeque<>();
// Assign keys to primary nodes.
GridNearLockMapping map = null;
for (KeyCacheObject key : keys) {
GridNearLockMapping updated = map(key, map, topVer);
// If new mapping was created, add to collection.
if (updated != map) {
mappings.add(updated);
if (tx != null && updated.node().isLocal())
tx.colocatedLocallyMapped(true);
}
map = updated;
}
if (isDone()) {
if (log.isDebugEnabled())
log.debug("Abandoning (re)map because future is done: " + this);
return;
}
if (log.isDebugEnabled())
log.debug("Starting (re)map for mappings [mappings=" + mappings + ", fut=" + this + ']');
boolean hasRmtNodes = false;
boolean first = true;
// Create mini futures.
for (Iterator<GridNearLockMapping> iter = mappings.iterator(); iter.hasNext(); ) {
GridNearLockMapping mapping = iter.next();
ClusterNode node = mapping.node();
Collection<KeyCacheObject> mappedKeys = mapping.mappedKeys();
boolean loc = node.equals(cctx.localNode());
assert !mappedKeys.isEmpty();
GridNearLockRequest req = null;
Collection<KeyCacheObject> distributedKeys = new ArrayList<>(mappedKeys.size());
for (KeyCacheObject key : mappedKeys) {
IgniteTxKey txKey = cctx.txKey(key);
GridDistributedCacheEntry entry = null;
if (tx != null) {
IgniteTxEntry txEntry = tx.entry(txKey);
if (txEntry != null) {
entry = (GridDistributedCacheEntry) txEntry.cached();
if (entry != null && loc == entry.detached()) {
entry = cctx.colocated().entryExx(key, topVer, true);
txEntry.cached(entry);
}
}
}
boolean explicit;
while (true) {
try {
if (entry == null)
entry = cctx.colocated().entryExx(key, topVer, true);
if (!cctx.isAll(entry, filter)) {
if (log.isDebugEnabled())
log.debug("Entry being locked did not pass filter (will not lock): " + entry);
onComplete(false, false);
return;
}
assert loc ^ entry.detached() : "Invalid entry [loc=" + loc + ", entry=" + entry + ']';
GridCacheMvccCandidate cand = addEntry(entry);
// Will either return value from dht cache or null if this is a miss.
IgniteBiTuple<GridCacheVersion, CacheObject> val = entry.detached() ? null : ((GridDhtCacheEntry) entry).versionedValue(topVer);
GridCacheVersion dhtVer = null;
if (val != null) {
dhtVer = val.get1();
valMap.put(key, val);
}
if (cand != null && !cand.reentry()) {
if (req == null) {
boolean clientFirst = false;
if (first) {
clientFirst = clientNode && !topLocked && (tx == null || !tx.hasRemoteLocks());
first = false;
}
assert !implicitTx() && !implicitSingleTx() : tx;
req = new GridNearLockRequest(cctx.cacheId(), topVer, cctx.nodeId(), threadId, futId, lockVer, inTx(), read, retval, isolation(), isInvalidate(), timeout, mappedKeys.size(), inTx() ? tx.size() : mappedKeys.size(), inTx() && tx.syncMode() == FULL_SYNC, inTx() ? tx.subjectId() : null, inTx() ? tx.taskNameHash() : 0, read ? createTtl : -1L, read ? accessTtl : -1L, skipStore, keepBinary, clientFirst, cctx.deploymentEnabled());
mapping.request(req);
}
distributedKeys.add(key);
if (tx != null)
tx.addKeyMapping(txKey, mapping.node());
req.addKeyBytes(key, retval, // Include DHT version to match remote DHT entry.
dhtVer, cctx);
}
explicit = inTx() && cand == null;
if (explicit)
tx.addKeyMapping(txKey, mapping.node());
break;
} catch (GridCacheEntryRemovedException ignored) {
if (log.isDebugEnabled())
log.debug("Got removed entry in lockAsync(..) method (will retry): " + entry);
entry = null;
}
}
// Mark mapping explicit lock flag.
if (explicit) {
boolean marked = tx != null && tx.markExplicit(node.id());
assert tx == null || marked;
}
}
if (!distributedKeys.isEmpty()) {
mapping.distributedKeys(distributedKeys);
hasRmtNodes |= !mapping.node().isLocal();
} else {
assert mapping.request() == null;
iter.remove();
}
}
if (hasRmtNodes) {
trackable = true;
if (!remap && !cctx.mvcc().addFuture(this))
throw new IllegalStateException("Duplicate future ID: " + this);
} else
trackable = false;
proceedMapping();
}
use of org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey in project ignite by apache.
the class GridNearOptimisticTxPrepareFuture method requestedKeys.
/**
* @return Keys for which {@code MiniFuture} isn't completed.
*/
@SuppressWarnings("ForLoopReplaceableByForEach")
public Set<IgniteTxKey> requestedKeys() {
synchronized (this) {
int size = futuresCountNoLock();
for (int i = 0; i < size; i++) {
IgniteInternalFuture<GridNearTxPrepareResponse> fut = future(i);
if (isMini(fut) && !fut.isDone()) {
MiniFuture miniFut = (MiniFuture) fut;
Collection<IgniteTxEntry> entries = miniFut.mapping().entries();
Set<IgniteTxKey> keys = U.newHashSet(entries.size());
for (IgniteTxEntry entry : entries) keys.add(entry.txKey());
return keys;
}
}
}
return null;
}
use of org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey in project ignite by apache.
the class GridNearOptimisticTxPrepareFuture method onTimeout.
/**
*
*/
@SuppressWarnings("ForLoopReplaceableByForEach")
private void onTimeout() {
if (cctx.tm().deadlockDetectionEnabled()) {
Set<IgniteTxKey> keys = null;
if (keyLockFut != null)
keys = new HashSet<>(keyLockFut.lockKeys);
else {
synchronized (this) {
int size = futuresCountNoLock();
for (int i = 0; i < size; i++) {
IgniteInternalFuture<GridNearTxPrepareResponse> fut = future(i);
if (isMini(fut) && !fut.isDone()) {
MiniFuture miniFut = (MiniFuture) fut;
Collection<IgniteTxEntry> entries = miniFut.mapping().entries();
keys = U.newHashSet(entries.size());
for (IgniteTxEntry entry : entries) keys.add(entry.txKey());
break;
}
}
}
}
add(new GridEmbeddedFuture<>(new IgniteBiClosure<TxDeadlock, Exception, GridNearTxPrepareResponse>() {
@Override
public GridNearTxPrepareResponse apply(TxDeadlock deadlock, Exception e) {
if (e != null)
U.warn(log, "Failed to detect deadlock.", e);
else {
e = new IgniteTxTimeoutCheckedException("Failed to acquire lock within provided timeout for " + "transaction [timeout=" + tx.timeout() + ", tx=" + tx + ']', deadlock != null ? new TransactionDeadlockException(deadlock.toString(cctx)) : null);
}
onDone(null, e);
return null;
}
}, cctx.tm().detectDeadlock(tx, keys)));
} else {
ERR_UPD.compareAndSet(this, null, new IgniteTxTimeoutCheckedException("Failed to acquire lock " + "within provided timeout for transaction [timeout=" + tx.timeout() + ", tx=" + tx + ']'));
onComplete();
}
}
use of org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey in project ignite by apache.
the class GridNearTxLocal method checkMissed.
/**
* @param cacheCtx Cache context.
* @param topVer Topology version.
* @param map Return map.
* @param missedMap Missed keys.
* @param deserializeBinary Deserialize binary flag.
* @param skipVals Skip values flag.
* @param keepCacheObjects Keep cache objects flag.
* @param skipStore Skip store flag.
* @param expiryPlc Expiry policy.
* @return Loaded key-value pairs.
*/
private <K, V> IgniteInternalFuture<Map<K, V>> checkMissed(final GridCacheContext cacheCtx, final AffinityTopologyVersion topVer, final Map<K, V> map, final Map<KeyCacheObject, GridCacheVersion> missedMap, final boolean deserializeBinary, final boolean skipVals, final boolean keepCacheObjects, final boolean skipStore, final boolean recovery, final boolean needVer, final ExpiryPolicy expiryPlc) {
if (log.isDebugEnabled())
log.debug("Loading missed values for missed map: " + missedMap);
final boolean needReadVer = (serializable() && optimistic()) || needVer;
return new GridEmbeddedFuture<>(new C2<Void, Exception, Map<K, V>>() {
@Override
public Map<K, V> apply(Void v, Exception e) {
if (e != null) {
setRollbackOnly();
throw new GridClosureException(e);
}
return map;
}
}, loadMissing(cacheCtx, topVer, !skipStore, false, missedMap.keySet(), skipVals, needReadVer, !deserializeBinary, recovery, expiryPlc, new GridInClosure3<KeyCacheObject, Object, GridCacheVersion>() {
@Override
public void apply(KeyCacheObject key, Object val, GridCacheVersion loadVer) {
if (isRollbackOnly()) {
if (log.isDebugEnabled())
log.debug("Ignoring loaded value for read because transaction was rolled back: " + GridNearTxLocal.this);
return;
}
CacheObject cacheVal = cacheCtx.toCacheObject(val);
CacheObject visibleVal = cacheVal;
IgniteTxKey txKey = cacheCtx.txKey(key);
IgniteTxEntry txEntry = entry(txKey);
if (txEntry != null) {
if (!readCommitted())
txEntry.readValue(cacheVal);
if (!F.isEmpty(txEntry.entryProcessors()))
visibleVal = txEntry.applyEntryProcessors(visibleVal);
}
assert txEntry != null || readCommitted() || skipVals;
GridCacheEntryEx e = txEntry == null ? entryEx(cacheCtx, txKey, topVer) : txEntry.cached();
if (readCommitted() || skipVals) {
cacheCtx.evicts().touch(e, topologyVersion());
if (visibleVal != null) {
cacheCtx.addResult(map, key, visibleVal, skipVals, keepCacheObjects, deserializeBinary, false, needVer ? loadVer : null, 0, 0);
}
} else {
assert txEntry != null;
txEntry.setAndMarkValid(cacheVal);
if (needReadVer) {
assert loadVer != null;
txEntry.entryReadVersion(loadVer);
}
if (visibleVal != null) {
cacheCtx.addResult(map, key, visibleVal, skipVals, keepCacheObjects, deserializeBinary, false, needVer ? loadVer : null, 0, 0);
}
}
}
}));
}
use of org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey in project ignite by apache.
the class GridNearTxLocal method enlistRead.
/**
* @param cacheCtx Cache context.
* @param keys Key to enlist.
* @param expiryPlc Explicitly specified expiry policy for entry.
* @param map Return map.
* @param missed Map of missed keys.
* @param keysCnt Keys count (to avoid call to {@code Collection.size()}).
* @param deserializeBinary Deserialize binary flag.
* @param skipVals Skip values flag.
* @param keepCacheObjects Keep cache objects flag.
* @param skipStore Skip store flag.
* @throws IgniteCheckedException If failed.
* @return Enlisted keys.
*/
@SuppressWarnings({ "RedundantTypeArguments" })
private <K, V> Collection<KeyCacheObject> enlistRead(final GridCacheContext cacheCtx, @Nullable AffinityTopologyVersion entryTopVer, Collection<KeyCacheObject> keys, @Nullable ExpiryPolicy expiryPlc, Map<K, V> map, Map<KeyCacheObject, GridCacheVersion> missed, int keysCnt, boolean deserializeBinary, boolean skipVals, boolean keepCacheObjects, boolean skipStore, boolean recovery, final boolean needVer) throws IgniteCheckedException {
assert !F.isEmpty(keys);
assert keysCnt == keys.size();
cacheCtx.checkSecurity(SecurityPermission.CACHE_READ);
boolean single = keysCnt == 1;
Collection<KeyCacheObject> lockKeys = null;
AffinityTopologyVersion topVer = entryTopVer != null ? entryTopVer : topologyVersion();
boolean needReadVer = (serializable() && optimistic()) || needVer;
// outside of this loop.
for (KeyCacheObject key : keys) {
if ((pessimistic() || needReadVer) && !readCommitted() && !skipVals)
addActiveCache(cacheCtx, recovery);
IgniteTxKey txKey = cacheCtx.txKey(key);
// Check write map (always check writes first).
IgniteTxEntry txEntry = entry(txKey);
// Either non-read-committed or there was a previous write.
if (txEntry != null) {
CacheObject val = txEntry.value();
if (txEntry.hasValue()) {
if (!F.isEmpty(txEntry.entryProcessors()))
val = txEntry.applyEntryProcessors(val);
if (val != null) {
GridCacheVersion ver = null;
if (needVer) {
if (txEntry.op() != READ)
ver = IgniteTxEntry.GET_ENTRY_INVALID_VER_UPDATED;
else {
ver = txEntry.entryReadVersion();
if (ver == null && pessimistic()) {
while (true) {
try {
GridCacheEntryEx cached = txEntry.cached();
ver = cached.isNear() ? ((GridNearCacheEntry) cached).dhtVersion() : cached.version();
break;
} catch (GridCacheEntryRemovedException ignored) {
txEntry.cached(entryEx(cacheCtx, txEntry.txKey(), topVer));
}
}
}
if (ver == null) {
assert optimistic() && repeatableRead() : this;
ver = IgniteTxEntry.GET_ENTRY_INVALID_VER_AFTER_GET;
}
}
assert ver != null;
}
cacheCtx.addResult(map, key, val, skipVals, keepCacheObjects, deserializeBinary, false, ver, 0, 0);
}
} else {
assert txEntry.op() == TRANSFORM;
while (true) {
try {
GridCacheVersion readVer = null;
EntryGetResult getRes = null;
Object transformClo = (txEntry.op() == TRANSFORM && cctx.gridEvents().isRecordable(EVT_CACHE_OBJECT_READ)) ? F.first(txEntry.entryProcessors()) : null;
if (needVer) {
getRes = txEntry.cached().innerGetVersioned(null, this, /*update-metrics*/
true, /*event*/
!skipVals, CU.subjectId(this, cctx), transformClo, resolveTaskName(), null, txEntry.keepBinary(), null);
if (getRes != null) {
val = getRes.value();
readVer = getRes.version();
}
} else {
val = txEntry.cached().innerGet(null, this, /*read-through*/
false, /*metrics*/
true, /*event*/
!skipVals, CU.subjectId(this, cctx), transformClo, resolveTaskName(), null, txEntry.keepBinary());
}
if (val != null) {
if (!readCommitted() && !skipVals)
txEntry.readValue(val);
if (!F.isEmpty(txEntry.entryProcessors()))
val = txEntry.applyEntryProcessors(val);
cacheCtx.addResult(map, key, val, skipVals, keepCacheObjects, deserializeBinary, false, getRes, readVer, 0, 0, needVer);
} else
missed.put(key, txEntry.cached().version());
break;
} catch (GridCacheEntryRemovedException ignored) {
txEntry.cached(entryEx(cacheCtx, txEntry.txKey(), topVer));
}
}
}
} else // First time access within transaction.
{
if (lockKeys == null && !skipVals)
lockKeys = single ? Collections.singleton(key) : new ArrayList<KeyCacheObject>(keysCnt);
if (!single && !skipVals)
lockKeys.add(key);
while (true) {
GridCacheEntryEx entry = entryEx(cacheCtx, txKey, topVer);
try {
GridCacheVersion ver = entry.version();
CacheObject val = null;
GridCacheVersion readVer = null;
EntryGetResult getRes = null;
if (!pessimistic() || readCommitted() && !skipVals) {
IgniteCacheExpiryPolicy accessPlc = optimistic() ? accessPolicy(cacheCtx, txKey, expiryPlc) : null;
if (needReadVer) {
getRes = primaryLocal(entry) ? entry.innerGetVersioned(null, this, /*metrics*/
true, /*event*/
true, CU.subjectId(this, cctx), null, resolveTaskName(), accessPlc, !deserializeBinary, null) : null;
if (getRes != null) {
val = getRes.value();
readVer = getRes.version();
}
} else {
val = entry.innerGet(null, this, /*read-through*/
false, /*metrics*/
true, /*event*/
!skipVals, CU.subjectId(this, cctx), null, resolveTaskName(), accessPlc, !deserializeBinary);
}
if (val != null) {
cacheCtx.addResult(map, key, val, skipVals, keepCacheObjects, deserializeBinary, false, getRes, readVer, 0, 0, needVer);
} else
missed.put(key, ver);
} else
// We must wait for the lock in pessimistic mode.
missed.put(key, ver);
if (!readCommitted() && !skipVals) {
txEntry = addEntry(READ, val, null, null, entry, expiryPlc, null, true, -1L, -1L, null, skipStore, !deserializeBinary);
// for non-pessimistic if value is not null.
if (val != null && !pessimistic()) {
txEntry.markValid();
if (needReadVer) {
assert readVer != null;
txEntry.entryReadVersion(readVer);
}
}
}
// While.
break;
} catch (GridCacheEntryRemovedException ignored) {
if (log.isDebugEnabled())
log.debug("Got removed entry in transaction getAllAsync(..) (will retry): " + key);
} finally {
if (entry != null && readCommitted()) {
if (cacheCtx.isNear()) {
if (cacheCtx.affinity().partitionBelongs(cacheCtx.localNode(), entry.partition(), topVer)) {
if (entry.markObsolete(xidVer))
cacheCtx.cache().removeEntry(entry);
}
} else
entry.context().evicts().touch(entry, topVer);
}
}
}
}
}
return lockKeys != null ? lockKeys : Collections.<KeyCacheObject>emptyList();
}
Aggregations