blob: a813a4b5c6617ea8b523741e808accea2f68d554 [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.control;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.util.Properties;
import java.util.Set;
import javax.management.ListenerNotFoundException;
import javax.management.NotificationEmitter;
import org.apache.logging.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.apache.geode.cache.AttributesFactory;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.LowMemoryException;
import org.apache.geode.cache.PartitionAttributes;
import org.apache.geode.cache.PartitionAttributesFactory;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionFactory;
import org.apache.geode.cache.Scope;
import org.apache.geode.cache.control.ResourceManager;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.internal.cache.control.InternalResourceManager.ResourceType;
import org.apache.geode.logging.internal.log4j.api.LogService;
public class MemoryMonitorJUnitTest {
private static Logger logger = LogService.getLogger();
public static final int SYSTEM_LISTENERS = 1;
DistributedSystem ds;
GemFireCacheImpl cache;
@Before
public void setUp() throws Exception {
Properties p = new Properties();
p.setProperty(MCAST_PORT, "0");
this.ds = DistributedSystem.connect(p);
this.cache = (GemFireCacheImpl) CacheFactory.create(this.ds);
HeapMemoryMonitor.setTestDisableMemoryUpdates(true);
logger.info(addExpectedAbove);
logger.info(addExpectedBelow);
}
@After
public void tearDown() throws Exception {
try {
HeapMemoryMonitor.setTestDisableMemoryUpdates(false);
this.cache.close();
this.ds.disconnect();
} finally {
logger.info(removeExpectedAbove);
logger.info(removeExpectedBelow);
}
}
static final String expectedEx = "Member: .*? above .*? critical threshold";
public static final String addExpectedAbove =
"<ExpectedException action=add>" + expectedEx + "</ExpectedException>";
public static final String removeExpectedAbove =
"<ExpectedException action=remove>" + expectedEx + "</ExpectedException>";
static final String expectedBelow = "Member: .*? below .*? critical threshold";
public static final String addExpectedBelow =
"<ExpectedException action=add>" + expectedBelow + "</ExpectedException>";
public static final String removeExpectedBelow =
"<ExpectedException action=remove>" + expectedBelow + "</ExpectedException>";
/**
* Test: 1. safe events are not delivered before critical 2. listeners are invoked 3. duplicate
* safe and critical events are not delivered 4. stats are updated
*/
@Test
public void testInvokeListeners() throws Exception {
InternalResourceManager internalManager = this.cache.getInternalResourceManager();
HeapMemoryMonitor heapMonitor = internalManager.getHeapMonitor();
heapMonitor.setTestMaxMemoryBytes(1000);
HeapMemoryMonitor.setTestBytesUsedForThresholdSet(50);
internalManager.setCriticalHeapPercentage(90.0f);
internalManager.setEvictionHeapPercentage(80.0f);
// test stats
assertEquals(900, internalManager.getStats().getCriticalThreshold());
assertEquals(800, internalManager.getStats().getEvictionThreshold());
// register a bunch of listeners
for (int i = 0; i < 10; i++) {
ResourceListener listener = new TestMemoryThresholdListener();
internalManager.addResourceListener(ResourceType.HEAP_MEMORY, listener);
}
Set<ResourceListener> heapListeners =
internalManager.getResourceListeners(ResourceType.HEAP_MEMORY);
assertEquals(10 + SYSTEM_LISTENERS, heapListeners.size());
heapMonitor.updateStateAndSendEvent(700, "test");
assertEquals(0, internalManager.getStats().getEvictionStartEvents());
for (ResourceListener listener : heapListeners) {
if (listener instanceof TestMemoryThresholdListener) {
assertEquals(0, ((TestMemoryThresholdListener) listener).getEvictionThresholdCalls());
}
}
// make sure listeners are invoked
heapMonitor.updateStateAndSendEvent(870, "test");
assertEquals(0, internalManager.getStats().getEvictionStopEvents());
assertEquals(1, internalManager.getStats().getEvictionStartEvents());
assertEquals(0, internalManager.getStats().getHeapCriticalEvents());
for (ResourceListener listener : heapListeners) {
if (listener instanceof TestMemoryThresholdListener) {
assertEquals(0, ((TestMemoryThresholdListener) listener).getCriticalThresholdCalls());
assertEquals(1, ((TestMemoryThresholdListener) listener).getEvictionThresholdCalls());
}
}
// make sure same event is not triggered twice
heapMonitor.updateStateAndSendEvent(880, "test");
assertEquals(0, internalManager.getStats().getEvictionStopEvents());
assertEquals(1, internalManager.getStats().getEvictionStartEvents());
assertEquals(0, internalManager.getStats().getHeapCriticalEvents());
for (ResourceListener listener : heapListeners) {
if (listener instanceof TestMemoryThresholdListener) {
assertEquals(0, ((TestMemoryThresholdListener) listener).getCriticalThresholdCalls());
assertEquals(1, ((TestMemoryThresholdListener) listener).getEvictionThresholdCalls());
}
}
}
/**
* By default both thresholds are disabled. make sure no event goes through. Enable thresholds and
* verify that events are delivered
*/
// TODO: write a converse of this test when default values are enabled
@Test
public void testDefaultThresholds() throws Exception {
final InternalResourceManager irm = this.cache.getInternalResourceManager();
final HeapMemoryMonitor hmm = irm.getHeapMonitor();
TestMemoryThresholdListener listener = new TestMemoryThresholdListener();
irm.addResourceListener(ResourceType.HEAP_MEMORY, listener);
hmm.setTestMaxMemoryBytes(1000);
hmm.updateStateAndSendEvent(870, "test");
assertEquals(0, irm.getStats().getHeapCriticalEvents());
hmm.updateStateAndSendEvent(950, "test");
hmm.updateStateAndSendEvent(770, "test");
assertEquals(0, irm.getStats().getHeapCriticalEvents());
assertEquals(0, irm.getStats().getEvictionStartEvents());
// enable thresholds and make sure events go through
HeapMemoryMonitor.setTestBytesUsedForThresholdSet(770);
irm.setEvictionHeapPercentage(80f);
assertEquals(0, irm.getStats().getEvictionStartEvents());
assertEquals(0, irm.getStats().getHeapCriticalEvents());
hmm.updateStateAndSendEvent(870, "test");
assertEquals(1, listener.getEvictionThresholdCalls());
assertEquals(1, irm.getStats().getEvictionStartEvents());
assertEquals(0, irm.getStats().getHeapCriticalEvents());
listener.resetThresholdCalls();
HeapMemoryMonitor.setTestBytesUsedForThresholdSet(870);
irm.setEvictionHeapPercentage(0.0f); // resets the old state
assertEquals(1, irm.getStats().getEvictionStartEvents());
assertEquals(0, irm.getStats().getHeapCriticalEvents());
hmm.updateStateAndSendEvent(870, "test");
assertEquals(1, irm.getStats().getEvictionStartEvents());
assertEquals(0, irm.getStats().getHeapCriticalEvents());
HeapMemoryMonitor.setTestBytesUsedForThresholdSet(870);
irm.setCriticalHeapPercentage(90f);
assertEquals(1, irm.getStats().getEvictionStartEvents());
assertEquals(0, irm.getStats().getHeapCriticalEvents());
hmm.updateStateAndSendEvent(970, "test");
assertEquals(1, irm.getStats().getHeapCriticalEvents());
assertEquals(0, listener.getEvictionThresholdCalls());
assertEquals(1, irm.getStats().getEvictionStartEvents());
}
@Test
public void testSubRegionCloseRemovesListener() {
// test local sub region
AttributesFactory factory = new AttributesFactory();
factory.setScope(Scope.LOCAL);
Region parent = cache.createRegion("parent", factory.create());
parent.createSubregion("sub", factory.create());
parent.close();
assertEquals(0 + SYSTEM_LISTENERS, cache.getInternalResourceManager(false)
.getResourceListeners(ResourceType.HEAP_MEMORY).size());
// test nested local region
parent = cache.createRegion("parent2", factory.create());
parent.createSubregion("sub", factory.create()).createSubregion("subsub", factory.create());
parent.close();
assertEquals(0 + SYSTEM_LISTENERS, cache.getInternalResourceManager(false)
.getResourceListeners(ResourceType.HEAP_MEMORY).size());
// test distributed sub region
factory.setScope(Scope.DISTRIBUTED_ACK);
parent = cache.createRegion("parent3", factory.create());
parent.createSubregion("sub", factory.create());
parent.close();
assertEquals(0 + SYSTEM_LISTENERS, cache.getInternalResourceManager(false)
.getResourceListeners(ResourceType.HEAP_MEMORY).size());
// test nested distributed region
parent = cache.createRegion("parent4", factory.create());
parent.createSubregion("sub", factory.create()).createSubregion("subsub", factory.create());
parent.close();
assertEquals(0 + SYSTEM_LISTENERS, cache.getInternalResourceManager(false)
.getResourceListeners(ResourceType.HEAP_MEMORY).size());
}
/**
* creates a distributed region and invokes criticalThresholdReached then does a put to verify
* that the put is rejected
*/
@Test
public void testPutsRejectionDistributedRegion() throws Exception {
AttributesFactory attr = new AttributesFactory();
attr.setScope(Scope.DISTRIBUTED_ACK);
Region region = cache.createRegion("DistributedRegion", attr.create());
checkOpRejection(region, false, true);
region.close();
assertEquals(0 + SYSTEM_LISTENERS, cache.getInternalResourceManager(false)
.getResourceListeners(ResourceType.HEAP_MEMORY).size());
}
@Test
public void testTxDistributedRegion() throws Exception {
AttributesFactory attr = new AttributesFactory();
attr.setScope(Scope.DISTRIBUTED_ACK);
Region region = cache.createRegion("DistributedRegion", attr.create());
checkOpRejection(region, true, true);
region.close();
assertEquals(0 + SYSTEM_LISTENERS, cache.getInternalResourceManager(false)
.getResourceListeners(ResourceType.HEAP_MEMORY).size());
}
@Test
public void testPutsLocalRegion() throws Exception {
AttributesFactory attr = new AttributesFactory();
attr.setScope(Scope.LOCAL);
Region region = cache.createRegion("localRegion", attr.create());
checkOpRejection(region, false, true);
region.close();
assertEquals(0 + SYSTEM_LISTENERS, cache.getInternalResourceManager(false)
.getResourceListeners(ResourceType.HEAP_MEMORY).size());
}
@Test
public void testTxLocalRegion() throws Exception {
AttributesFactory attr = new AttributesFactory();
attr.setScope(Scope.LOCAL);
Region region = cache.createRegion("localRegion", attr.create());
checkOpRejection(region, true, true);
region.close();
assertEquals(0 + SYSTEM_LISTENERS, cache.getInternalResourceManager(false)
.getResourceListeners(ResourceType.HEAP_MEMORY).size());
}
@Test
public void testPutsRejectedSubRegion() throws Exception {
AttributesFactory factory = new AttributesFactory();
factory.setScope(Scope.LOCAL);
Region subRegion =
cache.createRegion("local1", factory.create()).createSubregion("sub1", factory.create());
checkOpRejection(subRegion, false, true);
subRegion.close();
// root region is still present
assertEquals(1 + SYSTEM_LISTENERS, cache.getInternalResourceManager(false)
.getResourceListeners(ResourceType.HEAP_MEMORY).size());
}
@Test
public void testTxSubRegion() throws Exception {
AttributesFactory factory = new AttributesFactory();
factory.setScope(Scope.LOCAL);
Region subRegion =
cache.createRegion("local1", factory.create()).createSubregion("sub1", factory.create());
checkOpRejection(subRegion, true, true);
subRegion.close();
// root region is still present
assertEquals(1 + SYSTEM_LISTENERS, cache.getInternalResourceManager(false)
.getResourceListeners(ResourceType.HEAP_MEMORY).size());
}
@Test
public void testPutsPartitionedRegion() throws Exception {
PartitionAttributes pa =
new PartitionAttributesFactory().setRedundantCopies(0).setTotalNumBuckets(3).create();
Region region = new RegionFactory().setPartitionAttributes(pa).create("parReg");
checkOpRejection(region, false, true);
region.close();
assertEquals(0 + SYSTEM_LISTENERS, cache.getInternalResourceManager(false)
.getResourceListeners(ResourceType.HEAP_MEMORY).size());
}
private void checkOpRejection(Region region, boolean useTransaction, boolean expectLowMemEx)
throws Exception {
if (useTransaction) {
cache.getCacheTransactionManager().begin();
}
region.put("key-1", "value-1");
int addSubregion = 0;
if (region.getName().equals("sub1")) {
addSubregion++;
}
InternalResourceManager internalManager = cache.getInternalResourceManager();
HeapMemoryMonitor heapMonitor = internalManager.getHeapMonitor();
TestMemoryThresholdListener listener = new TestMemoryThresholdListener();
internalManager.addResourceListener(ResourceType.HEAP_MEMORY, listener);
heapMonitor.setTestMaxMemoryBytes(100);
HeapMemoryMonitor.setTestBytesUsedForThresholdSet(50);
internalManager.setCriticalHeapPercentage(95.0f);
// make sure that the region is added as a memory event listener
assertEquals(2 + addSubregion + SYSTEM_LISTENERS,
internalManager.getResourceListeners(ResourceType.HEAP_MEMORY).size());
assertEquals(2 + addSubregion + SYSTEM_LISTENERS,
internalManager.getResourceListeners(ResourceType.HEAP_MEMORY).size());
heapMonitor.updateStateAndSendEvent(97, "test");
assertEquals(1, listener.getCriticalThresholdCalls());
boolean caughtException = false;
try {
region.put("key-1", "value-2");
} catch (LowMemoryException low) {
cache.getLogger().info("caught expected exception", low);
caughtException = true;
}
if (expectLowMemEx && !caughtException) {
throw new AssertionError("An expected exception was not thrown");
}
// make region healthy
heapMonitor.updateStateAndSendEvent(91, "test");
// try the puts again
try {
region.put("key-1", "value-2");
} catch (LowMemoryException low) {
throw new AssertionError("Unexpected exception:", low);
}
if (useTransaction) {
cache.getCacheTransactionManager().commit();
}
internalManager.removeResourceListener(listener);
}
@Test
public void testCriticalHeapThreshold() throws Exception {
final int toohigh = 101;
final int toolow = -1;
final float disabled = 0.0f;
final float justright = 92.5f;
final ResourceManager rm = this.cache.getResourceManager();
long usageThreshold = -1;
int once = 0;
for (MemoryPoolMXBean p : ManagementFactory.getMemoryPoolMXBeans()) {
if (p.isUsageThresholdSupported() && HeapMemoryMonitor.isTenured(p)) {
usageThreshold = p.getUsageThreshold();
once++;
}
}
assertEquals("Expected only one pool to be assigned", 1, once);
// Default test, current default is disabled
assertEquals(rm.getCriticalHeapPercentage(), MemoryThresholds.DEFAULT_CRITICAL_PERCENTAGE,
0.01);
NotificationEmitter emitter = (NotificationEmitter) ManagementFactory.getMemoryMXBean();
try {
emitter.removeNotificationListener(
InternalResourceManager.getInternalResourceManager(cache).getHeapMonitor());
assertTrue("Expected that the resource manager was not registered", false);
} catch (ListenerNotFoundException expected) {
}
try {
rm.setCriticalHeapPercentage(toohigh);
assertTrue("Expected illegal argument exception for value " + toohigh, false);
} catch (IllegalArgumentException toohi) {
}
try {
rm.setCriticalHeapPercentage(toolow);
assertTrue("Expected illegal argument exception for value " + toolow, false);
} catch (IllegalArgumentException toohi) {
}
rm.setCriticalHeapPercentage(justright);
emitter = (NotificationEmitter) ManagementFactory.getMemoryMXBean();
{
InternalResourceManager irm = InternalResourceManager.getInternalResourceManager(cache);
HeapMemoryMonitor hmm = irm.getHeapMonitor();
// Expect no exception for removal (it was installed during set)
hmm.stopMonitoring();
}
assertEquals(rm.getCriticalHeapPercentage(), justright, 0.01);
rm.setCriticalHeapPercentage(disabled);
assertEquals(rm.getCriticalHeapPercentage(), disabled, 0.01);
emitter = (NotificationEmitter) ManagementFactory.getMemoryMXBean();
try {
emitter.removeNotificationListener(
InternalResourceManager.getInternalResourceManager(cache).getHeapMonitor());
assertTrue("Expected that the resource manager was not registered", false);
} catch (ListenerNotFoundException expected) {
}
// Assert the threshold was reset
for (MemoryPoolMXBean p : ManagementFactory.getMemoryPoolMXBeans()) {
if (HeapMemoryMonitor.isTenured(p)) {
assertEquals(usageThreshold, p.getUsageThreshold());
}
}
}
@Test
public void testHandleNotification() throws Exception {
final InternalResourceManager irm = this.cache.getInternalResourceManager();
final HeapMemoryMonitor hmm = irm.getHeapMonitor();
hmm.setTestMaxMemoryBytes(100);
HeapMemoryMonitor.setTestBytesUsedForThresholdSet(50);
irm.setEvictionHeapPercentage(80);
irm.setCriticalHeapPercentage(90);
TestMemoryThresholdListener listener = new TestMemoryThresholdListener();
listener.resetThresholdCalls();
irm.addResourceListener(ResourceType.HEAP_MEMORY, listener);
assertEquals(0, listener.getAllCalls());
// test EVICTION, CRITICAL, EVICTION, NORMAL cycle
for (int i = 0; i < 3; i++) {
hmm.updateStateAndSendEvent(82, "test"); // EVICTION
assertEquals(i * 4 + 1, listener.getAllCalls());
assertEquals((i * 3) + 1, listener.getEvictionThresholdCalls());
assertEquals(i + 1, irm.getStats().getEvictionStartEvents());
assertEquals(82, listener.getCurrentHeapPercentage());
assertEquals(2, listener.getBytesFromThreshold());
hmm.updateStateAndSendEvent(92, "test"); // CRITICAL
assertEquals(i * 4 + 2, listener.getAllCalls());
assertEquals(i + 1, listener.getCriticalThresholdCalls());
assertEquals(i + 1, irm.getStats().getHeapCriticalEvents());
assertEquals(92, listener.getCurrentHeapPercentage());
assertEquals(2, listener.getBytesFromThreshold());
hmm.updateStateAndSendEvent(85, "test"); // EVICTION
assertEquals(i * 4 + 3, listener.getAllCalls());
assertEquals((i * 3) + 3, listener.getEvictionThresholdCalls());
assertEquals(i + 1, irm.getStats().getHeapSafeEvents());
assertEquals(85, listener.getCurrentHeapPercentage());
assertEquals(5, listener.getBytesFromThreshold());
hmm.updateStateAndSendEvent(76, "test"); // NORMAL
assertEquals(i * 4 + 4, listener.getAllCalls());
assertEquals(i + 1, listener.getNormalCalls());
assertEquals(i + 1, irm.getStats().getEvictionStopEvents());
assertEquals(76, listener.getCurrentHeapPercentage());
assertEquals(4, listener.getBytesFromThreshold());
}
listener.resetThresholdCalls();
// test CRITICAL back to NORMAL
hmm.updateStateAndSendEvent(95, "test"); // CRITICAL
assertEquals(1, listener.getEvictionThresholdCalls());
assertEquals(1, listener.getCriticalThresholdCalls());
assertEquals(4, irm.getStats().getHeapCriticalEvents());
assertEquals(4, irm.getStats().getEvictionStartEvents());
assertEquals(1, listener.getAllCalls());
assertEquals(95, listener.getCurrentHeapPercentage());
assertEquals(5, listener.getBytesFromThreshold());
hmm.updateStateAndSendEvent(75, "test"); // NORMAL
assertEquals(1, listener.getNormalCalls());
assertEquals(1, listener.getEvictionThresholdCalls());
assertEquals(1, listener.getCriticalThresholdCalls());
assertEquals(75, listener.getCurrentHeapPercentage());
assertEquals(5, listener.getBytesFromThreshold());
assertEquals(2, listener.getAllCalls());
listener.resetThresholdCalls();
// generate many events in threshold thickness for eviction threshold
for (int i = 0; i < 5; i++) {
hmm.updateStateAndSendEvent(82, "test"); // EVICTION
assertEquals(1, listener.getEvictionThresholdCalls());
assertEquals((i * 2) + 1, listener.getAllCalls());
assertEquals(82, listener.getCurrentHeapPercentage());
assertEquals(2, listener.getBytesFromThreshold());
hmm.updateStateAndSendEvent(79, "test"); // EVICTION THICKNESS
}
listener.resetThresholdCalls();
// generate many events in threshold thickness for critical threshold
for (int i = 0; i < 5; i++) {
hmm.updateStateAndSendEvent(92, "test"); // CRITICAL
assertEquals(1, listener.getCriticalThresholdCalls());
assertEquals((i * 2) + 1, listener.getAllCalls());
assertEquals(92, listener.getCurrentHeapPercentage());
assertEquals(2, listener.getBytesFromThreshold());
hmm.updateStateAndSendEvent(89, "test"); // CRITICAL THICKNESS
}
hmm.updateStateAndSendEvent(75, "test");
listener.resetThresholdCalls();
// generate many events around threshold thickness for eviction threshold
for (int i = 1; i < 6; i++) {
hmm.updateStateAndSendEvent(82, "test"); // EVICTION
assertEquals(i, listener.getEvictionThresholdCalls());
assertEquals(82, listener.getCurrentHeapPercentage());
assertEquals(2, listener.getBytesFromThreshold());
hmm.updateStateAndSendEvent(77, "test"); // NORMAL
assertEquals(i, listener.getNormalCalls());
assertEquals(77, listener.getCurrentHeapPercentage());
assertEquals(3, listener.getBytesFromThreshold());
assertEquals(i * 2, listener.getAllCalls());
}
hmm.updateStateAndSendEvent(87, "test"); // EVICTION
listener.resetThresholdCalls();
// generate many events around threshold thickness for critical threshold
for (int i = 1; i < 6; i++) {
hmm.updateStateAndSendEvent(92, "test"); // CRITICAL
assertEquals(i, listener.getCriticalThresholdCalls());
assertEquals(92, listener.getCurrentHeapPercentage());
assertEquals(2, listener.getBytesFromThreshold());
hmm.updateStateAndSendEvent(87, "test"); // EVICTION
assertEquals(i * 2, listener.getEvictionThresholdCalls());
assertEquals(87, listener.getCurrentHeapPercentage());
assertEquals(3, listener.getBytesFromThreshold());
assertEquals(i * 2, listener.getAllCalls());
}
listener.resetThresholdCalls();
// from CRITICAL drop to EVICTION THICKNESS, and then to NORMAL
hmm.updateStateAndSendEvent(96, "test"); // CRITICAL
assertEquals(1, listener.getCriticalThresholdCalls());
assertEquals(1, listener.getAllCalls());
assertEquals(6, listener.getBytesFromThreshold());
assertEquals(96, listener.getCurrentHeapPercentage());
listener.resetThresholdCalls();
hmm.updateStateAndSendEvent(79, "test"); // EVICTION THICKNESS
assertEquals(1, listener.getEvictionThresholdCalls());
assertEquals(1, listener.getAllCalls());
assertEquals(11, listener.getBytesFromThreshold());
assertEquals(79, listener.getCurrentHeapPercentage());
listener.resetThresholdCalls();
hmm.updateStateAndSendEvent(77, "test"); // NORMAL
assertEquals(1, listener.getNormalCalls());
assertEquals(1, listener.getAllCalls());
assertEquals(3, listener.getBytesFromThreshold());
assertEquals(77, listener.getCurrentHeapPercentage());
listener.resetThresholdCalls();
}
@Test
public void testDisabledThresholds() {
final InternalResourceManager irm = this.cache.getInternalResourceManager();
final HeapMemoryMonitor hmm = irm.getHeapMonitor();
hmm.setTestMaxMemoryBytes(100);
HeapMemoryMonitor.setTestBytesUsedForThresholdSet(50);
irm.setEvictionHeapPercentage(80);
irm.setCriticalHeapPercentage(90);
TestMemoryThresholdListener listener = new TestMemoryThresholdListener();
irm.addResourceListener(ResourceType.HEAP_MEMORY, listener);
listener.resetThresholdCalls();
assertEquals(0, listener.getAllCalls());
// make sure that both thresholds are enabled, disable one threshold, make sure
// events for the other are delivered, enable the threshold
// eviction threshold
hmm.updateStateAndSendEvent(82, "test"); // EVICTION
assertEquals(1, listener.getEvictionThresholdCalls());
assertEquals(1, listener.getAllCalls());
assertEquals(1, irm.getStats().getEvictionStartEvents());
hmm.updateStateAndSendEvent(92, "test"); // CRITICAL
assertEquals(1, listener.getCriticalThresholdCalls());
assertEquals(2, listener.getAllCalls());
assertEquals(1, irm.getStats().getHeapCriticalEvents());
listener.resetThresholdCalls();
// disable threshold
HeapMemoryMonitor.setTestBytesUsedForThresholdSet(92);
irm.setEvictionHeapPercentage(0f);
assertEquals(1, listener.getEvictionDisabledCalls());
assertEquals(1, irm.getStats().getEvictionStopEvents());
irm.setEvictionHeapPercentage(0f);
assertEquals(1, listener.getEvictionDisabledCalls());
assertEquals(0, irm.getStats().getEvictionThreshold());
assertEquals(1, irm.getStats().getEvictionStopEvents());
hmm.updateStateAndSendEvent(75, "test"); // EVICTION_DISABLED
assertEquals(1, listener.getNormalCalls());
assertEquals(0, listener.getEvictionThresholdCalls());
assertEquals(1, irm.getStats().getEvictionStopEvents());
assertEquals(1, irm.getStats().getHeapSafeEvents());
hmm.updateStateAndSendEvent(85, "test"); // EVICTION_DISABLED
assertEquals(0, listener.getEvictionThresholdCalls());
assertEquals(1, irm.getStats().getEvictionStartEvents());
assertEquals(2, listener.getAllCalls());
hmm.updateStateAndSendEvent(92, "test"); // CRITICAL
assertEquals(3, listener.getAllCalls());
assertEquals(2, listener.getCriticalThresholdCalls());
listener.resetThresholdCalls();
// enable threshold again
HeapMemoryMonitor.setTestBytesUsedForThresholdSet(92);
irm.setEvictionHeapPercentage(80f);
assertEquals(1, listener.getEvictionThresholdCalls());
hmm.updateStateAndSendEvent(84, "test"); // EVICTION
assertEquals(2, listener.getAllCalls()); // EVICTION_CRITICAL+EVICTION
hmm.updateStateAndSendEvent(77, "test"); // NORMAL
assertEquals(1, listener.getNormalCalls());
assertEquals(3, listener.getAllCalls());
hmm.updateStateAndSendEvent(82, "test"); // EVICTION
assertEquals(3, listener.getEvictionThresholdCalls());
assertEquals(4, listener.getAllCalls());
hmm.updateStateAndSendEvent(91, "test"); // CRITICAL
assertEquals(2, listener.getCriticalThresholdCalls());
assertEquals(5, listener.getAllCalls());
hmm.updateStateAndSendEvent(87, "test"); // EVICTION
assertEquals(5, listener.getEvictionThresholdCalls());
assertEquals(3, irm.getStats().getHeapSafeEvents());
assertEquals(6, listener.getAllCalls());
listener.resetThresholdCalls();
// now disable critical
HeapMemoryMonitor.setTestBytesUsedForThresholdSet(87);
irm.setCriticalHeapPercentage(0f); // forced event
assertEquals(1, listener.getCriticalDisabledCalls());
irm.setCriticalHeapPercentage(0f);
assertEquals(1, listener.getCriticalDisabledCalls());
assertEquals(0, irm.getStats().getCriticalThreshold());
hmm.updateStateAndSendEvent(92, "test"); // NO EVENT
assertEquals(0, listener.getCriticalThresholdCalls());
assertEquals(3, irm.getStats().getHeapCriticalEvents());
assertEquals(2, listener.getAllCalls());
hmm.updateStateAndSendEvent(89, "test"); // NO EVENT
assertEquals(3, irm.getStats().getHeapSafeEvents());
assertEquals(3, listener.getAllCalls());
hmm.updateStateAndSendEvent(77, "test"); // NORMAL
assertEquals(1, listener.getNormalCalls());
assertEquals(4, listener.getAllCalls());
hmm.updateStateAndSendEvent(93, "test"); // EVICTION
assertEquals(2, listener.getEvictionThresholdCalls());
assertEquals(5, listener.getAllCalls());
listener.resetThresholdCalls();
// enable critical threshold again
HeapMemoryMonitor.setTestBytesUsedForThresholdSet(93);
irm.setCriticalHeapPercentage(90f); // forced event
assertEquals(1, listener.getAllCalls());
hmm.updateStateAndSendEvent(92, "test"); // NO EVENT
assertEquals(1, listener.getCriticalThresholdCalls());
assertEquals(2, listener.getAllCalls());
hmm.updateStateAndSendEvent(89, "test"); // CRITICAL THICKNESS
assertEquals(1, listener.getEvictionThresholdCalls());
hmm.updateStateAndSendEvent(87, "test"); // EVICTION
assertEquals(2, listener.getEvictionThresholdCalls());
assertEquals(4, listener.getAllCalls());
hmm.updateStateAndSendEvent(77, "test"); // NORMAL
assertEquals(1, listener.getNormalCalls());
assertEquals(5, listener.getAllCalls());
hmm.updateStateAndSendEvent(83, "test"); // EVICTION
assertEquals(3, listener.getEvictionThresholdCalls());
assertEquals(6, listener.getAllCalls());
listener.resetThresholdCalls();
// disable both thresholds (to make sure previous event is reset)
// enable one at a time, and confirm event delivery
HeapMemoryMonitor.setTestBytesUsedForThresholdSet(33);
irm.setCriticalHeapPercentage(0f);
assertEquals(1, listener.getCriticalDisabledCalls());
irm.setEvictionHeapPercentage(0f);
assertEquals(1, listener.getEvictionDisabledCalls());
hmm.updateStateAndSendEvent(95, "test"); // NO EVENT
hmm.updateStateAndSendEvent(87, "test"); // NO EVENT
hmm.updateStateAndSendEvent(77, "test"); // NO EVENT
assertEquals(5, listener.getAllCalls()); // the two DISABLE calls
listener.resetThresholdCalls();
// enable eviction, verify that forced event is not generated
HeapMemoryMonitor.setTestBytesUsedForThresholdSet(77);
irm.setEvictionHeapPercentage(80f);
assertEquals(0, listener.getEvictionThresholdCalls());
hmm.updateStateAndSendEvent(88, "test"); // EVICTION
assertEquals(1, listener.getEvictionThresholdCalls());
assertEquals(2, listener.getAllCalls());
hmm.updateStateAndSendEvent(92, "test"); // NO EVENT
assertEquals(3, listener.getAllCalls());
hmm.updateStateAndSendEvent(77, "test"); // NORMAL
assertEquals(2, listener.getNormalCalls());
hmm.updateStateAndSendEvent(98, "test"); // EVICTION
assertEquals(2, listener.getEvictionThresholdCalls());
assertEquals(5, listener.getAllCalls());
HeapMemoryMonitor.setTestBytesUsedForThresholdSet(98);
irm.setEvictionHeapPercentage(0f); // resets old state
listener.resetThresholdCalls();
hmm.updateStateAndSendEvent(87, "test"); // NO EVENT
hmm.updateStateAndSendEvent(77, "test"); // NO EVENT
hmm.updateStateAndSendEvent(85, "test"); // NO EVENT
assertEquals(3, listener.getAllCalls());
// enable critical, verify that forced event is not generated
HeapMemoryMonitor.setTestBytesUsedForThresholdSet(85);
irm.setCriticalHeapPercentage(90f);
assertEquals(0, listener.getCriticalThresholdCalls());
assertEquals(4, listener.getAllCalls());
hmm.updateStateAndSendEvent(94, "test"); // CRITICAL
assertEquals(5, listener.getAllCalls());
hmm.updateStateAndSendEvent(77, "test"); // NORMAL
assertEquals(2, listener.getNormalCalls());
assertEquals(6, listener.getAllCalls());
hmm.updateStateAndSendEvent(87, "test"); // NO EVENT
assertEquals(6, listener.getAllCalls());
assertEquals(1, listener.getCriticalThresholdCalls());
hmm.updateStateAndSendEvent(85, "test"); // NORMAL
assertEquals(2, listener.getNormalCalls());
}
@Test
public void testAddListeners() {
final InternalResourceManager internalManager = this.cache.getInternalResourceManager();
ResourceListener<MemoryEvent> memoryListener = new ResourceListener<MemoryEvent>() {
@Override
public void onEvent(MemoryEvent event) {
cache.getLogger().info("Received MemoryEvent");
}
};
internalManager.addResourceListener(ResourceType.HEAP_MEMORY, memoryListener);
assertEquals(1 + SYSTEM_LISTENERS,
internalManager.getResourceListeners(ResourceType.HEAP_MEMORY).size());
}
}