blob: 379fcaffd94f178686f92f8b257b5be4719c5edf [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.apache.geode.distributed.ConfigurationProperties.OFF_HEAP_MEMORY_SIZE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Properties;
import org.apache.logging.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.EvictionAlgorithm;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionFactory;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.internal.cache.EvictionAttributesImpl;
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 MemoryMonitorOffHeapJUnitTest {
private static final Logger logger = LogService.getLogger();
private 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");
p.setProperty(OFF_HEAP_MEMORY_SIZE, "1m");
this.ds = DistributedSystem.connect(p);
this.cache = (GemFireCacheImpl) CacheFactory.create(this.ds);
logger.info(addExpectedAbove);
logger.info(addExpectedBelow);
}
@After
public void tearDown() throws Exception {
try {
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
public void testGeneratingEvents() throws Exception {
InternalResourceManager internalManager = this.cache.getInternalResourceManager();
OffHeapMemoryMonitor monitor = internalManager.getOffHeapMonitor();
monitor.setEvictionThreshold(50.0f);
monitor.setCriticalThreshold(75.0f);
monitor.stopMonitoring(true);
assertEquals(524288, internalManager.getStats().getOffHeapEvictionThreshold());
assertEquals(786432, internalManager.getStats().getOffHeapCriticalThreshold());
// Register a bunch of listeners
for (int i = 0; i < 10; i++) {
ResourceListener listener = new TestMemoryThresholdListener();
internalManager.addResourceListener(ResourceType.OFFHEAP_MEMORY, listener);
}
assertEquals(10 + SYSTEM_LISTENERS,
internalManager.getResourceListeners(ResourceType.OFFHEAP_MEMORY).size());
// Start at normal
setThenTestListenersAndStats(400000, 0, 0, 0, 0, 0, 0, 0);
// Move to eviction
setThenTestListenersAndStats(550000, 0, 1, 0, 0, 1, 0, 0);
// Stay at eviction
setThenTestListenersAndStats(560000, 0, 1, 0, 0, 1, 0, 0);
// Move to critical
setThenTestListenersAndStats(850000, 0, 1, 0, 1, 2, 1, 0);
// Stay at critical (above critical clear margin)
setThenTestListenersAndStats(786431, 0, 1, 0, 1, 2, 1, 0);
setThenTestListenersAndStats(765465, 0, 1, 0, 1, 2, 1, 0);
// Move to eviction
setThenTestListenersAndStats(765454, 0, 1, 1, 1, 3, 1, 0);
// Stay at eviction (above eviction clear margin)
setThenTestListenersAndStats(524281, 0, 1, 1, 1, 3, 1, 0);
setThenTestListenersAndStats(503321, 0, 1, 1, 1, 3, 1, 0);
// Move to normal
setThenTestListenersAndStats(503310, 1, 1, 1, 1, 3, 1, 1);
// Disable eviction and verify normal event
monitor.setEvictionThreshold(0f);
setThenTestListenersAndStats(503315, 1, 1, 1, 1, 3, 1, 2);
// Enable eviction verify normal event
monitor.setEvictionThreshold(50f);
setThenTestListenersAndStats(503315, 1, 1, 1, 1, 3, 1, 3);
// Disable critical verify normal event
monitor.setCriticalThreshold(0f);
setThenTestListenersAndStats(503315, 1, 1, 1, 1, 3, 1, 4);
// Enable critical verify normal event
monitor.setCriticalThreshold(75f);
setThenTestListenersAndStats(503315, 1, 1, 1, 1, 3, 1, 5);
}
private void setThenTestListenersAndStats(final long memUsed, final int evictionStop,
final int evictionStart, final int safe, final int critical, final int evictionEvents,
final int criticalEvents, final int normalEvents) {
this.cache.getInternalResourceManager().getOffHeapMonitor().updateStateAndSendEvent(memUsed);
ResourceManagerStats stats = this.cache.getInternalResourceManager().getStats();
assertEquals(evictionStop, stats.getOffHeapEvictionStopEvents());
assertEquals(evictionStart, stats.getOffHeapEvictionStartEvents());
assertEquals(critical, stats.getOffHeapCriticalEvents());
assertEquals(safe, stats.getOffHeapSafeEvents());
for (ResourceListener listener : this.cache.getInternalResourceManager()
.getResourceListeners(ResourceType.OFFHEAP_MEMORY)) {
if (listener instanceof TestMemoryThresholdListener) {
assertEquals(evictionEvents,
((TestMemoryThresholdListener) listener).getEvictionThresholdCalls());
assertEquals(criticalEvents,
((TestMemoryThresholdListener) listener).getCriticalThresholdCalls());
assertEquals(normalEvents, ((TestMemoryThresholdListener) listener).getNormalCalls());
}
}
}
@Test
public void testDisabledThresholds() throws Exception {
final InternalResourceManager irm = this.cache.getInternalResourceManager();
final OffHeapMemoryMonitor monitor = irm.getOffHeapMonitor();
final RegionFactory regionFactory = this.cache.createRegionFactory(RegionShortcut.LOCAL);
regionFactory.setOffHeap(true);
final EvictionAttributesImpl evictionAttrs = new EvictionAttributesImpl();
evictionAttrs.setAlgorithm(EvictionAlgorithm.NONE);
regionFactory.setEvictionAttributes(evictionAttrs);
final Region region = regionFactory.create("testDefaultThresholdsRegion");
TestMemoryThresholdListener listener = new TestMemoryThresholdListener();
irm.addResourceListener(ResourceType.OFFHEAP_MEMORY, listener);
region.put("1", new Byte[550000]);
region.put("2", new Byte[200000]);
assertEquals(0, irm.getStats().getOffHeapEvictionStartEvents());
assertEquals(0, irm.getStats().getOffHeapEvictionStopEvents());
assertEquals(0, irm.getStats().getOffHeapCriticalEvents());
assertEquals(0, irm.getStats().getOffHeapSafeEvents());
assertEquals(0, listener.getEvictionThresholdCalls());
assertEquals(0, listener.getCriticalThresholdCalls());
// Enable eviction threshold and make sure event is generated
monitor.setEvictionThreshold(50f);
assertEquals(1, irm.getStats().getOffHeapEvictionStartEvents());
assertEquals(0, irm.getStats().getOffHeapCriticalEvents());
assertEquals(1, listener.getEvictionThresholdCalls());
assertEquals(0, listener.getCriticalThresholdCalls());
// Enable critical threshold and make sure event is generated
region.put("3", new Byte[200000]);
monitor.setCriticalThreshold(70f);
assertEquals(1, irm.getStats().getOffHeapEvictionStartEvents());
assertEquals(1, irm.getStats().getOffHeapCriticalEvents());
assertEquals(2, listener.getEvictionThresholdCalls());
assertEquals(1, listener.getCriticalThresholdCalls());
// Disable thresholds and verify events
monitor.setEvictionThreshold(0f);
monitor.setCriticalThreshold(0f);
assertEquals(1, irm.getStats().getOffHeapEvictionStartEvents());
assertEquals(1, irm.getStats().getOffHeapEvictionStopEvents());
assertEquals(1, irm.getStats().getOffHeapCriticalEvents());
assertEquals(1, irm.getStats().getOffHeapSafeEvents());
assertEquals(2, listener.getEvictionThresholdCalls());
assertEquals(2, listener.getCriticalThresholdCalls());
assertEquals(0, listener.getNormalCalls());
assertEquals(2, listener.getEvictionDisabledCalls());
assertEquals(2, listener.getCriticalDisabledCalls());
}
@Test
public void testAllowedThreholds() {
final OffHeapMemoryMonitor monitor =
this.cache.getInternalResourceManager().getOffHeapMonitor();
// Test eviction bounds
try {
monitor.setEvictionThreshold(100.1f);
fail("Too high value allowed for setEvictionThreshold");
} catch (IllegalArgumentException expected) {
// Expected
}
try {
monitor.setEvictionThreshold(-0.1f);
fail("Too low value allowed for setEvictionThreshold");
} catch (IllegalArgumentException expected) {
// Expected
}
monitor.setEvictionThreshold(13f);
monitor.setEvictionThreshold(0f);
monitor.setEvictionThreshold(92f);
monitor.setEvictionThreshold(100f);
monitor.setEvictionThreshold(0f);
// Test critical bounds
try {
monitor.setCriticalThreshold(100.1f);
fail("Too high value allowed for setCriticalThreshold");
} catch (IllegalArgumentException expected) {
// Expected
}
try {
monitor.setCriticalThreshold(-0.1f);
fail("Too low value allowed for setCriticalThreshold");
} catch (IllegalArgumentException expected) {
// Expected
}
monitor.setCriticalThreshold(13f);
monitor.setCriticalThreshold(0f);
monitor.setCriticalThreshold(92f);
monitor.setCriticalThreshold(100f);
monitor.setCriticalThreshold(0f);
// Test values relative to each other
monitor.setEvictionThreshold(1f);
monitor.setCriticalThreshold(1.1f);
monitor.setCriticalThreshold(0);
monitor.setCriticalThreshold(1.1f);
monitor.setEvictionThreshold(0);
monitor.setEvictionThreshold(1.0f);
monitor.setCriticalThreshold(100f);
monitor.setEvictionThreshold(99.9f);
monitor.setCriticalThreshold(0f);
monitor.setEvictionThreshold(0f);
monitor.setEvictionThreshold(64.1f);
monitor.setCriticalThreshold(64.2f);
try {
monitor.setCriticalThreshold(50f);
monitor.setEvictionThreshold(50.1f);
fail("Allowed eviction threshold to be set higher than critical threshold");
} catch (IllegalArgumentException expected) {
// Expected
}
}
@Test
public void testMonitorRunning() {
final OffHeapMemoryMonitor monitor =
this.cache.getInternalResourceManager().getOffHeapMonitor();
assertFalse("Off-heap monitor is not running", monitor.started);
monitor.setEvictionThreshold(1f);
assertTrue("Off-heap monitor is running", monitor.started);
monitor.setEvictionThreshold(0f);
assertFalse("Off-heap monitor is not running", monitor.started);
monitor.setCriticalThreshold(1f);
assertTrue("Off-heap monitor is running", monitor.started);
monitor.setCriticalThreshold(0f);
assertFalse("Off-heap monitor is not running", monitor.started);
monitor.setEvictionThreshold(1f);
monitor.setCriticalThreshold(1.1f);
assertTrue("Off-heap monitor is running", monitor.started);
monitor.setEvictionThreshold(0f);
monitor.setCriticalThreshold(0f);
assertFalse("Off-heap monitor is not running", monitor.started);
}
@Test
public void testGettersAndSetters() {
final OffHeapMemoryMonitor monitor =
this.cache.getInternalResourceManager().getOffHeapMonitor();
assertEquals(0f, monitor.getEvictionThreshold(), 0.01);
assertEquals(0f, monitor.getCriticalThreshold(), 0.01);
monitor.setEvictionThreshold(35);
assertEquals(35f, monitor.getEvictionThreshold(), 0.01);
assertEquals(0f, monitor.getCriticalThreshold(), 0.01);
monitor.setCriticalThreshold(45);
assertEquals(35f, monitor.getEvictionThreshold(), 0.01);
assertEquals(45f, monitor.getCriticalThreshold(), 0.01);
monitor.setEvictionThreshold(0);
monitor.setCriticalThreshold(0);
assertEquals(0f, monitor.getEvictionThreshold(), 0.01);
assertEquals(0f, monitor.getCriticalThreshold(), 0.01);
}
}