瀏覽代碼

ZOOKEEPER-1271. testEarlyLeaderAbandonment failing on solaris - clients not retrying connection (mahadev via phunt)

git-svn-id: https://svn.apache.org/repos/asf/zookeeper/trunk@1196819 13f79535-47bb-0310-9956-ffa450edef68
Patrick D. Hunt 13 年之前
父節點
當前提交
736e27df12

+ 3 - 0
CHANGES.txt

@@ -42,6 +42,9 @@ BUGFIXES:
   
   ZOOKEEPER-1246. Dead code in PrepRequestProcessor catch Exception block. (camille)
 
+  ZOOKEEPER-1271. testEarlyLeaderAbandonment failing on solaris -
+  clients not retrying connection (mahadev via phunt)
+
 IMPROVEMENTS:
 
   ZOOKEEPER-1170. Fix compiler (eclipse) warnings: unused imports,

+ 2 - 0
ivy.xml

@@ -53,6 +53,8 @@
     <dependency org="org.vafer" name="jdeb" rev="0.8" conf="package->master"/>
 
     <dependency org="junit" name="junit" rev="4.9" conf="test->default"/>
+	<dependency org="org.mockito" name="mockito-all" rev="1.8.2"
+               conf="test->default"/>
     <dependency org="checkstyle" name="checkstyle" rev="5.0"
                 conf="test->default"/>
 

+ 32 - 10
src/java/main/org/apache/zookeeper/ClientCnxnSocketNIO.java

@@ -181,23 +181,45 @@ public class ClientCnxnSocketNIO extends ClientCnxnSocket {
             LOG.warn("Ignoring exception during selector close", e);
         }
     }
-
-    @Override
-    void connect(InetSocketAddress addr) throws IOException {
+    
+    /**
+     * create a socket channel.
+     * @return the created socket channel
+     * @throws IOException
+     */
+    SocketChannel createSock() throws IOException {
         SocketChannel sock;
         sock = SocketChannel.open();
         sock.configureBlocking(false);
         sock.socket().setSoLinger(false, -1);
         sock.socket().setTcpNoDelay(true);
-        try {            
-            sockKey = sock.register(selector, SelectionKey.OP_CONNECT);
-            boolean immediateConnect = sock.connect(addr);
-            if (immediateConnect) {
-                sendThread.primeConnection();
-            }
-        } catch (IOException e) {
+        return sock;
+    }
+
+    /**
+     * register with the selection and connect
+     * @param sock the {@link SocketChannel} 
+     * @param addr the address of remote host
+     * @throws IOException
+     */
+    void registerAndConnect(SocketChannel sock, InetSocketAddress addr) 
+    throws IOException {
+        sockKey = sock.register(selector, SelectionKey.OP_CONNECT);
+        boolean immediateConnect = sock.connect(addr);            
+        if (immediateConnect) {
+            sendThread.primeConnection();
+        }
+    }
+    
+    @Override
+    void connect(InetSocketAddress addr) throws IOException {
+        SocketChannel sock = createSock();
+        try {
+           registerAndConnect(sock, addr);
+      } catch (IOException e) {
             LOG.error("Unable to open socket to " + addr);
             sock.close();
+            throw e;
         }
         initialized = false;
 

+ 78 - 0
src/java/test/org/apache/zookeeper/ClientReconnectTest.java

@@ -0,0 +1,78 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper;
+
+
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.nio.channels.SocketChannel;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.zookeeper.client.HostProvider;
+import org.junit.Test;
+
+public class ClientReconnectTest extends TestCase {
+    private SocketChannel sc;
+    private CountDownLatch countDownLatch = new CountDownLatch(3);
+    
+    class MockCnxn extends ClientCnxnSocketNIO {
+        MockCnxn() throws IOException {
+            super();
+        }
+
+        @Override
+        void registerAndConnect(SocketChannel sock, InetSocketAddress addr) throws
+        IOException {
+            countDownLatch.countDown();
+            throw new IOException("failed to register");
+        }
+
+        @Override
+        SocketChannel createSock() {
+            return sc;
+        }
+    }
+
+    @Test
+    public void testClientReconnect() throws IOException, InterruptedException {
+        HostProvider hostProvider = mock(HostProvider.class);
+        when(hostProvider.size()).thenReturn(1);
+        InetSocketAddress inaddr = new InetSocketAddress(1111);
+        when(hostProvider.next(anyLong())).thenReturn(inaddr);
+        ZooKeeper zk = mock(ZooKeeper.class);
+        sc =  SocketChannel.open();
+
+        ClientCnxnSocketNIO nioCnxn = new MockCnxn();
+        ClientWatchManager watcher = mock(ClientWatchManager.class);
+        ClientCnxn clientCnxn = new ClientCnxn(
+                "tmp", hostProvider, 5000,
+                zk, watcher, nioCnxn, false);
+        clientCnxn.start();
+        countDownLatch.await(5000, TimeUnit.MILLISECONDS);
+        Assert.assertTrue(countDownLatch.getCount() == 0);
+        clientCnxn.close();
+    }
+}