This is an automated email from the ASF dual-hosted git repository. klund pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/geode.git
commit 0e6a1b9e0ea0b3cbfeac8c18f4b67ada1972a0bb Author: Kirk Lund <[email protected]> AuthorDate: Wed Mar 21 17:49:33 2018 -0700 GEODE-1279: Rename Bug39079DUnitTest This test has been split into: * GiiDiskAccessExceptionRegressionTest * InitializedDiskRegionWithIoExceptionRegressionTest --- .../geode/internal/cache/Bug39079DUnitTest.java | 341 --------------------- .../GiiDiskAccessExceptionRegressionTest.java | 211 +++++++++++++ ...zedDiskRegionWithIoExceptionRegressionTest.java | 174 +++++++++++ 3 files changed, 385 insertions(+), 341 deletions(-) diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/Bug39079DUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/Bug39079DUnitTest.java deleted file mode 100644 index 15a9a4d..0000000 --- a/geode-core/src/test/java/org/apache/geode/internal/cache/Bug39079DUnitTest.java +++ /dev/null @@ -1,341 +0,0 @@ -/* - * 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; - -import static org.apache.geode.distributed.ConfigurationProperties.*; -import static org.apache.geode.test.dunit.Assert.*; - -import java.io.IOException; -import java.util.List; -import java.util.Properties; - -import org.junit.Test; -import org.junit.experimental.categories.Category; - -import org.apache.geode.cache.AttributesFactory; -import org.apache.geode.cache.DataPolicy; -import org.apache.geode.cache.DiskAccessException; -import org.apache.geode.cache.Region; -import org.apache.geode.cache.RegionAttributes; -import org.apache.geode.cache.Scope; -import org.apache.geode.cache.client.PoolManager; -import org.apache.geode.cache.client.internal.PoolImpl; -import org.apache.geode.cache.server.CacheServer; -import org.apache.geode.cache30.CacheSerializableRunnable; -import org.apache.geode.internal.AvailablePort; -import org.apache.geode.internal.cache.entries.VMThinDiskRegionEntryHeapObjectKey; -import org.apache.geode.internal.cache.persistence.UninterruptibleFileChannel; -import org.apache.geode.test.dunit.Host; -import org.apache.geode.test.dunit.NetworkUtils; -import org.apache.geode.test.dunit.VM; -import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase; -import org.apache.geode.test.junit.categories.DistributedTest; - -/** - * Tests that if a node doing GII experiences DiskAccessException, it should also not try to recover - * from the disk - */ -@Category(DistributedTest.class) -public class Bug39079DUnitTest extends JUnit4CacheTestCase { - - private static final String REGION_NAME_testBridgeServerStoppingInSynchPersistOnlyForIOExceptionCase = - "IGNORE_EXCEPTION_testBridgeServerStoppingInSynchPersistOnlyForIOExceptionCase"; - private static final String REGION_NAME_testGIIDiskAccessException = - "IGNORE_EXCEPTION_testGIIDiskAccessException"; - - private VM vm0; - private VM vm1; - - @Override - public final void postSetUp() throws Exception { - disconnectAllFromDS(); - - final Host host = Host.getHost(0); - vm0 = host.getVM(0); - vm1 = host.getVM(1); - - vm0.invoke(() -> ignorePreAllocate(true)); - vm1.invoke(() -> ignorePreAllocate(true)); - } - - @Override - public final void postTearDownCacheTestCase() throws Exception { - disconnectAllFromDS(); - - vm0.invoke(() -> ignorePreAllocate(false)); - vm1.invoke(() -> ignorePreAllocate(false)); - } - - /** - * If the node experiences disk access exception during GII, it should get destroyed & not attempt - * to recover from the disk - */ - @Test - public void testGIIDiskAccessException() throws Exception { - vm0.invoke(createCacheForVM0()); - vm1.invoke(createCacheForVM1()); - - // Create DiskRegion locally in controller VM also - getSystem(); - - - assertTrue(getCache() != null); - AttributesFactory factory = new AttributesFactory(); - factory.setScope(Scope.DISTRIBUTED_ACK); - factory.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE); - factory.setDiskSynchronous(false); - factory.setDiskStoreName(getCache().createDiskStoreFactory().setDiskDirs(getDiskDirs()) - .create(getClass().getSimpleName()).getName()); - RegionAttributes attr = factory.create(); - Region region = getCache().createRegion(REGION_NAME_testGIIDiskAccessException, attr); - - // Now put entries in the disk region - for (int i = 0; i < 100; ++i) { - region.put(new Integer(i), new Integer(i)); - } - - // Now close the region in the controller VM - region.close(); - - // Now recreate the region but set the factory such that disk region entry object - // used is customized by us to throw exception while writing to disk - - DistributedRegion distRegion = - new DistributedRegion(REGION_NAME_testGIIDiskAccessException, attr, null, - (GemFireCacheImpl) getCache(), new InternalRegionArguments().setDestroyLockFlag(true) - .setRecreateFlag(false).setSnapshotInputStream(null).setImageTarget(null)); - - distRegion.entries.setEntryFactory(TestAbstractDiskRegionEntry.getEntryFactory()); - region = null; - - try { - region = - ((GemFireCacheImpl) getCache()).createVMRegion(REGION_NAME_testGIIDiskAccessException, - attr, new InternalRegionArguments().setInternalMetaRegion(distRegion) - .setDestroyLockFlag(true).setSnapshotInputStream(null).setImageTarget(null)); - fail("Expected DiskAccessException"); - } catch (DiskAccessException expected) { - } - - assertTrue(region == null || region.isDestroyed()); // TODO: why is this an OR instead of - // deterministic? - } - - /** - * If IOException occurs while updating an entry in an already initialized DiskRegion ,then the - * bridge servers should be stopped , if any running - */ - @Test - public void testBridgeServerStoppingInSynchPersistOnlyForIOExceptionCase() throws Exception { - // create server cache - Integer port = vm0.invoke(() -> createServerCache()); - - // create cache client - vm1.invoke(() -> createClientCache(NetworkUtils.getServerHostName(vm0.getHost()), port)); - - // validate - vm0.invoke(() -> validateRunningBridgeServerList()); - - // close server cache - vm0.invoke(() -> closeCacheAndDisconnect()); - - // close client cache - vm1.invoke(() -> closeCacheAndDisconnect()); - } - - private int createServerCache() throws IOException { - createCache(new Properties()); - DiskRegionProperties props = new DiskRegionProperties(); - props.setRegionName(REGION_NAME_testBridgeServerStoppingInSynchPersistOnlyForIOExceptionCase); - props.setOverflow(true); - props.setRolling(true); - props.setDiskDirs(getDiskDirs()); - props.setPersistBackup(true); - - Region region = - DiskRegionHelperFactory.getSyncPersistOnlyRegion(getCache(), props, Scope.DISTRIBUTED_ACK); - assertNotNull(region); - CacheServer bs1 = getCache().addCacheServer(); - int port = AvailablePort.getRandomAvailablePort(AvailablePort.SOCKET); - bs1.setPort(port); - bs1.start(); - return bs1.getPort(); - } - - private void closeCacheAndDisconnect() { - closeCache(); - disconnectFromDS(); - } - - private void createCache(Properties props) { - getSystem(props); - assertNotNull(getCache()); - } - - private void validateRunningBridgeServerList() throws IOException { - Region region = getCache() - .getRegion(REGION_NAME_testBridgeServerStoppingInSynchPersistOnlyForIOExceptionCase); - try { - region.create("key1", new byte[16]); - region.create("key2", new byte[16]); - - // Get the oplog handle & hence the underlying file & close it - UninterruptibleFileChannel oplogFileChannel = - ((LocalRegion) region).getDiskRegion().testHook_getChild().getFileChannel(); - - try { - oplogFileChannel.close(); - region.put("key2", new byte[16]); - fail("Expected DiskAccessException"); - } catch (DiskAccessException expected) { - } - - ((LocalRegion) region).getDiskStore().waitForClose(); - assertTrue(region.getRegionService().isClosed()); - - region = null; - List bsRunning = getCache().getCacheServers(); - assertTrue(bsRunning.isEmpty()); - } finally { - if (region != null) { - region.destroyRegion(); - } - } - } - - private void createClientCache(String host, Integer port1) { - Properties props = new Properties(); - props.setProperty(MCAST_PORT, "0"); - props.setProperty(LOCATORS, ""); - createCache(props); - - PoolImpl pool = (PoolImpl) PoolManager.createFactory().addServer(host, port1.intValue()) - .setSubscriptionEnabled(true).setSubscriptionRedundancy(0).setThreadLocalConnections(true) - .setMinConnections(0).setReadTimeout(20000).setRetryAttempts(1) - .create(getClass().getSimpleName()); - - AttributesFactory factory = new AttributesFactory(); - factory.setScope(Scope.DISTRIBUTED_ACK); - factory.setPoolName(pool.getName()); - - RegionAttributes attrs = factory.create(); - Region region = getCache().createRegion( - REGION_NAME_testBridgeServerStoppingInSynchPersistOnlyForIOExceptionCase, attrs); - region.registerInterest("ALL_KEYS"); - } - - /** - * This method is used to create Cache in VM0 - */ - private CacheSerializableRunnable createCacheForVM0() { - return new CacheSerializableRunnable("createCache") { - @Override - public void run2() { - try { - getSystem(); - assertNotNull(getCache()); - - AttributesFactory factory = new AttributesFactory(); - factory.setScope(Scope.DISTRIBUTED_ACK); - factory.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE); - factory.setDiskSynchronous(false); - factory.setDiskStoreName(getCache().createDiskStoreFactory().setDiskDirs(getDiskDirs()) - .create(getClass().getSimpleName()).getName()); - - RegionAttributes attr = factory.create(); - getCache().createRegion(REGION_NAME_testGIIDiskAccessException, attr); - } catch (Exception ex) { - fail("Error Creating cache / region ", ex); - } - } - }; - } - - /** - * This method is used to create Cache in VM1 - */ - private CacheSerializableRunnable createCacheForVM1() { - return new CacheSerializableRunnable("createCache") { - @Override - public void run2() { - try { - getSystem(); - assertNotNull(getCache()); - - AttributesFactory factory = new AttributesFactory(); - factory.setScope(Scope.DISTRIBUTED_ACK); - factory.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE); - factory.setDiskSynchronous(false); - factory.setDiskStoreName(getCache().createDiskStoreFactory().setDiskDirs(getDiskDirs()) - .create(getClass().getSimpleName()).getName()); - - RegionAttributes attr = factory.create(); - getCache().createRegion(REGION_NAME_testGIIDiskAccessException, attr); - } catch (Exception ex) { - fail("Error Creating cache / region ", ex); - } - } - }; - } - - private void ignorePreAllocate(boolean flag) throws Exception { - DiskStoreImpl.SET_IGNORE_PREALLOCATE = flag; - } - - private static class TestAbstractDiskRegionEntry extends VMThinDiskRegionEntryHeapObjectKey { - - protected TestAbstractDiskRegionEntry(RegionEntryContext r, Object key, Object value) { - super(r, key, value); - } - - private static RegionEntryFactory factory = new RegionEntryFactory() { - - @Override - public RegionEntry createEntry(RegionEntryContext r, Object key, Object value) { - throw new DiskAccessException(new IOException("Test Exception")); - } - - @Override - public Class getEntryClass() { - return getClass(); - } - - @Override - public RegionEntryFactory makeVersioned() { - return this; - } - - @Override - public RegionEntryFactory makeOnHeap() { - return this; - } - }; - - /** - * Overridden setValue method to throw exception - */ - @Override - protected void setValueField(Object v) { - throw new DiskAccessException(new IOException("Test Exception")); - } - - public static RegionEntryFactory getEntryFactory() { - return factory; - } - } -} diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/GiiDiskAccessExceptionRegressionTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/GiiDiskAccessExceptionRegressionTest.java new file mode 100644 index 0000000..78de8bc --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/GiiDiskAccessExceptionRegressionTest.java @@ -0,0 +1,211 @@ +/* + * 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; + +import static org.apache.geode.test.dunit.Host.getHost; +import static org.apache.geode.test.dunit.IgnoredException.addIgnoredException; +import static org.apache.geode.test.dunit.Invoke.invokeInEveryVM; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.io.File; +import java.io.IOException; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import org.apache.geode.cache.AttributesFactory; +import org.apache.geode.cache.DataPolicy; +import org.apache.geode.cache.DiskAccessException; +import org.apache.geode.cache.DiskStore; +import org.apache.geode.cache.DiskStoreFactory; +import org.apache.geode.cache.Region; +import org.apache.geode.cache.Scope; +import org.apache.geode.test.dunit.VM; +import org.apache.geode.test.dunit.cache.CacheTestCase; +import org.apache.geode.test.junit.categories.DistributedTest; +import org.apache.geode.test.junit.rules.serializable.SerializableTemporaryFolder; +import org.apache.geode.test.junit.rules.serializable.SerializableTestName; + +/** + * Tests that if a node doing GII experiences DiskAccessException, it should also not try to recover + * from the disk + * + * GiiDiskAccessExceptionRegressionTest + * + * <p> + * TRAC #39079: Regions with persistence remain in use after IOException have occurred + */ +@Category(DistributedTest.class) +public class GiiDiskAccessExceptionRegressionTest extends CacheTestCase { + + private String uniqueName; + + private File[] vm0DiskDirs; + private File[] vm1DiskDirs; + private File[] controllerDiskDirs; + + private VM vm0; + private VM vm1; + + @Rule + public SerializableTemporaryFolder temporaryFolder = new SerializableTemporaryFolder(); + + @Rule + public SerializableTestName testName = new SerializableTestName(); + + @Before + public void setUp() throws Exception { + vm0 = getHost(0).getVM(0); + vm1 = getHost(0).getVM(1); + + uniqueName = getClass().getSimpleName() + "_" + testName.getMethodName(); + + vm0DiskDirs = new File[] {temporaryFolder.newFolder(uniqueName + "_vm0_disk")}; + vm1DiskDirs = new File[] {temporaryFolder.newFolder(uniqueName + "_vm1_disk")}; + controllerDiskDirs = new File[] {temporaryFolder.newFolder(uniqueName + "_controller_disk")}; + + DiskStoreImpl.SET_IGNORE_PREALLOCATE = true; + + invokeInEveryVM(() -> { + DiskStoreImpl.SET_IGNORE_PREALLOCATE = true; + }); + + addIgnoredException(uniqueName); + } + + @After + public void tearDown() throws Exception { + disconnectAllFromDS(); + + DiskStoreImpl.SET_IGNORE_PREALLOCATE = false; + + invokeInEveryVM(() -> { + DiskStoreImpl.SET_IGNORE_PREALLOCATE = false; + }); + } + + /** + * If the node experiences disk access exception during GII, it should get destroyed & not attempt + * to recover from the disk + */ + @Test + public void diskAccessExceptionDuringGiiShouldShutdown() throws Exception { + vm0.invoke(() -> createCacheForVM0()); + vm1.invoke(() -> createCacheForVM1()); + + // Create DiskRegion locally in controller VM also + DiskStoreFactory diskStoreFactory = getCache().createDiskStoreFactory(); + diskStoreFactory.setDiskDirs(controllerDiskDirs); + + DiskStore diskStore = diskStoreFactory.create(uniqueName); + + AttributesFactory factory = new AttributesFactory(); + factory.setScope(Scope.DISTRIBUTED_ACK); + factory.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE); + factory.setDiskSynchronous(false); + factory.setDiskStoreName(diskStore.getName()); + + Region<Integer, Integer> region = getCache().createRegion(uniqueName, factory.create()); + + // Now put entries in the disk region + for (int i = 0; i < 100; ++i) { + region.put(i, i); + } + + // Now close the region in the controller VM + region.close(); + + // Now recreate the region but set the factory such that disk region entry object + // used is customized by us to throw exception while writing to disk + + DistributedRegion distributedRegion = new DistributedRegion(uniqueName, factory.create(), null, + getCache(), new InternalRegionArguments().setDestroyLockFlag(true).setRecreateFlag(false) + .setSnapshotInputStream(null).setImageTarget(null)); + + distributedRegion.entries.setEntryFactory(new DiskRegionEntryThrowsFactory()); + + InternalRegionArguments internalRegionArguments = new InternalRegionArguments(); + internalRegionArguments.setInternalMetaRegion(distributedRegion); + internalRegionArguments.setDestroyLockFlag(true); + internalRegionArguments.setSnapshotInputStream(null); + internalRegionArguments.setImageTarget(null); + + assertThatThrownBy( + () -> getCache().createVMRegion(uniqueName, factory.create(), internalRegionArguments)) + .isInstanceOf(DiskAccessException.class); + } + + /** + * This method is used to create Cache in VM0 + */ + private void createCacheForVM0() { + DiskStoreFactory diskStoreFactory = getCache().createDiskStoreFactory(); + diskStoreFactory.setDiskDirs(vm0DiskDirs); + + DiskStore diskStore = diskStoreFactory.create(uniqueName); + + AttributesFactory factory = new AttributesFactory(); + factory.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE); + factory.setDiskStoreName(diskStore.getName()); + factory.setDiskSynchronous(false); + factory.setScope(Scope.DISTRIBUTED_ACK); + + getCache().createRegion(uniqueName, factory.create()); + } + + /** + * This method is used to create Cache in VM1 + */ + private void createCacheForVM1() { + DiskStoreFactory diskStoreFactory = getCache().createDiskStoreFactory(); + diskStoreFactory.setDiskDirs(vm1DiskDirs); + + DiskStore diskStore = diskStoreFactory.create(uniqueName); + + AttributesFactory factory = new AttributesFactory(); + factory.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE); + factory.setDiskStoreName(diskStore.getName()); + factory.setDiskSynchronous(false); + factory.setScope(Scope.DISTRIBUTED_ACK); + + getCache().createRegion(uniqueName, factory.create()); + } + + private class DiskRegionEntryThrowsFactory implements RegionEntryFactory { + + @Override + public RegionEntry createEntry(RegionEntryContext context, Object key, Object value) { + throw new DiskAccessException(new IOException(uniqueName)); + } + + @Override + public Class getEntryClass() { + return getClass(); + } + + @Override + public RegionEntryFactory makeVersioned() { + return this; + } + + @Override + public RegionEntryFactory makeOnHeap() { + return this; + } + } +} diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/InitializedDiskRegionWithIoExceptionRegressionTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/InitializedDiskRegionWithIoExceptionRegressionTest.java new file mode 100644 index 0000000..53b0823 --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/InitializedDiskRegionWithIoExceptionRegressionTest.java @@ -0,0 +1,174 @@ +/* + * 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; + +import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS; +import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT; +import static org.apache.geode.test.dunit.Host.getHost; +import static org.apache.geode.test.dunit.IgnoredException.addIgnoredException; +import static org.apache.geode.test.dunit.Invoke.invokeInEveryVM; +import static org.apache.geode.test.dunit.NetworkUtils.getServerHostName; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Properties; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import org.apache.geode.cache.AttributesFactory; +import org.apache.geode.cache.DiskAccessException; +import org.apache.geode.cache.Region; +import org.apache.geode.cache.Scope; +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.internal.cache.persistence.DiskRecoveryStore; +import org.apache.geode.internal.cache.persistence.UninterruptibleFileChannel; +import org.apache.geode.test.dunit.VM; +import org.apache.geode.test.dunit.cache.CacheTestCase; +import org.apache.geode.test.junit.categories.DistributedTest; +import org.apache.geode.test.junit.rules.serializable.SerializableTemporaryFolder; +import org.apache.geode.test.junit.rules.serializable.SerializableTestName; + +/** + * If IOException occurs while updating an entry in an already initialized DiskRegion, then the + * cache server should be stopped. + * + * <p> + * TRAC #39079: Regions with persistence remain in use after IOException have occurred + */ +@Category(DistributedTest.class) +public class InitializedDiskRegionWithIoExceptionRegressionTest extends CacheTestCase { + + private String hostName; + private String uniqueName; + + private File[] serverDiskDirs; + + private VM server; + private VM client; + + @Rule + public SerializableTemporaryFolder temporaryFolder = new SerializableTemporaryFolder(); + + @Rule + public SerializableTestName testName = new SerializableTestName(); + + @Before + public void setUp() throws Exception { + server = getHost(0).getVM(0); + client = getHost(0).getVM(1); + + uniqueName = getClass().getSimpleName() + "_" + testName.getMethodName(); + + serverDiskDirs = new File[] {temporaryFolder.newFolder(uniqueName + "_server1_disk")}; + + hostName = getServerHostName(server.getHost()); + + DiskStoreImpl.SET_IGNORE_PREALLOCATE = true; + + invokeInEveryVM(() -> { + DiskStoreImpl.SET_IGNORE_PREALLOCATE = true; + }); + + addIgnoredException(uniqueName); + } + + @After + public void tearDown() throws Exception { + disconnectAllFromDS(); + + DiskStoreImpl.SET_IGNORE_PREALLOCATE = false; + + invokeInEveryVM(() -> { + DiskStoreImpl.SET_IGNORE_PREALLOCATE = false; + }); + } + + @Test + public void cacheServerPersistWithIOExceptionShouldShutdown() throws Exception { + // create server cache + int port = server.invoke(() -> createServerCache()); + + // create cache client + client.invoke(() -> createClientCache(hostName, port)); + + // validate + server.invoke(() -> validateNoCacheServersRunning()); + } + + private int createServerCache() throws IOException { + DiskRegionProperties props = new DiskRegionProperties(); + props.setRegionName(uniqueName); + props.setOverflow(true); + props.setRolling(true); + props.setDiskDirs(serverDiskDirs); + props.setPersistBackup(true); + + DiskRegionHelperFactory.getSyncPersistOnlyRegion(getCache(), props, Scope.DISTRIBUTED_ACK); + + CacheServer cacheServer = getCache().addCacheServer(); + cacheServer.setPort(0); + cacheServer.start(); + return cacheServer.getPort(); + } + + private void validateNoCacheServersRunning() throws IOException { + Region<String, byte[]> region = getCache().getRegion(uniqueName); + + region.create("key1", new byte[16]); + region.create("key2", new byte[16]); + + // Get the oplog handle & hence the underlying file & close it + UninterruptibleFileChannel oplogFileChannel = + ((LocalRegion) region).getDiskRegion().testHook_getChild().getFileChannel(); + oplogFileChannel.close(); + + assertThatThrownBy(() -> region.put("key2", new byte[16])) + .isInstanceOf(DiskAccessException.class); + + ((DiskRecoveryStore) region).getDiskStore().waitForClose(); + assertThat(region.getRegionService().isClosed()).isTrue(); + + List<CacheServer> cacheServers = getCache().getCacheServers(); + assertThat(cacheServers).isEmpty(); + } + + private void createClientCache(String host, int port) { + Properties config = new Properties(); + config.setProperty(MCAST_PORT, "0"); + config.setProperty(LOCATORS, ""); + getCache(config); + + Pool pool = PoolManager.createFactory().addServer(host, port).setSubscriptionEnabled(true) + .setSubscriptionRedundancy(0).setThreadLocalConnections(true).setMinConnections(0) + .setReadTimeout(20000).setRetryAttempts(1).create(uniqueName); + + AttributesFactory factory = new AttributesFactory(); + factory.setScope(Scope.DISTRIBUTED_ACK); + factory.setPoolName(pool.getName()); + + Region region = getCache().createRegion(uniqueName, factory.create()); + + region.registerInterest("ALL_KEYS"); + } +} -- To stop receiving notification emails like this one, please contact [email protected].
