Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--jetty-ajp/src/main/java/org/eclipse/jetty/ajp/Ajp13Generator.java2
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/AbstractHttpConnection.java68
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/AsyncHttpConnection.java291
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java30
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/HttpExchangeTest.java3
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/AbstractGenerator.java2
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/Generator.java2
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java157
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java2
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java9
-rw-r--r--jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedGenerator.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java1
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/HttpWriterTest.java2
13 files changed, 267 insertions, 304 deletions
diff --git a/jetty-ajp/src/main/java/org/eclipse/jetty/ajp/Ajp13Generator.java b/jetty-ajp/src/main/java/org/eclipse/jetty/ajp/Ajp13Generator.java
index 4e767501db..77d17e6db0 100644
--- a/jetty-ajp/src/main/java/org/eclipse/jetty/ajp/Ajp13Generator.java
+++ b/jetty-ajp/src/main/java/org/eclipse/jetty/ajp/Ajp13Generator.java
@@ -487,7 +487,7 @@ public class Ajp13Generator extends AbstractGenerator
/* ------------------------------------------------------------ */
@Override
- public long flushBuffer() throws IOException
+ public int flushBuffer() throws IOException
{
try
{
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractHttpConnection.java b/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractHttpConnection.java
index 24502b41e4..0e619f1707 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractHttpConnection.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractHttpConnection.java
@@ -127,7 +127,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection implemen
else
{
AsyncEndPoint scep = (AsyncEndPoint)_endp;
- scep.scheduleWrite();
+ scep.asyncDispatch();
}
adjustIdleTimeout();
@@ -254,29 +254,14 @@ public abstract class AbstractHttpConnection extends AbstractConnection implemen
}
}
- protected void reset(boolean returnBuffers) throws IOException
+ protected void reset() throws IOException
{
_connectionHeader = null;
_parser.reset();
- if (returnBuffers)
- _parser.returnBuffers();
_generator.reset();
_http11 = true;
}
- protected boolean shouldClose()
- {
- if (_endp.isInputShutdown())
- return true;
- if (_connectionHeader!=null)
- {
- if (HttpHeaderValues.CLOSE_BUFFER.equals(_connectionHeader))
- return true;
- if (HttpHeaderValues.KEEP_ALIVE_BUFFER.equals(_connectionHeader))
- return false;
- }
- return !_http11;
- }
private class Handler extends HttpParser.EventHandler
{
@@ -294,28 +279,33 @@ public abstract class AbstractHttpConnection extends AbstractConnection implemen
public void startResponse(Buffer version, int status, Buffer reason) throws IOException
{
HttpExchange exchange = _exchange;
- if (exchange!=null)
+ if (exchange==null)
{
- switch(status)
- {
- case HttpStatus.CONTINUE_100:
- case HttpStatus.PROCESSING_102:
- // TODO check if appropriate expect was sent in the request.
- exchange.setEventListener(new NonFinalResponseListener(exchange));
- break;
-
- case HttpStatus.OK_200:
- // handle special case for CONNECT 200 responses
- if (HttpMethods.CONNECT.equalsIgnoreCase(exchange.getMethod()))
- _parser.setHeadResponse(true);
- break;
- }
+ LOG.warn("No exchange for response");
+ _endp.close();
+ return;
+ }
+
+ switch(status)
+ {
+ case HttpStatus.CONTINUE_100:
+ case HttpStatus.PROCESSING_102:
+ // TODO check if appropriate expect was sent in the request.
+ exchange.setEventListener(new NonFinalResponseListener(exchange));
+ break;
- _http11 = HttpVersions.HTTP_1_1_BUFFER.equals(version);
- _status=status;
- exchange.getEventListener().onResponseStatus(version,status,reason);
- exchange.setStatus(HttpExchange.STATUS_PARSING_HEADERS);
+ case HttpStatus.OK_200:
+ // handle special case for CONNECT 200 responses
+ if (HttpMethods.CONNECT.equalsIgnoreCase(exchange.getMethod()))
+ _parser.setHeadResponse(true);
+ break;
}
+
+ _http11 = HttpVersions.HTTP_1_1_BUFFER.equals(version);
+ _status=status;
+ exchange.getEventListener().onResponseStatus(version,status,reason);
+ exchange.setStatus(HttpExchange.STATUS_PARSING_HEADERS);
+
}
@Override
@@ -429,6 +419,12 @@ public abstract class AbstractHttpConnection extends AbstractConnection implemen
protected void exchangeExpired(HttpExchange exchange)
{
+ System.err.println("exchangeEXPIRED "+this);
+ System.err.println(exchange);
+ System.err.println(_endp);
+ System.err.println(_generator);
+ System.err.println(_parser);
+
synchronized (this)
{
// We are expiring an exchange, but the exchange is pending
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/AsyncHttpConnection.java b/jetty-client/src/main/java/org/eclipse/jetty/client/AsyncHttpConnection.java
index 6fc12f5af6..df1787e873 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/AsyncHttpConnection.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/AsyncHttpConnection.java
@@ -12,6 +12,7 @@ import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.nio.AsyncConnection;
+import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.io.nio.SslSelectChannelEndPoint;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -21,7 +22,6 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
{
private static final Logger LOG = Log.getLogger(AsyncHttpConnection.class);
- private Buffer _requestContentChunk;
private boolean _requestComplete;
private int _status;
@@ -30,116 +30,97 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
super(requestBuffers,responseBuffers,endp);
}
- protected void reset(boolean returnBuffers) throws IOException
+ protected void reset() throws IOException
{
_requestComplete = false;
- super.reset(returnBuffers);
+ super.reset();
}
public Connection handle() throws IOException
{
+ Connection connection = this;
+ boolean progress=true;
+
try
{
- boolean progress=true;
boolean failed = false;
+ int loops=1000; // TODO remove this safety net
+
// While the endpoint is open
// AND we have more characters to read OR we made some progress
while (_endp.isOpen() &&
(_parser.isMoreInBuffer() || _endp.isBufferingInput() || progress))
{
-
- // If no exchange, skipCRLF or close on unexpected characters
- HttpExchange exchange;
- synchronized (this)
- {
- exchange=_exchange;
- }
-
- if (exchange == null)
+ // System.err.println("loop");
+ if (loops--<0)
{
- // TODO long filled = _parser.fill();
- long filled = -1;
- if (filled < 0)
- close();
- else
- {
- // Hopefully just space?
- // TODO _parser.skipCRLF();
- if (_parser.isMoreInBuffer())
- {
- LOG.warn("Unexpected data received but no request sent");
- close();
- }
- }
- return this;
+ System.err.println("LOOPING!!!");
+ System.err.println(this);
+ System.err.println(_endp);
+ System.err.println(((SelectChannelEndPoint)_endp).getSelectManager().dump());
+ System.exit(1);
}
-
+
+ progress=false;
+ HttpExchange exchange=_exchange;
try
{
- if (exchange.getStatus() == HttpExchange.STATUS_WAITING_FOR_COMMIT)
+ // Should we commit the request?
+ if (!_generator.isCommitted() && exchange!=null && exchange.getStatus() == HttpExchange.STATUS_WAITING_FOR_COMMIT)
{
progress=true;
commitRequest();
}
- _endp.flush();
-
- if (_generator.isComplete())
- {
- if (!_requestComplete)
- {
- _requestComplete = true;
- exchange.getEventListener().onRequestComplete();
- }
- }
- else
+ // Generate output
+ if (_generator.isCommitted() && !_generator.isComplete())
{
- long flushed = _generator.flushBuffer();
- progress|=(flushed>0);
-
- if (_generator.isComplete())
+ int flushed=_generator.flushBuffer();
+ if (flushed>0)
+ progress=true;
+
+ // Is there more content to send or should we complete the generator
+ if (!_generator.isComplete() && _generator.isEmpty())
{
- InputStream in = exchange.getRequestContentSource();
- if (in != null)
+ if (exchange!=null)
{
- if (_requestContentChunk == null || _requestContentChunk.length() == 0)
+ Buffer chunk = _exchange.getRequestContentChunk();
+ if (chunk!=null)
+ _generator.addContent(chunk,false);
+ else
{
- _requestContentChunk = _exchange.getRequestContentChunk();
-
- if (_requestContentChunk != null)
- _generator.addContent(_requestContentChunk,false);
- else
- _generator.complete();
-
- flushed = _generator.flushBuffer();
- progress|=(flushed>0);
+ _generator.complete();
+ progress=true;
}
}
else
+ {
_generator.complete();
+ progress=true;
+ }
}
else
+ {
_generator.complete();
-
+ progress=true;
+ }
}
+ // Signal request completion
if (_generator.isComplete() && !_requestComplete)
{
_requestComplete = true;
- _exchange.getEventListener().onRequestComplete();
+ exchange.getEventListener().onRequestComplete();
}
- // If we are not ended then parse available
- if (!_parser.isComplete() && (_generator.isComplete() || _generator.isCommitted() && !_endp.isBlocking()))
- {
- if (_parser.parseAvailable())
- progress=true;
+ // Flush output from buffering endpoint
+ if (_endp.isBufferingOutput())
+ _endp.flush();
- if (_parser.isIdle() && (_endp.isInputShutdown() || !_endp.isOpen()))
- throw new EOFException();
- }
-
+ // Read any input that is available
+ if (!_parser.isComplete() && _parser.parseAvailable())
+ progress=true;
}
catch (Throwable e)
{
@@ -152,144 +133,85 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
synchronized (this)
{
- if (_exchange != null)
+ if (exchange != null)
{
// Cancelling the exchange causes an exception as we close the connection,
// but we don't report it as it is normal cancelling operation
- if (_exchange.getStatus() != HttpExchange.STATUS_CANCELLING &&
- _exchange.getStatus() != HttpExchange.STATUS_CANCELLED)
+ if (exchange.getStatus() != HttpExchange.STATUS_CANCELLING &&
+ exchange.getStatus() != HttpExchange.STATUS_CANCELLED)
{
- _exchange.setStatus(HttpExchange.STATUS_EXCEPTED);
- _exchange.getEventListener().onException(e);
+ exchange.setStatus(HttpExchange.STATUS_EXCEPTED);
+ exchange.getEventListener().onException(e);
}
}
else
{
if (e instanceof IOException)
throw (IOException)e;
-
if (e instanceof Error)
throw (Error)e;
-
if (e instanceof RuntimeException)
throw (RuntimeException)e;
-
throw new RuntimeException(e);
}
}
}
finally
{
- boolean complete = false;
- boolean close = failed; // always close the connection on error
- if (!failed)
+ boolean complete = failed || _generator.isComplete() && _parser.isComplete();
+
+ if (complete)
{
- // are we complete?
- if (_generator.isComplete())
+ boolean persistent = !failed && _parser.isPersistent() && _generator.isPersistent();
+ _generator.setPersistent(persistent);
+ reset();
+ if (persistent)
+ _endp.setMaxIdleTime((int)_destination.getHttpClient().getIdleTimeout());
+
+ synchronized (this)
{
- if (!_requestComplete)
- {
- _requestComplete = true;
- _exchange.getEventListener().onRequestComplete();
- }
+ exchange=_exchange;
+ _exchange = null;
- // we need to return the HttpConnection to a state that
- // it can be reused or closed out
- if (_parser.isComplete())
+ // Cancel the exchange
+ if (exchange!=null)
{
- _exchange.cancelTimeout(_destination.getHttpClient());
- complete = true;
+ exchange.cancelTimeout(_destination.getHttpClient());
+
+ // TODO should we check the exchange is done?
}
- }
-
- // if the endpoint is closed, but the parser incomplete
- if (!_endp.isOpen() && !(_parser.isComplete()||_parser.isIdle()))
- {
- // we wont be called again so let the parser see the close
- complete=true;
- _parser.parseAvailable();
- // TODO should not need this
- if (!(_parser.isComplete()||_parser.isIdle()))
+
+ // handle switched protocols
+ if (_status==HttpStatus.SWITCHING_PROTOCOLS_101)
{
- LOG.warn("Incomplete {} {}",_parser,_endp);
- if (_exchange!=null && !_exchange.isDone())
+ Connection switched=exchange.onSwitchProtocol(_endp);
+ if (switched!=null)
+ connection=switched;
{
- _exchange.setStatus(HttpExchange.STATUS_EXCEPTED);
- _exchange.getEventListener().onException(new EOFException("Incomplete"));
+ // switched protocol!
+ _pipeline = null;
+ if (_pipeline!=null)
+ _destination.send(_pipeline);
+ _pipeline = null;
+
+ connection=switched;
}
}
- }
- }
-
- if (_endp.isInputShutdown() && !_parser.isComplete() && !_parser.isIdle())
- {
- if (_exchange!=null && !_exchange.isDone())
- {
- _exchange.setStatus(HttpExchange.STATUS_EXCEPTED);
- _exchange.getEventListener().onException(new EOFException("Incomplete"));
- }
- _endp.close();
- }
-
- if (complete || failed)
- {
- synchronized (this)
- {
- if (!close)
- close = shouldClose();
-
- reset(true);
-
- progress=true;
- if (_exchange != null)
+
+ // handle pipelined requests
+ if (_pipeline!=null)
{
- exchange=_exchange;
- _exchange = null;
-
- // Reset the maxIdleTime because it may have been changed
- if (!close)
- _endp.setMaxIdleTime((int)_destination.getHttpClient().getIdleTimeout());
-
- if (_status==HttpStatus.SWITCHING_PROTOCOLS_101)
- {
- Connection switched=exchange.onSwitchProtocol(_endp);
- if (switched!=null)
- {
- // switched protocol!
- exchange = _pipeline;
- _pipeline = null;
- if (exchange!=null)
- _destination.send(exchange);
-
- return switched;
- }
- }
-
- if (_pipeline == null)
- {
- if (!isReserved())
- _destination.returnConnection(this, close);
- }
+ if (!persistent || connection!=this)
+ _destination.send(_pipeline);
else
- {
- if (close)
- {
- if (!isReserved())
- _destination.returnConnection(this,close);
-
- exchange = _pipeline;
- _pipeline = null;
- _destination.send(exchange);
- }
- else
- {
- exchange = _pipeline;
- _pipeline = null;
- send(exchange);
- }
- }
+ _exchange=_pipeline;
+ _pipeline=null;
}
+
+ if (_exchange==null && !isReserved()) // TODO how do we return switched connections?
+ _destination.returnConnection(this, !persistent);
}
+
}
}
}
@@ -297,20 +219,29 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
finally
{
_parser.returnBuffers();
-
- // Do we have more stuff to write?
- if (!_generator.isComplete() && _generator.getBytesBuffered()>0 && _endp.isOpen() && _endp instanceof AsyncEndPoint)
+ _generator.returnBuffers();
+
+ // TODO why is this needed?
+ if (!_generator.isEmpty())
{
- // Assume we are write blocked!
- ((AsyncEndPoint)_endp).scheduleWrite();
+ if (((SelectChannelEndPoint)_endp).isWritable())
+ {
+ System.err.println("early exit??? "+progress);
+ System.err.println(_endp);
+ System.err.println(_generator);
+ System.exit(1);
+ }
+
+ ((SelectChannelEndPoint)_endp).scheduleWrite();
}
}
- return this;
+ return connection;
}
public void onInputShutdown() throws IOException
{
- // TODO
+ if (_generator.isIdle())
+ _endp.shutdownOutput();
}
}
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java
index 38c9b89a8d..9b33c6eac9 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java
@@ -123,7 +123,6 @@ public class HttpExchange
{
if (getStatus() < HttpExchange.STATUS_COMPLETED)
setStatus(HttpExchange.STATUS_EXPIRED);
-
destination.exchangeExpired(this);
AbstractHttpConnection connection = _connection;
if (connection != null)
@@ -709,21 +708,24 @@ public class HttpExchange
{
synchronized (this)
{
- if (_requestContentChunk == null)
- _requestContentChunk = new ByteArrayBuffer(4096); // TODO configure
- else
+ if (_requestContentSource!=null)
{
- if (_requestContentChunk.hasContent())
- throw new IllegalStateException();
- _requestContentChunk.clear();
- }
+ if (_requestContentChunk == null)
+ _requestContentChunk = new ByteArrayBuffer(4096); // TODO configure
+ else
+ {
+ if (_requestContentChunk.hasContent())
+ throw new IllegalStateException();
+ _requestContentChunk.clear();
+ }
- int read = _requestContentChunk.capacity();
- int length = _requestContentSource.read(_requestContentChunk.array(),0,read);
- if (length >= 0)
- {
- _requestContentChunk.setPutIndex(length);
- return _requestContentChunk;
+ int read = _requestContentChunk.capacity();
+ int length = _requestContentSource.read(_requestContentChunk.array(),0,read);
+ if (length >= 0)
+ {
+ _requestContentChunk.setPutIndex(length);
+ return _requestContentChunk;
+ }
}
return null;
}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpExchangeTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpExchangeTest.java
index 677bb3414f..dc2856f8d1 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpExchangeTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpExchangeTest.java
@@ -127,6 +127,7 @@ public class HttpExchangeTest
*/
public void sender(final int nb, final boolean close) throws Exception
{
+ // System.err.printf("%nSENDER %d %s%n",nb,close);
_count.set(0);
final CountDownLatch complete = new CountDownLatch(nb);
final AtomicInteger allcontent = new AtomicInteger(nb);
@@ -299,7 +300,7 @@ public class HttpExchangeTest
httpExchange.setURI(uri);
httpExchange.setMethod(HttpMethods.GET);
_httpClient.send(httpExchange);
- int status = httpExchange.waitForDone();
+ int status = httpExchange.waitForDone();
//httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
String result=httpExchange.getResponseContent();
assertNotNull("Should have received response content", result);
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/AbstractGenerator.java b/jetty-http/src/main/java/org/eclipse/jetty/http/AbstractGenerator.java
index ca3f94c346..eab87b3786 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/AbstractGenerator.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/AbstractGenerator.java
@@ -422,7 +422,7 @@ public abstract class AbstractGenerator implements Generator
}
/* ------------------------------------------------------------ */
- public abstract long flushBuffer() throws IOException;
+ public abstract int flushBuffer() throws IOException;
/* ------------------------------------------------------------ */
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/Generator.java b/jetty-http/src/main/java/org/eclipse/jetty/http/Generator.java
index 2e0bc06a13..961c24d197 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/Generator.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/Generator.java
@@ -50,7 +50,7 @@ public interface Generator
void completeHeader(HttpFields responseFields, boolean last) throws IOException;
- long flushBuffer() throws IOException;
+ int flushBuffer() throws IOException;
int getContentBufferSize();
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java
index 7a12c84da7..85e5f96df1 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java
@@ -127,6 +127,17 @@ public class HttpGenerator extends AbstractGenerator
@Override
public void reset()
{
+ if (_persistent!=null && !_persistent && _endp!=null && !_endp.isOutputShutdown())
+ {
+ try
+ {
+ _endp.shutdownOutput();
+ }
+ catch(IOException e)
+ {
+ LOG.ignore(e);
+ }
+ }
super.reset();
if (_buffer!=null)
_buffer.clear();
@@ -161,16 +172,16 @@ public class HttpGenerator extends AbstractGenerator
if (_last || _state==STATE_END)
{
- LOG.debug("Ignoring extra content {}",content);
+ LOG.warn("Ignoring extra content {}",content);
content.clear();
return;
}
_last = last;
-
+
// Handle any unfinished business?
if (_content!=null && _content.length()>0 || _bufferChunked)
{
- if (!_endp.isOpen())
+ if (_endp.isOutputShutdown())
throw new EofException();
flushBuffer();
if (_content != null && _content.length()>0)
@@ -246,7 +257,7 @@ public class HttpGenerator extends AbstractGenerator
if (_last || _state==STATE_END)
{
- LOG.debug("Ignoring extra content {}",Byte.valueOf(b));
+ LOG.warn("Ignoring extra content {}",Byte.valueOf(b));
return false;
}
@@ -815,10 +826,11 @@ public class HttpGenerator extends AbstractGenerator
/* ------------------------------------------------------------ */
@Override
- public long flushBuffer() throws IOException
+ public int flushBuffer() throws IOException
{
try
{
+
if (_state == STATE_HEADER)
throw new IllegalStateException("State==HEADER");
@@ -838,79 +850,92 @@ public class HttpGenerator extends AbstractGenerator
int total= 0;
int len = -1;
- int to_flush = ((_header != null && _header.length() > 0)?4:0) | ((_buffer != null && _buffer.length() > 0)?2:0) | ((_bypass && _content != null && _content.length() > 0)?1:0);
- switch (to_flush)
+ int to_flush =
+ ((_header != null && _header.length() > 0)?4:0) |
+ ((_buffer != null && _buffer.length() > 0)?2:0) |
+ ((_bypass && _content != null && _content.length() > 0)?1:0);
+ int last_flush;
+
+ do
{
- case 7:
- throw new IllegalStateException(); // should never happen!
- case 6:
- len = _endp.flush(_header, _buffer, null);
- break;
- case 5:
- len = _endp.flush(_header, _content, null);
- break;
- case 4:
- len = _endp.flush(_header);
- break;
- case 3:
- len = _endp.flush(_buffer, _content, null);
- break;
- case 2:
- len = _endp.flush(_buffer);
- break;
- case 1:
- len = _endp.flush(_content);
- break;
- case 0:
+ last_flush=to_flush;
+ switch (to_flush)
{
- // Nothing more we can write now.
- if (_header != null)
- _header.clear();
+ case 7:
+ throw new IllegalStateException(); // should never happen!
+ case 6:
+ len = _endp.flush(_header, _buffer, null);
+ break;
+ case 5:
+ len = _endp.flush(_header, _content, null);
+ break;
+ case 4:
+ len = _endp.flush(_header);
+ break;
+ case 3:
+ len = _endp.flush(_buffer, _content, null);
+ break;
+ case 2:
+ len = _endp.flush(_buffer);
+ break;
+ case 1:
+ len = _endp.flush(_content);
+ break;
+ case 0:
+ {
+ len=0;
+ // Nothing more we can write now.
+ if (_header != null)
+ _header.clear();
- _bypass = false;
- _bufferChunked = false;
+ _bypass = false;
+ _bufferChunked = false;
- if (_buffer != null)
- {
- _buffer.clear();
- if (_contentLength == HttpTokens.CHUNKED_CONTENT)
+ if (_buffer != null)
{
- // reserve some space for the chunk header
- _buffer.setPutIndex(CHUNK_SPACE);
- _buffer.setGetIndex(CHUNK_SPACE);
-
- // Special case handling for small left over buffer from
- // an addContent that caused a buffer flush.
- if (_content != null && _content.length() < _buffer.space() && _state != STATE_FLUSHING)
+ _buffer.clear();
+ if (_contentLength == HttpTokens.CHUNKED_CONTENT)
{
- _buffer.put(_content);
- _content.clear();
- _content=null;
+ // reserve some space for the chunk header
+ _buffer.setPutIndex(CHUNK_SPACE);
+ _buffer.setGetIndex(CHUNK_SPACE);
+
+ // Special case handling for small left over buffer from
+ // an addContent that caused a buffer flush.
+ if (_content != null && _content.length() < _buffer.space() && _state != STATE_FLUSHING)
+ {
+ _buffer.put(_content);
+ _content.clear();
+ _content=null;
+ }
}
}
- }
- // Are we completely finished for now?
- if (!_needCRLF && !_needEOC && (_content==null || _content.length()==0))
- {
- if (_state == STATE_FLUSHING)
+ // Are we completely finished for now?
+ if (!_needCRLF && !_needEOC && (_content==null || _content.length()==0))
{
- _state = STATE_END;
- }
-
- if (_state==STATE_END && _persistent != null && !_persistent && _status!=100 && _method==null)
- {
- _endp.shutdownOutput();
+ if (_state == STATE_FLUSHING)
+ _state = STATE_END;
+
+ if (_state==STATE_END && _persistent != null && !_persistent && _status!=100 && _method==null)
+ _endp.shutdownOutput();
}
+ else
+ // Try to prepare more to write.
+ prepareBuffers();
}
- else
- // Try to prepare more to write.
- prepareBuffers();
- }
- }
-
- if (len > 0)
- total+=len;
+ }
+
+ if (len > 0)
+ total+=len;
+
+ to_flush =
+ ((_header != null && _header.length() > 0)?4:0) |
+ ((_buffer != null && _buffer.length() > 0)?2:0) |
+ ((_bypass && _content != null && _content.length() > 0)?1:0);
+ }
+ // loop while progress is being made (OR we have prepared some buffers that might make progress)
+ while (len>0 || (to_flush!=0 && last_flush==0));
return total;
}
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java
index 04a6e26ec8..bd0f74dc9f 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java
@@ -11,7 +11,7 @@ public abstract class AbstractConnection implements Connection
private static final Logger LOG = Log.getLogger(AbstractConnection.class);
private final long _timeStamp;
- protected final EndPoint _endp;
+ public final EndPoint _endp; // TODO make private
public AbstractConnection(EndPoint endp)
{
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java
index 31660996c0..cb9cc818e2 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java
@@ -427,6 +427,9 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
}
/* ------------------------------------------------------------ */
+ /**
+ * @see org.eclipse.jetty.io.AsyncEndPoint#scheduleWrite()
+ */
public void scheduleWrite()
{
if (_writable==true)
@@ -435,6 +438,12 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
_writable=false;
updateKey();
}
+
+ // TODO remove
+ public boolean isWritable()
+ {
+ return _writable;
+ }
/* ------------------------------------------------------------ */
/**
diff --git a/jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedGenerator.java b/jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedGenerator.java
index b9c970207e..47d74c3d1e 100644
--- a/jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedGenerator.java
+++ b/jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedGenerator.java
@@ -252,7 +252,7 @@ public class NestedGenerator extends AbstractGenerator
/* ------------------------------------------------------------ */
@Override
- public long flushBuffer() throws IOException
+ public int flushBuffer() throws IOException
{
if (_state == STATE_HEADER)
throw new IllegalStateException("State==HEADER");
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java
index 99addd1c9b..f8c2124131 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java
@@ -30,7 +30,6 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
boolean some_progress=false;
boolean progress=true;
- // Loop while more in buffer
try
{
setCurrentConnection(this);
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpWriterTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpWriterTest.java
index 314afb2df9..3d21c41375 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpWriterTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpWriterTest.java
@@ -52,7 +52,7 @@ public class HttpWriterTest
}
@Override
- public long flushBuffer() throws IOException
+ public int flushBuffer() throws IOException
{
return 0;
}

Back to the top