Merged branch 'jetty-11.0.x' into 'jetty-12.0.x'.
Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
commit
c19a5817f9
|
@ -91,7 +91,7 @@ import org.slf4j.LoggerFactory;
|
|||
* that says that a hunter should eat (i.e. consume) what they kill (i.e. produced).</p>
|
||||
*/
|
||||
@ManagedObject("Adaptive execution strategy")
|
||||
public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements ExecutionStrategy
|
||||
public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements ExecutionStrategy, Runnable
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AdaptiveExecutionStrategy.class);
|
||||
|
||||
|
@ -133,7 +133,6 @@ public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements Exe
|
|||
private final Executor _executor;
|
||||
private final TryExecutor _tryExecutor;
|
||||
private final Executor _virtualExecutor;
|
||||
private final Runnable _runPendingProducer = () -> tryProduce(true);
|
||||
private final AtomicBiInteger _state = new AtomicBiInteger();
|
||||
|
||||
/**
|
||||
|
@ -187,7 +186,7 @@ public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements Exe
|
|||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} dispatch {}", this, execute);
|
||||
if (execute)
|
||||
_executor.execute(_runPendingProducer);
|
||||
_executor.execute(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -196,6 +195,12 @@ public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements Exe
|
|||
tryProduce(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
tryProduce(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to become the producing thread and then produces and consumes tasks.
|
||||
*
|
||||
|
@ -330,7 +335,7 @@ public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements Exe
|
|||
int pending = AtomicBiInteger.getHi(biState);
|
||||
|
||||
// If a pending producer is available or one can be started
|
||||
if (tryExecuted || pending <= 0 && _tryExecutor.tryExecute(_runPendingProducer))
|
||||
if (tryExecuted || pending <= 0 && _tryExecutor.tryExecute(this))
|
||||
{
|
||||
tryExecuted = true;
|
||||
pending++;
|
||||
|
@ -371,7 +376,7 @@ public class AdaptiveExecutionStrategy extends ContainerLifeCycle implements Exe
|
|||
int pending = AtomicBiInteger.getHi(biState);
|
||||
|
||||
// If a pending producer is available or one can be started
|
||||
if (tryExecuted || pending <= 0 && _tryExecutor.tryExecute(_runPendingProducer))
|
||||
if (tryExecuted || pending <= 0 && _tryExecutor.tryExecute(this))
|
||||
{
|
||||
tryExecuted = true;
|
||||
pending++;
|
||||
|
|
|
@ -79,6 +79,8 @@ public class ServletChannel
|
|||
private final AtomicLong _requests = new AtomicLong();
|
||||
private final HttpInput _httpInput;
|
||||
private final HttpOutput _httpOutput;
|
||||
private final Dispatchable _requestDispatchable;
|
||||
private final Dispatchable _asyncDispatchable;
|
||||
private ServletContextRequest _servletContextRequest;
|
||||
private Request _request;
|
||||
private Response _response;
|
||||
|
@ -99,6 +101,8 @@ public class ServletChannel
|
|||
_state = new ServletRequestState(this);
|
||||
_httpInput = new HttpInput(this);
|
||||
_httpOutput = new HttpOutput(this);
|
||||
_requestDispatchable = new RequestDispatchable();
|
||||
_asyncDispatchable = new AsyncDispatchable();
|
||||
}
|
||||
|
||||
public ConnectionMetaData getConnectionMetaData()
|
||||
|
@ -476,73 +480,13 @@ public class ServletChannel
|
|||
|
||||
case DISPATCH:
|
||||
{
|
||||
dispatch(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
_context.getServletContextHandler().requestInitialized(_servletContextRequest, _servletContextRequest.getServletApiRequest());
|
||||
|
||||
ServletHandler servletHandler = _context.getServletContextHandler().getServletHandler();
|
||||
ServletHandler.MappedServlet mappedServlet = _servletContextRequest.getMatchedResource().getResource();
|
||||
|
||||
mappedServlet.handle(servletHandler, Request.getPathInContext(_servletContextRequest), _servletContextRequest.getServletApiRequest(), _servletContextRequest.getHttpServletResponse());
|
||||
}
|
||||
finally
|
||||
{
|
||||
_context.getServletContextHandler().requestDestroyed(_servletContextRequest, _servletContextRequest.getServletApiRequest());
|
||||
}
|
||||
});
|
||||
|
||||
dispatch(_requestDispatchable);
|
||||
break;
|
||||
}
|
||||
|
||||
case ASYNC_DISPATCH:
|
||||
{
|
||||
dispatch(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
_context.getServletContextHandler().requestInitialized(_servletContextRequest, _servletContextRequest.getServletApiRequest());
|
||||
|
||||
HttpURI uri;
|
||||
String pathInContext;
|
||||
AsyncContextEvent asyncContextEvent = _state.getAsyncContextEvent();
|
||||
String dispatchString = asyncContextEvent.getDispatchPath();
|
||||
if (dispatchString != null)
|
||||
{
|
||||
String contextPath = _context.getContextPath();
|
||||
HttpURI.Immutable dispatchUri = HttpURI.from(dispatchString);
|
||||
pathInContext = URIUtil.canonicalPath(dispatchUri.getPath());
|
||||
uri = HttpURI.build(_servletContextRequest.getHttpURI())
|
||||
.path(URIUtil.addPaths(contextPath, pathInContext))
|
||||
.query(dispatchUri.getQuery());
|
||||
}
|
||||
else
|
||||
{
|
||||
uri = asyncContextEvent.getBaseURI();
|
||||
if (uri == null)
|
||||
{
|
||||
uri = _servletContextRequest.getHttpURI();
|
||||
pathInContext = Request.getPathInContext(_servletContextRequest);
|
||||
}
|
||||
else
|
||||
{
|
||||
pathInContext = uri.getCanonicalPath();
|
||||
if (_context.getContextPath().length() > 1)
|
||||
pathInContext = pathInContext.substring(_context.getContextPath().length());
|
||||
}
|
||||
}
|
||||
// We first worked with the core pathInContext above, but now need to convert to servlet style
|
||||
String decodedPathInContext = URIUtil.decodePath(pathInContext);
|
||||
|
||||
Dispatcher dispatcher = new Dispatcher(getServletContextHandler(), uri, decodedPathInContext);
|
||||
dispatcher.async(asyncContextEvent.getSuppliedRequest(), asyncContextEvent.getSuppliedResponse());
|
||||
}
|
||||
finally
|
||||
{
|
||||
_context.getServletContextHandler().requestDestroyed(_servletContextRequest, _servletContextRequest.getServletApiRequest());
|
||||
}
|
||||
});
|
||||
dispatch(_asyncDispatchable);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -591,7 +535,7 @@ public class ServletChannel
|
|||
{
|
||||
// We do not notify ServletRequestListener on this dispatch because it might not
|
||||
// be dispatched to an error page, so we delegate this responsibility to the ErrorHandler.
|
||||
dispatch(() -> errorHandler.handle(_servletContextRequest, getServletContextResponse(), blocker));
|
||||
dispatch(new ErrorDispatchable(errorHandler, blocker));
|
||||
blocker.block();
|
||||
}
|
||||
}
|
||||
|
@ -949,4 +893,97 @@ public class ServletChannel
|
|||
{
|
||||
void dispatch() throws Exception;
|
||||
}
|
||||
|
||||
private class RequestDispatchable implements Dispatchable
|
||||
{
|
||||
@Override
|
||||
public void dispatch() throws Exception
|
||||
{
|
||||
ServletContextHandler servletContextHandler = getServletContextHandler();
|
||||
ServletContextRequest servletContextRequest = getServletContextRequest();
|
||||
ServletApiRequest servletApiRequest = servletContextRequest.getServletApiRequest();
|
||||
try
|
||||
{
|
||||
servletContextHandler.requestInitialized(servletContextRequest, servletApiRequest);
|
||||
ServletHandler servletHandler = servletContextHandler.getServletHandler();
|
||||
ServletHandler.MappedServlet mappedServlet = servletContextRequest.getMatchedResource().getResource();
|
||||
mappedServlet.handle(servletHandler, Request.getPathInContext(servletContextRequest), servletApiRequest, servletContextRequest.getHttpServletResponse());
|
||||
}
|
||||
finally
|
||||
{
|
||||
servletContextHandler.requestDestroyed(servletContextRequest, servletApiRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class AsyncDispatchable implements Dispatchable
|
||||
{
|
||||
@Override
|
||||
public void dispatch() throws Exception
|
||||
{
|
||||
ServletContextHandler servletContextHandler = getServletContextHandler();
|
||||
ServletContextRequest servletContextRequest = getServletContextRequest();
|
||||
ServletApiRequest servletApiRequest = servletContextRequest.getServletApiRequest();
|
||||
try
|
||||
{
|
||||
servletContextHandler.requestInitialized(servletContextRequest, servletApiRequest);
|
||||
|
||||
HttpURI uri;
|
||||
String pathInContext;
|
||||
AsyncContextEvent asyncContextEvent = _state.getAsyncContextEvent();
|
||||
String dispatchString = asyncContextEvent.getDispatchPath();
|
||||
if (dispatchString != null)
|
||||
{
|
||||
String contextPath = _context.getContextPath();
|
||||
HttpURI.Immutable dispatchUri = HttpURI.from(dispatchString);
|
||||
pathInContext = URIUtil.canonicalPath(dispatchUri.getPath());
|
||||
uri = HttpURI.build(servletContextRequest.getHttpURI())
|
||||
.path(URIUtil.addPaths(contextPath, pathInContext))
|
||||
.query(dispatchUri.getQuery());
|
||||
}
|
||||
else
|
||||
{
|
||||
uri = asyncContextEvent.getBaseURI();
|
||||
if (uri == null)
|
||||
{
|
||||
uri = servletContextRequest.getHttpURI();
|
||||
pathInContext = Request.getPathInContext(servletContextRequest);
|
||||
}
|
||||
else
|
||||
{
|
||||
pathInContext = uri.getCanonicalPath();
|
||||
int length = _context.getContextPath().length();
|
||||
if (length > 1)
|
||||
pathInContext = pathInContext.substring(length);
|
||||
}
|
||||
}
|
||||
// We first worked with the core pathInContext above, but now need to convert to servlet style
|
||||
String decodedPathInContext = URIUtil.decodePath(pathInContext);
|
||||
Dispatcher dispatcher = new Dispatcher(servletContextHandler, uri, decodedPathInContext);
|
||||
dispatcher.async(asyncContextEvent.getSuppliedRequest(), asyncContextEvent.getSuppliedResponse());
|
||||
}
|
||||
finally
|
||||
{
|
||||
servletContextHandler.requestDestroyed(servletContextRequest, servletApiRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ErrorDispatchable implements Dispatchable
|
||||
{
|
||||
private final Request.Handler _errorHandler;
|
||||
private final Callback _callback;
|
||||
|
||||
private ErrorDispatchable(Request.Handler errorHandler, Callback callback)
|
||||
{
|
||||
_errorHandler = errorHandler;
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatch() throws Exception
|
||||
{
|
||||
_errorHandler.handle(getServletContextRequest(), getServletContextResponse(), _callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,6 +84,8 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
private final Request _request;
|
||||
private final Response _response;
|
||||
private final Listener _combinedListener;
|
||||
private final Dispatchable _requestDispatcher;
|
||||
private final Dispatchable _asyncDispatcher;
|
||||
@Deprecated
|
||||
private final List<Listener> _transientListeners = new ArrayList<>();
|
||||
private MetaData.Response _committedMetaData;
|
||||
|
@ -109,8 +111,9 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
_request = new Request(this, newHttpInput());
|
||||
_response = new Response(this, newHttpOutput());
|
||||
_executor = _connector.getServer().getThreadPool();
|
||||
|
||||
_combinedListener = new HttpChannelListeners(_connector.getBeans(Listener.class));
|
||||
_requestDispatcher = new RequestDispatchable();
|
||||
_asyncDispatcher = new AsyncDispatchable();
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("new {} -> {},{},{}",
|
||||
|
@ -567,17 +570,14 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
if (!_request.hasMetaData())
|
||||
throw new IllegalStateException("state=" + _state);
|
||||
|
||||
dispatch(DispatcherType.REQUEST, () ->
|
||||
{
|
||||
_contextHandler.handle(HttpChannel.this);
|
||||
});
|
||||
dispatch(DispatcherType.REQUEST, _requestDispatcher);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ASYNC_DISPATCH:
|
||||
{
|
||||
dispatch(DispatcherType.ASYNC, () -> _contextHandler.handleAsync(this));
|
||||
dispatch(DispatcherType.ASYNC, _asyncDispatcher);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -616,11 +616,7 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
break;
|
||||
}
|
||||
|
||||
dispatch(DispatcherType.ERROR, () ->
|
||||
{
|
||||
errorHandler.handle(null, _request, _request, _response);
|
||||
_request.setHandled(true);
|
||||
});
|
||||
dispatch(DispatcherType.ERROR, new ErrorDispatchable(errorHandler));
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
|
@ -1661,4 +1657,39 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
request.getHttpChannel().notifyEvent1(listener -> listener::onComplete, request);
|
||||
}
|
||||
}
|
||||
|
||||
private class RequestDispatchable implements Dispatchable
|
||||
{
|
||||
@Override
|
||||
public void dispatch() throws IOException, ServletException
|
||||
{
|
||||
_contextHandler.handle(HttpChannel.this);
|
||||
}
|
||||
}
|
||||
|
||||
private class AsyncDispatchable implements Dispatchable
|
||||
{
|
||||
@Override
|
||||
public void dispatch() throws IOException, ServletException
|
||||
{
|
||||
_contextHandler.handleAsync(HttpChannel.this);
|
||||
}
|
||||
}
|
||||
|
||||
private class ErrorDispatchable implements Dispatchable
|
||||
{
|
||||
private final ErrorHandler _errorHandler;
|
||||
|
||||
public ErrorDispatchable(ErrorHandler errorHandler)
|
||||
{
|
||||
_errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatch() throws IOException, ServletException
|
||||
{
|
||||
_errorHandler.handle(null, _request, _request, _response);
|
||||
_request.setHandled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue