http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/895fd144/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/StatisticAttributeInfo.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/StatisticAttributeInfo.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/StatisticAttributeInfo.java new file mode 100755 index 0000000..1d5b9b4 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/StatisticAttributeInfo.java @@ -0,0 +1,72 @@ +/* + * 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.internal.admin.api.jmx.impl; + +import org.apache.geode.internal.admin.api.Statistic; +import org.apache.geode.internal.Assert; + +import javax.management.Descriptor; +import javax.management.modelmbean.DescriptorSupport; +import javax.management.modelmbean.ModelMBeanAttributeInfo; + +/** + * Subclass of AttributeInfo with {@link Statistic} + * added for use as the {@link + * javax.management.modelmbean.ModelMBeanAttributeInfo} descriptor's + * <i>targetObject</i> value. + * + * @since GemFire 3.5 + * + */ +class StatisticAttributeInfo extends org.apache.commons.modeler.AttributeInfo { + private static final long serialVersionUID = 28022387514935560L; + + private Statistic stat; + + public StatisticAttributeInfo() { + super(); + } + + public Statistic getStat() { + return this.stat; + } + + public void setStat(Statistic stat) { + // System.out.println(">> stat = " + stat); + Assert.assertTrue(stat != null, "Attempting to set stat to null"); + this.stat = stat; + } + + @Override + public ModelMBeanAttributeInfo createAttributeInfo() { + Descriptor desc = new DescriptorSupport(new String[] {"name=" + this.displayName, + "descriptorType=attribute", "currencyTimeLimit=-1", // always stale + "displayName=" + this.displayName, "getMethod=getValue"}); + + Assert.assertTrue(this.stat != null, "Stat target object is null!"); + desc.setField("targetObject", this.stat); + + ModelMBeanAttributeInfo info = new ModelMBeanAttributeInfo(this.displayName, // name + this.type, // type + this.description, // description + this.readable, // isReadable + this.writeable, // isWritable + this.is, // isIs + desc); + + return info; + } +} +
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/895fd144/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/StatisticResourceJmxImpl.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/StatisticResourceJmxImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/StatisticResourceJmxImpl.java new file mode 100755 index 0000000..1d18889 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/StatisticResourceJmxImpl.java @@ -0,0 +1,347 @@ +/* + * 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.internal.admin.api.jmx.impl; + +import javax.management.Notification; +import javax.management.ObjectName; +import javax.management.modelmbean.ModelMBean; +import javax.naming.OperationNotSupportedException; + +import org.apache.commons.modeler.ManagedBean; +import org.apache.logging.log4j.Logger; + +import org.apache.geode.CancelException; +import org.apache.geode.SystemFailure; +import org.apache.geode.internal.admin.api.AdminException; +import org.apache.geode.internal.admin.api.OperationCancelledException; +import org.apache.geode.internal.admin.api.Statistic; +import org.apache.geode.internal.admin.StatResource; +import org.apache.geode.internal.admin.api.impl.StatisticResourceImpl; +import org.apache.geode.internal.i18n.LocalizedStrings; +import org.apache.geode.internal.logging.LogService; + +/** + * Provides MBean support for the monitoring of a statistic resource. + * + * @since GemFire 3.5 + * + */ +public class StatisticResourceJmxImpl +extends StatisticResourceImpl +implements javax.management.NotificationListener, ManagedResource { + + private static final Logger logger = LogService.getLogger(); + + /** + * Interval in seconds between refreshes. Values less than one results in no refreshing . + */ + private int refreshInterval = 0; + + /** The JMX object name of this managed resource */ + private ObjectName objectName; + + /** A flag to indicate if time is inited. MBeanUtil lookup is costly */ + private boolean timerInited = false; + + // ------------------------------------------------------------------------- + // Constructor(s) + // ------------------------------------------------------------------------- + + /** + * Constructor for the StatisticResource object + * + * @param statResource the admin StatResource to manage/monitor + * @param member the SystemMember owning this resource + * @exception AdminException + * if unable to create this StatisticResource for administration + */ + public StatisticResourceJmxImpl(StatResource statResource, + SystemMemberJmx member) + throws AdminException { + super(statResource, member); + initializeMBean(); + } + + /** Create and register the MBean to manage this resource */ + private void initializeMBean() + throws AdminException { + this.mbeanName = new StringBuffer("GemFire.Statistic:") + .append("source=").append(MBeanUtil.makeCompliantMBeanNameProperty(this.member.getId())) + .append(",type=").append(MBeanUtil.makeCompliantMBeanNameProperty(getType())) + .append(",name=").append(MBeanUtil.makeCompliantMBeanNameProperty(getName())) + .append(",uid=").append(getUniqueId()).toString(); + + this.objectName = + MBeanUtil.createMBean(this, addDynamicAttributes(MBeanUtil.lookupManagedBean(this))); + + // Refresh Interval + AdminDistributedSystemJmxImpl sysJmx = + (AdminDistributedSystemJmxImpl) this.member.getDistributedSystem(); + if (sysJmx.getRefreshInterval() > 0) + this.refreshInterval = sysJmx.getRefreshInterval(); + } + + // ------------------------------------------------------------------------- + // MBean attributes - accessors/mutators + // ------------------------------------------------------------------------- + + /** + * Gets the interval in seconds between statistics refreshes + * + * @return the current refresh interval in seconds + */ + public int getRefreshInterval() { + return this.refreshInterval; + } + + /** + * Sets interval in seconds between statistic refreshes; zero or less turns off auto refreshing. + * Manual refreshing has no effect on when the next scheduled refresh will occur. + * + * @param refreshInterval the new refresh interval in seconds + */ + private void _setRefreshInterval(int refreshInterval) { + boolean isRegistered = MBeanUtil.isRefreshNotificationRegistered(this, + RefreshNotificationType.STATISTIC_RESOURCE_STATISTICS); + + if (isRegistered && (getRefreshInterval() == refreshInterval)) + return; + + try { + MBeanUtil.registerRefreshNotification(this, // NotificationListener + getMBeanName(), // User Data as MBean Name + RefreshNotificationType.STATISTIC_RESOURCE_STATISTICS, refreshInterval); // int + + this.refreshInterval = refreshInterval; + timerInited = true; + } catch (RuntimeException e) { + logger.warn(e.getMessage(), e); // dead in water, print, and then ignore + this.refreshInterval = 0; // zero out to avoid more exceptions + } catch (VirtualMachineError err) { + SystemFailure.initiateFailure(err); + // If this ever returns, rethrow the error. We're poisoned + // now, so don't let this thread continue. + throw err; + } catch (Error e) { + // Whenever you catch Error or Throwable, you must also + // catch VirtualMachineError (see above). However, there is + // _still_ a possibility that you are dealing with a cascading + // error condition, so you also need to check to see if the JVM + // is still usable: + SystemFailure.checkFailure(); + logger.error(e.getMessage(), e); // dead in water, print, and then ignore + this.refreshInterval = 0; // zero out to avoid more exceptions + } + } + + /** + * RefreshInterval is now set only through the AdminDistributedSystem property refreshInterval. + * Attempt to set refreshInterval on StatisticResourceJmx MBean would result in an + * OperationNotSupportedException Auto-refresh is enabled on demand when a call to getStatistics + * is made + * + * @param refreshInterval the new refresh interval in seconds + * @deprecated since 6.0 use DistributedSystemConfig.refreshInterval instead + */ + @Deprecated + public void setRefreshInterval(int refreshInterval) throws OperationNotSupportedException { + throw new OperationNotSupportedException( + LocalizedStrings.MANAGED_RESOURCE_REFRESH_INTERVAL_CANT_BE_SET_DIRECTLY + .toLocalizedString()); + } + + // ------------------------------------------------------------------------- + // JMX Notification listener + // ------------------------------------------------------------------------- + + /** + * Handles notification to refresh. Reacts by refreshing the values of this SystemMember's + * ConfigurationParamaters. Any other notification is ignored. Given notification is handled only + * if there is any JMX client connected to the system. + * <p> + * TODO: investigate use of NotificationFilter instead of explicit check... + * + * @param notification the JMX notification being received + * @param hb handback object is unused + */ + public void handleNotification(Notification notification, Object hb) { + AdminDistributedSystemJmxImpl adminDSJmx = + (AdminDistributedSystemJmxImpl) this.member.getDistributedSystem(); + + String typeStatResourceStats = RefreshNotificationType.STATISTIC_RESOURCE_STATISTICS.getType(); + + if (typeStatResourceStats.equals(notification.getType()) + && getMBeanName().equals(notification.getUserData()) + && !adminDSJmx.isRmiClientCountZero()) { + try { + refresh(); + + } catch (AdminException e) { + logger.warn(e.getMessage(), e); + } catch (OperationCancelledException e) { + // underlying resource is no longer reachable by remote admin + logger.warn(e.getMessage(), e); + _setRefreshInterval(0); + } catch (CancelException e) { + // shutting down - okay to ignore + } catch (java.lang.RuntimeException e) { + logger.debug(e.getMessage(), e); // dead in water, print, and then ignore + _setRefreshInterval(0); // zero out to avoid more exceptions + } catch (VirtualMachineError err) { + SystemFailure.initiateFailure(err); + // If this ever returns, rethrow the error. We're poisoned + // now, so don't let this thread continue. + throw err; + } catch (java.lang.Error e) { + // Whenever you catch Error or Throwable, you must also + // catch VirtualMachineError (see above). However, there is + // _still_ a possibility that you are dealing with a cascading + // error condition, so you also need to check to see if the JVM + // is still usable: + SystemFailure.checkFailure(); + logger.error(e.getMessage(), e); // dead in water, print, and then ignore + this.refreshInterval = 0; // zero out to avoid more exceptions + } + } + } + + // ------------------------------------------------------------------------- + // Create MBean attributes for each Statistic + // ------------------------------------------------------------------------- + + /** + * Add MBean attribute definitions for each Statistic. + * + * @param managed the mbean definition to add attributes to + * @return a new instance of ManagedBean copied from <code>managed</code> but with the new + * attributes added + */ + ManagedBean addDynamicAttributes(ManagedBean managed) + throws AdminException { + if (managed == null) { + throw new IllegalArgumentException( + LocalizedStrings.StatisticResourceJmxImpl_MANAGEDBEAN_IS_NULL.toLocalizedString()); + } + + refresh(); // to get the stats... + + // need to create a new instance of ManagedBean to clean the "slate"... + ManagedBean newManagedBean = new DynamicManagedBean(managed); + for (int i = 0; i < this.statistics.length; i++) { + StatisticAttributeInfo attrInfo = new StatisticAttributeInfo(); + + attrInfo.setName(this.statistics[i].getName()); + attrInfo.setDisplayName(this.statistics[i].getName()); + attrInfo.setDescription(this.statistics[i].getDescription()); + attrInfo.setType("java.lang.Number"); + + attrInfo.setIs(false); + attrInfo.setReadable(true); + attrInfo.setWriteable(false); + + attrInfo.setStat(this.statistics[i]); + + newManagedBean.addAttribute(attrInfo); + } + return newManagedBean; + } + + public Statistic[] getStatistics() { + if (!timerInited) { + // 1st call to getStatistics would trigger + // the auto-refresh if an interval is set + if (this.refreshInterval > 0) { + this._setRefreshInterval(this.refreshInterval); + } + } + + if (this.statistics == null) { + try { + this.refresh(); + } catch (AdminException e) { + this.statistics = new Statistic[0]; + } + } + + return this.statistics; + } + + // ------------------------------------------------------------------------- + // ManagedResource implementation + // ------------------------------------------------------------------------- + + /** The name of the MBean that will manage this resource */ + private String mbeanName; + + /** The ModelMBean that is configured to manage this resource */ + private ModelMBean modelMBean; + + public String getMBeanName() { + return this.mbeanName; + } + + public ModelMBean getModelMBean() { + return this.modelMBean; + } + + public void setModelMBean(ModelMBean modelMBean) { + this.modelMBean = modelMBean; + } + + public ObjectName getObjectName() { + return this.objectName; + } + + public ManagedResourceType getManagedResourceType() { + return ManagedResourceType.STATISTIC_RESOURCE; + } + + public void cleanupResource() { + this.modelMBean = null; + this.member = null; + this.statistics = null; + this.statResource = null; + } + + /** + * Checks equality of the given object with <code>this</code> based on the type (Class) and the + * MBean Name returned by <code>getMBeanName()</code> methods. + * + * @param obj object to check equality with + * @return true if the given object is if the same type and its MBean Name is same as + * <code>this</code> object's MBean Name, false otherwise + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof StatisticResourceJmxImpl)) { + return false; + } + + StatisticResourceJmxImpl other = (StatisticResourceJmxImpl) obj; + + return this.getMBeanName().equals(other.getMBeanName()); + } + + /** + * Returns hash code for <code>this</code> object which is based on the MBean Name generated. + * + * @return hash code for <code>this</code> object + */ + @Override + public int hashCode() { + return this.getMBeanName().hashCode(); + } +} + http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/895fd144/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberBridgeServerJmxImpl.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberBridgeServerJmxImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberBridgeServerJmxImpl.java new file mode 100644 index 0000000..72e3468 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberBridgeServerJmxImpl.java @@ -0,0 +1,125 @@ +/* + * 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.internal.admin.api.jmx.impl; + +import org.apache.geode.internal.admin.api.AdminException; +import org.apache.geode.internal.admin.api.SystemMemberBridgeServer; +import org.apache.geode.internal.admin.api.impl.SystemMemberBridgeServerImpl; +import org.apache.geode.internal.admin.api.impl.SystemMemberCacheImpl; +import org.apache.geode.internal.admin.AdminBridgeServer; +import org.apache.geode.internal.admin.GemFireVM; + +import javax.management.ObjectName; +import javax.management.modelmbean.ModelMBean; + +/** + * MBean representation of a {@link + * SystemMemberBridgeServer}. + * + * @since GemFire 4.0 + */ +public class SystemMemberBridgeServerJmxImpl extends SystemMemberBridgeServerImpl + implements ManagedResource { + + /** The object name of this managed resource */ + private ObjectName objectName; + + /** The name of the MBean that will manage this resource */ + private String mbeanName; + + /** The ModelMBean that is configured to manage this resource */ + private ModelMBean modelMBean; + + ////////////////////// Constructors ////////////////////// + + /** + * Creates a new <code>SystemMemberBridgeServerJmxImpl</code> that serves the contents of the + * given cache. + */ + SystemMemberBridgeServerJmxImpl(SystemMemberCacheImpl cache, AdminBridgeServer bridgeInfo) + throws AdminException { + + super(cache, bridgeInfo); + initializeMBean(cache); + } + + ////////////////////// Instance Methods ////////////////////// + + /** + * Creates and registers the MBean to manage this resource + */ + private void initializeMBean(SystemMemberCacheImpl cache) throws AdminException { + + GemFireVM vm = cache.getVM(); + this.mbeanName = new StringBuffer("GemFire.Cache:").append("name=") + .append(MBeanUtil.makeCompliantMBeanNameProperty(cache.getName())).append(",id=") + .append(this.getBridgeId()).append(",owner=") + .append(MBeanUtil.makeCompliantMBeanNameProperty(vm.getId().toString())) + .append(",type=CacheServer").toString(); + + this.objectName = MBeanUtil.createMBean(this); + } + + public String getMBeanName() { + return this.mbeanName; + } + + public ModelMBean getModelMBean() { + return this.modelMBean; + } + + public void setModelMBean(ModelMBean modelMBean) { + this.modelMBean = modelMBean; + } + + public ObjectName getObjectName() { + return this.objectName; + } + + public ManagedResourceType getManagedResourceType() { + return ManagedResourceType.SYSTEM_MEMBER_CACHE_SERVER; + } + + public void cleanupResource() {} + + /** + * Checks equality of the given object with <code>this</code> based on the type (Class) and the + * MBean Name returned by <code>getMBeanName()</code> methods. + * + * @param obj object to check equality with + * @return true if the given object is if the same type and its MBean Name is same as + * <code>this</code> object's MBean Name, false otherwise + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof SystemMemberBridgeServerJmxImpl)) { + return false; + } + + SystemMemberBridgeServerJmxImpl other = (SystemMemberBridgeServerJmxImpl) obj; + + return this.getMBeanName().equals(other.getMBeanName()); + } + + /** + * Returns hash code for <code>this</code> object which is based on the MBean Name generated. + * + * @return hash code for <code>this</code> object + */ + @Override + public int hashCode() { + return this.getMBeanName().hashCode(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/895fd144/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberCacheJmxImpl.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberCacheJmxImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberCacheJmxImpl.java new file mode 100644 index 0000000..abbd6cb --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberCacheJmxImpl.java @@ -0,0 +1,453 @@ +/* + * 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.internal.admin.api.jmx.impl; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; +import javax.management.modelmbean.ModelMBean; + +import org.apache.commons.modeler.ManagedBean; +import org.apache.logging.log4j.Level; + +import org.apache.geode.SystemFailure; +import org.apache.geode.internal.admin.api.AdminException; +import org.apache.geode.internal.admin.api.SystemMemberCache; +import org.apache.geode.internal.admin.api.SystemMemberCacheServer; +import org.apache.geode.internal.admin.api.SystemMemberRegion; +import org.apache.geode.internal.admin.api.impl.SystemMemberBridgeServerImpl; +import org.apache.geode.cache.Region; +import org.apache.geode.internal.admin.AdminBridgeServer; +import org.apache.geode.internal.admin.GemFireVM; +import org.apache.geode.internal.admin.api.impl.SystemMemberCacheImpl; +import org.apache.geode.internal.i18n.LocalizedStrings; + +/** + * MBean representation of {@link SystemMemberCache}. + * + * @since GemFire 3.5 + */ +public class SystemMemberCacheJmxImpl +extends SystemMemberCacheImpl +implements ManagedResource { + + /** The object name of this managed resource */ + private ObjectName objectName; + + /** collection to collect all the resources created for this member */ + private Map<String, SystemMemberRegionJmxImpl> managedRegionResourcesMap = + new HashMap<String, SystemMemberRegionJmxImpl>(); + private Map<Number, SystemMemberBridgeServerJmxImpl> managedCacheServerResourcesMap = + new HashMap<Number, SystemMemberBridgeServerJmxImpl>(); + + // ------------------------------------------------------------------------- + // Constructor(s) + // ------------------------------------------------------------------------- + + /** + * Constructs an instance of SystemMemberCacheJmxImpl. + * + * @param vm The vm owning the cache this object will manage + */ + public SystemMemberCacheJmxImpl(GemFireVM vm) + throws AdminException { + super(vm); + initializeMBean(); + } + + /** Create and register the MBean to manage this resource */ + private void initializeMBean() + throws AdminException { + this.mbeanName = new StringBuffer("GemFire.Cache:") + .append("name=") + .append(MBeanUtil.makeCompliantMBeanNameProperty(getName())) + .append(",id=") + .append(getId()) + .append(",owner=") + .append(MBeanUtil.makeCompliantMBeanNameProperty(vm.getId().toString())) + .append(",type=Cache").toString(); + + this.objectName = + MBeanUtil.createMBean(this, addDynamicAttributes(MBeanUtil.lookupManagedBean(this))); + } + + // ------------------------------------------------------------------------- + // Template methods overriden from superclass... + // ------------------------------------------------------------------------- + + /** + * Override createSystemMemberRegion by instantiating SystemMemberRegionJmxImpl. This instance is + * also added to the managedResources collection. + * + * @param r reference to Region instance for which this JMX resource is to be created + * @return SystemMemberRegionJmxImpl - JMX Implementation of SystemMemberRegion + * @throws AdminException if constructing SystemMemberRegionJmxImpl instance fails + */ + @Override + protected SystemMemberRegion createSystemMemberRegion(Region r) + throws AdminException { + SystemMemberRegionJmxImpl managedSystemMemberRegion = null; + boolean needsRefresh = false; + synchronized (this.managedRegionResourcesMap) { + /* + * Ensuring that a single instance of System Member Region is created per Region. + */ + SystemMemberRegionJmxImpl managedResource = managedRegionResourcesMap.get(r.getFullPath()); + if (managedResource != null) { + managedSystemMemberRegion = managedResource; + } else { + managedSystemMemberRegion = new SystemMemberRegionJmxImpl(this, r); + managedRegionResourcesMap.put(r.getFullPath(), managedSystemMemberRegion); + needsRefresh = true; + } + } + if (needsRefresh) { + managedSystemMemberRegion.refresh(); + } + return managedSystemMemberRegion; + } + + /** + * Creates a SystemMemberBridgeServerJmxImpl instance. This instance is also added to the + * managedResources collection. + * + * @param bridge reference to AdminBridgeServer for which this JMX resource is to be created + * @return SystemMemberBridgeServerJmxImpl - JMX Implementation of SystemMemberBridgeServerImpl + * @throws AdminException if constructing SystemMemberBridgeServerJmxImpl instance fails + */ + @Override + protected SystemMemberBridgeServerImpl createSystemMemberBridgeServer(AdminBridgeServer bridge) + throws AdminException { + SystemMemberBridgeServerJmxImpl managedSystemMemberBridgeServer = null; + synchronized (this.managedCacheServerResourcesMap) { + /* + * Ensuring that a single instance of SystemMember BridgeServer is created per + * AdminBridgeServer. + */ + SystemMemberBridgeServerJmxImpl managedCacheServerResource = + managedCacheServerResourcesMap.get(bridge.getId()); + if (managedCacheServerResource != null) { + managedSystemMemberBridgeServer = managedCacheServerResource; + } else { + managedSystemMemberBridgeServer = new SystemMemberBridgeServerJmxImpl(this, bridge); + managedCacheServerResourcesMap.put(bridge.getId(), managedSystemMemberBridgeServer); + } + } + return managedSystemMemberBridgeServer; + } + + // ------------------------------------------------------------------------- + // Create MBean attributes for each Statistic + // ------------------------------------------------------------------------- + + /** + * Add MBean attribute definitions for each Statistic. + * + * @param managed the mbean definition to add attributes to + * @return a new instance of ManagedBean copied from <code>managed</code> but with the new + * attributes added + */ + ManagedBean addDynamicAttributes(ManagedBean managed) + throws AdminException { + if (managed == null) { + throw new IllegalArgumentException( + LocalizedStrings.SystemMemberCacheJmxImpl_MANAGEDBEAN_IS_NULL.toLocalizedString()); + } + + refresh(); // to get the stats... + + // need to create a new instance of ManagedBean to clean the "slate"... + ManagedBean newManagedBean = new DynamicManagedBean(managed); + for (int i = 0; i < this.statistics.length; i++) { + StatisticAttributeInfo attrInfo = new StatisticAttributeInfo(); + + attrInfo.setName(this.statistics[i].getName()); + attrInfo.setDisplayName(this.statistics[i].getName()); + attrInfo.setDescription(this.statistics[i].getDescription()); + attrInfo.setType("java.lang.Number"); + + attrInfo.setIs(false); + attrInfo.setReadable(true); + attrInfo.setWriteable(false); + + attrInfo.setStat(this.statistics[i]); + + newManagedBean.addAttribute(attrInfo); + } + + return newManagedBean; + } + + // ------------------------------------------------------------------------- + // MBean Operations + // ------------------------------------------------------------------------- + + /** + * Returns the ObjectName of the Region for the specified path. + * + * @throws AdminException If no region with path <code>path</code> exists + */ + public ObjectName manageRegion(String path) throws AdminException, MalformedObjectNameException { + try { + SystemMemberRegionJmxImpl region = null; + + try { + region = (SystemMemberRegionJmxImpl) getRegion(path); + + } catch (AdminException e) { + MBeanUtil.logStackTrace(Level.WARN, e); + throw e; + } + + if (region == null) { + throw new AdminException( + LocalizedStrings.SystemMemberCacheJmxImpl_THIS_CACHE_DOES_NOT_CONTAIN_REGION_0 + .toLocalizedString(path)); + + } else { + return ObjectName.getInstance(region.getMBeanName()); + } + } catch (RuntimeException e) { + MBeanUtil.logStackTrace(Level.WARN, e); + throw e; + } catch (VirtualMachineError err) { + SystemFailure.initiateFailure(err); + // If this ever returns, rethrow the error. We're poisoned + // now, so don't let this thread continue. + throw err; + } catch (Error e) { + // Whenever you catch Error or Throwable, you must also + // catch VirtualMachineError (see above). However, there is + // _still_ a possibility that you are dealing with a cascading + // error condition, so you also need to check to see if the JVM + // is still usable: + SystemFailure.checkFailure(); + MBeanUtil.logStackTrace(Level.ERROR, e); + throw e; + } + } + + /** + * Creates a new cache server MBean and returns its <code>ObjectName</code>. + * + * @since GemFire 5.7 + */ + public ObjectName manageCacheServer() throws AdminException, MalformedObjectNameException { + + try { + SystemMemberBridgeServerJmxImpl bridge = (SystemMemberBridgeServerJmxImpl) addCacheServer(); + return ObjectName.getInstance(bridge.getMBeanName()); + } catch (AdminException e) { + MBeanUtil.logStackTrace(Level.WARN, e); + throw e; + } catch (RuntimeException e) { + MBeanUtil.logStackTrace(Level.WARN, e); + throw e; + } catch (VirtualMachineError err) { + SystemFailure.initiateFailure(err); + // If this ever returns, rethrow the error. We're poisoned + // now, so don't let this thread continue. + throw err; + } catch (Error e) { + // Whenever you catch Error or Throwable, you must also + // catch VirtualMachineError (see above). However, there is + // _still_ a possibility that you are dealing with a cascading + // error condition, so you also need to check to see if the JVM + // is still usable: + SystemFailure.checkFailure(); + MBeanUtil.logStackTrace(Level.ERROR, e); + throw e; + } + } + + /** + * Returns the MBean <code>ObjectName</code>s for all cache servers that serve this cache to + * clients. + * + * @since GemFire 4.0 + */ + public ObjectName[] manageCacheServers() throws AdminException, MalformedObjectNameException { + + try { + SystemMemberCacheServer[] bridges = getCacheServers(); + ObjectName[] names = new ObjectName[bridges.length]; + for (int i = 0; i < bridges.length; i++) { + SystemMemberBridgeServerJmxImpl bridge = (SystemMemberBridgeServerJmxImpl) bridges[i]; + names[i] = ObjectName.getInstance(bridge.getMBeanName()); + } + + return names; + } catch (AdminException e) { + MBeanUtil.logStackTrace(Level.WARN, e); + throw e; + } catch (RuntimeException e) { + MBeanUtil.logStackTrace(Level.WARN, e); + throw e; + } catch (VirtualMachineError err) { + SystemFailure.initiateFailure(err); + // If this ever returns, rethrow the error. We're poisoned + // now, so don't let this thread continue. + throw err; + } catch (Error e) { + // Whenever you catch Error or Throwable, you must also + // catch VirtualMachineError (see above). However, there is + // _still_ a possibility that you are dealing with a cascading + // error condition, so you also need to check to see if the JVM + // is still usable: + SystemFailure.checkFailure(); + MBeanUtil.logStackTrace(Level.ERROR, e); + throw e; + } + } + + /** + * Returns the MBean <code>ObjectName</code>s for all bridge servers that serve this cache. + * + * @since GemFire 4.0 + * @deprecated as of 5.7 + */ + @Deprecated + public ObjectName[] manageBridgeServers() throws AdminException, MalformedObjectNameException { + return manageCacheServers(); + } + + // ------------------------------------------------------------------------- + // ManagedResource implementation + // ------------------------------------------------------------------------- + + /** The name of the MBean that will manage this resource */ + private String mbeanName; + + /** The ModelMBean that is configured to manage this resource */ + private ModelMBean modelMBean; + + public String getMBeanName() { + return this.mbeanName; + } + + public ModelMBean getModelMBean() { + return this.modelMBean; + } + + public void setModelMBean(ModelMBean modelMBean) { + this.modelMBean = modelMBean; + } + + public ObjectName getObjectName() { + return this.objectName; + } + + public ManagedResourceType getManagedResourceType() { + return ManagedResourceType.SYSTEM_MEMBER_CACHE; + } + + + /** + * Un-registers all the statistics & cache managed resource created for this member. After + * un-registering the resource MBean instances, clears this.memberResources collection. + * + * Creates ConfigurationParameterJmxImpl, StatisticResourceJmxImpl and SystemMemberCacheJmxImpl. + * But cleans up only StatisticResourceJmxImpl and SystemMemberCacheJmxImpl which are of type + * ManagedResource. + */ + public void cleanupResource() { + synchronized (this.managedRegionResourcesMap) { + Collection<SystemMemberRegionJmxImpl> values = managedRegionResourcesMap.values(); + + for (SystemMemberRegionJmxImpl systemMemberRegionJmxImpl : values) { + MBeanUtil.unregisterMBean(systemMemberRegionJmxImpl); + } + + this.managedRegionResourcesMap.clear(); + } + + synchronized (this.managedCacheServerResourcesMap) { + Collection<SystemMemberBridgeServerJmxImpl> values = managedCacheServerResourcesMap.values(); + + for (SystemMemberBridgeServerJmxImpl SystemMemberBridgeServerJmxImpl : values) { + MBeanUtil.unregisterMBean(SystemMemberBridgeServerJmxImpl); + } + + this.managedCacheServerResourcesMap.clear(); + } + } + + /** + * Cleans up managed resources created for the region that was (created and) destroyed in a cache + * represented by this Managed Resource. + * + * @param regionPath path of the region that got destroyed + * @return a managed resource related to this region path + */ + public ManagedResource cleanupRegionResources(String regionPath) { + ManagedResource cleaned = null; + + synchronized (this.managedRegionResourcesMap) { + Set<Entry<String, SystemMemberRegionJmxImpl>> entries = managedRegionResourcesMap.entrySet(); + for (Iterator<Entry<String, SystemMemberRegionJmxImpl>> it = entries.iterator(); it + .hasNext();) { + Entry<String, SystemMemberRegionJmxImpl> entry = it.next(); + SystemMemberRegionJmxImpl managedResource = entry.getValue(); + ObjectName objName = managedResource.getObjectName(); + + String pathProp = objName.getKeyProperty("path"); + if (pathProp != null && pathProp.equals(regionPath)) { + cleaned = managedResource; + it.remove(); + + break; + } + } + } + + return cleaned; + } + + /** + * Checks equality of the given object with <code>this</code> based on the type (Class) and the + * MBean Name returned by <code>getMBeanName()</code> methods. + * + * @param obj object to check equality with + * @return true if the given object is if the same type and its MBean Name is same as + * <code>this</code> object's MBean Name, false otherwise + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof SystemMemberCacheJmxImpl)) { + return false; + } + + SystemMemberCacheJmxImpl other = (SystemMemberCacheJmxImpl) obj; + + return this.getMBeanName().equals(other.getMBeanName()); + } + + /** + * Returns hash code for <code>this</code> object which is based on the MBean Name generated. + * + * @return hash code for <code>this</code> object + */ + @Override + public int hashCode() { + return this.getMBeanName().hashCode(); + } +} + http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/895fd144/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberJmx.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberJmx.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberJmx.java new file mode 100644 index 0000000..3e67419 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberJmx.java @@ -0,0 +1,466 @@ +/* + * 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.internal.admin.api.jmx.impl; + +import org.apache.geode.SystemFailure; +import org.apache.geode.cache.Operation; +import org.apache.geode.distributed.internal.DistributionConfig; +import org.apache.geode.internal.admin.ClientMembershipMessage; +import org.apache.geode.internal.admin.api.AdminException; +import org.apache.geode.internal.admin.api.ConfigurationParameter; +import org.apache.geode.internal.admin.api.OperationCancelledException; +import org.apache.geode.internal.admin.api.StatisticResource; +import org.apache.geode.internal.admin.api.SystemMember; +import org.apache.geode.internal.admin.api.SystemMemberCache; +import org.apache.geode.internal.admin.api.SystemMemberCacheEvent; +import org.apache.geode.internal.admin.api.SystemMemberRegionEvent; +import org.apache.geode.internal.i18n.LocalizedStrings; +import org.apache.geode.internal.logging.LogService; +import org.apache.geode.internal.logging.log4j.LocalizedMessage; +import org.apache.commons.modeler.ManagedBean; +import org.apache.logging.log4j.Logger; + +import javax.management.*; +import javax.naming.OperationNotSupportedException; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Defines methods that all <code>SystemMember</code> MBeans should implement. + * + * @since GemFire 4.0 + */ +public interface SystemMemberJmx extends SystemMember, NotificationListener { + /** + * Notification type for indicating a cache got created on a member of this distributed system. + */ + public static final String NOTIF_CACHE_CREATED = + DistributionConfig.GEMFIRE_PREFIX + "distributedsystem.cache.created"; + /** + * Notification type for indicating a cache is closed on a member of this distributed system. + */ + public static final String NOTIF_CACHE_CLOSED = + DistributionConfig.GEMFIRE_PREFIX + "distributedsystem.cache.closed"; + /** + * Notification type for indicating a region is created in a cache on a member of this distributed + * system. + */ + public static final String NOTIF_REGION_CREATED = + DistributionConfig.GEMFIRE_PREFIX + "distributedsystem.cache.region.created"; + /** + * Notification type for indicating a region was removed from a cache on a member of this + * distributed system. + */ + public static final String NOTIF_REGION_LOST = + DistributionConfig.GEMFIRE_PREFIX + "distributedsystem.cache.region.lost"; + + /** Notification type for indicating client joined */ + public static final String NOTIF_CLIENT_JOINED = + DistributionConfig.GEMFIRE_PREFIX + "distributedsystem.cache.client.joined"; + + /** Notification type for indicating client left */ + public static final String NOTIF_CLIENT_LEFT = + DistributionConfig.GEMFIRE_PREFIX + "distributedsystem.cache.client.left"; + + /** Notification type for indicating client crashed */ + public static final String NOTIF_CLIENT_CRASHED = + DistributionConfig.GEMFIRE_PREFIX + "distributedsystem.cache.client.crashed"; + + /** + * Gets the interval in seconds between config refreshes + * + * @return the current refresh interval in seconds + */ + public int getRefreshInterval(); + + /** + * RefreshInterval is now set only through the AdminDistributedSystem property refreshInterval. + * Attempt to set refreshInterval on SystemMemberJmx MBean would result in an + * OperationNotSupportedException Auto-refresh is enabled on demand when a call to refreshConfig + * is made + * + * @param refreshInterval the new refresh interval in seconds + * @deprecated since 6.0 use DistributedSystemConfig.refreshInterval instead + */ + @Deprecated + public void setRefreshInterval(int refreshInterval) throws OperationNotSupportedException; + + /** + * Sets the refresh interval field. Sets interval in seconds between config refreshes; zero or + * less turns off auto refreshing. Manual refreshing has no effect on when the next scheduled + * refresh will occur. + */ + public void _setRefreshInterval(int refreshInterval); + + /** + * Gets this member's cache. + * + * @return <code>ObjectName</code> for this member's cache + * + * @throws AdminException If this system member does not host a cache + */ + public ObjectName manageCache() throws AdminException, MalformedObjectNameException; + + /** + * Gets all active StatisticResources for this manager. + * + * @return array of ObjectName instances + */ + public ObjectName[] manageStats() throws AdminException, MalformedObjectNameException; + + /** + * Gets the active StatisticResources for this manager, based on the typeName as the key + * + * @return ObjectName of StatisticResourceJMX instance + */ + public ObjectName[] manageStat(String statisticsTypeName) + throws AdminException, MalformedObjectNameException; + + /** + * Handles notification to refresh. Reacts by refreshing the values of this GemFireManager's + * ConfigurationParamaters. Any other notification is ignored. + * + * @param notification the JMX notification being received + * @param hb handback object is unused + */ + public void handleNotification(Notification notification, Object hb); + + /** + * Add MBean attribute definitions for each ConfigurationParameter. + * + * @param managed the mbean definition to add attributes to + * @return a new instance of ManagedBean copied from <code>managed</code> but with the new + * attributes added + */ + public ManagedBean addDynamicAttributes(ManagedBean managed) throws AdminException; + + + /** + * Implementation should handle creation of cache by extracting the details from the given event + * object. + * + * @param event event object corresponding to the creation of the cache + */ + public void handleCacheCreate(SystemMemberCacheEvent event); + + /** + * Implementation should handle closure of cache by extracting the details from the given event + * object. + * + * @param event event object corresponding to the closure of the cache + */ + public void handleCacheClose(SystemMemberCacheEvent event); + + /** + * Implementation should handle creation of region by extracting the details from the given event + * object. + * + * @param event event object corresponding to the creation of a region + */ + public void handleRegionCreate(SystemMemberRegionEvent event); + + /** + * Implementation should handle loss of region by extracting the details from the given event + * object. + * + * @param event event object corresponding to the loss of a region + */ + public void handleRegionLoss(SystemMemberRegionEvent event); + + /** + * Implementation should handle client membership changes. + * + * @param clientId id of the client for whom membership change happened + * @param eventType membership change type; one of {@link ClientMembershipMessage#JOINED}, + * {@link ClientMembershipMessage#LEFT}, {@link ClientMembershipMessage#CRASHED} + */ + public void handleClientMembership(String clientId, int eventType); + + ////////////////////// Inner Classess ////////////////////// + + /** + * A helper class that provides implementation of the <code>SystemMemberJmx</code> interface as + * static methods. + */ + public static class Helper { + private static final Logger logger = LogService.getLogger(); + + private static AtomicInteger notificationSequenceNumber = new AtomicInteger(); + + public static int setAndReturnRefreshInterval(SystemMemberJmx member, int refreshInterval) { + int ret = refreshInterval; + + try { + MBeanUtil.registerRefreshNotification(member, // NotificationListener + ((ManagedResource) member).getMBeanName(), // User Data + RefreshNotificationType.SYSTEM_MEMBER_CONFIG, refreshInterval); // int + + } catch (RuntimeException e) { + logger.warn(e.getMessage(), e); // dead in water, print, and then ignore + ret = 0; // zero out to avoid more exceptions + + } catch (VirtualMachineError err) { + SystemFailure.initiateFailure(err); + // If this ever returns, rethrow the error. We're poisoned + // now, so don't let this thread continue. + throw err; + } catch (Error e) { + // Whenever you catch Error or Throwable, you must also + // catch VirtualMachineError (see above). However, there is + // _still_ a possibility that you are dealing with a cascading + // error condition, so you also need to check to see if the JVM + // is still usable: + SystemFailure.checkFailure(); + logger.error(e.getMessage(), e); // dead in water, print, and then ignore + ret = 0; // zero out to avoid more exceptions + } + + return ret; + } + + public static ObjectName manageCache(SystemMemberJmx member) + throws AdminException, MalformedObjectNameException { + boolean IthrewIt = false; + try { + SystemMemberCache cache = member.getCache(); + if (cache == null) { + IthrewIt = true; + throw new AdminException( + LocalizedStrings.SystemMemberJmx_THIS_SYSTEM_MEMBER_DOES_NOT_HAVE_A_CACHE + .toLocalizedString()); + } + // Assert.assertTrue(cache != null); (cannot be null) + SystemMemberCacheJmxImpl cacheJmx = (SystemMemberCacheJmxImpl) cache; + return ObjectName.getInstance(cacheJmx.getMBeanName()); + } catch (AdminException e) { + if (!IthrewIt) { + logger.warn(e.getMessage(), e); + } + throw e; + } catch (RuntimeException e) { + logger.warn(e.getMessage(), e); + throw e; + } catch (VirtualMachineError err) { + SystemFailure.initiateFailure(err); + // If this ever returns, rethrow the error. We're poisoned + // now, so don't let this thread continue. + throw err; + } catch (Error e) { + // Whenever you catch Error or Throwable, you must also + // catch VirtualMachineError (see above). However, there is + // _still_ a possibility that you are dealing with a cascading + // error condition, so you also need to check to see if the JVM + // is still usable: + SystemFailure.checkFailure(); + logger.error(e.getMessage(), e); + throw e; + } + } + + public static ObjectName[] manageStats(SystemMemberJmx member) + throws AdminException, MalformedObjectNameException { + try { + StatisticResource[] stats = member.getStats(); + ObjectName[] onames = new ObjectName[stats.length]; + for (int i = 0; i < stats.length; i++) { + StatisticResourceJmxImpl stat = (StatisticResourceJmxImpl) stats[i]; + onames[i] = ObjectName.getInstance(stat.getMBeanName()); + } + return onames; + } catch (AdminException e) { + logger.warn(e.getMessage(), e); + throw e; + } catch (RuntimeException e) { + logger.warn(e.getMessage(), e); + throw e; + } catch (VirtualMachineError err) { + SystemFailure.initiateFailure(err); + // If this ever returns, rethrow the error. We're poisoned + // now, so don't let this thread continue. + throw err; + } catch (Error e) { + // Whenever you catch Error or Throwable, you must also + // catch VirtualMachineError (see above). However, there is + // _still_ a possibility that you are dealing with a cascading + // error condition, so you also need to check to see if the JVM + // is still usable: + SystemFailure.checkFailure(); + logger.error(e.getMessage(), e); + throw e; + } + } + + public static ObjectName[] manageStat(SystemMemberJmx member, String statisticsTypeName) + throws AdminException, MalformedObjectNameException { + try { + StatisticResource[] stats = member.getStat(statisticsTypeName); + if (stats == null) + return null; + else { + ObjectName[] statNames = new ObjectName[stats.length]; + for (int i = 0; i < stats.length; i++) { + StatisticResourceJmxImpl statJMX = (StatisticResourceJmxImpl) stats[i]; + statNames[i] = ObjectName.getInstance(statJMX.getMBeanName()); + } + return statNames; + } + } catch (AdminException e) { + logger.warn(e.getMessage(), e); + throw e; + } catch (RuntimeException e) { + logger.warn(e.getMessage(), e); + throw e; + } catch (Error e) { + logger.error(e.getMessage(), e); + throw e; + } + } + + public static void handleNotification(SystemMemberJmx member, Notification notification, + Object hb) { + if (RefreshNotificationType.SYSTEM_MEMBER_CONFIG.getType().equals(notification.getType()) + && ((ManagedResource) member).getMBeanName().equals(notification.getUserData())) { + + try { + member.refreshConfig(); + + } catch (AdminException e) { + logger.warn(e.getMessage(), e); + } catch (OperationCancelledException e) { + // underlying resource is no longer reachable by remote admin + logger.warn(e.getMessage(), e); + member._setRefreshInterval(0); + + } catch (java.lang.RuntimeException e) { + logger.warn(e.getMessage(), e); // dead in water, print, and then ignore + member._setRefreshInterval(0); // zero out to avoid more exceptions + + } catch (VirtualMachineError err) { + SystemFailure.initiateFailure(err); + // If this ever returns, rethrow the error. We're poisoned + // now, so don't let this thread continue. + throw err; + } catch (java.lang.Error e) { + // Whenever you catch Error or Throwable, you must also + // catch VirtualMachineError (see above). However, there is + // _still_ a possibility that you are dealing with a cascading + // error condition, so you also need to check to see if the JVM + // is still usable: + SystemFailure.checkFailure(); + logger.error(e.getMessage(), e); // dead in water, print, and then ignore + member._setRefreshInterval(0); // zero out to avoid more exceptions + } + } + } + + public static ManagedBean addDynamicAttributes(SystemMemberJmx member, ManagedBean managed) + throws AdminException { + + if (managed == null) { + throw new IllegalArgumentException( + LocalizedStrings.SystemMemberJmx_MANAGEDBEAN_IS_NULL.toLocalizedString()); + } + + member.refreshConfig(); // to get the config parms... + + // need to create a new instance of ManagedBean to clean the "slate"... + ManagedBean newManagedBean = new DynamicManagedBean(managed); + ConfigurationParameter[] params = member.getConfiguration(); + for (int i = 0; i < params.length; i++) { + ConfigurationParameterJmxImpl parm = (ConfigurationParameterJmxImpl) params[i]; + ConfigAttributeInfo attrInfo = new ConfigAttributeInfo(parm); + + attrInfo.setName(parm.getName()); + attrInfo.setDisplayName(parm.getName()); + attrInfo.setDescription(parm.getDescription()); + attrInfo.setType(parm.getJmxValueType().getName()); + + attrInfo.setIs(false); + attrInfo.setReadable(true); + attrInfo.setWriteable(parm.isModifiable()); + + newManagedBean.addAttribute(attrInfo); + } + return newManagedBean; + } + + /** + * Returns the next notification sequence number. + * + * @return the notificationSequenceNumber + */ + /* default */static int getNextNotificationSequenceNumber() { + return notificationSequenceNumber.incrementAndGet(); + } + + /** + * Returns the cache event details extracted from the given SystemMemberCacheEvent + * + * @param event SystemMemberCacheEvent instance + * @return the cache event details extracted from the given SystemMemberCacheEvent + */ + /* default */static String getCacheEventDetails(SystemMemberCacheEvent event) { + String memberId = event.getMemberId(); + Operation operation = event.getOperation(); + + return "CacheEvent[MemberId: " + memberId + ", operation: " + operation + "]"; + } + + /** + * Returns the region event details extracted from the given SystemMemberRegionEvent + * + * @param event SystemMemberRegionEvent instance + * @return the cache event details extracted from the given SystemMemberRegionEvent + */ + /* default */static String getRegionEventDetails(SystemMemberRegionEvent event) { + String memberId = event.getMemberId(); + Operation operation = event.getOperation(); + + return "RegionEvent[MemberId: " + memberId + ", operation: " + operation + ", region:" + + event.getRegionPath() + "]"; + } + + /** + * Sends the given notification. + * + * @param notif notification to send + * + * @throws NullPointerException if resource or ModelMBean for resource is null + */ + /* default */static void sendNotification(ManagedResource resource, Notification notif) { + try { + if (MBeanUtil.isRegistered(resource.getObjectName())) { + resource.getModelMBean().sendNotification(notif); + if (logger.isDebugEnabled()) { + logger.debug("Sent '{}' notification", notif.getType()); + } + } + } catch (RuntimeOperationsException e) { + logger + .info( + LocalizedMessage.create( + LocalizedStrings.SystemMemberJmx_FAILED_TO_SEND_0_NOTIFICATION_FOR_1, + new Object[] {"'" + notif.getType() + "'", "'" + notif.getMessage() + "'"}), + e); + } catch (MBeanException e) { + logger + .info( + LocalizedMessage.create( + LocalizedStrings.SystemMemberJmx_FAILED_TO_SEND_0_NOTIFICATION_FOR_1, + new Object[] {"'" + notif.getType() + "'", "'" + notif.getMessage() + "'"}), + e); + } + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/895fd144/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberJmxImpl.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberJmxImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberJmxImpl.java new file mode 100755 index 0000000..f3a0d75 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberJmxImpl.java @@ -0,0 +1,543 @@ +/* + * 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.internal.admin.api.jmx.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import javax.management.MalformedObjectNameException; +import javax.management.Notification; +import javax.management.ObjectName; +import javax.management.modelmbean.ModelMBean; +import javax.naming.OperationNotSupportedException; + +import org.apache.commons.modeler.ManagedBean; +import org.apache.logging.log4j.Logger; + +import org.apache.geode.internal.admin.api.AdminException; +import org.apache.geode.internal.admin.api.ConfigurationParameter; +import org.apache.geode.internal.admin.api.StatisticResource; +import org.apache.geode.internal.admin.api.SystemMemberCache; +import org.apache.geode.internal.admin.api.SystemMemberCacheEvent; +import org.apache.geode.internal.admin.api.SystemMemberRegionEvent; +import org.apache.geode.internal.admin.api.impl.ConfigurationParameterImpl; +import org.apache.geode.distributed.internal.membership.InternalDistributedMember; +import org.apache.geode.internal.admin.ApplicationVM; +import org.apache.geode.internal.admin.ClientMembershipMessage; +import org.apache.geode.internal.admin.GemFireVM; +import org.apache.geode.internal.admin.StatResource; +import org.apache.geode.internal.admin.api.impl.SystemMemberImpl; +import org.apache.geode.internal.i18n.LocalizedStrings; +import org.apache.geode.internal.logging.LogService; + +/** + * Provides MBean support for managing a SystemMember application. + * <p> + * TODO: refactor to implement SystemMember and delegate to SystemMemberImpl. Wrap all delegate + * calls w/ e.printStackTrace() since the HttpAdaptor devours them + * + * @since GemFire 3.5 + * + */ +public class SystemMemberJmxImpl +extends SystemMemberImpl +implements SystemMemberJmx, javax.management.NotificationListener, ManagedResource { + + private static final Logger logger = LogService.getLogger(); + + /** + * Interval in seconds between refreshes. Value less than one results in no refreshing + */ + private int refreshInterval = 0; + + /** The JMX object name of this managed resource */ + private ObjectName objectName; + + /** Reference to the cache MBean representing a Cache in the Cache VM Member */ + private SystemMemberCacheJmxImpl managedSystemMemberCache; + + /** collection to collect all the resources created for this member */ + private Map<StatResource, StatisticResourceJmxImpl> managedStatisticsResourcesMap = + new HashMap<StatResource, StatisticResourceJmxImpl>(); + + + // ------------------------------------------------------------------------- + // Constructor(s) + // ------------------------------------------------------------------------- + + /** + * Constructs an instance of SystemMemberJmxImpl. + * + * @param system the distributed system this SystemMember is a member of + * @param application the internal admin application to delegate actual work + */ + public SystemMemberJmxImpl(AdminDistributedSystemJmxImpl system, + ApplicationVM application) + throws AdminException { + super(system, application); + initializeMBean(); + } + + /** + * Constructs the instance of SystemMember using the corresponding InternalDistributedMember + * instance of a DS member for the given AdminDistributedSystem. + * + * @param system Current AdminDistributedSystem instance + * @param member InternalDistributedMember instance for which a SystemMember instance is to be + * constructed. + * @throws AdminException if construction of SystemMember fails + * + * @since GemFire 6.5 + */ + protected SystemMemberJmxImpl(AdminDistributedSystemJmxImpl system, + InternalDistributedMember member) throws AdminException { + super(system, member); + initializeMBean(); + } + + /** Create and register the MBean to manage this resource */ + private void initializeMBean() + throws AdminException { + //initialize Managed Resources for stats & cache first. +// initializeManagedResources(); + + this.mbeanName = new StringBuffer("GemFire.Member:id=") + .append(MBeanUtil.makeCompliantMBeanNameProperty(getId())).append(",type=") + .append(MBeanUtil.makeCompliantMBeanNameProperty(getType().getName())).toString(); + + this.objectName = + MBeanUtil.createMBean(this, addDynamicAttributes(MBeanUtil.lookupManagedBean(this))); + + // Refresh Interval + AdminDistributedSystemJmxImpl sysJmx = (AdminDistributedSystemJmxImpl) system; + if (sysJmx.getRefreshInterval() > 0) + this.refreshInterval = sysJmx.getRefreshInterval(); + } + + // ------------------------------------------------------------------------- + // MBean attributes - accessors/mutators + // ------------------------------------------------------------------------- + + /** + * Gets the interval in seconds between config refreshes + * + * @return the current refresh interval in seconds + */ + public int getRefreshInterval() { + return this.refreshInterval; + } + + /** + * RefreshInterval is now set only through the AdminDistributedSystem property refreshInterval. + * Attempt to set refreshInterval on SystemMemberJmx MBean would result in an + * OperationNotSupportedException Auto-refresh is enabled on demand when a call to refreshConfig + * is made + * + * @param refreshInterval the new refresh interval in seconds + * @deprecated since 6.0 use DistributedSystemConfig.refreshInterval instead + */ + @Deprecated + public void setRefreshInterval(int refreshInterval) throws OperationNotSupportedException { + throw new OperationNotSupportedException( + LocalizedStrings.MANAGED_RESOURCE_REFRESH_INTERVAL_CANT_BE_SET_DIRECTLY + .toLocalizedString()); + } + + /** + * Sets interval in seconds between member config refreshes; zero or less turns off auto + * refreshing. Manual refreshing has no effect on when the next scheduled refresh will occur. + * + * @param refreshInterval the new refresh interval in seconds + */ + public void _setRefreshInterval(int refreshInterval) { + boolean isRegistered = MBeanUtil.isRefreshNotificationRegistered(this, + RefreshNotificationType.SYSTEM_MEMBER_CONFIG); + + if (isRegistered && (getRefreshInterval() == refreshInterval)) + return; + + this.refreshInterval = Helper.setAndReturnRefreshInterval(this, refreshInterval); + } + + // ------------------------------------------------------------------------- + // MBean Operations + // ------------------------------------------------------------------------- + + public void refreshConfig() throws AdminException { + // 1st call to refreshConfig would trigger + // the auto-refresh if an interval is set + if (this.refreshInterval > 0) { + this._setRefreshInterval(this.refreshInterval); + } + + super.refreshConfig(); + } + + /** + * Initializes Cache & Statistics managed resources. + * + * @throws AdminException if initialization of managed resources fails + */ + // private void initializeManagedResources() throws AdminException { + // try { + // manageCache(); + // } catch (MalformedObjectNameException e) { + // throw new + // AdminException(LocalizedStrings.SystemMemberJmxImpl_EXCEPTION_OCCURRED_WHILE_INITIALIZING_0_MBEANS_FOR_1.toLocalizedString( + // new Object[] {"Cache", getId()}), + // e); + // } catch (AdminException ae) { + // if + // (LocalizedStrings.SystemMemberJmx_THIS_SYSTEM_MEMBER_DOES_NOT_HAVE_A_CACHE.toLocalizedString().equals(ae.getMessage())) + // { + // //ignore this exception for a cache-less peer + // } else { + // throw ae; + // } + // } + // try { + // manageStats(); + // } catch (MalformedObjectNameException e) { + // throw new + // AdminException(LocalizedStrings.SystemMemberJmxImpl_EXCEPTION_OCCURRED_WHILE_INITIALIZING_0_MBEANS_FOR_1.toLocalizedString( + // new Object[] {"Statistics", getId()}), + // e); + // } + // } + + /** + * Gets this member's cache. + * + * @return <code>ObjectName</code> for this member's cache + * + * @throws AdminException If this system member does not host a cache + */ + public ObjectName manageCache() throws AdminException, MalformedObjectNameException { + + return Helper.manageCache(this); + } + + /** + * Gets all active StatisticResources for this manager. + * + * @return array of ObjectName instances + */ + public ObjectName[] manageStats() throws AdminException, MalformedObjectNameException { + + return Helper.manageStats(this); + } + + /** + * Gets the active StatisticResources for this manager, based on the typeName as the key + * + * @return ObjectName of StatisticResourceJMX instance + */ + public ObjectName[] manageStat(String statisticsTypeName) + throws AdminException, MalformedObjectNameException { + + return Helper.manageStat(this, statisticsTypeName); + } + + // ------------------------------------------------------------------------- + // JMX Notification listener + // ------------------------------------------------------------------------- + + /** + * Handles notification to refresh. Reacts by refreshing the values of this SystemMember's + * ConfigurationParamaters. Any other notification is ignored. Given notification is handled only + * if there is any JMX client connected to the system. + * + * @param notification the JMX notification being received + * @param hb handback object is unused + */ + public void handleNotification(Notification notification, Object hb) { + AdminDistributedSystemJmxImpl systemJmx = (AdminDistributedSystemJmxImpl) this.system; + + if (!systemJmx.isRmiClientCountZero()) { + Helper.handleNotification(this, notification, hb); + } + } + + // ------------------------------------------------------------------------- + // Template methods overriden from superclass... + // ------------------------------------------------------------------------- + + /** + * Template method for creating instance of ConfigurationParameter. Overridden to return + * ConfigurationParameterJmxImpl. + */ + @Override + protected ConfigurationParameter createConfigurationParameter(String name, String description, + Object value, Class type, boolean userModifiable) { + return new ConfigurationParameterJmxImpl(name, description, value, type, userModifiable); + } + + /** + * Override createStatisticResource by instantiating StatisticResourceJmxImpl if it was not + * created earlier otherwise returns the same instance. + * + * @param stat StatResource reference for which this JMX resource is to be created + * @return StatisticResourceJmxImpl - JMX Implementation of StatisticResource + * @throws AdminException if constructing StatisticResourceJmxImpl instance fails + */ + @Override + protected StatisticResource createStatisticResource(StatResource stat) + throws AdminException { + StatisticResourceJmxImpl managedStatisticResource = null; + + synchronized (this.managedStatisticsResourcesMap) { + /* + * Ensuring that a single instance of Statistic Resource is created per StatResource. + */ + StatisticResourceJmxImpl statisticResourceJmxImpl = managedStatisticsResourcesMap.get(stat); + if (statisticResourceJmxImpl != null) { + managedStatisticResource = statisticResourceJmxImpl; + } else { + managedStatisticResource = new StatisticResourceJmxImpl(stat, this); + managedStatisticResource.getStatistics();// inits timer + managedStatisticsResourcesMap.put(stat, managedStatisticResource); + } + } + return managedStatisticResource; + } + + /** + * Override createSystemMemberCache by instantiating SystemMemberCacheJmxImpl if it was not + * created earlier. + * + * @param vm GemFireVM reference for which this JMX resource is to be created + * @return SystemMemberCacheJmxImpl - JMX Implementation of SystemMemberCache + * @throws AdminException if constructing SystemMemberCacheJmxImpl instance fails + */ + @Override + protected SystemMemberCache createSystemMemberCache(GemFireVM vm) + throws AdminException { + if (managedSystemMemberCache == null) { + managedSystemMemberCache = new SystemMemberCacheJmxImpl(vm); + } + return managedSystemMemberCache; + } + + // ------------------------------------------------------------------------- + // Create MBean attributes for each ConfigurationParameter + // ------------------------------------------------------------------------- + + /** + * Add MBean attribute definitions for each ConfigurationParameter. + * + * @param managed the mbean definition to add attributes to + * @return a new instance of ManagedBean copied from <code>managed</code> but with the new + * attributes added + */ + public ManagedBean addDynamicAttributes(ManagedBean managed) throws AdminException { + + return Helper.addDynamicAttributes(this, managed); + } + + // ------------------------------------------------------------------------- + // ManagedResource implementation + // ------------------------------------------------------------------------- + + /** The name of the MBean that will manage this resource */ + private String mbeanName; + + /** The ModelMBean that is configured to manage this resource */ + private ModelMBean modelMBean; + + public String getMBeanName() { + return this.mbeanName; + } + + public ModelMBean getModelMBean() { + return this.modelMBean; + } + + public void setModelMBean(ModelMBean modelMBean) { + this.modelMBean = modelMBean; + } + + public ObjectName getObjectName() { + return this.objectName; + } + + public ManagedResourceType getManagedResourceType() { + return ManagedResourceType.SYSTEM_MEMBER; + } + + /** + * Un-registers all the statistics & cache managed resource created for this member. After + * un-registering the resource MBean instances, clears managedStatisticsResourcesMap collection. + */ + public void cleanupResource() { + synchronized (this.managedStatisticsResourcesMap) { + ConfigurationParameter[] names = getConfiguration(); + if (names != null) { + for (int i = 0; i < names.length; i++) { + ConfigurationParameter parm = names[i]; + ((ConfigurationParameterImpl) parm).removeConfigurationParameterListener(this); + } + } + this.parms.clear(); + + Collection<StatisticResourceJmxImpl> statisticResources = + managedStatisticsResourcesMap.values(); + + for (StatisticResourceJmxImpl statisticResource : statisticResources) { + MBeanUtil.unregisterMBean(statisticResource); + } + + this.managedStatisticsResourcesMap.clear(); + } + MBeanUtil.unregisterMBean(managedSystemMemberCache); + } + + + /** + * Cleans up Managed Resources created for the client that was connected to the server represented + * by this class. + * + * @param clientId id of the client to be removed + * @return List of ManagedResources associated with the client of given client id + */ + /* + * This clean up is for the clients. The clients are started with a loner DM. Hence the clientId + * is not supposed to contain '/' as per InternalDistributedMember.toString(). + */ + public List<ManagedResource> cleanupBridgeClientResources(String clientId) { + List<ManagedResource> returnedResources = new ArrayList<ManagedResource>(); + + String compatibleId = "id_" + MBeanUtil.makeCompliantMBeanNameProperty(clientId); + synchronized (this.managedStatisticsResourcesMap) { + Set<Entry<StatResource, StatisticResourceJmxImpl>> entrySet = + this.managedStatisticsResourcesMap.entrySet(); + + for (Iterator<Entry<StatResource, StatisticResourceJmxImpl>> it = entrySet.iterator(); it + .hasNext();) { + Entry<StatResource, StatisticResourceJmxImpl> entry = it.next(); + StatisticResourceJmxImpl resource = entry.getValue(); + if (resource.getMBeanName().contains(compatibleId)) { + it.remove(); // remove matching entry + returnedResources.add(resource); + } + } + } + return returnedResources; + } + + /** + * Implementation handles client membership changes. + * + * @param clientId id of the client for whom membership change happened + * @param eventType membership change type; one of {@link ClientMembershipMessage#JOINED}, + * {@link ClientMembershipMessage#LEFT}, {@link ClientMembershipMessage#CRASHED} + */ + public void handleClientMembership(String clientId, int eventType) { + String notifType = null; + List<ManagedResource> cleanedUp = null; + + if (eventType == ClientMembershipMessage.LEFT) { + notifType = NOTIF_CLIENT_LEFT; + cleanedUp = cleanupBridgeClientResources(clientId); + } else if (eventType == ClientMembershipMessage.CRASHED) { + notifType = NOTIF_CLIENT_CRASHED; + cleanedUp = cleanupBridgeClientResources(clientId); + } else if (eventType == ClientMembershipMessage.JOINED) { + notifType = NOTIF_CLIENT_JOINED; + } + + if (cleanedUp != null) { + for (ManagedResource resource : cleanedUp) { + MBeanUtil.unregisterMBean(resource); + } + } + + Helper.sendNotification(this, new Notification(notifType, this.modelMBean, + Helper.getNextNotificationSequenceNumber(), clientId)); + } + + /** + * Implementation handles creation of cache by extracting the details from the given event object + * and sending the {@link SystemMemberJmx#NOTIF_CACHE_CREATED} notification to the connected JMX + * Clients. + * + * @param event event object corresponding to the creation of the cache + */ + public void handleCacheCreate(SystemMemberCacheEvent event) { + Helper.sendNotification(this, new Notification(NOTIF_CACHE_CREATED, this.modelMBean, + Helper.getNextNotificationSequenceNumber(), Helper.getCacheEventDetails(event))); + } + + /** + * Implementation handles closure of cache by extracting the details from the given event object + * and sending the {@link SystemMemberJmx#NOTIF_CACHE_CLOSED} notification to the connected JMX + * Clients. + * + * @param event event object corresponding to the closure of the cache + */ + public void handleCacheClose(SystemMemberCacheEvent event) { + Helper.sendNotification(this, new Notification(NOTIF_CACHE_CLOSED, this.modelMBean, + Helper.getNextNotificationSequenceNumber(), Helper.getCacheEventDetails(event))); + } + + /** + * Implementation handles creation of region by extracting the details from the given event object + * and sending the {@link SystemMemberJmx#NOTIF_REGION_CREATED} notification to the connected JMX + * Clients. Region Path is set as User Data in Notification. + * + * @param event event object corresponding to the creation of a region + */ + public void handleRegionCreate(SystemMemberRegionEvent event) { + Notification notification = new Notification(NOTIF_REGION_CREATED, this.modelMBean, + Helper.getNextNotificationSequenceNumber(), Helper.getRegionEventDetails(event)); + + notification.setUserData(event.getRegionPath()); + + Helper.sendNotification(this, notification); + } + + /** + * Implementation should handle loss of region by extracting the details from the given event + * object and sending the {@link SystemMemberJmx#NOTIF_REGION_LOST} notification to the connected + * JMX Clients. Region Path is set as User Data in Notification. Additionally, it also clears the + * ManagedResources created for the region that is lost. + * + * @param event event object corresponding to the loss of a region + */ + public void handleRegionLoss(SystemMemberRegionEvent event) { + SystemMemberCacheJmxImpl cacheResource = this.managedSystemMemberCache; + + if (cacheResource != null) { + ManagedResource cleanedUp = cacheResource.cleanupRegionResources(event.getRegionPath()); + + if (cleanedUp != null) { + MBeanUtil.unregisterMBean(cleanedUp); + } + } + + Notification notification = new Notification(NOTIF_REGION_LOST, this.modelMBean, + Helper.getNextNotificationSequenceNumber(), Helper.getRegionEventDetails(event)); + + notification.setUserData(event.getRegionPath()); + + Helper.sendNotification(this, notification); + } +} + http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/895fd144/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberRegionJmxImpl.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberRegionJmxImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberRegionJmxImpl.java new file mode 100644 index 0000000..500f0ee --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/jmx/impl/SystemMemberRegionJmxImpl.java @@ -0,0 +1,133 @@ +/* + * 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.internal.admin.api.jmx.impl; + +import org.apache.geode.internal.admin.api.AdminException; +import org.apache.geode.internal.admin.api.SystemMemberRegion; +import org.apache.geode.internal.admin.api.impl.SystemMemberCacheImpl; +import org.apache.geode.cache.Region; +import org.apache.geode.internal.admin.GemFireVM; +import org.apache.geode.internal.admin.api.impl.SystemMemberRegionImpl; + +import javax.management.ObjectName; +import javax.management.modelmbean.ModelMBean; + +/** + * MBean representation of {@link + * SystemMemberRegion}. + * + * @since GemFire 3.5 + */ +public class SystemMemberRegionJmxImpl +extends SystemMemberRegionImpl +implements ManagedResource { + + /** The object name of this managed resource */ + private ObjectName objectName; + + // ------------------------------------------------------------------------- + // Constructor(s) + // ------------------------------------------------------------------------- + + /** + * Constructs an instance of SystemMemberRegionJmxImpl. + * + * @param cache the cache this region belongs to + * @param region internal region to delegate real work to + */ + public SystemMemberRegionJmxImpl(SystemMemberCacheImpl cache, + Region region) + throws AdminException { + super(cache, region); + initializeMBean(cache); + } + + /** Create and register the MBean to manage this resource */ + private void initializeMBean(SystemMemberCacheImpl cache) + throws AdminException { + + GemFireVM vm = cache.getVM(); + this.mbeanName = new StringBuffer("GemFire.Cache:").append("path=") + .append(MBeanUtil.makeCompliantMBeanNameProperty(getFullPath())).append(",name=") + .append(MBeanUtil.makeCompliantMBeanNameProperty(cache.getName())).append(",id=") + .append(cache.getId()).append(",owner=") + .append(MBeanUtil.makeCompliantMBeanNameProperty(vm.getId().toString())) + .append(",type=Region").toString(); + + this.objectName = MBeanUtil.createMBean(this); + } + + // ------------------------------------------------------------------------- + // ManagedResource implementation + // ------------------------------------------------------------------------- + + /** The name of the MBean that will manage this resource */ + private String mbeanName; + + /** The ModelMBean that is configured to manage this resource */ + private ModelMBean modelMBean; + + public String getMBeanName() { + return this.mbeanName; + } + + public ModelMBean getModelMBean() { + return this.modelMBean; + } + + public void setModelMBean(ModelMBean modelMBean) { + this.modelMBean = modelMBean; + } + + public ObjectName getObjectName() { + return this.objectName; + } + + public ManagedResourceType getManagedResourceType() { + return ManagedResourceType.SYSTEM_MEMBER_REGION; + } + + public void cleanupResource() {} + + /** + * Checks equality of the given object with <code>this</code> based on the type (Class) and the + * MBean Name returned by <code>getMBeanName()</code> methods. + * + * @param obj object to check equality with + * @return true if the given object is if the same type and its MBean Name is same as + * <code>this</code> object's MBean Name, false otherwise + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof SystemMemberRegionJmxImpl)) { + return false; + } + + SystemMemberRegionJmxImpl other = (SystemMemberRegionJmxImpl) obj; + + return this.getMBeanName().equals(other.getMBeanName()); + } + + /** + * Returns hash code for <code>this</code> object which is based on the MBean Name generated. + * + * @return hash code for <code>this</code> object + */ + @Override + public int hashCode() { + return this.getMBeanName().hashCode(); + } +} +