Repository: ignite Updated Branches: refs/heads/ignite-1607 001b42e78 -> 177ae71e2
ignite-1607 WIP Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/177ae71e Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/177ae71e Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/177ae71e Branch: refs/heads/ignite-1607 Commit: 177ae71e220e87617b640de8337c2b27ea5737a2 Parents: 001b42e Author: sboikov <[email protected]> Authored: Thu Oct 15 16:37:00 2015 +0300 Committer: sboikov <[email protected]> Committed: Thu Oct 15 16:37:00 2015 +0300 ---------------------------------------------------------------------- .../processors/cache/GridCacheEntryEx.java | 12 +- .../processors/cache/GridCacheMapEntry.java | 13 + .../processors/cache/GridCacheMvcc.java | 136 ++++++++-- .../cache/GridCacheMvccCandidate.java | 26 +- .../distributed/GridDistributedCacheEntry.java | 4 +- .../distributed/dht/GridDhtCacheEntry.java | 16 +- .../distributed/dht/GridDhtLockFuture.java | 1 + .../distributed/dht/GridDhtTxPrepareFuture.java | 64 ++++- .../colocated/GridDhtColocatedLockFuture.java | 6 +- .../cache/local/GridLocalCacheEntry.java | 10 +- .../cache/transactions/IgniteTxManager.java | 21 +- .../CacheSerializableTransactionsTest.java | 255 ++++++++++++++++--- .../cache/GridCacheMvccFlagsTest.java | 6 +- .../cache/GridCacheMvccPartitionedSelfTest.java | 164 ++++++++++++ .../processors/cache/GridCacheMvccSelfTest.java | 3 +- .../processors/cache/GridCacheTestEntryEx.java | 7 + 16 files changed, 650 insertions(+), 94 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java index ebbc736..d00929a 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java @@ -542,7 +542,9 @@ public interface GridCacheEntryEx { * @throws GridDistributedLockCancelledException If lock has been cancelled. * @throws IgniteCheckedException If failed. */ - public boolean tmLock(IgniteInternalTx tx, long timeout, @Nullable GridCacheVersion serReadVer) + public boolean tmLock(IgniteInternalTx tx, + long timeout, + @Nullable GridCacheVersion serReadVer) throws GridCacheEntryRemovedException, GridDistributedLockCancelledException, IgniteCheckedException; /** @@ -594,6 +596,14 @@ public interface GridCacheEntryEx { public GridCacheVersion version() throws GridCacheEntryRemovedException; /** + * Checks if there was read/write conflict in serializable transaction. + * + * @param serReadVer Version read in serializable transaction. + * @return {@code True} if version check passed. + */ + public boolean checkSerializableReadVersion(GridCacheVersion serReadVer); + + /** * Peeks into entry without loading value or updating statistics. * * @param heap Read from heap flag. http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java index c734629..8d7d6ac 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java @@ -44,6 +44,7 @@ import org.apache.ignite.internal.processors.cache.extras.GridCacheObsoleteEntry import org.apache.ignite.internal.processors.cache.extras.GridCacheTtlEntryExtras; import org.apache.ignite.internal.processors.cache.query.GridCacheQueryManager; import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx; +import org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry; import org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey; import org.apache.ignite.internal.processors.cache.transactions.IgniteTxLocalAdapter; import org.apache.ignite.internal.processors.cache.version.GridCachePlainVersionedEntry; @@ -2832,6 +2833,18 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme return ver; } + /** {@inheritDoc} */ + @Override public synchronized boolean checkSerializableReadVersion(GridCacheVersion serReadVer) { + assert !obsolete() : this; + + if (!serReadVer.equals(ver)) { + if (!((isStartVersion() || deletedUnlocked()) && serReadVer.equals(IgniteTxEntry.READ_NEW_ENTRY_VER))) + return false; + } + + return true; + } + /** * Gets hash value for the entry key. * http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvcc.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvcc.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvcc.java index c2102bd..e9c68f6 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvcc.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvcc.java @@ -20,6 +20,7 @@ package org.apache.ignite.internal.processors.cache; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.Deque; import java.util.Iterator; import java.util.LinkedList; @@ -53,6 +54,32 @@ public final class GridCacheMvcc { /** Logger. */ private static volatile IgniteLogger log; + /** */ + private static final Comparator<GridCacheVersion> SER_VER_COMPARATOR = new Comparator<GridCacheVersion>() { + @Override public int compare(GridCacheVersion ver1, GridCacheVersion ver2) { + long time1 = ver1.globalTime(); + long time2 = ver2.globalTime(); + + if (time1 == time2) { + int nodeOrder1 = ver1.nodeOrder(); + int nodeOrder2 = ver2.nodeOrder(); + + if (nodeOrder1 == nodeOrder2) { + long order1 = ver1.order(); + long order2 = ver2.order(); + + assert order1 != order2; + + return order1 > order2 ? 1 : -1; + } + else + return nodeOrder1 > nodeOrder2 ? 1 : -1; + } + else + return time1 > time2 ? 1 : -1; + } + }; + /** Cache context. */ @GridToStringExclude private final GridCacheContext<?, ?> cctx; @@ -160,8 +187,9 @@ public final class GridCacheMvcc { /** * @param cand Candidate to add. + * @return {@code False} if failed to add candidate and transaction should be cancelled. */ - private void add0(GridCacheMvccCandidate cand) { + private boolean add0(GridCacheMvccCandidate cand) { assert cand != null; // Local. @@ -171,31 +199,59 @@ public final class GridCacheMvcc { if (!cand.nearLocal()) { if (!locs.isEmpty()) { - GridCacheMvccCandidate c = locs.getFirst(); + if (cand.serializable()) { + GridCacheMvccCandidate last = locs.getLast(); + + if (!last.serializable()) + return false; + + GridCacheVersion lastOrder = last.serializableOrder(); + + assert lastOrder != null : last; + + GridCacheVersion candOrder = cand.serializableOrder(); + + assert candOrder != null : cand; - if (c.owner()) { + int cmp = SER_VER_COMPARATOR.compare(lastOrder, candOrder); + + assert cmp != 0; + + if (cmp > 0) + return false; + + locs.addLast(cand); + + return true; + } + + GridCacheMvccCandidate first = locs.getFirst(); + + if (first.owner()) { // If reentry, add at the beginning. Note that // no reentry happens for DHT-local candidates. - if (!cand.dhtLocal() && c.threadId() == cand.threadId()) { + if (!cand.dhtLocal() && first.threadId() == cand.threadId()) { + assert !first.serializable(); + cand.setOwner(); cand.setReady(); cand.setReentry(); locs.addFirst(cand); - return; + return true; } } // Iterate in reverse order. for (ListIterator<GridCacheMvccCandidate> it = locs.listIterator(locs.size()); it.hasPrevious(); ) { - c = it.previous(); + GridCacheMvccCandidate c = it.previous(); assert !c.version().equals(cand.version()) : "Versions can't match [existing=" + c + ", new=" + cand + ']'; - // Add after the owner. - if (c.owner()) { + // Add after the owner or serializable tx. + if (c.owner() || c.serializable()) { // Threads are checked above. assert cand.dhtLocal() || c.threadId() != cand.threadId(); @@ -204,7 +260,7 @@ public final class GridCacheMvcc { it.add(cand); - return; + return true; } // If not the owner, add after the lesser version. @@ -214,7 +270,7 @@ public final class GridCacheMvcc { it.add(cand); - return; + return true; } } } @@ -228,6 +284,8 @@ public final class GridCacheMvcc { } // Remote. else { + assert !cand.serializable() : cand; + if (rmts == null) rmts = new LinkedList<>(); @@ -241,12 +299,14 @@ public final class GridCacheMvcc { if (cand.owner()) cur.setOwner(); - return; + return true; } // Either list is empty or candidate is last. rmts.add(cand); } + + return true; } /** @@ -456,6 +516,7 @@ public final class GridCacheMvcc { threadId, ver, timeout, + /*serializable order*/null, reenter, tx, implicitSingle, @@ -484,6 +545,7 @@ public final class GridCacheMvcc { long threadId, GridCacheVersion ver, long timeout, + @Nullable GridCacheVersion serOrder, boolean reenter, boolean tx, boolean implicitSingle, @@ -528,12 +590,17 @@ public final class GridCacheMvcc { tx, implicitSingle, /*near-local*/false, - dhtLoc + dhtLoc, + serOrder ); - cctx.mvcc().addLocal(cand); + if (!add0(cand)) { + assert serOrder != null : cand; - add0(cand); + return null; + } + + cctx.mvcc().addLocal(cand); return cand; } @@ -575,7 +642,8 @@ public final class GridCacheMvcc { tx, implicitSingle, nearLoc, - false + false, + null ); addRemote(cand); @@ -596,11 +664,28 @@ public final class GridCacheMvcc { * @param implicitSingle Implicit flag. * @return Add remote candidate. */ - public GridCacheMvccCandidate addNearLocal(GridCacheEntryEx parent, UUID nodeId, - @Nullable UUID otherNodeId, long threadId, GridCacheVersion ver, long timeout, boolean tx, + public GridCacheMvccCandidate addNearLocal(GridCacheEntryEx parent, + UUID nodeId, + @Nullable UUID otherNodeId, + long threadId, + GridCacheVersion ver, + long timeout, + boolean tx, boolean implicitSingle) { - GridCacheMvccCandidate cand = new GridCacheMvccCandidate(parent, nodeId, otherNodeId, null, threadId, ver, - timeout, /*local*/true, /*reentry*/false, tx, implicitSingle, /*near loc*/true, /*dht loc*/false); + GridCacheMvccCandidate cand = new GridCacheMvccCandidate(parent, + nodeId, + otherNodeId, + null, + threadId, + ver, + timeout, + /*local*/true, + /*reentry*/false, + tx, + implicitSingle, + /*near loc*/true, + /*dht loc*/false, + null); add0(cand); @@ -854,7 +939,18 @@ public final class GridCacheMvcc { } } - if (locs != null) { + if (locs != null && !locs.isEmpty()) { + GridCacheMvccCandidate first = locs.getFirst(); + + if (first.serializable()) { + if (first.owner() || !first.ready()) + return; + + first.setOwner(); + + return; + } + for (ListIterator<GridCacheMvccCandidate> it = locs.listIterator(); it.hasNext(); ) { GridCacheMvccCandidate cand = it.next(); http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccCandidate.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccCandidate.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccCandidate.java index f19a054..aba8318 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccCandidate.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccCandidate.java @@ -126,6 +126,9 @@ public class GridCacheMvccCandidate implements Externalizable, @GridToStringInclude private transient volatile GridCacheVersion ownerVer; + /** */ + private GridCacheVersion serOrder; + /** * Empty constructor required by {@link Externalizable}. */ @@ -147,6 +150,7 @@ public class GridCacheMvccCandidate implements Externalizable, * @param singleImplicit Single-key-implicit-transaction flag. * @param nearLoc Near-local flag. * @param dhtLoc DHT local flag. + * @param serOrder Version for serializable transactions ordering. */ public GridCacheMvccCandidate( GridCacheEntryEx parent, @@ -161,7 +165,9 @@ public class GridCacheMvccCandidate implements Externalizable, boolean tx, boolean singleImplicit, boolean nearLoc, - boolean dhtLoc) { + boolean dhtLoc, + @Nullable GridCacheVersion serOrder + ) { assert nodeId != null; assert ver != null; assert parent != null; @@ -173,6 +179,7 @@ public class GridCacheMvccCandidate implements Externalizable, this.threadId = threadId; this.ver = ver; this.timeout = timeout; + this.serOrder = serOrder; mask(LOCAL, loc); mask(REENTRY, reentry); @@ -244,7 +251,8 @@ public class GridCacheMvccCandidate implements Externalizable, tx(), singleImplicit(), nearLocal(), - dhtLocal()); + dhtLocal(), + serializableOrder()); reentry.topVer = topVer; @@ -452,6 +460,20 @@ public class GridCacheMvccCandidate implements Externalizable, } /** + * @return Serializable transaction flag. + */ + public boolean serializable() { + return serOrder != null; + } + + /** + * @return Version for serializable transactions ordering. + */ + @Nullable public GridCacheVersion serializableOrder() { + return serOrder; + } + + /** * @return {@code True} if this candidate is a reentry. */ public boolean reentry() { http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedCacheEntry.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedCacheEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedCacheEntry.java index 0bfbe7d..d564768 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedCacheEntry.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedCacheEntry.java @@ -743,7 +743,9 @@ public class GridDistributedCacheEntry extends GridCacheMapEntry { } /** {@inheritDoc} */ - @Override public boolean tmLock(IgniteInternalTx tx, long timeout, GridCacheVersion serReadVer) + @Override public boolean tmLock(IgniteInternalTx tx, + long timeout, + GridCacheVersion serReadVer) throws GridCacheEntryRemovedException, GridDistributedLockCancelledException, IgniteCheckedException { if (tx.local()) // Null is returned if timeout is negative and there is other lock owner. http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java index 9c10a0a..c483e01 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java @@ -180,6 +180,7 @@ public class GridDhtCacheEntry extends GridDistributedCacheEntry { AffinityTopologyVersion topVer, long threadId, GridCacheVersion ver, + @Nullable GridCacheVersion serOrder, @Nullable GridCacheVersion serReadVer, long timeout, boolean reenter, @@ -187,6 +188,9 @@ public class GridDhtCacheEntry extends GridDistributedCacheEntry { boolean implicitSingle) throws GridCacheEntryRemovedException, GridDistributedLockCancelledException, IgniteCheckedException { + assert serReadVer == null || serOrder != null; + assert !reenter || serOrder == null; + GridCacheMvccCandidate cand; GridCacheMvccCandidate prev; GridCacheMvccCandidate owner; @@ -203,10 +207,8 @@ public class GridDhtCacheEntry extends GridDistributedCacheEntry { if (serReadVer != null) { unswap(false); - if (!serReadVer.equals(this.ver)) { - if (!((isNew() || deleted()) && serReadVer.equals(IgniteTxEntry.READ_NEW_ENTRY_VER))) - return null; - } + if (!checkSerializableReadVersion(serReadVer)) + return null; } GridCacheMvcc mvcc = mvccExtras(); @@ -228,6 +230,7 @@ public class GridDhtCacheEntry extends GridDistributedCacheEntry { threadId, ver, timeout, + serOrder, reenter, tx, implicitSingle, @@ -265,7 +268,9 @@ public class GridDhtCacheEntry extends GridDistributedCacheEntry { } /** {@inheritDoc} */ - @Override public boolean tmLock(IgniteInternalTx tx, long timeout, GridCacheVersion serReadVer) + @Override public boolean tmLock(IgniteInternalTx tx, + long timeout, + GridCacheVersion serReadVer) throws GridCacheEntryRemovedException, GridDistributedLockCancelledException, IgniteCheckedException { if (tx.local()) { GridDhtTxLocalAdapter dhtTx = (GridDhtTxLocalAdapter)tx; @@ -277,6 +282,7 @@ public class GridDhtCacheEntry extends GridDistributedCacheEntry { tx.topologyVersion(), tx.threadId(), tx.xidVersion(), + (tx.optimistic() && tx.serializable()) ? tx.nearXidVersion() : null, serReadVer, timeout, /*reenter*/false, http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java index c64d909..016d030 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java @@ -402,6 +402,7 @@ public final class GridDhtLockFuture extends GridCompoundIdentityFuture<Boolean> threadId, lockVer, null, + null, timeout, /*reenter*/false, inTx(), http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java index b0f72dc..f25ee33 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java @@ -57,6 +57,7 @@ import org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry; import org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey; import org.apache.ignite.internal.processors.cache.version.GridCacheVersion; import org.apache.ignite.internal.processors.dr.GridDrType; +import org.apache.ignite.internal.transactions.IgniteTxOptimisticCheckedException; import org.apache.ignite.internal.util.F0; import org.apache.ignite.internal.util.GridConcurrentHashSet; import org.apache.ignite.internal.util.GridLeanSet; @@ -469,9 +470,18 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter if (log.isDebugEnabled()) log.debug("Marking all local candidates as ready: " + this); - Iterable<IgniteTxEntry> checkEntries = - (tx.optimistic() && tx.serializable()) ? F.concat(false, writes, reads) : writes; + readyLocks(writes); + if (tx.optimistic() && tx.serializable()) + readyLocks(reads); + + locksReady = true; + } + + /** + * @param checkEntries Entries. + */ + private void readyLocks(Iterable<IgniteTxEntry> checkEntries) { for (IgniteTxEntry txEntry : checkEntries) { GridCacheContext cacheCtx = txEntry.context(); @@ -511,8 +521,6 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter } } } - - locksReady = true; } /** @@ -903,10 +911,58 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter } /** + * @param entries Entries. + * @return Not null exception if version check failed. + */ + @Nullable private IgniteTxOptimisticCheckedException checkReadConflict(Collection<IgniteTxEntry> entries) { + for (IgniteTxEntry entry : entries) { + GridCacheVersion serReadVer = entry.serializableReadVersion(); + + if (serReadVer != null && !entry.cached().checkSerializableReadVersion(serReadVer)) { + GridCacheContext cctx = entry.context(); + + return new IgniteTxOptimisticCheckedException("Failed to prepare transaction, " + + "read conflict [key=" + entry.key().value(cctx.cacheObjectContext(), false) + + ", cache=" + cctx.name() + ']'); + } + } + + return null; + } + + /** * */ private void prepare0() { try { + if (tx.optimistic() && tx.serializable()) { + IgniteTxOptimisticCheckedException err0 = checkReadConflict(writes); + + if (err0 == null) + err0 = checkReadConflict(reads); + + if (err0 != null) { + err.compareAndSet(null, err0); + + final GridNearTxPrepareResponse res = createPrepareResponse(); + + tx.rollbackAsync().listen(new CI1<IgniteInternalFuture<IgniteInternalTx>>() { + @Override public void apply(IgniteInternalFuture<IgniteInternalTx> fut) { + if (GridDhtTxPrepareFuture.super.onDone(res, res.error())) { + try { + sendPrepareResponse(res); + } + catch (IgniteCheckedException e) { + U.error(log, "Failed to send prepare response for transaction: " + tx, e); + } + } + } + }); + + return; + } + } + // We are holding transaction-level locks for entries here, so we can get next write version. onEntriesLocked(); http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java index be09f54..c9969e3 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java @@ -323,7 +323,8 @@ public final class GridDhtColocatedLockFuture extends GridCompoundIdentityFuture inTx(), inTx() && tx.implicitSingle(), false, - false); + false, + null); cand.topologyVersion(topVer.get()); } @@ -342,7 +343,8 @@ public final class GridDhtColocatedLockFuture extends GridCompoundIdentityFuture inTx(), inTx() && tx.implicitSingle(), false, - false); + false, + null); cand.topologyVersion(topVer.get()); } http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalCacheEntry.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalCacheEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalCacheEntry.java index fcc6abe..32c2fa9 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalCacheEntry.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalCacheEntry.java @@ -95,10 +95,8 @@ public class GridLocalCacheEntry extends GridCacheMapEntry { checkObsolete(); if (serReadVer != null) { - if (!serReadVer.equals(this.ver)) { - if (!((isNew() || deleted()) && serReadVer.equals(IgniteTxEntry.READ_NEW_ENTRY_VER))) - return null; - } + if (!checkSerializableReadVersion(serReadVer)) + return null; } GridCacheMvcc mvcc = mvccExtras(); @@ -201,7 +199,9 @@ public class GridLocalCacheEntry extends GridCacheMapEntry { } /** {@inheritDoc} */ - @Override public boolean tmLock(IgniteInternalTx tx, long timeout, GridCacheVersion serReadVer) + @Override public boolean tmLock(IgniteInternalTx tx, + long timeout, + GridCacheVersion serReadVer) throws GridCacheEntryRemovedException { GridCacheMvccCandidate cand = addLocal( tx.threadId(), http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java index 21053a2..24ea634 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java @@ -29,7 +29,6 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentNavigableMap; -import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.atomic.AtomicInteger; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteClientDisconnectedException; @@ -1375,20 +1374,12 @@ public class IgniteTxManager extends GridCacheSharedManagerAdapter { throws IgniteCheckedException { assert tx.optimistic() || !tx.local(); - long timeout; + long remainingTime = U.currentTimeMillis() - (tx.startTime() + tx.timeout()); - boolean ser = tx.optimistic() && tx.serializable(); - - if (!ser) { - long remainingTime = U.currentTimeMillis() - (tx.startTime() + tx.timeout()); - - // For serializable transactions, failure to acquire lock means - // that there is a serializable conflict. For all other isolation levels, - // we wait for the lock. - timeout = tx.timeout() == 0 ? 0 : remainingTime; - } - else - timeout = -1L; + // For serializable transactions, failure to acquire lock means + // that there is a serializable conflict. For all other isolation levels, + // we wait for the lock. + long timeout = tx.timeout() == 0 ? 0 : remainingTime; for (IgniteTxEntry txEntry1 : entries) { // Check if this entry was prepared before. @@ -1406,7 +1397,7 @@ public class IgniteTxManager extends GridCacheSharedManagerAdapter { GridCacheVersion serReadVer = txEntry1.serializableReadVersion(); - assert serReadVer == null || ser : txEntry1; + assert serReadVer == null || (tx.optimistic() && tx.serializable()) : txEntry1; if (!entry1.tmLock(tx, timeout, serReadVer)) { // Unlock locks locked so far. http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheSerializableTransactionsTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheSerializableTransactionsTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheSerializableTransactionsTest.java index 2342a5d..0c9debf 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheSerializableTransactionsTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheSerializableTransactionsTest.java @@ -25,8 +25,10 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeMap; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -2750,38 +2752,47 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest { * @throws Exception If failed. */ public void testAccountTx1() throws Exception { - accountTx(false, false, TestMemoryMode.HEAP); + accountTx(false, false, false, TestMemoryMode.HEAP); } /** * @throws Exception If failed. */ - public void testAccountTxNearCache() throws Exception { - accountTx(false, true, TestMemoryMode.HEAP); + public void testAccountTx2() throws Exception { + accountTx(true, false, false, TestMemoryMode.HEAP); } /** * @throws Exception If failed. */ - public void testAccountTx2() throws Exception { - accountTx(true, false, TestMemoryMode.HEAP); + public void testAccountTxWithNonSerializable() throws Exception { + accountTx(false, false, true, TestMemoryMode.HEAP); + } + + /** + * @throws Exception If failed. + */ + public void testAccountTxNearCache() throws Exception { + accountTx(false, true, false, TestMemoryMode.HEAP); } /** * @throws Exception If failed. */ public void testAccountTxOffheapTiered() throws Exception { - accountTx(false, false, TestMemoryMode.OFFHEAP_TIERED); + accountTx(false, false, false, TestMemoryMode.OFFHEAP_TIERED); } /** * @param getAll If {@code true} uses getAll/putAll in transaction. * @param nearCache If {@code true} near cache is enabled. + * @param nonSer If {@code true} starts threads executing non-serializable transactions. * @param memMode Test memory mode. * @throws Exception If failed. */ private void accountTx(final boolean getAll, final boolean nearCache, + final boolean nonSer, TestMemoryMode memMode) throws Exception { final Ignite ignite0 = ignite(0); @@ -2808,6 +2819,67 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest { final long stopTime = System.currentTimeMillis() + 10_000; + IgniteInternalFuture<?> nonSerFut = null; + + if (nonSer) { + nonSerFut = runMultiThreadedAsync(new Callable<Void>() { + @Override public Void call() throws Exception { + int nodeIdx = idx.getAndIncrement() % clients.size(); + + Ignite node = clients.get(nodeIdx); + + Thread.currentThread().setName("update-pessimistic-" + node.name()); + + log.info("Pessimistic tx thread: " + node.name()); + + final IgniteTransactions txs = node.transactions(); + + final IgniteCache<Integer, Account> cache = + nearCache ? node.createNearCache(cacheName, new NearCacheConfiguration<Integer, Account>()) : + node.<Integer, Account>cache(cacheName); + + assertNotNull(cache); + + ThreadLocalRandom rnd = ThreadLocalRandom.current(); + + while (U.currentTimeMillis() < stopTime) { + int id1 = rnd.nextInt(ACCOUNTS); + + int id2 = rnd.nextInt(ACCOUNTS); + + while (id2 == id1) + id2 = rnd.nextInt(ACCOUNTS); + + if (id1 > id2) { + int tmp = id1; + id1 = id2; + id2 = tmp; + } + + try (Transaction tx = txs.txStart(PESSIMISTIC, REPEATABLE_READ)) { + Account a1 = cache.get(id1); + Account a2 = cache.get(id2); + + assertNotNull(a1); + assertNotNull(a2); + + if (a1.value() > 0) { + a1 = new Account(a1.value() - 1); + a2 = new Account(a2.value() + 1); + } + + cache.put(id1, a1); + cache.put(id2, a2); + + tx.commit(); + } + } + + return null; + } + }, 10, "non-ser-thread"); + } + IgniteInternalFuture<?> fut = runMultiThreadedAsync(new Callable<Void>() { @Override public Void call() throws Exception { int nodeIdx = idx.getAndIncrement() % clients.size(); @@ -2898,6 +2970,9 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest { fut.get(30_000); + if (nonSerFut != null) + nonSerFut.get(); + int sum = 0; for (int i = 0; i < ACCOUNTS; i++) { @@ -2962,53 +3037,100 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest { /** * @throws Exception If failed. */ + public void testConflictResolution() throws Exception { + final Ignite ignite = ignite(0); + + final String cacheName = + ignite.createCache(cacheConfiguration(PARTITIONED, FULL_SYNC, 1, false, false)).getName(); + + try { + final Map<Integer, Integer> keys = new HashMap<>(); + + for (int i = 0; i < 500; i++) + keys.put(i, i); + + final int THREADS = 5; + + for (int i = 0; i < 10; i++) { + final CyclicBarrier barrier = new CyclicBarrier(THREADS); + + final AtomicInteger commitCntr = new AtomicInteger(0); + + GridTestUtils.runMultiThreadedAsync(new Callable<Void>() { + @Override public Void call() throws Exception { + IgniteCache<Integer, Integer> cache = ignite.cache(cacheName); + + IgniteTransactions txs = cache.unwrap(Ignite.class).transactions(); + + try (Transaction tx = txs.txStart(OPTIMISTIC, SERIALIZABLE)) { + cache.putAll(keys); + + barrier.await(); + + tx.commit(); + + commitCntr.incrementAndGet(); + } + catch (TransactionOptimisticException e) { + log.info("Optimistic error: " + e); + } + + return null; + } + }, THREADS, "update-thread").get(); + + int commits = commitCntr.get(); + + log.info("Iteration [iter=" + i + ", commits=" + commits + ']'); + + assertTrue(commits > 0); + } + } + finally { + ignite.destroyCache(cacheName); + } + } + + /** + * @throws Exception If failed. + */ public void testConcurrentUpdateNoDeadlock() throws Exception { - concurrentUpdateNoDeadlock(Collections.singletonList(ignite(0)), 10, false, false); + concurrentUpdateNoDeadlock(Collections.singletonList(ignite(0)), 10, false, false, false); } /** * @throws Exception If failed. */ public void testConcurrentUpdateNoDeadlockGetPut() throws Exception { - concurrentUpdateNoDeadlock(Collections.singletonList(ignite(0)), 10, true, false); + concurrentUpdateNoDeadlock(Collections.singletonList(ignite(0)), 10, true, false, false); } /** * @throws Exception If failed. */ - public void testConcurrentUpdateNoDeadlockNodeRestart() throws Exception { - concurrentUpdateNoDeadlock(Collections.singletonList(ignite(1)), 10, false, true); + public void testConcurrentUpdateNoDeadlockWithNonSerializable() throws Exception { + concurrentUpdateNoDeadlock(Collections.singletonList(ignite(0)), 10, true, false, true); } /** * @throws Exception If failed. */ - public void testConcurrentUpdateNoDeadlockFromClients() throws Exception { - concurrentUpdateNoDeadlock(clients(), 20, false, false); + public void testConcurrentUpdateNoDeadlockNodeRestart() throws Exception { + concurrentUpdateNoDeadlock(Collections.singletonList(ignite(1)), 10, false, true, false); } /** * @throws Exception If failed. */ - public void testConcurrentUpdateNoDeadlockFromClientsNodeRestart() throws Exception { - concurrentUpdateNoDeadlock(clients(), 20, false, true); + public void testConcurrentUpdateNoDeadlockFromClients() throws Exception { + concurrentUpdateNoDeadlock(clients(), 20, false, false, false); } /** - * @return Client nodes. + * @throws Exception If failed. */ - private List<Ignite> clients() { - List<Ignite> clients = new ArrayList<>(); - - for (int i = 0; i < CLIENTS; i++) { - Ignite ignite = ignite(SRVS + i); - - assertTrue(ignite.configuration().isClientMode()); - - clients.add(ignite); - } - - return clients; + public void testConcurrentUpdateNoDeadlockFromClientsNodeRestart() throws Exception { + concurrentUpdateNoDeadlock(clients(), 20, false, true, false); } /** @@ -3016,12 +3138,15 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest { * @param threads Number of threads executing updates. * @param get If {@code true} gets value in transaction. * @param restart If {@code true} restarts one node. + * @param nonSer If {@code true} starts threads executing non-serializable transactions. * @throws Exception If failed. */ private void concurrentUpdateNoDeadlock(final List<Ignite> updateNodes, int threads, final boolean get, - final boolean restart) throws Exception { + final boolean restart, + final boolean nonSer + ) throws Exception { if (FAST) return; @@ -3065,6 +3190,45 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest { final AtomicInteger idx = new AtomicInteger(); + IgniteInternalFuture<?> nonSerFut = null; + + if (nonSer) { + nonSerFut = GridTestUtils.runMultiThreadedAsync(new Callable<Void>() { + @Override public Void call() throws Exception { + int nodeIdx = idx.getAndIncrement() % updateNodes.size(); + + Ignite node = updateNodes.get(nodeIdx); + + log.info("Non-serializable tx thread: " + node.name()); + + final IgniteCache<Integer, Integer> cache = node.cache(cacheName); + + assertNotNull(cache); + + final ThreadLocalRandom rnd = ThreadLocalRandom.current(); + + while (U.currentTimeMillis() < stopTime) { + final TreeMap<Integer, Integer> map = new TreeMap<>(); + + for (int i = 0; i < KEYS / 2; i++) + map.put(rnd.nextInt(KEYS), rnd.nextInt()); + + TransactionConcurrency concurrency = rnd.nextBoolean() ? PESSIMISTIC : OPTIMISTIC; + + doInTransaction(node, concurrency, REPEATABLE_READ, new Callable<Void>() { + @Override public Void call() throws Exception { + cache.putAll(map); + + return null; + } + }); + } + + return null; + } + }, 5, "non-ser-thread"); + } + IgniteInternalFuture<?> updateFut = GridTestUtils.runMultiThreadedAsync(new Callable<Void>() { @Override public Void call() throws Exception { int nodeIdx = idx.getAndIncrement() % updateNodes.size(); @@ -3082,17 +3246,17 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest { final ThreadLocalRandom rnd = ThreadLocalRandom.current(); while (U.currentTimeMillis() < stopTime) { - final Map<Integer, Integer> keys = new LinkedHashMap<>(); + final Map<Integer, Integer> map = new LinkedHashMap<>(); for (int i = 0; i < KEYS / 2; i++) - keys.put(rnd.nextInt(KEYS), rnd.nextInt()); + map.put(rnd.nextInt(KEYS), rnd.nextInt()); try { if (restart) { doInTransaction(node, OPTIMISTIC, SERIALIZABLE, new Callable<Void>() { @Override public Void call() throws Exception { if (get) { - for (Map.Entry<Integer, Integer> e : keys.entrySet()) { + for (Map.Entry<Integer, Integer> e : map.entrySet()) { if (rnd.nextBoolean()) { cache.get(e.getKey()); @@ -3104,7 +3268,7 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest { } } else - cache.putAll(keys); + cache.putAll(map); return null; } @@ -3113,7 +3277,7 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest { else { try (Transaction tx = txs.txStart(OPTIMISTIC, SERIALIZABLE)) { if (get) { - for (Map.Entry<Integer, Integer> e : keys.entrySet()) { + for (Map.Entry<Integer, Integer> e : map.entrySet()) { if (rnd.nextBoolean()) { cache.get(e.getKey()); @@ -3125,7 +3289,7 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest { } } else - cache.putAll(keys); + cache.putAll(map); tx.commit(); } @@ -3147,6 +3311,9 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest { updateFut.get(60, SECONDS); + if (nonSerFut != null) + nonSerFut.get(60, SECONDS); + IgniteCache<Integer, Integer> cache = srv.cache(cacheName); for (int key = 0; key < KEYS; key++) { @@ -3260,8 +3427,7 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest { final TransactionIsolation isolation, final IgniteClosure<IgniteCache<Integer, Integer>, Void> c) throws Exception { IgniteInternalFuture<?> fut = GridTestUtils.runAsync(new Callable<Void>() { - @Override - public Void call() throws Exception { + @Override public Void call() throws Exception { IgniteTransactions txs = cache.unwrap(Ignite.class).transactions(); try (Transaction tx = txs.txStart(concurrency, isolation)) { @@ -3401,6 +3567,23 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest { } /** + * @return Client nodes. + */ + private List<Ignite> clients() { + List<Ignite> clients = new ArrayList<>(); + + for (int i = 0; i < CLIENTS; i++) { + Ignite ignite = ignite(SRVS + i); + + assertTrue(ignite.configuration().isClientMode()); + + clients.add(ignite); + } + + return clients; + } + + /** * */ private static class TestStoreFactory implements Factory<CacheStore<Integer, Integer>> { http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccFlagsTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccFlagsTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccFlagsTest.java index 084bc75..234f362 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccFlagsTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccFlagsTest.java @@ -88,7 +88,8 @@ public class GridCacheMvccFlagsTest extends GridCommonAbstractTest { true, true, true, - true + true, + null ); c.setOwner(); @@ -128,7 +129,8 @@ public class GridCacheMvccFlagsTest extends GridCommonAbstractTest { false, false, false, - false + false, + null ); short flags = c.flags(); http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccPartitionedSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccPartitionedSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccPartitionedSelfTest.java index 0af7183..1b97663 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccPartitionedSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccPartitionedSelfTest.java @@ -595,6 +595,170 @@ public class GridCacheMvccPartitionedSelfTest extends GridCommonAbstractTest { } /** + * @throws Exception If failed. + */ + public void testSerializableLocks() throws Exception { + checkSerializableAdd(false); + + checkSerializableAdd(true); + + checkNonSerializableConflict(); + } + + /** + * @throws Exception If failed. + */ + private void checkNonSerializableConflict() throws Exception { + GridCacheAdapter<String, String> cache = grid.internalCache(); + + UUID nodeId = UUID.randomUUID(); + + GridCacheMvcc mvcc = new GridCacheMvcc(cache.context()); + + GridCacheTestEntryEx e = new GridCacheTestEntryEx(cache.context(), "1"); + + GridCacheMvccCandidate cand1 = mvcc.addLocal(e, + nodeId, + null, + 1, + version(1), + 0, + null, + false, + true, + false, + true + ); + + assertNotNull(cand1); + + GridCacheMvccCandidate cand2 = mvcc.addLocal(e, + nodeId, + null, + 1, + version(2), + 0, + new GridCacheVersion(0, 0, 30, 1), + false, + true, + false, + true + ); + + assertNull(cand2); + } + + /** + * @param incVer If {@code true} lock version is incremented. + * @throws Exception If failed. + */ + private void checkSerializableAdd(boolean incVer) throws Exception { + GridCacheAdapter<String, String> cache = grid.internalCache(); + + UUID nodeId = UUID.randomUUID(); + + GridCacheMvcc mvcc = new GridCacheMvcc(cache.context()); + + GridCacheTestEntryEx e = new GridCacheTestEntryEx(cache.context(), "1"); + + GridCacheVersion serOrder1 = new GridCacheVersion(0, 0, 10, 1); + GridCacheVersion serOrder2 = new GridCacheVersion(0, 0, 20, 1); + GridCacheVersion serOrder3 = new GridCacheVersion(0, 0, 15, 1); + GridCacheVersion serOrder4 = new GridCacheVersion(0, 0, 30, 1); + + GridCacheVersion ver1 = incVer ? version(1) : version(4); + GridCacheVersion ver2 = incVer ? version(2) : version(3); + GridCacheVersion ver3 = incVer ? version(3) : version(2); + GridCacheVersion ver4 = incVer ? version(4) : version(1); + + GridCacheMvccCandidate cand1 = mvcc.addLocal(e, + nodeId, + null, + 1, + ver1, + 0, + serOrder1, + false, + true, + false, + true + ); + + assertNotNull(cand1); + + GridCacheMvccCandidate cand2 = mvcc.addLocal(e, + nodeId, + null, + 2, + ver2, + 0, + serOrder2, + false, + true, + false, + true + ); + + assertNotNull(cand2); + + GridCacheMvccCandidate cand3 = mvcc.addLocal(e, + nodeId, + null, + 3, + ver3, + 0, + serOrder3, + false, + true, + false, + true + ); + + assertNull(cand3); + + GridCacheMvccCandidate cand4 = mvcc.addLocal(e, + nodeId, + null, + 4, + ver4, + 0, + serOrder4, + false, + true, + false, + true + ); + + assertNotNull(cand4); + + GridCacheMvccCandidate owner = mvcc.recheck(); + + assertNull(owner); + + cand2.setReady(); + + owner = mvcc.recheck(); + + assertNull(owner); + + cand1.setReady(); + + owner = mvcc.recheck(); + + assertSame(cand1, owner); + + owner = mvcc.recheck(); + + assertSame(cand1, owner); + + mvcc.remove(cand1.version()); + + owner = mvcc.recheck(); + + assertSame(cand2, owner); + } + + /** * Gets version based on order. * * @param order Order. http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccSelfTest.java index cdf8eca..59f9a9d 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccSelfTest.java @@ -101,7 +101,8 @@ public class GridCacheMvccSelfTest extends GridCommonAbstractTest { true, false, false, - false + false, + null ); Marshaller marshaller = getTestResources().getMarshaller(); http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java index 6b2a6c4..dd3c79a 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java @@ -630,6 +630,13 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr } /** @inheritDoc */ + @Override public boolean checkSerializableReadVersion(GridCacheVersion ver) { + assert false; + + return false; + } + + /** @inheritDoc */ @Override public boolean initialValue( CacheObject val, GridCacheVersion ver,
