332937 Added Destroyable Dumpable interfaces and reworked dependent lifecycles, specially of JNDI

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2721 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2011-02-02 01:35:38 +00:00
parent f807e15c77
commit f9458ee5ca
15 changed files with 284 additions and 118 deletions

View File

@ -14,7 +14,7 @@ jetty-7.3.0-SNAPSHOT
+ 332703 Cleanup context scope JNDI at stop
+ 332796 Annotations inheritance does not work with jetty7
+ 332799 100% CPU on redeploy session invalidation
+ 332937 Added Destroyable interface and reworked dependent lifecycles, specially of JNDI
+ 332937 Added Destroyable Dumpable interfaces and reworked dependent lifecycles, specially of JNDI
+ 333247 fix api compat issue in ConstraintSecurityHandler
+ 333415 wired up HttpInput.available and added test harnesses
+ 333481 Handle UTF-32 codepoints in decode and encode

View File

@ -43,6 +43,8 @@ public class LikeJettyXml
System.setProperty("jetty.home",jetty_home);
Server server = new Server();
server.setDumpAfterStart(true);
server.setDumpBeforeStop(true);
// Setup JMX
MBeanContainer mbContainer=new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
@ -134,8 +136,6 @@ public class LikeJettyXml
server.start();
System.err.println(server.dump());
server.join();
}

View File

@ -590,7 +590,8 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
{
synchronized(this)
{
return "SCEP@" + hashCode() + " [d=" + _dispatched + ",io=" + _interestOps+
return "SCEP@" + hashCode() + _channel+
"[d=" + _dispatched + ",io=" + _interestOps+
",w=" + _writable + ",rb=" + _readBlocked + ",wb=" + _writeBlocked + "]";
}
}

View File

@ -20,14 +20,22 @@ import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.io.ConnectedEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.thread.Timeout;
import org.eclipse.jetty.util.thread.Timeout.Task;
@ -41,7 +49,7 @@ import org.eclipse.jetty.util.thread.Timeout.Task;
* This class works around a number of know JVM bugs. For details
* see http://wiki.eclipse.org/Jetty/Feature/JVM_NIO_Bug
*/
public abstract class SelectorManager extends AbstractLifeCycle
public abstract class SelectorManager extends AbstractLifeCycle implements Dumpable
{
// TODO Tune these by approx system speed.
private static final int __JVMBUG_THRESHHOLD=Integer.getInteger("org.eclipse.jetty.io.nio.JVMBUG_THRESHHOLD",0).intValue();
@ -281,39 +289,25 @@ public abstract class SelectorManager extends AbstractLifeCycle
*/
protected abstract SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectorManager.SelectSet selectSet, SelectionKey sKey) throws IOException;
/* ------------------------------------------------------------------------------- */
public void dump()
/* ------------------------------------------------------------ */
public String dump()
{
for (final SelectSet set :_selectSet)
{
Thread selecting = set._selecting;
Log.info("SelectSet "+set._setID+" : "+selecting);
if (selecting!=null)
{
StackTraceElement[] trace =selecting.getStackTrace();
if (trace!=null)
{
for (StackTraceElement e : trace)
{
Log.info("\tat "+e.toString());
}
}
}
set.addChange(new Runnable(){
public void run()
{
set.dump();
}
});
}
return AggregateLifeCycle.dump(this);
}
/* ------------------------------------------------------------ */
public void dump(Appendable out, String indent) throws IOException
{
out.append(String.valueOf(this)).append("\n");
AggregateLifeCycle.dump(out,indent,Arrays.asList(_selectSet));
}
/* ------------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------------- */
public class SelectSet
public class SelectSet implements Dumpable
{
private final int _setID;
private final Timeout _timeout;
@ -837,20 +831,67 @@ public abstract class SelectorManager extends AbstractLifeCycle
_selector=null;
}
}
public void dump()
/* ------------------------------------------------------------ */
public String dump()
{
synchronized (System.err)
return AggregateLifeCycle.dump(this);
}
/* ------------------------------------------------------------ */
public void dump(Appendable out, String indent) throws IOException
{
out.append(String.valueOf(this)).append(" id=").append(String.valueOf(_setID)).append("\n");
Thread selecting = _selecting;
Object where = "not selecting";
StackTraceElement[] trace =selecting==null?null:selecting.getStackTrace();
if (trace!=null)
{
Selector selector=_selector;
Log.info("SelectSet "+_setID+" "+selector.keys().size());
for (SelectionKey key: selector.keys())
for (StackTraceElement t:trace)
if (t.getClassName().startsWith("org.eclipse.jetty."))
{
where=t;
break;
}
}
Selector selector=_selector;
final ArrayList<Object> dump = new ArrayList<Object>(selector.keys().size()*2);
dump.add(where);
final CountDownLatch latch = new CountDownLatch(1);
addChange(new Runnable(){
public void run()
{
if (key.isValid())
Log.info(key.channel()+" "+key.interestOps()+" "+key.readyOps()+" "+key.attachment());
else
Log.info(key.channel()+" - - "+key.attachment());
dumpKeyState(dump);
latch.countDown();
}
});
try
{
latch.await(5,TimeUnit.SECONDS);
}
catch(InterruptedException e)
{
Log.ignore(e);
}
AggregateLifeCycle.dump(out,indent,dump);
}
public void dumpKeyState(List<Object> dumpto)
{
Selector selector=_selector;
dumpto.add(selector+" keys="+selector.keys().size());
for (SelectionKey key: selector.keys())
{
if (key.isValid())
dumpto.add(key.attachment()+" "+key.interestOps()+" "+key.readyOps());
else
dumpto.add(key.attachment()+" - - ");
}
}
}

View File

@ -962,7 +962,7 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
{
final NIOBuffer i=_inNIOBuffer;
final NIOBuffer o=_outNIOBuffer;
return super.toString()+","+_engine.getHandshakeStatus()+", in/out="+
return "SSL"+super.toString()+","+_engine.getHandshakeStatus()+", in/out="+
(i==null?0:_inNIOBuffer.length())+"/"+(o==null?0:o.length())+" "+_result;
}
}

View File

@ -0,0 +1,2 @@
AggregateLifeCycle: A LifeCycle holding other LifeCycles
dumpStdErr():Object:INFO:Dump the nested Object state to StdErr

View File

@ -5,6 +5,7 @@ name: Name of the thread pool
daemon: Is pool thread using daemon thread
threadsPriority: The priority of threads in the pool
maxIdleTimeMs: Maximum time a thread may be idle in ms
detailedDump: Full stack detail in dump output
dump(): Dump thread state
stopThread(long): Stop a pool thread
stopThread(long)[0]: id:Thread ID

View File

@ -25,6 +25,7 @@
<New class="org.eclipse.jetty.util.thread.QueuedThreadPool">
<Set name="minThreads">10</Set>
<Set name="maxThreads">200</Set>
<Set name="detailedDump">false</Set>
</New>
</Set>
@ -72,5 +73,7 @@
<Set name="sendServerVersion">true</Set>
<Set name="sendDateHeader">true</Set>
<Set name="gracefulShutdown">1000</Set>
<Set name="dumpAfterStart">false</Set>
<Set name="dumpBeforeStop">false</Set>
</Configure>

View File

@ -24,13 +24,14 @@ import javax.servlet.ServletRequest;
import org.eclipse.jetty.http.HttpBuffers;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.HttpSchemes;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.statistic.SampleStatistic;
@ -51,7 +52,7 @@ import org.eclipse.jetty.util.thread.ThreadPool;
*
*
*/
public abstract class AbstractConnector extends HttpBuffers implements Connector
public abstract class AbstractConnector extends HttpBuffers implements Connector, Dumpable
{
private String _name;
@ -98,13 +99,6 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
{
}
/* ------------------------------------------------------------ */
public final Buffer newBuffer(int size)
{
// TODO remove once no overrides established
return null;
}
/* ------------------------------------------------------------ */
@Override
public Buffer newRequestBuffer(int size)
@ -1137,4 +1131,18 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
oldValue = valueHolder.get();
}
}
/* ------------------------------------------------------------ */
public String dump()
{
return AggregateLifeCycle.dump(this);
}
/* ------------------------------------------------------------ */
public void dump(Appendable out, String indent) throws IOException
{
out.append(String.valueOf(this)).append("\n");
}
}

View File

@ -73,6 +73,8 @@ public class Server extends HandlerWrapper implements Attributes
private int _graceful=0;
private boolean _stopAtShutdown;
private int _maxCookieVersion=1;
private boolean _dumpAfterStart=false;
private boolean _dumpBeforeStop=false;
/* ------------------------------------------------------------ */
@ -205,6 +207,38 @@ public class Server extends HandlerWrapper implements Attributes
addBean(_threadPool);
}
/**
* @return true if {@link #dumpStdErr()} is called after starting
*/
public boolean isDumpAfterStart()
{
return _dumpAfterStart;
}
/**
* @param dumpAfterStart true if {@link #dumpStdErr()} is called after starting
*/
public void setDumpAfterStart(boolean dumpAfterStart)
{
_dumpAfterStart = dumpAfterStart;
}
/**
* @return true if {@link #dumpStdErr()} is called before stopping
*/
public boolean isDumpBeforeStop()
{
return _dumpBeforeStop;
}
/**
* @param dumpBeforeStop true if {@link #dumpStdErr()} is called before stopping
*/
public void setDumpBeforeStop(boolean dumpBeforeStop)
{
_dumpBeforeStop = dumpBeforeStop;
}
/* ------------------------------------------------------------ */
@Override
protected void doStart() throws Exception
@ -239,8 +273,9 @@ public class Server extends HandlerWrapper implements Attributes
}
}
}
if (Log.isDebugEnabled())
System.err.println(dump());
if (isDumpAfterStart())
dumpStdErr();
mex.ifExceptionThrow();
}
@ -249,6 +284,9 @@ public class Server extends HandlerWrapper implements Attributes
@Override
protected void doStop() throws Exception
{
if (isDumpBeforeStop())
dumpStdErr();
MultiException mex=new MultiException();
if (_graceful>0)
@ -573,8 +611,7 @@ public class Server extends HandlerWrapper implements Attributes
dumpThis(out);
dump(out,indent,TypeUtil.asList(getHandlers()),getBeans(),TypeUtil.asList(_connectors));
}
/* ------------------------------------------------------------ */
/* A handler that can be gracefully shutdown.
* Called by doStop if a {@link #setGracefulShutdown} period is set.

View File

@ -93,7 +93,7 @@ public abstract class AbstractHandler extends AggregateLifeCycle implements Hand
/* ------------------------------------------------------------ */
public void dumpThis(Appendable out) throws IOException
{
out.append(toString()).append(isStarted()?" started":" STOPPED").append('\n');
out.append(toString()).append(' ').append(getState()).append('\n');
}
}

View File

@ -19,6 +19,8 @@ import java.net.Socket;
import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;
import java.util.Collections;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.io.ConnectedEndPoint;
@ -29,6 +31,7 @@ import org.eclipse.jetty.io.nio.SelectorManager;
import org.eclipse.jetty.io.nio.SelectorManager.SelectSet;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.thread.Timeout.Task;
@ -65,45 +68,7 @@ public class SelectChannelConnector extends AbstractNIOConnector
private int _lowResourcesMaxIdleTime;
private int _localPort=-1;
private final SelectorManager _manager = new SelectorManager()
{
@Override
public boolean dispatch(Runnable task)
{
return getThreadPool().dispatch(task);
}
@Override
protected void endPointClosed(final SelectChannelEndPoint endpoint)
{
connectionClosed(endpoint.getConnection());
}
@Override
protected void endPointOpened(SelectChannelEndPoint endpoint)
{
// TODO handle max connections and low resources
connectionOpened(endpoint.getConnection());
}
@Override
protected void endPointUpgraded(ConnectedEndPoint endpoint, Connection oldConnection)
{
connectionUpgraded(oldConnection,endpoint.getConnection());
}
@Override
protected Connection newConnection(SocketChannel channel,SelectChannelEndPoint endpoint)
{
return SelectChannelConnector.this.newConnection(channel,endpoint);
}
@Override
protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey sKey) throws IOException
{
return SelectChannelConnector.this.newEndPoint(channel,selectSet,sKey);
}
};
private final SelectorManager _manager = new ConnectorSelectorManager();
/* ------------------------------------------------------------------------------- */
/**
@ -337,10 +302,54 @@ public class SelectChannelConnector extends AbstractNIOConnector
};
}
/* ------------------------------------------------------------------------------- */
public void dump()
/* ------------------------------------------------------------ */
public void dump(Appendable out, String indent) throws IOException
{
Log.info("channel "+_acceptChannel+(_acceptChannel.isOpen()?" is open":" is closed"));
_manager.dump();
out.append(String.valueOf(this)).append("\n");
AggregateLifeCycle.dump(out,indent,Arrays.asList(new Object[]{_acceptChannel,_acceptChannel.isOpen()?"OPEN":"CLOSED",_manager}));
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
private final class ConnectorSelectorManager extends SelectorManager
{
@Override
public boolean dispatch(Runnable task)
{
return getThreadPool().dispatch(task);
}
@Override
protected void endPointClosed(final SelectChannelEndPoint endpoint)
{
connectionClosed(endpoint.getConnection());
}
@Override
protected void endPointOpened(SelectChannelEndPoint endpoint)
{
// TODO handle max connections and low resources
connectionOpened(endpoint.getConnection());
}
@Override
protected void endPointUpgraded(ConnectedEndPoint endpoint, Connection oldConnection)
{
connectionUpgraded(oldConnection,endpoint.getConnection());
}
@Override
protected Connection newConnection(SocketChannel channel,SelectChannelEndPoint endpoint)
{
return SelectChannelConnector.this.newConnection(channel,endpoint);
}
@Override
protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey sKey) throws IOException
{
return SelectChannelConnector.this.newEndPoint(channel,selectSet,sKey);
}
}
}

View File

@ -1,2 +1 @@
AbstractHandler: Jetty Handler.
dump(): dump the handler structure as a string
AbstractHandler: Jetty Handler.

View File

@ -5,3 +5,5 @@ sendServerVersion: If true include the server version in HTTP headers
threadPool: MObject:The server Thread Pool
contexts: MMBean:RO:The contexts of this server
startupTime: MBean:RO:The startup time, in milliseconds, since January 1st 1970
dumpAfterStart: RW:Dump state to stderr after start
dumpBeforeStop: RW:Dump state to stderr before stop

View File

@ -14,6 +14,10 @@
package org.eclipse.jetty.util.thread;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
@ -25,10 +29,12 @@ import java.util.concurrent.atomic.AtomicLong;
import org.eclipse.jetty.util.BlockingArrayQueue;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.log.Log;
public class QueuedThreadPool extends AbstractLifeCycle implements ThreadPool, Executor
public class QueuedThreadPool extends AbstractLifeCycle implements ThreadPool, Executor, Dumpable
{
private final AtomicInteger _threadsStarted = new AtomicInteger();
private final AtomicInteger _threadsIdle = new AtomicInteger();
@ -44,6 +50,7 @@ public class QueuedThreadPool extends AbstractLifeCycle implements ThreadPool, E
private int _priority=Thread.NORM_PRIORITY;
private boolean _daemon=false;
private int _maxStopTime=100;
private boolean _detailedDump=false;
/* ------------------------------------------------------------------- */
/** Construct
@ -321,7 +328,18 @@ public class QueuedThreadPool extends AbstractLifeCycle implements ThreadPool, E
return _daemon;
}
/* ------------------------------------------------------------ */
public boolean isDetailedDump()
{
return _detailedDump;
}
/* ------------------------------------------------------------ */
public void setDetailedDump(boolean detailedDump)
{
_detailedDump = detailedDump;
}
/* ------------------------------------------------------------ */
public boolean dispatch(Runnable job)
{
@ -427,12 +445,71 @@ public class QueuedThreadPool extends AbstractLifeCycle implements ThreadPool, E
return new Thread(runnable);
}
/* ------------------------------------------------------------ */
public String dump()
{
return AggregateLifeCycle.dump(this);
}
/* ------------------------------------------------------------ */
public void dump(Appendable out, String indent) throws IOException
{
List<Object> dump = new ArrayList<Object>(getMaxThreads());
for (final Thread thread: _threads)
{
final StackTraceElement[] trace=thread.getStackTrace();
boolean inIdleJobPoll=false;
for (StackTraceElement t : trace)
{
if ("idleJobPoll".equals(t.getMethodName()))
{
inIdleJobPoll=true;
break;
}
}
final boolean idle=inIdleJobPoll;
if (_detailedDump)
{
dump.add(new Dumpable()
{
public void dump(Appendable out, String indent) throws IOException
{
out.append(String.valueOf(thread.getId())).append(' ').append(thread.getName()).append(' ').append(thread.getState().toString()).append(idle?" IDLE":"").append('\n');
if (!idle)
AggregateLifeCycle.dump(out,indent,Arrays.asList(trace));
}
public String dump()
{
return null;
}
});
}
else
{
dump.add(thread.getId()+" "+thread.getName()+" "+thread.getState()+" @ "+trace[0]+(idle?" IDLE":""));
}
}
out.append(String.valueOf(this)).append("\n");
AggregateLifeCycle.dump(out,indent,dump);
}
/* ------------------------------------------------------------ */
@Override
public String toString()
{
return _name+"{"+getMinThreads()+"<="+getIdleThreads()+"<="+getThreads()+"/"+getMaxThreads()+","+(_jobs==null?-1:_jobs.size())+"}";
}
private Runnable idleJobPoll() throws InterruptedException
{
return _jobs.poll(_maxIdleTimeMs,TimeUnit.MILLISECONDS);
}
/* ------------------------------------------------------------ */
private Runnable _runnable = new Runnable()
@ -477,7 +554,7 @@ public class QueuedThreadPool extends AbstractLifeCycle implements ThreadPool, E
return;
}
}
job=_jobs.poll(_maxIdleTimeMs,TimeUnit.MILLISECONDS);
job=idleJobPoll();
}
}
}
@ -504,20 +581,6 @@ public class QueuedThreadPool extends AbstractLifeCycle implements ThreadPool, E
}
};
public String dump()
{
StringBuilder buf = new StringBuilder();
for (Thread thread: _threads)
{
buf.append(thread.getId()).append(" ").append(thread.getName()).append(" ").append(thread.getState()).append(":\n");
for (StackTraceElement element : thread.getStackTrace())
buf.append(" at ").append(element.toString()).append('\n');
}
return buf.toString();
}
/* ------------------------------------------------------------ */
/**
* @param id The thread ID to stop.