package org.jboss.monitor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import org.jboss.naming.NonSerializableFactory;
import org.jboss.system.ServiceMBeanSupport;
public class EntityLockMonitor extends ServiceMBeanSupport
implements EntityLockMonitorMBean
{
public static final String JNDI_NAME = "EntityLockMonitor";
protected HashMap monitorMap = new HashMap();
protected long contenders = 0;
protected long maxContenders = 0;
protected ArrayList times = new ArrayList();
protected long contentions = 0;
protected long totalTime = 0;
protected long sumContenders = 0;
public EntityLockMonitor()
{
}
protected void startService()
throws Exception
{
bind();
log.info("EntityLockMonitor started");
}
protected void stopService() {
try
{
unbind();
}
catch (Exception ignored) {}
log.info("EntityLockMonitor stopped");
}
public synchronized long getAverageContenders()
{
if (contentions == 0)
{
return 0;
}
else
{
return sumContenders / contentions;
}
}
public synchronized long getMaxContenders()
{
return maxContenders;
}
public synchronized long getMedianWaitTime()
{
if (times.size() < 1)
{
return 0;
}
Long[] alltimes = (Long[])times.toArray(new Long[times.size()]);
long[] thetimes = new long[alltimes.length];
for (int i = 0; i < thetimes.length; i++)
{
thetimes[i] = alltimes[i].longValue();
}
Arrays.sort(thetimes);
return thetimes[thetimes.length / 2];
}
public synchronized long getTotalContentions()
{
return contentions;
}
public Set listMonitoredBeans()
{
synchronized(monitorMap)
{
return new TreeSet(monitorMap.keySet());
}
}
public LockMonitor getLockMonitor(String jndiName)
{
synchronized(monitorMap)
{
return (LockMonitor)monitorMap.get(jndiName);
}
}
public String printLockMonitor()
{
StringBuffer rtn = new StringBuffer();
rtn.append("<table width=\"1\" border=\"1\">");
rtn.append("<tr><td><b>EJB JNDI-NAME</b></td><td><b>Total Lock Time</b></td><td><b>Num Contentions</b></td><td><b>Time Outs</b></td><td><b>Max Contenders</b></td></tr>");
synchronized(monitorMap)
{
Iterator it = monitorMap.keySet().iterator();
while (it.hasNext())
{
rtn.append("<tr>");
String jndiName = (String)it.next();
rtn.append("<td>");
rtn.append(jndiName);
rtn.append("</td>");
LockMonitor lm = (LockMonitor)monitorMap.get(jndiName);
rtn.append("<td>");
rtn.append(("" + lm.getTotalTime()));
rtn.append("</td><td>");
rtn.append(("" + lm.getNumContentions()));
rtn.append("</td><td>");
rtn.append(("" + lm.getTimeouts()));
rtn.append("</td><td>");
rtn.append(("" + lm.getMaxContenders()));
rtn.append("</td></tr>");
}
}
rtn.append("</table>");
return rtn.toString();
}
public synchronized void clearMonitor()
{
contenders = 0;
maxContenders = 0;
times.clear();
contentions = 0;
totalTime = 0;
sumContenders = 0;
synchronized(monitorMap)
{
Iterator it = monitorMap.keySet().iterator();
while (it.hasNext())
{
String jndiName = (String)it.next();
LockMonitor lm = (LockMonitor)monitorMap.get(jndiName);
lm.reset();
}
}
}
public synchronized void incrementContenders()
{
++contenders;
++contentions;
sumContenders += contenders;
if (contenders > maxContenders)
{
maxContenders = contenders;
}
}
public synchronized void decrementContenders(long time)
{
times.add(new Long(time));
--contenders;
}
public LockMonitor getEntityLockMonitor(String jndiName)
{
LockMonitor lm = null;
synchronized(monitorMap)
{
lm = (LockMonitor)monitorMap.get(jndiName);
if (lm == null)
{
lm = new LockMonitor(this);
monitorMap.put(jndiName, lm);
}
}
return lm;
}
private void bind() throws NamingException
{
Context ctx = new InitialContext();
NonSerializableFactory.bind(JNDI_NAME, this);
StringRefAddr addr = new StringRefAddr("nns", JNDI_NAME);
Reference ref = new Reference(EntityLockMonitor.class.getName(), addr, NonSerializableFactory.class.getName(), null);
ctx.bind(JNDI_NAME, ref);
}
private void unbind() throws NamingException
{
new InitialContext().unbind(JNDI_NAME);
NonSerializableFactory.unbind(JNDI_NAME);
}
}