Author: henry
Date: Fri May 21 16:22:52 2010
New Revision: 947063

URL: http://svn.apache.org/viewvc?rev=947063&view=rev
Log:
ZOOKEEPER-769: Leader can treat observers as quorum members

Modified:
    hadoop/zookeeper/trunk/CHANGES.txt
    
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumPeerConfig.java
    
hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/server/quorum/QuorumPeerMainTest.java

Modified: hadoop/zookeeper/trunk/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/CHANGES.txt?rev=947063&r1=947062&r2=947063&view=diff
==============================================================================
--- hadoop/zookeeper/trunk/CHANGES.txt (original)
+++ hadoop/zookeeper/trunk/CHANGES.txt Fri May 21 16:22:52 2010
@@ -68,6 +68,9 @@ IMPROVEMENTS:
   ZOOKEEPER-766. forrest recipes docs don't mention the lock/queue recipe
   implementations available in the release (phunt via mahadev)
 
+  ZOOKEEPER-769: Leader can treat observers as quorum members (Sergey
+  Doroshenko via henryr)
+
 NEW FEATURES:
   ZOOKEEPER-729. Java client API to recursively delete a subtree. (Kay
   Kay via henry)

Modified: 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumPeerConfig.java
URL: 
http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumPeerConfig.java?rev=947063&r1=947062&r2=947063&view=diff
==============================================================================
--- 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumPeerConfig.java
 (original)
+++ 
hadoop/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumPeerConfig.java
 Fri May 21 16:22:52 2010
@@ -310,6 +310,18 @@ public class QuorumPeerConfig {
                 throw new IllegalArgumentException("serverid " + myIdString
                         + " is not a number");
             }
+            
+            // Warn about inconsistent peer type
+            LearnerType roleByServersList = observers.containsKey(serverId) ? 
LearnerType.OBSERVER
+                    : LearnerType.PARTICIPANT;
+            if (roleByServersList != peerType) {
+                LOG.warn("Peer type from servers list (" + roleByServersList
+                        + ") doesn't match peerType (" + peerType
+                        + "). Defaulting to servers list.");
+
+                peerType = roleByServersList;
+            }
+            
         }
     }
 

Modified: 
hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/server/quorum/QuorumPeerMainTest.java
URL: 
http://svn.apache.org/viewvc/hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/server/quorum/QuorumPeerMainTest.java?rev=947063&r1=947062&r2=947063&view=diff
==============================================================================
--- 
hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/server/quorum/QuorumPeerMainTest.java
 (original)
+++ 
hadoop/zookeeper/trunk/src/java/test/org/apache/zookeeper/server/quorum/QuorumPeerMainTest.java
 Fri May 21 16:22:52 2010
@@ -162,6 +162,94 @@ public class QuorumPeerMainTest extends 
     }
 
     /**
+     * Verify handling of inconsistent peer type
+     */
+    @Test
+    public void testInconsistentPeerType() throws Exception {
+        ClientBase.setupTestEnv();
+
+        // setup the logger to capture all logs
+        Layout layout =
+            Logger.getRootLogger().getAppender("CONSOLE").getLayout();
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        WriterAppender appender = new WriterAppender(layout, os);
+        appender.setThreshold(Level.INFO);
+        Logger qlogger = 
Logger.getLogger("org.apache.zookeeper.server.quorum");
+        qlogger.addAppender(appender);
+
+        // test the most likely situation only: server is stated as observer 
in 
+        // servers list, but there's no "peerType=observer" token in config
+        try {
+            final int CLIENT_PORT_QP1 = PortAssignment.unique();
+            final int CLIENT_PORT_QP2 = PortAssignment.unique();
+            final int CLIENT_PORT_QP3 = PortAssignment.unique();
+
+            String quorumCfgSection =
+                "server.1=127.0.0.1:" + PortAssignment.unique()
+                + ":" + PortAssignment.unique()
+                + "\nserver.2=127.0.0.1:" + PortAssignment.unique()
+                + ":" + PortAssignment.unique()
+                + "\nserver.3=127.0.0.1:" + PortAssignment.unique()
+                + ":" + PortAssignment.unique() + ":observer";
+
+            MainThread q1 = new MainThread(1, CLIENT_PORT_QP1, 
quorumCfgSection);
+            MainThread q2 = new MainThread(2, CLIENT_PORT_QP2, 
quorumCfgSection);
+            MainThread q3 = new MainThread(3, CLIENT_PORT_QP3, 
quorumCfgSection);
+            q1.start();
+            q2.start();
+            q3.start();
+
+            Assert.assertTrue("waiting for server 1 being up",
+                    ClientBase.waitForServerUp("127.0.0.1:" + CLIENT_PORT_QP1,
+                            CONNECTION_TIMEOUT));
+            Assert.assertTrue("waiting for server 2 being up",
+                    ClientBase.waitForServerUp("127.0.0.1:" + CLIENT_PORT_QP2,
+                            CONNECTION_TIMEOUT));
+            Assert.assertTrue("waiting for server 3 being up",
+                    ClientBase.waitForServerUp("127.0.0.1:" + CLIENT_PORT_QP3,
+                            CONNECTION_TIMEOUT));
+
+            q1.shutdown();
+            q2.shutdown();
+            q3.shutdown();
+
+            Assert.assertTrue("waiting for server 1 down",
+                    ClientBase.waitForServerDown("127.0.0.1:" + 
CLIENT_PORT_QP1,
+                            ClientBase.CONNECTION_TIMEOUT));
+            Assert.assertTrue("waiting for server 2 down",
+                    ClientBase.waitForServerDown("127.0.0.1:" + 
CLIENT_PORT_QP2,
+                            ClientBase.CONNECTION_TIMEOUT));
+            Assert.assertTrue("waiting for server 3 down",
+                    ClientBase.waitForServerDown("127.0.0.1:" + 
CLIENT_PORT_QP3,
+                            ClientBase.CONNECTION_TIMEOUT));
+
+        } finally {
+            qlogger.removeAppender(appender);
+        }
+
+        LineNumberReader r = new LineNumberReader(new 
StringReader(os.toString()));
+        String line;
+        boolean warningPresent = false;
+        boolean defaultedToObserver = false;
+        Pattern pWarn =
+            Pattern.compile(".*Peer type from servers list.* doesn't match 
peerType.*");
+        Pattern pObserve = Pattern.compile(".*OBSERVING.*");
+        while ((line = r.readLine()) != null) {
+            if (pWarn.matcher(line).matches()) { 
+                warningPresent = true;
+            }
+            if (pObserve.matcher(line).matches()) {
+                defaultedToObserver = true;
+            }
+            if (warningPresent && defaultedToObserver) {
+                break;
+            }
+        }
+        Assert.assertTrue("Should warn about inconsistent peer type", 
+                warningPresent && defaultedToObserver);
+    }
+
+    /**
      * verify if bad packets are being handled properly 
      * at the quorum port
      * @throws Exception


Reply via email to