Repository: geode Updated Branches: refs/heads/develop 1aec1f835 -> e606f3e6e
GEODE-1672: Disabled recovering values for LRU region during startup. When recovering persistent files, system stores the values in temp maps (for regions) using a background thread, as these maps are not actual regions, the temp-regions are not considered/included for LRU eviction, which causes the system to run OOM. The problem is fixed by skipping recovering values for LRU regions. A new system property ""disk.recoverLruValues" is added to support reading values for lru regions. Project: http://git-wip-us.apache.org/repos/asf/geode/repo Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/e606f3e6 Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/e606f3e6 Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/e606f3e6 Branch: refs/heads/develop Commit: e606f3e6ec0828f5fc30e20a9dbdf3aa8c3c8620 Parents: 1aec1f8 Author: Anil <aging...@pivotal.io> Authored: Wed Feb 1 11:23:25 2017 -0800 Committer: Anil <aging...@pivotal.io> Committed: Wed Feb 1 11:23:25 2017 -0800 ---------------------------------------------------------------------- .../geode/internal/cache/DiskStoreImpl.java | 10 + .../org/apache/geode/internal/cache/Oplog.java | 40 ++- .../cache/DiskLruRegRecoveryJUnitTest.java | 290 +++++++++++++++++++ .../cache/DiskRegRecoveryJUnitTest.java | 8 + .../internal/cache/DiskRegionHelperFactory.java | 26 ++ .../internal/cache/DiskRegionProperties.java | 12 +- .../PersistentPartitionedRegionJUnitTest.java | 137 +++++++++ 7 files changed, 508 insertions(+), 15 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/geode/blob/e606f3e6/geode-core/src/main/java/org/apache/geode/internal/cache/DiskStoreImpl.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/DiskStoreImpl.java b/geode-core/src/main/java/org/apache/geode/internal/cache/DiskStoreImpl.java index 5affdb5..e53aa5d 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/cache/DiskStoreImpl.java +++ b/geode-core/src/main/java/org/apache/geode/internal/cache/DiskStoreImpl.java @@ -124,10 +124,20 @@ public class DiskStoreImpl implements DiskStore { DistributionConfig.GEMFIRE_PREFIX + "disk.recoverValues"; public static final String RECOVER_VALUES_SYNC_PROPERTY_NAME = DistributionConfig.GEMFIRE_PREFIX + "disk.recoverValuesSync"; + + /** + * Allows recovering values for LRU regions. By default values are not recovered for LRU regions + * during recovery. + */ + public static final String RECOVER_LRU_VALUES_PROPERTY_NAME = + DistributionConfig.GEMFIRE_PREFIX + "disk.recoverLruValues"; + boolean RECOVER_VALUES = getBoolean(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME, true); boolean RECOVER_VALUES_SYNC = getBoolean(DiskStoreImpl.RECOVER_VALUES_SYNC_PROPERTY_NAME, false); boolean FORCE_KRF_RECOVERY = getBoolean(DistributionConfig.GEMFIRE_PREFIX + "disk.FORCE_KRF_RECOVERY", false); + final boolean RECOVER_LRU_VALUES = + getBoolean(DiskStoreImpl.RECOVER_LRU_VALUES_PROPERTY_NAME, false); public static boolean getBoolean(String sysProp, boolean def) { return Boolean.valueOf(System.getProperty(sysProp, Boolean.valueOf(def).toString())); http://git-wip-us.apache.org/repos/asf/geode/blob/e606f3e6/geode-core/src/main/java/org/apache/geode/internal/cache/Oplog.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/Oplog.java b/geode-core/src/main/java/org/apache/geode/internal/cache/Oplog.java index 32d6e30..0b98364 100755 --- a/geode-core/src/main/java/org/apache/geode/internal/cache/Oplog.java +++ b/geode-core/src/main/java/org/apache/geode/internal/cache/Oplog.java @@ -47,11 +47,13 @@ import org.apache.geode.internal.util.BlobHelper; import org.apache.geode.internal.util.IOUtils; import org.apache.geode.internal.util.TransformUtils; import org.apache.geode.pdx.internal.PdxWriterImpl; + import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectIterator; + import org.apache.logging.log4j.Logger; import java.io.*; @@ -2421,6 +2423,24 @@ public final class Oplog implements CompactableOplog, Flushable { } /** + * Returns true if the values for the given disk recovery store should be recovered. + */ + private boolean recoverLruValue(DiskRecoveryStore drs) { + if (isLruValueRecoveryDisabled(drs)) { + return false; + } else if (drs.lruLimitExceeded()) { + this.stats.incRecoveredValuesSkippedDueToLRU(); + return false; + } + return true; + } + + private boolean isLruValueRecoveryDisabled(DiskRecoveryStore store) { + return !store.getDiskStore().isOffline() && !getParent().RECOVER_LRU_VALUES + && !store.getEvictionAttributes().getAlgorithm().isNone(); + } + + /** * Reads an oplog entry of type Create * * @param dis DataInputStream from which the oplog is being read @@ -2465,10 +2485,10 @@ public final class Oplog implements CompactableOplog, Flushable { this.stats.incRecoveryRecordsSkipped(); incSkipped(); } - } else if (recoverValue && drs.lruLimitExceeded() && !getParent().isOfflineCompacting()) { - this.stats.incRecoveredValuesSkippedDueToLRU(); - recoverValue = false; + } else if (recoverValue && !getParent().isOfflineCompacting()) { + recoverValue = recoverLruValue(drs); } + CompactionRecord p2cr = null; long crOffset; if (EntryBits.isAnyInvalid(userBits) || EntryBits.isTombstone(userBits)) { @@ -2659,9 +2679,8 @@ public final class Oplog implements CompactableOplog, Flushable { incSkipped(); this.stats.incRecoveryRecordsSkipped(); } - } else if (recoverValue && drs.lruLimitExceeded() && !getParent().isOfflineCompacting()) { - this.stats.incRecoveredValuesSkippedDueToLRU(); - recoverValue = false; + } else if (recoverValue && !getParent().isOfflineCompacting()) { + recoverValue = recoverLruValue(drs); } byte[] objValue = null; @@ -2884,9 +2903,8 @@ public final class Oplog implements CompactableOplog, Flushable { incSkipped(); this.stats.incRecoveryRecordsSkipped(); } - } else if (recoverValue && drs.lruLimitExceeded() && !getParent().isOfflineCompacting()) { - this.stats.incRecoveredValuesSkippedDueToLRU(); - recoverValue = false; + } else if (recoverValue && !getParent().isOfflineCompacting()) { + recoverValue = recoverLruValue(drs); } byte[] objValue = null; @@ -6176,15 +6194,13 @@ public final class Oplog implements CompactableOplog, Flushable { HashMap<Long, DiskRegionInfo> targetRegions = new HashMap<Long, DiskRegionInfo>(this.regionMap); synchronized (diskRecoveryStores) { - // Don't bother to include any stores that have reached the lru limit Iterator<DiskRecoveryStore> itr = diskRecoveryStores.values().iterator(); while (itr.hasNext()) { DiskRecoveryStore store = itr.next(); - if (store.lruLimitExceeded()) { + if (isLruValueRecoveryDisabled(store) || store.lruLimitExceeded()) { itr.remove(); } } - // Get the a sorted list of live entries from the target regions targetRegions.keySet().retainAll(diskRecoveryStores.keySet()); } http://git-wip-us.apache.org/repos/asf/geode/blob/e606f3e6/geode-core/src/test/java/org/apache/geode/internal/cache/DiskLruRegRecoveryJUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/DiskLruRegRecoveryJUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/DiskLruRegRecoveryJUnitTest.java new file mode 100644 index 0000000..0bf3b38 --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/DiskLruRegRecoveryJUnitTest.java @@ -0,0 +1,290 @@ +/* + * 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.junit.Assert.*; + +import java.util.concurrent.CountDownLatch; + +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.apache.geode.cache.EntryNotFoundException; +import org.apache.geode.cache.Region; +import org.apache.geode.cache.Scope; +import org.apache.geode.test.junit.categories.IntegrationTest; + +/** + * Disk LRU region recovery tests. + */ +@Category(IntegrationTest.class) +public class DiskLruRegRecoveryJUnitTest extends DiskRegionTestingBase { + + @Override + protected final void postTearDown() throws Exception { + DiskStoreObserver.setInstance(null); + } + + private int getValuesInVM(Region region, int size) { + int valuesInVm = 0; + for (int i = 0; i < size; i++) { + try { + Object value = ((LocalRegion) region).getValueInVM(new Integer(i)); + if (value != null) { + valuesInVm++; + } + } catch (EntryNotFoundException e) { + fail("Entry not found not expected but occured "); + } + } + return valuesInVm; + } + + private Region createNonLruRegion() { + DiskRegionProperties nonLruDiskProps = new DiskRegionProperties(); + nonLruDiskProps.setDiskDirs(dirs); + nonLruDiskProps.setPersistBackup(true); + nonLruDiskProps.setRegionName("RecoveryTestNonLruRegion"); + return DiskRegionHelperFactory.getSyncPersistOnlyRegion(cache, nonLruDiskProps, Scope.LOCAL); + } + + private void createRegionAndIntiateRecovery(boolean lruEntryEviction, + boolean recoveryByCacheClose, boolean addNonLruRegion, int load, int expectedValues) { + + DiskRegionProperties diskProps = new DiskRegionProperties(); + Region nonLruRegion = null; + + diskProps.setDiskDirs(dirs); + diskProps.setPersistBackup(true); + diskProps.setRegionName("RecoveryTestRegion"); + + if (lruEntryEviction) { + int overflowCapacity = 5; + diskProps.setOverFlowCapacity(overflowCapacity); + region = DiskRegionHelperFactory.getSyncOverFlowAndPersistRegion(cache, diskProps); + } else { + region = DiskRegionHelperFactory.getSyncHeapLruAndPersistRegion(cache, diskProps); + } + + if (addNonLruRegion) { + nonLruRegion = createNonLruRegion(); + } + + for (int i = 0; i < load; i++) { + region.put(new Integer(i), new Integer(i)); + if (nonLruRegion != null) { + nonLruRegion.put(new Integer(i), new Integer(i)); + } + } + + if (recoveryByCacheClose) { + cache.close(); + cache = createCache(); + } else { + region.close(); + if (nonLruRegion != null) { + nonLruRegion.close(); + } + } + + final CountDownLatch recoveryDone = new CountDownLatch(1); + DiskStoreObserver.setInstance(new DiskStoreObserver() { + @Override + public void afterAsyncValueRecovery(DiskStoreImpl store) { + recoveryDone.countDown(); + } + }); + + if (lruEntryEviction) { + region = DiskRegionHelperFactory.getSyncOverFlowAndPersistRegion(cache, diskProps); + } else { + region = DiskRegionHelperFactory.getSyncHeapLruAndPersistRegion(cache, diskProps); + } + + if (addNonLruRegion) { + nonLruRegion = createNonLruRegion(); + } + + // Wait for recovery to finish. + try { + recoveryDone.await(); + } catch (InterruptedException ie) { + fail("Found interrupted exception while waiting for recovery."); + } + + int valuesInVm = getValuesInVM(region, load); + assertEquals("Values for lru regions should not be recovered from Disk.", expectedValues, valuesInVm); + + if (nonLruRegion != null) { + valuesInVm = getValuesInVM(nonLruRegion, load); + // The values should be recovered for non LRU regions. + assertEquals("Values for non lru regions are not recovered from Disk.", load, valuesInVm); + } + } + + @Test + public void testValuesAreNotRecoveredForLruRegionWithCacheClose() { + createRegionAndIntiateRecovery(true, true, false, 10, 0); + } + + @Test + public void testValuesAreNotRecoveredForLruRegionWithRegionClose() { + createRegionAndIntiateRecovery(true, false, false, 10, 0); + } + + @Test + public void testValuesAreNotRecoveredForLruAndRecoveredForNonLru() { + createRegionAndIntiateRecovery(true, true, true, 10, 0); + } + + @Test + public void testValuesAreNotRecoveredForLruAndRecoveredForNonLruWithRegionClose() { + createRegionAndIntiateRecovery(true, false, true, 10, 0); + } + + @Test + public void testValuesAreNotRecoveredForHeapLruRegion() { + createRegionAndIntiateRecovery(false, true, true, 10, 0); + } + + @Test + public void testValuesAreNotRecoveredForHeapLruRegionWithRegionClose() { + createRegionAndIntiateRecovery(false, false, true, 10, 0); + } + + @Test + public void testValuesAreNotRecoveredForLruRegionWithReocoverValuePropertySet() { + String oldValue = System.getProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME); + System.setProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME, "true"); + + try { + createRegionAndIntiateRecovery(true, true, true, 10, 0); + } finally { + if (oldValue != null) { + System.setProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME, oldValue); + } else { + System.clearProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME); + } + } + } + + @Test + public void testValuesAreNotRecoveredForLruRegionWithReocoverValuePropertySetWithRegionClose() { + String oldValue = System.getProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME); + System.setProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME, "true"); + + try { + createRegionAndIntiateRecovery(true, false, true, 10, 0); + } finally { + if (oldValue != null) { + System.setProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME, oldValue); + } else { + System.clearProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME); + } + } + } + + @Test + public void testValuesAreRecoveredForLruRegionWithReocoverValueAndRecoverLruPropertySet() { + String oldValue = System.getProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME); + System.setProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME, "true"); + + String lruOldValue = System.getProperty(DiskStoreImpl.RECOVER_LRU_VALUES_PROPERTY_NAME); + System.setProperty(DiskStoreImpl.RECOVER_LRU_VALUES_PROPERTY_NAME, "true"); + + try { + createRegionAndIntiateRecovery(false, true, true, 10, 10); + } finally { + if (oldValue != null) { + System.setProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME, oldValue); + } else { + System.clearProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME); + } + + if (lruOldValue != null) { + System.setProperty(DiskStoreImpl.RECOVER_LRU_VALUES_PROPERTY_NAME, lruOldValue); + } else { + System.clearProperty(DiskStoreImpl.RECOVER_LRU_VALUES_PROPERTY_NAME); + } + } + } + + @Test + public void testValuesAreRecoveredForLruRegionWithReocoverValueAndRecoverLruPropertySetWithRegionClose() { + String oldValue = System.getProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME); + System.setProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME, "true"); + + String lruOldValue = System.getProperty(DiskStoreImpl.RECOVER_LRU_VALUES_PROPERTY_NAME); + System.setProperty(DiskStoreImpl.RECOVER_LRU_VALUES_PROPERTY_NAME, "true"); + + try { + createRegionAndIntiateRecovery(false, false, true, 10, 10); + } finally { + if (oldValue != null) { + System.setProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME, oldValue); + } else { + System.clearProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME); + } + + if (lruOldValue != null) { + System.setProperty(DiskStoreImpl.RECOVER_LRU_VALUES_PROPERTY_NAME, lruOldValue); + } else { + System.clearProperty(DiskStoreImpl.RECOVER_LRU_VALUES_PROPERTY_NAME); + } + } + } + + @Test + public void testBasicVerifyStats() { + DiskRegionProperties diskProps = new DiskRegionProperties(); + final Integer key = 1; + diskProps.setDiskDirs(dirs); + diskProps.setPersistBackup(true); + diskProps.setRegionName("basicVerifyStats"); + region = DiskRegionHelperFactory.getSyncOverFlowAndPersistRegion(cache, diskProps); + region.put(key, new Integer(1)); + region.put(key, new Integer(2)); + region.close(); + + final CountDownLatch recoveryDone = new CountDownLatch(1); + DiskStoreObserver.setInstance(new DiskStoreObserver() { + @Override + public void afterAsyncValueRecovery(DiskStoreImpl store) { + recoveryDone.countDown(); + } + }); + + region = DiskRegionHelperFactory.getSyncOverFlowAndPersistRegion(cache, diskProps); + // Wait for recovery to finish. + try { + recoveryDone.await(); + } catch (InterruptedException ie) { + fail("Found interrupted exception while waiting for recovery."); + } + + DiskRegion dr = ((LocalRegion) region).getDiskRegion(); + assertEquals(0, dr.getNumEntriesInVM()); + assertEquals(1, dr.getNumOverflowOnDisk()); + + region.get(key); + assertEquals(1, dr.getNumEntriesInVM()); + assertEquals(0, dr.getNumOverflowOnDisk()); + + region.clear(); + assertEquals(0, dr.getNumEntriesInVM()); + assertEquals(0, dr.getNumOverflowOnDisk()); + } + +} + http://git-wip-us.apache.org/repos/asf/geode/blob/e606f3e6/geode-core/src/test/java/org/apache/geode/internal/cache/DiskRegRecoveryJUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/DiskRegRecoveryJUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/DiskRegRecoveryJUnitTest.java index 6a5c338..d6ee1ea 100644 --- a/geode-core/src/test/java/org/apache/geode/internal/cache/DiskRegRecoveryJUnitTest.java +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/DiskRegRecoveryJUnitTest.java @@ -515,7 +515,9 @@ public class DiskRegRecoveryJUnitTest extends DiskRegionTestingBase { @Test public void testNoEvictionDuringRecoveryIfNoGIIRecoverValuesTrue() { String oldValue = System.getProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME); + String oldLruValue = System.getProperty(DiskStoreImpl.RECOVER_LRU_VALUES_PROPERTY_NAME); System.setProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME, "true"); + System.setProperty(DiskStoreImpl.RECOVER_LRU_VALUES_PROPERTY_NAME, "true"); try { diskProps.setDiskDirs(dirs); diskProps.setPersistBackup(true); @@ -560,6 +562,12 @@ public class DiskRegRecoveryJUnitTest extends DiskRegionTestingBase { } else { System.clearProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME); } + + if (oldLruValue != null) { + System.setProperty(DiskStoreImpl.RECOVER_LRU_VALUES_PROPERTY_NAME, oldLruValue); + } else { + System.clearProperty(DiskStoreImpl.RECOVER_LRU_VALUES_PROPERTY_NAME); + } } } http://git-wip-us.apache.org/repos/asf/geode/blob/e606f3e6/geode-core/src/test/java/org/apache/geode/internal/cache/DiskRegionHelperFactory.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/DiskRegionHelperFactory.java b/geode-core/src/test/java/org/apache/geode/internal/cache/DiskRegionHelperFactory.java index fa68044..4ad246f 100755 --- a/geode-core/src/test/java/org/apache/geode/internal/cache/DiskRegionHelperFactory.java +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/DiskRegionHelperFactory.java @@ -17,6 +17,7 @@ package org.apache.geode.internal.cache; import java.io.File; import org.apache.geode.cache.*; +import org.apache.geode.cache.util.ObjectSizer; /** * @@ -76,6 +77,9 @@ public class DiskRegionHelperFactory { factory.setEvictionAttributes( EvictionAttributes.createLRUEntryAttributes(capacity, EvictionAction.OVERFLOW_TO_DISK)); + } else if (diskProps.isHeapEviction()) { + factory.setEvictionAttributes(EvictionAttributes.createLRUHeapAttributes(ObjectSizer.DEFAULT, + EvictionAction.OVERFLOW_TO_DISK)); } factory.setConcurrencyLevel(diskProps.getConcurrencyLevel()); @@ -158,6 +162,28 @@ public class DiskRegionHelperFactory { return getRegion(cache, diskRegionProperties, Scope.LOCAL); } + public static Region getSyncHeapLruAndPersistRegion(Cache cache, + DiskRegionProperties diskRegionProperties) { + if (diskRegionProperties == null) { + diskRegionProperties = new DiskRegionProperties(); + } + diskRegionProperties.setPersistBackup(true); + diskRegionProperties.setSynchronous(true); + diskRegionProperties.setHeapEviction(true); + return getRegion(cache, diskRegionProperties, Scope.LOCAL); + } + + public static Region getAsyncHeapLruAndPersistRegion(Cache cache, + DiskRegionProperties diskRegionProperties) { + if (diskRegionProperties == null) { + diskRegionProperties = new DiskRegionProperties(); + } + diskRegionProperties.setPersistBackup(true); + diskRegionProperties.setSynchronous(false); + diskRegionProperties.setHeapEviction(true); + return getRegion(cache, diskRegionProperties, Scope.LOCAL); + } + public static Region getSyncPersistOnlyRegionInfiniteOplog(Cache cache, DiskRegionProperties diskRegionProperties, String regionName) { if (diskRegionProperties == null) { http://git-wip-us.apache.org/repos/asf/geode/blob/e606f3e6/geode-core/src/test/java/org/apache/geode/internal/cache/DiskRegionProperties.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/DiskRegionProperties.java b/geode-core/src/test/java/org/apache/geode/internal/cache/DiskRegionProperties.java index 19662bf..e7299c0 100755 --- a/geode-core/src/test/java/org/apache/geode/internal/cache/DiskRegionProperties.java +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/DiskRegionProperties.java @@ -50,6 +50,7 @@ public class DiskRegionProperties { private int initialCapacity = 16; private float loadFactor = 0.75f; private boolean statisticsEnabled = false; + private boolean isHeapEviction = false; public DiskRegionProperties() {} @@ -66,6 +67,10 @@ public class DiskRegionProperties { return isOverflow; } + public boolean isHeapEviction() { + return isHeapEviction; + } + public boolean isPersistBackup() { return isPersistBackup; } @@ -128,6 +133,10 @@ public class DiskRegionProperties { this.isOverflow = isOverflow; } + public void setHeapEviction(boolean isHeapEviction) { + this.isHeapEviction = isHeapEviction; + } + public void setPersistBackup(boolean isPersistBackup) { this.isPersistBackup = isPersistBackup; } @@ -160,17 +169,14 @@ public class DiskRegionProperties { this.timeInterval = timeInterval; } - public String getRegionName() { return regionName; } - public void setRegionName(String regionName) { this.regionName = regionName; } - public void setStatisticsEnabled(boolean v) { this.statisticsEnabled = v; } http://git-wip-us.apache.org/repos/asf/geode/blob/e606f3e6/geode-core/src/test/java/org/apache/geode/internal/cache/PersistentPartitionedRegionJUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/PersistentPartitionedRegionJUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/PersistentPartitionedRegionJUnitTest.java index b0170e1..a72b069 100644 --- a/geode-core/src/test/java/org/apache/geode/internal/cache/PersistentPartitionedRegionJUnitTest.java +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/PersistentPartitionedRegionJUnitTest.java @@ -15,6 +15,7 @@ package org.apache.geode.internal.cache; import org.apache.geode.cache.*; +import org.apache.geode.cache.util.ObjectSizer; import org.apache.geode.internal.FileUtil; import org.apache.geode.test.junit.categories.IntegrationTest; import org.junit.After; @@ -24,9 +25,11 @@ import org.junit.experimental.categories.Category; import java.io.File; import java.util.Properties; +import java.util.concurrent.CountDownLatch; import static org.apache.geode.distributed.ConfigurationProperties.*; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; @Category(IntegrationTest.class) public class PersistentPartitionedRegionJUnitTest { @@ -190,7 +193,132 @@ public class PersistentPartitionedRegionJUnitTest { assertEquals(1000, bucket.getDiskRegion().getStats().getNumEntriesInVM()); } + @Test + public void testValuesAreNotRecoveredForHeapLruRegions() { + createLRURegionAndValidateRecovery(false, true, 10, 0); + } + + @Test + public void testValuesAreNotRecoveredForHeapLruRegionsWithRegionClose() { + createLRURegionAndValidateRecovery(true, true, 10, 0); + } + + @Test + public void testValuesAreNotRecoveredForHeapLruRegionsWithRecoverPropertySet() { + String oldValue = System.getProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME); + System.setProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME, "true"); + + try { + createLRURegionAndValidateRecovery(false, true, 10, 0); + } finally { + if (oldValue != null) { + System.setProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME, oldValue); + } else { + System.clearProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME); + } + } + } + + @Test + public void testValuesAreRecoveredForHeapLruRegionsWithRecoverValueAndRecoverLruPropertySet() { + String oldValue = System.getProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME); + System.setProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME, "true"); + + String lruOldValue = System.getProperty(DiskStoreImpl.RECOVER_LRU_VALUES_PROPERTY_NAME); + System.setProperty(DiskStoreImpl.RECOVER_LRU_VALUES_PROPERTY_NAME, "true"); + + try { + createLRURegionAndValidateRecovery(false, true, 10, 10); + } finally { + if (oldValue != null) { + System.setProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME, oldValue); + } else { + System.clearProperty(DiskStoreImpl.RECOVER_VALUE_PROPERTY_NAME); + } + + if (lruOldValue != null) { + System.setProperty(DiskStoreImpl.RECOVER_LRU_VALUES_PROPERTY_NAME, lruOldValue); + } else { + System.clearProperty(DiskStoreImpl.RECOVER_LRU_VALUES_PROPERTY_NAME); + } + } + } + + @Test + public void testValuesAreNotRecoveredForEntryLruRegion() { + createLRURegionAndValidateRecovery(false, false, 10, 0); + } + + @Test + public void testValuesAreNotRecoveredForEntryLruRegionWithRegionClose() { + createLRURegionAndValidateRecovery(true, false, 10, 0); + } + + private void createLRURegionAndValidateRecovery(boolean isRegionClose, boolean heapLru, int size, int expectedInMemory) { + PartitionedRegion region; + boolean entryLru = !heapLru; + region = (PartitionedRegion) createRegion(-1, heapLru, entryLru); + + for (int i = 0; i < size; i++) { + region.put(new Integer(i), new Integer(i)); + } + + if (isRegionClose) { + region.close(); + } else { + cache.close(); + } + + final CountDownLatch recoveryDone = new CountDownLatch(1); + DiskStoreObserver.setInstance(new DiskStoreObserver() { + @Override + public void afterAsyncValueRecovery(DiskStoreImpl store) { + recoveryDone.countDown(); + } + }); + region = (PartitionedRegion) createRegion(-1, heapLru, entryLru); + + // Wait for recovery to finish. + try { + recoveryDone.await(); + } catch (InterruptedException ie) { + fail("Found interrupted exception while waiting for recovery."); + } + + int valuesInVm = getValuesInVM(region, size); + assertEquals("Values for lru regions should not be recovered from Disk.", expectedInMemory, valuesInVm); + + BucketRegion bucket = region.getBucketRegion("A"); + assertEquals((size - expectedInMemory), bucket.getDiskRegion().getStats().getNumOverflowOnDisk()); + assertEquals(expectedInMemory, bucket.getDiskRegion().getStats().getNumEntriesInVM()); + + // Load values into memory using get. + for (int i = 0; i < size; i++) { + region.get(new Integer(i)); + } + assertEquals(size, bucket.getDiskRegion().getStats().getNumEntriesInVM()); + } + + private int getValuesInVM(Region region, int size) { + int valuesInVm = 0; + for (int i = 0; i < size; i++) { + try { + Object value = ((LocalRegion) region).getValueInVM(new Integer(i)); + if (value != null) { + valuesInVm++; + } + } catch (EntryNotFoundException e) { + fail("Entry not found not expected but occured "); + } + } + return valuesInVm; + } + private Region createRegion(int ttl) { + return createRegion(ttl, false, false); + } + + private Region createRegion(int ttl, boolean isHeapEviction, boolean isEntryEviction) { Properties props = new Properties(); props.setProperty(MCAST_PORT, "0"); props.setProperty(LOG_LEVEL, "info"); @@ -205,6 +333,15 @@ public class PersistentPartitionedRegionJUnitTest { if (ttl > 0) { rf.setEntryTimeToLive(new ExpirationAttributes(ttl, ExpirationAction.DESTROY)); } + + if (isEntryEviction) { + rf.setEvictionAttributes( + EvictionAttributes.createLRUEntryAttributes(10, EvictionAction.OVERFLOW_TO_DISK)); + } else if (isHeapEviction) { + rf.setEvictionAttributes(EvictionAttributes.createLRUHeapAttributes(ObjectSizer.DEFAULT, + EvictionAction.OVERFLOW_TO_DISK)); + } + Region region = rf.create("region"); return region; }