/*
* 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.cache30;
import static org.apache.geode.test.dunit.Assert.*;
import java.io.IOException;
import java.util.Iterator;
import java.util.Properties;
import org.apache.geode.cache.AttributesFactory;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.Declarable;
import org.apache.geode.cache.LoaderHelper;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionAttributes;
import org.apache.geode.cache.Scope;
import org.apache.geode.cache.client.Pool;
import org.apache.geode.cache.client.PoolFactory;
import org.apache.geode.cache.client.PoolManager;
import org.apache.geode.cache.server.CacheServer;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.internal.AvailablePortHelper;
import org.apache.geode.test.dunit.DistributedTestUtils;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.Wait;
import org.apache.geode.test.dunit.WaitCriterion;
import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase;
/**
* Provides helper methods for testing clients and servers. This test case was created by
* refactoring methods from ConnectionPoolDUnitTest into this class.
*
* @since GemFire 4.2.1
*/
public abstract class ClientServerTestCase extends JUnit4CacheTestCase {
public static String NON_EXISTENT_KEY = "NON_EXISTENT_KEY";
public static boolean AUTO_LOAD_BALANCE = false;
@Override
public final void postSetUp() throws Exception {
// this makes sure we don't have any connection left over from previous tests
disconnectAllFromDS();
postSetUpClientServerTestCase();
}
protected void postSetUpClientServerTestCase() throws Exception {}
@Override
public final void preTearDownCacheTestCase() throws Exception {
preTearDownClientServerTestCase();
// this makes sure we don't leave anything for the next tests
disconnectAllFromDS();
}
protected void preTearDownClientServerTestCase() throws Exception {}
/**
* Starts a bridge server on the given port
*
* @since GemFire 4.0
*/
public int startBridgeServer(int port) throws IOException {
Cache cache = getCache();
CacheServer bridge = cache.addCacheServer();
bridge.setPort(port);
bridge.setMaxThreads(getMaxThreads());
bridge.start();
return bridge.getPort();
}
/**
* Defaults to 0 which means no selector in server. Subclasses can override setting this to a
* value > 0 to enable selector.
*/
protected int getMaxThreads() {
return 0;
}
/**
* Stops the bridge server that serves up the given cache.
*
* @since GemFire 4.0
*/
public void stopBridgeServers(Cache cache) {
CacheServer bridge = null;
for (Iterator bsI = cache.getCacheServers().iterator(); bsI.hasNext();) {
bridge = (CacheServer) bsI.next();
bridge.stop();
assertFalse(bridge.isRunning());
}
}
/**
* Returns region attributes for a <code>LOCAL</code> region
*/
protected RegionAttributes getRegionAttributes() {
AttributesFactory factory = new AttributesFactory();
factory.setScope(Scope.LOCAL);
return factory.create();
}
public static String createBridgeClientConnection(String host, int[] ports) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < ports.length; i++) {
if (i > 0) {
sb.append(",");
}
sb.append("name" + i + "=");
sb.append(host + ":" + ports[i]);
}
return sb.toString();
}
public static Pool configureConnectionPool(AttributesFactory factory, String host, int port1,
int port2, boolean establish, int redundancy, int connectionsPerServer, String serverGroup,
int pingInterval, int idleTimeout, boolean threadLocalCnxs, int lifetimeTimeout) {
int[] ports;
if (port2 != -1) {
ports = new int[] {port1, port2};
} else {
ports = new int[] {port1};
}
return configureConnectionPool(factory, host, ports, establish, redundancy,
connectionsPerServer, serverGroup, pingInterval, idleTimeout, threadLocalCnxs,
lifetimeTimeout);
}
public static Pool configureConnectionPool(AttributesFactory factory, String host, int port1,
int port2, boolean establish, int redundancy, int connectionsPerServer, String serverGroup,
int pingInterval, int idleTimeout, boolean threadLocalCnxs) {
return configureConnectionPool(factory, host, port1, port2, establish, redundancy,
connectionsPerServer, serverGroup, pingInterval, idleTimeout, threadLocalCnxs,
-2/* lifetimeTimeout */);
}
public static Pool configureConnectionPool(AttributesFactory factory, String host, int port1,
int port2, boolean establish, int redundancy, int connectionsPerServer, String serverGroup,
int pingInterval) {
return configureConnectionPool(factory, host, port1, port2, establish, redundancy,
connectionsPerServer, serverGroup, pingInterval, -1, false);
}
public static Pool configureConnectionPool(AttributesFactory factory, String host, int port1,
int port2, boolean establish, int redundancy, int connectionsPerServer, String serverGroup) {
return configureConnectionPool(factory, host, port1, port2, establish, redundancy,
connectionsPerServer, serverGroup, -1/* pingInterval */);
}
public static Pool configureConnectionPoolWithName(AttributesFactory factory, String host,
int[] ports, boolean establish, int redundancy, int connectionsPerServer, String serverGroup,
String poolName) {
return configureConnectionPoolWithNameAndFactory(factory, host, ports, establish, redundancy,
connectionsPerServer, serverGroup, poolName, PoolManager.createFactory(), -1, -1, false, -2,
-1);
}
public static Pool configureConnectionPoolWithName(AttributesFactory factory, String host,
int[] ports, boolean establish, int redundancy, int connectionsPerServer, String serverGroup,
String poolName, int pingInterval, int idleTimeout, boolean threadLocalCnxs,
int lifetimeTimeout, int statisticInterval) {
return configureConnectionPoolWithNameAndFactory(factory, host, ports, establish, redundancy,
connectionsPerServer, serverGroup, poolName, PoolManager.createFactory(), pingInterval,
idleTimeout, threadLocalCnxs, lifetimeTimeout, statisticInterval);
}
public static Pool configureConnectionPoolWithNameAndFactory(AttributesFactory factory,
String host, int[] ports, boolean establish, int redundancy, int connectionsPerServer,
String serverGroup, String poolName, PoolFactory pf) {
return configureConnectionPoolWithNameAndFactory(factory, host, ports, establish, redundancy,
connectionsPerServer, serverGroup, poolName, pf, -1, -1, false, -2, -1);
}
public static Pool configureConnectionPoolWithNameAndFactory(AttributesFactory factory,
String host, int[] ports, boolean establish, int redundancy, int connectionsPerServer,
String serverGroup, String poolName, PoolFactory pf, int pingInterval, int idleTimeout,
boolean threadLocalCnxs, int lifetimeTimeout, int statisticInterval) {
if (AUTO_LOAD_BALANCE) {
pf.addLocator(host, DistributedTestUtils.getDUnitLocatorPort());
} else {
for (int z = 0; z < ports.length; z++) {
pf.addServer(host, ports[z]);
}
}
// TODO - probably should pass in minConnections rather than connecions per server
if (connectionsPerServer != -1) {
pf.setMinConnections(connectionsPerServer * ports.length);
}
if (threadLocalCnxs) {
pf.setThreadLocalConnections(true);
}
if (pingInterval != -1) {
pf.setPingInterval(pingInterval);
}
if (idleTimeout != -1) {
pf.setIdleTimeout(idleTimeout);
}
if (statisticInterval != -1) {
pf.setStatisticInterval(statisticInterval);
}
if (lifetimeTimeout != -2) {
pf.setLoadConditioningInterval(lifetimeTimeout);
}
if (establish) {
pf.setSubscriptionEnabled(true);
pf.setSubscriptionRedundancy(redundancy);
pf.setSubscriptionAckInterval(1);
}
if (serverGroup != null) {
pf.setServerGroup(serverGroup);
}
String rpoolName = "testPool";
if (poolName != null) {
rpoolName = poolName;
}
Pool pool = pf.create(rpoolName);
if (factory != null) {
factory.setPoolName(rpoolName);
}
return pool;
}
public static Pool configureConnectionPool(AttributesFactory factory, String host, int[] ports,
boolean establish, int redundancy, int connectionsPerServer, String serverGroup) {
return configureConnectionPool(factory, host, ports, establish, redundancy,
connectionsPerServer, serverGroup, -1/* pingInterval */, -1/* idleTimeout */,
false/* threadLocalCnxs */, -2/* lifetimeTimeout */);
}
public static Pool configureConnectionPool(AttributesFactory factory, String host, int[] ports,
boolean establish, int redundancy, int connectionsPerServer, String serverGroup,
int pingInterval, int idleTimeout, boolean threadLocalCnxs, int lifetimeTimeout) {
return configureConnectionPoolWithName(factory, host, ports, establish, redundancy,
connectionsPerServer, serverGroup, null/* poolName */, pingInterval, idleTimeout,
threadLocalCnxs, lifetimeTimeout, -1);
}
public static Pool configureConnectionPool(AttributesFactory factory, String host, int[] ports,
boolean establish, int redundancy, int connectionsPerServer, String serverGroup,
int pingInterval, int idleTimeout, boolean threadLocalCnxs, int lifetimeTimeout,
int statisticInterval) {
return configureConnectionPoolWithName(factory, host, ports, establish, redundancy,
connectionsPerServer, serverGroup, null/* poolName */, pingInterval, idleTimeout,
threadLocalCnxs, lifetimeTimeout, statisticInterval);
}
/*
* protected static InternalDistributedMember findDistributedMember() { DM dm =
* ((InternalDistributedSystem)
* InternalDistributedSystem.getAnyInstance()).getDistributionManager(); return
* dm.getDistributionManagerId(); }
*/
protected static DistributedMember getMemberId() {
WaitCriterion w = new WaitCriterion() {
public String description() {
return "client never finished connecting: " + getSystemStatic().getMemberId();
}
public boolean done() {
// getLogWriter().warning("checking member id " + system.getMemberId() +
// " for member " + system.getDistributedMember() + " hash " +
// System.identityHashCode(system.getDistributedMember()));
return getSystemStatic().getDistributedMember().getPort() > 0;
}
};
int waitMillis = 20000;
int interval = 100;
boolean throwException = true;
Wait.waitForCriterion(w, waitMillis, interval, throwException);
return getSystemStatic().getDistributedMember();
}
protected static DistributedMember getDistributedMember() {
DistributedSystem system = InternalDistributedSystem.getAnyInstance();
return system.getDistributedMember();
}
protected static Properties getSystemProperties() {
DistributedSystem system = InternalDistributedSystem.getAnyInstance();
return system.getProperties();
}
public static class CacheServerCacheLoader extends TestCacheLoader implements Declarable {
public CacheServerCacheLoader() {}
@Override
public Object load2(LoaderHelper helper) {
if (helper.getArgument() instanceof Integer) {
try {
Thread.sleep(((Integer) helper.getArgument()).intValue());
} catch (InterruptedException ugh) {
fail("interrupted");
}
}
Object ret = helper.getKey();
if (ret instanceof String) {
if (ret != null && ret.equals(NON_EXISTENT_KEY))
return null;// return null
}
return ret;
}
public void init(Properties props) {}
}
public final static String BridgeServerKey = "BridgeServerKey";
/**
* Create a server that has a value for every key queried and a unique key/value in the specified
* Region that uniquely identifies each instance.
*
* @param vm the VM on which to create the server
* @param rName the name of the Region to create on the server
* @param port the TCP port on which the server should listen
*/
public void createBridgeServer(VM vm, final String rName, final int port) {
vm.invoke(new CacheSerializableRunnable("Create Region on Server") {
@Override
public void run2() {
try {
AttributesFactory factory = new AttributesFactory();
factory.setScope(Scope.DISTRIBUTED_ACK); // can't be local since used with
// registerInterest
factory.setCacheLoader(new CacheServerCacheLoader());
beginCacheXml();
createRootRegion(rName, factory.create());
startBridgeServer(port);
finishCacheXml(rName + "-" + port);
Region region = getRootRegion(rName);
assertNotNull(region);
region.put(BridgeServerKey, new Integer(port)); // A unique key/value to identify the
// BridgeServer
} catch (Exception e) {
getSystem().getLogWriter().severe(e);
fail("Failed to start CacheServer " + e);
}
}
});
}
public static int[] createUniquePorts(int numToCreate) {
return AvailablePortHelper.getRandomAvailableTCPPorts(numToCreate);
}
}