/** * Expects any commands. The moment a single command is detected, the {@link #waitForRpc()} command will be * unblocked. */ public void expectAny() { expect(c -> true); }
public void expect(Predicate<VisitableCommand>... predicates) { expect(Arrays.asList(predicates)); }
public void expect(Class<? extends VisitableCommand> expectedCommand) { expect(Collections.singleton(expectedCommand::isInstance)); }
public void expect(Predicate<VisitableCommand> predicate) { expect(Collections.singleton(predicate)); }
/** * Expects a specific set of commands. {@link #waitForRpc()} will block until all of these commands are detected. * * @param expectedCommands commands to expect */ public void expect(Class<? extends VisitableCommand>... expectedCommands) { Function<Class<? extends VisitableCommand>, Predicate<VisitableCommand>> predicateGenerator = clazz -> clazz::isInstance; expect(Stream.of(expectedCommands).map(predicateGenerator).collect(Collectors.toList())); }
private void waitForInvalidations() { for (Map.Entry<Address, List<InvalidateL1Command>> expected : expectedL1Invalidations.entrySet()) { Address address = expected.getKey(); ReplListener replListener = listenerLookup.get(address); List<InvalidateL1Command> list = expected.getValue(); if (!list.isEmpty()) { log.tracef("Waiting for invalidations on %s: %s", address, list); synchronized (list) { for (InvalidateL1Command cmd : list) { replListener.expect(InvalidateL1Command.class); } list.clear(); } replListener.waitForRpc(); } } }
/** * Expects any commands, within transactional scope (i.e., as a payload to a PrepareCommand). If the cache mode is * synchronous, a CommitCommand is expected as well. */ @SuppressWarnings("unchecked") public void expectAnyWithTx() { List<Class<? extends VisitableCommand>> cmdsToExpect = new ArrayList<Class<? extends VisitableCommand>>(2); cmdsToExpect.add(PrepareCommand.class); //this is because for async replication we have an 1pc transaction if (cache.getCacheConfiguration().clustering().cacheMode().isSynchronous()) cmdsToExpect.add(CommitCommand.class); expect(cmdsToExpect.toArray(new Class[cmdsToExpect.size()])); }
/** * Expects a specific set of commands, within transactional scope (i.e., as a payload to a PrepareCommand). If the * cache mode is synchronous, a CommitCommand is expected as well. * * @param commands commands to expect (not counting transaction boundary commands like PrepareCommand and * CommitCommand) */ @SuppressWarnings("unchecked") public void expectWithTx(Class<? extends VisitableCommand>... commands) { List<Class<? extends VisitableCommand>> cmdsToExpect = new ArrayList<>(); cmdsToExpect.add(PrepareCommand.class); if (commands != null) cmdsToExpect.addAll(Arrays.asList(commands)); //this is because for async replication we have an 1pc transaction if (cache.getCacheConfiguration().clustering().cacheMode().isSynchronous()) cmdsToExpect.add(CommitCommand.class); expect(cmdsToExpect.toArray(new Class[cmdsToExpect.size()])); }
@Override protected void asyncWait(Object key, Predicate<VisitableCommand> command) { if (key == null) { // test all caches. for (ReplListener rl : r) rl.expect(command); for (ReplListener rl : r) rl.waitForRpc(); } else { for (Cache<?, ?> c : getOwners(key)) { listenerLookup.get(address(c)).expect(command); listenerLookup.get(address(c)).waitForRpc(); } } waitForInvalidations(); }
@Override protected void asyncWaitOnPrimary(Object key, Class<? extends VisitableCommand> command) { assert key != null; Cache<?, ?> primary = getFirstOwner(key); listenerLookup.get(address(primary)).expect(command); listenerLookup.get(address(primary)).waitForRpc(); waitForInvalidations(); } }
public void testPutIfAbsent() { AdvancedCache<String, String> cache1 = advancedCache(0,"invalidation"); AdvancedCache<String, String> cache2 = advancedCache(1,"invalidation"); assert null == cache2.withFlags(CACHE_MODE_LOCAL).put("key", "value"); assert cache2.get("key").equals("value"); assert cache1.get("key") == null; replListener(cache2).expect(InvalidateCommand.class); cache1.putIfAbsent("key", "value"); replListener(cache2).waitForRpc(); assert cache1.get("key").equals("value"); assert cache2.get("key") == null; assert null == cache2.withFlags(CACHE_MODE_LOCAL).put("key", "value2"); assert cache1.get("key").equals("value"); assert cache2.get("key").equals("value2"); cache1.putIfAbsent("key", "value3"); assert cache1.get("key").equals("value"); assert cache2.get("key").equals("value2"); // should not invalidate cache2!! }
public void testRemoveIfPresent() { AdvancedCache<String, String> cache1 = advancedCache(0,"invalidation"); AdvancedCache<String, String> cache2 = advancedCache(1,"invalidation"); cache1.withFlags(CACHE_MODE_LOCAL).put("key", "value1"); cache2.withFlags(CACHE_MODE_LOCAL).put("key", "value2"); assert cache1.get("key").equals("value1"); assert cache2.get("key").equals("value2"); assert !cache1.remove("key", "value"); assert cache1.get("key").equals("value1") : "Should not remove"; assert cache2.get("key").equals("value2") : "Should not evict"; replListener(cache2).expect(InvalidateCommand.class); cache1.remove("key", "value1"); replListener(cache2).waitForRpc(); assert cache1.get("key") == null; assert cache2.get("key") == null; }
public void testClear() { AdvancedCache<String, String> cache1 = advancedCache(0,"invalidation"); AdvancedCache<String, String> cache2 = advancedCache(1,"invalidation"); cache1.withFlags(CACHE_MODE_LOCAL).put("key", "value1"); cache2.withFlags(CACHE_MODE_LOCAL).put("key", "value2"); assert cache1.get("key").equals("value1"); assert cache2.get("key").equals("value2"); replListener(cache2).expect(ClearCommand.class); cache1.clear(); replListener(cache2).waitForRpc(); assert cache1.get("key") == null; assert cache2.get("key") == null; }
public void testReplaceWithOldVal() { AdvancedCache<String, String> cache1 = advancedCache(0,"invalidation"); AdvancedCache<String, String> cache2 = advancedCache(1,"invalidation"); cache2.withFlags(CACHE_MODE_LOCAL).put("key", "value2"); assert cache1.get("key") == null; assert cache2.get("key").equals("value2"); assert !cache1.replace("key", "valueOld", "value1"); // should do nothing since there is nothing to replace on cache1 assert cache1.get("key") == null; assert cache2.get("key").equals("value2"); assert null == cache1.withFlags(CACHE_MODE_LOCAL).put("key", "valueN"); assert !cache1.replace("key", "valueOld", "value1"); // should do nothing since there is nothing to replace on cache1 assert cache1.get("key").equals("valueN"); assert cache2.get("key").equals("value2"); replListener(cache2).expect(InvalidateCommand.class); assert cache1.replace("key", "valueN", "value1"); replListener(cache2).waitForRpc(); assert cache1.get("key").equals("value1"); assert cache2.get("key") == null; }
public void testReplace() { AdvancedCache<String, String> cache1 = advancedCache(0,"invalidation"); AdvancedCache<String, String> cache2 = advancedCache(1,"invalidation"); cache2.withFlags(CACHE_MODE_LOCAL).put("key", "value2"); assert cache1.get("key") == null; assert cache2.get("key").equals("value2"); assert null == cache1.replace("key", "value1"); // should do nothing since there is nothing to replace on cache1 assert cache1.get("key") == null; assert cache2.get("key").equals("value2"); assert null == cache1.withFlags(CACHE_MODE_LOCAL).put("key", "valueN"); replListener(cache2).expect(InvalidateCommand.class); cache1.replace("key", "value1"); replListener(cache2).waitForRpc(); assert cache1.get("key").equals("value1"); assert cache2.get("key") == null; }
public void testPut() { initAndTest(); Cache<Object, String> nonOwner = getFirstNonOwner(KEY1); Cache<Object, String> owner = getOwners(KEY1)[0]; Collection<ReplListener> listeners = new ArrayList<ReplListener>(); // Put an object in from a non-owner, this will cause an L1 record to be created there nonOwner.put(KEY1, "foo"); assertNull(nonOwner.getAdvancedCache().getDataContainer().get(KEY1)); Assert.assertEquals(owner.getAdvancedCache().getDataContainer().get(KEY1).getValue(), "foo"); // Check that all nodes (except the one we put to) are notified // but only if the transport is multicast-capable if (owner.getAdvancedCache().getRpcManager().getTransport().isMulticastCapable()) { for (Cache<Object, String> c : getNonOwners(KEY1)) { ReplListener rl = new ReplListener(c); rl.expect(InvalidateL1Command.class); listeners.add(rl); log.debugf("Added nonowner %s", c); } } else { ReplListener rl = new ReplListener(nonOwner); rl.expect(InvalidateL1Command.class); listeners.add(rl); } // Put an object into an owner, this will cause the L1 records for this key to be invalidated owner.put(KEY1, "bar"); for (ReplListener rl : listeners) { rl.waitForRpc(); } Assert.assertNull(nonOwner.getAdvancedCache().getDataContainer().get(KEY1)); }
public void testPut() { initAndTest(); Cache<Object, String> nonOwner = getFirstNonOwner(KEY1); Cache<Object, String> owner = getOwners(KEY1)[0]; Cache<Object, String> secondNonOwner = getSecondNonOwner(KEY1); Collection<ReplListener> listeners = new ArrayList<ReplListener>(); // Put an object in from a non-owner, this will cause an L1 record to be created there nonOwner.put(KEY1, "foo"); assertNull(nonOwner.getAdvancedCache().getDataContainer().get(KEY1)); assertEquals(owner.getAdvancedCache().getDataContainer().get(KEY1).getValue(), "foo"); // Request from another non-owner so that we can get an invalidation command there assertEquals(secondNonOwner.get(KEY1), "foo"); assertEquals(secondNonOwner.getAdvancedCache().getDataContainer().get(KEY1).getValue(), "foo"); // Check that the non owners are notified ReplListener rl = new ReplListener(nonOwner); rl.expect(InvalidateL1Command.class); listeners.add(rl); rl = new ReplListener(secondNonOwner); rl.expect(InvalidateL1Command.class); listeners.add(rl); // Put an object into an owner, this will cause the L1 records for this key to be invalidated owner.put(KEY1, "bar"); for (ReplListener r : listeners) { r.waitForRpc(); } Assert.assertNull(secondNonOwner.getAdvancedCache().getDataContainer().get(KEY1)); Assert.assertNull(nonOwner.getAdvancedCache().getDataContainer().get(KEY1)); }
public void testDeleteNonExistentEntry() throws Exception { if (!isSync) { return; } AdvancedCache<String, String> cache1 = advancedCache(0,"invalidationTx"); AdvancedCache<String, String> cache2 = advancedCache(1,"invalidationTx"); assertNull("Should be null", cache1.get("key")); assertNull("Should be null", cache2.get("key")); log.info("before..."); replListener(cache2).expect(InvalidateCommand.class); cache1.put("key", "value"); log.info("after..."); replListener(cache2).waitForRpc(); assertEquals("value", cache1.get("key")); assertNull("Should be null", cache2.get("key")); // OK, here's the real test TransactionManager tm = TestingUtil.getTransactionManager(cache2); replListener(cache1).expect(InvalidateCommand.class); // invalidates always happen outside of a tx tm.begin(); // Remove an entry that doesn't exist in cache2 cache2.remove("key"); tm.commit(); replListener(cache1).waitForRpc(); assert cache1.get("key") == null; assert cache2.get("key") == null; }
public void testResurrectEntry() throws Exception { AdvancedCache<String, String> cache1 = advancedCache(0,"invalidation"); AdvancedCache<String, String> cache2 = advancedCache(1,"invalidation"); replListener(cache2).expect(InvalidateCommand.class); cache1.put("key", "value"); replListener(cache2).waitForRpc(); assertEquals("value", cache1.get("key")); assertEquals(null, cache2.get("key")); replListener(cache2).expect(InvalidateCommand.class); cache1.put("key", "newValue"); replListener(cache2).waitForRpc(); assertEquals("newValue", cache1.get("key")); assertEquals(null, cache2.get("key")); replListener(cache2).expect(InvalidateCommand.class); assertEquals("newValue", cache1.remove("key")); replListener(cache2).waitForRpc(); assertEquals(null, cache1.get("key")); assertEquals(null, cache2.get("key")); // Restore locally replListener(cache2).expect(InvalidateCommand.class); cache1.put("key", "value"); replListener(cache2).waitForRpc(); assertEquals("value", cache1.get("key")); assertEquals(null, cache2.get("key")); replListener(cache1).expect(InvalidateCommand.class); cache2.put("key", "value2"); replListener(cache1).waitForRpc(); assertEquals("value2", cache2.get("key")); assertEquals(null, cache1.get("key")); }
public void testBasicPropagation() throws Exception { final Cache<String, String> cache1 = cache(0, CACHE_NAME); final Cache<String, String> cache2 = cache(1, CACHE_NAME); assertFalse(cache1.containsKey(key)); assertFalse(cache2.containsKey(key)); ReplListener replListener2 = replListener(cache2); replListener2.expect(PutKeyValueCommand.class); cache1.putForExternalRead(key, value); replListener2.waitForRpc(); // wait for command the finish executing asynchronously eventually(() -> cache1.containsKey(key) && cache2.containsKey(key)); assertEquals("PFER updated cache1", value, cache1.get(key)); assertEquals("PFER propagated to cache2 as expected", value, cache2.get(key)); // replication to cache 1 should NOT happen. cache2.putForExternalRead(key, value + "0"); assertEquals("PFER updated cache2", value, cache2.get(key)); assertEquals("Cache1 should be unaffected", value, cache1.get(key)); }