com.gemstone.gemfire.admin.jmx.internal.MemberInfoWithStatsMBean Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gemfire-core Show documentation
Show all versions of gemfire-core Show documentation
SnappyData store based off Pivotal GemFireXD
/*
* Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
*
* Licensed 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. See accompanying
* LICENSE file.
*/
package com.gemstone.gemfire.admin.jmx.internal;
import java.net.InetAddress;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicLong;
import javax.management.InstanceNotFoundException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationEmitter;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.OperationsException;
import javax.management.ReflectionException;
import mx4j.AbstractDynamicMBean;
import com.gemstone.gemfire.admin.AdminDistributedSystem;
import com.gemstone.gemfire.admin.AdminException;
import com.gemstone.gemfire.admin.CacheVm;
import com.gemstone.gemfire.admin.ConfigurationParameter;
import com.gemstone.gemfire.admin.GemFireMemberStatus;
import com.gemstone.gemfire.admin.RegionSubRegionSnapshot;
import com.gemstone.gemfire.admin.StatisticResource;
import com.gemstone.gemfire.admin.SystemMember;
import com.gemstone.gemfire.admin.SystemMemberCacheServer;
import com.gemstone.gemfire.admin.jmx.Agent;
import com.gemstone.gemfire.cache.InterestPolicy;
import com.gemstone.gemfire.cache.SubscriptionAttributes;
import com.gemstone.gemfire.distributed.internal.DistributionConfig;
import com.gemstone.gemfire.i18n.LogWriterI18n;
import com.gemstone.gemfire.internal.GemFireVersion;
import com.gemstone.gemfire.internal.admin.remote.ClientHealthStats;
import com.gemstone.gemfire.internal.cache.GatewayEndpointStatus;
import com.gemstone.gemfire.internal.cache.GatewayHubStatus;
import com.gemstone.gemfire.internal.cache.GatewayStatus;
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
/**
* This class uses the JMX Attributes/Operations that use (return/throw)
* GemFire types. This is the single MBean accessible with ObjectName string
* {@link MemberInfoWithStatsMBean#MBEAN_NAME}}. This MBean can be used to
* retrieve the all member details as plain java types.
*
* This MBean also acts as a Notification Hub for all the Notifications that are
* defined for Admin Distributed System.
*
* @author abhishek
*
* @since 6.5
*/
public class MemberInfoWithStatsMBean extends AbstractDynamicMBean
implements NotificationEmitter {
/* constants defining max no of attributes/operations/notifications */
private static final int MAX_ATTRIBUTES_COUNT = 3;
private static final int MAX_OPERATIONS_COUNT = 3;
private static final int MAX_NOTIFICATIONS_COUNT = 9;
private static final String NOT_AVAILABLE_STR = "N/A";
private static final String NOT_AVAILABLE = null;
private static final Number NOT_AVAILABLE_NUMBER = null;
/* String constant used for a region that is used on admin side just as a root
* for rootRegions defined on the member */
private static final String PLACE_HOLDER_ROOT_REGION = "/Root/";
/* String that are used to form QueryExp/ObjectName for querying MBeanServer */
private static final String REGION_QUERY_EXPRESSION = "*GemFire.Cache*:*,owner={0},type=Region";
private static final String STATS_QUERY_EXPRESSION = "*GemFire.Statistic*:*,source={0},name={1}";
/** mbean name string for this MBean */
/*default*/static final String MBEAN_NAME = "GemFire:type=MemberInfoWithStatsMBean";
/** ObjectName handle for this MBean */
private ObjectName objectName;
/** version of the GemFire Enterprise system that is running */
private String version;
private int refreshInterval;
private String id;
private Agent agent;
private AdminDistributedSystemJmxImpl adminDSJmx;
private LogWriterI18n logWriter;
private NotificationForwarder forwarder;
private boolean isInitialized;//needs synchronization?
/**
* Default Constructor
*
* @param agent Admin Agent instance
* @throws OperationsException if ObjectName can't be formed for this MBean
* @throws MBeanRegistrationException
* @throws AdminException
*/
MemberInfoWithStatsMBean(Agent agent) throws OperationsException, MBeanRegistrationException, AdminException {
this.agent = agent;
this.logWriter = this.agent.getLogWriter().convertToLogWriterI18n();
this.objectName = ObjectName.getInstance(MBEAN_NAME);
this.version = GemFireVersion.getGemFireVersion();
this.refreshInterval = -1;
this.id = NOT_AVAILABLE_STR;
this.forwarder = new NotificationForwarder(agent.getMBeanServer(), this.logWriter);
}
/**
* Returns attributes defined for this MBean as an array of
* MBeanAttributeInfo objects.
*
* @return attributes defined as an array of MBeanAttributeInfo objects.
*/
@Override
protected MBeanAttributeInfo[] createMBeanAttributeInfo() {
MBeanAttributeInfo[] attributesInfo = new MBeanAttributeInfo[MAX_ATTRIBUTES_COUNT];
/* First letter in attribute name has to be 'V' so that getVersion is
* called. With 'v' it looks for getversion, same for others */
attributesInfo[0] = new MBeanAttributeInfo("Version",
String.class.getName(),
"GemFire Enterprise Version",
true, /*readable*/
false, /*writable*/
false);/*has getter with name like 'is****'*/
attributesInfo[1] = new MBeanAttributeInfo("RefreshInterval",
String.class.getName(),
"The interval (in seconds) between auto-polling for updating member & statistics resources. If this is '-1', it means the this MBean has not yet been initialized. First call to getMembers operation will initialize this MBean.",
true, /*readable*/
false, /*writable*/
false);/*has getter with name like 'is****'*/
attributesInfo[2] = new MBeanAttributeInfo("Id",
String.class.getName(),
"Identifier of the GemFire Enterprise. If this is 'N/A', it means the this MBean has not yet been initialized. First call to getMembers operation will initialize this MBean.",
true, /*readable*/
false, /*writable*/
false);/*has getter with name like 'is****'*/
return attributesInfo;
}
/**
* Returns operations defined for this MBean as an array of
* MBeanOperationInfo objects.
*
* @return operations defined as an array of MBeanOperationInfo objects.
*/
@Override
protected MBeanOperationInfo[] createMBeanOperationInfo() {
MBeanOperationInfo[] operationsInfo = new MBeanOperationInfo[MAX_OPERATIONS_COUNT];
operationsInfo[0] = new MBeanOperationInfo("getMembers",
"Returns ids as strings for all the members - Application Peers & Cache Servers.",
new MBeanParameterInfo[] {},
String[].class.getName(),
MBeanOperationInfo.ACTION_INFO);
MBeanParameterInfo[] getMemberDetailsArgs = new MBeanParameterInfo[1];
getMemberDetailsArgs[0] = new MBeanParameterInfo("memberId", String.class.getName(), "Id of the member for all the details are to be retrieved.");
operationsInfo[1] = new MBeanOperationInfo("getMemberDetails",
"Returns details for a given member",
getMemberDetailsArgs,
Map.class.getName(),
MBeanOperationInfo.ACTION_INFO);
/* For retrieving ObjectNames of existing Region MBeans, MBeanServerConnection.queryMBeans(), could be called */
MBeanParameterInfo[] getRegionSnapArgs = new MBeanParameterInfo[1];
getRegionSnapArgs[0] = new MBeanParameterInfo("memberId", String.class.getName(), "Id of the member on which we want to discover all the region MBean.");
operationsInfo[2] = new MBeanOperationInfo("getRegions",
"Returns a java.util.Map of details of regions on a member",
getRegionSnapArgs,
Map.class.getName(),
MBeanOperationInfo.ACTION_INFO);
return operationsInfo;
}
/**
* Returns notifications defined for this MBean as an array of
* MBeanNotificationInfo objects.
*
* @return notification definitions as an array of MBeanNotificationInfo
* objects.
*/
@Override
protected MBeanNotificationInfo[] createMBeanNotificationInfo() {
MBeanNotificationInfo[] notificationsInfo = new MBeanNotificationInfo[MAX_NOTIFICATIONS_COUNT];
String[] notificationTypes = new String[] {AdminDistributedSystemJmxImpl.NOTIF_MEMBER_JOINED};
notificationsInfo[0] = new MBeanNotificationInfo(notificationTypes,
Notification.class.getName(),
"A GemFire manager, cache, or other member has joined this distributed system.");
notificationTypes = new String[] {AdminDistributedSystemJmxImpl.NOTIF_MEMBER_LEFT};
notificationsInfo[1] = new MBeanNotificationInfo(notificationTypes,
Notification.class.getName(),
"A GemFire manager, cache, or other member has left the distributed system.");
notificationTypes = new String[] {AdminDistributedSystemJmxImpl.NOTIF_MEMBER_CRASHED};
notificationsInfo[2] = new MBeanNotificationInfo(notificationTypes,
Notification.class.getName(),
"A member of this distributed system has crashed instead of leaving cleanly.");
notificationTypes = new String[] {AdminDistributedSystemJmxImpl.NOTIF_ALERT};
notificationsInfo[3] = new MBeanNotificationInfo(notificationTypes,
Notification.class.getName(),
"A member of this distributed system has generated an alert.");
notificationTypes = new String[] {AdminDistributedSystemJmxImpl.NOTIF_ADMIN_SYSTEM_DISCONNECT};
notificationsInfo[4] = new MBeanNotificationInfo(notificationTypes,
Notification.class.getName(),
"A GemFire manager, cache, or other member has joined this distributed system.");
notificationTypes = new String[] {SystemMemberJmx.NOTIF_CACHE_CREATED};
notificationsInfo[5] = new MBeanNotificationInfo(notificationTypes,
Notification.class.getName(),
"A cache got created on a member of this distributed system.");
notificationTypes = new String[] {SystemMemberJmx.NOTIF_CACHE_CLOSED};
notificationsInfo[6] = new MBeanNotificationInfo(notificationTypes,
Notification.class.getName(),
"A cache is closed on a member of this distributed system.");
notificationTypes = new String[] {SystemMemberJmx.NOTIF_REGION_CREATED};
notificationsInfo[7] = new MBeanNotificationInfo(notificationTypes,
Notification.class.getName(),
"A region is created in a cache on a member of this distributed system.");
notificationTypes = new String[] {SystemMemberJmx.NOTIF_REGION_LOST};
notificationsInfo[8] = new MBeanNotificationInfo(notificationTypes,
Notification.class.getName(),
"A region was removed from a cache on a member of this distributed system.");
// String[] notificationTypes5 = new String[] {AdminDistributedSystemJmxImpl.NOTIF_STAT_ALERT};
// notificationsInfo[9] = new MBeanNotificationInfo(notificationTypes5,
// Notification.class.getName(),
// "An alert based on statistic(s) has been raised.");
return notificationsInfo;
}
/**
*
* @return ObjectName of this MBean
*/
/*default*/ ObjectName getObjectName() {
return objectName;
}
/**
* Returns the version of the GemFire Enterprise instance as a string.
*
* @return GemFire Enterprise version string derived from {@link GemFireVersion}
*/
/* getter for attribute - Version */
public String getVersion() {
return version;
}
/**
* @return the refreshInterval
*/
public int getRefreshInterval() {
return refreshInterval;
}
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* Connects the Admin Agent in the DS
*
* @return AdminDistributedSystem MBean ObjectName
* @throws OperationsException
* if connection to the DS fails
* @throws AdminException
* if connection to the DS fails
*/
private ObjectName connectToSystem() throws OperationsException, AdminException {
ObjectName adminDsObjName = agent.connectToSystem();
AdminDistributedSystem adminDS = agent.getDistributedSystem();
if (adminDSJmx == null && adminDS instanceof AdminDistributedSystemJmxImpl) {//instanceof checks for null
adminDSJmx = (AdminDistributedSystemJmxImpl) adminDS;
refreshInterval = adminDSJmx.getRefreshInterval();
id = adminDSJmx.getId();
forwarder.registerNotificationListener(adminDSJmx.getObjectName());
}
return adminDsObjName;
}
/**
*
* @param memberId
* @return SystemMemberJmx instance for given memberId
* @throws AdminException
*/
private SystemMemberJmx findMember(String memberId) throws AdminException {
SystemMemberJmx foundMember = null;
if (agent.isConnected()) {
SystemMember[] members = adminDSJmx.getSystemMemberApplications();
for (SystemMember app : members) {
if (app.getId().equals(memberId)) {
foundMember = (SystemMemberJmx) app;
break;
}
}
if (foundMember == null) {
members = adminDSJmx.getCacheVms();
for (SystemMember cacheVm : members) {
if (cacheVm.getId().equals(memberId)) {
foundMember = (SystemMemberJmx) cacheVm;
break;
}
}
}
}
return foundMember;
}
/**
* Return ObjectNames for all the Member MBeans in the DS.
*
* @return Array of ObjectNames of all Member MBeans
* @throws OperationsException
* if (1)agent could not connect in the DS OR
* (2)Notification Listener could not be registered for the Admin
* DS MBean OR
* (3)fails to retrieve information from Admin DS
*/
public String[] getMembers() throws OperationsException {
String[] members = new String[0];
try {
if (!isInitialized) {
initializeAll(); //initialize if not yet
}
if (adminDSJmx != null) {
CacheVm[] cacheVms = adminDSJmx.getCacheVms();
SystemMember[] appVms = adminDSJmx.getSystemMemberApplications();
List membersList = new ArrayList();
if (cacheVms != null && cacheVms.length !=0) {
for (SystemMember cacheVm : cacheVms) {
membersList.add(cacheVm.getId());
}
}
if (appVms != null && appVms.length !=0) {
for (SystemMember appVm : appVms) {
membersList.add(appVm.getId());
}
}
members = new String[membersList.size()];
members = membersList.toArray(members);
}
} catch (AdminException e) {
logWriter.warning(LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_FOR_OPERATION_0, "getMembers", e);
throw new OperationsException(e.getMessage());
} catch (Exception e) {
logWriter.warning(LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_FOR_OPERATION_0, "getMembers", e);
throw new OperationsException(e.getMessage());
}
return members;
}
/**
* Returns information including ObjectNames for all regions on a member with
* given member id.
*
* @param memberId
* member identifier as a String
* @return Map of details of all regions on a member with given id
* @throws OperationsException
* if fails to retrieve the regions information
*/
public Map> getRegions(String memberId) throws OperationsException {
Map> regionsInfo = new LinkedHashMap>();
if (memberId != null) {
try {
SystemMemberJmx foundMember = findMember(memberId);
if (foundMember != null) {
SystemMemberCacheJmxImpl cache = (SystemMemberCacheJmxImpl) foundMember.getCache();
if (cache != null) {
Map existingRegionMbeans = getExistingRegionMbeansFullPaths(memberId);
//TODO: this is in-efficient
//Can a region.create JMX notification be used?
regionsInfo = getAllRegionsDetails(cache, existingRegionMbeans);
existingRegionMbeans.clear();
}
}
} catch (AdminException e) {
logWriter.warning(LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_FOR_OPERATION_0_FOR_MEMBER_1, new Object[]{"getRegions", memberId}, e);
throw new OperationsException(e.getMessage());
} catch (Exception e) {
logWriter.warning(LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_FOR_OPERATION_0_FOR_MEMBER_1, new Object[]{"getRegions", memberId}, e);
throw new OperationsException(e.getMessage());
}
}
return regionsInfo;
}
/* **************************************************************************/
/* ************* INITIALIZE THE ENTIRE ADMIN DS AT A TIME *******************/
/* **************************************************************************/
/**
* Initializes all the possible MBeans for all the members.
*
*/
private void initializeAll() throws OperationsException {
try {
connectToSystem();
if (adminDSJmx != null) {
//Members are already inited after connectToSystem. Now init Cache, Region & Stats MBeans
SystemMember[] cacheVms = adminDSJmx.getCacheVms();
for (int i = 0; i < cacheVms.length; i++) {
try {
initializeCacheRegionsAndStats((SystemMemberJmx)cacheVms[i]);
} catch (AdminException e) {
logWriter.info(LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_WHILE_INTIALIZING_0_CONTINUING,
cacheVms[i].getId(), e);
}
}
SystemMember[] appVms = adminDSJmx.getSystemMemberApplications();
for (int i = 0; i < appVms.length; i++) {
try {
initializeCacheRegionsAndStats((SystemMemberJmx)appVms[i]);
} catch (AdminException e) {
logWriter.info(LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_WHILE_INTIALIZING_0_CONTINUING,
appVms[i].getId(), e);
}
}
}
} catch (AdminException e) {
logWriter.warning(LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_WHILE_INTIALIZING, e);
throw new OperationsException(e.getMessage());
} catch (Exception e) {
logWriter.warning(LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_WHILE_INTIALIZING, e);
throw new OperationsException(e.getMessage());
}
isInitialized = true;
}
/**
* Initializes Cache, Regions & Statistics Types MBeans for the given Member.
*
* @param memberJmx
* Member Mbean instance
* @throws OperationsException
* if fails to initialize required MBeans
* @throws AdminException
* if fails to initialize required MBeans
*/
private void initializeCacheRegionsAndStats(SystemMemberJmx memberJmx)
throws OperationsException, AdminException {
if (memberJmx != null) {
SystemMemberCacheJmxImpl cache = (SystemMemberCacheJmxImpl) memberJmx.getCache();
if (cache != null) {
RegionSubRegionSnapshot regionSnapshot = cache.getRegionSnapshot();
initializeRegionSubRegions(cache, regionSnapshot);
}
initStats(memberJmx);
}
}
/**
* Initializes statistics for a member with the given mbean.
*
* @param memberJmx
* Member Mbean instance
* @throws AdminException
* if fails to initialize required statistic MBeans
*/
private void initStats(SystemMemberJmx memberJmx) throws AdminException {
StatisticResource[] statResources = memberJmx.getStats();
for (StatisticResource statResource : statResources) {
statResource.getStatistics();
}
}
/**
* Initializes all regions & its subregions using the Cache MBean and the
* RegionSubRegionSnapshot for this cache MBean.
*
* @param cache
* Cache MBean resource
* @param regionSnapshot
* RegionSubRegionSnapshot instance for the cache
* @throws MalformedObjectNameException
* if fails to initialize the region MBean
* @throws AdminException
* if fails to initialize the region MBean
*/
@SuppressWarnings("rawtypes")
private void initializeRegionSubRegions(SystemMemberCacheJmxImpl cache,
RegionSubRegionSnapshot regionSnapshot)
throws MalformedObjectNameException,
AdminException {
String fullPath = regionSnapshot.getFullPath();
if (!fullPath.equals(PLACE_HOLDER_ROOT_REGION)) {
fullPath = fullPath.substring(PLACE_HOLDER_ROOT_REGION.length()-1);
cache.manageRegion(fullPath);
}
Set subRegionSnapshots = regionSnapshot.getSubRegionSnapshots();
for (Iterator iterator = subRegionSnapshots.iterator(); iterator.hasNext();) {
RegionSubRegionSnapshot subRegion = (RegionSubRegionSnapshot) iterator.next();
try {
initializeRegionSubRegions(cache, subRegion);
} catch (AdminException e) {
logWriter.info(LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_WHILE_INTIALIZING_0_CONTINUING, subRegion.getFullPath(), e);
}
}
}
/* **************************************************************************/
/* ********************** EVERYTHING HYPERIC NEEDS **************************/
/* **************************************************************************/
/* constants defined that could be used simply retrieve needed info from Map */
private static final String TYPE_NAME_CACHESERVER = "Cache Server";
private static final String TYPE_NAME_APPLICATION = "Application Peer";
private static final String TYPE_NAME_GATEWAYHUB = "Gateway Hub";
/*
* NOTE -
* (My Understanding about the followings - abhishek)
* 1. CacheVM - a VM started using Cache Server Launcher. This is considered
* to be a dedicated cache VM because there is only GemFire Cache code
* running here.
* 2. ApplicationVM - a VM started with a written code using APIs and we can
* not guarantee that there will be ONLY GemFire code running in this VM.
* 3. Cache Server - Responsible for serving requests from the clients. There
* could be multiple of these per Cache and hence per VM - one of 1 or 2 above.
* These could be specified by (or deprecated )
* element(s) in the cache-xml file or using an API Cache.addCacheServer().
*/
// private static final String VERSION = "gemfire.version.string";
// private static final String MEMBER_COUNT = "gemfire.membercount.int";
// private static final String GATEWAYHUB_COUNT = "gemfire.gatewayhubcount.int";
// private static final String CLIENT_COUNT = "gemfire.clientcount.int";
private static final String MEMBER_ID = "gemfire.member.id.string";
private static final String MEMBER_NAME = "gemfire.member.name.string";
private static final String MEMBER_HOST = "gemfire.member.host.string";
private static final String MEMBER_PORT = "gemfire.member.port.int";
private static final String MEMBER_UPTIME = "gemfire.member.uptime.long";
private static final String MEMBER_CLIENTS = "gemfire.member.clients.map";
private static final String MEMBER_REGIONS = "gemfire.member.regions.map";
private static final String MEMBER_TYPE = "gemfire.member.type.string";
private static final String IS_SERVER = "gemfire.member.isserver.boolean";
private static final String IS_GATEWAY = "gemfire.member.isgateway.boolean";
private static final String MEMBER_STATSAMPLING_ENABLED = "gemfire.member.config.statsamplingenabled.boolean";
private static final String MEMBER_TIME_STATS_ENABLED = "gemfire.member.config.timestatsenabled.boolean";
private static final String GATEWAYHUB_ID = "gemfire.member.gatewayhub.id.string";
private static final String GATEWAYHUB_ISPRIMARY = "gemfire.member.gatewayhub.isprimary.boolean";
private static final String GATEWAYHUB_LISTENINGPORT = "gemfire.member.gatewayhub.listeningport.int";
private static final String GATEWAYHUB_GATEWAYS = "gemfire.member.gatewayhub.gateways.collection";
private static final String GATEWAY_ID = "gemfire.member.gateway.id.string";
private static final String GATEWAY_QUEUESIZE = "gemfire.member.gateway.queuesize.int";
private static final String GATEWAY_ISCONNECTED = "gemfire.member.gateway.isconnected.boolean";
private static final String GATEWAY_ENDPOINTS = "gemfire.member.gateway.endpoints.collection";
private static final String GATEWAYENDPOINT_ID = "gemfire.member.gateway.endpoint.id.string";
private static final String GATEWAYENDPOINT_HOST = "gemfire.member.gateway.endpoint.host.string";
private static final String GATEWAYENDPOINT_PORT = "gemfire.member.gateway.endpoint.port.int";
private static final String STATS_PROCESSCPUTIME = "gemfire.member.stat.processcputime.long";
private static final String STATS_CPUS = "gemfire.member.stat.cpus.int";
private static final String STATS_USEDMEMORY = "gemfire.member.stat.usedmemory.long";
private static final String STATS_MAXMEMORY = "gemfire.member.stat.maxmemory.long";
private static final String STATS_GETS = "gemfire.member.stat.gets.int";
private static final String STATS_GETTIME = "gemfire.member.stat.gettime.long";
private static final String STATS_PUTS = "gemfire.member.stat.puts.int";
private static final String STATS_PUTTIME = "gemfire.member.stat.puttime.long";
private static final String REGION_NAME = "gemfire.region.name.string";
private static final String REGION_PATH = "gemfire.region.path.string";
private static final String REGION_SCOPE = "gemfire.region.scope.string";
private static final String REGION_DATAPOLICY = "gemfire.region.datapolicy.string";
private static final String REGION_INTERESTPOLICY = "gemfire.region.interestpolicy.string";
private static final String REGION_ENTRYCOUNT = "gemfire.region.entrycount.int";
private static final String REGION_DISKATTRS = "gemfire.region.diskattrs.string";
private static final String CLIENT_ID = "gemfire.client.id.string";
private static final String CLIENT_NAME = "gemfire.client.name.string";
private static final String CLIENT_HOST = "gemfire.client.host.string";
private static final String CLIENT_QUEUESIZE = "gemfire.client.queuesize.int";
private static final String CLIENT_STATS_GETS = "gemfire.client.stats.gets.int";
private static final String CLIENT_STATS_PUTS = "gemfire.client.stats.puts.int";
private static final String CLIENT_STATS_CACHEMISSES = "gemfire.client.stats.cachemisses.int";
private static final String CLIENT_STATS_CPUUSAGE = "gemfire.client.stats.cpuusage.long";
private static final String CLIENT_STATS_CPUS = "gemfire.client.stats.cpus.int";
private static final String CLIENT_STATS_UPDATETIME = "gemfire.client.stats.updatetime.long";
private static final String CLIENT_STATS_THREADS = "gemfire.client.stats.threads.int";
/**
*
* @param memberId
* @return All the required details for a member with given memberId
* @throws OperationsException
*/
public Map getMemberDetails(String memberId)
throws OperationsException {
Map allDetails = new TreeMap();
if (memberId != null) {
try {
SystemMemberJmx member = findMember(memberId);
if (member != null) {
SystemMemberCacheJmxImpl cache = (SystemMemberCacheJmxImpl) member.getCache();
GemFireMemberStatus snapshot = cache.getSnapshot();
boolean isServer = snapshot.getIsServer();
boolean isGatewayHub = snapshot.getIsGatewayHub();
//1. Member info
allDetails.put(MEMBER_ID, member.getId());
allDetails.put(MEMBER_NAME, member.getName());
String host = member.getHost();//from of GemFireVM.getHost
InetAddress hostAddr = member.getHostAddress();
//possibility of null host address
if (hostAddr != null) {
host = hostAddr.getHostName();
}
allDetails.put(MEMBER_HOST, host);
allDetails.put(MEMBER_UPTIME, snapshot.getUpTime());
allDetails.put(IS_SERVER, isServer);
allDetails.put(IS_GATEWAY, isGatewayHub);
String memberType = "";
if (isGatewayHub) {
memberType = TYPE_NAME_GATEWAYHUB;
} else if (member instanceof CacheServerJmxImpl) {
memberType = TYPE_NAME_CACHESERVER;
} else {//Mark it of Application type if neither a gateway hub nor a server
memberType = TYPE_NAME_APPLICATION;
}
// if (isGatewayHub) {
// memberType = TYPE_NAME_GATEWAYHUB;
// } else if (isServer) {
// memberType = TYPE_NAME_CACHESERVER;
// } else {//Mark it of Application type if neither a gateway nor a server
// memberType = TYPE_NAME_APPLICATION;
// }
allDetails.put(MEMBER_TYPE, memberType);
//2. Region info
Map existingRegionMbeans = getExistingRegionMbeansFullPaths(memberId);
allDetails.put(MEMBER_REGIONS, getAllRegionsDetails(cache, existingRegionMbeans));
existingRegionMbeans.clear();
//3. Clients info
allDetails.put(MEMBER_CLIENTS, getClientDetails(snapshot));
//4. GatewayHub info
if (isGatewayHub) {
GatewayHubStatus hubStatus = (GatewayHubStatus) snapshot.getGatewayHubStatus();
allDetails.putAll(getAllGatewayDetails(hubStatus));
}
boolean statSamplingEnabled = true;
//assuming will never return as per current implementation
ConfigurationParameter[] configParams = member.getConfiguration();
for (ConfigurationParameter configParam : configParams) {
if (DistributionConfig.STATISTIC_SAMPLING_ENABLED_NAME.equals(configParam.getName())) {
allDetails.put(MEMBER_STATSAMPLING_ENABLED, configParam.getValue());
statSamplingEnabled = Boolean.parseBoolean(""+configParam.getValue());
} else if (DistributionConfig.ENABLE_TIME_STATISTICS_NAME.equals(configParam.getName())) {
allDetails.put(MEMBER_TIME_STATS_ENABLED, configParam.getValue());
}
}
//5. Stats info
allDetails.putAll(getRequiredStats(member, statSamplingEnabled));
SystemMemberCacheServer[] cacheServers = cache.getCacheServers();
//attempt refreshing the cache info once
if (cacheServers.length == 0) {
cache.refresh();
cacheServers = cache.getCacheServers();
}
Integer memberCacheServerPort = Integer.valueOf(0);
if (cacheServers.length != 0) {
/*
* Taking the first cache server port.
* We don't recommend multiple cache severs for a cache.
*/
memberCacheServerPort = Integer.valueOf(cacheServers[0].getPort());
}
allDetails.put(MEMBER_PORT, memberCacheServerPort);
}
} catch (AdminException e) {
logWriter.warning(LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_FOR_OPERATION_0_FOR_MEMBER_1,
new Object[] {"getMemberDetails", memberId}, e);
throw new OperationsException(e.getMessage());
} catch (Exception e) {
logWriter.warning(LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_FOR_OPERATION_0_FOR_MEMBER_1,
new Object[] {"getMemberDetails", memberId}, e);
throw new OperationsException(e.getMessage());
}
}
return allDetails;
}
/**
*
* @param snapshot
* @return Map of client details
*/
@SuppressWarnings("rawtypes")
private Map> getClientDetails(GemFireMemberStatus snapshot) {
Map> clientsInfo =
new LinkedHashMap>();
Set connectedClients = snapshot.getConnectedClients();
if (!connectedClients.isEmpty()) {
Map clientHealthStatsMap = snapshot.getClientHealthStats();
for (Iterator iterator = connectedClients.iterator(); iterator.hasNext();) {
Map clientData = new HashMap();
String clientId = (String) iterator.next();
String host = snapshot.getClientHostName(clientId);
clientData.put(CLIENT_ID, clientId);
clientData.put(CLIENT_NAME, extractClientName(clientId, host));
clientData.put(CLIENT_HOST, host);
clientData.put(CLIENT_QUEUESIZE, snapshot.getClientQueueSize(clientId));
ClientHealthStats clientHealthStats = (ClientHealthStats) clientHealthStatsMap.get(clientId);
if (clientHealthStats != null) {
clientData.put(CLIENT_STATS_GETS, clientHealthStats.getNumOfGets());
clientData.put(CLIENT_STATS_PUTS, clientHealthStats.getNumOfPuts());
clientData.put(CLIENT_STATS_CACHEMISSES, clientHealthStats.getNumOfMisses());
clientData.put(CLIENT_STATS_CPUUSAGE, clientHealthStats.getProcessCpuTime());
clientData.put(CLIENT_STATS_CPUS, clientHealthStats.getCpus());
clientData.put(CLIENT_STATS_UPDATETIME, clientHealthStats.getUpdateTime().getTime());
clientData.put(CLIENT_STATS_THREADS, clientHealthStats.getNumOfThreads());
} else {
clientData.put(CLIENT_STATS_GETS, Integer.valueOf(0));
clientData.put(CLIENT_STATS_PUTS, Integer.valueOf(0));
clientData.put(CLIENT_STATS_CACHEMISSES, Integer.valueOf(0));
clientData.put(CLIENT_STATS_CPUUSAGE, Long.valueOf(0));
clientData.put(CLIENT_STATS_CPUS, Integer.valueOf(0));
clientData.put(CLIENT_STATS_UPDATETIME, Long.valueOf(0));
clientData.put(CLIENT_STATS_THREADS, Integer.valueOf(0));
}
clientsInfo.put(clientId, clientData);
}
}
return clientsInfo;
}
/**
* Returns a Map containing information about regions.
*
* @param cache
* Reference to an MBean representing a Cache on a member
* @param existingRegionMbeans
* Map of Path against Region MBean ObjectNames
* @return Map of all region details
* @throws OperationsException
* if fails to retrieve
*/
private Map> getAllRegionsDetails(
SystemMemberCacheJmxImpl cache,
Map existingRegionMbeans)
throws OperationsException {
Map> regionsInfo =
new TreeMap>();
if (cache != null) {
try {
RegionSubRegionSnapshot regionSnapshot = cache.getRegionSnapshot();
collectAllRegionsDetails(cache, regionSnapshot, regionsInfo, existingRegionMbeans);
} catch (AdminException e) {
logWriter.warning(LocalizedStrings.ONE_ARG, "Exception occurred while getting region details.", e);
throw new OperationsException(e.getMessage());
} catch (Exception e) {
logWriter.warning(LocalizedStrings.ONE_ARG, "Exception occurred while getting region details.", e);
throw new OperationsException(e.getMessage());
}
}
return regionsInfo;
}
/**
* Collects all the region details from the RegionSubRegionSnapshot instance
* passed and the Cache MBean. Checks in the set of existingRegionMbeans
* before initializing Region Mbeans if there are not initialized yet.
*
* @param cache
* Cache MBean instance
* @param regionSnapshot
* RegionSubRegionSnapshot instance
* @param regionsInfo
* Map of regions information that gets populated recursively
* @param existingRegionMbeans
* Map of ObjectNames of existing region MBeans
* @throws AdminException
* if unable to initialize region MBean
* @throws OperationsException
* if fails to retrieve the Region MBean attribute info
* @throws MBeanException
* if fails to retrieve the Region MBean attribute info
* @throws ReflectionException
* if fails to retrieve the Region MBean attribute info
*/
@SuppressWarnings("rawtypes")
private void collectAllRegionsDetails(SystemMemberCacheJmxImpl cache,
RegionSubRegionSnapshot regionSnapshot,
Map> regionsInfo,
Map existingRegionMbeans)
throws AdminException, OperationsException,
MBeanException, ReflectionException {
String fullPath = regionSnapshot.getFullPath();
if (!fullPath.equals(PLACE_HOLDER_ROOT_REGION)) {
fullPath = fullPath.substring(PLACE_HOLDER_ROOT_REGION.length()-1);
String name = regionSnapshot.getName();
Integer entryCount = Integer.valueOf(regionSnapshot.getEntryCount());
Map details = new TreeMap();
details.put(REGION_NAME, name);
details.put(REGION_PATH, fullPath);
details.put(REGION_ENTRYCOUNT, entryCount);
ObjectName regionObjectName = existingRegionMbeans.get(fullPath);
if (regionObjectName == null) {//initialize if has not yet been
regionObjectName = cache.manageRegion(fullPath);
}
Object attribute = getAttribute(regionObjectName, "scope", NOT_AVAILABLE);
attribute = attribute != null ? attribute.toString() : attribute;
details.put(REGION_SCOPE, attribute);
attribute = getAttribute(regionObjectName, "dataPolicy", NOT_AVAILABLE);
attribute = attribute != null ? attribute.toString() : attribute;
details.put(REGION_DATAPOLICY, attribute);
SubscriptionAttributes interestPolicyAttr =
(SubscriptionAttributes) getAttribute(regionObjectName,
"subscriptionAttributes", null);
String interestPolicyStr = NOT_AVAILABLE;
if (interestPolicyAttr != null) {
InterestPolicy interestPolicy = interestPolicyAttr.getInterestPolicy();
if (interestPolicy != null) {
interestPolicyStr = interestPolicy.toString();
}
}
details.put(REGION_INTERESTPOLICY, interestPolicyStr);
attribute = getAttribute(regionObjectName, "diskWriteAttributes", NOT_AVAILABLE);
attribute = attribute != null ? attribute.toString() : attribute;
details.put(REGION_DISKATTRS, attribute);
regionsInfo.put(fullPath, details);
}
Set subRegionSnapshots = regionSnapshot.getSubRegionSnapshots();
for (Iterator iterator = subRegionSnapshots.iterator(); iterator.hasNext();) {
RegionSubRegionSnapshot subRegion = (RegionSubRegionSnapshot) iterator.next();
collectAllRegionsDetails(cache, subRegion, regionsInfo, existingRegionMbeans);
}
}
/**
* Checks if the given host name string contains ':' as in IPv6 host address.
*
* @param host
* host name string
* @return true if the host string contains ':', false otherwise
*/
private static boolean isIPv6(String host) {
return host.contains(":");
}
/**
* Checks if the given host name is actually a String representation of an
* IPv4 address.
*
* @param host
* host name string
* @return true if given host name is a String representation of an IPv4
* address, false otherwise
*/
private static boolean isIPv4(String host) {
String regex = "\\d{1,3}.\\d{1,3}.\\d{1,3}.\\d{1,3}";
return host.matches(regex);
}
/**
* Excludes the host name from the client id and returns the String. If the
* host name can not be detected, returns an empty string. Typically, the
* client id looks like: HOST(VM_PID:VM_KIND):PORT:RANDOM_STRING:CLIENT_NAME
*
* Extracts the client name from the client id. If the client id is not in the
* expected format, returns 'N/A'
*
* @param clientId
* string identifier for a client
* @param host
* host name (FQDN) the client is running on
* @return name extracted from given client id
*/
/*
* Some examples of Client Id format:
* (1) Java Client:
* nase(21716:loner):51789:42e9a0bf:client_nase_21716
* nase(2560:loner):2:7a84729a:Feeder
*
* (2) Native Client:
* nase(21045:loner):2:GFNative_OnNnEpyRWL:ExampleDistributedSystem
*
* (3) IPv6 Host whose name can not be resolved:
* fdf0:76cf:a0ed:9449:0:0:0:1001(21716:loner):51789:42e9a0b:client_nase_21716
* fdf0:76cf:a0ed:9449:0:0:0:1001:51789:42e9a0b:client_nase_21716
*/
private static String extractClientName(String clientId, String host) {
/* This isIPv6, isIPv4, extractClientName is taken from GFMon code base*/
String hostExcludedId = "";
if ( (isIPv6(host) || isIPv4(host))&& clientId.startsWith(host)) {
hostExcludedId = clientId.substring(host.length());
} else {
int firstDotIndex = host.indexOf(".");
if (firstDotIndex != -1) {
String hostShortName = host.substring(0, firstDotIndex);
hostExcludedId = clientId.substring(hostShortName.length());
}
}
String vmPIDAndKindRegex = "\\(\\w+:\\w+\\)";
String regex = "(\\)?:[0-9]+(:\\w+){2}+";
String name = NOT_AVAILABLE;
String temp = hostExcludedId;
int openIndex = temp.indexOf("(");
if (openIndex != -1) {
regex = vmPIDAndKindRegex + regex;
}
if (temp.matches(regex)) {
String[] splitted = temp.split(":");
name = splitted[splitted.length - 1];
}
return name;
}
/**
* Returns all the gateway hub details from the given GatewayHubStatus
*
* @param gatewayHubStatus GatewayHubStatus instance
* @return Map of gateway hub details
*/
private Map getAllGatewayDetails(
GatewayHubStatus gatewayHubStatus){
Map hubDetails = new TreeMap();
if (gatewayHubStatus != null) {
hubDetails.put(GATEWAYHUB_ID, gatewayHubStatus.getId());
hubDetails.put(GATEWAYHUB_ISPRIMARY, gatewayHubStatus.getIsPrimary());
hubDetails.put(GATEWAYHUB_LISTENINGPORT, gatewayHubStatus.getPort());
GatewayStatus[] gatewayStatuses = gatewayHubStatus.getGatewayStatuses();
List