[jboss-cvs] JBossCache/src/org/jboss/cache/jmx ...
Brian Stansberry
brian.stansberry at jboss.com
Thu May 10 00:00:23 EDT 2007
User: bstansberry
Date: 07/05/10 00:00:23
Modified: src/org/jboss/cache/jmx CacheJmxWrapper.java
Added: src/org/jboss/cache/jmx CacheNotificationBroadcaster.java
CacheNotificationListener.java
Log:
[JBCACHE-855] CacheMgmtInterceptor no longer handles JMX notifications; CacheJmxWrapper does
Revision Changes Path
1.16 +162 -101 JBossCache/src/org/jboss/cache/jmx/CacheJmxWrapper.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: CacheJmxWrapper.java
===================================================================
RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/jmx/CacheJmxWrapper.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- CacheJmxWrapper.java 9 May 2007 18:31:19 -0000 1.15
+++ CacheJmxWrapper.java 10 May 2007 04:00:23 -0000 1.16
@@ -22,12 +22,14 @@
package org.jboss.cache.jmx;
import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
+import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
@@ -39,10 +41,11 @@
import org.jboss.cache.DefaultCacheFactory;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.config.ConfigurationException;
-import org.jboss.cache.interceptors.CacheMgmtInterceptor;
import org.jboss.cache.interceptors.Interceptor;
-public class CacheJmxWrapper implements CacheJmxWrapperMBean, MBeanRegistration
+public class CacheJmxWrapper
+ extends NotificationBroadcasterSupport
+ implements CacheJmxWrapperMBean, MBeanRegistration, CacheNotificationBroadcaster
{
private Log log = LogFactory.getLog(getClass().getName());
@@ -55,16 +58,24 @@
private boolean created;
private Boolean manageCacheLifecycle;
private boolean registerInterceptors = true;
+ private final AtomicInteger listenerCount = new AtomicInteger(0);
+ private final CacheNotificationListener cacheNotificationListener;
+
+ // ----------------------------------------------------------- Constructors
public CacheJmxWrapper()
{
+ cacheNotificationListener = new CacheNotificationListener(this);
}
public CacheJmxWrapper(Cache cache)
{
+ this();
setCache(cache);
}
+ // --------------------------------------------------- CacheJmxWrapperMBean
+
public org.jboss.cache.Cache getCache()
{
return cache;
@@ -117,50 +128,27 @@
return cache == null ? "Cache is null" : formatHtml(cache.printLockInfo());
}
- public void addNotificationListener(NotificationListener notificationListener, NotificationFilter notificationFilter, Object object) throws IllegalArgumentException
+ public boolean getRegisterInterceptors()
{
- getCacheMgmtInterceptor().addNotificationListener(notificationListener, notificationFilter, object);
+ return registerInterceptors;
}
- public void removeNotificationListener(NotificationListener notificationListener) throws ListenerNotFoundException
+ public void setRegisterInterceptors(boolean register)
{
- getCacheMgmtInterceptor().removeNotificationListener(notificationListener);
+ this.registerInterceptors = register;
}
- public MBeanNotificationInfo[] getNotificationInfo()
+ public boolean getManageCacheLifecycle()
{
- return getCacheMgmtInterceptor().getNotificationInfo();
+ return manageCacheLifecycle == null ? selfConstructed : manageCacheLifecycle.booleanValue();
}
- private CacheMgmtInterceptor getCacheMgmtInterceptor()
- {
- List<Interceptor> interc = cache.getInterceptorChain();
- if (interc != null)
- {
- for (Interceptor i : interc)
+ public void setManageCacheLifecycle(boolean manageCacheLifecycle)
{
- if (i instanceof CacheMgmtInterceptor)
- return (CacheMgmtInterceptor) i;
- }
- }
- throw new RuntimeException("Cache management interceptor not found");
+ this.manageCacheLifecycle = manageCacheLifecycle ? Boolean.TRUE : Boolean.FALSE;
}
- /**
- * Formats a given String for display as an HTML snippet.
- *
- * @param s string to format
- * @return formatted string
- */
- public static String formatHtml(String s)
- {
- s = s.replaceAll("\r\n", "<br />");
- s = s.replaceAll("\r", "<br />");
- s = s.replaceAll("\n", "<br />");
- s = s.replaceAll("\t", " ");
- s = s.replaceAll(" ", " ");
- return s;
- }
+ // -------------------------------------------------------------- Lifecycle
public void create() throws Exception
{
@@ -214,67 +202,7 @@
created = false;
}
- public boolean getRegisterInterceptors()
- {
- return registerInterceptors;
- }
-
- public void setRegisterInterceptors(boolean register)
- {
- this.registerInterceptors = register;
- }
-
- public boolean getManageCacheLifecycle()
- {
- return manageCacheLifecycle == null ? selfConstructed : manageCacheLifecycle.booleanValue();
- }
-
- public void setManageCacheLifecycle(boolean manageCacheLifecycle)
- {
- this.manageCacheLifecycle = manageCacheLifecycle ? Boolean.TRUE : Boolean.FALSE;
- }
-
- protected void constructCache() throws Exception
- {
- log.debug("Constructing Cache");
- setCache(DefaultCacheFactory.getInstance().createCache(config, false));
- selfConstructed = true;
- }
-
- protected boolean registerInterceptors() throws Exception
- {
- if (registerInterceptors && !interceptorsRegistered && server != null)
- {
- log.debug("Registering interceptors");
- List<Interceptor> interc = cache.getInterceptorChain();
- if (interc != null && interc.size() > 0)
- {
- JmxUtil.registerInterceptors(server, interc, cacheObjectName);
- interceptorsRegistered = true;
- return true;
- }
- }
- return false;
- }
-
- protected void unregisterInterceptors()
- {
- if (registerInterceptors && interceptorsRegistered && server != null)
- {
- try
- {
- log.debug("Unreqistering interceptors");
- JmxUtil.unregisterInterceptors(server, cache.getInterceptorChain(), getCacheObjectName());
- interceptorsRegistered = false;
- }
- catch (Exception e)
- {
- log.error("Exception unregistering interceptors from JMX", e);
- }
- }
- }
-
- // -------------------------------------------------------------- MBeanRegistration
+ // ------------------------------------------------------ MBeanRegistration
/**
* Caches the provided <code>server</code> and <code>objName</code>.
@@ -342,7 +270,7 @@
server = null;
}
- // --------------------------------------------------------------- Public methods
+ // --------------------------------------------------------- Public methods
/**
* Sets the configuration that the underlying cache should use.
@@ -370,6 +298,13 @@
// FIXME -- having to cast is ugly!!
this.cache = (CacheImpl) cache;
this.config = (cache == null ? null : cache.getConfiguration());
+ synchronized (listenerCount)
+ {
+ if (listenerCount.get() > 0)
+ {
+ cache.addCacheListener(cacheNotificationListener);
+ }
+ }
}
public String getCacheObjectName()
@@ -391,13 +326,139 @@
this.cacheObjectName = name;
}
- // ------------------------------------------------------ Protected Methods
-
public MBeanServer getMBeanServer()
{
return server;
}
+ /**
+ * Formats a given String for display as an HTML snippet.
+ *
+ * @param s string to format
+ * @return formatted string
+ */
+ public static String formatHtml(String s)
+ {
+ s = s.replaceAll("\r\n", "<br />");
+ s = s.replaceAll("\r", "<br />");
+ s = s.replaceAll("\n", "<br />");
+ s = s.replaceAll("\t", " ");
+ s = s.replaceAll(" ", " ");
+ return s;
+ }
+
+ // ---------------------------------------------------- Superclass Overrides
+
+ @Override
+ public void addNotificationListener(NotificationListener notificationListener, NotificationFilter notificationFilter, Object object) throws IllegalArgumentException
+ {
+ super.addNotificationListener(notificationListener, notificationFilter, object);
+ notificationRegistration(true);
+ }
+
+ @Override
+ public void removeNotificationListener(NotificationListener notificationListener) throws ListenerNotFoundException
+ {
+ super.removeNotificationListener(notificationListener);
+ notificationRegistration(false);
+ }
+
+ @Override
+ public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException
+ {
+ super.removeNotificationListener(listener, filter, handback);
+ notificationRegistration(false);
+ }
+
+ @Override
+ public MBeanNotificationInfo[] getNotificationInfo()
+ {
+ return cacheNotificationListener.getNotificationInfo();
+ }
+
+ // ------------------------------------------------------ Protected Methods
+
+ protected void constructCache() throws Exception
+ {
+ log.debug("Constructing Cache");
+ setCache(DefaultCacheFactory.getInstance().createCache(config, false));
+ selfConstructed = true;
+ }
+
+ protected boolean registerInterceptors() throws Exception
+ {
+ if (registerInterceptors && !interceptorsRegistered && server != null)
+ {
+ log.debug("Registering interceptors");
+ List<Interceptor> interc = cache.getInterceptorChain();
+ if (interc != null && interc.size() > 0)
+ {
+ JmxUtil.registerInterceptors(server, interc, cacheObjectName);
+ interceptorsRegistered = true;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected void unregisterInterceptors()
+ {
+ if (registerInterceptors && interceptorsRegistered && server != null)
+ {
+ try
+ {
+ log.debug("Unreqistering interceptors");
+ JmxUtil.unregisterInterceptors(server, cache.getInterceptorChain(), getCacheObjectName());
+ interceptorsRegistered = false;
+ }
+ catch (Exception e)
+ {
+ log.error("Exception unregistering interceptors from JMX", e);
+ }
+ }
+ }
+
// -------------------------------------------------------- Private methods
+
+ /**
+ * Adds and removes the CacheListener.
+ * A counter is used to determine whether we have any clients who are
+ * registered for notifications from this mbean. When the count is zero,
+ * we don't need to listen to cache events, so we remove the CacheListener.
+ * Note that a client who terminates without unregistering for notifications
+ * will leave the count greater than zero so we'll still listen in that case.
+ *
+ * @param add <code>true</code> if the event was a listerner addition,
+ * <code>false</code> if it was a removal
+ */
+ private void notificationRegistration(boolean add)
+ {
+ // This method adds and removes the CacheImpl listener.
+ // The m_listeners counter is used to determine whether
+ // we have any clients who are registered for notifications
+ // from this mbean. When the count is zero, we don't need to
+ // listen to cache events. Note that a client who terminates
+ // without unregistering for notifications will leave the count
+ // greater than zero so we'll still listen in that case.
+ synchronized (listenerCount)
+ {
+ if (add)
+ {
+ listenerCount.incrementAndGet();
+ if (cache != null)
+ cache.addCacheListener(cacheNotificationListener);
+ }
+ else
+ {
+ if (listenerCount.decrementAndGet() <= 0)
+ {
+ if (cache != null)
+ cache.removeCacheListener(cacheNotificationListener);
+
+ listenerCount.set(0);
+ }
+ }
+ }
+ }
}
1.1 date: 2007/05/10 04:00:23; author: bstansberry; state: Exp;JBossCache/src/org/jboss/cache/jmx/CacheNotificationBroadcaster.java
Index: CacheNotificationBroadcaster.java
===================================================================
package org.jboss.cache.jmx;
import javax.management.Notification;
import javax.management.NotificationEmitter;
public interface CacheNotificationBroadcaster extends NotificationEmitter
{
// Notification Types
public static final String
NOTIF_CACHE_STARTED = "org.jboss.cache.CacheStarted",
NOTIF_CACHE_STOPPED = "org.jboss.cache.CacheStopped",
NOTIF_NODE_CREATED = "org.jboss.cache.NodeCreated",
NOTIF_NODE_MODIFIED = "org.jboss.cache.NodeModified",
NOTIF_NODE_REMOVED = "org.jboss.cache.NodeRemoved",
NOTIF_NODE_MOVED = "org.jboss.cache.NodeMoved",
NOTIF_NODE_VISITED = "org.jboss.cache.NodeVisited",
NOTIF_NODE_EVICTED = "org.jboss.cache.NodeEvicted",
NOTIF_NODE_LOADED = "org.jboss.cache.NodeLoaded",
NOTIF_NODE_ACTIVATED = "org.jboss.cache.NodeActivated",
NOTIF_NODE_PASSIVATED = "org.jboss.cache.NodePassivated",
NOTIF_VIEW_CHANGED = "org.jboss.cache.ViewChanged";
/**
* Sends a notification to any interested NotificationListener.
*
* @param notification the notification to send
*/
void sendNotification(Notification notification);
}
1.1 date: 2007/05/10 04:00:23; author: bstansberry; state: Exp;JBossCache/src/org/jboss/cache/jmx/CacheNotificationListener.java
Index: CacheNotificationListener.java
===================================================================
/*
* JBoss, Home of Professional Open Source.
* Copyright 2006, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.cache.jmx;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import javax.management.MBeanNotificationInfo;
import javax.management.Notification;
import org.jboss.cache.CacheListener;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.Fqn;
import org.jgroups.View;
/**
* A {@link CacheListener} that creates JMX notifications from listener
* events.
*
* @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
* @version $Revision: 1.1 $
*/
class CacheNotificationListener implements CacheListener
{
// Notification Messages
private static final String MSG_CACHE_STARTED = "Cache has been started.";
private static final String MSG_CACHE_STOPPED = "Cache has been stopped.";
private static final String MSG_NODE_CREATED = "Node has been created.";
private static final String MSG_NODE_MODIFIED = "Node has been modifed.";
private static final String MSG_NODE_REMOVED = "Node has been removed.";
private static final String MSG_NODE_MOVED = "Node has been moved.";
private static final String MSG_NODE_VISITED = "Node has been visited.";
private static final String MSG_NODE_EVICTED = "Node has been evicted.";
private static final String MSG_NODE_LOADED = "Node has been loaded.";
private static final String MSG_NODE_ACTIVATED = "Node has been activated.";
private static final String MSG_NODE_PASSIVATED = "Node has been passivated.";
private static final String MSG_VIEW_CHANGED = "Cache cluster view has changed.";
// Notification Info
private static final String NOTIFICATION_NAME = Notification.class.getName();
private static final String NOTIFICATION_DESCR = "JBossCache event notifications";
private final CacheNotificationBroadcaster broadcaster;
private final AtomicLong sequence = new AtomicLong(0);
private String serviceName;
// ------------------------------------------------------------ Constructors
CacheNotificationListener(CacheNotificationBroadcaster support)
{
this.broadcaster = support;
}
// ----------------------------------------------------------- PublicMethods
public String getServiceName()
{
return serviceName;
}
public void setServiceName(String serviceName)
{
this.serviceName = serviceName;
}
public MBeanNotificationInfo[] getNotificationInfo()
{
String[] types = new String[]
{
CacheNotificationBroadcaster.NOTIF_CACHE_STARTED,
CacheNotificationBroadcaster.NOTIF_CACHE_STOPPED,
CacheNotificationBroadcaster.NOTIF_NODE_CREATED,
CacheNotificationBroadcaster.NOTIF_NODE_EVICTED,
CacheNotificationBroadcaster.NOTIF_NODE_LOADED,
CacheNotificationBroadcaster.NOTIF_NODE_MODIFIED,
CacheNotificationBroadcaster.NOTIF_NODE_ACTIVATED,
CacheNotificationBroadcaster.NOTIF_NODE_PASSIVATED,
CacheNotificationBroadcaster.NOTIF_NODE_REMOVED,
CacheNotificationBroadcaster.NOTIF_NODE_VISITED,
CacheNotificationBroadcaster.NOTIF_VIEW_CHANGED
};
MBeanNotificationInfo info = new MBeanNotificationInfo(types, NOTIFICATION_NAME, NOTIFICATION_DESCR);
return new MBeanNotificationInfo[]{info};
}
// ----------------------------------------------------------- CacheListener
public void cacheStarted(CacheSPI cache)
{
Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_CACHE_STARTED, broadcaster, seq(), MSG_CACHE_STARTED);
n.setUserData(cache.getConfiguration().getServiceName());
broadcaster.sendNotification(n);
}
public void cacheStopped(CacheSPI cache)
{
Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_CACHE_STOPPED, broadcaster, seq(), MSG_CACHE_STOPPED);
n.setUserData(cache.getConfiguration().getServiceName());
broadcaster.sendNotification(n);
}
public void nodeCreated(Fqn fqn, boolean pre, boolean isLocal)
{
Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_CREATED, broadcaster, seq(), MSG_NODE_CREATED);
n.setUserData(new Object[]{fqn.toString(), pre, isLocal});
broadcaster.sendNotification(n);
}
public void nodeEvicted(Fqn fqn, boolean pre, boolean isLocal)
{
Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_EVICTED, broadcaster, seq(), MSG_NODE_EVICTED);
n.setUserData(new Object[]{fqn.toString(), pre, isLocal});
broadcaster.sendNotification(n);
}
public void nodeLoaded(Fqn fqn, boolean pre, Map data)
{
Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_LOADED, broadcaster, seq(), MSG_NODE_LOADED);
n.setUserData(new Object[]{fqn.toString(), pre});
broadcaster.sendNotification(n);
}
public void nodeModified(Fqn fqn, boolean pre, boolean isLocal, ModificationType modType, Map data)
{
Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_MODIFIED, broadcaster, seq(), MSG_NODE_MODIFIED);
n.setUserData(new Object[]{fqn.toString(), pre, isLocal});
broadcaster.sendNotification(n);
}
public void nodeRemoved(Fqn fqn, boolean pre, boolean isLocal, Map data)
{
Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_REMOVED, broadcaster, seq(), MSG_NODE_REMOVED);
n.setUserData(new Object[]{fqn.toString(), pre, isLocal});
broadcaster.sendNotification(n);
}
public void nodeMoved(Fqn from, Fqn to, boolean pre, boolean isLocal)
{
Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_MOVED, broadcaster, seq(), MSG_NODE_MOVED);
n.setUserData(new Object[]{from.toString(), to.toString(), pre});
broadcaster.sendNotification(n);
}
public void nodeVisited(Fqn fqn, boolean pre)
{
Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_VISITED, broadcaster, seq(), MSG_NODE_VISITED);
n.setUserData(new Object[]{fqn.toString(), pre});
broadcaster.sendNotification(n);
}
public void viewChange(View view)
{
Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_VIEW_CHANGED, broadcaster, seq(), MSG_VIEW_CHANGED);
n.setUserData(view.toString());
broadcaster.sendNotification(n);
}
public void nodeActivated(Fqn fqn, boolean pre)
{
Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_ACTIVATED, broadcaster, seq(), MSG_NODE_ACTIVATED);
n.setUserData(new Object[]{fqn.toString(), pre});
broadcaster.sendNotification(n);
}
public void nodePassivated(Fqn fqn, boolean pre)
{
Notification n = new Notification(CacheNotificationBroadcaster.NOTIF_NODE_PASSIVATED, broadcaster, seq(), MSG_NODE_PASSIVATED);
n.setUserData(new Object[]{fqn.toString(), pre});
broadcaster.sendNotification(n);
}
private long seq()
{
return sequence.getAndIncrement();
}
}
More information about the jboss-cvs-commits
mailing list