282807 283049 282543 Improved handling of timeouts and complete. More debug

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@538 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2009-07-10 08:20:24 +00:00
parent c3b43f49d8
commit 6096568c7f
13 changed files with 243 additions and 30 deletions

View File

@ -7,6 +7,7 @@ jetty-7.0.0.RC0 8 June 2009
+ 271535 Adding integration tests, and enabling RFC2616 tests
+ 281287 Handle date headers before 1 Jan 1970
+ 282807 Better handling of 100 continues if response committed.
+ 282807 283049 282543 Improved handling of timeouts and complete. More debug
jetty-7.0.0.M4 1 June 2009
+ 281059 NPE in QTP with debug on

View File

@ -18,6 +18,11 @@
<artifactId>jetty-webapp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-deploy</artifactId>

View File

@ -26,6 +26,7 @@ import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
public class LikeJettyXml
@ -34,6 +35,7 @@ public class LikeJettyXml
throws Exception
{
String jetty_home = System.getProperty("jetty.home","../jetty-distribution/target/distribution");
System.setProperty("jetty.home",jetty_home);
Server server = new Server();
@ -45,6 +47,15 @@ public class LikeJettyXml
connector.setPort(8080);
connector.setMaxIdleTime(30000);
server.setConnectors(new Connector[]{connector});
SslSelectChannelConnector ssl_connector=new SslSelectChannelConnector();
ssl_connector.setPort(8443);
ssl_connector.setKeystore(jetty_home+"/etc/keystore");
ssl_connector.setPassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
ssl_connector.setKeyPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");
ssl_connector.setTruststore(jetty_home+"/etc/keystore");
ssl_connector.setTrustPassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
server.addConnector(ssl_connector);
HandlerCollection handlers = new HandlerCollection();
ContextHandlerCollection contexts = new ContextHandlerCollection();

View File

@ -0,0 +1,41 @@
// ========================================================================
// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.embedded;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.bio.SocketConnector;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlets.ProxyServlet;
public class ProxyServer
{
public static void main(String[] args)
throws Exception
{
Server server = new Server();
Connector connector=new SocketConnector();
connector.setPort(8080);
server.setConnectors(new Connector[]{connector});
ServletHandler handler=new ServletHandler();
server.setHandler(handler);
handler.addServletWithMapping(ProxyServlet.class, "/");
server.start();
server.join();
}
}

View File

@ -26,21 +26,26 @@ import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.nio.DirectNIOBuffer;
import org.eclipse.jetty.io.nio.NIOBuffer;
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.io.nio.SelectorManager;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
/**
* SslHttpChannelEndPoint.
*
*
*
* SslSelectChannelEndPoint
* <p>
* A SelectChannelEndPoint that uses an {@link SSLEngine} to handle an
* SSL connection.
* <p>
* There is a named logger "org.eclipse.jetty.http.ssl"
* </p>
*/
public class SslSelectChannelEndPoint extends SelectChannelEndPoint
{
static Logger __log = Log.getLogger("org.eclipse.jetty.http.ssl");
private static final ByteBuffer[] __NO_BUFFERS={};
private final Buffers _buffers;
@ -59,6 +64,8 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
private SSLEngineResult _result;
private String _last;
private final boolean _debug = __log.isDebugEnabled(); // snapshot debug status for optimizer
// TODO get rid of this
// StringBuilder h = new StringBuilder(500);
@ -92,6 +99,7 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
_inBuffer=_inNIOBuffer.getByteBuffer();
// h.append("CONSTRUCTED\n");
if (_debug) __log.debug(_session+" channel="+channel);
}
// TODO get rid of these dumps
@ -165,6 +173,7 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
Thread.sleep(100); // TODO yuck
}
if (_debug) __log.debug(_session+" closing "+_engine.getHandshakeStatus());
switch(_engine.getHandshakeStatus())
{
case FINISHED:
@ -215,6 +224,7 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
_result=null;
_last="close wrap";
_result=_engine.wrap(__NO_BUFFERS,_outBuffer);
if (_debug) __log.debug(_session+" close wrap "+_result);
_outNIOBuffer.setPutIndex(put+_result.bytesProduced());
}
finally
@ -311,6 +321,7 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
// The fix simply detects the signature of the bug and then close the connection (fail-fast) so that ff3 will delegate to using SSL instead of TLS.
// This is a jvm bug on java1.6 where the SSLEngine expects more data from the initial handshake when the client(ff3-tls) already had given it.
// See http://jira.codehaus.org/browse/JETTY-567 for more details
if (_debug) __log.warn(_session+" JETTY-567");
return -1;
}
break;
@ -329,6 +340,7 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
_result=null;
_last="fill wrap";
_result=_engine.wrap(__NO_BUFFERS,_outBuffer);
if (_debug) __log.debug(_session+" fill wrap "+_result);
switch(_result.getStatus())
{
case BUFFER_OVERFLOW:
@ -469,6 +481,7 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
_result=null;
_last="flush wrap";
_result=_engine.wrap(__NO_BUFFERS,_outBuffer);
if (_debug) __log.debug(_session+" flush wrap "+_result);
switch(_result.getStatus())
{
case BUFFER_OVERFLOW:
@ -496,13 +509,13 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
return consumed;
}
/* ------------------------------------------------------------ */
public void flush() throws IOException
{
while (_outNIOBuffer.length()>0)
{
int flushed=super.flush(_outNIOBuffer);
if (_debug) __log.debug(_session+" flushed "+flushed);
// h.append("flushed=").append(flushed).append(" of ").append(_outNIOBuffer.length()).append('\n');
if (flushed==0)
@ -542,6 +555,7 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
try
{
int filled=super.fill(_inNIOBuffer);
if (_debug) __log.debug(_session+" unwrap filled "+filled);
// h.append("fill=").append(filled).append('\n');
if (filled<=0)
break;
@ -571,6 +585,7 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
_result=null;
_last="unwrap";
_result=_engine.unwrap(_inBuffer,buffer);
if (_debug) __log.debug(_session+" unwrap unwrap "+_result);
// h.append("unwrap=").append(_result).append('\n');
_inNIOBuffer.skip(_result.bytesConsumed());
}
@ -579,7 +594,6 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
_inBuffer.position(0);
_inBuffer.limit(_inBuffer.capacity());
}
switch(_result.getStatus())
{
@ -646,6 +660,7 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
_result=null;
_last="wrap wrap";
_result=_engine.wrap(_gather,_outBuffer);
if (_debug) __log.debug(_session+" wrap wrap "+_result);
// h.append("wrap2=").append(_result).append('\n');
_outNIOBuffer.setGetIndex(0);
_outNIOBuffer.setPutIndex(_result.bytesProduced());
@ -716,6 +731,7 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
_result=null;
_last="wrap wrap";
_result=_engine.wrap(_gather[0],_outBuffer);
if (_debug) __log.debug(_session+" wrap wrap "+_result);
// h.append("wrap1=").append(_result).append('\n');
_outNIOBuffer.setGetIndex(0);
_outNIOBuffer.setPutIndex(_result.bytesProduced());

View File

@ -86,7 +86,6 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements Runnable,
*/
public void schedule()
{
// If threads are blocked on this
synchronized (this)
{
// If there is no key, then do nothing

View File

@ -35,6 +35,8 @@ import org.eclipse.jetty.util.thread.Timeout;
*/
public class AsyncContinuation implements AsyncContext, Continuation
{
private final static long DEFAULT_TIMEOUT=30000L;
private final static ContinuationThrowable __exception = new ContinuationThrowable();
// STATES:
@ -72,8 +74,9 @@ public class AsyncContinuation implements AsyncContext, Continuation
private boolean _resumed;
private boolean _expired;
private volatile boolean _responseWrapped;
private long _timeoutMs;
private long _timeoutMs=DEFAULT_TIMEOUT;
private AsyncEventState _event;
private volatile long _expireAt;
// private StringBuilder _history = new StringBuilder();
@ -573,7 +576,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
_expired=false;
_responseWrapped=false;
cancelTimeout();
_timeoutMs=60000L; // TODO configure
_timeoutMs=DEFAULT_TIMEOUT;
_listeners=null;
}
}
@ -607,9 +610,9 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
synchronized(this)
{
long expire_at = System.currentTimeMillis()+_timeoutMs;
_expireAt = System.currentTimeMillis()+_timeoutMs;
long wait=_timeoutMs;
while (_timeoutMs>0 && wait>0)
while (_expireAt>0 && wait>0)
{
try
{
@ -619,11 +622,13 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
Log.ignore(e);
}
wait=expire_at-System.currentTimeMillis();
wait=_expireAt-System.currentTimeMillis();
}
if (_timeoutMs>0 && wait<=0)
if (_expireAt>0 && wait<=0)
{
expired();
}
}
}
else
@ -638,7 +643,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
synchronized(this)
{
_timeoutMs=0;
_expireAt=0;
this.notifyAll();
}
}

View File

@ -382,7 +382,7 @@ public class HttpConnection implements Connection
// Loop while more in buffer
boolean more_in_buffer =true; // assume true until proven otherwise
boolean progress=true;
try
{
assert getCurrentConnection()==null;
@ -396,14 +396,17 @@ public class HttpConnection implements Connection
{
if (_request._async.isAsync())
{
Log.debug("resume request",_request);
Log.debug("async request",_request);
if (!_request._async.isComplete())
handleRequest();
else if (!_parser.isComplete())
progress|=_parser.parseAvailable()>0;
{
long parsed=_parser.parseAvailable();
progress|=parsed>0;
}
if (_generator.isCommitted() && !_generator.isComplete())
_generator.flushBuffer();
progress|=_generator.flushBuffer()>0;
if (_endp.isBufferingOutput())
_endp.flush();
}

View File

@ -37,6 +37,7 @@ import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.http.HttpHeaderValues;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.HttpSchemes;
import org.eclipse.jetty.http.HttpURI;
@ -45,6 +46,7 @@ import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
@ -55,9 +57,13 @@ import org.eclipse.jetty.util.log.Log;
*
* This servlet needs the jetty-util and jetty-client classes to be available to
* the web application.
*
* This servlet has a a logger called "org.eclipse.jetty.servlets.ProxyServlet".
*/
public class ProxyServlet implements Servlet
{
private static Logger __log = Log.getLogger("org.eclipse.jetty.servlets.ProxyServlet");
HttpClient _client;
protected HashSet<String> _DontProxyHeaders = new HashSet<String>();
@ -111,6 +117,8 @@ public class ProxyServlet implements Servlet
public void service(ServletRequest req, ServletResponse res) throws ServletException,
IOException
{
final int debug=__log.isDebugEnabled()?req.hashCode():0;
final HttpServletRequest request = (HttpServletRequest)req;
final HttpServletResponse response = (HttpServletResponse)res;
if ("CONNECT".equalsIgnoreCase(request.getMethod()))
@ -136,6 +144,10 @@ public class ProxyServlet implements Servlet
request.getServerName(),
request.getServerPort(),
uri);
if (debug!=0)
__log.debug(debug+" proxy "+uri+"-->"+url);
if (url==null)
{
response.sendError(HttpServletResponse.SC_FORBIDDEN);
@ -154,11 +166,15 @@ public class ProxyServlet implements Servlet
protected void onResponseComplete() throws IOException
{
if (debug!=0)
__log.debug(debug+" complete");
continuation.complete();
}
protected void onResponseContent(Buffer content) throws IOException
{
if (debug!=0)
__log.debug(debug+" content"+content.length());
content.writeTo(out);
}
@ -168,6 +184,9 @@ public class ProxyServlet implements Servlet
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
{
if (debug!=0)
__log.debug(debug+" "+version+" "+status+" "+reason);
if (reason!=null && reason.length()>0)
response.setStatus(status,reason.toString());
else
@ -177,8 +196,17 @@ public class ProxyServlet implements Servlet
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
{
String s = name.toString().toLowerCase();
if (!_DontProxyHeaders.contains(s))
if (!_DontProxyHeaders.contains(s) ||
(HttpHeaders.CONNECTION_BUFFER.equals(name) &&
HttpHeaderValues.CLOSE_BUFFER.equals(value)))
{
if (debug!=0)
__log.debug(debug+" "+name+": "+value);
response.addHeader(name.toString(),value.toString());
}
else if (debug!=0)
__log.debug(debug+" "+name+"! "+value);
}
protected void onConnectionFailed(Throwable ex)
@ -213,9 +241,9 @@ public class ProxyServlet implements Servlet
exchange.setMethod(request.getMethod());
exchange.setURL(url.toString());
exchange.setVersion(request.getProtocol());
if (Log.isDebugEnabled())
Log.debug("PROXY TO "+url);
if (debug!=0)
__log.debug(debug+" "+request.getMethod()+" "+url+" "+request.getProtocol());
// check connection header
String connectionHdr = request.getHeader("Connection");
@ -245,13 +273,15 @@ public class ProxyServlet implements Servlet
if ("content-type".equals(lhdr))
hasContent=true;
if ("content-length".equals(lhdr))
else if ("content-length".equals(lhdr))
{
contentLength=request.getContentLength();
exchange.setRequestHeader(HttpHeaders.CONTENT_LENGTH,TypeUtil.toString(contentLength));
if (contentLength>0)
hasContent=true;
}
else if ("x-forwarded-for".equals(lhdr))
xForwardedFor=true;
Enumeration<?> vals = request.getHeaders(hdr);
while (vals.hasMoreElements())
@ -259,8 +289,10 @@ public class ProxyServlet implements Servlet
String val = (String)vals.nextElement();
if (val!=null)
{
exchange.setRequestHeader(lhdr,val);
xForwardedFor|="X-Forwarded-For".equalsIgnoreCase(hdr);
if (debug!=0)
__log.debug(debug+" "+hdr+": "+val);
exchange.setRequestHeader(hdr,val);
}
}
}

View File

@ -28,9 +28,12 @@ public interface Logger
*/
public void setDebugEnabled(boolean enabled);
public void info(String msg);
public void info(String msg,Object arg0, Object arg1);
public void debug(String msg);
public void debug(String msg,Throwable th);
public void debug(String msg,Object arg0, Object arg1);
public void warn(String msg);
public void warn(String msg,Object arg0, Object arg1);
public void warn(String msg, Throwable th);
public Logger getLogger(String name);

View File

@ -67,6 +67,21 @@ public class LoggerLog implements Logger
}
}
public void debug(String msg)
{
if (_debug)
{
try
{
_debugMAA.invoke(_logger,msg,null,null);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
public void debug(String msg, Object arg0, Object arg1)
{
if (_debug)
@ -96,6 +111,18 @@ public class LoggerLog implements Logger
return this;
}
public void info(String msg)
{
try
{
_infoMAA.invoke(_logger,msg,null,null);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void info(String msg, Object arg0, Object arg1)
{
try
@ -127,6 +154,18 @@ public class LoggerLog implements Logger
}
public void warn(String msg)
{
try
{
_warnMAA.invoke(_logger,msg,null,null);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void warn(String msg, Object arg0, Object arg1)
{
try

View File

@ -33,6 +33,15 @@ public class Slf4jLog implements Logger
logger = org.slf4j.LoggerFactory.getLogger( name );
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.log.Log#doDebug(java.lang.String)
*/
public void debug(String msg)
{
logger.debug(msg);
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.log.Log#doDebug(java.lang.String, java.lang.Object, java.lang.Object)
@ -60,6 +69,16 @@ public class Slf4jLog implements Logger
return logger.isDebugEnabled();
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.log.Log#doInfo(java.lang.String)
*/
public void info(String msg)
{
logger.info(msg);
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.log.Log#doInfo(java.lang.String, java.lang.Object, java.lang.Object)
@ -69,6 +88,16 @@ public class Slf4jLog implements Logger
logger.info(msg, arg0, arg1);
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.log.Log#doWarn(java.lang.String)
*/
public void warn(String msg)
{
logger.warn(msg);
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.log.Log#doWarn(java.lang.String, java.lang.Object, java.lang.Object)

View File

@ -19,15 +19,19 @@ import org.eclipse.jetty.util.DateCache;
/** StdErr Logging.
* This implementation of the Logging facade sends all logs to StdErr with minimal formatting.
*
* If the system property org.eclipse.jetty.util.log.DEBUG is set,
* If the system property "org.eclipse.jetty.util.log.DEBUG" is set,
* then debug logs are printed if stderr is being used.
* <p>
* For named debuggers, the system property name+".DEBUG" is checked. If it is not not set, then
* "org.eclipse.jetty.util.log.DEBUG" is used as the default.
*
*/
public class StdErrLog implements Logger
{
private static DateCache _dateCache;
private static boolean _debug = Boolean.parseBoolean(System.getProperty("org.eclipse.jetty.util.log.DEBUG","false"));
private final static boolean __debug = Boolean.parseBoolean(System.getProperty("org.eclipse.jetty.util.log.DEBUG","false"));
private boolean _debug = __debug;
private String _name;
private boolean _hideStacks=false;
@ -52,6 +56,7 @@ public class StdErrLog implements Logger
public StdErrLog(String name)
{
this._name=name==null?"":name;
_debug=Boolean.parseBoolean(System.getProperty(name+".DEBUG",Boolean.toString(__debug)));
}
public boolean isDebugEnabled()
@ -74,6 +79,13 @@ public class StdErrLog implements Logger
_hideStacks = hideStacks;
}
public void info(String msg)
{
String d=_dateCache.now();
int ms=_dateCache.lastMs();
System.err.println(d+(ms>99?".":(ms>0?".0":".00"))+ms+":"+_name+":INFO: "+msg);
}
public void info(String msg,Object arg0, Object arg1)
{
String d=_dateCache.now();
@ -98,6 +110,16 @@ public class StdErrLog implements Logger
}
}
public void debug(String msg)
{
if (_debug)
{
String d=_dateCache.now();
int ms=_dateCache.lastMs();
System.err.println(d+(ms>99?".":(ms>0?".0":".00"))+ms+":"+_name+":DEBUG: "+msg);
}
}
public void debug(String msg,Object arg0, Object arg1)
{
if (_debug)
@ -108,6 +130,13 @@ public class StdErrLog implements Logger
}
}
public void warn(String msg)
{
String d=_dateCache.now();
int ms=_dateCache.lastMs();
System.err.println(d+(ms>99?".":(ms>0?".0":".00"))+ms+":"+_name+":WARN: "+msg);
}
public void warn(String msg,Object arg0, Object arg1)
{
String d=_dateCache.now();
@ -146,12 +175,12 @@ public class StdErrLog implements Logger
if ((name==null && this._name==null) ||
(name!=null && name.equals(this._name)))
return this;
return new StdErrLog(name);
return new StdErrLog(_name==null||_name.length()==0?name:_name+"."+name);
}
public String toString()
{
return "STDERR"+_name;
return "StdErrLog:"+_name+":DEBUG="+_debug;
}
}