Author: mahadev
Date: Thu Aug  6 23:23:32 2009
New Revision: 801839

URL: http://svn.apache.org/viewvc?rev=801839&view=rev
Log:
ZOOKEEPER-484.  Clients get SESSION MOVED exception when switching from 
follower to a leader. (mahadev)

Modified:
    hadoop/zookeeper/trunk/CHANGES.txt
    
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java
    
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/PrepRequestProcessor.java
    
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ServerCnxn.java
    
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ZooKeeperServer.java
    
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/FollowerHandler.java
    
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LeaderZooKeeperServer.java
    
hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/QuorumTest.java
    
hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/SessionTest.java

Modified: hadoop/zookeeper/trunk/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/CHANGES.txt?rev=801839&r1=801838&r2=801839&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/CHANGES.txt (original)
+++ hadoop/zookeeper/trunk/CHANGES.txt Thu Aug  6 23:23:32 2009
@@ -48,6 +48,9 @@
 
   ZOOKEEPER-311. handle small path lengths in zoo_create() (chris barroch via 
breed)
 
+  ZOOKEEPER-484.  Clients get SESSION MOVED exception when switching from
+  follower to a leader. (mahadev)
+
 IMPROVEMENTS:
   ZOOKEEPER-473. cleanup junit tests to eliminate false positives due to
   "socket reuse" and failure to close client (phunt via mahadev)

Modified: 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java
URL: 
http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java?rev=801839&r1=801838&r2=801839&view=diff
==============================================================================
--- 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java
 (original)
+++ 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java
 Thu Aug  6 23:23:32 2009
@@ -70,10 +70,7 @@
 
     private ConnectionBean jmxConnectionBean;
 
-    // This is just an arbitrary object to represent requests issued by
-    // (aka owned by) this class
-    final private static Object me = new Object();
-
+   
     static public class Factory extends Thread {
         ZooKeeperServer zks;
 
@@ -545,7 +542,7 @@
             return;
         } else {
             Request si = new Request(this, sessionId, h.getXid(), h.getType(), 
incomingBuffer, authInfo);
-            si.setOwner(me);
+            si.setOwner(ServerCnxn.me);
             zk.submitRequest(si);
         }
         if (h.getXid() >= 0) {

Modified: 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/PrepRequestProcessor.java
URL: 
http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/PrepRequestProcessor.java?rev=801839&r1=801838&r2=801839&view=diff
==============================================================================
--- 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/PrepRequestProcessor.java
 (original)
+++ 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/PrepRequestProcessor.java
 Thu Aug  6 23:23:32 2009
@@ -356,7 +356,7 @@
                 txn = new CreateSessionTxn(to);
                 request.request.rewind();
                 zks.sessionTracker.addSession(request.sessionId, to);
-                zks.sessionTracker.setOwner(request.sessionId, 
request.getOwner());
+                zks.setOwner(request.sessionId, request.getOwner());
                 break;
             case OpCode.closeSession:
                 txnHeader = new TxnHeader(request.sessionId, request.cxid, zks

Modified: 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ServerCnxn.java
URL: 
http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ServerCnxn.java?rev=801839&r1=801838&r2=801839&view=diff
==============================================================================
--- 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ServerCnxn.java
 (original)
+++ 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ServerCnxn.java
 Thu Aug  6 23:23:32 2009
@@ -55,6 +55,10 @@
     
     final static ByteBuffer imok = ByteBuffer.wrap("imok".getBytes());
 
+    // This is just an arbitrary object to represent requests issued by
+    // (aka owned by) this class
+    final public static Object me = new Object();
+
     public abstract int getSessionTimeout();
 
     public abstract void close();

Modified: 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ZooKeeperServer.java
URL: 
http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ZooKeeperServer.java?rev=801839&r1=801838&r2=801839&view=diff
==============================================================================
--- 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ZooKeeperServer.java
 (original)
+++ 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ZooKeeperServer.java
 Thu Aug  6 23:23:32 2009
@@ -38,6 +38,7 @@
 import org.apache.jute.Record;
 import org.apache.log4j.Logger;
 import org.apache.zookeeper.Environment;
+import org.apache.zookeeper.KeeperException.SessionExpiredException;
 import org.apache.zookeeper.ZooDefs.OpCode;
 import org.apache.zookeeper.data.ACL;
 import org.apache.zookeeper.data.Id;
@@ -500,6 +501,16 @@
         return sessionId;
     }
 
+    /**
+     * set the owner of this session as owner
+     * @param id the session id
+     * @param owner the owner of the session
+     * @throws SessionExpiredException
+     */
+    public void setOwner(long id, Object owner) throws SessionExpiredException 
{
+        sessionTracker.setOwner(id, owner);
+    }
+
     protected void revalidateSession(ServerCnxn cnxn, long sessionId,
             int sessionTimeout) throws IOException, InterruptedException {
         boolean rc = sessionTracker.touchSession(sessionId, sessionTimeout);

Modified: 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/FollowerHandler.java
URL: 
http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/FollowerHandler.java?rev=801839&r1=801838&r2=801839&view=diff
==============================================================================
--- 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/FollowerHandler.java
 (original)
+++ 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/FollowerHandler.java
 Thu Aug  6 23:23:32 2009
@@ -355,6 +355,9 @@
                     boolean valid = leader.zk.touch(id, to);
                     if (valid) {
                         try {
+                            //set the session owner
+                            // as the follower that
+                            // owns the session
                             leader.zk.setOwner(id, this);
                         } catch (SessionExpiredException e) {
                             LOG.error("Somehow session " + 
Long.toHexString(id) + " expired right after being renewed! (impossible)", e);

Modified: 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LeaderZooKeeperServer.java
URL: 
http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LeaderZooKeeperServer.java?rev=801839&r1=801838&r2=801839&view=diff
==============================================================================
--- 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LeaderZooKeeperServer.java
 (original)
+++ 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LeaderZooKeeperServer.java
 Thu Aug  6 23:23:32 2009
@@ -154,16 +154,14 @@
         return "leader";
     }
 
-    public void setOwner(long id, Object owner) throws SessionExpiredException 
{
-        sessionTracker.setOwner(id, owner);
-    }
-
     @Override
     protected void revalidateSession(ServerCnxn cnxn, long sessionId,
         int sessionTimeout) throws IOException, InterruptedException {
         super.revalidateSession(cnxn, sessionId, sessionTimeout);
         try {
-            setOwner(sessionId, this);
+            // setowner as the leader itself, unless updated
+            // via the follower handlers
+            setOwner(sessionId, ServerCnxn.me);
         } catch (SessionExpiredException e) {
             // this is ok, it just means that the session revalidation failed.
         }

Modified: 
hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/QuorumTest.java
URL: 
http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/QuorumTest.java?rev=801839&r1=801838&r2=801839&view=diff
==============================================================================
--- 
hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/QuorumTest.java 
(original)
+++ 
hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/QuorumTest.java 
Thu Aug  6 23:23:32 2009
@@ -17,6 +17,8 @@
  */
 
 package org.apache.zookeeper.test;
+import static org.apache.zookeeper.test.ClientBase.CONNECTION_TIMEOUT;
+
 import java.io.IOException;
 import java.util.ArrayList;
 
@@ -27,6 +29,7 @@
 import org.apache.zookeeper.Watcher;
 import org.apache.zookeeper.ZooDefs;
 import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.ZooDefs.Ids;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -97,6 +100,40 @@
         ct.testMutipleWatcherObjs();
     }
 
+    /**
+     * Make sure that we can change sessions 
+     *  from follower to leader.
+     *
+     * @throws IOException
+     * @throws InterruptedException
+     * @throws KeeperException
+     */
+    @Test
+    public void testSessionMoved() throws IOException, InterruptedException, 
KeeperException {
+        String hostPorts[] = qb.hostPort.split(",");
+        ZooKeeper zk = new DisconnectableZooKeeper(hostPorts[0], 
ClientBase.CONNECTION_TIMEOUT, new Watcher() {
+            public void process(WatchedEvent event) {
+            }});
+        zk.create("/sessionMoveTest", new byte[0], Ids.OPEN_ACL_UNSAFE, 
CreateMode.EPHEMERAL);
+        // we want to loop through the list twice
+        for(int i = 0; i < hostPorts.length*2; i++) {
+            // This should stomp the zk handle
+            ZooKeeper zknew = new 
DisconnectableZooKeeper(hostPorts[(i+1)%hostPorts.length], 
ClientBase.CONNECTION_TIMEOUT, 
+                    new Watcher() {public void process(WatchedEvent event) {
+                    }},
+                    zk.getSessionId(),
+                    zk.getSessionPasswd());
+            zknew.setData("/", new byte[1], -1);
+            try {
+                zk.setData("/", new byte[1], -1);
+                fail("Should have lost the connection");
+            } catch(KeeperException.SessionMovedException e) {
+            }
+            //zk.close();
+            zk = zknew;
+        }
+        zk.close();
+    }
     @Test
     /**
      * Connect to two different servers with two different handles using the 
same session and

Modified: 
hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/SessionTest.java
URL: 
http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/SessionTest.java?rev=801839&r1=801838&r2=801839&view=diff
==============================================================================
--- 
hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/SessionTest.java 
(original)
+++ 
hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/test/SessionTest.java 
Thu Aug  6 23:23:32 2009
@@ -224,19 +224,24 @@
      */
     @Test
     public void testSessionMove() throws IOException, InterruptedException, 
KeeperException {
-        ZooKeeper zk = createClient();
-        zk.getChildren("/", false);
-        // This should stomp the zk handle
-        ZooKeeper zknew = new DisconnectableZooKeeper(HOSTPORT, 
CONNECTION_TIMEOUT, this,
-                   zk.getSessionId(),
-                   zk.getSessionPasswd());
-        zknew.getChildren("/", false);
-        try {
-            zk.getChildren("/", false);
-            fail("Should have lost the connection");
-        } catch(KeeperException.ConnectionLossException e) {
+        String hostPorts[] = HOSTPORT.split(",");
+        ZooKeeper zk = new DisconnectableZooKeeper(hostPorts[0], 
CONNECTION_TIMEOUT, this);
+        zk.create("/sessionMoveTest", new byte[0], Ids.OPEN_ACL_UNSAFE, 
CreateMode.EPHEMERAL);
+        // we want to loop through the list twice
+        for(int i = 0; i < hostPorts.length*2; i++) {
+            // This should stomp the zk handle
+            ZooKeeper zknew = new 
DisconnectableZooKeeper(hostPorts[(i+1)%hostPorts.length], CONNECTION_TIMEOUT, 
this,
+                    zk.getSessionId(),
+                    zk.getSessionPasswd());
+            zknew.setData("/", new byte[1], -1);
+            try {
+                zk.setData("/", new byte[1], -1);
+                fail("Should have lost the connection");
+            } catch(KeeperException.ConnectionLossException e) {
+            }
+            //zk.close();
+            zk = zknew;
         }
-        zknew.close();
         zk.close();
     }
     @Test


Reply via email to