use of org.apache.ignite.internal.processors.cache.version.GridCacheVersion in project ignite by apache.
the class GridCacheMvcc method readyNearLocal.
/**
* Marks near-local candidate as ready and makes locks reassignment. Following reorderings are performed when
* candidate is marked ready:
* <ul>
* <li/> All candidates preceding ready one are moved right after it.
* <li/> Near local candidate is assigned a mapped dht version. All remote non-pending candidates with
* version less then mapped dht version are marked as owned.
* </ul>
*
* @param ver Version to mark as ready.
* @param mappedVer Mapped dht version.
* @param committedVers Committed versions.
* @param rolledBackVers Rolled back versions.
* @param pending Pending dht versions that are not owned and which version is less then mapped.
* @return Lock owner after reassignment.
*/
@Nullable
public CacheLockCandidates readyNearLocal(GridCacheVersion ver, GridCacheVersion mappedVer, Collection<GridCacheVersion> committedVers, Collection<GridCacheVersion> rolledBackVers, Collection<GridCacheVersion> pending) {
GridCacheMvccCandidate cand = candidate(locs, ver);
if (cand != null) {
assert cand.nearLocal() : "Near local candidate is not marked as near local: " + cand;
cand.setReady();
boolean setMapped = cand.otherVersion(mappedVer);
assert setMapped : "Failed to set mapped dht version for near local candidate [mappedVer=" + mappedVer + ", cand=" + cand + ']';
// For near locals we move all not owned candidates after this one.
List<GridCacheMvccCandidate> mvAfter = null;
for (ListIterator<GridCacheMvccCandidate> it = locs.listIterator(); it.hasNext(); ) {
GridCacheMvccCandidate c = it.next();
assert c.nearLocal() : "Near local candidate is not marked as near local: " + c;
if (c == cand) {
if (mvAfter != null)
for (GridCacheMvccCandidate mv : mvAfter) it.add(mv);
break;
} else {
if (c.owner())
continue;
assert !c.ready() || (c.read() && cand.read()) : "Cannot have more then one ready near-local candidate [c=" + c + ", cand=" + cand + ", mvcc=" + this + ']';
it.remove();
if (mvAfter == null)
mvAfter = new LinkedList<>();
mvAfter.add(c);
}
}
// Mark all remote candidates with less version as owner unless it is pending.
if (rmts != null) {
for (GridCacheMvccCandidate rmt : rmts) {
GridCacheVersion rmtVer = rmt.version();
if (rmtVer.isLess(mappedVer)) {
if (!pending.contains(rmtVer) && !mappedVer.equals(rmt.ownerVersion()))
rmt.setOwner();
} else {
// Remote version is greater, so need to check if it was committed or rolled back.
if (committedVers.contains(rmtVer) || rolledBackVers.contains(rmtVer))
rmt.setOwner();
}
}
}
reassign();
}
return allOwners();
}
use of org.apache.ignite.internal.processors.cache.version.GridCacheVersion in project ignite by apache.
the class GridDhtTransactionalCacheAdapter method lockAllAsync.
/**
* @param cacheCtx Cache context.
* @param nearNode Near node.
* @param req Request.
* @param filter0 Filter.
* @return Future.
*/
public IgniteInternalFuture<GridNearLockResponse> lockAllAsync(final GridCacheContext<?, ?> cacheCtx, final ClusterNode nearNode, final GridNearLockRequest req, @Nullable final CacheEntryPredicate[] filter0) {
final List<KeyCacheObject> keys = req.keys();
CacheEntryPredicate[] filter = filter0;
// Set message into thread context.
GridDhtTxLocal tx = null;
try {
int cnt = keys.size();
if (req.inTx()) {
GridCacheVersion dhtVer = ctx.tm().mappedVersion(req.version());
if (dhtVer != null)
tx = ctx.tm().tx(dhtVer);
}
final List<GridCacheEntryEx> entries = new ArrayList<>(cnt);
// Unmarshal filter first.
if (filter == null)
filter = req.filter();
GridDhtLockFuture fut = null;
if (!req.inTx()) {
GridDhtPartitionTopology top = null;
if (req.firstClientRequest()) {
assert CU.clientNode(nearNode);
top = topology();
topology().readLock();
}
try {
if (top != null && needRemap(req.topologyVersion(), top.topologyVersion())) {
if (log.isDebugEnabled()) {
log.debug("Client topology version mismatch, need remap lock request [" + "reqTopVer=" + req.topologyVersion() + ", locTopVer=" + top.topologyVersion() + ", req=" + req + ']');
}
GridNearLockResponse res = sendClientLockRemapResponse(nearNode, req, top.topologyVersion());
return new GridFinishedFuture<>(res);
}
fut = new GridDhtLockFuture(ctx, nearNode.id(), req.version(), req.topologyVersion(), cnt, req.txRead(), req.needReturnValue(), req.timeout(), tx, req.threadId(), req.createTtl(), req.accessTtl(), filter, req.skipStore(), req.keepBinary());
// Add before mapping.
if (!ctx.mvcc().addFuture(fut))
throw new IllegalStateException("Duplicate future ID: " + fut);
} finally {
if (top != null)
top.readUnlock();
}
}
boolean timedout = false;
for (KeyCacheObject key : keys) {
if (timedout)
break;
while (true) {
// Specify topology version to make sure containment is checked
// based on the requested version, not the latest.
GridDhtCacheEntry entry = entryExx(key, req.topologyVersion());
try {
if (fut != null) {
// This method will add local candidate.
// Entry cannot become obsolete after this method succeeded.
fut.addEntry(key == null ? null : entry);
if (fut.isDone()) {
timedout = true;
break;
}
}
entries.add(entry);
break;
} catch (GridCacheEntryRemovedException ignore) {
if (log.isDebugEnabled())
log.debug("Got removed entry when adding lock (will retry): " + entry);
} catch (GridDistributedLockCancelledException e) {
if (log.isDebugEnabled())
log.debug("Got lock request for cancelled lock (will ignore): " + entry);
fut.onError(e);
return new GridDhtFinishedFuture<>(e);
}
}
}
// Handle implicit locks for pessimistic transactions.
if (req.inTx()) {
if (tx == null) {
GridDhtPartitionTopology top = null;
if (req.firstClientRequest()) {
assert CU.clientNode(nearNode);
top = topology();
topology().readLock();
}
try {
if (top != null && needRemap(req.topologyVersion(), top.topologyVersion())) {
if (log.isDebugEnabled()) {
log.debug("Client topology version mismatch, need remap lock request [" + "reqTopVer=" + req.topologyVersion() + ", locTopVer=" + top.topologyVersion() + ", req=" + req + ']');
}
GridNearLockResponse res = sendClientLockRemapResponse(nearNode, req, top.topologyVersion());
return new GridFinishedFuture<>(res);
}
tx = new GridDhtTxLocal(ctx.shared(), req.topologyVersion(), nearNode.id(), req.version(), req.futureId(), req.miniId(), req.threadId(), /*implicitTx*/
false, /*implicitSingleTx*/
false, ctx.systemTx(), false, ctx.ioPolicy(), PESSIMISTIC, req.isolation(), req.timeout(), req.isInvalidate(), !req.skipStore(), false, req.txSize(), null, req.subjectId(), req.taskNameHash());
if (req.syncCommit())
tx.syncMode(FULL_SYNC);
tx = ctx.tm().onCreated(null, tx);
if (tx == null || !tx.init()) {
String msg = "Failed to acquire lock (transaction has been completed): " + req.version();
U.warn(log, msg);
if (tx != null)
tx.rollbackDhtLocal();
return new GridDhtFinishedFuture<>(new IgniteCheckedException(msg));
}
tx.topologyVersion(req.topologyVersion());
} finally {
if (top != null)
top.readUnlock();
}
}
ctx.tm().txContext(tx);
if (log.isDebugEnabled())
log.debug("Performing DHT lock [tx=" + tx + ", entries=" + entries + ']');
IgniteInternalFuture<GridCacheReturn> txFut = tx.lockAllAsync(cacheCtx, entries, req.messageId(), req.txRead(), req.needReturnValue(), req.createTtl(), req.accessTtl(), req.skipStore(), req.keepBinary());
final GridDhtTxLocal t = tx;
return new GridDhtEmbeddedFuture(txFut, new C2<GridCacheReturn, Exception, IgniteInternalFuture<GridNearLockResponse>>() {
@Override
public IgniteInternalFuture<GridNearLockResponse> apply(GridCacheReturn o, Exception e) {
if (e != null)
e = U.unwrap(e);
assert !t.empty();
// Create response while holding locks.
final GridNearLockResponse resp = createLockReply(nearNode, entries, req, t, t.xidVersion(), e);
assert !t.implicit() : t;
assert !t.onePhaseCommit() : t;
sendLockReply(nearNode, t, req, resp);
return new GridFinishedFuture<>(resp);
}
});
} else {
assert fut != null;
// This will send remote messages.
fut.map();
final GridCacheVersion mappedVer = fut.version();
return new GridDhtEmbeddedFuture<>(new C2<Boolean, Exception, GridNearLockResponse>() {
@Override
public GridNearLockResponse apply(Boolean b, Exception e) {
if (e != null)
e = U.unwrap(e);
else if (!b)
e = new GridCacheLockTimeoutException(req.version());
GridNearLockResponse res = createLockReply(nearNode, entries, req, null, mappedVer, e);
sendLockReply(nearNode, null, req, res);
return res;
}
}, fut);
}
} catch (IgniteCheckedException | RuntimeException e) {
String err = "Failed to unmarshal at least one of the keys for lock request message: " + req;
U.error(log, err, e);
if (tx != null) {
try {
tx.rollbackDhtLocal();
} catch (IgniteCheckedException ex) {
U.error(log, "Failed to rollback the transaction: " + tx, ex);
}
}
return new GridDhtFinishedFuture<>(new IgniteCheckedException(err, e));
}
}
use of org.apache.ignite.internal.processors.cache.version.GridCacheVersion in project ignite by apache.
the class GridDhtTransactionalCacheAdapter method createLockReply.
/**
* @param nearNode Near node.
* @param entries Entries.
* @param req Lock request.
* @param tx Transaction.
* @param mappedVer Mapped version.
* @param err Error.
* @return Response.
*/
private GridNearLockResponse createLockReply(ClusterNode nearNode, List<GridCacheEntryEx> entries, GridNearLockRequest req, @Nullable GridDhtTxLocalAdapter tx, GridCacheVersion mappedVer, Throwable err) {
assert mappedVer != null;
assert tx == null || tx.xidVersion().equals(mappedVer);
try {
// Send reply back to originating near node.
GridNearLockResponse res = new GridNearLockResponse(ctx.cacheId(), req.version(), req.futureId(), req.miniId(), tx != null && tx.onePhaseCommit(), entries.size(), err, null, ctx.deploymentEnabled());
if (err == null) {
res.pending(localDhtPendingVersions(entries, mappedVer));
// We have to add completed versions for cases when nearLocal and remote transactions
// execute concurrently.
IgnitePair<Collection<GridCacheVersion>> versPair = ctx.tm().versions(req.version());
res.completedVersions(versPair.get1(), versPair.get2());
int i = 0;
for (ListIterator<GridCacheEntryEx> it = entries.listIterator(); it.hasNext(); ) {
GridCacheEntryEx e = it.next();
assert e != null;
while (true) {
try {
// Don't return anything for invalid partitions.
if (tx == null || !tx.isRollbackOnly()) {
GridCacheVersion dhtVer = req.dhtVersion(i);
GridCacheVersion ver = e.version();
boolean ret = req.returnValue(i) || dhtVer == null || !dhtVer.equals(ver);
CacheObject val = null;
if (ret)
val = e.innerGet(null, tx, /*read-through*/
false, /*update-metrics*/
true, /*event notification*/
req.returnValue(i), CU.subjectId(tx, ctx.shared()), null, tx != null ? tx.resolveTaskName() : null, null, req.keepBinary());
assert e.lockedBy(mappedVer) || (ctx.mvcc().isRemoved(e.context(), mappedVer) && req.timeout() > 0) : "Entry does not own lock for tx [locNodeId=" + ctx.localNodeId() + ", entry=" + e + ", mappedVer=" + mappedVer + ", ver=" + ver + ", tx=" + tx + ", req=" + req + ", err=" + err + ']';
boolean filterPassed = false;
if (tx != null && tx.onePhaseCommit()) {
IgniteTxEntry writeEntry = tx.entry(ctx.txKey(e.key()));
assert writeEntry != null : "Missing tx entry for locked cache entry: " + e;
filterPassed = writeEntry.filtersPassed();
}
if (ret && val == null)
val = e.valueBytes(null);
// We include values into response since they are required for local
// calls and won't be serialized. We are also including DHT version.
res.addValueBytes(ret ? val : null, filterPassed, ver, mappedVer);
} else {
// We include values into response since they are required for local
// calls and won't be serialized. We are also including DHT version.
res.addValueBytes(null, false, e.version(), mappedVer);
}
break;
} catch (GridCacheEntryRemovedException ignore) {
if (log.isDebugEnabled())
log.debug("Got removed entry when sending reply to DHT lock request " + "(will retry): " + e);
e = entryExx(e.key());
it.set(e);
}
}
i++;
}
}
return res;
} catch (IgniteCheckedException e) {
U.error(log, "Failed to get value for lock reply message for node [node=" + U.toShortString(nearNode) + ", req=" + req + ']', e);
return new GridNearLockResponse(ctx.cacheId(), req.version(), req.futureId(), req.miniId(), false, entries.size(), e, null, ctx.deploymentEnabled());
}
}
use of org.apache.ignite.internal.processors.cache.version.GridCacheVersion in project ignite by apache.
the class GridDhtLockFuture method loadMissingFromStore.
/**
*
*/
private void loadMissingFromStore() {
if (!skipStore && (read || cctx.loadPreviousValue()) && cctx.readThrough() && (needReturnVal || read)) {
final Map<KeyCacheObject, GridDhtCacheEntry> loadMap = new LinkedHashMap<>();
final GridCacheVersion ver = version();
for (GridDhtCacheEntry entry : entries) {
try {
entry.unswap(false);
if (!entry.hasValue())
loadMap.put(entry.key(), entry);
} catch (GridCacheEntryRemovedException e) {
assert false : "Should not get removed exception while holding lock on entry " + "[entry=" + entry + ", e=" + e + ']';
} catch (IgniteCheckedException e) {
onDone(e);
return;
}
}
try {
cctx.store().loadAll(null, loadMap.keySet(), new CI2<KeyCacheObject, Object>() {
@Override
public void apply(KeyCacheObject key, Object val) {
// No value loaded from store.
if (val == null)
return;
GridDhtCacheEntry entry0 = loadMap.get(key);
try {
CacheObject val0 = cctx.toCacheObject(val);
long ttl = createTtl;
long expireTime;
if (ttl == CU.TTL_ZERO)
expireTime = CU.expireTimeInPast();
else {
if (ttl == CU.TTL_NOT_CHANGED)
ttl = CU.TTL_ETERNAL;
expireTime = CU.toExpireTime(ttl);
}
entry0.initialValue(val0, ver, ttl, expireTime, false, topVer, GridDrType.DR_LOAD, true);
} catch (GridCacheEntryRemovedException e) {
assert false : "Should not get removed exception while holding lock on entry " + "[entry=" + entry0 + ", e=" + e + ']';
} catch (IgniteCheckedException e) {
onDone(e);
}
}
});
} catch (IgniteCheckedException e) {
onDone(e);
}
}
}
use of org.apache.ignite.internal.processors.cache.version.GridCacheVersion in project ignite by apache.
the class GridDhtCacheEntry method localCandidateByNearVersion.
/**
* @param nearVer Near version.
* @param rmv If {@code true}, then add to removed list if not found.
* @return Local candidate by near version.
* @throws GridCacheEntryRemovedException If removed.
*/
@Nullable
synchronized GridCacheMvccCandidate localCandidateByNearVersion(GridCacheVersion nearVer, boolean rmv) throws GridCacheEntryRemovedException {
checkObsolete();
GridCacheMvcc mvcc = mvccExtras();
if (mvcc != null) {
for (GridCacheMvccCandidate c : mvcc.localCandidatesNoCopy(false)) {
GridCacheVersion ver = c.otherVersion();
if (ver != null && ver.equals(nearVer))
return c;
}
}
if (rmv)
addRemoved(nearVer);
return null;
}
Aggregations