blob: c902b0b2e0b8cfa089a2e7598f09cc23749f2785 [file] [log] [blame]
/*=========================================================================
* Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* one or more patents listed at http://www.pivotal.io/patents.
*=========================================================================
*/
package com.gemstone.gemfire.modules.session.bootstrap;
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.control.ResourceManager;
import com.gemstone.gemfire.distributed.internal.AbstractDistributionConfig;
import com.gemstone.gemfire.distributed.internal.DistributionConfig;
import com.gemstone.gemfire.internal.cache.LocalRegion;
import com.gemstone.gemfire.modules.util.Banner;
import com.gemstone.gemfire.modules.util.RegionHelper;
import com.gemstone.gemfire.modules.util.ResourceManagerValidator;
import java.util.concurrent.atomic.AtomicBoolean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class AbstractCache {
protected GemFireCache cache;
private static final DateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd");
protected static final String DEFAULT_LOG_FILE_NAME = RegionHelper.NAME + "." + FORMAT.format(new Date()) + ".log";
protected static final String DEFAULT_STATISTIC_ARCHIVE_FILE_NAME = RegionHelper.NAME + ".gfs";
protected static final float DEFAULT_EVICTION_HEAP_PERCENTAGE = LocalRegion.DEFAULT_HEAPLRU_EVICTION_HEAP_PERCENTAGE;
protected static final float DEFAULT_CRITICAL_HEAP_PERCENTAGE = ResourceManager.DEFAULT_CRITICAL_HEAP_PERCENTAGE;
protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractCache.class);
protected float evictionHeapPercentage = DEFAULT_EVICTION_HEAP_PERCENTAGE;
protected float criticalHeapPercentage = DEFAULT_CRITICAL_HEAP_PERCENTAGE;
protected boolean rebalance = false;
protected final Map<String,String> gemfireProperties;
private final AtomicBoolean started = new AtomicBoolean(false);
/**
* Instance reference which is set in static initialization blocks of any
* subclasses.
*/
protected static AbstractCache instance = null;
public AbstractCache() {
this.gemfireProperties = new ConcurrentHashMap<String,String>();
}
public void lifecycleEvent(LifecycleTypeAdapter eventType) {
if (getLogger().isDebugEnabled()) {
getLogger().debug("Received " + eventType + " event");
}
if (eventType.equals(LifecycleTypeAdapter.START) &&
started.compareAndSet(false, true)) {
// Create or retrieve the cache
getLogger().info("Initializing " + Banner.getString());
createOrRetrieveCache();
// Initialize the resource manager
initializeResourceManager();
} else if (eventType.equals(LifecycleTypeAdapter.AFTER_START)) {
if (getRebalance()) {
rebalanceCache();
}
} else if (eventType.equals(LifecycleTypeAdapter.STOP)) {
// Close the cache
// closeCache();
// TODO: Do we need to reset the started flag here?
}
}
public boolean isStarted() {
return started.get();
}
public void close() {
getCache().close();
while (! getCache().isClosed()) {
}
started.set(false);
}
public GemFireCache getCache() {
return this.cache;
}
public String getLogFileName() {
String logFileName = getGemFireProperties().get(DistributionConfig.LOG_FILE_NAME);
if (logFileName == null) {
logFileName = DEFAULT_LOG_FILE_NAME;
}
return logFileName;
}
public String getStatisticArchiveFileName() {
String statisticsArchiveFileName = getGemFireProperties().get(DistributionConfig.STATISTIC_ARCHIVE_FILE_NAME);
if (statisticsArchiveFileName == null) {
statisticsArchiveFileName = DEFAULT_STATISTIC_ARCHIVE_FILE_NAME;
}
return statisticsArchiveFileName;
}
public String getCacheXmlFileName() {
String cacheXmlFileName = getGemFireProperties().get(DistributionConfig.CACHE_XML_FILE_NAME);
if (cacheXmlFileName == null) {
cacheXmlFileName = getDefaultCacheXmlFileName();
}
return cacheXmlFileName;
}
protected File getCacheXmlFile() {
String cacheXmlFileName = getCacheXmlFileName();
File cacheXmlFile = new File(cacheXmlFileName);
// If the cache xml file is not absolute, point it at the conf directory.
if (!cacheXmlFile.isAbsolute()) {
if (System.getProperty("catalina.base") != null) {
cacheXmlFile = new File(System.getProperty("catalina.base") + "/conf/", cacheXmlFileName);
}
}
return cacheXmlFile;
}
public float getEvictionHeapPercentage() {
return this.evictionHeapPercentage;
}
public void setEvictionHeapPercentage(String evictionHeapPercentage) {
this.evictionHeapPercentage = Float.valueOf(evictionHeapPercentage);
}
public float getCriticalHeapPercentage() {
return this.criticalHeapPercentage;
}
public void setCriticalHeapPercentage(String criticalHeapPercentage) {
this.criticalHeapPercentage = Float.valueOf(criticalHeapPercentage);
}
public void setRebalance(boolean rebalance) {
this.rebalance = rebalance;
}
public boolean getRebalance() {
return this.rebalance;
}
public Map<String,String> getGemFireProperties() {
return this.gemfireProperties;
}
public void setProperty(String name, String value) {
//TODO Look at fake attributes
if (name.equals("className")) {
return;
}
// Determine the validity of the input property
boolean validProperty = false;
for (String gemfireProperty : AbstractDistributionConfig._getAttNames()) {
if (name.equals(gemfireProperty)) {
validProperty = true;
break;
}
}
// If it is a valid GemFire property, add it to the the GemFire properties.
// Otherwise, log a warning.
if (validProperty) {
this.gemfireProperties.put(name, value);
} else {
getLogger().warn("The input property named " + name + " is not a valid GemFire property. It is being ignored.");
}
}
public Logger getLogger() {
return LOGGER;
}
protected Properties createDistributedSystemProperties() {
Properties properties = new Properties();
// Add any additional gemfire properties
for (Map.Entry<String,String> entry : this.gemfireProperties.entrySet()) {
properties.put(entry.getKey(), entry.getValue());
}
// Replace the cache xml file in the properties
File cacheXmlFile = getCacheXmlFile();
String absoluteCacheXmlFileName = cacheXmlFile.getAbsolutePath();
// If the file doesn't exist and the name is the default, set cache-xml-file
// to the GemFire default. This is for the case where only the jars have been
// installed and no default cache.xml exists in the conf directory.
if (getCacheXmlFileName().equals(getDefaultCacheXmlFileName()) && !cacheXmlFile.exists()) {
absoluteCacheXmlFileName = DistributionConfig.DEFAULT_CACHE_XML_FILE.getName();
}
properties.put(DistributionConfig.CACHE_XML_FILE_NAME, absoluteCacheXmlFileName);
// Replace the log file in the properties
properties.put(DistributionConfig.LOG_FILE_NAME, getLogFile().getAbsolutePath());
// Replace the statistics archive file in the properties
File statisticArchiveFile = getStatisticArchiveFile();
if (statisticArchiveFile == null) {
// Remove the statistics archive file name since statistic sampling is disabled
properties.remove(DistributionConfig.STATISTIC_ARCHIVE_FILE_NAME);
properties.remove(DistributionConfig.STATISTIC_SAMPLING_ENABLED_NAME);
} else {
properties.put(DistributionConfig.STATISTIC_ARCHIVE_FILE_NAME, statisticArchiveFile.getAbsolutePath());
}
getLogger().info("Creating distributed system from: " + properties);
return properties;
}
protected void closeCache() {
if (getLogger().isDebugEnabled()) {
getLogger().debug("Closing " + this.cache);
}
if (getCache() != null) {
getCache().close();
}
getLogger().info("Closed " + this.cache);
}
protected File getLogFile() {
String logFileName = getLogFileName();
File logFile = new File(logFileName);
// If the log file is not absolute, point it at the logs directory.
if (!logFile.isAbsolute()) {
if (System.getProperty("catalina.base") != null) {
logFile = new File(System.getProperty("catalina.base") + "/logs/", logFileName);
} else if (System.getProperty("weblogic.Name") != null) {
String weblogicName = System.getProperty("weblogic.Name");
String separator = System.getProperty("file.separator");
logFile = new File("servers" + separator + weblogicName + separator +
"logs" + separator + logFileName);
} else {
logFile = new File(System.getProperty("gemfire.logdir"), logFileName);
}
}
return logFile;
}
protected File getStatisticArchiveFile() {
File statisticsArchiveFile = null;
String statisticSamplingEnabled = getGemFireProperties().get(DistributionConfig.STATISTIC_SAMPLING_ENABLED_NAME);
if (statisticSamplingEnabled != null && statisticSamplingEnabled.equals("true")) {
String statisticsArchiveFileName = getStatisticArchiveFileName();
statisticsArchiveFile = new File(statisticsArchiveFileName);
// If the statistics archive file is not absolute, point it at the logs directory.
if (!statisticsArchiveFile.isAbsolute()) {
if (System.getProperty("catalina.base") != null) {
statisticsArchiveFile = new File(System.getProperty("catalina.base") +
"/logs/", statisticsArchiveFileName);
} else if (System.getProperty("weblogic.Name") != null) {
String weblogicName = System.getProperty("weblogic.Name");
String separator = System.getProperty("file.separator");
statisticsArchiveFile = new File("servers" + separator + weblogicName + separator +
"logs" + separator + statisticsArchiveFileName);
} else {
statisticsArchiveFile = new File(System.getProperty("gemfire.statisticsdir"),
statisticsArchiveFileName);
}
}
}
return statisticsArchiveFile;
}
protected void initializeResourceManager() {
// Get current eviction and critical heap percentages
ResourceManager rm = getCache().getResourceManager();
float currentEvictionHeapPercentage = rm.getEvictionHeapPercentage();
float currentCriticalHeapPercentage = rm.getCriticalHeapPercentage();
// Set new eviction and critical heap percentages if necessary
if (getEvictionHeapPercentage() != currentEvictionHeapPercentage
|| getCriticalHeapPercentage() != currentCriticalHeapPercentage) {
if (getLogger().isDebugEnabled()) {
StringBuilder builder = new StringBuilder();
builder
.append("Previous eviction heap percentage=")
.append(currentEvictionHeapPercentage)
.append("; critical heap percentage=")
.append(currentCriticalHeapPercentage);
getLogger().debug(builder.toString());
builder.setLength(0);
builder
.append("Requested eviction heap percentage=")
.append(getEvictionHeapPercentage())
.append("; critical heap percentage=")
.append(getCriticalHeapPercentage());
getLogger().debug(builder.toString());
}
if (currentCriticalHeapPercentage == 0.0f) {
// If the current critical heap percentage is 0 (disabled), set eviction
// heap percentage first, then set the critical heap percentage. At this
// point, the eviction heap percentage can be set to anything.
try {
rm.setEvictionHeapPercentage(getEvictionHeapPercentage());
rm.setCriticalHeapPercentage(getCriticalHeapPercentage());
} catch (IllegalArgumentException e) {
handleResourceManagerException(e, currentEvictionHeapPercentage, currentCriticalHeapPercentage);
rm.setEvictionHeapPercentage(currentEvictionHeapPercentage);
rm.setCriticalHeapPercentage(currentCriticalHeapPercentage);
}
} else if (getCriticalHeapPercentage() >= currentCriticalHeapPercentage) {
// If the requested critical heap percentage is >= the current critical
// heap percentage, then set the critical heap percentage first since it
// can safely be slid up. Then, set the eviction heap percentage.
try {
rm.setCriticalHeapPercentage(getCriticalHeapPercentage());
rm.setEvictionHeapPercentage(getEvictionHeapPercentage());
} catch (IllegalArgumentException e) {
handleResourceManagerException(e, currentEvictionHeapPercentage, currentCriticalHeapPercentage);
rm.setCriticalHeapPercentage(currentCriticalHeapPercentage);
rm.setEvictionHeapPercentage(currentEvictionHeapPercentage);
}
} else {
// If the requested critical heap percentage is < the current critical
// heap percentage, then set the eviction heap percentage first since it
// can safely be slid down. Then, set the critical heap percentage.
try {
rm.setEvictionHeapPercentage(getEvictionHeapPercentage());
rm.setCriticalHeapPercentage(getCriticalHeapPercentage());
} catch (IllegalArgumentException e) {
handleResourceManagerException(e, currentEvictionHeapPercentage, currentCriticalHeapPercentage);
rm.setEvictionHeapPercentage(currentEvictionHeapPercentage);
rm.setCriticalHeapPercentage(currentCriticalHeapPercentage);
}
}
if (getLogger().isDebugEnabled()) {
StringBuilder builder = new StringBuilder();
builder
.append("Actual eviction heap percentage=")
.append(rm.getEvictionHeapPercentage())
.append("; critical heap percentage=")
.append(rm.getCriticalHeapPercentage());
getLogger().debug(builder.toString());
}
}
// Validate java startup parameters (done after setting the eviction and
// critical heap percentages so that the CMSInitiatingOccupancyFraction can
// be compared against them.
ResourceManagerValidator.validateJavaStartupParameters(getCache());
}
private void handleResourceManagerException(IllegalArgumentException e,
float currentEvictionHeapPercentage, float currentCriticalHeapPercentage) {
StringBuilder builder = new StringBuilder();
builder
.append("Caught exception attempting to set eviction heap percentage=")
.append(getEvictionHeapPercentage())
.append(" and critical heap percentage=")
.append(getCriticalHeapPercentage())
.append(". The percentages will be set back to their previous values (eviction heap percentage=")
.append(currentEvictionHeapPercentage)
.append(" and critical heap percentage=")
.append(currentCriticalHeapPercentage)
.append(").");
getLogger().warn(builder.toString(), e);
}
@Override
public String toString() {
return new StringBuilder()
.append(getClass().getSimpleName())
.append("[")
.append("cache=")
.append(this.cache)
.append("]")
.toString();
}
protected abstract void createOrRetrieveCache();
protected abstract void rebalanceCache();
protected abstract String getDefaultCacheXmlFileName();
}