blob: 71660244095cbcdc7f8becebf3725a671615276f [file] [log] [blame]
/*=========================================================================
* Copyright (c) 2002-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
* more patents listed at http://www.pivotal.io/patents.
*=========================================================================
*/
package com.gemstone.gemfire.internal.admin;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import com.gemstone.gemfire.Statistics;
import com.gemstone.gemfire.StatisticsType;
import com.gemstone.gemfire.cache.CacheWriterException;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.client.internal.PoolImpl;
import com.gemstone.gemfire.cache.client.internal.ServerRegionProxy;
import com.gemstone.gemfire.cache.query.CqQuery;
import com.gemstone.gemfire.cache.util.BridgeWriterException;
import com.gemstone.gemfire.distributed.DistributedSystemDisconnectedException;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import com.gemstone.gemfire.i18n.LogWriterI18n;
import com.gemstone.gemfire.internal.admin.remote.ClientHealthStats;
import com.gemstone.gemfire.internal.cache.EntryEventImpl;
import com.gemstone.gemfire.internal.cache.EventID;
import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
import com.gemstone.gemfire.management.internal.cli.CliUtil;
/**
* This class publishes the client statistics using the admin region.
*
* @author Hrishi
*/
public class ClientStatsManager {
/**
* Last cache that was initialized
*
* @guarded.By ClientStatsManager.class
*/
static GemFireCacheImpl lastInitializedCache = null;
/**
* @guarded.By ClientStatsManager.class
*/
private static Statistics cachePerfStats = null;
/**
* @guarded.By ClientStatsManager.class
*/
private static Statistics vmStats = null;
/**
* This method publishes the client stats using the admin region.
*
* @param pool
* Connection pool which may be used for admin region.
*/
public static synchronized void publishClientStats(PoolImpl pool) {
GemFireCacheImpl currentCache = GemFireCacheImpl.getInstance();
if (!initializeStatistics(currentCache)) {
return; // handles null case too
}
LogWriterI18n logger = currentCache.getLoggerI18n();
if (logger.fineEnabled())
logger.fine("Entering ClientStatsManager#publishClientStats...");
ClientHealthStats stats = getClientHealthStats(currentCache, pool);
try {
InternalDistributedSystem ds = (InternalDistributedSystem)
currentCache.getDistributedSystem();
ServerRegionProxy regionProxy = new ServerRegionProxy(ClientHealthMonitoringRegion.ADMIN_REGION_NAME, pool);
EventID eventId = new EventID(ds);
EntryEventImpl event = new EntryEventImpl((Object)null);
try {
event.setEventId(eventId);
regionProxy.putForMetaRegion(ds.getMemberId(), stats, null, event, null, true);
} finally {
event.release();
}
}
catch (DistributedSystemDisconnectedException e) {
throw e;
}
catch (BridgeWriterException bgx) {
pool.getCancelCriterion().checkCancelInProgress(bgx);
currentCache.getCancelCriterion().checkCancelInProgress(bgx);
//TODO: Need to analyze these exception scenarios.
logger.warning(LocalizedStrings.ClientStatsManager_FAILED_TO_SEND_CLIENT_HEALTH_STATS_TO_CACHESERVER, bgx);
}
catch (CacheWriterException cwx) {
pool.getCancelCriterion().checkCancelInProgress(cwx);
currentCache.getCancelCriterion().checkCancelInProgress(cwx);
// TODO: Need to analyze these exception scenarios.
logger.warning(LocalizedStrings.ClientStatsManager_FAILED_TO_SEND_CLIENT_HEALTH_STATS_TO_CACHESERVER, cwx);
}
catch (Exception e) {
pool.getCancelCriterion().checkCancelInProgress(e);
currentCache.getCancelCriterion().checkCancelInProgress(e);
logger.info(LocalizedStrings.ClientStatsManager_FAILED_TO_PUBLISH_CLIENT_STATISTICS, e);
}
if (logger.fineEnabled())
logger.fine("Exiting ClientStatsManager#publishClientStats.");
}
public static void cleanupForTests() {
lastInitializedCache = null;
}
/**
* This method initializes the client statistics to be queried.
*
* @return true if statistics correctly initialized
* @guarded.By ClientStatsManager.class
*/
private static boolean initializeStatistics(GemFireCacheImpl currentCache) {
if (currentCache == null) {
return false;
}
LogWriterI18n logger = currentCache.getLoggerI18n();
InternalDistributedSystem ds = (InternalDistributedSystem)currentCache.getDistributedSystem();
if (currentCache.isClosed()) {
return false;
}
boolean restart = lastInitializedCache != currentCache;
lastInitializedCache = currentCache;
if(restart) {
if(logger.infoEnabled()) {
logger.info(LocalizedStrings.ClientStatsManager_CLIENTSTATSMANAGER_INTIALIZING_THE_STATISTICS);
}
cachePerfStats = null;
vmStats = null;
}
if(cachePerfStats == null) {
StatisticsType type = ds.findType("CachePerfStats");
if(type != null) {
Statistics[] statistics = ds.findStatisticsByType(type);
if(statistics != null && statistics.length > 0) {
cachePerfStats = statistics[0];
}
}
}
if(vmStats == null) {
StatisticsType type = ds.findType("VMStats");
if(type != null) {
Statistics[] statistics = ds.findStatisticsByType(type);
if(statistics != null && statistics.length > 0) {
vmStats = statistics[0];
}
}
}
// Validate that cache has changed before logging the warning, thus logging it once per cache
if(cachePerfStats == null && restart) {
logger.warning(LocalizedStrings.ClientStatsManager_CLIENTSTATSMANAGER_0_ARE_NOT_AVAILABLE, "CachePerfStats");
}
// Validate that cache has changed before logging the warning, thus logging it once per cache
if(vmStats == null && restart) {
logger.warning(LocalizedStrings.ClientStatsManager_CLIENTSTATSMANAGER_0_ARE_NOT_AVAILABLE, "VMStats");
}
return true;
}
/**
* This method queries the client stats & prepares the client health stats
* object to be published to the server.
*
* @return the client health stats object to be published to the server.
*/
private static ClientHealthStats getClientHealthStats(GemFireCacheImpl currentCache, PoolImpl pool) {
if (currentCache == null) {
return null;
}
ClientHealthStats stats = new ClientHealthStats();
LogWriterI18n logger = currentCache.getLoggerI18n();
{
int gets = -1;
int puts = -1;
int misses = -1;
long processCpuTime = -1;
int threads = -1;
int cacheListenerCalls = -1;
int cpus = -1;
String poolName = "";
if(cachePerfStats != null) {
gets = cachePerfStats.getInt("gets");
puts = cachePerfStats.getInt("puts");
misses = cachePerfStats.getInt("misses");
cacheListenerCalls = cachePerfStats.getInt("cacheListenerCallsCompleted");
}
if(vmStats != null) {
processCpuTime = vmStats.getLong("processCpuTime");
threads =vmStats.getInt("threads");
cpus = vmStats.getInt("cpus");
}
stats.setNumOfGets(gets);
stats.setNumOfPuts(puts);
stats.setNumOfMisses(misses);
stats.setNumOfCacheListenerCalls(cacheListenerCalls);
stats.setProcessCpuTime(processCpuTime);
stats.setNumOfThreads(threads);
stats.setCpus(cpus);
poolName = pool.getName();
try {
Map<String, String> newPoolStats = stats.getPoolStats();
String poolStatsStr = "MinConnections=" + pool.getMinConnections() + ";MaxConnections=" + pool.getMaxConnections()
+ ";Redudancy=" + pool.getSubscriptionRedundancy() + ";CQS=" + pool.getQueryService().getCqs().length ;
logger.info(LocalizedStrings.DEBUG,"ClientHealthStats for poolname " + poolName + " poolStatsStr=" + poolStatsStr);
newPoolStats.put(poolName, poolStatsStr);
// consider old stats
Region clientHealthMonitoringRegion = ClientHealthMonitoringRegion.getInstance(currentCache);
if (clientHealthMonitoringRegion != null) {
InternalDistributedSystem ds = (InternalDistributedSystem) currentCache.getDistributedSystem();
ClientHealthStats oldStats = (ClientHealthStats) clientHealthMonitoringRegion.get(ds.getMemberId());
logger.info(LocalizedStrings.DEBUG,"getClientHealthStats got oldStats " + oldStats);
if (oldStats != null) {
Map<String, String> oldPoolStats = oldStats.getPoolStats();
logger.info(LocalizedStrings.DEBUG,"getClientHealthStats got oldPoolStats " + oldPoolStats);
if (oldPoolStats != null) {
Iterator<Entry<String, String>> it = oldPoolStats.entrySet().iterator();
while (it.hasNext()) {
Entry<String, String> entry = it.next();
if (!poolName.equals(entry.getKey())) {
stats.getPoolStats().put(entry.getKey(), entry.getValue());
}
}
}
}
}
} catch (Exception e) {
logger.fine("Exception in getting pool stats in getClientHealthStats " + CliUtil.stackTraceAsString(e));
}
}
stats.setUpdateTime(new Date());
return stats;
}
}