| /*========================================================================= |
| * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved. |
| * This product is protected by U.S. and international copyright |
| * and intellectual property laws. Pivotal products are covered by |
| * one or more patents listed at http://www.pivotal.io/patents. |
| *========================================================================= |
| */ |
| /** |
| * |
| */ |
| package com.gemstone.gemfire.internal.cache.tier.sockets; |
| |
| import java.util.ArrayList; |
| import java.util.Properties; |
| |
| import com.gemstone.gemfire.cache.CacheFactory; |
| import com.gemstone.gemfire.cache.GemFireCache; |
| import com.gemstone.gemfire.cache.Region; |
| import com.gemstone.gemfire.cache.RegionFactory; |
| import com.gemstone.gemfire.cache.RegionShortcut; |
| import com.gemstone.gemfire.cache.client.ClientCacheFactory; |
| import com.gemstone.gemfire.cache.client.ClientRegionFactory; |
| import com.gemstone.gemfire.cache.client.ClientRegionShortcut; |
| import com.gemstone.gemfire.cache.client.PoolManager; |
| import com.gemstone.gemfire.cache.client.internal.PoolImpl; |
| import com.gemstone.gemfire.cache.server.CacheServer; |
| import com.gemstone.gemfire.distributed.DistributedSystem; |
| import com.gemstone.gemfire.internal.AvailablePort; |
| import com.gemstone.gemfire.internal.cache.FilterProfile; |
| import com.gemstone.gemfire.internal.cache.GemFireCacheImpl; |
| |
| import dunit.DistributedTestCase; |
| import dunit.Host; |
| import dunit.VM; |
| |
| /** |
| * @author ashetkar |
| */ |
| public class UnregisterInterestDUnitTest extends DistributedTestCase { |
| |
| private VM server0 = null; |
| private VM client1 = null; |
| private VM client2 = null; |
| |
| private static GemFireCache cache = null; |
| |
| private static final String regionname = "UnregisterInterestDUnitTest_region"; |
| private static final int all_keys = 0; |
| private static final int list = 1; |
| private static final int regex = 2; |
| private static final int filter = 3; |
| private static final boolean receiveValuesConstant = true; |
| |
| /** |
| * @param name |
| */ |
| public UnregisterInterestDUnitTest(String name) { |
| super(name); |
| } |
| |
| public void setUp() throws Exception { |
| super.setUp(); |
| Host host = Host.getHost(0); |
| server0 = host.getVM(0); |
| client1 = host.getVM(1); |
| client2 = host.getVM(2); |
| |
| int port = (Integer)server0.invoke(UnregisterInterestDUnitTest.class, "createCacheAndStartServer"); |
| client1.invoke(UnregisterInterestDUnitTest.class, "createClientCache", new Object[]{client1.getHost(), port}); |
| client2.invoke(UnregisterInterestDUnitTest.class, "createClientCache", new Object[]{client2.getHost(), port}); |
| } |
| |
| public void tearDown2() throws Exception { |
| closeCache(); |
| server0.invoke(UnregisterInterestDUnitTest.class, "closeCache"); |
| client1.invoke(UnregisterInterestDUnitTest.class, "closeCache"); |
| client2.invoke(UnregisterInterestDUnitTest.class, "closeCache"); |
| } |
| |
| public static void closeCache() { |
| if (cache != null) { |
| cache.close(); |
| cache = null; |
| } |
| } |
| |
| /** |
| * The test starts two clients who register interest in "ALL_KEYS" but close |
| * without unregistering the same. The test then verifies that the server |
| * cleans up the register interest artifacts of these clients properly. |
| * |
| * See bug #47619 |
| * |
| * @throws Exception |
| */ |
| public void testUnregisterInterestAllKeys() throws Exception { |
| server0.invoke(UnregisterInterestDUnitTest.class, "checkRIArtifacts", new Object[] {all_keys, 0, 0}); |
| client1.invoke(UnregisterInterestDUnitTest.class, "registerInterest", new Object[] {all_keys, receiveValuesConstant, null}); |
| client2.invoke(UnregisterInterestDUnitTest.class, "registerInterest", new Object[] {all_keys, !receiveValuesConstant, null}); |
| server0.invoke(UnregisterInterestDUnitTest.class, "checkRIArtifacts", new Object[] {all_keys, 1, 1}); |
| client1.invoke(UnregisterInterestDUnitTest.class, "closeCache"); |
| client2.invoke(UnregisterInterestDUnitTest.class, "closeCache"); |
| server0.invoke(UnregisterInterestDUnitTest.class, "checkRIArtifacts", new Object[] {all_keys, 0, 0}); |
| } |
| |
| /** |
| * The test starts two clients who register interest in a list keys but close |
| * without unregistering the same. The test then verifies that the server |
| * cleans up the register interest artifacts of these clients properly. |
| * |
| * See bug #47619 |
| * |
| * @throws Exception |
| */ |
| public void testUnregisterInterestKeys() throws Exception { |
| server0.invoke(UnregisterInterestDUnitTest.class, "checkRIArtifacts", new Object[] {list, 0, 0}); |
| client1.invoke(UnregisterInterestDUnitTest.class, "registerInterest", new Object[] {list, receiveValuesConstant, new String[]{"key_1", "key_2", "key_3", "key_4", "key_5"}}); |
| client2.invoke(UnregisterInterestDUnitTest.class, "registerInterest", new Object[] {list, !receiveValuesConstant, new String[]{"key_1", "key_2", "key_3", "key_4", "key_5"}}); |
| server0.invoke(UnregisterInterestDUnitTest.class, "checkRIArtifacts", new Object[] {list, 1, 1}); |
| client1.invoke(UnregisterInterestDUnitTest.class, "closeCache"); |
| client2.invoke(UnregisterInterestDUnitTest.class, "closeCache"); |
| server0.invoke(UnregisterInterestDUnitTest.class, "checkRIArtifacts", new Object[] {list, 0, 0}); |
| } |
| |
| /** |
| * The test starts two clients who register interest with regular expression |
| * "[a-z]*[0-9]" but close without unregistering the same. The test then |
| * verifies that the server cleans up the register interest artifacts of these |
| * clients properly. |
| * |
| * See bug #47619 |
| * |
| * @throws Exception |
| */ |
| public void testUnregisterInterestPatterns() throws Exception { |
| server0.invoke(UnregisterInterestDUnitTest.class, "checkRIArtifacts", new Object[] {regex, 0, 0}); |
| client1.invoke(UnregisterInterestDUnitTest.class, "registerInterest", new Object[] {regex, receiveValuesConstant, new String[] {"[a-z]*[0-9]"}}); |
| client2.invoke(UnregisterInterestDUnitTest.class, "registerInterest", new Object[] {regex, !receiveValuesConstant, new String[] {"[a-z]*[0-9]"}}); |
| server0.invoke(UnregisterInterestDUnitTest.class, "checkRIArtifacts", new Object[] {regex, 1, 1}); |
| client1.invoke(UnregisterInterestDUnitTest.class, "closeCache"); |
| client2.invoke(UnregisterInterestDUnitTest.class, "closeCache"); |
| server0.invoke(UnregisterInterestDUnitTest.class, "checkRIArtifacts", new Object[] {regex, 0, 0}); |
| } |
| |
| /** |
| * The test starts two clients who register interest in a common list of keys, |
| * with the option of receiving updates as invalidates. One of the clients |
| * later unregisters its interests in the list of keys. Server then does some |
| * puts on the keys. The test then verifies that the server does send these |
| * updates to the second client while first client sees no events. |
| * |
| * See bug #47717 |
| * |
| * @throws Exception |
| */ |
| public void testUnregisterInterestKeysInvForOneClientDoesNotAffectOtherClient() throws Exception { |
| server0.invoke(UnregisterInterestDUnitTest.class, "checkRIArtifacts", new Object[] {list, 0, 0}); |
| client1.invoke(UnregisterInterestDUnitTest.class, "registerInterest", new Object[] {list, !receiveValuesConstant, new String[] {"key_1", "key_2", "key_3", "key_4", "key_5"}}); |
| client2.invoke(UnregisterInterestDUnitTest.class, "registerInterest", new Object[] {list, !receiveValuesConstant, new String[] {"key_1", "key_2", "key_3", "key_4", "key_5"}}); |
| server0.invoke(UnregisterInterestDUnitTest.class, "checkRIArtifacts", new Object[] {list, 0, 2}); |
| client1.invoke(UnregisterInterestDUnitTest.class, "unregisterInterest", new Object[] {new String[] {"key_1", "key_2", "key_3"}}); |
| server0.invoke(UnregisterInterestDUnitTest.class, "updateKeys", new Object[] {new String[] {"key_1", "key_2", "key_3", "key_4", "key_5"}}); |
| client1.invoke(UnregisterInterestDUnitTest.class, "timedWaitForInvalidates", new Object[] {2}); |
| client2.invoke(UnregisterInterestDUnitTest.class, "timedWaitForInvalidates", new Object[] {5}); |
| } |
| |
| /** |
| * The test starts two clients who register interest with the same regular |
| * expression, with the option of receiving updates as invalidates. One of the |
| * clients later unregisters its interest with the regular expression. Server |
| * then does some puts on the keys. The test then verifies that the server |
| * does send these updates to the second client while the first client sees no |
| * events. |
| * |
| * See bug #47717 |
| * |
| * @throws Exception |
| */ |
| public void testUnregisterInterestRegexInvForOneClientDoesNotAffectOtherClient() throws Exception { |
| server0.invoke(UnregisterInterestDUnitTest.class, "checkRIArtifacts", new Object[] {regex, 0, 0}); |
| client1.invoke(UnregisterInterestDUnitTest.class, "registerInterest", new Object[] {regex, !receiveValuesConstant, new String[] {"[a-z]*[0-9]"}}); |
| client2.invoke(UnregisterInterestDUnitTest.class, "registerInterest", new Object[] {regex, !receiveValuesConstant, new String[] {"[a-z]*[0-9]"}}); |
| server0.invoke(UnregisterInterestDUnitTest.class, "checkRIArtifacts", new Object[] {regex, 0, 2}); |
| client1.invoke(UnregisterInterestDUnitTest.class, "unregisterInterestRegex", new Object[] {new String[] {"[a-z]*[0-9]"}}); |
| server0.invoke(UnregisterInterestDUnitTest.class, "updateKeys", new Object[] {new String[] {"key1", "key2", "key3", "key4", "key5"}}); |
| client1.invoke(UnregisterInterestDUnitTest.class, "timedWaitForInvalidates", new Object[] {0}); |
| client2.invoke(UnregisterInterestDUnitTest.class, "timedWaitForInvalidates", new Object[] {5}); |
| } |
| |
| public void _testUnregisterInterestFilters() throws Exception { |
| |
| } |
| |
| public static void checkRIArtifacts(Integer interestType, Integer value, Integer valueInv) { |
| switch (interestType) { |
| case all_keys: |
| checkAllKeys(value, valueInv); |
| break; |
| case list: |
| checkKeyList(value, valueInv); |
| break; |
| case regex: |
| checkPatterns(value, valueInv); |
| break; |
| case filter: |
| checkFilters(value, valueInv); |
| break; |
| default: |
| fail("Invalid interest type: " + interestType, new IllegalArgumentException("Invalid interest type: " + interestType)); |
| } |
| } |
| |
| public static void checkAllKeys(Integer value, Integer valueInv) { |
| FilterProfile fp = ((GemFireCacheImpl)cache).getFilterProfile(regionname); |
| assertEquals(value.intValue(), fp.getAllKeyClientsSize()); |
| assertEquals(valueInv.intValue(), fp.getAllKeyClientsInvSize()); |
| } |
| |
| public static void checkKeyList(Integer value, Integer valueInv) { |
| FilterProfile fp = ((GemFireCacheImpl)cache).getFilterProfile(regionname); |
| assertEquals(value.intValue(), fp.getKeysOfInterestSize()); |
| assertEquals(valueInv.intValue(), fp.getKeysOfInterestInvSize()); |
| } |
| |
| public static void checkPatterns(Integer value, Integer valueInv) { |
| FilterProfile fp = ((GemFireCacheImpl)cache).getFilterProfile(regionname); |
| assertEquals(value.intValue(), fp.getPatternsOfInterestSize()); |
| assertEquals(valueInv.intValue(), fp.getPatternsOfInterestInvSize()); |
| } |
| |
| public static void checkFilters(Integer value, Integer valueInv) { |
| } |
| |
| public static void registerInterest(Integer interestType, Boolean receiveValues, String[] values) { |
| Region region = cache.getRegion(regionname); |
| switch (interestType) { |
| case all_keys: |
| region.registerInterest("ALL_KEYS", false, receiveValues); |
| break; |
| case list: |
| ArrayList<String> keys = new ArrayList<String>(); |
| for (Object key : values) { |
| keys.add((String)key); |
| } |
| region.registerInterest(keys, false, receiveValues); |
| break; |
| case regex: |
| region.registerInterestRegex((String)values[0], false, receiveValues); |
| break; |
| case filter: |
| break; |
| default: |
| fail("Invalid interest type: " + interestType, new IllegalArgumentException("Invalid interest type: " + interestType)); |
| } |
| } |
| |
| public static void unregisterInterest(String[] keys) { |
| Region region = cache.getRegion(regionname); |
| |
| for (String key : keys) { |
| region.unregisterInterest(key); |
| } |
| } |
| |
| public static void unregisterInterestRegex(String[] patterns) { |
| Region region = cache.getRegion(regionname); |
| |
| for (String pattern : patterns) { |
| region.unregisterInterestRegex(pattern); |
| } |
| } |
| |
| public static void updateKeys(String[] keys) { |
| Region region = cache.getRegion(regionname); |
| |
| for (String key : keys) { |
| region.put(key, key + "_VALUE"); |
| } |
| } |
| |
| public static void timedWaitForInvalidates(Integer invalidates) { |
| final int inv = invalidates; |
| final PoolImpl pool = (PoolImpl) PoolManager.find(cache.getRegion(regionname)); |
| |
| WaitCriterion wc = new WaitCriterion() { |
| @Override |
| public boolean done() { |
| // Client region listeners are not invoked for invalidates that create entries. |
| return pool.getInvalidateCount() == inv; |
| } |
| |
| @Override |
| public String description() { |
| return "Expected to receive " + inv + " invalidates but received " + pool.getInvalidateCount(); |
| } |
| }; |
| DistributedTestCase.waitForCriterion(wc, 10000, 100, true); |
| } |
| |
| public static Integer createCacheAndStartServer() throws Exception { |
| DistributedSystem ds = new UnregisterInterestDUnitTest("UnregisterInterestDUnitTest").getSystem(); |
| ds.disconnect(); |
| Properties props = new Properties(); |
| props.setProperty("locators", ""); |
| props.setProperty("mcast-port", String.valueOf(AvailablePort.getRandomAvailablePort(AvailablePort.JGROUPS))); |
| CacheFactory cf = new CacheFactory(props); |
| cache = cf.create(); |
| RegionFactory rf = ((GemFireCacheImpl)cache).createRegionFactory(RegionShortcut.REPLICATE); |
| rf.create(regionname); |
| CacheServer server = ((GemFireCacheImpl)cache).addCacheServer(); |
| server.setPort(AvailablePort.getRandomAvailablePort(AvailablePort.SOCKET)); |
| server.start(); |
| return server.getPort(); |
| } |
| |
| public static void createClientCache(Host host, Integer port) throws Exception { |
| DistributedSystem ds = new UnregisterInterestDUnitTest("UnregisterInterestDUnitTest").getSystem(); |
| ds.disconnect(); |
| |
| Properties props = new Properties(); |
| props.setProperty("locators", ""); |
| props.setProperty("mcast-port", "0"); |
| ClientCacheFactory ccf = new ClientCacheFactory(props); |
| ccf.setPoolSubscriptionEnabled(true); |
| ccf.addPoolServer(host.getHostName(), port); |
| cache = ccf.create(); |
| ClientRegionFactory crf = ((GemFireCacheImpl)cache).createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY); |
| crf.create(regionname); |
| } |
| } |