/* * Copyright (C) 2005 Alfresco, Inc. * * Licensed under the Mozilla Public License version 1.1 * with a permitted attribution clause. You may obtain a * copy of the License at * * http://www.alfresco.org/legal/license.txt * * 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.alfresco.repo.cache; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.List; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheException; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Element; import net.sf.ehcache.Status; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; /** * Analyzes the size of EHCache caches used. *
* To activate this class, call the {@link #init()} method.
*
* @author Derek Hulley
*/
public class EhCacheTracerJob implements Job
{
private static Log logger = LogFactory.getLog(EhCacheTracerJob.class);
private CacheManager cacheManager;
/**
* Set the cache manager to analyze. The default cache manager will be analyzed
* if this property is not set.
*
* @param cacheManager optional cache manager to analyze
*/
public void setCacheManager(CacheManager cacheManager)
{
this.cacheManager = cacheManager;
}
public void execute(JobExecutionContext context) throws JobExecutionException
{
try
{
execute();
}
catch (Throwable e)
{
logger.error("Exception during execution of job", e);
}
}
private void execute() throws Exception
{
if (cacheManager == null)
{
cacheManager = CacheManager.getInstance();
}
long maxHeapSize = Runtime.getRuntime().maxMemory();
long allCachesTotalSize = 0L;
double estimatedMaxSize = 0L;
// get all the caches
String[] cacheNames = cacheManager.getCacheNames();
logger.debug("Dumping EHCache info:");
boolean analyzeAll = true;
for (String cacheName : cacheNames)
{
Cache cache = cacheManager.getCache(cacheName);
if (cache == null) // perhaps a temporary cache
{
continue;
}
Log cacheLogger = LogFactory.getLog(this.getClass().getName() + "." + cacheName);
// log each cache to its own logger
// dump
if (cacheLogger.isDebugEnabled())
{
CacheAnalysis analysis = new CacheAnalysis(cache);
cacheLogger.debug(analysis);
// get the size
allCachesTotalSize += analysis.getSize();
double cacheEstimatedMaxSize = analysis.getEstimatedMaxSize();
estimatedMaxSize += (Double.isNaN(cacheEstimatedMaxSize) || Double.isInfinite(cacheEstimatedMaxSize))
? 0.0
: cacheEstimatedMaxSize;
}
else
{
analyzeAll = false;
}
}
if (analyzeAll)
{
// check the size
double sizePercentage = (double)allCachesTotalSize / (double)maxHeapSize * 100.0;
double maxSizePercentage = estimatedMaxSize / (double)maxHeapSize * 100.0;
String msg = String.format(
"EHCaches currently consume %5.2f MB or %3.2f percent of system VM size. \n" +
"The estimated maximum size is %5.2f MB or %3.2f percent of system VM size.",
(double)allCachesTotalSize / 1024.0 / 1024.0,
sizePercentage,
estimatedMaxSize / 1024.0 / 1024.0,
maxSizePercentage);
logger.debug(msg);
}
}
private static class CacheAnalysis
{
private Cache cache;
private long size = 0L;
double sizeMB;
long maxSize;
long currentSize;
long hitCount;
long missCount;
double percentageFull;
double estMaxSize;
public CacheAnalysis(Cache cache) throws CacheException
{
this.cache = cache;
if (this.cache.getStatus().equals(Status.STATUS_ALIVE))
{
try
{
calculateSize();
}
catch (Throwable e)
{
// just ignore
}
}
}
public synchronized long getSize()
{
return size;
}
public synchronized double getEstimatedMaxSize()
{
return estMaxSize;
}
@SuppressWarnings("unchecked")
private synchronized void calculateSize() throws CacheException
{
// calculate the cache deep size - EHCache 1.1 is always returning 0L
List