blob: ba1338fcb37c082548a53064e37a92fd8e2a790c [file] [log] [blame]
/*
* 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 java.util.concurrent.atomic.AtomicInteger;
import javax.management.MBeanException;
import javax.management.MalformedObjectNameException;
import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.RuntimeOperationsException;
import javax.naming.OperationNotSupportedException;
import org.apache.commons.modeler.ManagedBean;
import org.apache.logging.log4j.Logger;
import org.apache.geode.SystemFailure;
import org.apache.geode.admin.AdminException;
import org.apache.geode.admin.ConfigurationParameter;
import org.apache.geode.admin.OperationCancelledException;
import org.apache.geode.admin.StatisticResource;
import org.apache.geode.admin.SystemMember;
import org.apache.geode.admin.SystemMemberCache;
import org.apache.geode.admin.SystemMemberCacheEvent;
import org.apache.geode.admin.SystemMemberRegionEvent;
import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.cache.Operation;
import org.apache.geode.internal.admin.ClientMembershipMessage;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.util.internal.GeodeGlossary;
/**
* Defines methods that all <code>SystemMember</code> MBeans should implement.
*
* @since GemFire 4.0
*/
@Deprecated
public interface SystemMemberJmx extends SystemMember, NotificationListener {
/**
* Notification type for indicating a cache got created on a member of this distributed system.
*/
String NOTIF_CACHE_CREATED =
GeodeGlossary.GEMFIRE_PREFIX + "distributedsystem.cache.created";
/**
* Notification type for indicating a cache is closed on a member of this distributed system.
*/
String NOTIF_CACHE_CLOSED = GeodeGlossary.GEMFIRE_PREFIX + "distributedsystem.cache.closed";
/**
* Notification type for indicating a region is created in a cache on a member of this distributed
* system.
*/
String NOTIF_REGION_CREATED =
GeodeGlossary.GEMFIRE_PREFIX + "distributedsystem.cache.region.created";
/**
* Notification type for indicating a region was removed from a cache on a member of this
* distributed system.
*/
String NOTIF_REGION_LOST =
GeodeGlossary.GEMFIRE_PREFIX + "distributedsystem.cache.region.lost";
/** Notification type for indicating client joined */
String NOTIF_CLIENT_JOINED =
GeodeGlossary.GEMFIRE_PREFIX + "distributedsystem.cache.client.joined";
/** Notification type for indicating client left */
String NOTIF_CLIENT_LEFT =
GeodeGlossary.GEMFIRE_PREFIX + "distributedsystem.cache.client.left";
/** Notification type for indicating client crashed */
String NOTIF_CLIENT_CRASHED =
GeodeGlossary.GEMFIRE_PREFIX + "distributedsystem.cache.client.crashed";
/**
* Gets the interval in seconds between config refreshes
*
* @return the current refresh interval in seconds
*/
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
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.
*/
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
*/
ObjectName manageCache() throws AdminException, MalformedObjectNameException;
/**
* Gets all active StatisticResources for this manager.
*
* @return array of ObjectName instances
*/
ObjectName[] manageStats() throws AdminException, MalformedObjectNameException;
/**
* Gets the active StatisticResources for this manager, based on the typeName as the key
*
* @return ObjectName of StatisticResourceJMX instance
*/
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
*/
@Override
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
*/
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
*/
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
*/
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
*/
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
*/
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}
*/
void handleClientMembership(String clientId, int eventType);
////////////////////// Inner Classess //////////////////////
/**
* A helper class that provides implementation of the <code>SystemMemberJmx</code> interface as
* static methods.
*/
class Helper {
private static final Logger logger = LogService.getLogger();
@MakeNotStatic
private static final AtomicInteger notificationSequenceNumber = new AtomicInteger();
public static int setAndReturnRefreshInterval(SystemMemberJmx member, int refreshInterval) {
int ret = refreshInterval;
try {
MBeanUtils.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(
"This System Member does not have a Cache.");
}
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 (org.apache.geode.admin.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(
"ManagedBean is null");
}
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 (final ConfigurationParameter param : params) {
ConfigurationParameterJmxImpl parm = (ConfigurationParameterJmxImpl) param;
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 (MBeanUtils.isRegistered(resource.getObjectName())) {
resource.getModelMBean().sendNotification(notif);
if (logger.isDebugEnabled()) {
logger.debug("Sent '{}' notification", notif.getType());
}
}
} catch (RuntimeOperationsException e) {
logger
.info(String.format("Failed to send %s notification for %s",
"'" + notif.getType() + "'", "'" + notif.getMessage() + "'"),
e);
} catch (MBeanException e) {
logger
.info(String.format("Failed to send %s notification for %s",
"'" + notif.getType() + "'", "'" + notif.getMessage() + "'"),
e);
}
}
}
}