blob: c67c5ec9f1cddbc7eac3ef334a6c6b2024c8b997 [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.modules.util;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.control.ResourceManager;
public class ResourceManagerValidator {
private static final Pattern DIGIT_PATTERN = Pattern.compile("(\\d+|[^\\d]+)");
public static void validateJavaStartupParameters(GemFireCache cache) {
// Get the input arguments
ResourceManager rm = cache.getResourceManager();
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
List<String> inputArguments = runtimeBean.getInputArguments();
if (cache.getLogger().fineEnabled()) {
cache.getLogger().fine("Full input java arguments: " + inputArguments);
}
// Validate the arguments based on VM vendor
String vmVendor = runtimeBean.getVmVendor();
if (vmVendor.startsWith("Sun") || vmVendor.startsWith("Apple")) {
// java.vm.vendor = Sun Microsystems Inc. || java.vm.vendor = Apple Inc.
validateSunArguments(cache, rm, inputArguments);
} else if (vmVendor.startsWith("IBM")) {
// java.vm.vendor = IBM Corporation
// TODO validate IBM input arguments
} else if (vmVendor.startsWith("BEA")) {
// java.vm.vendor = BEA Systems, Inc.
// TODO validate JRockit input arguments
}
}
private static void validateSunArguments(GemFireCache cache, ResourceManager rm,
List<String> inputArguments) {
// Retrieve the -Xms, -Xmx, UseConcMarkSweepGC and CMSInitiatingOccupancyFraction arguments
String dashXms = null, dashXmx = null, useCMS = null, cmsIOF = null;
for (String argument : inputArguments) {
if (argument.startsWith("-Xms")) {
dashXms = argument;
} else if (argument.startsWith("-Xmx")) {
dashXmx = argument;
} else if (argument.equals("-XX:+UseConcMarkSweepGC")) {
useCMS = argument;
} else if (argument.startsWith("-XX:CMSInitiatingOccupancyFraction")) {
cmsIOF = argument;
}
}
if (cache.getLogger().fineEnabled()) {
StringBuilder builder = new StringBuilder();
builder.append("Relevant input java arguments: ").append("dashXms=").append(dashXms)
.append("; dashXmx=").append(dashXmx).append("; useCMS=").append(useCMS)
.append("; cmsIOF=").append(cmsIOF);
cache.getLogger().fine(builder.toString());
}
// Validate the heap parameters
validateJavaHeapParameters(cache, dashXms, dashXmx);
// Verify CMS is specified
verifyCMSGC(cache, useCMS);
// Verify CMSInitiatingOccupancyFraction is specified
verifyCMSInitiatingOccupancyFraction(cache, rm, cmsIOF);
}
private static void validateJavaHeapParameters(GemFireCache cache, String dashXms,
String dashXmx) {
if (dashXms == null) {
cache.getLogger().warning(
"Setting the initial size of the heap (configured using -Xms) is recommended so that GemFire cache eviction is optimal");
} else if (dashXmx == null) {
cache.getLogger().warning(
"Setting the maximum size of the heap (configured using -Xmx) is recommended so that GemFire cache eviction is optimal");
} else {
// Neither heap parameter is null. Parse them and verify they are the same.
List<String> dashXmsList = splitAtDigits(dashXms);
String dashXmsStr = dashXmsList.get(1);
List<String> dashXmxList = splitAtDigits(dashXmx);
String dashXmxStr = dashXmxList.get(1);
if (!dashXmsStr.equals(dashXmxStr)) {
StringBuilder builder = new StringBuilder();
builder.append("Setting the initial (").append(dashXmsStr).append(dashXmsList.get(2))
.append(") and maximum (").append(dashXmxStr).append(dashXmxList.get(2)).append(
") sizes of the heap the same is recommended so that GemFire cache eviction is optimal");
cache.getLogger().warning(builder.toString());
}
}
}
private static void verifyCMSGC(GemFireCache cache, String useCMS) {
if (useCMS == null) {
cache.getLogger().warning(
"Using the concurrent garbage collector (configured using -XX:+UseConcMarkSweepGC) is recommended so that GemFire cache eviction is optimal");
}
}
private static void verifyCMSInitiatingOccupancyFraction(GemFireCache cache, ResourceManager rm,
String cmsIOF) {
if (cmsIOF == null) {
cache.getLogger().warning(
"Setting the CMS initiating occupancy fraction (configured using -XX:CMSInitiatingOccupancyFraction=N) is recommended so that GemFire cache eviction is optimal");
} else {
// Parse the CMSInitiatingOccupancyFraction. Verify it is less than both eviction and critical
// thresholds.
int cmsIOFVal = Integer.parseInt(cmsIOF.split("=")[1]);
float currentEvictionHeapPercentage = rm.getEvictionHeapPercentage();
if (currentEvictionHeapPercentage != 0 && currentEvictionHeapPercentage < cmsIOFVal) {
cache.getLogger()
.warning("Setting the CMS initiating occupancy fraction (" + cmsIOFVal
+ ") less than the eviction heap percentage (" + currentEvictionHeapPercentage
+ ") is recommended so that GemFire cache eviction is optimal");
}
float currentCriticalHeapPercentage = rm.getCriticalHeapPercentage();
if (currentCriticalHeapPercentage != 0 && currentCriticalHeapPercentage < cmsIOFVal) {
cache.getLogger()
.warning("Setting the CMS initiating occupancy fraction (" + cmsIOFVal
+ ") less than the critical heap percentage (" + currentCriticalHeapPercentage
+ ") is recommended so that GemFire cache eviction is optimal");
}
}
}
private static List<String> splitAtDigits(String input) {
Matcher matcher = DIGIT_PATTERN.matcher(input);
List<String> result = new ArrayList<String>();
while (matcher.find()) {
result.add(matcher.group());
}
return result;
}
private ResourceManagerValidator() {}
}