/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.apache.geode.internal.cache.tier.sockets; import static org.apache.geode.distributed.ConfigurationProperties.*; import static org.apache.geode.test.dunit.Assert.*; import java.io.File; import java.net.InetSocketAddress; import java.net.URISyntaxException; import java.net.URL; import java.util.Enumeration; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Properties; import org.apache.geode.cache.AttributesFactory; import org.apache.geode.cache.Cache; import org.apache.geode.cache.CacheFactory; import org.apache.geode.cache.DataPolicy; import org.apache.geode.cache.Declarable; import org.apache.geode.cache.EntryEvent; import org.apache.geode.cache.RegionAttributes; import org.apache.geode.cache.Scope; import org.apache.geode.cache.client.ClientCache; import org.apache.geode.cache.client.ClientCacheFactory; import org.apache.geode.cache.client.ClientRegionShortcut; import org.apache.geode.cache.client.Pool; import org.apache.geode.cache.client.PoolManager; import org.apache.geode.cache.client.internal.PoolImpl; import org.apache.geode.cache.query.CqEvent; import org.apache.geode.cache.server.CacheServer; import org.apache.geode.cache.util.CacheListenerAdapter; import org.apache.geode.cache.util.CqListenerAdapter; import org.apache.geode.distributed.DistributedSystem; import org.apache.geode.distributed.internal.DistributionConfig; import org.apache.geode.internal.AvailablePort; import org.apache.geode.internal.cache.GemFireCacheImpl; import org.apache.geode.internal.cache.PoolFactoryImpl; import org.apache.geode.internal.cache.PoolFactoryImpl.PoolAttributes; import org.apache.geode.test.dunit.Assert; import org.apache.geode.test.dunit.DistributedTestUtils; import org.apache.geode.test.dunit.IgnoredException; import org.apache.geode.test.dunit.LogWriterUtils; import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase; public class CacheServerTestUtil extends JUnit4DistributedTestCase { private static Cache cache = null; private static IgnoredException expected; private static PoolImpl pool = null; protected final static int TYPE_CREATE = 0; protected final static int TYPE_UPDATE = 1; protected final static int TYPE_INVALIDATE = 2; protected final static int TYPE_DESTROY = 3; public static void createCacheClient(Pool poolAttr, String regionName) throws Exception { createCacheClient(poolAttr, regionName, getClientProperties(), Boolean.FALSE); } public static void createCacheClient(Pool poolAttr, String regionName, Properties dsProperties) throws Exception { createCacheClient(poolAttr, regionName, dsProperties, Boolean.FALSE); } public static void createClientCache(Pool poolAttr, String regionName) throws Exception { createClientCache(poolAttr, regionName, getClientProperties()); } public static void createClientCache(Pool poolAttr, String regionName, Properties dsProperties) throws Exception { ClientCacheFactory ccf = new ClientCacheFactory(dsProperties); if (poolAttr != null) { ccf.setPoolFreeConnectionTimeout(poolAttr.getFreeConnectionTimeout()) .setPoolLoadConditioningInterval(poolAttr.getLoadConditioningInterval()) .setPoolSocketBufferSize(poolAttr.getSocketBufferSize()) .setPoolMinConnections(poolAttr.getMinConnections()) .setPoolMaxConnections(poolAttr.getMaxConnections()) .setPoolIdleTimeout(poolAttr.getIdleTimeout()) .setPoolPingInterval(poolAttr.getPingInterval()) .setPoolStatisticInterval(poolAttr.getStatisticInterval()) .setPoolRetryAttempts(poolAttr.getRetryAttempts()) .setPoolThreadLocalConnections(poolAttr.getThreadLocalConnections()) .setPoolReadTimeout(poolAttr.getReadTimeout()) .setPoolSubscriptionEnabled(poolAttr.getSubscriptionEnabled()) .setPoolPRSingleHopEnabled(poolAttr.getPRSingleHopEnabled()) .setPoolSubscriptionRedundancy(poolAttr.getSubscriptionRedundancy()) .setPoolSubscriptionMessageTrackingTimeout( poolAttr.getSubscriptionMessageTrackingTimeout()) .setPoolSubscriptionAckInterval(poolAttr.getSubscriptionAckInterval()) .setPoolServerGroup(poolAttr.getServerGroup()) .setPoolMultiuserAuthentication(poolAttr.getMultiuserAuthentication()); for (InetSocketAddress locator : poolAttr.getLocators()) { ccf.addPoolLocator(locator.getHostName(), locator.getPort()); } for (InetSocketAddress server : poolAttr.getServers()) { ccf.addPoolServer(server.getHostName(), server.getPort()); } } new CacheServerTestUtil().createClientCache(dsProperties, ccf); ClientCache cc = (ClientCache) cache; cc.createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY).create(regionName); pool = (PoolImpl) ((GemFireCacheImpl) cc).getDefaultPool(); } public static void createPool(PoolAttributes poolAttr) throws Exception { Properties props = new Properties(); props.setProperty(MCAST_PORT, "0"); props.setProperty(LOCATORS, ""); DistributedSystem ds = new CacheServerTestUtil().getSystem(props);; PoolFactoryImpl pf = (PoolFactoryImpl) PoolManager.createFactory(); pf.init(poolAttr); PoolImpl p = (PoolImpl) pf.create("CacheServerTestUtil"); AttributesFactory factory = new AttributesFactory(); factory.setScope(Scope.LOCAL); factory.setPoolName(p.getName()); RegionAttributes attrs = factory.create(); pool = p; } public static void createCacheClient(Pool poolAttr, String regionName, Properties dsProperties, Boolean addControlListener) throws Exception { createCacheClient(poolAttr, regionName, dsProperties, addControlListener, null); } public static void createCacheClient(Pool poolAttr, String regionName, Properties dsProperties, Boolean addControlListener, Properties javaSystemProperties) throws Exception { new CacheServerTestUtil().createCache(dsProperties); IgnoredException.addIgnoredException("java.net.ConnectException||java.net.SocketException"); if (javaSystemProperties != null && javaSystemProperties.size() > 0) { Enumeration e = javaSystemProperties.propertyNames(); while (e.hasMoreElements()) { String key = (String) e.nextElement(); System.setProperty(key, javaSystemProperties.getProperty(key)); } } PoolFactoryImpl pf = (PoolFactoryImpl) PoolManager.createFactory(); pf.init(poolAttr); PoolImpl p = (PoolImpl) pf.create("CacheServerTestUtil"); AttributesFactory factory = new AttributesFactory(); factory.setScope(Scope.LOCAL); factory.setPoolName(p.getName()); if (addControlListener.booleanValue()) { factory.addCacheListener(new ControlListener()); } RegionAttributes attrs = factory.create(); cache.createRegion(regionName, attrs); pool = p; } public static void unsetJavaSystemProperties(Properties javaSystemProperties) { if (javaSystemProperties != null && javaSystemProperties.size() > 0) { Enumeration e = javaSystemProperties.propertyNames(); while (e.hasMoreElements()) { String key = (String) e.nextElement(); System.clearProperty(key); } } } public static void createCacheClient(Pool poolAttr, String regionName1, String regionName2) throws Exception { new CacheServerTestUtil().createCache(getClientProperties()); PoolFactoryImpl pf = (PoolFactoryImpl) PoolManager.createFactory(); pf.init(poolAttr); PoolImpl p = (PoolImpl) pf.create("CacheServerTestUtil"); AttributesFactory factory = new AttributesFactory(); factory.setScope(Scope.LOCAL); factory.setPoolName(p.getName()); RegionAttributes attrs = factory.create(); cache.createRegion(regionName1, attrs); cache.createRegion(regionName2, attrs); pool = p; } public static void createCacheClientFromXmlN(URL url, String poolName, String durableClientId, int timeout, Boolean addControlListener) { ClientCacheFactory ccf = new ClientCacheFactory(); try { File cacheXmlFile = new File(url.toURI().getPath()); ccf.set(CACHE_XML_FILE, cacheXmlFile.toURI().getPath()); } catch (URISyntaxException e) { throw new ExceptionInInitializerError(e); } ccf.set(MCAST_PORT, "0"); ccf.set(DURABLE_CLIENT_ID, durableClientId); ccf.set(DURABLE_CLIENT_TIMEOUT, String.valueOf(timeout)); ccf.set(LOG_FILE, "abs_client_system.log"); ccf.set(LOG_LEVEL, LogWriterUtils.getDUnitLogLevel()); cache = (Cache) ccf.create(); expected = IgnoredException .addIgnoredException("java.net.ConnectionException||java.net.SocketException"); pool = (PoolImpl) PoolManager.find(poolName); } public static void createCacheClientFromXml(URL url, String poolName, String durableClientId, int timeout, Boolean addControlListener) { ClientCacheFactory ccf = new ClientCacheFactory(); try { File cacheXmlFile = new File(url.toURI().getPath()); ccf.set(CACHE_XML_FILE, cacheXmlFile.toURI().getPath()); } catch (URISyntaxException e) { throw new ExceptionInInitializerError(e); } ccf.set(MCAST_PORT, "0"); ccf.set(DURABLE_CLIENT_ID, durableClientId); ccf.set(DURABLE_CLIENT_TIMEOUT, String.valueOf(timeout)); cache = (Cache) ccf.create(); expected = IgnoredException .addIgnoredException("java.net.ConnectionException||java.net.SocketException"); pool = (PoolImpl) PoolManager.find(poolName); } public static Integer createCacheServerFromXmlN(URL url) { CacheFactory ccf = new CacheFactory(); try { File cacheXmlFile = new File(url.toURI().getPath()); ccf.set(CACHE_XML_FILE, cacheXmlFile.toURI().getPath()); ccf.set(MCAST_PORT, "0"); ccf.set(LOCATORS, "localhost[" + DistributedTestUtils.getDUnitLocatorPort() + "]"); ccf.set(LOG_FILE, "abs_server_system.log"); ccf.set(LOG_LEVEL, LogWriterUtils.getDUnitLogLevel()); } catch (URISyntaxException e) { throw new ExceptionInInitializerError(e); } cache = ccf.create(); return new Integer(cache.getCacheServers().get(0).getPort()); } public static Integer createCacheServerFromXml(URL url) { CacheFactory ccf = new CacheFactory(); try { File cacheXmlFile = new File(url.toURI().getPath()); ccf.set(CACHE_XML_FILE, cacheXmlFile.toURI().getPath()); ccf.set(MCAST_PORT, "0"); ccf.set(LOCATORS, "localhost[" + DistributedTestUtils.getDUnitLocatorPort() + "]"); } catch (URISyntaxException e) { throw new ExceptionInInitializerError(e); } cache = ccf.create(); return new Integer(cache.getCacheServers().get(0).getPort()); } /** * Create client regions */ public static void createCacheClients(Pool poolAttr, String regionName1, String regionName2, Properties dsProperties) throws Exception { new CacheServerTestUtil().createCache(dsProperties); // Initialize region1 PoolFactoryImpl pf = (PoolFactoryImpl) PoolManager.createFactory(); pf.init(poolAttr); Pool p = pf.create("CacheServerTestUtil1"); AttributesFactory factory1 = new AttributesFactory(); factory1.setScope(Scope.LOCAL); factory1.setPoolName(p.getName()); cache.createRegion(regionName1, factory1.create()); // Initialize region2 p = pf.create("CacheServerTestUtil2"); AttributesFactory factory2 = new AttributesFactory(); factory2.setScope(Scope.LOCAL); factory2.setPoolName(p.getName()); cache.createRegion(regionName2, factory2.create()); } private static Properties getClientProperties() { Properties props = new Properties(); props.setProperty(MCAST_PORT, "0"); props.setProperty(LOCATORS, ""); return props; } private static Properties getClientProperties(boolean durable) { Properties props = new Properties(); props.setProperty(MCAST_PORT, "0"); props.setProperty(LOCATORS, ""); return props; } public static Integer createCacheServer(String regionName, Boolean notifyBySubscription) throws Exception { Properties props = new Properties(); props.setProperty(MCAST_PORT, "0"); props.setProperty(LOCATORS, "localhost[" + DistributedTestUtils.getDUnitLocatorPort() + "]"); new CacheServerTestUtil().createCache(props); AttributesFactory factory = new AttributesFactory(); factory.setScope(Scope.DISTRIBUTED_ACK); factory.setEnableBridgeConflation(true); factory.setDataPolicy(DataPolicy.REPLICATE); RegionAttributes attrs = factory.create(); cache.createRegion(regionName, attrs); CacheServer server1 = cache.addCacheServer(); int port = AvailablePort.getRandomAvailablePort(AvailablePort.SOCKET); server1.setPort(port); server1.setNotifyBySubscription(notifyBySubscription.booleanValue()); server1.start(); return new Integer(server1.getPort()); } public static Integer[] createCacheServerReturnPorts(String regionName, Boolean notifyBySubscription) throws Exception { Properties props = new Properties(); props.setProperty(MCAST_PORT, "0"); props.setProperty(LOCATORS, "localhost[" + DistributedTestUtils.getDUnitLocatorPort() + "]"); new CacheServerTestUtil().createCache(props); AttributesFactory factory = new AttributesFactory(); factory.setScope(Scope.DISTRIBUTED_ACK); factory.setEnableBridgeConflation(true); factory.setDataPolicy(DataPolicy.REPLICATE); RegionAttributes attrs = factory.create(); cache.createRegion(regionName, attrs); CacheServer server1 = cache.addCacheServer(); int port = AvailablePort.getRandomAvailablePort(AvailablePort.SOCKET); server1.setPort(port); server1.setNotifyBySubscription(notifyBySubscription.booleanValue()); server1.start(); return new Integer[] {port, 0}; } public static void createCacheServer(String regionName, Boolean notifyBySubscription, Integer serverPort) throws Exception { Properties props = new Properties(); props.setProperty(MCAST_PORT, "0"); props.setProperty(LOCATORS, "localhost[" + DistributedTestUtils.getDUnitLocatorPort() + "]"); new CacheServerTestUtil().createCache(props); AttributesFactory factory = new AttributesFactory(); factory.setScope(Scope.DISTRIBUTED_ACK); factory.setEnableBridgeConflation(true); factory.setDataPolicy(DataPolicy.REPLICATE); RegionAttributes attrs = factory.create(); cache.createRegion(regionName, attrs); CacheServer server = cache.addCacheServer(); server.setPort(serverPort.intValue()); server.setNotifyBySubscription(notifyBySubscription.booleanValue()); server.start(); } public static Integer createCacheServer(String regionName1, String regionName2, Boolean notifyBySubscription) throws Exception { new CacheServerTestUtil().createCache(new Properties()); AttributesFactory factory = new AttributesFactory(); factory.setScope(Scope.DISTRIBUTED_ACK); factory.setEnableBridgeConflation(true); factory.setDataPolicy(DataPolicy.REPLICATE); RegionAttributes attrs = factory.create(); if (!regionName1.equals("")) { cache.createRegion(regionName1, attrs); } if (!regionName2.equals("")) { cache.createRegion(regionName2, attrs); } CacheServer server1 = cache.addCacheServer(); int port = AvailablePort.getRandomAvailablePort(AvailablePort.SOCKET); server1.setPort(port); server1.setNotifyBySubscription(notifyBySubscription.booleanValue()); server1.start(); return new Integer(server1.getPort()); } private void createCache(Properties props) throws Exception { DistributedSystem ds = getSystem(props); assertNotNull(ds); ds.disconnect(); ds = getSystem(props); cache = CacheFactory.create(ds); assertNotNull(cache); } private void createClientCache(Properties props, ClientCacheFactory ccf) throws Exception { DistributedSystem ds = getSystem(props); assertNotNull(ds); ds.disconnect(); ClientCache cc = ccf.create(); setSystem(props, cc.getDistributedSystem()); cache = (Cache) cc; assertNotNull(cache); expected = IgnoredException .addIgnoredException("java.net.ConnectionException||java.net.SocketException"); } public static void closeCache() { if (expected != null) { expected.remove(); expected = null; } if (cache != null && !cache.isClosed()) { cache.close(); cache.getDistributedSystem().disconnect(); } } public static void closeCache(boolean keepalive) { if (expected != null) { expected.remove(); expected = null; } if (cache != null && !cache.isClosed()) { cache.close(keepalive); cache.getDistributedSystem().disconnect(); } } public static void clearCacheReference() { cache = null; } public static void setClientCrash(boolean crashOnClose) { org.apache.geode.cache.client.internal.ConnectionImpl .setTEST_DURABLE_CLIENT_CRASH(crashOnClose); } public static void disconnectClient() { pool.endpointsNetDownForDUnitTest(); } public static void reconnectClient() { if (pool != null) { pool.endpointsNetUpForDUnitTest(); } } public static void stopCacheServers() { Iterator iter = getCache().getCacheServers().iterator(); if (iter.hasNext()) { CacheServer server = (CacheServer) iter.next(); server.stop(); assertFalse(server.isRunning()); } } public static void restartCacheServers() { Iterator iter = getCache().getCacheServers().iterator(); if (iter.hasNext()) { CacheServer server = (CacheServer) iter.next(); try { server.start(); } catch (Exception e) { Assert.fail("Unexpected exception", e); } assertTrue(server.isRunning()); } } public static Cache getCache() { return cache; } public static PoolImpl getPool() { return pool; } /** * Disables the shuffling of endpoints for a client */ public static void disableShufflingOfEndpoints() { // TODO DISABLE_RANDOM doesn't seem to be used anywhere System.setProperty(DistributionConfig.GEMFIRE_PREFIX + "PoolImpl.DISABLE_RANDOM", "true"); System.setProperty(DistributionConfig.GEMFIRE_PREFIX + "bridge.disableShufflingOfEndpoints", "true"); } /** * Enables the shuffling of endpoints for a client * * @since GemFire 5.7 */ public static void enableShufflingOfEndpoints() { // TODO DISABLE_RANDOM doesn't seem to be used anywhere System.setProperty(DistributionConfig.GEMFIRE_PREFIX + "PoolImpl.DISABLE_RANDOM", "false"); System.setProperty(DistributionConfig.GEMFIRE_PREFIX + "bridge.disableShufflingOfEndpoints", "false"); } /** * Resets the 'disableShufflingOfEndpoints' flag */ public static void resetDisableShufflingOfEndpointsFlag() { System.setProperty(DistributionConfig.GEMFIRE_PREFIX + "bridge.disableShufflingOfEndpoints", "false"); } public static class EventWrapper { public final EntryEvent event; public final Object key; public final Object val; public final Object arg; public final int type; public EventWrapper(EntryEvent ee, int type) { this.event = ee; this.key = ee.getKey(); this.val = ee.getNewValue(); this.arg = ee.getCallbackArgument(); this.type = type; } public boolean isCreate() { return this.type == TYPE_CREATE; } public String toString() { return "EventWrapper: event=" + event + ", type=" + type; } } public static class ControlListener extends CacheListenerAdapter implements Declarable { public final LinkedList<EventWrapper> events = new LinkedList(); public final LinkedList<EntryEvent> createEvents = new LinkedList(); public final LinkedList<EntryEvent> updateEvents = new LinkedList(); public final LinkedList<EntryEvent> destroyEvents = new LinkedList(); public final Object CONTROL_LOCK = new Object(); // added to test creation of cache from xml @Override public void init(Properties props) {} public boolean waitWhileNotEnoughEvents(long sleepMs, int eventCount) { return waitWhileNotEnoughEvents(sleepMs, eventCount, -1); } public boolean waitWhileNotEnoughEvents(long sleepMs, int eventCount, int eventType) { return waitWhileNotEnoughEvents(sleepMs, eventCount, getEvents(eventType)); } public boolean waitWhileNotEnoughEvents(long sleepMs, int eventCount, List eventsToCheck) { long maxMillis = System.currentTimeMillis() + sleepMs; synchronized (this.CONTROL_LOCK) { try { while (eventsToCheck.size() < eventCount) { long waitMillis = maxMillis - System.currentTimeMillis(); if (waitMillis < 10) { break; } this.CONTROL_LOCK.wait(waitMillis); } // while } catch (InterruptedException abort) { fail("interrupted"); } return !eventsToCheck.isEmpty(); } // synchronized } public List getEvents(int eventType) { List eventsToCheck = null; switch (eventType) { case TYPE_CREATE: eventsToCheck = this.createEvents; break; case TYPE_UPDATE: eventsToCheck = this.updateEvents; break; case TYPE_DESTROY: eventsToCheck = this.destroyEvents; break; default: eventsToCheck = this.events; } return eventsToCheck; } @Override public void afterCreate(EntryEvent e) { synchronized (this.CONTROL_LOCK) { this.events.add(new EventWrapper(e, TYPE_CREATE)); this.createEvents.add(e); this.CONTROL_LOCK.notifyAll(); } } @Override public void afterUpdate(EntryEvent e) { synchronized (this.CONTROL_LOCK) { this.events.add(new EventWrapper(e, TYPE_UPDATE)); this.updateEvents.add(e); this.CONTROL_LOCK.notifyAll(); } } @Override public void afterInvalidate(EntryEvent e) { synchronized (this.CONTROL_LOCK) { this.events.add(new EventWrapper(e, TYPE_INVALIDATE)); this.CONTROL_LOCK.notifyAll(); } } @Override public void afterDestroy(EntryEvent e) { synchronized (this.CONTROL_LOCK) { this.events.add(new EventWrapper(e, TYPE_DESTROY)); this.destroyEvents.add(e); this.CONTROL_LOCK.notifyAll(); } } } public static class ControlCqListener extends CqListenerAdapter { public final LinkedList events = new LinkedList(); public final Object CONTROL_LOCK = new Object(); public boolean waitWhileNotEnoughEvents(long sleepMs, int eventCount) { long maxMillis = System.currentTimeMillis() + sleepMs; synchronized (this.CONTROL_LOCK) { try { while (this.events.size() < eventCount) { long waitMillis = maxMillis - System.currentTimeMillis(); if (waitMillis < 10) { break; } this.CONTROL_LOCK.wait(waitMillis); } // while } catch (InterruptedException abort) { fail("interrupted"); } return !this.events.isEmpty(); } // synchronized } @Override public void onEvent(CqEvent aCqEvent) { synchronized (this.CONTROL_LOCK) { this.events.add(aCqEvent); this.CONTROL_LOCK.notifyAll(); } } } }