Issue #298 spin-locked in MBeanContainer

protected the _beans map with a Lock
This commit is contained in:
Greg Wilkins 2016-02-17 16:05:28 +01:00
parent ba132dfb0f
commit 5ddb176f6b
1 changed files with 70 additions and 54 deletions

View File

@ -37,6 +37,7 @@ import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Locker;
/** /**
* Container class for the MBean instances * Container class for the MBean instances
@ -51,6 +52,7 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
__unique.clear(); __unique.clear();
} }
private final Locker _lock = new Locker();
private final MBeanServer _mbeanServer; private final MBeanServer _mbeanServer;
private final WeakHashMap<Object, ObjectName> _beans = new WeakHashMap<Object, ObjectName>(); private final WeakHashMap<Object, ObjectName> _beans = new WeakHashMap<Object, ObjectName>();
private String _domain = null; private String _domain = null;
@ -63,8 +65,11 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
*/ */
public synchronized ObjectName findMBean(Object object) public synchronized ObjectName findMBean(Object object)
{ {
ObjectName bean = _beans.get(object); try (Locker.Lock lock = _lock.lock())
return bean == null ? null : bean; {
ObjectName bean = _beans.get(object);
return bean == null ? null : bean;
}
} }
/** /**
@ -75,11 +80,14 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
*/ */
public synchronized Object findBean(ObjectName oname) public synchronized Object findBean(ObjectName oname)
{ {
for (Map.Entry<Object, ObjectName> entry : _beans.entrySet()) try (Locker.Lock lock = _lock.lock())
{ {
ObjectName bean = entry.getValue(); for (Map.Entry<Object, ObjectName> entry : _beans.entrySet())
if (bean.equals(oname)) {
return entry.getKey(); ObjectName bean = entry.getValue();
if (bean.equals(oname))
return entry.getKey();
}
} }
return null; return null;
} }
@ -130,32 +138,31 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("beanAdded {}->{}",parent,obj); LOG.debug("beanAdded {}->{}",parent,obj);
// Is their an object name for the parent try (Locker.Lock lock = _lock.lock())
ObjectName pname=null;
if (parent!=null)
{ {
pname=_beans.get(parent); // Is their an object name for the parent
if (pname==null) ObjectName pname=null;
if (parent!=null)
{ {
// create the parent bean
beanAdded(null,parent);
pname=_beans.get(parent); pname=_beans.get(parent);
if (pname==null)
{
// create the parent bean
beanAdded(null,parent);
pname=_beans.get(parent);
}
} }
}
// Does an mbean already exist?
// Does an mbean already exist? if (obj == null || _beans.containsKey(obj))
if (obj == null || _beans.containsKey(obj)) return;
return;
try
{
// Create an MBean for the object // Create an MBean for the object
Object mbean = ObjectMBean.mbeanFor(obj); Object mbean = ObjectMBean.mbeanFor(obj);
if (mbean == null) if (mbean == null)
return; return;
ObjectName oname = null; ObjectName oname = null;
if (mbean instanceof ObjectMBean) if (mbean instanceof ObjectMBean)
{ {
@ -171,7 +178,6 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
if (domain == null) if (domain == null)
domain = obj.getClass().getPackage().getName(); domain = obj.getClass().getPackage().getName();
String type = obj.getClass().getName().toLowerCase(Locale.ENGLISH); String type = obj.getClass().getName().toLowerCase(Locale.ENGLISH);
int dot = type.lastIndexOf('.'); int dot = type.lastIndexOf('.');
if (dot >= 0) if (dot >= 0)
@ -183,10 +189,10 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
String context = (mbean instanceof ObjectMBean)?makeName(((ObjectMBean)mbean).getObjectContextBasis()):null; String context = (mbean instanceof ObjectMBean)?makeName(((ObjectMBean)mbean).getObjectContextBasis()):null;
if (context==null && pname!=null) if (context==null && pname!=null)
context=pname.getKeyProperty("context"); context=pname.getKeyProperty("context");
if (context != null && context.length()>1) if (context != null && context.length()>1)
buf.append("context=").append(context).append(","); buf.append("context=").append(context).append(",");
buf.append("type=").append(type); buf.append("type=").append(type);
String name = (mbean instanceof ObjectMBean)?makeName(((ObjectMBean)mbean).getObjectNameBasis()):context; String name = (mbean instanceof ObjectMBean)?makeName(((ObjectMBean)mbean).getObjectNameBasis()):context;
@ -194,7 +200,7 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
buf.append(",").append("name=").append(name); buf.append(",").append("name=").append(name);
String basis = buf.toString(); String basis = buf.toString();
AtomicInteger count = __unique.get(basis); AtomicInteger count = __unique.get(basis);
if (count==null) if (count==null)
{ {
@ -202,7 +208,7 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
if (count==null) if (count==null)
count=__unique.get(basis); count=__unique.get(basis);
} }
oname = ObjectName.getInstance(domain + ":" + basis + ",id=" + count.getAndIncrement()); oname = ObjectName.getInstance(domain + ":" + basis + ",id=" + count.getAndIncrement());
} }
@ -210,7 +216,6 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Registered {}", oinstance.getObjectName()); LOG.debug("Registered {}", oinstance.getObjectName());
_beans.put(obj, oinstance.getObjectName()); _beans.put(obj, oinstance.getObjectName());
} }
catch (Exception e) catch (Exception e)
{ {
@ -223,23 +228,26 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("beanRemoved {}",obj); LOG.debug("beanRemoved {}",obj);
ObjectName bean = _beans.remove(obj); try (Locker.Lock lock = _lock.lock())
if (bean != null)
{ {
try ObjectName bean = _beans.remove(obj);
if (bean != null)
{ {
_mbeanServer.unregisterMBean(bean); try
if (LOG.isDebugEnabled()) {
LOG.debug("Unregistered {}", bean); _mbeanServer.unregisterMBean(bean);
} if (LOG.isDebugEnabled())
catch (javax.management.InstanceNotFoundException e) LOG.debug("Unregistered {}", bean);
{ }
LOG.ignore(e); catch (javax.management.InstanceNotFoundException e)
} {
catch (Exception e) LOG.ignore(e);
{ }
LOG.warn(e); catch (Exception e)
{
LOG.warn(e);
}
} }
} }
} }
@ -258,8 +266,11 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
@Override @Override
public void dump(Appendable out, String indent) throws IOException public void dump(Appendable out, String indent) throws IOException
{ {
ContainerLifeCycle.dumpObject(out,this); try (Locker.Lock lock = _lock.lock())
ContainerLifeCycle.dump(out, indent, _beans.entrySet()); {
ContainerLifeCycle.dumpObject(out,this);
ContainerLifeCycle.dump(out, indent, _beans.entrySet());
}
} }
@Override @Override
@ -270,17 +281,22 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
public void destroy() public void destroy()
{ {
for (ObjectName oname : _beans.values()) try (Locker.Lock lock = _lock.lock())
if (oname!=null) {
for (ObjectName oname : _beans.values())
{ {
try if (oname!=null)
{ {
_mbeanServer.unregisterMBean(oname); try
} {
catch (MBeanRegistrationException | InstanceNotFoundException e) _mbeanServer.unregisterMBean(oname);
{ }
LOG.warn(e); catch (MBeanRegistrationException | InstanceNotFoundException e)
{
LOG.warn(e);
}
} }
} }
}
} }
} }