Merge branch 'jetty-9.4.x-3361-thread-safe-setHandlers' of github.com:eclipse/jetty.project into jetty-9.4.x-3361-thread-safe-setHandlers

This commit is contained in:
Greg Wilkins 2019-03-21 10:05:45 +11:00
commit 2f2c9f2f3f
3 changed files with 37 additions and 55 deletions

View File

@ -43,8 +43,7 @@ import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.SerializedExecutor; import org.eclipse.jetty.util.thread.SerializedExecutor;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** ContextHandlerCollection. /**
*
* This {@link org.eclipse.jetty.server.handler.HandlerCollection} is creates a * This {@link org.eclipse.jetty.server.handler.HandlerCollection} is creates a
* Map of contexts to it's contained handlers based * Map of contexts to it's contained handlers based
* on the context path and virtual hosts of any contained {@link org.eclipse.jetty.server.handler.ContextHandler}s. * on the context path and virtual hosts of any contained {@link org.eclipse.jetty.server.handler.ContextHandler}s.
@ -87,10 +86,8 @@ public class ContextHandlerCollection extends HandlerCollection
protected Handlers newHandlers(Handler[] handlers) protected Handlers newHandlers(Handler[] handlers)
{ {
if (handlers==null || handlers.length==0) if (handlers==null || handlers.length==0)
{
return null; return null;
}
// Create map of contextPath to handler Branch // Create map of contextPath to handler Branch
// A branch is a Handler that could contain 0 or more ContextHandlers // A branch is a Handler that could contain 0 or more ContextHandlers
Map<String,Branch[]> path2Branches = new HashMap<>(); Map<String,Branch[]> path2Branches = new HashMap<>();
@ -133,7 +130,7 @@ public class ContextHandlerCollection extends HandlerCollection
continue loop; continue loop;
} }
} }
break loop; break;
} }
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
@ -156,9 +153,6 @@ public class ContextHandlerCollection extends HandlerCollection
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/*
* @see org.eclipse.jetty.server.server.Handler#handle(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
*/
@Override @Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{ {
@ -167,9 +161,6 @@ public class ContextHandlerCollection extends HandlerCollection
return; return;
Mapping mapping = (Mapping)handlers; Mapping mapping = (Mapping)handlers;
if (mapping==null)
return;
HttpChannelState async = baseRequest.getHttpChannelState(); HttpChannelState async = baseRequest.getHttpChannelState();
if (async.isAsync()) if (async.isAsync())
{ {
@ -230,7 +221,9 @@ public class ContextHandlerCollection extends HandlerCollection
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** Add a context handler. /**
* Adds a context handler.
*
* @param contextPath The context path to add * @param contextPath The context path to add
* @param resourceBase the base (root) Resource * @param resourceBase the base (root) Resource
* @return the ContextHandler just added * @return the ContextHandler just added
@ -273,7 +266,6 @@ public class ContextHandlerCollection extends HandlerCollection
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public void undeployHandler(Handler handler)
/** /**
* Thread safe undeploy of a Handler. * Thread safe undeploy of a Handler.
* <p> * <p>
@ -285,6 +277,7 @@ public class ContextHandlerCollection extends HandlerCollection
* </p> * </p>
* @param handler The handler to undeploy * @param handler The handler to undeploy
*/ */
public void undeployHandler(Handler handler)
{ {
_serializedExecutor.execute(()-> removeHandler(handler)); _serializedExecutor.execute(()-> removeHandler(handler));
} }
@ -298,7 +291,6 @@ public class ContextHandlerCollection extends HandlerCollection
return _contextClass; return _contextClass;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @param contextClass The class to use to add new Contexts * @param contextClass The class to use to add new Contexts
@ -338,7 +330,7 @@ public class ContextHandlerCollection extends HandlerCollection
Set<String> getContextPaths() Set<String> getContextPaths()
{ {
Set<String> set = new HashSet<String>(); Set<String> set = new HashSet<>();
for (ContextHandler context:_contexts) for (ContextHandler context:_contexts)
set.add(context.getContextPath()); set.add(context.getContextPath());
return set; return set;
@ -380,7 +372,7 @@ public class ContextHandlerCollection extends HandlerCollection
Mapping(Handler[] handlers, int capacity) Mapping(Handler[] handlers, int capacity)
{ {
super(handlers); super(handlers);
_pathBranches = new ArrayTernaryTrie(false, capacity); _pathBranches = new ArrayTernaryTrie<>(false, capacity);
} }
} }
} }

View File

@ -72,7 +72,7 @@ public class HandlerCollection extends AbstractHandlerContainer
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @return Returns the handlers. * @return the array of handlers.
*/ */
@Override @Override
@ManagedAttribute(value="Wrapped handlers", readonly=true) @ManagedAttribute(value="Wrapped handlers", readonly=true)
@ -84,7 +84,7 @@ public class HandlerCollection extends AbstractHandlerContainer
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @param handlers The handlers to set. * @param handlers the array of handlers to set.
*/ */
public void setHandlers(Handler[] handlers) public void setHandlers(Handler[] handlers)
{ {
@ -93,9 +93,9 @@ public class HandlerCollection extends AbstractHandlerContainer
while(true) while(true)
{ {
if(updateHandlers(_handlers.get(),newHandlers(handlers))) if (updateHandlers(_handlers.get(), newHandlers(handlers)))
break; break;
}; }
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -123,10 +123,11 @@ public class HandlerCollection extends AbstractHandlerContainer
handler.setServer(getServer()); handler.setServer(getServer());
} }
if (_handlers.compareAndSet(old, handlers))
if (_handlers.compareAndSet(old,handlers))
{ {
updateBeans(old==null?null:old._handlers,handlers==null?null:handlers._handlers); Handler[] oldBeans = old == null ? null : old._handlers;
Handler[] newBeans = handlers == null ? null : handlers._handlers;
updateBeans(oldBeans, newBeans);
return true; return true;
} }
return false; return false;
@ -143,28 +144,21 @@ public class HandlerCollection extends AbstractHandlerContainer
if (handlers==null) if (handlers==null)
return; return;
Handler[] h = handlers._handlers;
MultiException mex=null; MultiException mex=null;
for (Handler handler : handlers._handlers)
for (int i=0;i<h.length;i++)
{ {
try try
{ {
h[i].handle(target,baseRequest, request, response); handler.handle(target, baseRequest, request, response);
} }
catch(IOException e) catch (IOException | RuntimeException e)
{ {
throw e; throw e;
} }
catch(RuntimeException e) catch (Exception e)
{ {
throw e; if (mex == null)
} mex = new MultiException();
catch(Exception e)
{
if (mex==null)
mex=new MultiException();
mex.add(e); mex.add(e);
} }
} }
@ -179,9 +173,9 @@ public class HandlerCollection extends AbstractHandlerContainer
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/* Add a handler. /**
* Adds a handler.
* This implementation adds the passed handler to the end of the existing collection of handlers. * This implementation adds the passed handler to the end of the existing collection of handlers.
* @see org.eclipse.jetty.server.server.HandlerContainer#addHandler(org.eclipse.jetty.server.server.Handler)
*/ */
public void addHandler(Handler handler) public void addHandler(Handler handler)
{ {
@ -195,9 +189,9 @@ public class HandlerCollection extends AbstractHandlerContainer
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/* Prepend a handler. /**
* Prepends a handler.
* This implementation adds the passed handler to the start of the existing collection of handlers. * This implementation adds the passed handler to the start of the existing collection of handlers.
* @see org.eclipse.jetty.server.server.HandlerContainer#addHandler(org.eclipse.jetty.server.server.Handler)
*/ */
public void prependHandler(Handler handler) public void prependHandler(Handler handler)
{ {
@ -216,7 +210,6 @@ public class HandlerCollection extends AbstractHandlerContainer
while(true) while(true)
{ {
Handlers old = _handlers.get(); Handlers old = _handlers.get();
if (old==null || old._handlers.length==0) if (old==null || old._handlers.length==0)
break; break;
Handlers handlers = newHandlers(ArrayUtil.removeFromArray(old._handlers, handler)); Handlers handlers = newHandlers(ArrayUtil.removeFromArray(old._handlers, handler));

View File

@ -30,9 +30,8 @@ import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
class SerializedExecutorTest public class SerializedExecutorTest
{ {
@Test @Test
public void test() throws Exception public void test() throws Exception
{ {
@ -43,19 +42,19 @@ class SerializedExecutorTest
AtomicInteger ran = new AtomicInteger(); AtomicInteger ran = new AtomicInteger();
AtomicBoolean running = new AtomicBoolean(); AtomicBoolean running = new AtomicBoolean();
SerializedExecutor executor = new SerializedExecutor(); SerializedExecutor executor = new SerializedExecutor();
final CountDownLatch start = new CountDownLatch(1); CountDownLatch start = new CountDownLatch(1);
final CountDownLatch stop = new CountDownLatch(threads); CountDownLatch stop = new CountDownLatch(threads);
final Random random = new Random(); Random random = new Random();
for (int t=threads; t-->0;) for (int t = threads; t-- > 0; )
{ {
new Thread(()-> new Thread(() ->
{ {
try try
{ {
start.await(); start.await();
for (int l=loops; l-->0;) for (int l = loops; l-- > 0; )
{ {
final AtomicInteger d = new AtomicInteger(depth); final AtomicInteger d = new AtomicInteger(depth);
executor.execute(new Runnable() executor.execute(new Runnable()
@ -75,7 +74,7 @@ class SerializedExecutorTest
Thread.sleep(random.nextInt(5)); Thread.sleep(random.nextInt(5));
} }
} }
catch(Throwable th) catch (Throwable th)
{ {
th.printStackTrace(); th.printStackTrace();
} }
@ -88,8 +87,6 @@ class SerializedExecutorTest
start.countDown(); start.countDown();
assertTrue(stop.await(30, TimeUnit.SECONDS)); assertTrue(stop.await(30, TimeUnit.SECONDS));
assertThat(ran.get(), Matchers.is(threads*loops*depth)); assertThat(ran.get(), Matchers.is(threads * loops * depth));
} }
}
}