use of org.apache.ignite.internal.processors.cache.GridCacheMvccCandidate in project ignite by apache.
the class GridDhtLockFuture method map.
/**
* @param entries Entries.
*/
private void map(Iterable<GridDhtCacheEntry> entries) {
synchronized (this) {
if (mapped)
return;
mapped = true;
}
try {
if (log.isDebugEnabled())
log.debug("Mapping entry for DHT lock future: " + this);
// Assign keys to primary nodes.
for (GridDhtCacheEntry entry : entries) {
try {
while (true) {
try {
cctx.dhtMap(nearNodeId, topVer, entry, tx == null ? lockVer : null, log, dhtMap, null);
GridCacheMvccCandidate cand = entry.candidate(lockVer);
// Possible in case of lock cancellation.
if (cand == null) {
onFailed(false);
// Will mark initialized in finally block.
return;
}
break;
} catch (GridCacheEntryRemovedException ignore) {
if (log.isDebugEnabled())
log.debug("Got removed entry when mapping DHT lock future (will retry): " + entry);
entry = cctx.dht().entryExx(entry.key(), topVer);
}
}
} catch (GridDhtInvalidPartitionException e) {
assert false : "DHT lock should never get invalid partition [err=" + e + ", fut=" + this + ']';
}
}
if (checkDone())
return;
if (log.isDebugEnabled())
log.debug("Mapped DHT lock future [dhtMap=" + F.nodeIds(dhtMap.keySet()) + ", dhtLockFut=" + this + ']');
long timeout = inTx() ? tx.remainingTime() : this.timeout;
synchronized (this) {
// Prevents entry removal on concurrent rollback.
if (checkDone())
return;
// Create mini futures.
for (Map.Entry<ClusterNode, List<GridDhtCacheEntry>> mapped : dhtMap.entrySet()) {
ClusterNode n = mapped.getKey();
List<GridDhtCacheEntry> dhtMapping = mapped.getValue();
int cnt = F.size(dhtMapping);
if (cnt > 0) {
assert !n.id().equals(cctx.localNodeId());
if (inTx() && tx.remainingTime() == -1)
return;
MiniFuture fut = new MiniFuture(n, dhtMapping);
GridDhtLockRequest req = new GridDhtLockRequest(cctx.cacheId(), nearNodeId, inTx() ? tx.nearXidVersion() : null, threadId, futId, fut.futureId(), lockVer, topVer, inTx(), read, isolation(), isInvalidate(), timeout, cnt, 0, inTx() ? tx.size() : cnt, inTx() ? tx.taskNameHash() : 0, read ? accessTtl : -1L, skipStore, cctx.store().configured(), keepBinary, cctx.deploymentEnabled(), inTx() ? tx.label() : null);
try {
for (ListIterator<GridDhtCacheEntry> it = dhtMapping.listIterator(); it.hasNext(); ) {
GridDhtCacheEntry e = it.next();
boolean needVal = false;
try {
// Must unswap entry so that isNewLocked returns correct value.
e.unswap(false);
needVal = e.isNewLocked();
if (needVal) {
List<ClusterNode> owners = cctx.topology().owners(e.partition(), tx != null ? tx.topologyVersion() : cctx.affinity().affinityTopologyVersion());
// Do not preload if local node is partition owner.
if (owners.contains(cctx.localNode()))
needVal = false;
}
// Skip entry if it is not new and is not present in updated mapping.
if (tx != null && !needVal)
continue;
boolean invalidateRdr = e.readerId(n.id()) != null;
req.addDhtKey(e.key(), invalidateRdr, cctx);
if (needVal) {
// Mark last added key as needed to be preloaded.
req.markLastKeyForPreload();
if (tx != null) {
IgniteTxEntry txEntry = tx.entry(e.txKey());
// NOOP entries will be sent to backups on prepare step.
if (txEntry.op() == GridCacheOperation.READ)
txEntry.op(GridCacheOperation.NOOP);
}
}
GridCacheMvccCandidate added = e.candidate(lockVer);
assert added != null;
assert added.dhtLocal();
if (added.ownerVersion() != null)
req.owned(e.key(), added.ownerVersion());
} catch (GridCacheEntryRemovedException ex) {
assert false : "Entry cannot become obsolete when DHT local candidate is added " + "[e=" + e + ", ex=" + ex + ']';
}
}
if (!F.isEmpty(req.keys())) {
if (tx != null)
tx.addLockTransactionNode(n);
// Append new future.
add(fut);
cctx.io().send(n, req, cctx.ioPolicy());
if (msgLog.isDebugEnabled()) {
msgLog.debug("DHT lock fut, sent request [txId=" + nearLockVer + ", dhtTxId=" + lockVer + ", inTx=" + inTx() + ", nodeId=" + n.id() + ']');
}
}
} catch (IgniteCheckedException e) {
// Fail the whole thing.
if (e instanceof ClusterTopologyCheckedException)
fut.onResult();
else {
if (msgLog.isDebugEnabled()) {
msgLog.debug("DHT lock fut, failed to send request [txId=" + nearLockVer + ", dhtTxId=" + lockVer + ", inTx=" + inTx() + ", node=" + n.id() + ", err=" + e + ']');
}
fut.onResult(e);
}
}
}
}
}
} finally {
markInitialized();
}
}
use of org.apache.ignite.internal.processors.cache.GridCacheMvccCandidate in project ignite by apache.
the class GridDistributedCacheEntry method removeLock.
/**
* {@inheritDoc}
*/
@Override
public boolean removeLock(GridCacheVersion ver) throws GridCacheEntryRemovedException {
CacheLockCandidates prev = null;
CacheLockCandidates owner = null;
GridCacheMvccCandidate doomed;
GridCacheVersion deferredDelVer;
CacheObject val;
cctx.tm().detectPossibleCollidingKeys(this);
lockEntry();
try {
GridCacheMvcc mvcc = mvccExtras();
doomed = mvcc == null ? null : mvcc.candidate(ver);
if (doomed == null)
addRemoved(ver);
GridCacheVersion obsoleteVer = obsoleteVersionExtras();
if (obsoleteVer != null && !obsoleteVer.equals(ver))
checkObsolete();
if (doomed != null) {
prev = mvcc.allOwners();
boolean emptyBefore = mvcc.isEmpty();
mvcc.remove(doomed.version());
boolean emptyAfter = mvcc.isEmpty();
if (!doomed.local())
refreshRemotes();
checkCallbacks(emptyBefore, emptyAfter);
if (emptyAfter)
mvccExtras(null);
else
owner = mvcc.allOwners();
}
val = this.val;
deferredDelVer = this.ver;
} finally {
unlockEntry();
}
if (val == null) {
boolean deferred = cctx.deferredDelete() && !detached() && !isInternal();
if (deferred) {
if (deferredDelVer != null)
cctx.onDeferredDelete(this, deferredDelVer);
}
}
if (log.isDebugEnabled())
log.debug("Removed lock candidate from entry [doomed=" + doomed + ", owner=" + owner + ", prev=" + prev + ", entry=" + this + ']');
if (doomed != null && doomed.nearLocal())
cctx.mvcc().removeExplicitLock(doomed);
if (doomed != null)
checkThreadChain(doomed);
// This call must be outside of synchronization.
checkOwnerChanged(prev, owner, val);
return doomed != null;
}
use of org.apache.ignite.internal.processors.cache.GridCacheMvccCandidate in project ignite by apache.
the class GridDistributedCacheEntry method addLocal.
/**
* Add local candidate.
*
* @param threadId Owning thread ID.
* @param ver Lock version.
* @param topVer Topology version.
* @param timeout Timeout to acquire lock.
* @param reenter Reentry flag.
* @param tx Transaction flag.
* @param implicitSingle Implicit flag.
* @param read Read lock flag.
* @return New candidate.
* @throws GridCacheEntryRemovedException If entry has been removed.
*/
@Nullable
public GridCacheMvccCandidate addLocal(long threadId, GridCacheVersion ver, AffinityTopologyVersion topVer, long timeout, boolean reenter, boolean tx, boolean implicitSingle, boolean read) throws GridCacheEntryRemovedException {
GridCacheMvccCandidate cand;
CacheLockCandidates prev;
CacheLockCandidates owner;
CacheObject val;
lockEntry();
try {
checkObsolete();
GridCacheMvcc mvcc = mvccExtras();
if (mvcc == null) {
mvcc = new GridCacheMvcc(cctx);
mvccExtras(mvcc);
}
prev = mvcc.allOwners();
boolean emptyBefore = mvcc.isEmpty();
cand = mvcc.addLocal(this, threadId, ver, timeout, reenter, tx, implicitSingle, read);
if (cand != null)
cand.topologyVersion(topVer);
owner = mvcc.allOwners();
boolean emptyAfter = mvcc.isEmpty();
checkCallbacks(emptyBefore, emptyAfter);
val = this.val;
if (emptyAfter)
mvccExtras(null);
} finally {
unlockEntry();
}
// Don't link reentries.
if (cand != null && !cand.reentry())
// Link with other candidates in the same thread.
cctx.mvcc().addNext(cctx, cand);
checkOwnerChanged(prev, owner, val);
return cand;
}
use of org.apache.ignite.internal.processors.cache.GridCacheMvccCandidate in project ignite by apache.
the class GridDistributedCacheEntry method removeLock.
/**
* Unlocks local lock.
*
* @return Removed candidate, or <tt>null</tt> if thread still holds the lock.
*/
@Nullable
public GridCacheMvccCandidate removeLock() {
GridCacheMvccCandidate rmvd = null;
CacheLockCandidates prev = null;
CacheLockCandidates owner = null;
CacheObject val;
cctx.tm().detectPossibleCollidingKeys(this);
lockEntry();
try {
GridCacheMvcc mvcc = mvccExtras();
if (mvcc != null) {
prev = mvcc.allOwners();
boolean emptyBefore = mvcc.isEmpty();
rmvd = mvcc.releaseLocal();
boolean emptyAfter = mvcc.isEmpty();
checkCallbacks(emptyBefore, emptyAfter);
if (emptyAfter)
mvccExtras(null);
else
owner = mvcc.allOwners();
}
val = this.val;
} finally {
unlockEntry();
}
if (log.isDebugEnabled()) {
log.debug("Released local candidate from entry [owner=" + owner + ", prev=" + prev + ", rmvd=" + rmvd + ", entry=" + this + ']');
}
if (prev != null) {
for (int i = 0; i < prev.size(); i++) {
GridCacheMvccCandidate cand = prev.candidate(i);
checkThreadChain(cand);
}
}
// This call must be outside of synchronization.
checkOwnerChanged(prev, owner, val);
return rmvd;
}
use of org.apache.ignite.internal.processors.cache.GridCacheMvccCandidate in project ignite by apache.
the class GridDhtCacheEntry method addReader.
/**
* @param nodeId Reader to add.
* @param msgId Message ID.
* @param topVer Topology version.
* @return Future for all relevant transactions that were active at the time of adding reader,
* or {@code null} if reader was added
* @throws GridCacheEntryRemovedException If entry was removed.
*/
@SuppressWarnings("unchecked")
@Nullable
public IgniteInternalFuture<Boolean> addReader(UUID nodeId, long msgId, AffinityTopologyVersion topVer) throws GridCacheEntryRemovedException {
// Don't add local node as reader.
if (cctx.nodeId().equals(nodeId))
return null;
ClusterNode node = cctx.discovery().node(nodeId);
if (node == null) {
if (log.isDebugEnabled())
log.debug("Ignoring near reader because node left the grid: " + nodeId);
return null;
}
// If remote node is (primary?) or back up, don't add it as a reader.
if (cctx.affinity().partitionBelongs(node, partition(), topVer)) {
if (log.isDebugEnabled())
log.debug("Ignoring near reader because remote node is affinity node [locNodeId=" + cctx.localNodeId() + ", rmtNodeId=" + nodeId + ", key=" + key + ']');
return null;
}
boolean ret = false;
GridCacheMultiTxFuture txFut = null;
Collection<GridCacheMvccCandidate> cands = null;
ReaderId reader;
lockEntry();
try {
checkObsolete();
reader = readerId(nodeId);
if (reader == null) {
reader = new ReaderId(nodeId, msgId);
ReaderId[] rdrs = Arrays.copyOf(this.rdrs, this.rdrs.length + 1);
rdrs[rdrs.length - 1] = reader;
// Seal.
this.rdrs = rdrs;
// No transactions in ATOMIC cache.
if (!cctx.atomic()) {
txFut = reader.getOrCreateTxFuture(cctx);
cands = localCandidates();
ret = true;
}
} else {
txFut = reader.txFuture();
long id = reader.messageId();
if (id < msgId)
reader.messageId(msgId);
}
} finally {
unlockEntry();
}
if (ret) {
assert txFut != null;
if (!F.isEmpty(cands)) {
for (GridCacheMvccCandidate c : cands) {
IgniteInternalTx tx = cctx.tm().tx(c.version());
if (tx != null && tx.local())
txFut.addTx(tx);
}
}
txFut.init();
if (!txFut.isDone()) {
final ReaderId reader0 = reader;
txFut.listen(new CI1<IgniteInternalFuture<?>>() {
@Override
public void apply(IgniteInternalFuture<?> f) {
cctx.kernalContext().closure().runLocalSafe(new GridPlainRunnable() {
@Override
public void run() {
lockEntry();
try {
// Release memory.
reader0.resetTxFuture();
} finally {
unlockEntry();
}
}
});
}
});
} else {
lockEntry();
try {
// Release memory.
reader.resetTxFuture();
} finally {
unlockEntry();
}
txFut = null;
}
}
return txFut;
}
Aggregations