Author: andygumbrecht
Date: Sat Jul 19 13:12:31 2014
New Revision: 1611911

URL: http://svn.apache.org/r1611911
Log:
Don't return the same port as the last one.

Added:
    
tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/test/java/org/apache/openejb/util/NetworkUtilTest.java
Modified:
    
tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/util/NetworkUtil.java

Modified: 
tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/util/NetworkUtil.java
URL: 
http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/util/NetworkUtil.java?rev=1611911&r1=1611910&r2=1611911&view=diff
==============================================================================
--- 
tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/util/NetworkUtil.java
 (original)
+++ 
tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/util/NetworkUtil.java
 Sat Jul 19 13:12:31 2014
@@ -20,48 +20,39 @@ package org.apache.openejb.util;
 import java.io.IOException;
 import java.net.ServerSocket;
 import java.util.Collection;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.ReentrantLock;
 
 public final class NetworkUtil {
 
+    private static final ReentrantLock lock = new ReentrantLock();
+    private static final AtomicReference<LastPort> lastPort = new 
AtomicReference<LastPort>();
+
     private NetworkUtil() {
         // no-op
     }
 
     public static int getNextAvailablePort() {
-        return getNextAvailablePort(new int[]{0});
-    }
-
-    public static int getNextAvailablePort(final int[] portList) {
-        int port;
-        ServerSocket s = null;
+        final ReentrantLock l = lock;
+        l.lock();
         try {
-            s = create(portList);
-            port = s.getLocalPort();
-        } catch (final IOException ioe) {
-            port = -1;
+            return getNextAvailablePort(new int[]{0});
         } finally {
-            if (s != null) {
-                try {
-                    s.close();
-                } catch (final Throwable e) {
-                    //Ignore
-                }
-            }
+            l.unlock();
         }
-        return port;
     }
 
-    public static int getNextAvailablePort(final int min, final int max, final 
Collection<Integer> excepted) {
-        int port = -1;
-        ServerSocket s = null;
-        for (int i = min; i <= max; i++) {
+    public synchronized static int getNextAvailablePort(final int[] portList) {
+
+        final ReentrantLock l = lock;
+        l.lock();
+
+        try {
+            int port;
+            ServerSocket s = null;
             try {
-                s = create(new int[]{i});
+                s = create(portList);
                 port = s.getLocalPort();
-
-                if (excepted == null || !excepted.contains(port)) {
-                    break;
-                }
             } catch (final IOException ioe) {
                 port = -1;
             } finally {
@@ -73,13 +64,61 @@ public final class NetworkUtil {
                     }
                 }
             }
+
+            lastPort.set(new LastPort(port, System.currentTimeMillis()));
+            return port;
+        } finally {
+            l.unlock();
+        }
+    }
+
+    public synchronized static int getNextAvailablePort(final int min, final 
int max, final Collection<Integer> excluded) {
+
+        final ReentrantLock l = lock;
+        l.lock();
+
+        try {
+            int port = -1;
+            ServerSocket s = null;
+            for (int i = min; i <= max; i++) {
+                try {
+                    s = create(new int[]{i});
+                    port = s.getLocalPort();
+
+                    if (excluded == null || !excluded.contains(port)) {
+                        break;
+                    }
+                } catch (final IOException ioe) {
+                    port = -1;
+                } finally {
+                    if (s != null) {
+                        try {
+                            s.close();
+                        } catch (final Throwable e) {
+                            //Ignore
+                        }
+                    }
+                }
+            }
+
+            lastPort.set(new LastPort(port, System.currentTimeMillis()));
+            return port;
+        } finally {
+            l.unlock();
         }
-        return port;
     }
 
     private static ServerSocket create(final int[] ports) throws IOException {
         for (final int port : ports) {
             try {
+
+                final LastPort last = lastPort.get();
+                if (null != last && port == last.port) {
+                    if ((System.currentTimeMillis() - last.time) < 10000) {
+                        continue;
+                    }
+                }
+
                 return new ServerSocket(port);
             } catch (final IOException ex) {
                 // try next port
@@ -93,4 +132,14 @@ public final class NetworkUtil {
     public static String getLocalAddress(final String start, final String end) 
{
         return start + "localhost:" + getNextAvailablePort() + end;
     }
+
+    private static final class LastPort {
+        private final int port;
+        private final long time;
+
+        private LastPort(final int port, final long time) {
+            this.port = port;
+            this.time = time;
+        }
+    }
 }

Added: 
tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/test/java/org/apache/openejb/util/NetworkUtilTest.java
URL: 
http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/test/java/org/apache/openejb/util/NetworkUtilTest.java?rev=1611911&view=auto
==============================================================================
--- 
tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/test/java/org/apache/openejb/util/NetworkUtilTest.java
 (added)
+++ 
tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/test/java/org/apache/openejb/util/NetworkUtilTest.java
 Sat Jul 19 13:12:31 2014
@@ -0,0 +1,53 @@
+/**
+ * Tomitribe Confidential
+ * <p/>
+ * Copyright(c) Tomitribe Corporation. 2014
+ * <p/>
+ * The source code for this program is not published or otherwise divested
+ * of its trade secrets, irrespective of what has been deposited with the
+ * U.S. Copyright Office.
+ * <p/>
+ */
+package org.apache.openejb.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class NetworkUtilTest {
+
+    @Test
+    public void test() throws Exception {
+
+        final int count = 20;
+        final CountDownLatch latch = new CountDownLatch(count);
+        final long start = System.currentTimeMillis();
+        final CopyOnWriteArrayList<Integer> list = new 
CopyOnWriteArrayList<Integer>();
+
+        for (int i = 0; i < count; i++) {
+            final Thread thread = new Thread(new Runnable() {
+                public void run() {
+                    final int nextAvailablePort = 
NetworkUtil.getNextAvailablePort();
+                    if (list.contains(nextAvailablePort)) {
+                        if ((System.currentTimeMillis() - start) > 10000)
+                            Assert.fail("Got a duplicate port with ten 
seconds");
+                    } else {
+                        list.add(nextAvailablePort);
+                    }
+
+                    latch.countDown();
+                }
+            }, "test-thread-" + count);
+            thread.setDaemon(false);
+            thread.start();
+        }
+
+        final boolean success = latch.await(15, TimeUnit.SECONDS);
+        Assert.assertTrue(success);
+
+        System.out.println("Thread safe port list = " + list);
+    }
+}


Reply via email to