/* * 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.admin.jmx.internal; import static org.apache.geode.distributed.ConfigurationProperties.*; import org.apache.geode.admin.*; import org.apache.geode.admin.jmx.Agent; import org.apache.geode.cache.InterestPolicy; import org.apache.geode.cache.SubscriptionAttributes; import org.apache.geode.distributed.internal.DistributionConfig; import org.apache.geode.internal.GemFireVersion; import org.apache.geode.internal.admin.remote.ClientHealthStats; import org.apache.geode.internal.i18n.LocalizedStrings; import org.apache.geode.internal.logging.LogService; import org.apache.geode.internal.logging.log4j.LocalizedMessage; import mx4j.AbstractDynamicMBean; import org.apache.logging.log4j.Logger; import javax.management.*; import java.net.InetAddress; import java.text.MessageFormat; import java.util.*; import java.util.concurrent.atomic.AtomicLong; /** * 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. * * * @since GemFire 6.5 */ public class MemberInfoWithStatsMBean extends AbstractDynamicMBean implements NotificationEmitter { private static final Logger logger = LogService.getLogger(); /* 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 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.objectName = ObjectName.getInstance(MBEAN_NAME); this.version = GemFireVersion.getGemFireVersion(); this.refreshInterval = -1; this.id = NOT_AVAILABLE_STR; this.forwarder = new NotificationForwarder(agent.getMBeanServer()); } /** * 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<String> membersList = new ArrayList<String>(); 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) { logger.warn( LocalizedMessage.create( LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_FOR_OPERATION_0, "getMembers"), e); throw new OperationsException(e.getMessage()); } catch (Exception e) { logger.warn( LocalizedMessage.create( 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<String, Map<String, ?>> getRegions(String memberId) throws OperationsException { Map<String, Map<String, ?>> regionsInfo = new LinkedHashMap<String, Map<String, ?>>(); if (memberId != null) { try { SystemMemberJmx foundMember = findMember(memberId); if (foundMember != null) { SystemMemberCacheJmxImpl cache = (SystemMemberCacheJmxImpl) foundMember.getCache(); if (cache != null) { Map<String, ObjectName> 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) { logger.warn(LocalizedMessage.create( LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_FOR_OPERATION_0_FOR_MEMBER_1, new Object[] {"getRegions", memberId}), e); throw new OperationsException(e.getMessage()); } catch (Exception e) { logger.warn(LocalizedMessage.create( 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) { logger.info(LocalizedMessage.create( 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) { logger.info(LocalizedMessage.create( LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_WHILE_INTIALIZING_0_CONTINUING, appVms[i].getId()), e); } } } } catch (AdminException e) { logger.warn(LocalizedMessage .create(LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_WHILE_INTIALIZING), e); throw new OperationsException(e.getMessage()); } catch (Exception e) { logger.warn(LocalizedMessage .create(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) { logger.info(LocalizedMessage.create( 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"; /* * 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 <cache-server> (or * deprecated <bridge-server>) 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 = DistributionConfig.GEMFIRE_PREFIX + "member.id.string"; private static final String MEMBER_NAME = DistributionConfig.GEMFIRE_PREFIX + "member.name.string"; private static final String MEMBER_HOST = DistributionConfig.GEMFIRE_PREFIX + "member.host.string"; private static final String MEMBER_PORT = DistributionConfig.GEMFIRE_PREFIX + "member.port.int"; private static final String MEMBER_UPTIME = DistributionConfig.GEMFIRE_PREFIX + "member.uptime.long"; private static final String MEMBER_CLIENTS = DistributionConfig.GEMFIRE_PREFIX + "member.clients.map"; private static final String MEMBER_REGIONS = DistributionConfig.GEMFIRE_PREFIX + "member.regions.map"; private static final String MEMBER_TYPE = DistributionConfig.GEMFIRE_PREFIX + "member.type.string"; private static final String IS_SERVER = DistributionConfig.GEMFIRE_PREFIX + "member.isserver.boolean"; private static final String IS_GATEWAY = DistributionConfig.GEMFIRE_PREFIX + "member.isgateway.boolean"; private static final String MEMBER_STATSAMPLING_ENABLED = DistributionConfig.GEMFIRE_PREFIX + "member.config.statsamplingenabled.boolean"; private static final String MEMBER_TIME_STATS_ENABLED = DistributionConfig.GEMFIRE_PREFIX + "member.config.timestatsenabled.boolean"; private static final String STATS_PROCESSCPUTIME = DistributionConfig.GEMFIRE_PREFIX + "member.stat.processcputime.long"; private static final String STATS_CPUS = DistributionConfig.GEMFIRE_PREFIX + "member.stat.cpus.int"; private static final String STATS_USEDMEMORY = DistributionConfig.GEMFIRE_PREFIX + "member.stat.usedmemory.long"; private static final String STATS_MAXMEMORY = DistributionConfig.GEMFIRE_PREFIX + "member.stat.maxmemory.long"; private static final String STATS_GETS = DistributionConfig.GEMFIRE_PREFIX + "member.stat.gets.int"; private static final String STATS_GETTIME = DistributionConfig.GEMFIRE_PREFIX + "member.stat.gettime.long"; private static final String STATS_PUTS = DistributionConfig.GEMFIRE_PREFIX + "member.stat.puts.int"; private static final String STATS_PUTTIME = DistributionConfig.GEMFIRE_PREFIX + "member.stat.puttime.long"; private static final String REGION_NAME = DistributionConfig.GEMFIRE_PREFIX + "region.name.string"; private static final String REGION_PATH = DistributionConfig.GEMFIRE_PREFIX + "region.path.string"; private static final String REGION_SCOPE = DistributionConfig.GEMFIRE_PREFIX + "region.scope.string"; private static final String REGION_DATAPOLICY = DistributionConfig.GEMFIRE_PREFIX + "region.datapolicy.string"; private static final String REGION_INTERESTPOLICY = DistributionConfig.GEMFIRE_PREFIX + "region.interestpolicy.string"; private static final String REGION_ENTRYCOUNT = DistributionConfig.GEMFIRE_PREFIX + "region.entrycount.int"; private static final String REGION_DISKATTRS = DistributionConfig.GEMFIRE_PREFIX + "region.diskattrs.string"; private static final String CLIENT_ID = DistributionConfig.GEMFIRE_PREFIX + "client.id.string"; private static final String CLIENT_NAME = DistributionConfig.GEMFIRE_PREFIX + "client.name.string"; private static final String CLIENT_HOST = DistributionConfig.GEMFIRE_PREFIX + "client.host.string"; private static final String CLIENT_QUEUESIZE = DistributionConfig.GEMFIRE_PREFIX + "client.queuesize.int"; private static final String CLIENT_STATS_GETS = DistributionConfig.GEMFIRE_PREFIX + "client.stats.gets.int"; private static final String CLIENT_STATS_PUTS = DistributionConfig.GEMFIRE_PREFIX + "client.stats.puts.int"; private static final String CLIENT_STATS_CACHEMISSES = DistributionConfig.GEMFIRE_PREFIX + "client.stats.cachemisses.int"; private static final String CLIENT_STATS_CPUUSAGE = DistributionConfig.GEMFIRE_PREFIX + "client.stats.cpuusage.long"; private static final String CLIENT_STATS_CPUS = DistributionConfig.GEMFIRE_PREFIX + "client.stats.cpus.int"; private static final String CLIENT_STATS_UPDATETIME = DistributionConfig.GEMFIRE_PREFIX + "client.stats.updatetime.long"; private static final String CLIENT_STATS_THREADS = DistributionConfig.GEMFIRE_PREFIX + "client.stats.threads.int"; /** * * @param memberId * @return All the required details for a member with given memberId * @throws OperationsException */ public Map<String, Object> getMemberDetails(String memberId) throws OperationsException { Map<String, Object> allDetails = new TreeMap<String, Object>(); 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 (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<String, ObjectName> existingRegionMbeans = getExistingRegionMbeansFullPaths(memberId); allDetails.put(MEMBER_REGIONS, getAllRegionsDetails(cache, existingRegionMbeans)); existingRegionMbeans.clear(); // 3. Clients info allDetails.put(MEMBER_CLIENTS, getClientDetails(snapshot)); boolean statSamplingEnabled = true; // assuming will never return as per current implementation ConfigurationParameter[] configParams = member.getConfiguration(); for (ConfigurationParameter configParam : configParams) { if (STATISTIC_SAMPLING_ENABLED.equals(configParam.getName())) { allDetails.put(MEMBER_STATSAMPLING_ENABLED, configParam.getValue()); statSamplingEnabled = Boolean.parseBoolean("" + configParam.getValue()); } else if (ENABLE_TIME_STATISTICS.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) { logger.warn(LocalizedMessage.create( LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_FOR_OPERATION_0_FOR_MEMBER_1, new Object[] {"getMemberDetails", memberId}), e); throw new OperationsException(e.getMessage()); } catch (Exception e) { logger.warn(LocalizedMessage.create( 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<String, Map<String, ?>> getClientDetails(GemFireMemberStatus snapshot) { Map<String, Map<String, ?>> clientsInfo = new LinkedHashMap<String, Map<String, ?>>(); Set connectedClients = snapshot.getConnectedClients(); if (!connectedClients.isEmpty()) { Map clientHealthStatsMap = snapshot.getClientHealthStats(); for (Iterator iterator = connectedClients.iterator(); iterator.hasNext();) { Map<String, Object> clientData = new HashMap<String, Object>(); 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<String, Map<String, ?>> getAllRegionsDetails(SystemMemberCacheJmxImpl cache, Map<String, ObjectName> existingRegionMbeans) throws OperationsException { Map<String, Map<String, ?>> regionsInfo = new TreeMap<String, Map<String, ?>>(); if (cache != null) { try { RegionSubRegionSnapshot regionSnapshot = cache.getRegionSnapshot(); collectAllRegionsDetails(cache, regionSnapshot, regionsInfo, existingRegionMbeans); } catch (AdminException e) { logger.warn(LocalizedMessage.create(LocalizedStrings.ONE_ARG, "Exception occurred while getting region details."), e); throw new OperationsException(e.getMessage()); } catch (Exception e) { logger.warn(LocalizedMessage.create(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<String, Map<String, ?>> regionsInfo, Map<String, ObjectName> 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<String, Object> details = new TreeMap<String, Object>(); 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 = "(\\<ec\\>)?:[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 a Map of all the statistics required for Hyperic currently. It relies on the attribute * of the StatisticsResource Mbeans. * * @param member instance for which the stats are needed * @return Map of all the statistics required for Hyperic currently. * @throws OperationsException exceptions thrown while retrieving the attributes */ private Map<String, Object> getRequiredStats(SystemMemberJmx member, boolean statSamplingEnabled) throws OperationsException { Map<String, Object> statDetails = new TreeMap<String, Object>(); try { if (!statSamplingEnabled) { statDetails.put(STATS_PROCESSCPUTIME, NOT_AVAILABLE_NUMBER); statDetails.put(STATS_CPUS, NOT_AVAILABLE_NUMBER); statDetails.put(STATS_MAXMEMORY, NOT_AVAILABLE_NUMBER); statDetails.put(STATS_USEDMEMORY, NOT_AVAILABLE_NUMBER); statDetails.put(STATS_GETS, NOT_AVAILABLE_NUMBER); statDetails.put(STATS_GETTIME, NOT_AVAILABLE_NUMBER); statDetails.put(STATS_PUTS, NOT_AVAILABLE_NUMBER); statDetails.put(STATS_PUTTIME, NOT_AVAILABLE_NUMBER); } else { MBeanServer mBeanServer = agent.getMBeanServer(); Number defaultVal = NOT_AVAILABLE_NUMBER; Number processCpuTime = defaultVal; Number cpus = defaultVal; Number maxMemory = defaultVal; Number usedMemory = defaultVal; Number gets = defaultVal; Number getTime = defaultVal; Number puts = defaultVal; Number putTime = defaultVal; ObjectName[] vmMemoryUsageStats = getExistingStats(member.getId(), "vmHeapMemoryStats"); ObjectName[] vmStats = getExistingStats(member.getId(), "vmStats"); ObjectName[] cachePerfStats = getExistingStats(member.getId(), "cachePerfStats"); boolean needToReinit = false; if (vmMemoryUsageStats.length == 0 || vmStats.length == 0 || cachePerfStats.length == 0) { // if the StatisticResource MBeans are not created needToReinit = true; } if (!needToReinit) { /* * To handle a case when the StatisticResource MBeans are created but not registered with * RefreshTimer. If VMMemoryUsageStats are present, maxMemory should always be non-zero. */ for (int i = 0; i < vmMemoryUsageStats.length; i++) {// ideally there should be a single // instance String type = (String) mBeanServer.getAttribute(vmMemoryUsageStats[i], "type"); if ("VMMemoryUsageStats".equals(type)) { // first instance that has Statistics Type name maxMemory = (Number) getAttribute(vmMemoryUsageStats[i], "maxMemory", defaultVal); break; } } needToReinit = 0 == maxMemory.longValue(); } if (needToReinit) { logger.info(LocalizedMessage.create( LocalizedStrings.MemberInfoWithStatsMBean_REINITIALIZING_STATS_FOR_0, member.getId())); initStats(member); vmMemoryUsageStats = getExistingStats(member.getId(), "vmHeapMemoryStats"); vmStats = getExistingStats(member.getId(), "vmStats"); cachePerfStats = getExistingStats(member.getId(), "cachePerfStats"); } for (int i = 0; i < vmMemoryUsageStats.length; i++) {// ideally there should be a single // instance String type = (String) mBeanServer.getAttribute(vmMemoryUsageStats[i], "type"); if ("VMMemoryUsageStats".equals(type)) { // first instance that has Statistics Type name maxMemory = (Number) getAttribute(vmMemoryUsageStats[i], "maxMemory", defaultVal); usedMemory = (Number) getAttribute(vmMemoryUsageStats[i], "usedMemory", defaultVal); break; } } for (int i = 0; i < vmStats.length; i++) {// ideally there should be a single instance String type = (String) mBeanServer.getAttribute(vmStats[i], "type"); if ("VMStats".equals(type)) { // first instance that has Statistics Type name processCpuTime = (Number) getAttribute(vmStats[i], "processCpuTime", defaultVal); cpus = (Number) getAttribute(vmStats[i], "cpus", defaultVal); break; } } for (int i = 0; i < cachePerfStats.length; i++) {// ideally there should be a single // instance String type = (String) mBeanServer.getAttribute(cachePerfStats[i], "type"); if ("CachePerfStats".equals(type)) { // first instance that has Statistics Type name gets = (Number) getAttribute(cachePerfStats[i], "gets", defaultVal); getTime = (Number) getAttribute(cachePerfStats[i], "getTime", defaultVal); puts = (Number) getAttribute(cachePerfStats[i], "puts", defaultVal); putTime = (Number) getAttribute(cachePerfStats[i], "putTime", defaultVal); break; } } statDetails.put(STATS_PROCESSCPUTIME, processCpuTime == NOT_AVAILABLE_NUMBER ? NOT_AVAILABLE_NUMBER : processCpuTime.longValue()); statDetails.put(STATS_CPUS, cpus == NOT_AVAILABLE_NUMBER ? NOT_AVAILABLE_NUMBER : cpus.intValue()); statDetails.put(STATS_MAXMEMORY, maxMemory == NOT_AVAILABLE_NUMBER ? NOT_AVAILABLE_NUMBER : maxMemory.longValue()); statDetails.put(STATS_USEDMEMORY, usedMemory == NOT_AVAILABLE_NUMBER ? NOT_AVAILABLE_NUMBER : usedMemory.longValue()); statDetails.put(STATS_GETS, gets == NOT_AVAILABLE_NUMBER ? NOT_AVAILABLE_NUMBER : gets.intValue()); statDetails.put(STATS_GETTIME, getTime == NOT_AVAILABLE_NUMBER ? NOT_AVAILABLE_NUMBER : getTime.intValue()); statDetails.put(STATS_PUTS, puts == NOT_AVAILABLE_NUMBER ? NOT_AVAILABLE_NUMBER : puts.intValue()); statDetails.put(STATS_PUTTIME, putTime == NOT_AVAILABLE_NUMBER ? NOT_AVAILABLE_NUMBER : putTime.longValue()); } } catch (Exception e) { logger.warn(e.getMessage(), e); throw new OperationsException(e.getMessage()); } return statDetails; } /** * Returns attribute with given attribute name on MBean with given ObjectName. * * * @param objectName ObjectName for the MBean * @param attribute attribute name * @param unavailableValue return this value if the attribute value is null * @return value of attribute with given attribute name * @throws OperationsException if attribute is not found for MBean with this ObjectName or MBean * instance is not found * @throws MBeanException if MBeans getter throws exception * @throws ReflectionException thrown when trying to invoke the setter. */ private Object getAttribute(ObjectName objectName, String attribute, Object unavailableValue) throws OperationsException, MBeanException, ReflectionException { /* NOTE: callers methods rely on non-null value being returned */ Object value = null; MBeanServer mBeanServer = agent.getMBeanServer(); value = mBeanServer.getAttribute(objectName, attribute); value = (value != null) ? value : unavailableValue; return value; } /** * Return Map of region full against the ObjectName of existing region MBeans. * * @param memberId string identifier of a member * @return Map of region path vs ObjectName for existing region MBeans * @throws MalformedObjectNameException If the query expression used is not valid */ private Map<String, ObjectName> getExistingRegionMbeansFullPaths(String memberId) throws MalformedObjectNameException { Map<String, ObjectName> pathsToObjName = new HashMap<String, ObjectName>(); if (memberId != null && memberId.trim().length() != 0) { Object[] params = new Object[] {MBeanUtil.makeCompliantMBeanNameProperty(memberId)}; Set<ObjectName> queryNames = queryObjectNames(REGION_QUERY_EXPRESSION, params); for (ObjectName objectName : queryNames) { pathsToObjName.put(objectName.getKeyProperty("path"), objectName); } } return pathsToObjName; } /** * Returns an array of ObjectNames existing statistics types MBeans * * @param memberId string identifier of a member * @param name text id of the stats which appears in the stats ObjectName as name keyProperty * @return Array of Stats MBean ObjectNames * @throws MalformedObjectNameException If the query expression used is not valid */ private ObjectName[] getExistingStats(String memberId, String name) throws MalformedObjectNameException { ObjectName[] statObjectNames = new ObjectName[0]; if (memberId != null && memberId.trim().length() != 0) { Object[] params = new Object[] {MBeanUtil.makeCompliantMBeanNameProperty(memberId), name}; Set<ObjectName> queryNames = queryObjectNames(STATS_QUERY_EXPRESSION, params); statObjectNames = new ObjectName[queryNames.size()]; statObjectNames = queryNames.toArray(statObjectNames); } return statObjectNames; } /** * Queries the MBean server with the string formed using placing the params in the parameterized * string passed as queryStr. * * @param queryStr parameterized string * @param params params to put in the string * @return results of an ObjectName query * @throws MalformedObjectNameException If the query expression ObjectName formed is not valid */ private Set<ObjectName> queryObjectNames(String queryStr, Object... params) throws MalformedObjectNameException { Set<ObjectName> queried = Collections.emptySet(); queryStr = MessageFormat.format(queryStr, params); ObjectName queryExp = ObjectName.getInstance(queryStr); queried = agent.getMBeanServer().queryNames(null, queryExp); return queried; } /* *************************************************************************/ /* **************** NOTIFICATION EMITTER IMPLEMENTATION ********************/ /* *************************************************************************/ /** * @see NotificationEmitter#addNotificationListener(NotificationListener, NotificationFilter, * Object) */ public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException { forwarder.addNotificationListener(listener, filter, handback); } /** * @see NotificationEmitter#removeNotificationListener(NotificationListener) */ public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { forwarder.removeNotificationListener(listener); } /** * @see NotificationEmitter#getNotificationInfo() */ public MBeanNotificationInfo[] getNotificationInfo() { return getMBeanInfo().getNotifications(); } /** * @see NotificationEmitter#removeNotificationListener(NotificationListener, NotificationFilter, * Object) */ public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException { forwarder.removeNotificationListener(listener, filter, handback); } } /** * This class acts as a hub for the Notifications defined on AdminDistributedSystem & SystemMember * MBeans. This acts as a listener for these notifications and broadcasts them as notifications from * the {@link MemberInfoWithStatsMBean} MBean. This class extends * {@link NotificationBroadcasterSupport} only to have the functionality to send notifications. * * * @since GemFire 6.5 */ class NotificationForwarder extends NotificationBroadcasterSupport implements NotificationListener { private static final Logger logger = LogService.getLogger(); /* sequence generator for notifications from GemFireTypesWrapper MBean */ private static AtomicLong notificationSequenceNumber = new AtomicLong(); /* reference to the MBeanServer instance */ private MBeanServer mBeanServer; /** * Default Constructor * * @param mBeanServer reference to the MBeanServer instance */ /* default */ NotificationForwarder(MBeanServer mBeanServer) { this.mBeanServer = mBeanServer; } /** * Handles notifications as: 1. Member Joined: Registers this NotificationForwarder as a * notification listener for Cache/Region Notifications. 2. Member Left/Crashed: Unregisters this * NotificationForwarder as a notification listener for Cache/Region Notifications. 3. * AdminDistributedSystem Disconnected: Unregisters this NotificationForwarder as a notification * listener for member Notifications. * * Forwards the notifications to the JMX Clients that have registered for notifications on this * MBean * * @param notification notification to be handled * @param handback handback object used while NotificationForwarder was registered * * @see NotificationListener#handleNotification(Notification, Object) */ public void handleNotification(Notification notification, Object handback) { Object notifSource = notification.getSource(); if (AdminDistributedSystemJmxImpl.NOTIF_MEMBER_JOINED.equals(notification.getType())) { ObjectName source = (ObjectName) notifSource; // initialize statistics/register with refreshTimer for new member String[] noArgs = {}; try { ObjectName[] stats = (ObjectName[]) mBeanServer.invoke(source, "manageStats", noArgs, noArgs); if (stats != null) { for (ObjectName stat : stats) { mBeanServer.invoke(stat, "getStatistics", noArgs, noArgs); } } logger.debug("getStatistics call completed with no exceptions."); } catch (ReflectionException e) { logger.info(LocalizedMessage.create( LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_WHILE_INITIALIZING_STATISICS_FOR_0, source.toString()), e); } catch (MBeanException e) { logger.info(LocalizedMessage.create( LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_WHILE_INITIALIZING_STATISICS_FOR_0, source.toString()), e); } catch (InstanceNotFoundException e) { logger.info(LocalizedMessage.create( LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_WHILE_INITIALIZING_STATISICS_FOR_0, source.toString()), e); } // register this listener for joined member's cache/region notifications try { registerNotificationListener(source); } catch (OperationsException e) { logger.info(LocalizedMessage.create( LocalizedStrings.MemberInfoWithStatsMBean_EXCEPTION_WHILE_REGISTERING_NOTIFICATION_LISTENER_FOR_0, source.toString()), e); } } /* * else if (AdminDistributedSystemJmxImpl.NOTIF_MEMBER_LEFT.equals(notification.getType()) || * AdminDistributedSystemJmxImpl.NOTIF_MEMBER_CRASHED.equals(notification.getType())) { * ObjectName source = (ObjectName) notifSource; //unregister this listener from left member's * cache/region notifications try { unregisterNotificationListener(source); } catch * (OperationsException e) { logwriter.info(LocalizedMessage.create(LocalizedStrings. * MemberInfoWithStatsMBean_EXCEPTION_WHILE_UNREGISTERING_NOTIFICATION_LISTENER_FOR_0, * source.toString(), e); } } else if * (AdminDistributedSystemJmxImpl.NOTIF_ADMIN_SYSTEM_DISCONNECT.equals(notification.getType()) * ) { String source = (String) notifSource; //This notification does not have ObjectName as a * source. try { ObjectName instance = ObjectName.getInstance(source); * unregisterNotificationListener(instance); } catch (OperationsException e) { * logwriter.info(LocalizedMessage.create(LocalizedStrings. * MemberInfoWithStatsMBean_EXCEPTION_WHILE_UNREGISTERING_NOTIFICATION_LISTENER_FOR_0, * source.toString(), e); } catch (NullPointerException e) { * logwriter.info(LocalizedMessage.create(LocalizedStrings. * MemberInfoWithStatsMBean_EXCEPTION_WHILE_UNREGISTERING_NOTIFICATION_LISTENER_FOR_0, * source.toString(), e); } } */ // NOTIF_ALERT is sent as is // TODO: Check if same notification instance can be reused by simply changing the sequence // number notification = new Notification(notification.getType(), notifSource, notificationSequenceNumber.addAndGet(1L), notification.getTimeStamp(), notification.getMessage()); sendNotification(notification); } /** * Registers itself as a NotificationListener for Notifications sent from MBean with the * ObjectName given as source. * * @param source source of notifications * @throws InstanceNotFoundException The MBean name provided does not match any of the registered * MBeans. */ /* default */void registerNotificationListener(ObjectName source) throws InstanceNotFoundException { mBeanServer.addNotificationListener(source, this, null/* handback */, source); } /** * Unregisters itself as a NotificationListener for Notifications sent from MBean with the * ObjectName given as source. * * @param source source of notifications * @throws InstanceNotFoundException The MBean name provided does not match any of the registered * MBeans. * @throws ListenerNotFoundException The listener is not registered in the MBean. */ /* default */void unregisterNotificationListener(ObjectName source) throws InstanceNotFoundException, ListenerNotFoundException { mBeanServer.removeNotificationListener(source, this); } }