/*
* 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.rollingupgrade;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache30.CacheSerializableRunnable;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.internal.AvailablePortHelper;
import org.apache.geode.internal.FileUtil;
import org.apache.geode.internal.Version;
import org.apache.geode.test.dunit.DistributedTestUtils;
import org.apache.geode.test.dunit.Host;
import org.apache.geode.test.dunit.IgnoredException;
import org.apache.geode.test.dunit.Invoke;
import org.apache.geode.test.dunit.LogWriterUtils;
import org.apache.geode.test.dunit.NetworkUtils;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase;
import org.apache.geode.test.dunit.standalone.DUnitLauncher;
import org.apache.geode.test.dunit.standalone.VersionManager;
import org.apache.geode.test.junit.categories.BackwardCompatibilityTest;
import org.apache.geode.test.junit.categories.DistributedTest;
import org.apache.geode.test.junit.runners.CategoryWithParameterizedRunnerFactory;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
/**
* RollingUpgrade dunit tests are distributed among subclasses of RollingUpgradeDUnitTest to avoid
* spurious "hangs" being declared by Hydra.
*
* This test will not run properly in eclipse at this point due to having to bounce vms Currently,
* bouncing vms is necessary because we are starting gemfire with different class loaders and the
* class loaders are lingering (possibly due to daemon threads - the vm itself is still running)
*
* Note: to run in eclipse, I had to copy over the jg-magic-map.txt file into my GEMFIRE_OUTPUT
* location, in the same directory as #MagicNumberReader otherwise the two systems were unable to
* talk to one another due to one using a magic number and the other not. Also turnOffBounce will
* need to be set to true so that bouncing a vm doesn't lead to a NPE.
*
* @author jhuynh
*/
@Category({DistributedTest.class, BackwardCompatibilityTest.class})
@RunWith(Parameterized.class)
@Parameterized.UseParametersRunnerFactory(CategoryWithParameterizedRunnerFactory.class)
public class RollingUpgradeDUnitTest extends JUnit4DistributedTestCase {
@Parameterized.Parameters
public static Collection<String> data() {
List<String> result = VersionManager.getInstance().getVersionsWithoutCurrent();
if (result.size() < 1) {
throw new RuntimeException("No older versions of Geode were found to test against. "
+ "Current directory is " + new File(".").getAbsolutePath());
} else {
System.out.println("running against these versions: " + result);
}
return result;
}
private File[] testingDirs = new File[3];
private static String diskDir = "RollingUpgradeDUnitTest";
// Each vm will have a cache object
private static Object cache;
// the old version of Geode we're testing against
private String oldVersion;
private void deleteVMFiles() throws Exception {
System.out.println("deleting files in vm" + VM.getCurrentVMNum());
File pwd = new File(".");
for (File entry : pwd.listFiles()) {
try {
FileUtil.delete(entry);
} catch (Exception e) {
System.out.println("Could not delete " + entry + ": " + e.getMessage());
}
}
}
private void deleteWorkingDirFiles() throws Exception {
Invoke.invokeInEveryVM("delete files", () -> deleteVMFiles());
}
@Override
public void postSetUp() throws Exception {
deleteWorkingDirFiles();
IgnoredException.addIgnoredException(
"cluster configuration service not available|ConflictingPersistentDataException");
}
public RollingUpgradeDUnitTest(String version) {
oldVersion = version;
}
@Test
public void testRollServersOnReplicatedRegion_dataserializable() throws Exception {
doTestRollAll("replicate", "dataserializable", oldVersion);
}
@Test
public void testRollServersOnPartitionedRegion_dataserializable() throws Exception {
doTestRollAll("partitionedRedundant", "dataserializable", oldVersion);
}
@Test
public void testRollServersOnPersistentRegion_dataserializable() throws Exception {
doTestRollAll("persistentReplicate", "dataserializable", oldVersion);
}
// We start an "old" locator and old servers
// We roll the locator
// Now we roll all the servers from old to new
public void doTestRollAll(String regionType, String objectType, String startingVersion)
throws Exception {
final Host host = Host.getHost(0);
VM server1 = host.getVM(startingVersion, 0);
VM server2 = host.getVM(startingVersion, 1);
VM server3 = host.getVM(startingVersion, 2);
VM locator = host.getVM(startingVersion, 3);
String regionName = "aRegion";
String shortcutName = RegionShortcut.REPLICATE.name();
if (regionType.equals("replicate")) {
shortcutName = RegionShortcut.REPLICATE.name();
} else if ((regionType.equals("partitionedRedundant"))) {
shortcutName = RegionShortcut.PARTITION_REDUNDANT.name();
} else if ((regionType.equals("persistentReplicate"))) {
shortcutName = RegionShortcut.PARTITION_PERSISTENT.name();
for (int i = 0; i < testingDirs.length; i++) {
testingDirs[i] = new File(diskDir, "diskStoreVM_" + String.valueOf(host.getVM(i).getPid()))
.getAbsoluteFile();
if (!testingDirs[i].exists()) {
System.out.println(" Creating diskdir for server: " + i);
testingDirs[i].mkdirs();
}
}
}
int[] locatorPorts = AvailablePortHelper.getRandomAvailableTCPPorts(1);
String hostName = NetworkUtils.getServerHostName(host);
String locatorString = getLocatorString(locatorPorts);
final Properties locatorProps = new Properties();
// configure all class loaders for each vm
try {
locator.invoke(invokeStartLocator(hostName, locatorPorts[0], getTestMethodName(),
locatorString, locatorProps));
invokeRunnableInVMs(invokeCreateCache(getSystemProperties(locatorPorts)), server1, server2,
server3);
// create region
if ((regionType.equals("persistentReplicate"))) {
for (int i = 0; i < testingDirs.length; i++) {
CacheSerializableRunnable runnable =
invokeCreatePersistentReplicateRegion(regionName, testingDirs[i]);
invokeRunnableInVMs(runnable, host.getVM(i));
}
} else {
invokeRunnableInVMs(invokeCreateRegion(regionName, shortcutName), server1, server2,
server3);
}
putAndVerify(objectType, server1, regionName, 0, 10, server2, server3);
locator = rollLocatorToCurrent(locator, hostName, locatorPorts[0], getTestMethodName(),
locatorString);
server1 = rollServerToCurrentAndCreateRegion(server1, regionType, testingDirs[0],
shortcutName, regionName, locatorPorts);
verifyValues(objectType, regionName, 0, 10, server1);
putAndVerify(objectType, server1, regionName, 5, 15, server2, server3);
putAndVerify(objectType, server2, regionName, 10, 20, server1, server3);
server2 = rollServerToCurrentAndCreateRegion(server2, regionType, testingDirs[1],
shortcutName, regionName, locatorPorts);
verifyValues(objectType, regionName, 0, 10, server2);
putAndVerify(objectType, server2, regionName, 15, 25, server1, server3);
putAndVerify(objectType, server3, regionName, 20, 30, server2, server3);
server3 = rollServerToCurrentAndCreateRegion(server3, regionType, testingDirs[2],
shortcutName, regionName, locatorPorts);
verifyValues(objectType, regionName, 0, 10, server3);
putAndVerify(objectType, server3, regionName, 15, 25, server1, server2);
putAndVerify(objectType, server1, regionName, 20, 30, server1, server2, server3);
} finally {
invokeRunnableInVMs(true, invokeStopLocator(), locator);
invokeRunnableInVMs(true, invokeCloseCache(), server1, server2, server3);
if ((regionType.equals("persistentReplicate"))) {
deleteDiskStores();
}
}
}
// ******** TEST HELPER METHODS ********/
private void putAndVerify(String objectType, VM putter, String regionName, int start, int end,
VM check1, VM check2, VM check3) throws Exception {
if (objectType.equals("strings")) {
putStringsAndVerify(putter, regionName, start, end, check1, check2, check3);
} else if (objectType.equals("serializable")) {
putSerializableAndVerify(putter, regionName, start, end, check1, check2, check3);
} else if (objectType.equals("dataserializable")) {
putDataSerializableAndVerify(putter, regionName, start, end, check1, check2, check3);
} else {
throw new Error("Not a valid test object type");
}
}
// ******** TEST HELPER METHODS ********/
private void putAndVerify(String objectType, VM putter, String regionName, int start, int end,
VM check1, VM check2) throws Exception {
if (objectType.equals("strings")) {
putStringsAndVerify(putter, regionName, start, end, check1, check2);
} else if (objectType.equals("serializable")) {
putSerializableAndVerify(putter, regionName, start, end, check1, check2);
} else if (objectType.equals("dataserializable")) {
putDataSerializableAndVerify(putter, regionName, start, end, check1, check2);
} else {
throw new Error("Not a valid test object type");
}
}
private void putStringsAndVerify(VM putter, final String regionName, final int start,
final int end, VM... vms) {
for (int i = start; i < end; i++) {
putter.invoke(invokePut(regionName, "" + i, "VALUE(" + i + ")"));
}
threadSleep();
// verify present in others
for (VM vm : vms) {
vm.invoke(invokeAssertEntriesEqual(regionName, start, end));
}
}
private void putSerializableAndVerify(VM putter, String regionName, int start, int end,
VM... vms) {
for (int i = start; i < end; i++) {
putter.invoke(invokePut(regionName, "" + i, new Properties()));
}
threadSleep();
// verify present in others
for (VM vm : vms) {
vm.invoke(invokeAssertEntriesExist(regionName, start, end));
}
}
private void putDataSerializableAndVerify(VM putter, String regionName, int start, int end,
VM... vms) throws Exception {
for (int i = start; i < end; i++) {
Class aClass = Thread.currentThread().getContextClassLoader()
.loadClass("org.apache.geode.cache.ExpirationAttributes");
Constructor constructor = aClass.getConstructor(int.class);
Object testDataSerializable = constructor.newInstance(i);
putter.invoke(invokePut(regionName, "" + i, testDataSerializable));
}
threadSleep();
// verify present in others
for (VM vm : vms) {
vm.invoke(invokeAssertEntriesExist(regionName, start, end));
}
}
private void verifyValues(String objectType, String regionName, int start, int end, VM... vms) {
threadSleep();
if (objectType.equals("strings")) {
for (VM vm : vms) {
vm.invoke(invokeAssertEntriesEqual(regionName, start, end));
}
} else if (objectType.equals("serializable")) {
for (VM vm : vms) {
vm.invoke(invokeAssertEntriesExist(regionName, start, end));
}
} else if (objectType.equals("dataserializable")) {
for (VM vm : vms) {
vm.invoke(invokeAssertEntriesExist(regionName, start, end));
}
}
}
// Oddly the puts will return and for some reason the other vms have yet to recieve or process the
// put?
private void threadSleep() {
try {
Thread.sleep(250);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private void query(String queryString, int numExpectedResults, VM... vms) {
for (VM vm : vms) {
vm.invoke(invokeAssertQueryResults(queryString, numExpectedResults));
}
}
private void invokeRunnableInVMs(CacheSerializableRunnable runnable, VM... vms) throws Exception {
for (VM vm : vms) {
vm.invoke(runnable);
}
}
// Used to close cache and make sure we attempt on all vms even if some do not have a cache
private void invokeRunnableInVMs(boolean catchErrors, CacheSerializableRunnable runnable,
VM... vms) throws Exception {
for (VM vm : vms) {
try {
vm.invoke(runnable);
} catch (Exception e) {
if (!catchErrors) {
throw e;
}
}
}
}
private VM rollServerToCurrent(VM oldServer, int[] locatorPorts) throws Exception {
// Roll the server
oldServer.invoke(invokeCloseCache());
VM rollServer = Host.getHost(0).getVM(oldServer.getPid()); // gets a vm with the current version
rollServer.invoke(invokeCreateCache(locatorPorts == null ? getSystemPropertiesPost71()
: getSystemPropertiesPost71(locatorPorts)));
rollServer.invoke(invokeAssertVersion(Version.CURRENT_ORDINAL));
return rollServer;
}
/*
* @param rollServer
*
* @param createRegionMethod
*
* @param regionName
*
* @param locatorPorts if null, uses dunit locator
*
* @throws Exception
*/
private void rollServerToCurrentAndCreateRegion(VM rollServer, String shortcutName,
String regionName, int[] locatorPorts) throws Exception {
rollServerToCurrent(rollServer, locatorPorts);
// recreate region on "rolled" server
invokeRunnableInVMs(invokeCreateRegion(regionName, shortcutName), rollServer);
rollServer.invoke(invokeRebalance());
}
private VM rollServerToCurrentAndCreateRegion(VM oldServer, String regionType, File diskdir,
String shortcutName, String regionName, int[] locatorPorts) throws Exception {
VM rollServer = rollServerToCurrent(oldServer, locatorPorts);
// recreate region on "rolled" server
if ((regionType.equals("persistentReplicate"))) {
CacheSerializableRunnable runnable =
invokeCreatePersistentReplicateRegion(regionName, diskdir);
invokeRunnableInVMs(runnable, rollServer);
} else {
invokeRunnableInVMs(invokeCreateRegion(regionName, shortcutName), rollServer);
}
rollServer.invoke(invokeRebalance());
return rollServer;
}
private VM rollLocatorToCurrent(VM oldLocator, final String serverHostName, final int port,
final String testName, final String locatorString) throws Exception {
// Roll the locator
oldLocator.invoke(invokeStopLocator());
VM rollLocator = Host.getHost(0).getVM(oldLocator.getPid()); // gets a VM with current version
final Properties props = new Properties();
props.setProperty(DistributionConfig.ENABLE_CLUSTER_CONFIGURATION_NAME, "false");
rollLocator.invoke(invokeStartLocator(serverHostName, port, testName, locatorString, props));
return rollLocator;
}
// Due to licensing changes
public Properties getSystemPropertiesPost71() {
Properties props = getSystemProperties();
return props;
}
// Due to licensing changes
public Properties getSystemPropertiesPost71(int[] locatorPorts) {
Properties props = getSystemProperties(locatorPorts);
return props;
}
public Properties getSystemProperties() {
Properties props = DistributedTestUtils.getAllDistributedSystemProperties(new Properties());
props.remove("disable-auto-reconnect");
props.remove(DistributionConfig.OFF_HEAP_MEMORY_SIZE_NAME);
props.remove(DistributionConfig.LOCK_MEMORY_NAME);
return props;
}
public Properties getSystemProperties(int[] locatorPorts) {
Properties p = new Properties();
String locatorString = getLocatorString(locatorPorts);
p.setProperty("locators", locatorString);
p.setProperty("mcast-port", "0");
return p;
}
public Properties getClientSystemProperties() {
Properties p = new Properties();
p.setProperty("mcast-port", "0");
return p;
}
public static String getLocatorString(int locatorPort) {
String locatorString = getDUnitLocatorAddress() + "[" + locatorPort + "]";
return locatorString;
}
public static String getLocatorString(int[] locatorPorts) {
String locatorString = "";
int numLocators = locatorPorts.length;
for (int i = 0; i < numLocators; i++) {
locatorString += getLocatorString(locatorPorts[i]);
if (i + 1 < numLocators) {
locatorString += ",";
}
}
return locatorString;
}
private List<URL> addFile(File file) throws MalformedURLException {
ArrayList<URL> urls = new ArrayList<URL>();
if (file.isDirectory()) {
// Do not want to start cache with sample code xml
if (file.getName().contains("SampleCode")) {
return urls;
} else {
File[] files = file.listFiles();
for (File afile : files) {
urls.addAll(addFile(afile));
}
}
} else {
URL url = file.toURI().toURL();
urls.add(url);
}
return urls;
}
private CacheSerializableRunnable invokeStartLocator(final String serverHostName, final int port,
final String testName, final String locatorsString, final Properties props) {
return new CacheSerializableRunnable("execute: startLocator") {
public void run2() {
try {
startLocator(serverHostName, port, testName, locatorsString, props);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
private CacheSerializableRunnable invokeStartLocatorAndServer(final String serverHostName,
final int port, final String testName, final Properties systemProperties) {
return new CacheSerializableRunnable("execute: startLocator") {
public void run2() {
try {
systemProperties.put(DistributionConfig.START_LOCATOR_NAME,
"" + serverHostName + "[" + port + "]");
RollingUpgradeDUnitTest.cache = createCache(systemProperties);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
private CacheSerializableRunnable invokeCreateCache(final Properties systemProperties) {
return new CacheSerializableRunnable("execute: createCache") {
public void run2() {
try {
RollingUpgradeDUnitTest.cache = createCache(systemProperties);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
private CacheSerializableRunnable invokeCreateClientCache(final Properties systemProperties,
final String[] hosts, final int[] ports) {
return new CacheSerializableRunnable("execute: createClientCache") {
public void run2() {
try {
RollingUpgradeDUnitTest.cache = createClientCache(systemProperties, hosts, ports);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
private CacheSerializableRunnable invokeStartCacheServer(final int port) {
return new CacheSerializableRunnable("execute: startCacheServer") {
public void run2() {
try {
startCacheServer(RollingUpgradeDUnitTest.cache, port);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
private CacheSerializableRunnable invokeAssertVersion(final short version) {
return new CacheSerializableRunnable("execute: assertVersion") {
public void run2() {
try {
assertVersion(RollingUpgradeDUnitTest.cache, version);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
private CacheSerializableRunnable invokeCreateRegion(final String regionName,
final String shortcutName) {
return new CacheSerializableRunnable("execute: createRegion") {
public void run2() {
try {
createRegion(RollingUpgradeDUnitTest.cache, regionName, shortcutName);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
private CacheSerializableRunnable invokeCreatePersistentReplicateRegion(final String regionName,
final File diskstore) {
return new CacheSerializableRunnable("execute: createPersistentReplicateRegion") {
public void run2() {
try {
createPersistentReplicateRegion(RollingUpgradeDUnitTest.cache, regionName, diskstore);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
private CacheSerializableRunnable invokeCreateClientRegion(final String regionName,
final String shortcutName) {
return new CacheSerializableRunnable("execute: createClientRegion") {
public void run2() {
try {
createClientRegion(RollingUpgradeDUnitTest.cache, regionName, shortcutName);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
private CacheSerializableRunnable invokePut(final String regionName, final Object key,
final Object value) {
return new CacheSerializableRunnable("execute: put") {
public void run2() {
try {
put(RollingUpgradeDUnitTest.cache, regionName, key, value);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
private CacheSerializableRunnable invokeAssertEntriesEqual(final String regionName,
final int start, final int end) {
return new CacheSerializableRunnable("execute: assertEntriesEqual") {
public void run2() {
try {
for (int i = start; i < end; i++) {
assertEntryEquals(RollingUpgradeDUnitTest.cache, regionName, "" + i,
"VALUE(" + i + ")");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
private CacheSerializableRunnable invokeAssertEntriesExist(final String regionName,
final int start, final int end) {
return new CacheSerializableRunnable("execute: assertEntryExists") {
public void run2() {
try {
for (int i = start; i < end; i++) {
assertEntryExists(RollingUpgradeDUnitTest.cache, regionName, "" + i);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
private CacheSerializableRunnable invokeStopLocator() {
return new CacheSerializableRunnable("execute: stopLocator") {
public void run2() {
try {
stopLocator();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
private CacheSerializableRunnable invokeCloseCache() {
return new CacheSerializableRunnable("execute: closeCache") {
public void run2() {
try {
closeCache(RollingUpgradeDUnitTest.cache);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
private CacheSerializableRunnable invokeRebalance() {
return new CacheSerializableRunnable("execute: rebalance") {
public void run2() {
try {
rebalance(RollingUpgradeDUnitTest.cache);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
private CacheSerializableRunnable invokeAssertQueryResults(final String queryString,
final int numExpected) {
return new CacheSerializableRunnable("execute: assertQueryResults") {
public void run2() {
try {
assertQueryResults(RollingUpgradeDUnitTest.cache, queryString, numExpected);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
public void deleteDiskStores() throws Exception {
try {
FileUtil.delete(new File(diskDir).getAbsoluteFile());
} catch (IOException e) {
throw new Error("Error deleting files", e);
}
}
public static Object createCache(Properties systemProperties) throws Exception {
// systemProperties.put(DistributionConfig.LOG_FILE_NAME,
// "rollingUpgradeCacheVM" + VM.getCurrentVMNum() + ".log");
Class distConfigClass = Thread.currentThread().getContextClassLoader()
.loadClass("org.apache.geode.distributed.internal.DistributionConfigImpl");
boolean disableConfig = true;
try {
distConfigClass.getDeclaredField("useSharedConfiguration");
} catch (NoSuchFieldException e) {
disableConfig = false;
}
if (disableConfig) {
systemProperties.put(DistributionConfig.USE_CLUSTER_CONFIGURATION_NAME, "false");
}
Class cacheFactoryClass = Thread.currentThread().getContextClassLoader()
.loadClass("org.apache.geode.cache.CacheFactory");
Constructor constructor = cacheFactoryClass.getConstructor(Properties.class);
constructor.setAccessible(true);
Object cacheFactory = constructor.newInstance(systemProperties);
Method createMethod = cacheFactoryClass.getMethod("create");
createMethod.setAccessible(true);
Object cache = null;
cache = createMethod.invoke(cacheFactory);
return cache;
}
public static void startCacheServer(Object cache, int port) throws Exception {
Method addCacheServerMethod = cache.getClass().getMethod("addCacheServer");
addCacheServerMethod.setAccessible(true);
Object cacheServer = addCacheServerMethod.invoke(cache);
Method setPortMethod = cacheServer.getClass().getMethod("setPort", int.class);
setPortMethod.setAccessible(true);
setPortMethod.invoke(cacheServer, port);
Method startMethod = cacheServer.getClass().getMethod("start");
startMethod.setAccessible(true);
startMethod.invoke(cacheServer);
}
public static Object createClientCache(Properties systemProperties, String[] hosts, int[] ports)
throws Exception {
Class aClass = Thread.currentThread().getContextClassLoader()
.loadClass("org.apache.geode.cache.client.ClientCacheFactory");
Constructor constructor = aClass.getConstructor(Properties.class);
constructor.setAccessible(true);
Object ccf = constructor.newInstance(systemProperties);
Method addPoolLocatorMethod = aClass.getMethod("addPoolLocator", String.class, int.class);
addPoolLocatorMethod.setAccessible(true);
int hostsLength = hosts.length;
for (int i = 0; i < hostsLength; i++) {
addPoolLocatorMethod.invoke(ccf, hosts[i], ports[i]);
}
Method createMethod = aClass.getMethod("create");
createMethod.setAccessible(true);
Object cache = createMethod.invoke(ccf);
return cache;
}
public static boolean assertRegionExists(Object cache, String regionName) throws Exception {
Object region = cache.getClass().getMethod("getRegion", String.class).invoke(cache, regionName);
if (region == null) {
throw new Error("Region: " + regionName + " does not exist");
}
return true;
}
public static Object getRegion(Object cache, String regionName) throws Exception {
return cache.getClass().getMethod("getRegion", String.class).invoke(cache, regionName);
}
public static boolean assertEntryEquals(Object cache, String regionName, Object key, Object value)
throws Exception {
assertRegionExists(cache, regionName);
Object region = getRegion(cache, regionName);
Object regionValue = region.getClass().getMethod("get", Object.class).invoke(region, key);
if (regionValue == null) {
System.out.println("region value does not exist for key: " + key);
throw new Error("Region value does not exist for key:" + key);
}
if (!regionValue.equals(value)) {
System.out.println("Entry for key:" + key + " does not equal value: " + value);
throw new Error("Entry for key:" + key + " does not equal value: " + value);
}
return true;
}
public static boolean assertEntryExists(Object cache, String regionName, Object key)
throws Exception {
assertRegionExists(cache, regionName);
Object region = getRegion(cache, regionName);
Object regionValue = region.getClass().getMethod("get", Object.class).invoke(region, key);
if (regionValue == null) {
System.out.println("Entry for key:" + key + " does not exist");
throw new Error("Entry for key:" + key + " does not exist");
}
return true;
}
public static Object put(Object cache, String regionName, Object key, Object value)
throws Exception {
Object region = getRegion(cache, regionName);
return region.getClass().getMethod("put", Object.class, Object.class).invoke(region, key,
value);
}
public static void createRegion(Object cache, String regionName, String shortcutName)
throws Exception {
Class aClass = Thread.currentThread().getContextClassLoader()
.loadClass("org.apache.geode.cache.RegionShortcut");
Object[] enumConstants = aClass.getEnumConstants();
Object shortcut = null;
int length = enumConstants.length;
for (int i = 0; i < length; i++) {
Object constant = enumConstants[i];
if (((Enum) constant).name().equals(shortcutName)) {
shortcut = constant;
break;
}
}
Method createRegionFactoryMethod = cache.getClass().getMethod("createRegionFactory", aClass);
createRegionFactoryMethod.setAccessible(true);
Object regionFactory = createRegionFactoryMethod.invoke(cache, shortcut);
Method createMethod = regionFactory.getClass().getMethod("create", String.class);
createMethod.setAccessible(true);
createMethod.invoke(regionFactory, regionName);
}
public static void createPartitionedRegion(Object cache, String regionName) throws Exception {
createRegion(cache, regionName, RegionShortcut.PARTITION.name());
}
public static void createPartitionedRedundantRegion(Object cache, String regionName)
throws Exception {
createRegion(cache, regionName, RegionShortcut.PARTITION_REDUNDANT.name());
}
public static void createReplicatedRegion(Object cache, String regionName) throws Exception {
createRegion(cache, regionName, RegionShortcut.REPLICATE.name());
}
// Assumes a client cache is passed
public static void createClientRegion(Object cache, String regionName, String shortcutName)
throws Exception {
Class aClass = Thread.currentThread().getContextClassLoader()
.loadClass("org.apache.geode.cache.client.ClientRegionShortcut");
Object[] enumConstants = aClass.getEnumConstants();
Object shortcut = null;
int length = enumConstants.length;
for (int i = 0; i < length; i++) {
Object constant = enumConstants[i];
if (((Enum) constant).name().equals(shortcutName)) {
shortcut = constant;
break;
}
}
Object clientRegionFactory = cache.getClass()
.getMethod("createClientRegionFactory", shortcut.getClass()).invoke(cache, shortcut);
clientRegionFactory.getClass().getMethod("create", String.class).invoke(clientRegionFactory,
regionName);
}
public static void createRegion(String regionName, Object regionFactory) throws Exception {
regionFactory.getClass().getMethod("create", String.class).invoke(regionFactory, regionName);
}
public static void createPersistentReplicateRegion(Object cache, String regionName,
File diskStore) throws Exception {
Object store = cache.getClass().getMethod("findDiskStore", String.class).invoke(cache, "store");
Class dataPolicyObject = Thread.currentThread().getContextClassLoader()
.loadClass("org.apache.geode.cache.DataPolicy");
Object dataPolicy = dataPolicyObject.getField("PERSISTENT_REPLICATE").get(null);
if (store == null) {
Object dsf = cache.getClass().getMethod("createDiskStoreFactory").invoke(cache);
dsf.getClass().getMethod("setMaxOplogSize", long.class).invoke(dsf, 1L);
dsf.getClass().getMethod("setDiskDirs", File[].class).invoke(dsf,
new Object[] {new File[] {diskStore.getAbsoluteFile()}});
dsf.getClass().getMethod("create", String.class).invoke(dsf, "store");
}
Object rf = cache.getClass().getMethod("createRegionFactory").invoke(cache);
rf.getClass().getMethod("setDiskStoreName", String.class).invoke(rf, "store");
rf.getClass().getMethod("setDataPolicy", dataPolicy.getClass()).invoke(rf, dataPolicy);
rf.getClass().getMethod("create", String.class).invoke(rf, regionName);
}
public static void assertVersion(Object cache, short ordinal) throws Exception {
Class idmClass = Thread.currentThread().getContextClassLoader()
.loadClass("org.apache.geode.distributed.internal.membership.InternalDistributedMember");
Method getDSMethod = cache.getClass().getMethod("getDistributedSystem");
getDSMethod.setAccessible(true);
Object ds = getDSMethod.invoke(cache);
Method getDistributedMemberMethod = ds.getClass().getMethod("getDistributedMember");
getDistributedMemberMethod.setAccessible(true);
Object member = getDistributedMemberMethod.invoke(ds);
Method getVersionObjectMethod = member.getClass().getMethod("getVersionObject");
getVersionObjectMethod.setAccessible(true);
Object thisVersion = getVersionObjectMethod.invoke(member);
Method getOrdinalMethod = thisVersion.getClass().getMethod("ordinal");
getOrdinalMethod.setAccessible(true);
short thisOrdinal = (Short) getOrdinalMethod.invoke(thisVersion);
if (ordinal != thisOrdinal) {
throw new Error(
"Version ordinal:" + thisOrdinal + " was not the expected ordinal of:" + ordinal);
}
}
public static void assertQueryResults(Object cache, String queryString, int numExpectedResults) {
try {
Method getQSMethod = cache.getClass().getMethod("getQueryService");
getQSMethod.setAccessible(true);
Object qs = getQSMethod.invoke(cache);
Method newQueryMethod = qs.getClass().getMethod("newQuery", String.class);
newQueryMethod.setAccessible(true);
Object query = newQueryMethod.invoke(qs, queryString);
Method executeMethod = query.getClass().getMethod("execute");
executeMethod.setAccessible(true);
Object results = executeMethod.invoke(query);
Method sizeMethod = results.getClass().getMethod("size");
sizeMethod.setAccessible(true);
int numResults = (Integer) sizeMethod.invoke(results);
if (numResults != numExpectedResults) {
System.out.println("Num Results was:" + numResults);
throw new Error("Num results:" + numResults + " != num expected:" + numExpectedResults);
}
} catch (Exception e) {
throw new Error("Query Exception", e);
}
}
public static void stopCacheServers(Object cache) throws Exception {
Method getCacheServersMethod = cache.getClass().getMethod("getCacheServers");
getCacheServersMethod.setAccessible(true);
List cacheServers = (List) getCacheServersMethod.invoke(cache);
Method stopMethod = null;
for (Object cs : cacheServers) {
if (stopMethod == null) {
stopMethod = cs.getClass().getMethod("stop");
}
stopMethod.setAccessible(true);
stopMethod.invoke(cs);
}
}
public static void closeCache(Object cache) throws Exception {
if (cache == null) {
return;
}
Method isClosedMethod = cache.getClass().getMethod("isClosed");
isClosedMethod.setAccessible(true);
boolean cacheClosed = (Boolean) isClosedMethod.invoke(cache);
if (cache != null && !cacheClosed) {
stopCacheServers(cache);
Method method = cache.getClass().getMethod("close");
method.setAccessible(true);
method.invoke(cache);
long startTime = System.currentTimeMillis();
while (!cacheClosed && System.currentTimeMillis() - startTime < 30000) {
try {
Thread.sleep(1000);
Method cacheClosedMethod = cache.getClass().getMethod("isClosed");
cacheClosedMethod.setAccessible(true);
cacheClosed = (Boolean) cacheClosedMethod.invoke(cache);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
cache = null;
}
public static void rebalance(Object cache) throws Exception {
Method getRMMethod = cache.getClass().getMethod("getResourceManager");
getRMMethod.setAccessible(true);
Object manager = getRMMethod.invoke(cache);
Method createRebalanceFactoryMethod = manager.getClass().getMethod("createRebalanceFactory");
createRebalanceFactoryMethod.setAccessible(true);
Object rebalanceFactory = createRebalanceFactoryMethod.invoke(manager);
Object op = null;
Method m = rebalanceFactory.getClass().getMethod("start");
m.setAccessible(true);
op = m.invoke(rebalanceFactory);
// Wait until the rebalance is completex
try {
Method getResultsMethod = op.getClass().getMethod("getResults");
getResultsMethod.setAccessible(true);
Object results = getResultsMethod.invoke(op);
Method getTotalTimeMethod = results.getClass().getMethod("getTotalTime");
getTotalTimeMethod.setAccessible(true);
System.out.println("Took " + getTotalTimeMethod.invoke(results) + " milliseconds\n");
Method getTotalBucketsMethod = results.getClass().getMethod("getTotalBucketTransferBytes");
getTotalBucketsMethod.setAccessible(true);
System.out.println("Transfered " + getTotalBucketsMethod.invoke(results) + "bytes\n");
} catch (Exception e) {
Thread.currentThread().interrupt();
throw e;
}
}
/**
* Starts a locator with given configuration.
*
* @param props TODO
*/
public static void startLocator(final String serverHostName, final int port,
final String testName, final String locatorsString, final Properties props) throws Exception {
props.setProperty(DistributionConfig.MCAST_PORT_NAME, "0");
props.setProperty(DistributionConfig.LOCATORS_NAME, locatorsString);
props.setProperty(DistributionConfig.LOG_LEVEL_NAME, LogWriterUtils.getDUnitLogLevel());
InetAddress bindAddr = null;
try {
bindAddr = InetAddress.getByName(serverHostName);// getServerHostName(vm.getHost()));
} catch (UnknownHostException uhe) {
throw new Error("While resolving bind address ", uhe);
}
File logFile = new File(testName + "-locator" + port + ".log");
Class locatorClass = Thread.currentThread().getContextClassLoader()
.loadClass("org.apache.geode.distributed.Locator");
Method startLocatorAndDSMethod =
locatorClass.getMethod("startLocatorAndDS", int.class, File.class, InetAddress.class,
Properties.class, boolean.class, boolean.class, String.class);
startLocatorAndDSMethod.setAccessible(true);
startLocatorAndDSMethod.invoke(null, port, logFile, bindAddr, props, true, true, null);
}
public static void stopLocator() throws Exception {
Class internalLocatorClass = Thread.currentThread().getContextClassLoader()
.loadClass("org.apache.geode.distributed.internal.InternalLocator");
Method locatorMethod = internalLocatorClass.getMethod("getLocator");
locatorMethod.setAccessible(true);
Object locator = locatorMethod.invoke(null);
Method stopLocatorMethod = locator.getClass().getMethod("stop");
stopLocatorMethod.setAccessible(true);
stopLocatorMethod.invoke(locator);
}
/**
* Get the port that the standard dunit locator is listening on.
*
* @return
*/
public static String getDUnitLocatorAddress() {
return Host.getHost(0).getHostName();
}
}