blob: 25b149c1026740924b45b0534ef243a7643b7601 [file] [log] [blame]
/*
* 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.cache.Region.SEPARATOR;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.io.File;
import java.util.Properties;
import org.junit.Test;
import org.apache.geode.SystemFailure;
import org.apache.geode.cache.AttributesFactory;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheException;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.DynamicRegionFactory;
import org.apache.geode.cache.EvictionAction;
import org.apache.geode.cache.EvictionAttributes;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.Scope;
import org.apache.geode.internal.cache.xmlcache.CacheCreation;
import org.apache.geode.logging.internal.OSProcess;
import org.apache.geode.test.dunit.Host;
import org.apache.geode.test.dunit.LogWriterUtils;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase;
/**
* Test to make sure dynamic regions work
*
* @since GemFire 4.3
*/
public class DynamicRegionDUnitTest extends JUnit4CacheTestCase {
// Specify oplog size in MB
private static final int OPLOG_SIZE = 1;
public DynamicRegionDUnitTest() {
super();
}
// this test has special config of its distributed system so
// the setUp and tearDown methods need to make sure we don't
// use the ds from previous test and that we don't leave ours around
// for the next test to use.
@Override
public final void preSetUp() throws Exception {
try {
disconnectAllFromDS();
} finally {
File d = new File("DynamicRegionData" + OSProcess.getId());
d.mkdirs();
DynamicRegionFactory.get().open(new DynamicRegionFactory.Config(d, null));
}
}
/**
* Tear down the test suite.
* <p>
* <H1>IMPORTANT NOTE:</H1> Never throw an exception from this method as it will mask any
* exception thrown in a test.
* <p>
*/
@Override
public final void preTearDownCacheTestCase() throws Exception {
LogWriterUtils.getLogWriter().info("Running tearDown in " + this);
try {
// Asif destroy dynamic regions at the end of the test
CacheSerializableRunnable destroyDynRegn =
new CacheSerializableRunnable("Destroy Dynamic regions") {
@Override
public void run2() throws CacheException {
Region dr = getCache().getRegion("__DynamicRegions");
if (dr != null) {
dr.localDestroyRegion();
}
}
};
getOtherVm().invoke(destroyDynRegn);
Region dr = getCache().getRegion("__DynamicRegions");
if (dr != null) {
dr.localDestroyRegion();
}
} catch (VirtualMachineError e) {
SystemFailure.initiateFailure(e);
throw e;
} catch (Throwable t) {
LogWriterUtils.getLogWriter().severe("tearDown in " + this + " failed due to " + t);
} finally {
try {
disconnectAllFromDS();
} catch (VirtualMachineError e) {
SystemFailure.initiateFailure(e);
throw e;
} catch (Throwable t) {
LogWriterUtils.getLogWriter()
.severe("tearDown in " + this + " failed to disconnect all DS due to " + t);
}
}
if (!DynamicRegionFactory.get().isClosed()) {
LogWriterUtils.getLogWriter().severe("DynamicRegionFactory not closed!", new Exception());
}
}
////////////////////// Test Methods //////////////////////
private VM getOtherVm() {
Host host = Host.getHost(0);
return host.getVM(0);
}
private void doParentCreateOtherVm(final Properties p, final boolean persist) {
VM vm = getOtherVm();
vm.invoke(new CacheSerializableRunnable("create root") {
@Override
public void run2() throws CacheException {
File d = new File("DynamicRegionData" + OSProcess.getId());
d.mkdirs();
DynamicRegionFactory.get().open(new DynamicRegionFactory.Config(d, null));
getSystem(p);
assertEquals(true, DynamicRegionFactory.get().isOpen());
createParentRegion("parent", persist);
}
});
}
private void recreateOtherVm() {
VM vm = getOtherVm();
vm.invoke(new CacheSerializableRunnable("recreate") {
@Override
public void run2() throws CacheException {
beginCacheXml();
{
File d = new File("DynamicRegionData" + OSProcess.getId());
d.mkdirs();
CacheCreation cc = (CacheCreation) getCache();
cc.setDynamicRegionFactoryConfig(new DynamicRegionFactory.Config(d, null));
}
createParentRegion("parent", true);
finishCacheXml("dynamicRegionDUnitTest");
// now make sure we recovered from disk ok
assertEquals(true, DynamicRegionFactory.get().isOpen());
}
});
}
private void checkForRegionOtherVm(final String fullPath, final boolean shouldExist) {
VM vm = getOtherVm();
vm.invoke(new CacheSerializableRunnable("checkForRegion") {
@Override
public void run2() throws CacheException {
Region r = getCache().getRegion(fullPath);
if (shouldExist) {
if (r == null) {
fail("region " + fullPath + " does not exist");
}
// assertNotSame(r.getParentRegion().getAttributes().getCapacityController(),
// r.getAttributes().getCapacityController());
assertEquals(true, r.containsKey("key1"));
assertEquals(true, r.containsValueForKey("key1"));
assertEquals("value1", r.getEntry("key1").getValue());
} else {
assertEquals(null, r);
}
}
});
}
private void checkForSubregionOtherVm(final String fullPath, final boolean shouldExist) {
VM vm = getOtherVm();
vm.invoke(new CacheSerializableRunnable("checkForRegion") {
@Override
public void run2() throws CacheException {
Region r = getCache().getRegion(fullPath);
if (shouldExist) {
if (r == null) {
fail("region " + fullPath + " does not exist");
}
} else {
assertEquals(null, r);
}
}
});
}
/**
* @param persist added this param to fix bug 37439
*/
protected Region createParentRegion(String name, boolean persist) throws CacheException {
final AttributesFactory factory = new AttributesFactory();
factory.setScope(Scope.DISTRIBUTED_ACK);
factory.setDataPolicy(DataPolicy.REPLICATE);
File d = new File("DynamicRegionData" + OSProcess.getId());
factory.setDiskStoreName(getCache().createDiskStoreFactory().setDiskDirs(new File[] {d})
.setMaxOplogSize(OPLOG_SIZE).create("DynamicRegionDUnitTest").getName());
if (persist) {
factory.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE);
}
factory.setEvictionAttributes(
EvictionAttributes.createLRUEntryAttributes(100, EvictionAction.OVERFLOW_TO_DISK));
final Region r = createRootRegion(name, factory.create());
return r;
}
/**
* Make sure dynamic regions work on peers
*/
@Test
public void testPeerRegion() {
assertEquals(true, DynamicRegionFactory.get().isOpen());
createParentRegion("parent", true);
Properties p = new Properties();
doParentCreateOtherVm(p, false);
Region dr = DynamicRegionFactory.get().createDynamicRegion("parent", "dynamicRegion1");
String drFullPath = dr.getFullPath();
dr.put("key1", "value1");
// test for bug 35528 - support for dynamic subregions of dynamic regions
for (int i = 0; i < 10; i++) {
DynamicRegionFactory.get().createDynamicRegion(drFullPath, "subregion" + i);
}
LogWriterUtils.getLogWriter()
.info("testPeerRegion - check #1 make sure other region has new dynamic subregion");
checkForRegionOtherVm(drFullPath, true);
// spot check the subregions
checkForSubregionOtherVm(drFullPath + SEPARATOR + "subregion7", true);
// now see if OTHER can recreate which should fetch meta-info from controller
recreateOtherVm();
LogWriterUtils.getLogWriter().info(
"testPeerRegion - check #2 make sure other region has dynamic region after restarting through getInitialImage");
checkForRegionOtherVm(drFullPath, true);
// now close the controller and see if OTHER can still fetch meta-info from disk
closeCache();
recreateOtherVm();
LogWriterUtils.getLogWriter()
.info("testPeerRegion - check #3 make sure dynamic region can be recovered from disk");
checkForRegionOtherVm(drFullPath, true);
for (int i = 0; i < 10; i++) {
checkForSubregionOtherVm(drFullPath + SEPARATOR + "subregion" + i, true);
}
// now start our cache back up and see if we still have the dynamic regions
// even if we don't have disk on the controller to recover from.
// This means we will get them from the peer
{
assertEquals(true, DynamicRegionFactory.get().isClosed());
DynamicRegionFactory.get().open(new DynamicRegionFactory.Config());
beginCacheXml();
createParentRegion("parent", true);
finishCacheXml("dynamicRegionCTRDUnitTest");
assertEquals(true, DynamicRegionFactory.get().isOpen());
assertEquals(true, DynamicRegionFactory.get().isActive());
Cache c = getCache();
// verify that controller has all dynamic regions
assertEquals(true, c.getRegion(drFullPath) != null);
// now make sure we can destroy dynamic regions
for (int i = 0; i < 10; i++) {
String regName = drFullPath + SEPARATOR + "subregion" + i;
assertEquals(true, c.getRegion(regName) != null);
DynamicRegionFactory.get().destroyDynamicRegion(regName);
assertEquals(null, c.getRegion(regName));
checkForSubregionOtherVm(regName, false);
}
// make sure that we can explicitly destroy a region and then still
// ask the factory to destroy it.
c.getRegion(drFullPath).localDestroyRegion();
checkForRegionOtherVm(drFullPath, true);
DynamicRegionFactory.get().destroyDynamicRegion(drFullPath);
assertEquals(null, c.getRegion(drFullPath));
checkForRegionOtherVm(drFullPath, false);
}
}
}