Repository: incubator-reef Updated Branches: refs/heads/master c2e791628 -> 1ea4d64b1
[REEF-591] Use TcpPortProvider in HttpServerImpl This adds `TcpPortProvider` usage in `HttpServerImpl`. JIRA: [REEF-591](https://issues.apache.org/jira/browse/REEF-591) Pull Request: Thos closes #373 Project: http://git-wip-us.apache.org/repos/asf/incubator-reef/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-reef/commit/1ea4d64b Tree: http://git-wip-us.apache.org/repos/asf/incubator-reef/tree/1ea4d64b Diff: http://git-wip-us.apache.org/repos/asf/incubator-reef/diff/1ea4d64b Branch: refs/heads/master Commit: 1ea4d64b14260db063cf22a3d791795b1af5bc97 Parents: c2e7916 Author: Beysim Sezgin <[email protected]> Authored: Fri Aug 14 16:44:23 2015 -0700 Committer: Markus Weimer <[email protected]> Committed: Tue Aug 18 08:40:19 2015 -0700 ---------------------------------------------------------------------- .../apache/reef/webserver/HttpServerImpl.java | 51 +++++++++++----- .../apache/reef/webserver/MaxPortNumber.java | 2 + .../apache/reef/webserver/MaxRetryAttempts.java | 2 + .../apache/reef/webserver/MinPortNumber.java | 2 + .../org/apache/reef/webserver/PortNumber.java | 8 ++- .../apache/reef/webserver/TestHttpServer.java | 62 +++++++++++++++++++- 6 files changed, 108 insertions(+), 19 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1ea4d64b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/HttpServerImpl.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/HttpServerImpl.java b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/HttpServerImpl.java index 8935ff0..b76ea77 100644 --- a/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/HttpServerImpl.java +++ b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/HttpServerImpl.java @@ -21,10 +21,12 @@ package org.apache.reef.webserver; import org.apache.reef.tang.annotations.Parameter; import org.apache.reef.util.logging.LoggingScope; import org.apache.reef.util.logging.LoggingScopeFactory; +import org.apache.reef.wake.remote.ports.TcpPortProvider; import org.mortbay.jetty.Server; import javax.inject.Inject; import java.net.BindException; +import java.util.Iterator; import java.util.logging.Level; import java.util.logging.Logger; @@ -70,39 +72,56 @@ public final class HttpServerImpl implements HttpServer { @Parameter(MaxPortNumber.class) final int maxPortNumber, @Parameter(MinPortNumber.class) final int minPortNumber, @Parameter(MaxRetryAttempts.class) final int maxRetryAttempts, + final TcpPortProvider tcpPortProvider, final LoggingScopeFactory loggingScopeFactory) throws Exception { this.loggingScopeFactory = loggingScopeFactory; + this.jettyHandler = jettyHandler; + int availablePort = portNumber; + Server srv = null; + try (final LoggingScope ls = this.loggingScopeFactory.httpServer()) { - this.jettyHandler = jettyHandler; - int availablePort = portNumber; - Server srv = null; - boolean found = false; - for (int attempt = 0; attempt < maxRetryAttempts; ++attempt) { - if (attempt > 0) { - availablePort = getNextPort(maxPortNumber, minPortNumber); + if (portNumber != Integer.parseInt(PortNumber.DEFAULT_VALUE)) { + // legacy path to be removed + for (int attempt = 0; attempt < maxRetryAttempts && srv == null; ++attempt) { + if (attempt > 0) { + // first attempt should be portNumber passed in + availablePort = getNextPort(maxPortNumber, minPortNumber); + } + srv = tryPort(availablePort); } - srv = new Server(availablePort); - try { - srv.start(); - found = true; - break; - } catch (final BindException ex) { - LOG.log(Level.FINEST, "Cannot use port: {0}. Will try another", availablePort); + } else { + // new TcpPortProvider path + final Iterator<Integer> ports = tcpPortProvider.iterator(); + while (ports.hasNext() && srv == null) { + availablePort = ports.next(); + srv = tryPort(availablePort); } } - if (found) { + if (srv != null) { this.server = srv; this.port = availablePort; this.server.setHandler(jettyHandler); LOG.log(Level.INFO, "Jetty Server started with port: {0}", availablePort); } else { - throw new RuntimeException("Could not find available port in " + maxRetryAttempts + " attempts"); + throw new RuntimeException("Could not find available port for http"); } } } + private Server tryPort(final int portNumber) throws Exception { + Server srv = new Server(portNumber); + try { + srv.start(); + LOG.log(Level.INFO, "Jetty Server started with port: {0}", portNumber); + } catch (final BindException ex) { + srv = null; + LOG.log(Level.FINEST, "Cannot use port: {0}. Will try another", portNumber); + } + return srv; + } + /** * get a random port number in min and max range. * http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1ea4d64b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/MaxPortNumber.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/MaxPortNumber.java b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/MaxPortNumber.java index 51a2952..2c05c76 100644 --- a/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/MaxPortNumber.java +++ b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/MaxPortNumber.java @@ -23,7 +23,9 @@ import org.apache.reef.tang.annotations.NamedParameter; /** * max port number range when generating a port number for the Http Server. + * @deprecated in 0.13, use TcpPortRangeCount and TcpPortProvider instead. */ @NamedParameter(doc = "Max port number for Jetty Server", default_value = "49151") +@Deprecated public class MaxPortNumber implements Name<Integer> { } http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1ea4d64b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/MaxRetryAttempts.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/MaxRetryAttempts.java b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/MaxRetryAttempts.java index 390e0f5..c523187 100644 --- a/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/MaxRetryAttempts.java +++ b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/MaxRetryAttempts.java @@ -23,7 +23,9 @@ import org.apache.reef.tang.annotations.NamedParameter; /** * Max retry times when generating a port number for the Http Server. + * @deprecated in 0.13, use TcpPortRangeTryCount and TcpPortProvider instead. */ @NamedParameter(doc = "Maximum retry attempts for port number of Jetty Server", default_value = "100") +@Deprecated public class MaxRetryAttempts implements Name<Integer> { } http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1ea4d64b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/MinPortNumber.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/MinPortNumber.java b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/MinPortNumber.java index 62c1486..ecc76bb 100644 --- a/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/MinPortNumber.java +++ b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/MinPortNumber.java @@ -23,7 +23,9 @@ import org.apache.reef.tang.annotations.NamedParameter; /** * minimum port number range when generating a port number for the Http Server. + * @deprecated in 0.13, use TcpPortRangeStart and TcpPortProvider instead. */ @NamedParameter(doc = "Minimum port number for Jetty Server", default_value = "1024") +@Deprecated public class MinPortNumber implements Name<Integer> { } http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1ea4d64b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/PortNumber.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/PortNumber.java b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/PortNumber.java index d22647d..92bad3b 100644 --- a/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/PortNumber.java +++ b/lang/java/reef-webserver/src/main/java/org/apache/reef/webserver/PortNumber.java @@ -25,7 +25,11 @@ import org.apache.reef.tang.annotations.NamedParameter; * port number for the Http Server * Clients can set a preferred port number. However, Reef will detect if the given port number has been used * in the machine. If yes, it will generate another available port number. + * @deprecated in 0.13, use TcpPortRangeStart and TcpPortProvider instead. */ -@NamedParameter(doc = "Port number for Jetty Server", default_value = "8080") -public class PortNumber implements Name<Integer> { +@NamedParameter(doc = "Port number for Jetty Server", default_value = PortNumber.DEFAULT_VALUE) +@Deprecated +public final class PortNumber implements Name<Integer> { + private PortNumber(){} + public static final String DEFAULT_VALUE = "8080"; } http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1ea4d64b/lang/java/reef-webserver/src/test/java/org/apache/reef/webserver/TestHttpServer.java ---------------------------------------------------------------------- diff --git a/lang/java/reef-webserver/src/test/java/org/apache/reef/webserver/TestHttpServer.java b/lang/java/reef-webserver/src/test/java/org/apache/reef/webserver/TestHttpServer.java index a331052..cf05e6f 100644 --- a/lang/java/reef-webserver/src/test/java/org/apache/reef/webserver/TestHttpServer.java +++ b/lang/java/reef-webserver/src/test/java/org/apache/reef/webserver/TestHttpServer.java @@ -26,6 +26,9 @@ import org.apache.reef.tang.Injector; import org.apache.reef.tang.Tang; import org.apache.reef.tang.exceptions.InjectionException; import org.apache.reef.wake.remote.RemoteConfiguration; +import org.apache.reef.wake.remote.ports.parameters.TcpPortRangeBegin; +import org.apache.reef.wake.remote.ports.parameters.TcpPortRangeCount; +import org.apache.reef.wake.remote.ports.parameters.TcpPortRangeTryCount; import org.junit.Assert; import org.junit.Test; @@ -110,6 +113,62 @@ public class TestHttpServer { } @Test + public void httpServerPortRangeTestWithTcpPortProvider() throws Exception { + final Configuration httpRuntimeConfiguration = HttpRuntimeConfiguration.CONF.build(); + + final Configuration httpServerConfiguration = Tang.Factory.getTang().newConfigurationBuilder() + .bindNamedParameter(TcpPortRangeCount.class, "8900") + .bindNamedParameter(TcpPortRangeBegin.class, "1000") + .bindNamedParameter(TcpPortRangeTryCount.class, "3") + .build(); + + final Configuration configuration = + Configurations.merge(httpRuntimeConfiguration, httpServerConfiguration); + + final Injector injector1 = Tang.Factory.getTang().newInjector(configuration); + final HttpServer httpServer1 = injector1.getInstance(HttpServer.class); + + final Injector injector2 = Tang.Factory.getTang().newInjector(configuration); + final HttpServer httpServer2 = injector2.getInstance(HttpServer.class); + + Assert.assertTrue("port number is out of specified range", + httpServer2.getPort() >= 1000 && httpServer2.getPort() <= 9900); + + httpServer1.stop(); + httpServer2.stop(); + } + + + @Test + public void httpServerPortRetryTestWithTcpPortProvider() throws Exception { + + final Configuration httpRuntimeConfiguration = HttpRuntimeConfiguration.CONF.build(); + final Injector injector1 = Tang.Factory.getTang().newInjector(httpRuntimeConfiguration); + final HttpServer httpServer1 = injector1.getInstance(HttpServer.class); + final String portUsed = "" + httpServer1.getPort(); + + final Configuration httpServerConfiguration = Tang.Factory.getTang().newConfigurationBuilder() + .bindNamedParameter(TcpPortRangeCount.class, "1") + .bindNamedParameter(TcpPortRangeBegin.class, portUsed) + .bindNamedParameter(TcpPortRangeTryCount.class, "3") + .build(); + + final Configuration configuration = + Configurations.merge(httpRuntimeConfiguration, httpServerConfiguration); + + final Injector injector2 = Tang.Factory.getTang().newInjector(configuration); + + try { + injector2.getInstance(HttpServer.class); + Assert.fail("Created two web servers on the same port: " + portUsed); + } catch (final InjectionException ex) { + Assert.assertEquals("Could not find available port for http", ex.getCause().getMessage()); + } + + httpServer1.stop(); + } + + @Test public void httpServerPortRetryTest() throws Exception { final Configuration httpRuntimeConfiguration = HttpRuntimeConfiguration.CONF.build(); @@ -133,12 +192,13 @@ public class TestHttpServer { injector2.getInstance(HttpServer.class); Assert.fail("Created two web servers on the same port: " + portUsed); } catch (final InjectionException ex) { - Assert.assertEquals("Could not find available port in 3 attempts", ex.getCause().getMessage()); + Assert.assertEquals("Could not find available port for http", ex.getCause().getMessage()); } httpServer1.stop(); } + @Test public void httpServerAddHandlerTest() throws Exception {
