Skip to content

Commit

Permalink
Merged branch 'jetty-11.0.x' into 'jetty-12.0.x'.
Browse files Browse the repository at this point in the history
Signed-off-by: Simone Bordet <[email protected]>
  • Loading branch information
sbordet committed Jul 17, 2023
2 parents bd80b67 + af41787 commit c19a581
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
* 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);

Expand Down Expand Up @@ -133,7 +133,6 @@ private enum SubStrategy
private final Executor _executor;
private final TryExecutor _tryExecutor;
private final Executor _virtualExecutor;
private final Runnable _runPendingProducer = () -> tryProduce(true);
private final AtomicBiInteger _state = new AtomicBiInteger();

/**
Expand Down Expand Up @@ -187,7 +186,7 @@ public void dispatch()
if (LOG.isDebugEnabled())
LOG.debug("{} dispatch {}", this, execute);
if (execute)
_executor.execute(_runPendingProducer);
_executor.execute(this);
}

@Override
Expand All @@ -196,6 +195,12 @@ public void produce()
tryProduce(false);
}

@Override
public void run()
{
tryProduce(true);
}

/**
* Tries to become the producing thread and then produces and consumes tasks.
*
Expand Down Expand Up @@ -330,7 +335,7 @@ private SubStrategy selectSubStrategy(Runnable task, boolean nonBlocking)
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++;
Expand Down Expand Up @@ -371,7 +376,7 @@ private SubStrategy selectSubStrategy(Runnable task, boolean nonBlocking)
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++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -99,6 +101,8 @@ public ServletChannel(ServletContextHandler servletContextHandler, ConnectionMet
_state = new ServletRequestState(this);
_httpInput = new HttpInput(this);
_httpOutput = new HttpOutput(this);
_requestDispatchable = new RequestDispatchable();
_asyncDispatchable = new AsyncDispatchable();
}

public ConnectionMetaData getConnectionMetaData()
Expand Down Expand Up @@ -476,73 +480,13 @@ public boolean handle()

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;
}

Expand Down Expand Up @@ -591,7 +535,7 @@ public boolean handle()
{
// 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();
}
}
Expand Down Expand Up @@ -949,4 +893,97 @@ interface Dispatchable
{
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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -109,8 +111,9 @@ public HttpChannel(ContextHandler contextHandler, ConnectionMetaData connectionM
_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 {} -> {},{},{}",
Expand Down Expand Up @@ -567,17 +570,14 @@ public boolean handle()
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;
}

Expand Down Expand Up @@ -616,11 +616,7 @@ public boolean handle()
break;
}

dispatch(DispatcherType.ERROR, () ->
{
errorHandler.handle(null, _request, _request, _response);
_request.setHandled(true);
});
dispatch(DispatcherType.ERROR, new ErrorDispatchable(errorHandler));
}
catch (Throwable x)
{
Expand Down Expand Up @@ -1661,4 +1657,39 @@ public void onComplete(Request request)
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);
}
}
}

0 comments on commit c19a581

Please sign in to comment.