All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.ehcache.management.sampled.SampledMBeanRegistrationProvider Maven / Gradle / Ivy

/**
 *  Copyright Terracotta, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package net.sf.ehcache.management.sampled;

import java.lang.management.ManagementFactory;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;

import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Status;
import net.sf.ehcache.event.CacheManagerEventListener;
import net.sf.ehcache.hibernate.management.impl.BaseEmitterBean;
import net.sf.ehcache.management.provider.MBeanRegistrationProvider;
import net.sf.ehcache.management.provider.MBeanRegistrationProviderException;
import net.sf.ehcache.terracotta.ClusteredInstanceFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * An implementation of {@link MBeanRegistrationProvider} which registers
 * sampled MBeans for the CacheManager and its Caches.
 * This also implements {@link CacheManagerEventListener} to add/remove/cleanup
 * MBeans for new caches added or removed
 *
 * 

* * @author Abhishek Sanoujam * @since 1.7 */ public class SampledMBeanRegistrationProvider implements MBeanRegistrationProvider, CacheManagerEventListener { private static final Logger LOG = LoggerFactory.getLogger(SampledMBeanRegistrationProvider.class.getName()); private static final int MAX_MBEAN_REGISTRATION_RETRIES = 50; private Status status = Status.STATUS_UNINITIALISED; private CacheManager cacheManager; private String clientUUID; private final MBeanServer mBeanServer; private final Map mbeans = new ConcurrentHashMap(); // name of the cacheManager when the mbeans are registered. // On cacheManager.dispose(), need to remove // the mbean with the name used while registering the mbean. // Avoid leaking mbeans when user changes name of the cacheManager after // construction // by doing setName() private volatile String registeredCacheManagerName; private SampledCacheManager cacheManagerMBean; /** * Default constructor */ public SampledMBeanRegistrationProvider() { this.mBeanServer = ManagementFactory.getPlatformMBeanServer(); } /** * {@inheritDoc} */ public synchronized void initialize(CacheManager cacheManagerParam, ClusteredInstanceFactory clusteredInstanceFactory) { if (isAlive()) { return; } status = Status.STATUS_ALIVE; this.cacheManager = cacheManagerParam; this.clientUUID = clusteredInstanceFactory == null ? "" : clusteredInstanceFactory.getUUID(); try { cacheManagerMBean = new SampledCacheManager(cacheManager); registerCacheManagerMBean(cacheManagerMBean); } catch (Exception e) { status = Status.STATUS_UNINITIALISED; throw new CacheException(e); } // setup event listener so that addition of new caches registers // corresponding Cache MBeans cacheManager.getCacheManagerEventListenerRegistry().registerListener(this); } private void registerCacheManagerMBean(SampledCacheManager cacheManagerMBean) throws Exception { int tries = 0; boolean success = false; Exception exception = null; do { this.registeredCacheManagerName = cacheManager.getName(); if (tries != 0) { registeredCacheManagerName += "_" + tries; } try { // register the CacheManager MBean ObjectName cacheManagerObjectName = SampledEhcacheMBeans.getCacheManagerObjectName(clientUUID, registeredCacheManagerName); mBeanServer.registerMBean(cacheManagerMBean, cacheManagerObjectName); mbeans.put(cacheManagerObjectName, cacheManagerMBean); success = true; cacheManagerMBean.setMBeanRegisteredName(registeredCacheManagerName); break; } catch (InstanceAlreadyExistsException e) { success = false; exception = e; } tries++; } while (tries < MAX_MBEAN_REGISTRATION_RETRIES); if (!success) { throw new Exception("Cannot register mbean for CacheManager with name" + cacheManager.getName() + " after " + MAX_MBEAN_REGISTRATION_RETRIES + " retries. Last tried name=" + registeredCacheManagerName, exception); } // register Cache MBeans for the caches String[] caches = cacheManager.getCacheNames(); for (String cacheName : caches) { Ehcache cache = cacheManager.getEhcache(cacheName); registerCacheMBean(cache); registerStoreMBean(cache); } } /** * {@inheritDoc} */ public synchronized void reinitialize(ClusteredInstanceFactory clusteredInstanceFactory) throws MBeanRegistrationProviderException { dispose(); initialize(this.cacheManager, clusteredInstanceFactory); } /** * {@inheritDoc} */ public synchronized boolean isInitialized() { return status == Status.STATUS_ALIVE; } /** * CacheManagerEventListener.init() - no need to do anything here */ public void init() throws CacheException { // no-op } // no need to worry about duplicate cache names // cache manager does not allow duplicate cache names // and as cache manager mbeans names are unique, the mbeans for the caches // will also be unique private void registerCacheMBean(Ehcache cache) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { // enable sampled stats if (cache.isStatisticsEnabled()) { cache.setSampledStatisticsEnabled(true); } SampledCache terracottaCacheMBean = new SampledCache(cache); try { ObjectName cacheObjectName = SampledEhcacheMBeans.getCacheObjectName(clientUUID, registeredCacheManagerName, terracottaCacheMBean.getImmutableCacheName()); mBeanServer.registerMBean(terracottaCacheMBean, cacheObjectName); mbeans.put(cacheObjectName, terracottaCacheMBean); } catch (MalformedObjectNameException e) { throw new MBeanRegistrationException(e); } } private void registerStoreMBean(Ehcache cache) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { // enable sampled stats Object bean; if (cache instanceof net.sf.ehcache.Cache) { bean = ((net.sf.ehcache.Cache)cache).getStoreMBean(); if (bean != null) { try { ObjectName storeObjectName = SampledEhcacheMBeans.getStoreObjectName(clientUUID, registeredCacheManagerName, cache.getName()); mBeanServer.registerMBean(bean, storeObjectName); mbeans.put(storeObjectName, bean); } catch (MalformedObjectNameException e) { throw new MBeanRegistrationException(e); } } } } /** * Returns the listener status. * * @return the status at the point in time the method is called */ public synchronized Status getStatus() { return status; } /** * Stop the listener and free any resources. Removes registered ObjectNames * * @throws net.sf.ehcache.CacheException * - all exceptions are wrapped in CacheException */ public synchronized void dispose() throws CacheException { if (!isAlive()) { return; } Set registeredObjectNames = mbeans.keySet(); for (ObjectName objectName : registeredObjectNames) { try { if (mBeanServer.isRegistered(objectName)) { mBeanServer.unregisterMBean(objectName); } Object o = mbeans.get(objectName); if (o instanceof BaseEmitterBean) { BaseEmitterBean mbean = (BaseEmitterBean)o; mbean.dispose(); } } catch (Exception e) { LOG.warn("Error unregistering object instance " + objectName + " . Error was " + e.getMessage(), e); } } mbeans.clear(); cacheManager.getCacheManagerEventListenerRegistry().unregisterListener(this); status = Status.STATUS_SHUTDOWN; } /** * Returns true if this {@link SampledMBeanRegistrationProvider} is alive * * @return true if alive otherwise false */ public synchronized boolean isAlive() { return status == Status.STATUS_ALIVE; } /** * Called immediately after a cache has been added and activated. */ public void notifyCacheAdded(String cacheName) { if (!isAlive()) { return; } try { Ehcache cache = cacheManager.getEhcache(cacheName); registerCacheMBean(cache); registerStoreMBean(cache); } catch (Exception e) { LOG.warn("Error registering cache for management for " + cacheName + " . Error was " + e.getMessage(), e); } } /** * Called immediately after a cache has been disposed and removed. The * calling method will block until this method * returns. * * @param cacheName * the name of the Cache the operation relates to */ public void notifyCacheRemoved(String cacheName) { if (!isAlive()) { return; } ObjectName objectName = null; try { objectName = SampledEhcacheMBeans.getCacheObjectName(clientUUID, registeredCacheManagerName, cacheName); if (mBeanServer.isRegistered(objectName)) { mBeanServer.unregisterMBean(objectName); } } catch (Exception e) { LOG.warn("Error unregistering cache for management for " + objectName + " . Error was " + e.getMessage(), e); } try { ObjectName storeObjectName = SampledEhcacheMBeans.getStoreObjectName(clientUUID, registeredCacheManagerName, cacheName); if (mBeanServer.isRegistered(storeObjectName)) { mBeanServer.unregisterMBean(storeObjectName); } } catch (Exception e) { LOG.warn("Error unregistering cache for management for " + objectName + " . Error was " + e.getMessage(), e); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy