Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

ISPN-2757 ReplaceCommand in REPL mode cluster does not perform any mo…

…difications if the entry was not yet transfered during rehashing

* ReplicationInterceptor needs to be smart an if the command is conditional but the affected value is not yet available locally because state transfer did not have the chance to fetch it yet then we should fetch it now.
* The whole logic where the coordinator is the main lock owner has to be replaced to use the first topology member rather than the coordinator (the coordinator might not even run the cache in question)
* ClusteringDependentLogic needs to be split in separate implementations for each cache mode
  • Loading branch information...
commit cc1ac8e73d9b96b8d386fb193641919779999ca6 1 parent 9e52b8f
Adrian Nistor anistor authored Mircea Markus committed

Showing 14 changed files with 548 additions and 83 deletions. Show diff stats Hide diff stats

  1. +1 1  core/src/main/java/org/infinispan/commands/write/ReplaceCommand.java
  2. +6 2 core/src/main/java/org/infinispan/factories/EmptyConstructorNamedCacheFactory.java
  3. +136 32 core/src/main/java/org/infinispan/interceptors/ReplicationInterceptor.java
  4. +3 2 core/src/main/java/org/infinispan/interceptors/VersionedReplicationInterceptor.java
  5. +1 1  core/src/main/java/org/infinispan/interceptors/base/CommandInterceptor.java
  6. +98 26 core/src/main/java/org/infinispan/interceptors/locking/ClusteringDependentLogic.java
  7. +0 5 core/src/test/java/org/infinispan/distribution/InvalidationFailureTest.java
  8. +152 0 core/src/test/java/org/infinispan/interceptors/ReplicationInterceptorTest.java
  9. +5 4 core/src/test/java/org/infinispan/replication/BaseReplicatedAPITest.java
  10. +7 8 core/src/test/java/org/infinispan/statetransfer/BaseReplStateTransferConsistencyTest.java
  11. +40 0 core/src/test/java/org/infinispan/statetransfer/ReplNonTxOperationsDuringStateTransferTest.java
  12. +40 0 core/src/test/java/org/infinispan/statetransfer/ReplOptimisticTxOperationsDuringStateTransferTest.java
  13. +57 0 core/src/test/java/org/infinispan/statetransfer/ReplPessimisticOperationsDuringStateTransferTest.java
  14. +2 2 core/src/test/java/org/infinispan/tx/TransactionXaAdapterTmIntegrationTest.java
2  core/src/main/java/org/infinispan/commands/write/ReplaceCommand.java
@@ -168,7 +168,7 @@ public boolean isSuccessful() {
168 168
169 169 @Override
170 170 public boolean isConditional() {
171   - return true;
  171 + return !ignorePreviousValue;
172 172 }
173 173
174 174 public long getLifespanMillis() {
8 core/src/main/java/org/infinispan/factories/EmptyConstructorNamedCacheFactory.java
@@ -81,8 +81,12 @@
81 81 Class<?> componentImpl;
82 82 if (componentType.equals(ClusteringDependentLogic.class)) {
83 83 CacheMode cacheMode = configuration.clustering().cacheMode();
84   - if (cacheMode.isReplicated() || !cacheMode.isClustered() || cacheMode.isInvalidation()) {
85   - return componentType.cast(new ClusteringDependentLogic.AllNodesLogic());
  84 + if (!cacheMode.isClustered()) {
  85 + return componentType.cast(new ClusteringDependentLogic.LocalLogic());
  86 + } else if (cacheMode.isInvalidation()) {
  87 + return componentType.cast(new ClusteringDependentLogic.InvalidationLogic());
  88 + } else if (cacheMode.isReplicated()) {
  89 + return componentType.cast(new ClusteringDependentLogic.ReplicationLogic());
86 90 } else {
87 91 return componentType.cast(new ClusteringDependentLogic.DistributionLogic());
88 92 }
168 core/src/main/java/org/infinispan/interceptors/ReplicationInterceptor.java
@@ -23,21 +23,20 @@
23 23 package org.infinispan.interceptors;
24 24
25 25 import org.infinispan.commands.CommandsFactory;
  26 +import org.infinispan.commands.FlagAffectedCommand;
26 27 import org.infinispan.commands.control.LockControlCommand;
27 28 import org.infinispan.commands.read.AbstractDataCommand;
  29 +import org.infinispan.commands.read.GetCacheEntryCommand;
28 30 import org.infinispan.commands.read.GetKeyValueCommand;
29 31 import org.infinispan.commands.remote.ClusteredGetCommand;
30 32 import org.infinispan.commands.tx.CommitCommand;
31 33 import org.infinispan.commands.tx.PrepareCommand;
32 34 import org.infinispan.commands.tx.RollbackCommand;
33   -import org.infinispan.commands.write.ClearCommand;
34   -import org.infinispan.commands.write.PutKeyValueCommand;
35   -import org.infinispan.commands.write.PutMapCommand;
36   -import org.infinispan.commands.write.RemoveCommand;
37   -import org.infinispan.commands.write.ReplaceCommand;
38   -import org.infinispan.commands.write.WriteCommand;
  35 +import org.infinispan.commands.write.*;
39 36 import org.infinispan.configuration.cache.CacheMode;
40 37 import org.infinispan.configuration.cache.Configurations;
  38 +import org.infinispan.container.DataContainer;
  39 +import org.infinispan.container.EntryFactory;
41 40 import org.infinispan.container.entries.CacheEntry;
42 41 import org.infinispan.container.entries.InternalCacheEntry;
43 42 import org.infinispan.container.entries.InternalCacheValue;
@@ -45,6 +44,7 @@
45 44 import org.infinispan.context.InvocationContext;
46 45 import org.infinispan.context.impl.LocalTxInvocationContext;
47 46 import org.infinispan.context.impl.TxInvocationContext;
  47 +import org.infinispan.distribution.ch.ConsistentHash;
48 48 import org.infinispan.factories.annotations.Inject;
49 49 import org.infinispan.factories.annotations.Start;
50 50 import org.infinispan.interceptors.base.BaseRpcInterceptor;
@@ -58,13 +58,11 @@
58 58 import org.infinispan.statetransfer.StateTransferManager;
59 59 import org.infinispan.transaction.LockingMode;
60 60 import org.infinispan.transaction.xa.GlobalTransaction;
  61 +import org.infinispan.util.concurrent.locks.LockManager;
61 62 import org.infinispan.util.logging.Log;
62 63 import org.infinispan.util.logging.LogFactory;
63 64
64   -import java.util.ArrayList;
65   -import java.util.List;
66   -import java.util.Map;
67   -import java.util.Set;
  65 +import java.util.*;
68 66 import java.util.concurrent.TimeoutException;
69 67
70 68 /**
@@ -75,10 +73,14 @@
75 73 */
76 74 public class ReplicationInterceptor extends BaseRpcInterceptor {
77 75
78   - protected CommandsFactory cf;
  76 + private CommandsFactory cf;
79 77
  78 + private EntryFactory entryFactory;
  79 + private LockManager lockManager;
  80 + private DataContainer dataContainer;
80 81 private StateTransferManager stateTransferManager;
81 82
  83 + private boolean needReliableReturnValues;
82 84 private boolean isPessimisticCache;
83 85
84 86 private static final Log log = LogFactory.getLog(ReplicationInterceptor.class);
@@ -90,14 +92,18 @@ protected Log getLog() {
90 92 }
91 93
92 94 @Inject
93   - public void init(CommandsFactory cf, StateTransferManager stateTransferManager) {
  95 + public void init(CommandsFactory cf, EntryFactory entryFactory, DataContainer dataContainer, LockManager lockManager, StateTransferManager stateTransferManager) {
94 96 this.cf = cf;
  97 + this.entryFactory = entryFactory;
  98 + this.dataContainer = dataContainer;
  99 + this.lockManager = lockManager;
95 100 this.stateTransferManager = stateTransferManager;
96 101 }
97 102
98 103 @Start
99 104 public void start() {
100 105 isPessimisticCache = cacheConfiguration.transaction().lockingMode() == LockingMode.PESSIMISTIC;
  106 + needReliableReturnValues = !cacheConfiguration.unsafe().unreliableReturnValues();
101 107 }
102 108
103 109 @Override
@@ -149,7 +155,10 @@ public Object visitGetKeyValueCommand(InvocationContext ctx, GetKeyValueCommand
149 155 // the entry is mapped to the local node.
150 156 if (returnValue == null && ctx.isOriginLocal()) {
151 157 if (needsRemoteGet(ctx, command)) {
152   - returnValue = remoteGet(ctx, command, false);
  158 + returnValue = remoteGet(ctx, command.getKey(), command, false);
  159 + }
  160 + if (returnValue == null) {
  161 + returnValue = localGet(ctx, command.getKey(), false, command);
153 162 }
154 163 }
155 164 return returnValue;
@@ -172,15 +181,43 @@ public Object visitLockControlCommand(TxInvocationContext ctx, LockControlComman
172 181 }
173 182
174 183 private boolean needsRemoteGet(InvocationContext ctx, AbstractDataCommand command) {
175   - Object key = command.getKey();
176   - final CacheEntry entry;
177   - return !command.hasFlag(Flag.CACHE_MODE_LOCAL)
178   - && !command.hasFlag(Flag.SKIP_REMOTE_LOOKUP) //todo [anistor] do we need this? it should normally be used only in distributed mode, never in replicated mode
179   - && !stateTransferManager.getCacheTopology().getReadConsistentHash().isKeyLocalToNode(rpcManager.getAddress(), key)
180   - && ((entry = ctx.lookupEntry(key)) == null || entry.isNull() || entry.isLockPlaceholder());
  184 + if (command.hasFlag(Flag.CACHE_MODE_LOCAL)
  185 + || command.hasFlag(Flag.SKIP_REMOTE_LOOKUP) //todo [anistor] clarify usage of this flag in REPL mode
  186 + || command.hasFlag(Flag.IGNORE_RETURN_VALUES)) {
  187 + return false;
  188 + }
  189 + boolean shouldFetchFromRemote = false;
  190 + CacheEntry entry = ctx.lookupEntry(command.getKey());
  191 + if (entry == null || entry.isNull() || entry.isLockPlaceholder()) {
  192 + Object key = command.getKey();
  193 + ConsistentHash ch = stateTransferManager.getCacheTopology().getReadConsistentHash();
  194 + shouldFetchFromRemote = ctx.isOriginLocal() && !ch.isKeyLocalToNode(rpcManager.getAddress(), key) && !dataContainer.containsKey(key);
  195 + if (!shouldFetchFromRemote) {
  196 + log.tracef("Not doing a remote get for key %s since entry is mapped to current node (%s). Owners are %s", key, rpcManager.getAddress(), ch.locateOwners(key));
  197 + }
  198 + }
  199 + return shouldFetchFromRemote;
  200 + }
  201 +
  202 + private boolean isNeedReliableReturnValues(FlagAffectedCommand command) {
  203 + return !command.hasFlag(Flag.SKIP_REMOTE_LOOKUP)
  204 + && !command.hasFlag(Flag.IGNORE_RETURN_VALUES) && needReliableReturnValues;
  205 + }
  206 +
  207 + /**
  208 + * For conditional operations (replace, remove, put if absent) Used only for optimistic transactional caches, to solve the following situation:
  209 + * <pre>
  210 + * - node A (owner, tx originator) does a successful replace
  211 + * - the actual value changes
  212 + * - tx commits. The value is applied on A (the check was performed at operation time) but is not applied on
  213 + * B (check is performed at commit time).
  214 + * In such situations (optimistic caches) the remote conditional command should not re-check the old value.
  215 + * </pre>
  216 + */
  217 + private boolean ignorePreviousValueOnBackup(WriteCommand command, InvocationContext ctx) {
  218 + return ctx.isOriginLocal() && command.isSuccessful();
181 219 }
182 220
183   - //todo [anistor] need to revise these methods
184 221 /**
185 222 * This method retrieves an entry from a remote cache.
186 223 * <p/>
@@ -190,12 +227,12 @@ private boolean needsRemoteGet(InvocationContext ctx, AbstractDataCommand comman
190 227 *
191 228 *
192 229 * @param ctx invocation context
  230 + * @param key
193 231 * @param command
194 232 * @return value of a remote get, or null
195 233 * @throws Throwable if there are problems
196 234 */
197   - private Object remoteGet(InvocationContext ctx, AbstractDataCommand command, boolean isWrite) throws Throwable {
198   - Object key = command.getKey();
  235 + private Object remoteGet(InvocationContext ctx, Object key, FlagAffectedCommand command, boolean isWrite) throws Throwable {
199 236 if (trace) {
200 237 log.tracef("Key %s is not yet available on %s, so we may need to look elsewhere", key, rpcManager.getAddress());
201 238 }
@@ -211,16 +248,28 @@ private Object remoteGet(InvocationContext ctx, AbstractDataCommand command, boo
211 248 ((TxInvocationContext) ctx).addAffectedKey(key);
212 249 }
213 250
214   - return ice != null ? ice.getValue() : null;
  251 + if (ice != null) {
  252 + if (!ctx.replaceValue(key, ice.getValue())) {
  253 + if (isWrite) {
  254 + lockAndWrap(ctx, key, ice, command);
  255 + } else {
  256 + ctx.putLookedUpEntry(key, ice);
  257 + }
  258 + }
  259 + return ice.getValue();
  260 + }
  261 + return null;
  262 + }
  263 +
  264 + protected Address getPrimaryOwner() {
  265 + return stateTransferManager.getCacheTopology().getReadConsistentHash().getMembers().get(0);
215 266 }
216 267
217 268 private InternalCacheEntry retrieveFromRemoteSource(Object key, InvocationContext ctx, boolean acquireRemoteLock, Set<Flag> flags) {
218 269 GlobalTransaction gtx = acquireRemoteLock ? ((TxInvocationContext)ctx).getGlobalTransaction() : null;
219 270 ClusteredGetCommand get = cf.buildClusteredGetCommand(key, flags, acquireRemoteLock, gtx);
220 271
221   - List<Address> targets = new ArrayList<Address>(stateTransferManager.getCacheTopology().getReadConsistentHash().locateOwners(key));
222   - // if any of the recipients has left the cluster since the command was issued, just don't wait for its response
223   - targets.retainAll(rpcManager.getTransport().getMembers());
  272 + List<Address> targets = Collections.singletonList(getPrimaryOwner());
224 273 ResponseFilter filter = new ClusteredGetResponseValidityFilter(targets, rpcManager.getAddress());
225 274 Map<Address, Response> responses = rpcManager.invokeRemotely(targets, get, ResponseMode.WAIT_FOR_VALID_RESPONSE,
226 275 cacheConfiguration.clustering().sync().replTimeout(), true, filter);
@@ -237,36 +286,77 @@ private InternalCacheEntry retrieveFromRemoteSource(Object key, InvocationContex
237 286 return null;
238 287 }
239 288
  289 + private Object localGet(InvocationContext ctx, Object key, boolean isWrite, FlagAffectedCommand command) throws Throwable {
  290 + InternalCacheEntry ice = dataContainer.get(key);
  291 + if (ice != null) {
  292 + if (!ctx.replaceValue(key, ice.getValue())) {
  293 + if (isWrite)
  294 + lockAndWrap(ctx, key, ice, command);
  295 + else
  296 + ctx.putLookedUpEntry(key, ice);
  297 + }
  298 + return command instanceof GetCacheEntryCommand ? ice : ice.getValue();
  299 + }
  300 + return null;
  301 + }
  302 +
  303 + private void lockAndWrap(InvocationContext ctx, Object key, InternalCacheEntry ice, FlagAffectedCommand command) throws InterruptedException {
  304 + if (isPessimisticCache && rpcManager.getAddress().equals(getPrimaryOwner())) {
  305 + boolean skipLocking = hasSkipLocking(command);
  306 + long lockTimeout = getLockAcquisitionTimeout(command, skipLocking);
  307 + lockManager.acquireLock(ctx, key, lockTimeout, skipLocking);
  308 + }
  309 + entryFactory.wrapEntryForPut(ctx, key, ice, false, command);
  310 + }
  311 +
240 312 @Override
241 313 public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
242   - return handleCrudMethod(ctx, command);
  314 + return handleCrudMethod(ctx, command, !ctx.isOriginLocal());
243 315 }
244 316
245 317 @Override
246 318 public Object visitPutMapCommand(InvocationContext ctx, PutMapCommand command) throws Throwable {
247   - return handleCrudMethod(ctx, command);
  319 + return handleCrudMethod(ctx, command, true);
248 320 }
249 321
250 322 @Override
251 323 public Object visitRemoveCommand(InvocationContext ctx, RemoveCommand command) throws Throwable {
252   - return handleCrudMethod(ctx, command);
  324 + try {
  325 + return handleCrudMethod(ctx, command, !ctx.isOriginLocal());
  326 + } finally {
  327 + if (ignorePreviousValueOnBackup(command, ctx)) {
  328 + // the command that will execute remotely must ignore previous values
  329 + command.setIgnorePreviousValue(true);
  330 + }
  331 + }
253 332 }
254 333
255 334 @Override
256 335 public Object visitClearCommand(InvocationContext ctx, ClearCommand command) throws Throwable {
257   - return handleCrudMethod(ctx, command);
  336 + return handleCrudMethod(ctx, command, true);
258 337 }
259 338
260 339 @Override
261 340 public Object visitReplaceCommand(InvocationContext ctx, ReplaceCommand command) throws Throwable {
262   - return handleCrudMethod(ctx, command);
  341 + try {
  342 + return handleCrudMethod(ctx, command, !ctx.isOriginLocal());
  343 + } finally {
  344 + if (ignorePreviousValueOnBackup(command, ctx)) {
  345 + // the command that will execute remotely must ignore previous values
  346 + command.setIgnorePreviousValue(true);
  347 + }
  348 + }
263 349 }
264 350
265 351 /**
266 352 * If we are within one transaction we won't do any replication as replication would only be performed at commit
267 353 * time. If the operation didn't originate locally we won't do any replication either.
268 354 */
269   - private Object handleCrudMethod(final InvocationContext ctx, final WriteCommand command) throws Throwable {
  355 + private Object handleCrudMethod(InvocationContext ctx, WriteCommand command, boolean skipRemoteGet) throws Throwable {
  356 + if (!skipRemoteGet) {
  357 + remoteGetBeforeWrite(ctx, command);
  358 + }
  359 +
270 360 // FIRST pass this call up the chain. Only if it succeeds (no exceptions) locally do we attempt to replicate.
271 361 final Object returnValue = invokeNextInterceptor(ctx, command);
272 362 if (!isLocalModeForced(command) && command.isSuccessful() && ctx.isOriginLocal() && !ctx.isInTxScope()) {
@@ -275,4 +365,18 @@ private Object handleCrudMethod(final InvocationContext ctx, final WriteCommand
275 365 return returnValue;
276 366 }
277 367
  368 + private void remoteGetBeforeWrite(InvocationContext ctx, WriteCommand command) throws Throwable {
  369 + if (command instanceof AbstractDataCommand && (isNeedReliableReturnValues(command) || command.isConditional())) {
  370 + AbstractDataCommand singleKeyCommand = (AbstractDataCommand) command;
  371 +
  372 + Object returnValue = null;
  373 + // get it remotely if we do not have it yet
  374 + if (needsRemoteGet(ctx, singleKeyCommand)) {
  375 + returnValue = remoteGet(ctx, singleKeyCommand.getKey(), singleKeyCommand, true);
  376 + }
  377 + if (returnValue == null) {
  378 + localGet(ctx, singleKeyCommand.getKey(), true, command);
  379 + }
  380 + }
  381 + }
278 382 }
5 core/src/main/java/org/infinispan/interceptors/VersionedReplicationInterceptor.java
@@ -54,10 +54,11 @@ protected void broadcastPrepare(TxInvocationContext context, PrepareCommand comm
54 54 // is then stored in the transactional context to be used during the commit phase.
55 55 // However if the current node is already the coordinator, then we fall back to "normal" ReplicationInterceptor
56 56 // logic for this step.
57   - if (!rpcManager.getTransport().isCoordinator()) {
  57 + Address primaryOwner = getPrimaryOwner();
  58 + if (!primaryOwner.equals(rpcManager.getAddress())) {
58 59 setVersionsSeenOnPrepareCommand((VersionedPrepareCommand) command, context);
59 60 Map<Address, Response> resps = rpcManager.invokeRemotely(null, command, true, true);
60   - Response r = resps.get(rpcManager.getTransport().getCoordinator()); // We only really care about the coordinator's response.
  61 + Response r = resps.get(primaryOwner); // We only really care about the coordinator's response.
61 62 readVersionsFromResponse(r, context.getCacheTransaction());
62 63 } else {
63 64 super.broadcastPrepare(context, command);
2  core/src/main/java/org/infinispan/interceptors/base/CommandInterceptor.java
@@ -76,7 +76,7 @@ protected Log getLog() {
76 76 }
77 77
78 78 @Inject
79   - private void injectConfiguration(Configuration configuration) {
  79 + public void injectConfiguration(Configuration configuration) {
80 80 this.cacheConfiguration = configuration;
81 81 }
82 82
124 core/src/main/java/org/infinispan/interceptors/locking/ClusteringDependentLogic.java
@@ -40,16 +40,14 @@
40 40 import org.infinispan.remoting.rpc.RpcManager;
41 41 import org.infinispan.remoting.transport.Address;
42 42 import org.infinispan.statetransfer.StateTransferLock;
  43 +import org.infinispan.statetransfer.StateTransferManager;
43 44 import org.infinispan.transaction.WriteSkewHelper;
44 45 import org.infinispan.transaction.xa.CacheTransaction;
45   -import org.infinispan.util.logging.Log;
46   -import org.infinispan.util.logging.LogFactory;
47 46
48 47 import java.util.Collection;
49 48
50 49 import static org.infinispan.transaction.WriteSkewHelper.performWriteSkewCheckAndReturnNewVersions;
51 50
52   -// todo [anistor] need to review this for NBST
53 51 /**
54 52 * Abstractization for logic related to different clustering modes: replicated or distributed. This implements the <a
55 53 * href="http://en.wikipedia.org/wiki/Bridge_pattern">Bridge</a> pattern as described by the GoF: this plays the role of
@@ -61,8 +59,6 @@
61 59 @Scope(Scopes.NAMED_CACHE)
62 60 public interface ClusteringDependentLogic {
63 61
64   - Log log = LogFactory.getLog(ClusteringDependentLogic.class);
65   -
66 62 boolean localNodeIsOwner(Object key);
67 63
68 64 boolean localNodeIsPrimaryOwner(Object key);
@@ -77,10 +73,18 @@
77 73
78 74 Address getAddress();
79 75
80   - public static abstract class AbstractClusteringDependentLogic implements ClusteringDependentLogic {
  76 + public static abstract class AbstractClusteringDependentLogic implements ClusteringDependentLogic {
  77 +
  78 + protected DataContainer dataContainer;
81 79
82 80 protected CacheNotifier notifier;
83 81
  82 + @Inject
  83 + public void init(DataContainer dataContainer, CacheNotifier notifier) {
  84 + this.dataContainer = dataContainer;
  85 + this.notifier = notifier;
  86 + }
  87 +
84 88 protected void notifyCommitEntry(boolean created, boolean removed,
85 89 boolean evicted, CacheEntry entry, InvocationContext ctx) {
86 90 // Eviction has no notion of pre/post event since 4.2.0.ALPHA4.
@@ -109,13 +113,61 @@ protected void notifyCommitEntry(boolean created, boolean removed,
109 113 }
110 114
111 115 /**
112   - * This logic is used when a changing a key affects all the nodes in the cluster, e.g. int the replicated,
113   - * invalidated and local cache modes.
  116 + * This logic is used in local mode caches.
114 117 */
115   - public static final class AllNodesLogic extends AbstractClusteringDependentLogic {
  118 + public static class LocalLogic extends AbstractClusteringDependentLogic {
  119 +
  120 + @Override
  121 + public boolean localNodeIsOwner(Object key) {
  122 + return true;
  123 + }
  124 +
  125 + @Override
  126 + public boolean localNodeIsPrimaryOwner(Object key) {
  127 + return true;
  128 + }
  129 +
  130 + @Override
  131 + public Address getPrimaryOwner(Object key) {
  132 + throw new IllegalStateException("Cannot invoke this method for local caches");
  133 + }
  134 +
  135 + @Override
  136 + public Collection<Address> getOwners(Collection<Object> keys) {
  137 + return null;
  138 + }
  139 +
  140 + @Override
  141 + public Address getAddress() {
  142 + return null;
  143 + }
  144 +
  145 + @Override
  146 + public void commitEntry(CacheEntry entry, EntryVersion newVersion, boolean skipOwnershipCheck, InvocationContext ctx) {
  147 + // Cache flags before they're reset
  148 + // TODO: Can the reset be done after notification instead?
  149 + boolean created = entry.isCreated();
  150 + boolean removed = entry.isRemoved();
  151 + boolean evicted = entry.isEvicted();
116 152
117   - private DataContainer dataContainer;
  153 + entry.commit(dataContainer, newVersion);
  154 +
  155 + // Notify after events if necessary
  156 + notifyCommitEntry(created, removed, evicted, entry, ctx);
  157 + }
  158 +
  159 + @Override
  160 + public EntryVersionsMap createNewVersionsAndCheckForWriteSkews(VersionGenerator versionGenerator, TxInvocationContext context, VersionedPrepareCommand prepareCommand) {
  161 + throw new IllegalStateException("Cannot invoke this method for local caches");
  162 + }
  163 + }
118 164
  165 + /**
  166 + * This logic is used in invalidation mode caches.
  167 + */
  168 + public static class InvalidationLogic extends AbstractClusteringDependentLogic {
  169 +
  170 + private StateTransferManager stateTransferManager;
119 171 private RpcManager rpcManager;
120 172
121 173 private static final WriteSkewHelper.KeySpecificLogic keySpecificLogic = new WriteSkewHelper.KeySpecificLogic() {
@@ -126,27 +178,24 @@ public boolean performCheckOnKey(Object key) {
126 178 };
127 179
128 180 @Inject
129   - public void init(DataContainer dc, RpcManager rpcManager, CacheNotifier notifier) {
130   - this.dataContainer = dc;
  181 + public void init(RpcManager rpcManager, StateTransferManager stateTransferManager) {
131 182 this.rpcManager = rpcManager;
132   - this.notifier = notifier;
  183 + this.stateTransferManager = stateTransferManager;
133 184 }
134 185
135 186 @Override
136 187 public boolean localNodeIsOwner(Object key) {
137   - return true;
  188 + return stateTransferManager.getCacheTopology().getWriteConsistentHash().isKeyLocalToNode(rpcManager.getAddress(), key);
138 189 }
139 190
140 191 @Override
141 192 public boolean localNodeIsPrimaryOwner(Object key) {
142   - return rpcManager == null || rpcManager.getTransport().isCoordinator();
  193 + return stateTransferManager.getCacheTopology().getWriteConsistentHash().locatePrimaryOwner(key).equals(rpcManager.getAddress());
143 194 }
144 195
145 196 @Override
146 197 public Address getPrimaryOwner(Object key) {
147   - if (rpcManager == null)
148   - throw new IllegalStateException("Cannot invoke this method for local caches");
149   - return rpcManager.getTransport().getCoordinator();
  198 + return stateTransferManager.getCacheTopology().getWriteConsistentHash().locatePrimaryOwner(key);
150 199 }
151 200
152 201 @Override
@@ -165,7 +214,7 @@ public void commitEntry(CacheEntry entry, EntryVersion newVersion, boolean skipO
165 214
166 215 @Override
167 216 public Collection<Address> getOwners(Collection<Object> keys) {
168   - return null;
  217 + return null; //todo [anistor] should I actually return this based on current CH?
169 218 }
170 219
171 220 @Override
@@ -176,7 +225,7 @@ public Address getAddress() {
176 225 @Override
177 226 public EntryVersionsMap createNewVersionsAndCheckForWriteSkews(VersionGenerator versionGenerator, TxInvocationContext context, VersionedPrepareCommand prepareCommand) {
178 227 // In REPL mode, this happens if we are the coordinator.
179   - if (rpcManager.getTransport().isCoordinator()) {
  228 + if (stateTransferManager.getCacheTopology().getReadConsistentHash().getMembers().get(0).equals(rpcManager.getAddress())) {
180 229 // Perform a write skew check on each entry.
181 230 EntryVersionsMap uv = performWriteSkewCheckAndReturnNewVersions(prepareCommand, dataContainer,
182 231 versionGenerator, context,
@@ -194,10 +243,35 @@ public EntryVersionsMap createNewVersionsAndCheckForWriteSkews(VersionGenerator
194 243 }
195 244 }
196 245
197   - public static final class DistributionLogic extends AbstractClusteringDependentLogic {
  246 + /**
  247 + * This logic is used in replicated mode caches.
  248 + */
  249 + public static class ReplicationLogic extends InvalidationLogic {
  250 +
  251 + private StateTransferLock stateTransferLock;
  252 +
  253 + @Inject
  254 + public void init(StateTransferLock stateTransferLock) {
  255 + this.stateTransferLock = stateTransferLock;
  256 + }
  257 +
  258 + @Override
  259 + public void commitEntry(CacheEntry entry, EntryVersion newVersion, boolean skipOwnershipCheck, InvocationContext ctx) {
  260 + stateTransferLock.acquireSharedTopologyLock();
  261 + try {
  262 + super.commitEntry(entry, newVersion, skipOwnershipCheck, ctx);
  263 + } finally {
  264 + stateTransferLock.releaseSharedTopologyLock();
  265 + }
  266 + }
  267 + }
  268 +
  269 + /**
  270 + * This logic is used in distributed mode caches.
  271 + */
  272 + public static class DistributionLogic extends AbstractClusteringDependentLogic {
198 273
199 274 private DistributionManager dm;
200   - private DataContainer dataContainer;
201 275 private Configuration configuration;
202 276 private RpcManager rpcManager;
203 277 private StateTransferLock stateTransferLock;
@@ -210,14 +284,12 @@ public boolean performCheckOnKey(Object key) {
210 284 };
211 285
212 286 @Inject
213   - public void init(DistributionManager dm, DataContainer dataContainer, Configuration configuration,
214   - RpcManager rpcManager, StateTransferLock stateTransferLock, CacheNotifier notifier) {
  287 + public void init(DistributionManager dm, Configuration configuration,
  288 + RpcManager rpcManager, StateTransferLock stateTransferLock) {
215 289 this.dm = dm;
216   - this.dataContainer = dataContainer;
217 290 this.configuration = configuration;
218 291 this.rpcManager = rpcManager;
219 292 this.stateTransferLock = stateTransferLock;
220   - this.notifier = notifier;
221 293 }
222 294
223 295 @Override
5 core/src/test/java/org/infinispan/distribution/InvalidationFailureTest.java
@@ -22,17 +22,12 @@
22 22 */
23 23 package org.infinispan.distribution;
24 24
25   -import org.infinispan.affinity.KeyAffinityService;
26   -import org.infinispan.affinity.KeyAffinityServiceFactory;
27   -import org.infinispan.affinity.RndKeyGenerator;
28 25 import org.infinispan.config.Configuration;
29 26 import org.infinispan.manager.CacheContainer;
30 27 import org.infinispan.test.MultipleCacheManagersTest;
31 28 import org.testng.annotations.Test;
32 29
33 30 import javax.transaction.Transaction;
34   -import java.util.concurrent.ExecutorService;
35   -import java.util.concurrent.Executors;
36 31
37 32 /**
38 33 * @author Mircea.Markus@jboss.com
152 core/src/test/java/org/infinispan/interceptors/ReplicationInterceptorTest.java
... ... @@ -0,0 +1,152 @@
  1 +/*
  2 + * Copyright 2012 Red Hat, Inc. and/or its affiliates.
  3 + *
  4 + * This is free software; you can redistribute it and/or modify it
  5 + * under the terms of the GNU Lesser General Public License as
  6 + * published by the Free Software Foundation; either version 2.1 of
  7 + * the License, or (at your option) any later version.
  8 + *
  9 + * This software is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 + * Lesser General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser General Public
  15 + * License along with this library; if not, write to the Free Software
  16 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17 + * 02110-1301 USA
  18 + */
  19 +
  20 +package org.infinispan.interceptors;
  21 +
  22 +import org.infinispan.commands.CommandsFactory;
  23 +import org.infinispan.commands.read.GetKeyValueCommand;
  24 +import org.infinispan.commands.remote.ClusteredGetCommand;
  25 +import org.infinispan.configuration.cache.CacheMode;
  26 +import org.infinispan.configuration.cache.Configuration;
  27 +import org.infinispan.configuration.cache.ConfigurationBuilder;
  28 +import org.infinispan.configuration.global.GlobalConfigurationBuilder;
  29 +import org.infinispan.container.DataContainer;
  30 +import org.infinispan.container.EntryFactory;
  31 +import org.infinispan.container.entries.ImmortalCacheValue;
  32 +import org.infinispan.context.Flag;
  33 +import org.infinispan.context.InvocationContext;
  34 +import org.infinispan.distribution.TestAddress;
  35 +import org.infinispan.distribution.ch.ReplicatedConsistentHash;
  36 +import org.infinispan.interceptors.base.CommandInterceptor;
  37 +import org.infinispan.remoting.responses.Response;
  38 +import org.infinispan.remoting.responses.SuccessfulResponse;
  39 +import org.infinispan.remoting.rpc.ResponseFilter;
  40 +import org.infinispan.remoting.rpc.ResponseMode;
  41 +import org.infinispan.remoting.rpc.RpcManager;
  42 +import org.infinispan.remoting.transport.Address;
  43 +import org.infinispan.remoting.transport.Transport;
  44 +import org.infinispan.statetransfer.StateTransferManager;
  45 +import org.infinispan.topology.CacheTopology;
  46 +import org.infinispan.transaction.xa.GlobalTransaction;
  47 +import org.infinispan.util.concurrent.locks.LockManager;
  48 +import org.infinispan.util.logging.Log;
  49 +import org.infinispan.util.logging.LogFactory;
  50 +import org.mockito.invocation.InvocationOnMock;
  51 +import org.mockito.stubbing.Answer;
  52 +import org.testng.annotations.Test;
  53 +
  54 +import java.util.*;
  55 +
  56 +import static org.junit.Assert.assertEquals;
  57 +import static org.mockito.Matchers.*;
  58 +import static org.mockito.Mockito.mock;
  59 +import static org.mockito.Mockito.when;
  60 +
  61 +/**
  62 + * Tests ReplicationInterceptor.
  63 + *
  64 + * @author anistor@redhat.com
  65 + * @since 5.2
  66 + */
  67 +@Test(groups = "functional", testName = "interceptors.ReplicationInterceptorTest")
  68 +public class ReplicationInterceptorTest {
  69 +
  70 + private static final Log log = LogFactory.getLog(ReplicationInterceptorTest.class);
  71 +
  72 + public void testRemoteGetForGetKeyValueCommand() throws Throwable {
  73 + ConfigurationBuilder cb = new ConfigurationBuilder();
  74 + cb.clustering().cacheMode(CacheMode.REPL_SYNC);
  75 +
  76 + GlobalConfigurationBuilder gcb = GlobalConfigurationBuilder.defaultClusteredBuilder();
  77 + Configuration configuration = cb.build();
  78 +
  79 + ReplicationInterceptor replInterceptor = new ReplicationInterceptor();
  80 + CommandInterceptor nextInterceptor = mock(CommandInterceptor.class);
  81 + when(nextInterceptor.visitGetKeyValueCommand(any(InvocationContext.class), any(GetKeyValueCommand.class))).thenReturn(null);
  82 + replInterceptor.setNext(nextInterceptor);
  83 +
  84 + CommandsFactory commandsFactory = mock(CommandsFactory.class);
  85 + when(commandsFactory.buildClusteredGetCommand(any(Object.class), any(Set.class), anyBoolean(), any(GlobalTransaction.class))).thenAnswer(new Answer<ClusteredGetCommand>() {
  86 + @Override
  87 + public ClusteredGetCommand answer(InvocationOnMock invocation) {
  88 + Object key = invocation.getArguments()[0];
  89 + Set<Flag> flags = (Set<Flag>) invocation.getArguments()[1];
  90 + boolean acquireRemoteLock = (Boolean) invocation.getArguments()[2];
  91 + GlobalTransaction gtx = (GlobalTransaction) invocation.getArguments()[3];
  92 + return new ClusteredGetCommand(key, "cache1", flags, acquireRemoteLock, gtx);
  93 + }
  94 + });
  95 +
  96 + EntryFactory entryFactory = mock(EntryFactory.class);
  97 + DataContainer dataContainer = mock(DataContainer.class);
  98 + LockManager lockManager = mock(LockManager.class);
  99 + StateTransferManager stateTransferManager = mock(StateTransferManager.class);
  100 +
  101 + TestAddress A = new TestAddress(0, "A");
  102 + TestAddress B = new TestAddress(1, "B");
  103 + List<Address> members1 = new ArrayList<Address>();
  104 + List<Address> members2 = new ArrayList<Address>();
  105 + members1.add(A);
  106 + members2.add(A);
  107 + members2.add(B);
  108 + ReplicatedConsistentHash readCh = new ReplicatedConsistentHash(members1);
  109 + ReplicatedConsistentHash writeCh = new ReplicatedConsistentHash(members2);
  110 + final CacheTopology cacheTopology = new CacheTopology(1, readCh, writeCh);
  111 + when(stateTransferManager.getCacheTopology()).thenAnswer(new Answer<CacheTopology>() {
  112 + @Override
  113 + public CacheTopology answer(InvocationOnMock invocation) {
  114 + return cacheTopology;
  115 + }
  116 + });
  117 + replInterceptor.init(commandsFactory, entryFactory, dataContainer, lockManager, stateTransferManager);
  118 + RpcManager rpcManager = mock(RpcManager.class);
  119 + Transport transport = mock(Transport.class);
  120 + when(rpcManager.getAddress()).thenReturn(B);
  121 + when(rpcManager.getTransport()).thenReturn(transport);
  122 + when(transport.getMembers()).thenReturn(members2);
  123 + replInterceptor.inject(rpcManager);
  124 + replInterceptor.injectConfiguration(configuration);
  125 +
  126 + when(rpcManager.invokeRemotely(any(Collection.class), any(ClusteredGetCommand.class), any(ResponseMode.class),
  127 + anyLong(), anyBoolean(), any(ResponseFilter.class))).thenAnswer(new Answer<Map<Address, Response>>() {
  128 + @Override
  129 + public Map<Address, Response> answer(InvocationOnMock invocation) {
  130 + Collection<Address> recipients = (Collection<Address>) invocation.getArguments()[0];
  131 + ClusteredGetCommand clusteredGetCommand = (ClusteredGetCommand) invocation.getArguments()[1];
  132 + if (clusteredGetCommand.getKey().equals("theKey")) {
  133 + Map<Address, Response> results = new HashMap<Address, Response>();
  134 + for (Address recipient : recipients) {
  135 + results.put(recipient, SuccessfulResponse.create(new ImmortalCacheValue("theValue")));
  136 + }
  137 + return results;
  138 + }
  139 + return Collections.emptyMap();
  140 + }
  141 + });
  142 +
  143 + InvocationContext ctx = mock(InvocationContext.class);
  144 + when(ctx.isOriginLocal()).thenReturn(true);
  145 + when(ctx.isInTxScope()).thenReturn(false);
  146 +
  147 + GetKeyValueCommand getKeyValueCommand = new GetKeyValueCommand("theKey", null);
  148 +
  149 + Object retVal = replInterceptor.visitGetKeyValueCommand(ctx, getKeyValueCommand);
  150 + assertEquals("theValue", retVal);
  151 + }
  152 +}
9 core/src/test/java/org/infinispan/replication/BaseReplicatedAPITest.java
@@ -39,7 +39,7 @@
39 39 import org.infinispan.test.MultipleCacheManagersTest;
40 40 import org.testng.annotations.Test;
41 41
42   -@Test(groups = "functional", testName = "replication.BaseReplicatedAPITest")
  42 +@Test(groups = "functional")
43 43 public abstract class BaseReplicatedAPITest extends MultipleCacheManagersTest {
44 44
45 45 protected boolean isSync;
@@ -150,7 +150,7 @@ public void testRemoveIfPresent() {
150 150 waitForRpc(cache2);
151 151
152 152 assert cache1.get("key") == null;
153   - assert cache2.get("key").equals("value2");
  153 + assert cache2.get("key") == null;
154 154 }
155 155
156 156 public void testClear() {
@@ -214,8 +214,9 @@ public void testReplaceWithOldVal() {
214 214 cache1.replace("key", "valueN", "value1");
215 215 waitForRpc(cache2);
216 216
217   - assert cache1.get("key").equals("value1");
218   - assert cache2.get("key").equals("value2");
  217 + // the replace executed identically on both of them
  218 + assertEquals("value1", cache1.get("key"));
  219 + assertEquals("value1", cache2.get("key"));
219 220 }
220 221
221 222 public void testLocalOnlyClear() {
15 core/src/test/java/org/infinispan/statetransfer/BaseReplStateTransferConsistencyTest.java
@@ -120,7 +120,6 @@ public void testPutIfAbsent() throws Exception {
120 120 testStateTransferConsistency(Operation.PUT_IF_ABSENT);
121 121 }
122 122
123   - @Test(enabled = false) // disabled due to ISPN-2647
124 123 public void testReplace() throws Exception {
125 124 testStateTransferConsistency(Operation.REPLACE);
126 125 }
@@ -222,9 +221,9 @@ protected Object handleDefault(InvocationContext ctx, VisitableCommand cmd) thro
222 221 TestingUtil.waitForRehashToComplete(cache(0), cache(1), cache(2));
223 222
224 223 // at this point state transfer is fully done
225   - log.infof("Data container of NodeA has %d keys: %s", dc0.size(), dc0.keySet());
226   - log.infof("Data container of NodeB has %d keys: %s", dc1.size(), dc1.keySet());
227   - log.infof("Data container of NodeC has %d keys: %s", dc2.size(), dc2.keySet());
  224 + log.infof("Data container of NodeA has %d keys: %s", dc0.size(), dc0.entrySet());
  225 + log.infof("Data container of NodeB has %d keys: %s", dc1.size(), dc1.entrySet());
  226 + log.infof("Data container of NodeC has %d keys: %s", dc2.size(), dc2.entrySet());
228 227
229 228 if (op == Operation.CLEAR || op == Operation.REMOVE) {
230 229 // caches should be empty. check that no keys were revived by an inconsistent state transfer
@@ -253,9 +252,9 @@ protected Object handleDefault(InvocationContext ctx, VisitableCommand cmd) thro
253 252 }
254 253
255 254 private void assertValue(int cacheIndex, int key, String expectedValue) {
256   - InternalCacheEntry object = cache(cacheIndex).getAdvancedCache().getDataContainer().get(key);
257   - assertNotNull(object);
258   - assertEquals(expectedValue, object.getValue());
259   - assertEquals(expectedValue, cache(cacheIndex).get(key));
  255 + InternalCacheEntry ice = cache(cacheIndex).getAdvancedCache().getDataContainer().get(key);
  256 + assertNotNull("Found null on cache " + cacheIndex, ice);
  257 + assertEquals("Did not find the expected value on cache " + cacheIndex, expectedValue, ice.getValue());
  258 + assertEquals("Did not find the expected value on cache " + cacheIndex, expectedValue, cache(cacheIndex).get(key));
260 259 }
261 260 }
40 core/src/test/java/org/infinispan/statetransfer/ReplNonTxOperationsDuringStateTransferTest.java
... ... @@ -0,0 +1,40 @@
  1 +/*
  2 + * JBoss, Home of Professional Open Source
  3 + * Copyright 2013 Red Hat Inc. and/or its affiliates and other
  4 + * contributors as indicated by the @author tags. All rights reserved.
  5 + * See the copyright.txt in the distribution for a full listing of
  6 + * individual contributors.
  7 + *
  8 + * This is free software; you can redistribute it and/or modify it
  9 + * under the terms of the GNU Lesser General Public License as
  10 + * published by the Free Software Foundation; either version 2.1 of
  11 + * the License, or (at your option) any later version.
  12 + *
  13 + * This software is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 + * Lesser General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU Lesser General Public
  19 + * License along with this software; if not, write to the Free
  20 + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  21 + * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  22 + */
  23 +package org.infinispan.statetransfer;
  24 +
  25 +import org.infinispan.configuration.cache.CacheMode;
  26 +import org.infinispan.test.fwk.CleanupAfterMethod;
  27 +import org.testng.annotations.Test;
  28 +
  29 +/**
  30 + * @author anistor@redhat.com
  31 + * @since 5.2
  32 + */
  33 +@Test(groups = "functional", testName = "statetransfer.ReplNonTxOperationsDuringStateTransferTest")
  34 +@CleanupAfterMethod
  35 +public class ReplNonTxOperationsDuringStateTransferTest extends BaseOperationsDuringStateTransferTest {
  36 +
  37 + public ReplNonTxOperationsDuringStateTransferTest() {
  38 + super(CacheMode.REPL_SYNC, false, false, false);
  39 + }
  40 +}
40 core/src/test/java/org/infinispan/statetransfer/ReplOptimisticTxOperationsDuringStateTransferTest.java
... ... @@ -0,0 +1,40 @@
  1 +/*
  2 + * JBoss, Home of Professional Open Source
  3 + * Copyright 2013 Red Hat Inc. and/or its affiliates and other
  4 + * contributors as indicated by the @author tags. All rights reserved.
  5 + * See the copyright.txt in the distribution for a full listing of
  6 + * individual contributors.
  7 + *
  8 + * This is free software; you can redistribute it and/or modify it
  9 + * under the terms of the GNU Lesser General Public License as
  10 + * published by the Free Software Foundation; either version 2.1 of
  11 + * the License, or (at your option) any later version.
  12 + *
  13 + * This software is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 + * Lesser General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU Lesser General Public
  19 + * License along with this software; if not, write to the Free
  20 + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  21 + * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  22 + */
  23 +package org.infinispan.statetransfer;
  24 +
  25 +import org.infinispan.configuration.cache.CacheMode;
  26 +import org.infinispan.test.fwk.CleanupAfterMethod;
  27 +import org.testng.annotations.Test;
  28 +
  29 +/**
  30 + * @author anistor@redhat.com
  31 + * @since 5.2
  32 + */
  33 +@Test(groups = "functional", testName = "statetransfer.ReplOptimisticTxOperationsDuringStateTransferTest")
  34 +@CleanupAfterMethod
  35 +public class ReplOptimisticTxOperationsDuringStateTransferTest extends BaseOperationsDuringStateTransferTest {
  36 +
  37 + public ReplOptimisticTxOperationsDuringStateTransferTest() {
  38 + super(CacheMode.REPL_SYNC, true, true, false);
  39 + }
  40 +}
57 core/src/test/java/org/infinispan/statetransfer/ReplPessimisticOperationsDuringStateTransferTest.java
... ... @@ -0,0 +1,57 @@
  1 +/*
  2 + * JBoss, Home of Professional Open Source
  3 + * Copyright 2013 Red Hat Inc. and/or its affiliates and other
  4 + * contributors as indicated by the @author tags. All rights reserved.
  5 + * See the copyright.txt in the distribution for a full listing of
  6 + * individual contributors.
  7 + *
  8 + * This is free software; you can redistribute it and/or modify it
  9 + * under the terms of the GNU Lesser General Public License as
  10 + * published by the Free Software Foundation; either version 2.1 of
  11 + * the License, or (at your option) any later version.
  12 + *
  13 + * This software is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 + * Lesser General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU Lesser General Public
  19 + * License along with this software; if not, write to the Free
  20 + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  21 + * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  22 + */
  23 +package org.infinispan.statetransfer;
  24 +
  25 +import org.infinispan.configuration.cache.CacheMode;
  26 +import org.infinispan.test.fwk.CleanupAfterMethod;
  27 +import org.testng.annotations.Test;
  28 +
  29 +/**
  30 + * @author anistor@redhat.com
  31 + * @since 5.2
  32 + */
  33 +@Test(groups = "functional", testName = "statetransfer.ReplPessimisticOperationsDuringStateTransferTest",
  34 + enabled = false, description = "Disabled due to https://issues.jboss.org/browse/ISPN-2847")
  35 +@CleanupAfterMethod
  36 +public class ReplPessimisticOperationsDuringStateTransferTest extends BaseOperationsDuringStateTransferTest {
  37 +
  38 + public ReplPessimisticOperationsDuringStateTransferTest() {
  39 + super(CacheMode.REPL_SYNC, true, false, false);
  40 + }
  41 +
  42 + @Test(enabled = false)
  43 + public void testPut() throws Exception {
  44 + }
  45 +
  46 + @Test(enabled = false)
  47 + public void testReplace() throws Exception {
  48 + }
  49 +
  50 + @Test(enabled = false)
  51 + public void testGet() throws Exception {
  52 + }
  53 +
  54 + @Test(enabled = false)
  55 + public void testRemove() throws Exception {
  56 + }
  57 +}
4 core/src/test/java/org/infinispan/tx/TransactionXaAdapterTmIntegrationTest.java
@@ -68,10 +68,10 @@ public void setUp() {
68 68 txTable.addLocalTransactionMapping(localTx);
69 69
70 70 configuration = new ConfigurationBuilder().build();
71   - TransactionCoordinator txCoordinator = new TransactionCoordinator();
  71 + txCoordinator = new TransactionCoordinator();
72 72 txCoordinator.init(null, null, null, null, configuration);
73 73 xaAdapter = new TransactionXaAdapter(localTx, txTable, null, txCoordinator, null, null,
74   - new ClusteringDependentLogic.AllNodesLogic(), configuration, "");
  74 + new ClusteringDependentLogic.InvalidationLogic(), configuration, "");
75 75 }
76 76 <