Mercurial Hosting > luan
diff src/org/eclipse/jetty/server/AsyncHttpConnection.java @ 802:3428c60d7cfc
replace jetty jars with source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 07 Sep 2016 21:15:48 -0600 |
parents | |
children | 8e9db0bbf4f9 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/eclipse/jetty/server/AsyncHttpConnection.java Wed Sep 07 21:15:48 2016 -0600 @@ -0,0 +1,220 @@ +// +// ======================================================================== +// Copyright (c) 1995-2014 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.server; + +import java.io.IOException; + +import org.eclipse.jetty.http.HttpException; +import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.io.AsyncEndPoint; +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.util.log.Log; +import org.eclipse.jetty.util.log.Logger; + + +/* ------------------------------------------------------------ */ +/** Asychronous Server HTTP connection + * + */ +public class AsyncHttpConnection extends AbstractHttpConnection implements AsyncConnection +{ + private final static int NO_PROGRESS_INFO = Integer.getInteger("org.mortbay.jetty.NO_PROGRESS_INFO",100); + private final static int NO_PROGRESS_CLOSE = Integer.getInteger("org.mortbay.jetty.NO_PROGRESS_CLOSE",200); + + private static final Logger LOG = Log.getLogger(AsyncHttpConnection.class); + private int _total_no_progress; + private final AsyncEndPoint _asyncEndp; + private boolean _readInterested = true; + + public AsyncHttpConnection(Connector connector, EndPoint endpoint, Server server) + { + super(connector,endpoint,server); + _asyncEndp=(AsyncEndPoint)endpoint; + } + + @Override + public Connection handle() throws IOException + { + Connection connection = this; + boolean some_progress=false; + boolean progress=true; + + try + { + setCurrentConnection(this); + + // don't check for idle while dispatched (unless blocking IO is done). + _asyncEndp.setCheckForIdle(false); + + + // While progress and the connection has not changed + while (progress && connection==this) + { + progress=false; + try + { + // Handle resumed request + if (_request._async.isAsync()) + { + if (_request._async.isDispatchable()) + handleRequest(); + } + // else Parse more input + else if (!_parser.isComplete() && _parser.parseAvailable()) + progress=true; + + // Generate more output + if (_generator.isCommitted() && !_generator.isComplete() && !_endp.isOutputShutdown() && !_request.getAsyncContinuation().isAsyncStarted()) + if (_generator.flushBuffer()>0) + progress=true; + + // Flush output + _endp.flush(); + + // Has any IO been done by the endpoint itself since last loop + if (_asyncEndp.hasProgressed()) + progress=true; + } + catch (HttpException e) + { + if (LOG.isDebugEnabled()) + { + LOG.debug("uri="+_uri); + LOG.debug("fields="+_requestFields); + LOG.debug(e); + } + progress=true; + _generator.sendError(e.getStatus(), e.getReason(), null, true); + } + finally + { + some_progress|=progress; + // Is this request/response round complete and are fully flushed? + boolean parserComplete = _parser.isComplete(); + boolean generatorComplete = _generator.isComplete(); + boolean complete = parserComplete && generatorComplete; + if (parserComplete) + { + if (generatorComplete) + { + // Reset the parser/generator + progress=true; + + // look for a switched connection instance? + if (_response.getStatus()==HttpStatus.SWITCHING_PROTOCOLS_101) + { + Connection switched=(Connection)_request.getAttribute("org.eclipse.jetty.io.Connection"); + if (switched!=null) + connection=switched; + } + + reset(); + + // TODO Is this still required? + if (!_generator.isPersistent() && !_endp.isOutputShutdown()) + { + LOG.warn("Safety net oshut!!! IF YOU SEE THIS, PLEASE RAISE BUGZILLA"); + _endp.shutdownOutput(); + } + } + else + { + // We have finished parsing, but not generating so + // we must not be interested in reading until we + // have finished generating and we reset the generator + _readInterested = false; + LOG.debug("Disabled read interest while writing response {}", _endp); + } + } + + if (!complete && _request.getAsyncContinuation().isAsyncStarted()) + { + // The request is suspended, so even though progress has been made, + // exit the while loop by setting progress to false + LOG.debug("suspended {}",this); + progress=false; + } + } + } + } + finally + { + setCurrentConnection(null); + + // If we are not suspended + if (!_request.getAsyncContinuation().isAsyncStarted()) + { + // return buffers + _parser.returnBuffers(); + _generator.returnBuffers(); + + // reenable idle checking unless request is suspended + _asyncEndp.setCheckForIdle(true); + } + + // Safety net to catch spinning + if (some_progress) + _total_no_progress=0; + else + { + _total_no_progress++; + if (NO_PROGRESS_INFO>0 && _total_no_progress%NO_PROGRESS_INFO==0 && (NO_PROGRESS_CLOSE<=0 || _total_no_progress< NO_PROGRESS_CLOSE)) + LOG.info("EndPoint making no progress: "+_total_no_progress+" "+_endp+" "+this); + if (NO_PROGRESS_CLOSE>0 && _total_no_progress==NO_PROGRESS_CLOSE) + { + LOG.warn("Closing EndPoint making no progress: "+_total_no_progress+" "+_endp+" "+this); + if (_endp instanceof SelectChannelEndPoint) + ((SelectChannelEndPoint)_endp).getChannel().close(); + } + } + } + return connection; + } + + public void onInputShutdown() throws IOException + { + // If we don't have a committed response and we are not suspended + if (_generator.isIdle() && !_request.getAsyncContinuation().isSuspended()) + { + // then no more can happen, so close. + _endp.close(); + } + + // Make idle parser seek EOF + if (_parser.isIdle()) + _parser.setPersistent(false); + } + + @Override + public void reset() + { + _readInterested = true; + LOG.debug("Enabled read interest {}", _endp); + super.reset(); + } + + @Override + public boolean isSuspended() + { + return !_readInterested || super.isSuspended(); + } +}