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;
/* ------------------------------------------------------------ */
/** ContextHandlerCollection.
*
/**
* This {@link org.eclipse.jetty.server.handler.HandlerCollection} is creates a
* 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.
@ -87,10 +86,8 @@ public class ContextHandlerCollection extends HandlerCollection
protected Handlers newHandlers(Handler[] handlers)
{
if (handlers==null || handlers.length==0)
{
return null;
}
// Create map of contextPath to handler Branch
// A branch is a Handler that could contain 0 or more ContextHandlers
Map<String,Branch[]> path2Branches = new HashMap<>();
@ -133,7 +130,7 @@ public class ContextHandlerCollection extends HandlerCollection
continue loop;
}
}
break loop;
break;
}
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
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
@ -167,9 +161,6 @@ public class ContextHandlerCollection extends HandlerCollection
return;
Mapping mapping = (Mapping)handlers;
if (mapping==null)
return;
HttpChannelState async = baseRequest.getHttpChannelState();
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 resourceBase the base (root) Resource
* @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.
* <p>
@ -285,6 +277,7 @@ public class ContextHandlerCollection extends HandlerCollection
* </p>
* @param handler The handler to undeploy
*/
public void undeployHandler(Handler handler)
{
_serializedExecutor.execute(()-> removeHandler(handler));
}
@ -298,7 +291,6 @@ public class ContextHandlerCollection extends HandlerCollection
return _contextClass;
}
/* ------------------------------------------------------------ */
/**
* @param contextClass The class to use to add new Contexts
@ -338,7 +330,7 @@ public class ContextHandlerCollection extends HandlerCollection
Set<String> getContextPaths()
{
Set<String> set = new HashSet<String>();
Set<String> set = new HashSet<>();
for (ContextHandler context:_contexts)
set.add(context.getContextPath());
return set;
@ -380,7 +372,7 @@ public class ContextHandlerCollection extends HandlerCollection
Mapping(Handler[] handlers, int capacity)
{
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
@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)
{
@ -93,9 +93,9 @@ public class HandlerCollection extends AbstractHandlerContainer
while(true)
{
if(updateHandlers(_handlers.get(),newHandlers(handlers)))
if (updateHandlers(_handlers.get(), newHandlers(handlers)))
break;
};
}
}
/* ------------------------------------------------------------ */
@ -123,10 +123,11 @@ public class HandlerCollection extends AbstractHandlerContainer
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 false;
@ -143,28 +144,21 @@ public class HandlerCollection extends AbstractHandlerContainer
if (handlers==null)
return;
Handler[] h = handlers._handlers;
MultiException mex=null;
for (int i=0;i<h.length;i++)
for (Handler handler : handlers._handlers)
{
try
{
h[i].handle(target,baseRequest, request, response);
handler.handle(target, baseRequest, request, response);
}
catch(IOException e)
catch (IOException | RuntimeException e)
{
throw e;
}
catch(RuntimeException e)
catch (Exception e)
{
throw e;
}
catch(Exception e)
{
if (mex==null)
mex=new MultiException();
if (mex == null)
mex = new MultiException();
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.
* @see org.eclipse.jetty.server.server.HandlerContainer#addHandler(org.eclipse.jetty.server.server.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.
* @see org.eclipse.jetty.server.server.HandlerContainer#addHandler(org.eclipse.jetty.server.server.Handler)
*/
public void prependHandler(Handler handler)
{
@ -216,7 +210,6 @@ public class HandlerCollection extends AbstractHandlerContainer
while(true)
{
Handlers old = _handlers.get();
if (old==null || old._handlers.length==0)
break;
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.junit.jupiter.api.Assertions.assertTrue;
class SerializedExecutorTest
public class SerializedExecutorTest
{
@Test
public void test() throws Exception
{
@ -43,19 +42,19 @@ class SerializedExecutorTest
AtomicInteger ran = new AtomicInteger();
AtomicBoolean running = new AtomicBoolean();
SerializedExecutor executor = new SerializedExecutor();
final CountDownLatch start = new CountDownLatch(1);
final CountDownLatch stop = new CountDownLatch(threads);
final Random random = new Random();
CountDownLatch start = new CountDownLatch(1);
CountDownLatch stop = new CountDownLatch(threads);
Random random = new Random();
for (int t=threads; t-->0;)
for (int t = threads; t-- > 0; )
{
new Thread(()->
new Thread(() ->
{
try
{
start.await();
for (int l=loops; l-->0;)
for (int l = loops; l-- > 0; )
{
final AtomicInteger d = new AtomicInteger(depth);
executor.execute(new Runnable()
@ -75,7 +74,7 @@ class SerializedExecutorTest
Thread.sleep(random.nextInt(5));
}
}
catch(Throwable th)
catch (Throwable th)
{
th.printStackTrace();
}
@ -88,8 +87,6 @@ class SerializedExecutorTest
start.countDown();
assertTrue(stop.await(30, TimeUnit.SECONDS));
assertThat(ran.get(), Matchers.is(threads*loops*depth));
assertThat(ran.get(), Matchers.is(threads * loops * depth));
}
}
}