org.apache.geode.admin.jmx.internal.SystemMemberJmx.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.geode.admin.jmx.internal.SystemMemberJmx.java

Source

/*
 * 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 org.apache.geode.SystemFailure;
import org.apache.geode.admin.*;
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.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 (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(
                        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);
            }
        }
    }
}