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:
commit
2f2c9f2f3f
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue