| /* |
| * 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); |
| } |
| } |
| } |