/*
* 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.cache.client.internal;
import org.apache.geode.internal.lang.StringUtils;
import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase;
import org.apache.geode.cache.*;
import org.apache.geode.cache.client.Pool;
import org.apache.geode.cache.client.PoolManager;
import org.apache.geode.cache.server.CacheServer;
import org.apache.geode.cache.server.ServerLoadProbe;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.distributed.Locator;
import org.apache.geode.internal.cache.PoolFactoryImpl;
import org.apache.geode.test.dunit.*;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.*;
import static org.apache.geode.distributed.ConfigurationProperties.*;
/**
*
*/
public abstract class LocatorTestBase extends JUnit4DistributedTestCase {
protected static final String CACHE_KEY = "CACHE";
protected static final String LOCATOR_KEY = "LOCATOR";
protected static final String REGION_NAME = "A_REGION";
protected static final String POOL_NAME = "daPool";
protected static final Object CALLBACK_KEY = "callback";
/**
* A map for storing temporary objects in a remote VM so that they can be used between calls.
* Cleared after each test.
*/
protected static final HashMap remoteObjects = new HashMap();
public LocatorTestBase() {
super();
}
@Override
public final void preTearDown() throws Exception {
SerializableRunnable tearDown = new SerializableRunnable("tearDown") {
public void run() {
Locator locator = (Locator) remoteObjects.get(LOCATOR_KEY);
if (locator != null) {
try {
locator.stop();
} catch (Exception e) {
// do nothing
}
}
Cache cache = (Cache) remoteObjects.get(CACHE_KEY);
if (cache != null) {
try {
cache.close();
} catch (Exception e) {
// do nothing
}
}
remoteObjects.clear();
}
};
// We seem to like leaving the DS open if we can for
// speed, but lets at least destroy our cache and locator.
Invoke.invokeInEveryVM(tearDown);
tearDown.run();
postTearDownLocatorTestBase();
}
protected void postTearDownLocatorTestBase() throws Exception {}
protected void startLocator(final String hostName, final int locatorPort,
final String otherLocators) {
final String testName = getUniqueName();
disconnectFromDS();
Properties props = new Properties();
props.setProperty(MCAST_PORT, String.valueOf(0));
props.setProperty(LOCATORS, otherLocators);
props.setProperty(LOG_LEVEL, LogWriterUtils.getDUnitLogLevel());
props.setProperty(ENABLE_CLUSTER_CONFIGURATION, "false");
try {
File logFile = new File(testName + "-locator" + locatorPort + ".log");
InetAddress bindAddr = null;
try {
bindAddr = InetAddress.getByName(hostName);
} catch (UnknownHostException uhe) {
Assert.fail("While resolving bind address ", uhe);
}
Locator locator = Locator.startLocatorAndDS(locatorPort, logFile, bindAddr, props);
remoteObjects.put(LOCATOR_KEY, locator);
} catch (IOException ex) {
Assert.fail("While starting locator on port " + locatorPort, ex);
}
}
protected void startLocatorInVM(final VM vm, final int locatorPort, final String otherLocators) {
vm.invoke(new SerializableRunnable("Create Locator") {
public void run() {
String hostName = NetworkUtils.getServerHostName(vm.getHost());
startLocator(hostName, locatorPort, otherLocators);
}
});
}
protected void stopLocatorInVM(VM vm) {
vm.invoke(new SerializableRunnable("Stop Locator") {
public void run() {
stopLocator();
}
});
}
protected void stopLocator() {
Locator locator = (Locator) remoteObjects.remove(LOCATOR_KEY);
locator.stop();
}
protected int startBridgeServerInVM(VM vm, String[] groups, String locators) {
return startBridgeServerInVM(vm, groups, locators, new String[] {REGION_NAME});
}
protected int addCacheServer(final String[] groups) throws IOException {
Cache cache = (Cache) remoteObjects.get(CACHE_KEY);
CacheServer server = cache.addCacheServer();
server.setPort(0);
server.setGroups(groups);
server.start();
return new Integer(server.getPort());
}
protected int addCacheServerInVM(VM vm, final String[] groups) {
SerializableCallable connect = new SerializableCallable("Add Bridge server") {
public Object call() throws Exception {
return addCacheServer(groups);
}
};
Integer port = (Integer) vm.invoke(connect);
return port.intValue();
}
protected int startBridgeServerInVM(VM vm, final String[] groups, final String locators,
final String[] regions) {
return startBridgeServerInVM(vm, groups, locators, regions, CacheServer.DEFAULT_LOAD_PROBE,
false);
}
protected int startBridgeServerInVM(VM vm, String[] groups, String locators,
boolean useGroupsProperty) {
return startBridgeServerInVM(vm, groups, locators, new String[] {REGION_NAME},
CacheServer.DEFAULT_LOAD_PROBE, useGroupsProperty);
}
protected int startBridgeServerInVM(VM vm, final String[] groups, final String locators,
final String[] regions, final ServerLoadProbe probe, final boolean useGroupsProperty) {
SerializableCallable connect = new SerializableCallable("Start bridge server") {
public Object call() throws IOException {
return startBridgeServer(groups, locators, regions, probe, useGroupsProperty);
}
};
Integer port = (Integer) vm.invoke(connect);
return port.intValue();
}
protected int startBridgeServer(String[] groups, String locators) throws IOException {
return startBridgeServer(groups, locators, new String[] {REGION_NAME});
}
protected int startBridgeServer(final String[] groups, final String locators,
final String[] regions) throws IOException {
return startBridgeServer(groups, locators, regions, CacheServer.DEFAULT_LOAD_PROBE, false);
}
protected int startBridgeServer(final String[] groups, final String locators,
final String[] regions, final ServerLoadProbe probe, final boolean useGroupsProperty)
throws IOException {
Properties props = new Properties();
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, locators);
if (useGroupsProperty) {
props.setProperty(GROUPS, StringUtils.concat(groups, ","));
}
DistributedSystem ds = getSystem(props);
Cache cache = CacheFactory.create(ds);
AttributesFactory factory = new AttributesFactory();
factory.setScope(Scope.DISTRIBUTED_ACK);
factory.setEnableBridgeConflation(true);
factory.setDataPolicy(DataPolicy.REPLICATE);
RegionAttributes attrs = factory.create();
for (int i = 0; i < regions.length; i++) {
cache.createRegion(regions[i], attrs);
}
CacheServer server = cache.addCacheServer();
server.setPort(0);
if (!useGroupsProperty) {
server.setGroups(groups);
}
server.setLoadProbe(probe);
server.start();
remoteObjects.put(CACHE_KEY, cache);
return new Integer(server.getPort());
}
protected int startBridgeServerWithEmbeddedLocator(final String[] groups, final String locators,
final String[] regions, final ServerLoadProbe probe) throws IOException {
Properties props = new Properties();
props.setProperty(MCAST_PORT, String.valueOf(0));
props.setProperty(START_LOCATOR, locators);
props.setProperty(LOCATORS, locators);
DistributedSystem ds = getSystem(props);
Cache cache = CacheFactory.create(ds);
AttributesFactory factory = new AttributesFactory();
factory.setScope(Scope.DISTRIBUTED_ACK);
factory.setEnableBridgeConflation(true);
factory.setDataPolicy(DataPolicy.REPLICATE);
RegionAttributes attrs = factory.create();
for (int i = 0; i < regions.length; i++) {
cache.createRegion(regions[i], attrs);
}
CacheServer server = cache.addCacheServer();
server.setGroups(groups);
server.setLoadProbe(probe);
server.setPort(0);
server.start();
remoteObjects.put(CACHE_KEY, cache);
return new Integer(server.getPort());
}
protected int startBridgeServerWithEmbeddedLocatorInVM(VM vm, final String[] groups,
final String locators, final String[] regions, final ServerLoadProbe probe) {
SerializableCallable connect = new SerializableCallable("Start bridge server") {
public Object call() throws IOException {
return startBridgeServerWithEmbeddedLocator(groups, locators, regions, probe);
}
};
Integer port = (Integer) vm.invoke(connect);
return port.intValue();
}
protected void startBridgeClientInVM(VM vm, final String group, final String host, final int port)
throws Exception {
startBridgeClientInVM(vm, group, host, port, new String[] {REGION_NAME});
}
protected void startBridgeClientInVM(VM vm, final String group, final String host, final int port,
final String[] regions) throws Exception {
PoolFactoryImpl pf = new PoolFactoryImpl(null);
pf.addLocator(host, port).setServerGroup(group).setPingInterval(200)
.setSubscriptionEnabled(true).setSubscriptionRedundancy(-1);
startBridgeClientInVM(vm, pf.getPoolAttributes(), regions);
}
protected void startBridgeClientInVM(VM vm, final Pool pool, final String[] regions)
throws Exception {
SerializableRunnable connect = new SerializableRunnable("Start bridge client") {
public void run() throws Exception {
startBridgeClient(pool, regions);
}
};
if (vm == null) {
connect.run();
} else {
vm.invoke(connect);
}
}
protected void startBridgeClient(final String group, final String host, final int port)
throws Exception {
startBridgeClient(group, host, port, new String[] {REGION_NAME});
}
protected void startBridgeClient(final String group, final String host, final int port,
final String[] regions) throws Exception {
PoolFactoryImpl pf = new PoolFactoryImpl(null);
pf.addLocator(host, port).setServerGroup(group).setPingInterval(200)
.setSubscriptionEnabled(true).setSubscriptionRedundancy(-1);
startBridgeClient(pf.getPoolAttributes(), regions);
}
protected void startBridgeClient(final Pool pool, final String[] regions) throws Exception {
Properties props = new Properties();
props.setProperty(MCAST_PORT, String.valueOf(0));
props.setProperty(LOCATORS, "");
DistributedSystem ds = getSystem(props);
Cache cache = CacheFactory.create(ds);
AttributesFactory factory = new AttributesFactory();
factory.setScope(Scope.LOCAL);
factory.setPoolName(POOL_NAME);
PoolFactoryImpl pf = (PoolFactoryImpl) PoolManager.createFactory();
pf.init(pool);
LocatorDiscoveryCallback locatorCallback = new MyLocatorCallback();
remoteObjects.put(CALLBACK_KEY, locatorCallback);
pf.setLocatorDiscoveryCallback(locatorCallback);
pf.create(POOL_NAME);
RegionAttributes attrs = factory.create();
for (int i = 0; i < regions.length; i++) {
cache.createRegion(regions[i], attrs);
}
remoteObjects.put(CACHE_KEY, cache);
}
protected void stopBridgeMemberVM(VM vm) {
vm.invoke(new SerializableRunnable("Stop bridge member") {
public void run() {
Cache cache = (Cache) remoteObjects.remove(CACHE_KEY);
cache.close();
disconnectFromDS();
}
});
}
public String getLocatorString(Host host, int locatorPort) {
return getLocatorString(host, new int[] {locatorPort});
}
public String getLocatorString(Host host, int[] locatorPorts) {
StringBuffer str = new StringBuffer();
for (int i = 0; i < locatorPorts.length; i++) {
str.append(NetworkUtils.getServerHostName(host)).append("[").append(locatorPorts[i])
.append("]");
if (i < locatorPorts.length - 1) {
str.append(",");
}
}
return str.toString();
}
protected static class MyLocatorCallback extends LocatorDiscoveryCallbackAdapter {
private final Set discoveredLocators = new HashSet();
private final Set removedLocators = new HashSet();
public synchronized void locatorsDiscovered(List locators) {
discoveredLocators.addAll(locators);
notifyAll();
}
public synchronized void locatorsRemoved(List locators) {
removedLocators.addAll(locators);
notifyAll();
}
public boolean waitForDiscovery(InetSocketAddress locator, long time)
throws InterruptedException {
return waitFor(discoveredLocators, locator, time);
}
public boolean waitForRemove(InetSocketAddress locator, long time) throws InterruptedException {
return waitFor(removedLocators, locator, time);
}
private synchronized boolean waitFor(Set set, InetSocketAddress locator, long time)
throws InterruptedException {
long remaining = time;
long endTime = System.currentTimeMillis() + time;
while (!set.contains(locator) && remaining >= 0) {
wait(remaining);
remaining = endTime - System.currentTimeMillis();
}
return set.contains(locator);
}
public synchronized Set getDiscovered() {
return new HashSet(discoveredLocators);
}
}
}