blob: 935003e264b940c8c2980efd67d1191a2c7dc19f [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.internal.cache;
import static java.lang.System.getProperties;
import static java.util.Map.Entry;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.util.Properties;
import org.junit.Test;
import org.apache.geode.cache.AttributesFactory;
import org.apache.geode.cache.CacheException;
import org.apache.geode.cache.CacheListener;
import org.apache.geode.cache.DiskStore;
import org.apache.geode.cache.DiskStoreFactory;
import org.apache.geode.cache.EntryEvent;
import org.apache.geode.cache.EvictionAction;
import org.apache.geode.cache.EvictionAttributes;
import org.apache.geode.cache.InterestPolicy;
import org.apache.geode.cache.Operation;
import org.apache.geode.cache.PartitionAttributes;
import org.apache.geode.cache.PartitionAttributesFactory;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionAttributes;
import org.apache.geode.cache.SubscriptionAttributes;
import org.apache.geode.cache.util.CacheListenerAdapter;
import org.apache.geode.cache.util.ObjectSizer;
import org.apache.geode.cache30.CacheSerializableRunnable;
import org.apache.geode.internal.cache.control.HeapMemoryMonitor;
import org.apache.geode.internal.cache.control.InternalResourceManager.ResourceType;
import org.apache.geode.internal.cache.eviction.HeapEvictor;
import org.apache.geode.internal.cache.eviction.HeapLRUController;
import org.apache.geode.logging.internal.OSProcess;
import org.apache.geode.test.awaitility.GeodeAwaitility;
import org.apache.geode.test.dunit.Assert;
import org.apache.geode.test.dunit.Host;
import org.apache.geode.test.dunit.IgnoredException;
import org.apache.geode.test.dunit.SerializableCallable;
import org.apache.geode.test.dunit.SerializableRunnable;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.WaitCriterion;
import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase;
public class PartitionedRegionEvictionDUnitTest extends JUnit4CacheTestCase {
@Test
public void testHeapLRUWithOverflowToDisk() {
// Ignore this excetion as this can happen if pool is shutting down
IgnoredException
.addIgnoredException(java.util.concurrent.RejectedExecutionException.class.getName());
final Host host = Host.getHost(0);
final VM vm2 = host.getVM(2);
final VM vm3 = host.getVM(3);
final String uniqName = getUniqueName();
final float heapPercentage = 50.9f;
final int redundantCopies = 1;
final int evictorInterval = 100;
final String name = uniqName + "-PR";
final CacheSerializableRunnable create =
new CacheSerializableRunnable("Create Heap LRU with Overflow to disk partitioned Region") {
@Override
public void run2() {
System.setProperty(HeapLRUController.TOP_UP_HEAP_EVICTION_PERCENTAGE_PROPERTY,
Float.toString(0));
setEvictionPercentage(heapPercentage);
final Properties sp = System.getProperties();
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(
new PartitionAttributesFactory().setRedundantCopies(redundantCopies).create());
factory.setEvictionAttributes(
EvictionAttributes.createLRUHeapAttributes(null, EvictionAction.OVERFLOW_TO_DISK));
factory.setDiskSynchronous(true);
DiskStoreFactory dsf = getCache().createDiskStoreFactory();
final File[] diskDirs = new File[1];
diskDirs[0] = new File("overflowDir/" + uniqName + "_" + OSProcess.getId());
diskDirs[0].mkdirs();
dsf.setDiskDirs(diskDirs);
DiskStore ds = dsf.create(name);
factory.setDiskStoreName(ds.getName());
final PartitionedRegion pr =
(PartitionedRegion) createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
vm3.invoke(create);
vm2.invoke(create);
final int bucketsToCreate = 3;
final SerializableRunnable createBuckets = new SerializableRunnable("Create Buckets") {
@Override
public void run() {
setEvictionPercentage(heapPercentage);
final PartitionedRegion pr = (PartitionedRegion) getRootRegion(name);
assertNotNull(pr);
// Create three buckets, add enough stuff in each to force two
// overflow
// ops in each
for (int i = 0; i < bucketsToCreate; i++) {
// assume mod-based hashing for bucket creation
pr.put(i, "value0");
pr.put(i + pr.getPartitionAttributes().getTotalNumBuckets(), "value1");
pr.put(i + (pr.getPartitionAttributes().getTotalNumBuckets()) * 2, "value2");
}
}
};
vm3.invoke(createBuckets);
final SerializableCallable assertBucketAttributesAndEviction =
new SerializableCallable("Assert bucket attributes and eviction") {
@Override
public Object call() throws Exception {
try {
setEvictionPercentage(heapPercentage);
final Properties sp = getProperties();
final int expectedInvocations = 10;
final int maximumWaitSeconds = 60; // seconds
final int pollWaitMillis = evictorInterval * 2;
assertTrue(pollWaitMillis < (SECONDS.toMillis(maximumWaitSeconds) * 4));
final PartitionedRegion pr = (PartitionedRegion) getRootRegion(name);
assertNotNull(pr);
for (final Entry<Integer, BucketRegion> integerBucketRegionEntry : pr.getDataStore()
.getAllLocalBuckets()) {
final Entry entry = (Entry) integerBucketRegionEntry;
final BucketRegion bucketRegion = (BucketRegion) entry.getValue();
if (bucketRegion == null) {
continue;
}
assertTrue(bucketRegion.getAttributes().getEvictionAttributes().getAlgorithm()
.isLRUHeap());
assertTrue(bucketRegion.getAttributes().getEvictionAttributes().getAction()
.isOverflowToDisk());
}
raiseFakeNotification();
WaitCriterion wc = new WaitCriterion() {
String excuse;
@Override
public boolean done() {
// we have a primary
return pr.getDiskRegionStats().getNumOverflowOnDisk() == 9;
}
@Override
public String description() {
return excuse;
}
};
GeodeAwaitility.await().untilAsserted(wc);
int entriesEvicted = 0;
entriesEvicted += pr.getDiskRegionStats().getNumOverflowOnDisk();
return entriesEvicted;
} finally {
cleanUpAfterFakeNotification();
// Clean up the observer for future tests
// final Properties sp = System.getProperties();
/*
* assertNotNull(sp .remove(HeapLRUCapacityController.FREE_MEMORY_OBSERVER));
*/
}
}
};
final Integer v2i = (Integer) vm2.invoke(assertBucketAttributesAndEviction);
final Integer v3i = (Integer) vm3.invoke(assertBucketAttributesAndEviction);
final int totalEvicted = v2i + v3i;
// assume all three entries in each bucket were evicted to disk
assertEquals((3 * bucketsToCreate * (redundantCopies + 1)), totalEvicted);
}
protected void raiseFakeNotification() {
getCache().getHeapEvictor().setTestAbortAfterLoopCount(1);
HeapMemoryMonitor.setTestDisableMemoryUpdates(true);
setEvictionPercentage(85);
HeapMemoryMonitor hmm =
getCache().getInternalResourceManager().getHeapMonitor();
hmm.setTestMaxMemoryBytes(100);
hmm.updateStateAndSendEvent(90, "test");
}
protected void cleanUpAfterFakeNotification() {
getCache().getHeapEvictor().setTestAbortAfterLoopCount(Integer.MAX_VALUE);
HeapMemoryMonitor.setTestDisableMemoryUpdates(false);
}
@Test
public void testHeapLRUWithLocalDestroy() {
// Ignore this excetion as this can happen if pool is shutting down
IgnoredException
.addIgnoredException(java.util.concurrent.RejectedExecutionException.class.getName());
final Host host = Host.getHost(0);
final VM vm2 = host.getVM(2);
final VM vm3 = host.getVM(3);
final String uniqName = getUniqueName();
final float heapPercentage = 50.9f;
final int redundantCopies = 1;
final int evictorInterval = 100;
final String name = uniqName + "-PR";
final SerializableRunnable create = new CacheSerializableRunnable(
"Create Heap LRU with local destroy on a partitioned Region") {
@Override
public void run2() {
System.setProperty(HeapLRUController.TOP_UP_HEAP_EVICTION_PERCENTAGE_PROPERTY,
Float.toString(0));
setEvictionPercentage(heapPercentage);
final Properties sp = System.getProperties();
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(
new PartitionAttributesFactory().setRedundantCopies(redundantCopies).create());
factory.setEvictionAttributes(EvictionAttributes.createLRUHeapAttributes());
final PartitionedRegion pr = (PartitionedRegion) createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
vm3.invoke(create);
vm2.invoke(create);
final int bucketsToCreate = 3;
final SerializableRunnable createBuckets = new SerializableRunnable("Create Buckets") {
@Override
public void run() {
final PartitionedRegion pr = (PartitionedRegion) getRootRegion(name);
assertNotNull(pr);
// Create three buckets, add enough stuff in each to force two
// overflow
// ops in each
for (int i = 0; i < bucketsToCreate; i++) {
// assume mod-based hashing for bucket creation
pr.put(i, "value0");
pr.put(i + pr.getPartitionAttributes().getTotalNumBuckets(), "value1");
pr.put(i + (pr.getPartitionAttributes().getTotalNumBuckets()) * 2, "value2");
}
}
};
vm3.invoke(createBuckets);
final SerializableCallable assertBucketAttributesAndEviction =
new SerializableCallable("Assert bucket attributes and eviction") {
@Override
public Object call() throws Exception {
try {
final Properties sp = getProperties();
final int expectedInvocations = 10;
final int maximumWaitSeconds = 60; // seconds
final int pollWaitMillis = evictorInterval * 2;
assertTrue(pollWaitMillis < (SECONDS.toMillis(maximumWaitSeconds) * 4));
final PartitionedRegion pr = (PartitionedRegion) getRootRegion(name);
assertNotNull(pr);
long entriesEvicted = 0;
for (final Entry<Integer, BucketRegion> integerBucketRegionEntry : pr.getDataStore()
.getAllLocalBuckets()) {
final Entry entry = (Entry) integerBucketRegionEntry;
final BucketRegion bucketRegion = (BucketRegion) entry.getValue();
if (bucketRegion == null) {
continue;
}
assertTrue(bucketRegion.getAttributes().getEvictionAttributes().getAlgorithm()
.isLRUHeap());
assertTrue(bucketRegion.getAttributes().getEvictionAttributes().getAction()
.isLocalDestroy());
}
raiseFakeNotification();
WaitCriterion wc = new WaitCriterion() {
String excuse;
@Override
public boolean done() {
// we have a primary
return pr.getTotalEvictions() == 9;
}
@Override
public String description() {
return excuse;
}
};
GeodeAwaitility.await().untilAsserted(wc);
entriesEvicted = pr.getTotalEvictions();
return entriesEvicted;
} finally {
cleanUpAfterFakeNotification();
// Clean up the observer for future tests
// final Properties sp = System.getProperties();
/*
* assertNotNull(sp .remove(HeapLRUCapacityController.FREE_MEMORY_OBSERVER));
*/
}
}
};
final Long v2i = (Long) vm2.invoke(assertBucketAttributesAndEviction);
final Long v3i = (Long) vm3.invoke(assertBucketAttributesAndEviction);
final int totalEvicted = v2i.intValue() + v3i.intValue();
// assume all three entries in each bucket were evicted to disk
assertEquals((3 * bucketsToCreate * (redundantCopies + 1)), totalEvicted);
}
@Test
public void testMemoryLRUWithOverflowToDisk() {
final Host host = Host.getHost(0);
final VM vm2 = host.getVM(2);
final VM vm3 = host.getVM(3);
final VM vm0 = host.getVM(0);
final String uniqName = getUniqueName();
final int redundantCopies = 1;
final int maxBuckets = 8;
final int localMaxMem = 16;
final int halfKb = 512;
final int justShyOfTwoMb = (2 * 1024 * 1024) - halfKb;
final String name = uniqName + "-PR";
final SerializableRunnable create =
new SerializableRunnable("Create Memory LRU with Overflow to disk partitioned Region") {
@Override
public void run() {
try {
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(
new PartitionAttributesFactory().setRedundantCopies(redundantCopies)
.setLocalMaxMemory(localMaxMem).setTotalNumBuckets(maxBuckets).create());
factory.setEvictionAttributes(EvictionAttributes
.createLRUMemoryAttributes(ObjectSizer.DEFAULT, EvictionAction.OVERFLOW_TO_DISK));
factory.setDiskSynchronous(true);
DiskStoreFactory dsf = getCache().createDiskStoreFactory();
final File[] diskDirs = new File[1];
diskDirs[0] = new File("overflowDir/" + uniqName + "_" + OSProcess.getId());
diskDirs[0].mkdirs();
dsf.setDiskDirs(diskDirs);
DiskStore ds = dsf.create(name);
factory.setDiskStoreName(ds.getName());
final PartitionedRegion pr =
(PartitionedRegion) createRootRegion(name, factory.create());
assertNotNull(pr);
} catch (final CacheException ex) {
Assert.fail("While creating Partitioned region", ex);
}
}
};
vm3.invoke(create);
vm2.invoke(create);
final int extraEntries = 4;
final SerializableRunnable createBuckets = new SerializableRunnable("Create Buckets") {
@Override
public void run() {
final PartitionedRegion pr = (PartitionedRegion) getRootRegion(name);
assertNotNull(pr);
for (int counter = 1; counter <= localMaxMem + extraEntries; counter++) {
pr.put(counter, new byte[1 * 1024 * 1024]);
}
}
};
vm3.invoke(createBuckets);
final SerializableCallable assertBucketAttributesAndEviction =
new SerializableCallable("Assert bucket attributes and eviction") {
@Override
public Object call() throws Exception {
final PartitionedRegion pr = (PartitionedRegion) getRootRegion(name);
assertNotNull(pr);
assertNull(pr.getDiskRegion());
// assert over-flow behavior in local buckets and number of
// entries
// overflowed
long entriesEvicted = 0;
for (final Entry<Integer, BucketRegion> integerBucketRegionEntry : pr.getDataStore()
.getAllLocalBuckets()) {
final Entry entry = (Entry) integerBucketRegionEntry;
final BucketRegion bucketRegion = (BucketRegion) entry.getValue();
if (bucketRegion == null) {
continue;
}
assertTrue(bucketRegion.getAttributes().getEvictionAttributes().getAlgorithm()
.isLRUMemory());
assertTrue(bucketRegion.getAttributes().getEvictionAttributes().getAction()
.isOverflowToDisk());
}
entriesEvicted += pr.getDiskRegionStats().getNumOverflowOnDisk();
return entriesEvicted;
}
};
final Long vm2i = (Long) vm2.invoke(assertBucketAttributesAndEviction);
final Long vm3i = (Long) vm3.invoke(assertBucketAttributesAndEviction);
final int totalEvicted = vm2i.intValue() + vm3i.intValue();
assertTrue(2 * extraEntries <= totalEvicted);
// Test for bug 42056 - make sure we get the faulted out entries.
vm0.invoke(create);
vm0.invoke(new SerializableRunnable("Test to see that we can get keys") {
@Override
public void run() {
final PartitionedRegion pr = (PartitionedRegion) getRootRegion(name);
// Make sure we can get all of the entries
for (int counter = 1; counter <= localMaxMem + extraEntries; counter++) {
assertNotNull(pr.get(counter));
}
}
});
}
@Test
public void testMemoryLRUWithLocalDestroy() {
final Host host = Host.getHost(0);
final VM vm2 = host.getVM(2);
final VM vm3 = host.getVM(3);
final String uniqName = getUniqueName();
final int redundantCopies = 1;
final int maxBuckets = 8;
final int localMaxMem = 16;
final int halfKb = 512;
final int justShyOfTwoMb = (2 * 1024 * 1024) - halfKb;
final String name = uniqName + "-PR";
final SerializableRunnable create = new CacheSerializableRunnable(
"Create Memory LRU with local destroy on a partitioned Region") {
@Override
public void run2() {
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(
new PartitionAttributesFactory().setRedundantCopies(redundantCopies)
.setLocalMaxMemory(16).setTotalNumBuckets(maxBuckets).create());
factory.setEvictionAttributes(EvictionAttributes
.createLRUMemoryAttributes(ObjectSizer.DEFAULT, EvictionAction.LOCAL_DESTROY));
final PartitionedRegion pr = (PartitionedRegion) createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
vm3.invoke(create);
vm2.invoke(create);
final int extraEntries = 4;
final SerializableRunnable createBuckets = new SerializableRunnable("Create Buckets") {
@Override
public void run() {
final PartitionedRegion pr = (PartitionedRegion) getRootRegion(name);
assertNotNull(pr);
for (int counter = 1; counter <= localMaxMem + extraEntries; counter++) {
pr.put(counter, new byte[1 * 1024 * 1024]);
}
}
};
vm3.invoke(createBuckets);
final SerializableCallable assertBucketAttributesAndEviction =
new SerializableCallable("Assert bucket attributes and eviction") {
@Override
public Object call() throws Exception {
try {
final PartitionedRegion pr = (PartitionedRegion) getRootRegion(name);
assertNotNull(pr);
long entriesEvicted = 0;
for (final Entry<Integer, BucketRegion> integerBucketRegionEntry : pr.getDataStore()
.getAllLocalBuckets()) {
final Entry entry = (Entry) integerBucketRegionEntry;
final BucketRegion bucketRegion = (BucketRegion) entry.getValue();
if (bucketRegion == null) {
continue;
}
assertTrue(bucketRegion.getAttributes().getEvictionAttributes().getAlgorithm()
.isLRUMemory());
assertTrue(bucketRegion.getAttributes().getEvictionAttributes().getAction()
.isLocalDestroy());
}
entriesEvicted = pr.getTotalEvictions();
return entriesEvicted;
} finally {
}
}
};
final Long v2i = (Long) vm2.invoke(assertBucketAttributesAndEviction);
final Long v3i = (Long) vm3.invoke(assertBucketAttributesAndEviction);
final int totalEvicted = v2i.intValue() + v3i.intValue();
assertTrue(2 * extraEntries <= totalEvicted);
}
@Test
public void testEntryLRUWithOverflowToDisk() {
final Host host = Host.getHost(0);
final VM vm2 = host.getVM(2);
final VM vm3 = host.getVM(3);
final String uniqName = getUniqueName();
final int redundantCopies = 1;
final int maxBuckets = 8;
final int maxEntries = 16;
final String name = uniqName + "-PR";
final SerializableRunnable create =
new SerializableRunnable("Create Entry LRU with Overflow to disk partitioned Region") {
@Override
public void run() {
try {
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(new PartitionAttributesFactory()
.setRedundantCopies(redundantCopies).setTotalNumBuckets(maxBuckets).create());
factory.setEvictionAttributes(EvictionAttributes.createLRUEntryAttributes(maxEntries,
EvictionAction.OVERFLOW_TO_DISK));
factory.setDiskSynchronous(true);
DiskStoreFactory dsf = getCache().createDiskStoreFactory();
final File[] diskDirs = new File[1];
diskDirs[0] = new File("overflowDir/" + uniqName + "_" + OSProcess.getId());
diskDirs[0].mkdirs();
dsf.setDiskDirs(diskDirs);
DiskStore ds = dsf.create(name);
factory.setDiskStoreName(ds.getName());
final PartitionedRegion pr =
(PartitionedRegion) createRootRegion(name, factory.create());
assertNotNull(pr);
} catch (final CacheException ex) {
Assert.fail("While creating Partitioned region", ex);
}
}
};
vm3.invoke(create);
vm2.invoke(create);
final int extraEntries = 4;
final SerializableRunnable createBuckets = new SerializableRunnable("Create Buckets") {
@Override
public void run() {
final PartitionedRegion pr = (PartitionedRegion) getRootRegion(name);
assertNotNull(pr);
for (int counter = 1; counter <= maxEntries + extraEntries; counter++) {
pr.put(counter, new byte[1 * 1024 * 1024]);
}
}
};
vm3.invoke(createBuckets);
final SerializableCallable assertBucketAttributesAndEviction =
new SerializableCallable("Assert bucket attributes and eviction") {
@Override
public Object call() throws Exception {
final PartitionedRegion pr = (PartitionedRegion) getRootRegion(name);
assertNotNull(pr);
// assert over-flow behavior in local buckets and number of
// entries
// overflowed
int entriesEvicted = 0;
for (final Entry<Integer, BucketRegion> integerBucketRegionEntry : pr.getDataStore()
.getAllLocalBuckets()) {
final Entry entry = (Entry) integerBucketRegionEntry;
final BucketRegion bucketRegion = (BucketRegion) entry.getValue();
if (bucketRegion == null) {
continue;
}
assertTrue(
bucketRegion.getAttributes().getEvictionAttributes().getAlgorithm().isLRUEntry());
assertTrue(bucketRegion.getAttributes().getEvictionAttributes().getAction()
.isOverflowToDisk());
}
entriesEvicted += pr.getDiskRegionStats().getNumOverflowOnDisk();
return entriesEvicted;
}
};
final Integer vm2i = (Integer) vm2.invoke(assertBucketAttributesAndEviction);
final Integer vm3i = (Integer) vm3.invoke(assertBucketAttributesAndEviction);
final int totalEvicted = vm2i + vm3i;
assertEquals(extraEntries * 2, totalEvicted);
}
private static class VerifiableCacheListener extends CacheListenerAdapter
implements java.io.Serializable {
public boolean verify(long expectedEvictions) {
return false;
}
}
@Test
public void testEntryLRUWithLocalDestroy() {
final Host host = Host.getHost(0);
final VM vm2 = host.getVM(2);
final VM vm3 = host.getVM(3);
final String uniqName = getUniqueName();
final int redundantCopies = 1;
final int maxBuckets = 8;
final int maxEntries = 16;
final String name = uniqName + "-PR";
final int extraEntries = 4;
// final int heapPercentage = 66;
// final int evictorInterval = 100;
final SerializableRunnable create = new CacheSerializableRunnable(
"Create Entry LRU with local destroy on a partitioned Region") {
@Override
public void run2() {
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(new PartitionAttributesFactory()
.setRedundantCopies(redundantCopies).setTotalNumBuckets(maxBuckets).create());
factory.setEvictionAttributes(
EvictionAttributes.createLRUEntryAttributes(maxEntries, EvictionAction.LOCAL_DESTROY));
factory.addCacheListener(new VerifiableCacheListener() {
private long evictionDestroyEvents = 0;
@Override
public void afterDestroy(EntryEvent e) {
System.out.println("EEEEEEEEEEEEEE key:" + e.getKey());
EntryEventImpl eei = (EntryEventImpl) e;
if (Operation.EVICT_DESTROY.equals(eei.getOperation())) {
evictionDestroyEvents++;
}
}
@Override
public boolean verify(long expectedEntries) {
return expectedEntries == evictionDestroyEvents;
}
});
final PartitionedRegion pr = (PartitionedRegion) createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
vm3.invoke(create);
final SerializableRunnable create2 =
new SerializableRunnable("Create Entry LRU with local destroy on a partitioned Region") {
@Override
public void run() {
try {
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(new PartitionAttributesFactory()
.setRedundantCopies(redundantCopies).setTotalNumBuckets(8).create());
factory
.setEvictionAttributes(EvictionAttributes.createLRUEntryAttributes(maxEntries));
final PartitionedRegion pr =
(PartitionedRegion) createRootRegion(name, factory.create());
assertNotNull(pr);
} catch (final CacheException ex) {
Assert.fail("While creating Partitioned region", ex);
}
}
};
vm2.invoke(create2);
final SerializableRunnable createBuckets = new SerializableRunnable("Create Buckets") {
@Override
public void run() {
final PartitionedRegion pr = (PartitionedRegion) getRootRegion(name);
assertNotNull(pr);
for (int counter = 1; counter <= maxEntries + extraEntries; counter++) {
pr.put(counter, new byte[1 * 1024 * 1024]);
}
}
};
vm3.invoke(createBuckets);
final SerializableCallable assertBucketAttributesAndEviction =
new SerializableCallable("Assert bucket attributes and eviction") {
@Override
public Object call() throws Exception {
try {
final PartitionedRegion pr = (PartitionedRegion) getRootRegion(name);
assertNotNull(pr);
for (final Entry<Integer, BucketRegion> integerBucketRegionEntry : pr.getDataStore()
.getAllLocalBuckets()) {
final Entry entry = (Entry) integerBucketRegionEntry;
final BucketRegion bucketRegion = (BucketRegion) entry.getValue();
if (bucketRegion == null) {
continue;
}
assertTrue(bucketRegion.getAttributes().getEvictionAttributes().getAlgorithm()
.isLRUEntry());
assertTrue(bucketRegion.getAttributes().getEvictionAttributes().getAction()
.isLocalDestroy());
}
return pr.getTotalEvictions();
} finally {
}
}
};
final Long v2i = (Long) vm2.invoke(assertBucketAttributesAndEviction);
final Long v3i = (Long) vm3.invoke(assertBucketAttributesAndEviction);
final int totalEvicted = v2i.intValue() + v3i.intValue();
assertEquals(2 * extraEntries, totalEvicted);
final SerializableCallable assertListenerCount = new SerializableCallable(
"Assert that the number of listener invocations matches the expected total") {
@Override
public Object call() throws Exception {
final PartitionedRegion pr = (PartitionedRegion) getRootRegion(name);
assertNotNull(pr);
RegionAttributes attrs = pr.getAttributes();
assertNotNull(attrs);
long entriesEvicted = pr.getTotalEvictions();
VerifiableCacheListener verifyMe = null;
for (CacheListener listener : attrs.getCacheListeners()) {
if (listener instanceof VerifiableCacheListener) {
verifyMe = ((VerifiableCacheListener) listener);
}
}
assertNotNull(verifyMe); // assert if unable to find the expected listener
return verifyMe.verify(entriesEvicted);
}
};
assertTrue((Boolean) vm3.invoke(assertListenerCount));
}
// Test to validate the Eviction Attribute : LRU Check
@Test
public void testEvictionValidationForLRUEntry() {
final Host host = Host.getHost(0);
final VM testAccessor = host.getVM(1);
final VM testDatastore = host.getVM(2);
final VM firstDatastore = host.getVM(3);
final String uniqName = getUniqueName();
final int redundantCopies = 1;
final int maxEntries = 226;
final String name = uniqName + "-PR";
// final int evictionSizeInMB = 200;
final EvictionAttributes firstEvictionAttrs =
EvictionAttributes.createLRUEntryAttributes(maxEntries, EvictionAction.LOCAL_DESTROY);
// Creating LRU Entry Count Eviction Attribute
final SerializableRunnable create = new CacheSerializableRunnable(
"Create Entry LRU with local destroy on a partitioned Region") {
@Override
public void run2() {
// Assert that LRUEntry maximum can be less than 1 entry per
// bucket
// DUnit not required for this test, but its a convenient place
// to put it.
{
final int buks = 11;
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(new PartitionAttributesFactory().setTotalNumBuckets(buks)
.setRedundantCopies(0).create());
factory.setEvictionAttributes(EvictionAttributes.createLRUEntryAttributes((buks / 2)));
final PartitionedRegion pr = (PartitionedRegion) createRootRegion(name, factory.create());
final Integer key = 1;
pr.put(key, "testval");
final BucketRegion b;
try {
b = pr.getDataStore().getInitializedBucketForId(key,
PartitionedRegionHelper.getHashKey(pr, null, key, null, null));
} catch (final ForceReattemptException e) {
fail();
}
pr.destroyRegion();
}
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(
new PartitionAttributesFactory().setRedundantCopies(redundantCopies).create());
factory.setEvictionAttributes(firstEvictionAttrs);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
firstDatastore.invoke(create);
final SerializableRunnable create2 =
new SerializableRunnable("Create Entry LRU with Overflow to disk partitioned Region") {
@Override
public void run() {
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(
new PartitionAttributesFactory().setRedundantCopies(redundantCopies).create());
// Assert a different algo is invalid
try {
getCache().getLogger().info(
"<ExpectedException action=add>" + "IllegalStateException</ExpectedException>");
assertTrue(!firstEvictionAttrs.getAlgorithm().isLRUHeap());
final EvictionAttributes illegalEa =
EvictionAttributes.createLRUHeapAttributes(null, firstEvictionAttrs.getAction());
assertTrue(!firstEvictionAttrs.equals(illegalEa));
factory.setEvictionAttributes(illegalEa);
setEvictionPercentage(50);
createRootRegion(name, factory.create());
fail("Creating LRU Entry Count Eviction Attribute");
} catch (final IllegalStateException expected) {
assertTrue(expected.getMessage().contains(
PartitionRegionConfigValidator.EVICTION_ATTRIBUTES_ARE_INCOMPATIBLE_MESSAGE));
} finally {
getCache().getLogger().info("<ExpectedException action=remove>"
+ "IllegalStateException</ExpectedException>");
}
// Assert a different action is invalid
try {
getCache().getLogger().info(
"<ExpectedException action=add>" + "IllegalStateException</ExpectedException>");
assertTrue(firstEvictionAttrs.getAlgorithm().isLRUEntry());
assertTrue(!firstEvictionAttrs.getAction().isOverflowToDisk());
final EvictionAttributes illegalEa = EvictionAttributes.createLRUEntryAttributes(
firstEvictionAttrs.getMaximum(), EvictionAction.OVERFLOW_TO_DISK);
assertTrue(!firstEvictionAttrs.equals(illegalEa));
factory.setEvictionAttributes(illegalEa);
createRootRegion(name, factory.create());
fail("Creating LRU Entry Count Eviction Attribute");
} catch (final IllegalStateException expected) {
assertTrue(expected.getMessage().contains(
PartitionRegionConfigValidator.EVICTION_ATTRIBUTES_ARE_INCOMPATIBLE_MESSAGE));
} finally {
getCache().getLogger().info("<ExpectedException action=remove>"
+ "IllegalStateException</ExpectedException>");
}
assertTrue(firstEvictionAttrs.getAlgorithm().isLRUEntry());
final EvictionAttributes brokenEa = EvictionAttributes.createLRUEntryAttributes(
firstEvictionAttrs.getMaximum() + 1, firstEvictionAttrs.getAction());
assertTrue(!firstEvictionAttrs.equals(brokenEa));
factory.setEvictionAttributes(brokenEa);
createRootRegion(name, factory.create());
}
};
testDatastore.invoke(create2);
testAccessor.invoke(
new CacheSerializableRunnable("Create an Accessor with and without eviction attributes") {
@Override
public void run2() throws CacheException {
final PartitionAttributes pra = new PartitionAttributesFactory()
.setRedundantCopies(redundantCopies).setLocalMaxMemory(0).create();
AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(pra);
factory.setEvictionAttributes(firstEvictionAttrs);
setEvictionPercentage(50);
Region r1 = createRootRegion(name, factory.create());
assertNotNull(r1);
assertEquals(firstEvictionAttrs, r1.getAttributes().getEvictionAttributes());
}
});
}
// Test to validate the Eviction Attribute : LRU Action
@Test
public void testEvictionValidationForLRUAction() {
final Host host = Host.getHost(0);
final VM testDatastore = host.getVM(2);
final VM firstDatastore = host.getVM(3);
final String uniqName = getUniqueName();
final int redundantCopies = 1;
final int maxEntries = 226;
final String name = uniqName + "-PR";
final EvictionAttributes firstEa =
EvictionAttributes.createLRUEntryAttributes(maxEntries, EvictionAction.LOCAL_DESTROY);
// Creating LRU Entry Count Eviction Attribute : Algorithm :
// LOCAL_DESTROY
final SerializableRunnable create = new CacheSerializableRunnable(
"Create Entry LRU with local destroy on a partitioned Region") {
@Override
public void run2() {
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(
new PartitionAttributesFactory().setRedundantCopies(redundantCopies).create());
factory.setEvictionAttributes(firstEa);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
assertEquals(firstEa, pr.getAttributes().getEvictionAttributes());
}
};
firstDatastore.invoke(create);
final SerializableRunnable create2 =
new SerializableRunnable("Create Entry LRU with Overflow to disk partitioned Region") {
@Override
public void run() {
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(
new PartitionAttributesFactory().setRedundantCopies(redundantCopies).create());
// Creating LRU Entry Count Eviction Attribute : Action :
// OVERFLOW_TO_DISK // Exception should occur
try {
getCache().getLogger().info(
"<ExpectedException action=add>" + "IllegalStateException</ExpectedException>");
assertTrue(firstEa.getAlgorithm().isLRUEntry());
assertTrue(!firstEa.getAction().isOverflowToDisk());
factory.setEvictionAttributes(EvictionAttributes.createLRUEntryAttributes(maxEntries,
EvictionAction.OVERFLOW_TO_DISK));
createRootRegion(name, factory.create());
fail("Test to validate the Eviction Attribute : LRU Action");
} catch (final IllegalStateException expected) {
assertTrue(expected.getMessage().contains(
PartitionRegionConfigValidator.EVICTION_ATTRIBUTES_ARE_INCOMPATIBLE_MESSAGE));
} finally {
getCache().getLogger().info("<ExpectedException action=remove>"
+ "IllegalStateException</ExpectedException>");
}
// Creating LRU Entry Count Eviction Attribute : Action : NONE
// // Exception should occur
try {
getCache().getLogger().info(
"<ExpectedException action=add>" + "IllegalStateException</ExpectedException>");
assertTrue(firstEa.getAlgorithm().isLRUEntry());
assertTrue(!firstEa.getAction().isNone());
factory.setEvictionAttributes(
EvictionAttributes.createLRUEntryAttributes(maxEntries, EvictionAction.NONE));
createRootRegion(name, factory.create());
fail("Test to validate the Eviction Attribute : LRU Action");
} catch (final IllegalStateException expected) {
assertTrue(expected.getMessage().contains(
PartitionRegionConfigValidator.EVICTION_ATTRIBUTES_ARE_INCOMPATIBLE_MESSAGE));
} finally {
getCache().getLogger().info("<ExpectedException action=remove>"
+ "IllegalStateException</ExpectedException>");
}
// Creating LRU Entry Count Eviction Attribute : Action :
// LOCAL_DESTROY // Exception should not occur
factory.setEvictionAttributes(firstEa);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
assertEquals(firstEa, pr.getAttributes().getEvictionAttributes());
}
};
testDatastore.invoke(create2);
}
// Test to validate the Eviction Attribute : LRU Maximum
@Test
public void testEvictionValidationForLRUMaximum() {
final Host host = Host.getHost(0);
final VM testDatastore = host.getVM(2);
final VM firstDatastore = host.getVM(3);
final String uniqName = getUniqueName();
final int redundantCopies = 1;
final int maxEntries = 226;
final String name = uniqName + "-PR";
final EvictionAttributes firstEvictionAttributes =
EvictionAttributes.createLRUEntryAttributes(maxEntries, EvictionAction.LOCAL_DESTROY);
// Creating LRU Entry Count Eviction Attribute : maxentries : 2
final SerializableRunnable create = new CacheSerializableRunnable(
"Create Entry LRU with local destroy on a partitioned Region") {
@Override
public void run2() {
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(
new PartitionAttributesFactory().setRedundantCopies(redundantCopies).create());
factory.setEvictionAttributes(firstEvictionAttributes);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
assertEquals(firstEvictionAttributes, pr.getAttributes().getEvictionAttributes());
}
};
firstDatastore.invoke(create);
final SerializableRunnable create2 =
new SerializableRunnable("Create Entry LRU with Overflow to disk partitioned Region") {
@Override
public void run() {
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(
new PartitionAttributesFactory().setRedundantCopies(redundantCopies).create());
final EvictionAttributes ea = EvictionAttributes.createLRUEntryAttributes(
firstEvictionAttributes.getMaximum() + 10, firstEvictionAttributes.getAction());
factory.setEvictionAttributes(ea);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
testDatastore.invoke(create2);
}
// Test to validate the Eviction Attribute for LRUHeap
@Test
public void testEvictionValidationForLRUHeap() {
final Host host = Host.getHost(0);
final VM testDatastore = host.getVM(2);
final VM firstDatastore = host.getVM(3);
final String uniqName = getUniqueName();
final int redundantCopies = 1;
final String name = uniqName + "-PR";
final int heapPercentage = 66;
final int evictorInterval = 100;
final EvictionAttributes firstEvictionAttributes = EvictionAttributes.createLRUHeapAttributes();
// Creating Heap LRU Eviction Attribute : evictorInterval : 100
final SerializableRunnable create = new CacheSerializableRunnable(
"Create Entry LRU with local destroy on a partitioned Region") {
@Override
public void run2() {
getCache().getResourceManager().setEvictionHeapPercentage(heapPercentage);
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(
new PartitionAttributesFactory().setRedundantCopies(redundantCopies).create());
factory.setEvictionAttributes(firstEvictionAttributes);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
assertEquals(firstEvictionAttributes, pr.getAttributes().getEvictionAttributes());
}
};
firstDatastore.invoke(create);
final SerializableRunnable create2 =
new SerializableRunnable("Create Entry LRU with Overflow to disk partitioned Region") {
@Override
public void run() {
setEvictionPercentage(heapPercentage);
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(
new PartitionAttributesFactory().setRedundantCopies(redundantCopies).create());
// Assert that a different algo is invalid
try {
getCache().getLogger().info(
"<ExpectedException action=add>" + "IllegalStateException</ExpectedException>");
assertTrue(!firstEvictionAttributes.getAlgorithm().isLRUEntry());
final EvictionAttributes invalidEa = EvictionAttributes.createLRUEntryAttributes();
assertTrue(!invalidEa.equals(firstEvictionAttributes));
factory.setEvictionAttributes(invalidEa);
createRootRegion(name, factory.create());
fail("Expected an IllegalStateException");
} catch (final IllegalStateException expected) {
assertTrue(expected.getMessage().contains(
PartitionRegionConfigValidator.EVICTION_ATTRIBUTES_ARE_INCOMPATIBLE_MESSAGE));
} finally {
getCache().getLogger().info("<ExpectedException action=remove>"
+ "IllegalStateException</ExpectedException>");
}
// Assert that a different action is invalid
try {
getCache().getLogger().info(
"<ExpectedException action=add>" + "IllegalStateException</ExpectedException>");
assertTrue(firstEvictionAttributes.getAlgorithm().isLRUHeap());
assertTrue(!firstEvictionAttributes.getAction().isOverflowToDisk());
final EvictionAttributes invalidEa =
EvictionAttributes.createLRUHeapAttributes(null, EvictionAction.OVERFLOW_TO_DISK);
assertTrue(!invalidEa.equals(firstEvictionAttributes));
factory.setEvictionAttributes(invalidEa);
createRootRegion(name, factory.create());
fail("Expected an IllegalStateException");
} catch (final IllegalStateException expected) {
assertTrue(expected.getMessage().contains(
PartitionRegionConfigValidator.EVICTION_ATTRIBUTES_ARE_INCOMPATIBLE_MESSAGE));
} finally {
getCache().getLogger().info("<ExpectedException action=remove>"
+ "IllegalStateException</ExpectedException>");
}
// Assert that a different interval is valid
// {
// assertTrue(firstEvictionAttributes.getAlgorithm().isLRUHeap());
// final EvictionAttributes okHeapLRUea = EvictionAttributes
// .createLRUHeapAttributes((int)(firstEvictionAttributes.getInterval() + 100),
// firstEvictionAttributes.getAction());
// factory.setEvictionAttributes(okHeapLRUea);
// final Region pr = createRootRegion(name, factory.create());
// assertNotNull(pr);
// assertIndexDetailsEquals(okHeapLRUea, pr.getAttributes().getEvictionAttributes());
// pr.localDestroyRegion();
// }
// Assert that a different maximum is valid
// {
// assertTrue(firstEvictionAttributes.getAlgorithm().isLRUHeap());
// final EvictionAttributes okHeapLRUea = EvictionAttributes
// .createLRUHeapAttributes(
// (int)firstEvictionAttributes.getInterval(),
// firstEvictionAttributes.getAction());
// factory.setEvictionAttributes(okHeapLRUea);
// final Region pr = createRootRegion(name, factory.create());
// assertNotNull(pr);
// assertIndexDetailsEquals(okHeapLRUea, pr.getAttributes().getEvictionAttributes());
// pr.localDestroyRegion();
// }
// Assert that all attributes can be the same
{
factory.setEvictionAttributes(firstEvictionAttributes);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
assertEquals(firstEvictionAttributes, pr.getAttributes().getEvictionAttributes());
}
}
};
testDatastore.invoke(create2);
}
// Test to validate an accessor can set the initial attributes
@Test
public void testEvictionValidationWhenInitializedByAccessor() {
final Host host = Host.getHost(0);
final VM testDatastore = host.getVM(2);
final VM accessor = host.getVM(3);
final String uniqName = getUniqueName();
final int redundantCopies = 1;
final String name = uniqName;
final EvictionAttributes firstEvictionAttributes = EvictionAttributes
.createLRUMemoryAttributes(PartitionAttributesFactory.GLOBAL_MAX_BUCKETS_DEFAULT);
accessor.invoke(
new CacheSerializableRunnable("Create an Accessor which sets the first PR eviction attrs") {
@Override
public void run2() {
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(new PartitionAttributesFactory().setLocalMaxMemory(0)
.setRedundantCopies(redundantCopies).create());
factory.setEvictionAttributes(firstEvictionAttributes);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
assertNotSame(firstEvictionAttributes, pr.getAttributes().getEvictionAttributes());
assertEquals(firstEvictionAttributes, pr.getAttributes().getEvictionAttributes());
assertEquals(PartitionAttributesFactory.GLOBAL_MAX_BUCKETS_DEFAULT,
pr.getAttributes().getEvictionAttributes().getMaximum());
}
});
testDatastore.invoke(
new SerializableRunnable("Create a datastore to test existing eviction attributes") {
@Override
public void run() {
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(
new PartitionAttributesFactory().setRedundantCopies(redundantCopies).create());
// Assert that the same attrs is valid
factory.setEvictionAttributes(firstEvictionAttributes);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
assertNotSame(firstEvictionAttributes, pr.getAttributes().getEvictionAttributes());
assertNotSame(PartitionAttributesFactory.GLOBAL_MAX_BUCKETS_DEFAULT,
pr.getAttributes().getEvictionAttributes().getMaximum());
assertEquals(pr.getAttributes().getPartitionAttributes().getLocalMaxMemory(),
pr.getAttributes().getEvictionAttributes().getMaximum());
}
});
}
// Test to validate the Eviction Attribute : HeapLRU Interval
@Test
public void testEvictionValidationForLRUMemory() {
final Host host = Host.getHost(0);
final VM firstDatastore = host.getVM(1);
final VM testDatastore = host.getVM(2);
final VM testAccessor = host.getVM(3);
final String uniqName = getUniqueName();
final int redundantCopies = 1;
final String name = uniqName + "-PR";
final EvictionAttributes firstEvictionAttributes = EvictionAttributes
.createLRUMemoryAttributes(PartitionAttributesFactory.GLOBAL_MAX_BUCKETS_DEFAULT * 2);
firstDatastore
.invoke(new CacheSerializableRunnable("First datastore setting LRU memory eviction attrs") {
@Override
public void run2() {
// Assert that LRUMemory attributes may be lesser than 1 Mb per
// bucket
// DUnit not required for this test, but its a convenient place
// to put it.
{
final int totalNumBuckets = 11;
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(new PartitionAttributesFactory()
.setTotalNumBuckets(totalNumBuckets).setRedundantCopies(0).create());
factory.setEvictionAttributes(
EvictionAttributes.createLRUMemoryAttributes((totalNumBuckets / 2)));
final PartitionedRegion pr =
(PartitionedRegion) createRootRegion(name, factory.create());
final Integer key = 1;
pr.put(key, "testval");
final BucketRegion b;
try {
b = pr.getDataStore().getInitializedBucketForId(key,
PartitionedRegionHelper.getHashKey(pr, null, key, null, null));
} catch (final ForceReattemptException e) {
fail();
}
pr.destroyRegion();
}
// Set the "global" eviction attributes
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(
new PartitionAttributesFactory().setRedundantCopies(redundantCopies).create());
factory.setEvictionAttributes(firstEvictionAttributes);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
assertNotSame(firstEvictionAttributes, pr.getAttributes().getEvictionAttributes());
assertNotSame(PartitionAttributesFactory.GLOBAL_MAX_BUCKETS_DEFAULT,
pr.getAttributes().getEvictionAttributes().getMaximum());
assertEquals(pr.getAttributes().getPartitionAttributes().getLocalMaxMemory(),
pr.getAttributes().getEvictionAttributes().getMaximum());
}
});
class PRLRUMemoryRunnable extends CacheSerializableRunnable {
private static final long serialVersionUID = 1L;
final boolean isAccessor;
public PRLRUMemoryRunnable(final boolean accessor) {
super("Test LRU memory eviction attrs on a " + (accessor ? " accessor" : " datastore"));
isAccessor = accessor;
}
public PartitionAttributes createPartitionAttributes(final int localMaxMemory) {
if (isAccessor) {
return new PartitionAttributesFactory().setLocalMaxMemory(0)
.setRedundantCopies(redundantCopies).create();
} else {
return new PartitionAttributesFactory().setLocalMaxMemory(localMaxMemory)
.setRedundantCopies(redundantCopies).create();
}
}
@Override
public void run2() throws CacheException {
// Configure a PR with the same local max mem as the eviction
// attributes... and do these tests
PartitionAttributes pra = createPartitionAttributes(firstEvictionAttributes.getMaximum());
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(pra);
// Assert that no eviction attributes is invalid
try {
getCache().getLogger()
.info("<ExpectedException action=add>" + "IllegalStateException</ExpectedException>");
final RegionAttributes attrs = factory.create();
createRootRegion(name, attrs);
fail("Expected a IllegalStateException to be thrown");
} catch (final IllegalStateException expected) {
assertTrue(expected.getMessage().contains(
PartitionRegionConfigValidator.EVICTION_ATTRIBUTES_ARE_INCOMPATIBLE_MESSAGE));
} finally {
getCache().getLogger().info(
"<ExpectedException action=remove>" + "IllegalStateException</ExpectedException>");
}
// Assert different algo is invalid
try {
getCache().getLogger()
.info("<ExpectedException action=add>" + "IllegalStateException</ExpectedException>");
assertTrue(!((EvictionAttributesImpl) firstEvictionAttributes).isLIFOMemory());
final EvictionAttributes badEa =
EvictionAttributesImpl.createLIFOMemoryAttributes(100, EvictionAction.LOCAL_DESTROY);
assertTrue(!badEa.equals(firstEvictionAttributes));
factory.setEvictionAttributes(badEa);
createRootRegion(name, factory.create());
fail("Test to validate the Eviction Attribute : HeapLRU Interval");
} catch (final IllegalStateException expected) {
assertTrue(expected.getMessage().contains(
PartitionRegionConfigValidator.EVICTION_ATTRIBUTES_ARE_INCOMPATIBLE_MESSAGE));
} finally {
getCache().getLogger().info(
"<ExpectedException action=remove>" + "IllegalStateException</ExpectedException>");
}
// Assert different action is invalid
try {
getCache().getLogger()
.info("<ExpectedException action=add>" + "IllegalStateException</ExpectedException>");
assertTrue(!firstEvictionAttributes.getAction().isOverflowToDisk());
assertTrue(firstEvictionAttributes.getAlgorithm().isLRUMemory());
final EvictionAttributes badEa =
EvictionAttributes.createLRUMemoryAttributes(firstEvictionAttributes.getMaximum(),
firstEvictionAttributes.getObjectSizer(), EvictionAction.OVERFLOW_TO_DISK);
assertTrue(!badEa.equals(firstEvictionAttributes));
factory.setEvictionAttributes(badEa);
createRootRegion(name, factory.create());
fail("Test to validate the Eviction Attribute : HeapLRU Interval");
} catch (final IllegalStateException expected) {
assertTrue(expected.getMessage().contains(
PartitionRegionConfigValidator.EVICTION_ATTRIBUTES_ARE_INCOMPATIBLE_MESSAGE));
} finally {
getCache().getLogger().info(
"<ExpectedException action=remove>" + "IllegalStateException</ExpectedException>");
}
// Assert a smaller eviction maximum than the global is not valid (bug 40419)
{
assertTrue(firstEvictionAttributes.getAlgorithm().isLRUMemory());
final EvictionAttributes okEa =
EvictionAttributes.createLRUMemoryAttributes(firstEvictionAttributes.getMaximum() - 1,
firstEvictionAttributes.getObjectSizer(), firstEvictionAttributes.getAction());
if (!isAccessor) {
assertTrue(okEa.getMaximum() < pra.getLocalMaxMemory());
}
assertTrue(!okEa.equals(firstEvictionAttributes));
factory.setEvictionAttributes(okEa);
final RegionAttributes attrs = factory.create();
final Region pr = createRootRegion(name, attrs);
assertNotNull(pr);
assertNotSame(okEa, pr.getAttributes().getEvictionAttributes());
assertEquals(firstEvictionAttributes.getMaximum(),
pr.getAttributes().getEvictionAttributes().getMaximum());
pr.localDestroyRegion();
}
// Assert that a larger eviction maximum than the global is not
// valid (bug 40419)
{
assertTrue(firstEvictionAttributes.getAlgorithm().isLRUMemory());
final EvictionAttributes okEa =
EvictionAttributes.createLRUMemoryAttributes(firstEvictionAttributes.getMaximum() + 1,
firstEvictionAttributes.getObjectSizer(), firstEvictionAttributes.getAction());
assertTrue(!okEa.equals(firstEvictionAttributes));
if (!isAccessor) {
assertEquals(okEa.getMaximum(), pra.getLocalMaxMemory() + 1);
}
factory.setEvictionAttributes(okEa);
final RegionAttributes attrs = factory.create();
final Region pr = createRootRegion(name, attrs);
assertNotNull(pr);
assertNotSame(okEa, pr.getAttributes().getEvictionAttributes());
assertEquals(firstEvictionAttributes.getMaximum(),
pr.getAttributes().getEvictionAttributes().getMaximum());
pr.localDestroyRegion();
}
// Assert that an eviction maximum larger than the
// localMaxMemroy is allowed
// and that the local eviction maximum is re-set to the
// localMaxMemory value
{
// lower the localMaxMemory
pra = createPartitionAttributes(firstEvictionAttributes.getMaximum() - 1);
factory.setPartitionAttributes(pra);
if (!isAccessor) {
assertTrue(firstEvictionAttributes.getMaximum() > pra.getLocalMaxMemory());
}
factory.setEvictionAttributes(firstEvictionAttributes);
final RegionAttributes attrs = factory.create();
final Region pr = createRootRegion(name, attrs);
assertNotNull(pr);
if (!isAccessor) {
assertEquals(pr.getAttributes().getPartitionAttributes().getLocalMaxMemory(),
pr.getAttributes().getEvictionAttributes().getMaximum());
}
pr.localDestroyRegion();
}
// Assert exact same attributes is valid
{
factory.setEvictionAttributes(firstEvictionAttributes);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
assertNotSame(firstEvictionAttributes, pr.getAttributes().getEvictionAttributes());
assertEquals(pr.getAttributes().getPartitionAttributes().getLocalMaxMemory(),
pr.getAttributes().getEvictionAttributes().getMaximum());
pr.localDestroyRegion();
}
}
}
testDatastore.invoke(new PRLRUMemoryRunnable(false));
// testAccessor.invoke(new PRLRUMemoryRunnable(true));
}
@Test
public void testEvictionValidationForLRUEntry_AccessorFirst() {
final Host host = Host.getHost(0);
final VM firstAccessor = host.getVM(0);
final VM testAccessor = host.getVM(1);
final VM testDatastore = host.getVM(2);
final VM firstDatastore = host.getVM(3);
final String uniqName = getUniqueName();
final int redundantCopies = 1;
final int maxEntries = 226;
final String name = uniqName + "-PR";
final EvictionAttributes firstEvictionAttrs =
EvictionAttributes.createLRUEntryAttributes(maxEntries, EvictionAction.LOCAL_DESTROY);
final EvictionAttributes secondEvictionAttrs =
EvictionAttributes.createLRUEntryAttributes(maxEntries, EvictionAction.OVERFLOW_TO_DISK);
final SerializableRunnable createFirstAccessor =
new CacheSerializableRunnable("Create an accessor without eviction attributes") {
@Override
public void run2() {
final PartitionAttributes pra = new PartitionAttributesFactory()
.setRedundantCopies(redundantCopies).setLocalMaxMemory(0).create();
AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(pra);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
final SerializableRunnable createFirstDataStore =
new CacheSerializableRunnable("Create a data store with eviction attributes") {
@Override
public void run2() {
final PartitionAttributes pra = new PartitionAttributesFactory()
.setRedundantCopies(redundantCopies).setLocalMaxMemory(0).create();
AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(pra);
factory.setEvictionAttributes(firstEvictionAttrs);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
final SerializableRunnable createSecondAccessor =
new CacheSerializableRunnable("Create an accessor with incorrect eviction attributes") {
@Override
public void run2() {
final PartitionAttributes pra = new PartitionAttributesFactory()
.setRedundantCopies(redundantCopies).setLocalMaxMemory(0).create();
AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(pra);
factory.setEvictionAttributes(secondEvictionAttrs);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
final SerializableRunnable createSecondDataStore =
new CacheSerializableRunnable("Create a data store with eviction attributes") {
@Override
public void run2() {
final PartitionAttributes pra = new PartitionAttributesFactory()
.setRedundantCopies(redundantCopies).setLocalMaxMemory(0).create();
AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(pra);
factory.setEvictionAttributes(firstEvictionAttrs);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
firstAccessor.invoke(createFirstAccessor);
firstDatastore.invoke(createFirstDataStore);
testAccessor.invoke(createSecondAccessor);
testDatastore.invoke(createSecondDataStore);
}
@Test
public void testEvictionValidationForLRUEntry_DatastoreFirst() {
final Host host = Host.getHost(0);
final VM firstAccessor = host.getVM(0);
final VM testAccessor = host.getVM(1);
final VM testDatastore = host.getVM(2);
final VM firstDatastore = host.getVM(3);
final String uniqName = getUniqueName();
final int redundantCopies = 1;
final int maxEntries = 226;
final String name = uniqName + "-PR";
final EvictionAttributes firstEvictionAttrs =
EvictionAttributes.createLRUEntryAttributes(maxEntries, EvictionAction.LOCAL_DESTROY);
final EvictionAttributes secondEvictionAttrs =
EvictionAttributes.createLRUEntryAttributes(maxEntries, EvictionAction.OVERFLOW_TO_DISK);
final SerializableRunnable createFirstAccessor =
new CacheSerializableRunnable("Create an accessor without eviction attributes") {
@Override
public void run2() {
final PartitionAttributes pra = new PartitionAttributesFactory()
.setRedundantCopies(redundantCopies).setLocalMaxMemory(0).create();
AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(pra);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
final SerializableRunnable createFirstDataStore =
new CacheSerializableRunnable("Create a data store with eviction attributes") {
@Override
public void run2() {
final PartitionAttributes pra = new PartitionAttributesFactory()
.setRedundantCopies(redundantCopies).setLocalMaxMemory(0).create();
AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(pra);
factory.setEvictionAttributes(firstEvictionAttrs);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
final SerializableRunnable createSecondAccessor =
new CacheSerializableRunnable("Create an accessor with incorrect eviction attributes") {
@Override
public void run2() {
final PartitionAttributes pra = new PartitionAttributesFactory()
.setRedundantCopies(redundantCopies).setLocalMaxMemory(0).create();
AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(pra);
factory.setEvictionAttributes(secondEvictionAttrs);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
final SerializableRunnable createSecondDataStore =
new CacheSerializableRunnable("Create a data store with eviction attributes") {
@Override
public void run2() {
final PartitionAttributes pra = new PartitionAttributesFactory()
.setRedundantCopies(redundantCopies).setLocalMaxMemory(0).create();
AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(pra);
factory.setEvictionAttributes(firstEvictionAttrs);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
firstDatastore.invoke(createFirstDataStore);
firstAccessor.invoke(createFirstAccessor);
testDatastore.invoke(createSecondDataStore);
testAccessor.invoke(createSecondAccessor);
}
@Test
public void testEvictionValidationForLRUEntry_TwoAccessors() {
final Host host = Host.getHost(0);
final VM firstAccessor = host.getVM(0);
final VM testAccessor = host.getVM(1);
final VM testDatastore = host.getVM(2);
final VM firstDatastore = host.getVM(3);
final String uniqName = getUniqueName();
final int redundantCopies = 1;
final int maxEntries = 226;
final String name = uniqName + "-PR";
final EvictionAttributes firstEvictionAttrs =
EvictionAttributes.createLRUEntryAttributes(maxEntries, EvictionAction.LOCAL_DESTROY);
final SerializableRunnable createFirstAccessor =
new CacheSerializableRunnable("Create an accessor without eviction attributes") {
@Override
public void run2() {
final PartitionAttributes pra = new PartitionAttributesFactory()
.setRedundantCopies(redundantCopies).setLocalMaxMemory(0).create();
AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(pra);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
final SerializableRunnable createFirstDataStore =
new CacheSerializableRunnable("Create a data store with eviction attributes") {
@Override
public void run2() {
final PartitionAttributes pra = new PartitionAttributesFactory()
.setRedundantCopies(redundantCopies).setLocalMaxMemory(0).create();
AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(pra);
factory.setEvictionAttributes(firstEvictionAttrs);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
final SerializableRunnable createSecondAccessor =
new CacheSerializableRunnable("Create an accessor with correct eviction attributes") {
@Override
public void run2() {
final PartitionAttributes pra = new PartitionAttributesFactory()
.setRedundantCopies(redundantCopies).setLocalMaxMemory(0).create();
AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(pra);
factory.setEvictionAttributes(firstEvictionAttrs);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
final SerializableRunnable createSecondDataStore =
new CacheSerializableRunnable("Create a data store with eviction attributes") {
@Override
public void run2() {
final PartitionAttributes pra = new PartitionAttributesFactory()
.setRedundantCopies(redundantCopies).setLocalMaxMemory(0).create();
AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(pra);
factory.setEvictionAttributes(firstEvictionAttrs);
final Region pr = createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
firstAccessor.invoke(createFirstAccessor);
testAccessor.invoke(createSecondAccessor);
firstDatastore.invoke(createFirstDataStore);
testDatastore.invoke(createSecondDataStore);
}
/**
* Test that gets do not need to acquire a lock on the region entry when LRU is enabled. This is
* bug 42265
*/
@Test
public void testEntryLRUDeadlock() {
final Host host = Host.getHost(0);
final VM vm0 = host.getVM(0);
final VM vm1 = host.getVM(1);
final String uniqName = getUniqueName();
final int redundantCopies = 0;
final int maxBuckets = 8;
final int maxEntries = 16;
final String name = uniqName + "-PR";
final int extraEntries = 4;
// final int heapPercentage = 66;
// final int evictorInterval = 100;
final SerializableRunnable create = new CacheSerializableRunnable(
"Create Entry LRU with local destroy on a partitioned Region") {
@Override
public void run2() {
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(new PartitionAttributesFactory()
.setRedundantCopies(redundantCopies).setTotalNumBuckets(maxBuckets).create());
factory.setEvictionAttributes(
EvictionAttributes.createLRUEntryAttributes(maxEntries, EvictionAction.LOCAL_DESTROY));
final PartitionedRegion pr = (PartitionedRegion) createRootRegion(name, factory.create());
assertNotNull(pr);
}
};
vm0.invoke(create);
final SerializableRunnable create2 =
new SerializableRunnable("Create Entry LRU with local destroy on a partitioned Region") {
@Override
public void run() {
try {
final AttributesFactory factory = new AttributesFactory();
factory.setOffHeap(isOffHeap());
factory.setPartitionAttributes(
new PartitionAttributesFactory().setRedundantCopies(redundantCopies)
.setLocalMaxMemory(0).setTotalNumBuckets(maxBuckets).create());
factory
.setEvictionAttributes(EvictionAttributes.createLRUEntryAttributes(maxEntries));
factory.setSubscriptionAttributes(new SubscriptionAttributes(InterestPolicy.ALL));
// this listener will cause a deadlock if the get ends up
// locking the entry.
factory.addCacheListener(new CacheListenerAdapter() {
@Override
public void afterCreate(EntryEvent event) {
Region region = event.getRegion();
Object key = event.getKey();
region.get(key);
}
});
final PartitionedRegion pr =
(PartitionedRegion) createRootRegion(name, factory.create());
assertNotNull(pr);
} catch (final CacheException ex) {
Assert.fail("While creating Partitioned region", ex);
}
}
};
vm1.invoke(create2);
final SerializableRunnable doPuts = new SerializableRunnable("Do Puts") {
@Override
public void run() {
final PartitionedRegion pr = (PartitionedRegion) getRootRegion(name);
assertNotNull(pr);
for (int counter = 0; counter <= maxEntries + extraEntries; counter++) {
pr.put(counter, "value");
}
}
};
vm0.invoke(doPuts);
}
protected void setEvictionPercentage(float percentage) {
getCache().getResourceManager().setEvictionHeapPercentage(percentage);
}
protected boolean isOffHeap() {
return false;
}
protected ResourceType getMemoryType() {
return ResourceType.HEAP_MEMORY;
}
protected HeapEvictor getEvictor(Region region) {
return ((GemFireCacheImpl) region.getRegionService()).getHeapEvictor();
}
}