You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by rg...@apache.org on 2015/06/29 17:32:24 UTC

svn commit: r1688252 [1/2] - in /zookeeper/branches/branch-3.5: ./ src/java/main/org/apache/zookeeper/server/ src/java/main/org/apache/zookeeper/server/command/ src/java/test/org/apache/zookeeper/test/

Author: rgs
Date: Mon Jun 29 15:32:23 2015
New Revision: 1688252

URL: http://svn.apache.org/r1688252
Log:
ZOOKEEPER-2140: NettyServerCnxn and NIOServerCnxn code should be improved
(Arshad Mohammad via rgs)

Added:
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/AbstractFourLetterCommand.java
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/CnxnStatResetCommand.java
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/CommandExecutor.java
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/ConfCommand.java
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/ConsCommand.java
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/DumpCommand.java
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/EnvCommand.java
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/FourLetterCommands.java
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/IsroCommand.java
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/MonitorCommand.java
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/RuokCommand.java
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/SetTraceMaskCommand.java
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/StatCommand.java
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/StatResetCommand.java
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/TraceMaskCommand.java
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/WatchCommand.java
Modified:
    zookeeper/branches/branch-3.5/CHANGES.txt
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/NettyServerCnxn.java
    zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/ServerCnxn.java
    zookeeper/branches/branch-3.5/src/java/test/org/apache/zookeeper/test/FourLetterWordsTest.java

Modified: zookeeper/branches/branch-3.5/CHANGES.txt
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/CHANGES.txt?rev=1688252&r1=1688251&r2=1688252&view=diff
==============================================================================
--- zookeeper/branches/branch-3.5/CHANGES.txt (original)
+++ zookeeper/branches/branch-3.5/CHANGES.txt Mon Jun 29 15:32:23 2015
@@ -207,6 +207,9 @@ IMPROVEMENTS:
   ZOOKEEPER-2185: Run server with -XX:+HeapDumpOnOutOfMemoryError and
   -XX:OnOutOfMemoryError='kill %p' (Chris Nauroth via rgs)
 
+  ZOOKEEPER-2140: NettyServerCnxn and NIOServerCnxn code should be improved
+  (Arshad Mohammad via rgs)
+
 Release 3.5.0 - 8/4/2014
 
 NEW FEATURES:

Modified: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java?rev=1688252&r1=1688251&r2=1688252&view=diff
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java (original)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java Mon Jun 29 15:32:23 2015
@@ -30,29 +30,25 @@ import java.nio.channels.CancelledKeyExc
 import java.nio.channels.SelectionKey;
 import java.nio.channels.SocketChannel;
 import java.security.cert.Certificate;
-import java.util.List;
 import java.util.Queue;
+import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.LinkedBlockingQueue;
 
 import org.apache.jute.BinaryInputArchive;
 import org.apache.jute.BinaryOutputArchive;
 import org.apache.jute.Record;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.zookeeper.Environment;
-import org.apache.zookeeper.Version;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.data.Id;
 import org.apache.zookeeper.proto.ReplyHeader;
 import org.apache.zookeeper.proto.RequestHeader;
 import org.apache.zookeeper.proto.WatcherEvent;
 import org.apache.zookeeper.server.NIOServerCnxnFactory.SelectorThread;
-import org.apache.zookeeper.server.quorum.Leader;
-import org.apache.zookeeper.server.quorum.LeaderZooKeeperServer;
-import org.apache.zookeeper.server.quorum.ReadOnlyZooKeeperServer;
-import org.apache.zookeeper.server.util.OSMXBean;
+import org.apache.zookeeper.server.command.CommandExecutor;
+import org.apache.zookeeper.server.command.FourLetterCommands;
+import org.apache.zookeeper.server.command.SetTraceMaskCommand;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * This class handles communication with clients using NIO. There is one per
@@ -438,30 +434,6 @@ public class NIOServerCnxn extends Serve
     }
 
     /**
-     * clean up the socket related to a command and also make sure we flush the
-     * data before we do that
-     *
-     * @param pwriter
-     *            the pwriter for a command socket
-     */
-    private void cleanupWriterSocket(PrintWriter pwriter) {
-        try {
-            if (pwriter != null) {
-                pwriter.flush();
-                pwriter.close();
-            }
-        } catch (Exception e) {
-            LOG.info("Error closing PrintWriter ", e);
-        } finally {
-            try {
-                close();
-            } catch (Exception e) {
-                LOG.error("Error closing a command socket ", e);
-            }
-        }
-    }
-
-    /**
      * This class wraps the sendBuffer method of NIOServerCnxn. It is
      * responsible for chunking up the response to a client. Rather
      * than cons'ing up a response fully in memory, which may be large
@@ -500,336 +472,13 @@ public class NIOServerCnxn extends Serve
             checkFlush(false);
         }
     }
-
-    private static final String ZK_NOT_SERVING =
-        "This ZooKeeper instance is not currently serving requests";
-
-    /**
-     * Set of threads for commmand ports. All the 4
-     * letter commands are run via a thread. Each class
-     * maps to a corresponding 4 letter command. CommandThread
-     * is the abstract class from which all the others inherit.
-     */
-    private abstract class CommandThread {
-        PrintWriter pw;
-
-        CommandThread(PrintWriter pw) {
-            this.pw = pw;
-        }
-
-        public void start() {
-            run();
-        }
-
-        public void run() {
-            try {
-                commandRun();
-            } catch (IOException ie) {
-                LOG.error("Error in running command ", ie);
-            } finally {
-                cleanupWriterSocket(pw);
-            }
-        }
-
-        public abstract void commandRun() throws IOException;
-    }
-
-    private class RuokCommand extends CommandThread {
-        public RuokCommand(PrintWriter pw) {
-            super(pw);
-        }
-
-        @Override
-        public void commandRun() {
-            pw.print("imok");
-
-        }
-    }
-
-    private class TraceMaskCommand extends CommandThread {
-        TraceMaskCommand(PrintWriter pw) {
-            super(pw);
-        }
-
-        @Override
-        public void commandRun() {
-            long traceMask = ZooTrace.getTextTraceLevel();
-            pw.print(traceMask);
-        }
-    }
-
-    private class SetTraceMaskCommand extends CommandThread {
-        long trace = 0;
-        SetTraceMaskCommand(PrintWriter pw, long trace) {
-            super(pw);
-            this.trace = trace;
-        }
-
-        @Override
-        public void commandRun() {
-            pw.print(trace);
-        }
-    }
-
-    private class EnvCommand extends CommandThread {
-        EnvCommand(PrintWriter pw) {
-            super(pw);
-        }
-
-        @Override
-        public void commandRun() {
-            List<Environment.Entry> env = Environment.list();
-
-            pw.println("Environment:");
-            for(Environment.Entry e : env) {
-                pw.print(e.getKey());
-                pw.print("=");
-                pw.println(e.getValue());
-            }
-
-        }
-    }
-
-    private class ConfCommand extends CommandThread {
-        ConfCommand(PrintWriter pw) {
-            super(pw);
-        }
-
-        @Override
-        public void commandRun() {
-            if (zkServer == null) {
-                pw.println(ZK_NOT_SERVING);
-            } else {
-                zkServer.dumpConf(pw);
-            }
-        }
-    }
-
-    private class StatResetCommand extends CommandThread {
-        public StatResetCommand(PrintWriter pw) {
-            super(pw);
-        }
-
-        @Override
-        public void commandRun() {
-            if (zkServer == null) {
-                pw.println(ZK_NOT_SERVING);
-            }
-            else {
-                zkServer.serverStats().reset();
-                pw.println("Server stats reset.");
-            }
-        }
-    }
-
-    private class CnxnStatResetCommand extends CommandThread {
-        public CnxnStatResetCommand(PrintWriter pw) {
-            super(pw);
-        }
-
-        @Override
-        public void commandRun() {
-            if (zkServer == null) {
-                pw.println(ZK_NOT_SERVING);
-            } else {
-                for(ServerCnxn c : factory.cnxns){
-                    c.resetStats();
-                }
-                pw.println("Connection stats reset.");
-            }
-        }
-    }
-
-    private class DumpCommand extends CommandThread {
-        public DumpCommand(PrintWriter pw) {
-            super(pw);
-        }
-
-        @Override
-        public void commandRun() {
-            if (zkServer == null) {
-                pw.println(ZK_NOT_SERVING);
-            }
-            else {
-                pw.println("SessionTracker dump:");
-                zkServer.sessionTracker.dumpSessions(pw);
-                pw.println("ephemeral nodes dump:");
-                zkServer.dumpEphemerals(pw);
-                pw.println("Connections dump:");
-                factory.dumpConnections(pw);
-            }
-        }
-    }
-
-    private class StatCommand extends CommandThread {
-        int len;
-        public StatCommand(PrintWriter pw, int len) {
-            super(pw);
-            this.len = len;
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public void commandRun() {
-            if (zkServer == null) {
-                pw.println(ZK_NOT_SERVING);
-            }
-            else {
-                pw.print("Zookeeper version: ");
-                pw.println(Version.getFullVersion());
-                if (zkServer instanceof ReadOnlyZooKeeperServer) {
-                    pw.println("READ-ONLY mode; serving only " +
-                               "read-only clients");
-                }
-                if (len == statCmd) {
-                    LOG.info("Stat command output");
-                    pw.println("Clients:");
-                    for(ServerCnxn c : factory.cnxns){
-                        c.dumpConnectionInfo(pw, true);
-                        pw.println();
-                    }
-                    pw.println();
-                }
-                pw.print(zkServer.serverStats().toString());
-                pw.print("Node count: ");
-                pw.println(zkServer.getZKDatabase().getNodeCount());
-            }
-
-        }
-    }
-
-    private class ConsCommand extends CommandThread {
-        public ConsCommand(PrintWriter pw) {
-            super(pw);
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public void commandRun() {
-            if (zkServer == null) {
-                pw.println(ZK_NOT_SERVING);
-            } else {
-                for (ServerCnxn c : factory.cnxns) {
-                    c.dumpConnectionInfo(pw, false);
-                    pw.println();
-                }
-                pw.println();
-            }
-        }
-    }
-
-    private class WatchCommand extends CommandThread {
-        int len = 0;
-        public WatchCommand(PrintWriter pw, int len) {
-            super(pw);
-            this.len = len;
-        }
-
-        @Override
-        public void commandRun() {
-            if (zkServer == null) {
-                pw.println(ZK_NOT_SERVING);
-            } else {
-                DataTree dt = zkServer.getZKDatabase().getDataTree();
-                if (len == wchsCmd) {
-                    dt.dumpWatchesSummary(pw);
-                } else if (len == wchpCmd) {
-                    dt.dumpWatches(pw, true);
-                } else {
-                    dt.dumpWatches(pw, false);
-                }
-                pw.println();
-            }
-        }
-    }
-
-    private class MonitorCommand extends CommandThread {
-
-        MonitorCommand(PrintWriter pw) {
-            super(pw);
-        }
-
-        @Override
-        public void commandRun() {
-            if(zkServer == null) {
-                pw.println(ZK_NOT_SERVING);
-                return;
-            }
-            ZKDatabase zkdb = zkServer.getZKDatabase();
-            ServerStats stats = zkServer.serverStats();
-
-            print("version", Version.getFullVersion());
-
-            print("avg_latency", stats.getAvgLatency());
-            print("max_latency", stats.getMaxLatency());
-            print("min_latency", stats.getMinLatency());
-
-            print("packets_received", stats.getPacketsReceived());
-            print("packets_sent", stats.getPacketsSent());
-            print("num_alive_connections", stats.getNumAliveClientConnections());
-
-            print("outstanding_requests", stats.getOutstandingRequests());
-
-            print("server_state", stats.getServerState());
-            print("znode_count", zkdb.getNodeCount());
-
-            print("watch_count", zkdb.getDataTree().getWatchCount());
-            print("ephemerals_count", zkdb.getDataTree().getEphemeralsCount());
-            print("approximate_data_size", zkdb.getDataTree().approximateDataSize());
-
-            OSMXBean osMbean = new OSMXBean();
-            if (osMbean != null && osMbean.getUnix() == true) {
-                print("open_file_descriptor_count", osMbean.getOpenFileDescriptorCount());
-                print("max_file_descriptor_count", osMbean.getMaxFileDescriptorCount());
-            }
-
-            if(stats.getServerState().equals("leader")) {
-                Leader leader = ((LeaderZooKeeperServer)zkServer).getLeader();
-
-                print("followers", leader.getLearners().size());
-                print("synced_followers", leader.getForwardingFollowers().size());
-                print("pending_syncs", leader.getNumPendingSyncs());
-            }
-        }
-
-        private void print(String key, long number) {
-            print(key, "" + number);
-        }
-
-        private void print(String key, String value) {
-            pw.print("zk_");
-            pw.print(key);
-            pw.print("\t");
-            pw.println(value);
-        }
-
-    }
-
-    private class IsroCommand extends CommandThread {
-
-        public IsroCommand(PrintWriter pw) {
-            super(pw);
-        }
-
-        @Override
-        public void commandRun() {
-            if (zkServer == null) {
-                pw.print("null");
-            } else if (zkServer instanceof ReadOnlyZooKeeperServer) {
-                pw.print("ro");
-            } else {
-                pw.print("rw");
-            }
-        }
-    }
-
     /** Return if four letter word found and responded to, otw false **/
     private boolean checkFourLetterWord(final SelectionKey k, final int len)
     throws IOException
     {
         // We take advantage of the limited size of the length to look
         // for cmds. They are all 4-bytes which fits inside of an int
-        String cmd = cmd2String.get(len);
+        String cmd = FourLetterCommands.cmd2String.get(len);
         if (cmd == null) {
             return false;
         }
@@ -856,71 +505,21 @@ public class NIOServerCnxn extends Serve
 
         final PrintWriter pwriter = new PrintWriter(
                 new BufferedWriter(new SendBufferWriter()));
-        if (len == ruokCmd) {
-            RuokCommand ruok = new RuokCommand(pwriter);
-            ruok.start();
-            return true;
-        } else if (len == getTraceMaskCmd) {
-            TraceMaskCommand tmask = new TraceMaskCommand(pwriter);
-            tmask.start();
-            return true;
-        } else if (len == setTraceMaskCmd) {
+        if (len == FourLetterCommands.setTraceMaskCmd) {
             int rc = sock.read(incomingBuffer);
             if (rc < 0) {
                 throw new IOException("Read error");
             }
-
             incomingBuffer.flip();
             long traceMask = incomingBuffer.getLong();
             ZooTrace.setTextTraceLevel(traceMask);
-            SetTraceMaskCommand setMask = new SetTraceMaskCommand(pwriter, traceMask);
+            SetTraceMaskCommand setMask = new SetTraceMaskCommand(pwriter, this, traceMask);
             setMask.start();
             return true;
-        } else if (len == enviCmd) {
-            EnvCommand env = new EnvCommand(pwriter);
-            env.start();
-            return true;
-        } else if (len == confCmd) {
-            ConfCommand ccmd = new ConfCommand(pwriter);
-            ccmd.start();
-            return true;
-        } else if (len == srstCmd) {
-            StatResetCommand strst = new StatResetCommand(pwriter);
-            strst.start();
-            return true;
-        } else if (len == crstCmd) {
-            CnxnStatResetCommand crst = new CnxnStatResetCommand(pwriter);
-            crst.start();
-            return true;
-        } else if (len == dumpCmd) {
-            DumpCommand dump = new DumpCommand(pwriter);
-            dump.start();
-            return true;
-        } else if (len == statCmd || len == srvrCmd) {
-            StatCommand stat = new StatCommand(pwriter, len);
-            stat.start();
-            return true;
-        } else if (len == consCmd) {
-            ConsCommand cons = new ConsCommand(pwriter);
-            cons.start();
-            return true;
-        } else if (len == wchpCmd || len == wchcCmd || len == wchsCmd) {
-            WatchCommand wcmd = new WatchCommand(pwriter, len);
-            wcmd.start();
-            return true;
-        } else if (len == mntrCmd) {
-            MonitorCommand mntr = new MonitorCommand(pwriter);
-            mntr.start();
-            return true;
-        } else if (len == isroCmd) {
-            IsroCommand isro = new IsroCommand(pwriter);
-            isro.start();
-            return true;
-        } else if (len == telnetCloseCmd) {
-            cleanupWriterSocket(null);
-            return true;
+        } else {
+            CommandExecutor commandExecutor = new CommandExecutor();
+            return commandExecutor.execute(this, pwriter, len, zkServer, factory);
         }
-        return false;
     }
 
     /** Reads the first 4 bytes of lenBuffer, which could be true length or
@@ -1195,4 +794,5 @@ public class NIOServerCnxn extends Serve
         throw new UnsupportedOperationException(
                 "SSL is unsupported in NIOServerCnxn");
     }
+
 }

Modified: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/NettyServerCnxn.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/NettyServerCnxn.java?rev=1688252&r1=1688251&r2=1688252&view=diff
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/NettyServerCnxn.java (original)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/NettyServerCnxn.java Mon Jun 29 15:32:23 2015
@@ -29,32 +29,26 @@ import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.nio.ByteBuffer;
 import java.security.cert.Certificate;
-import java.util.AbstractSet;
 import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.jute.BinaryInputArchive;
 import org.apache.jute.BinaryOutputArchive;
 import org.apache.jute.Record;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.zookeeper.Environment;
-import org.apache.zookeeper.Version;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.proto.ReplyHeader;
 import org.apache.zookeeper.proto.WatcherEvent;
-import org.apache.zookeeper.server.quorum.Leader;
-import org.apache.zookeeper.server.quorum.LeaderZooKeeperServer;
-import org.apache.zookeeper.server.quorum.ReadOnlyZooKeeperServer;
-import org.apache.zookeeper.server.util.OSMXBean;
+import org.apache.zookeeper.server.command.CommandExecutor;
+import org.apache.zookeeper.server.command.FourLetterCommands;
+import org.apache.zookeeper.server.command.SetTraceMaskCommand;
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.jboss.netty.buffer.ChannelBuffers;
 import org.jboss.netty.channel.Channel;
 import org.jboss.netty.channel.ChannelFuture;
 import org.jboss.netty.channel.MessageEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class NettyServerCnxn extends ServerCnxn {
     private static final Logger LOG = LoggerFactory.getLogger(NettyServerCnxn.class);
@@ -225,29 +219,7 @@ public class NettyServerCnxn extends Ser
         packetSent();
     }
 
-    /**
-     * clean up the socket related to a command and also make sure we flush the
-     * data before we do that
-     * 
-     * @param pwriter
-     *            the pwriter for a command socket
-     */
-    private void cleanupWriterSocket(PrintWriter pwriter) {
-        try {
-            if (pwriter != null) {
-                pwriter.flush();
-                pwriter.close();
-            }
-        } catch (Exception e) {
-            LOG.info("Error closing PrintWriter ", e);
-        } finally {
-            try {
-                close();
-            } catch (Exception e) {
-                LOG.error("Error closing a command socket ", e);
-            }
-        }
-    }
+
 
     /**
      * This class wraps the sendBuffer method of NIOServerCnxn. It is
@@ -289,345 +261,13 @@ public class NettyServerCnxn extends Ser
         }
     }
 
-    private static final String ZK_NOT_SERVING =
-        "This ZooKeeper instance is not currently serving requests";
-    
-    /**
-     * Set of threads for commmand ports. All the 4
-     * letter commands are run via a thread. Each class
-     * maps to a correspoding 4 letter command. CommandThread
-     * is the abstract class from which all the others inherit.
-     */
-    private abstract class CommandThread /*extends Thread*/ {
-        PrintWriter pw;
-        
-        CommandThread(PrintWriter pw) {
-            this.pw = pw;
-        }
-        
-        public void start() {
-            run();
-        }
-
-        public void run() {
-            try {
-                commandRun();
-            } catch (IOException ie) {
-                LOG.error("Error in running command ", ie);
-            } finally {
-                cleanupWriterSocket(pw);
-            }
-        }
-        
-        public abstract void commandRun() throws IOException;
-    }
-    
-    private class RuokCommand extends CommandThread {
-        public RuokCommand(PrintWriter pw) {
-            super(pw);
-        }
-        
-        @Override
-        public void commandRun() {
-            pw.print("imok");
-            
-        }
-    }
-    
-    private class TraceMaskCommand extends CommandThread {
-        TraceMaskCommand(PrintWriter pw) {
-            super(pw);
-        }
-        
-        @Override
-        public void commandRun() {
-            long traceMask = ZooTrace.getTextTraceLevel();
-            pw.print(traceMask);
-        }
-    }
-    
-    private class SetTraceMaskCommand extends CommandThread {
-        long trace = 0;
-        SetTraceMaskCommand(PrintWriter pw, long trace) {
-            super(pw);
-            this.trace = trace;
-        }
-        
-        @Override
-        public void commandRun() {
-            pw.print(trace);
-        }
-    }
-    
-    private class EnvCommand extends CommandThread {
-        EnvCommand(PrintWriter pw) {
-            super(pw);
-        }
-        
-        @Override
-        public void commandRun() {
-            List<Environment.Entry> env = Environment.list();
-
-            pw.println("Environment:");
-            for(Environment.Entry e : env) {
-                pw.print(e.getKey());
-                pw.print("=");
-                pw.println(e.getValue());
-            }
-            
-        } 
-    }
-    
-    private class ConfCommand extends CommandThread {
-        ConfCommand(PrintWriter pw) {
-            super(pw);
-        }
-            
-        @Override
-        public void commandRun() {
-            if (zkServer == null) {
-                pw.println(ZK_NOT_SERVING);
-            } else {
-                zkServer.dumpConf(pw);
-            }
-        }
-    }
-    
-    private class StatResetCommand extends CommandThread {
-        public StatResetCommand(PrintWriter pw) {
-            super(pw);
-        }
-        
-        @Override
-        public void commandRun() {
-            if (zkServer == null) {
-                pw.println(ZK_NOT_SERVING);
-            }
-            else { 
-                zkServer.serverStats().reset();
-                pw.println("Server stats reset.");
-            }
-        }
-    }
-    
-    private class CnxnStatResetCommand extends CommandThread {
-        public CnxnStatResetCommand(PrintWriter pw) {
-            super(pw);
-        }
-        
-        @Override
-        public void commandRun() {
-            if (zkServer == null) {
-                pw.println(ZK_NOT_SERVING);
-            } else {
-                synchronized(factory.cnxns){
-                    for(ServerCnxn c : factory.cnxns){
-                        c.resetStats();
-                    }
-                }
-                pw.println("Connection stats reset.");
-            }
-        }
-    }
-
-    private class DumpCommand extends CommandThread {
-        public DumpCommand(PrintWriter pw) {
-            super(pw);
-        }
-        
-        @Override
-        public void commandRun() {
-            if (zkServer == null) {
-                pw.println(ZK_NOT_SERVING);
-            }
-            else {
-                pw.println("SessionTracker dump:");
-                zkServer.sessionTracker.dumpSessions(pw);
-                pw.println("ephemeral nodes dump:");
-                zkServer.dumpEphemerals(pw);
-            }
-        }
-    }
-    
-    private class StatCommand extends CommandThread {
-        int len;
-        public StatCommand(PrintWriter pw, int len) {
-            super(pw);
-            this.len = len;
-        }
-        
-        @Override
-        public void commandRun() {
-            if (zkServer == null) {
-                pw.println(ZK_NOT_SERVING);
-            }
-            else {   
-                pw.print("Zookeeper version: ");
-                pw.println(Version.getFullVersion());
-                if (zkServer instanceof ReadOnlyZooKeeperServer) {
-                    pw.println("READ-ONLY mode; serving only " +
-                               "read-only clients");
-                }
-                if (len == statCmd) {
-                    LOG.info("Stat command output");
-                    pw.println("Clients:");
-                    // clone should be faster than iteration
-                    // ie give up the cnxns lock faster
-                    HashSet<ServerCnxn> cnxns;
-                    synchronized(factory.cnxns){
-                        cnxns = new HashSet<ServerCnxn>(factory.cnxns);
-                    }
-                    for(ServerCnxn c : cnxns){
-                        c.dumpConnectionInfo(pw, true);
-                        pw.println();
-                    }
-                    pw.println();
-                }
-                pw.print(zkServer.serverStats().toString());
-                pw.print("Node count: ");
-                pw.println(zkServer.getZKDatabase().getNodeCount());
-            }
-            
-        }
-    }
-    
-    private class ConsCommand extends CommandThread {
-        public ConsCommand(PrintWriter pw) {
-            super(pw);
-        }
-        
-        @Override
-        public void commandRun() {
-            if (zkServer == null) {
-                pw.println(ZK_NOT_SERVING);
-            } else {
-                // clone should be faster than iteration
-                // ie give up the cnxns lock faster
-                AbstractSet<ServerCnxn> cnxns;
-                synchronized (factory.cnxns) {
-                    cnxns = new HashSet<ServerCnxn>(factory.cnxns);
-                }
-                for (ServerCnxn c : cnxns) {
-                    c.dumpConnectionInfo(pw, false);
-                    pw.println();
-                }
-                pw.println();
-            }
-        }
-    }
-    
-    private class WatchCommand extends CommandThread {
-        int len = 0;
-        public WatchCommand(PrintWriter pw, int len) {
-            super(pw);
-            this.len = len;
-        }
-
-        @Override
-        public void commandRun() {
-            if (zkServer == null) {
-                pw.println(ZK_NOT_SERVING);
-            } else {
-                DataTree dt = zkServer.getZKDatabase().getDataTree();
-                if (len == wchsCmd) {
-                    dt.dumpWatchesSummary(pw);
-                } else if (len == wchpCmd) {
-                    dt.dumpWatches(pw, true);
-                } else {
-                    dt.dumpWatches(pw, false);
-                }
-                pw.println();
-            }
-        }
-    }
-
-    private class MonitorCommand extends CommandThread {
-
-        MonitorCommand(PrintWriter pw) {
-            super(pw);
-        }
-
-        @Override
-        public void commandRun() {
-            if(zkServer == null) {
-                pw.println(ZK_NOT_SERVING);
-                return;
-            }
-            ZKDatabase zkdb = zkServer.getZKDatabase();
-            ServerStats stats = zkServer.serverStats();
-
-            print("version", Version.getFullVersion());
-
-            print("avg_latency", stats.getAvgLatency());
-            print("max_latency", stats.getMaxLatency());
-            print("min_latency", stats.getMinLatency());
-
-            print("packets_received", stats.getPacketsReceived());
-            print("packets_sent", stats.getPacketsSent());
-            print("num_alive_connections", stats.getNumAliveClientConnections());
-
-            print("outstanding_requests", stats.getOutstandingRequests());
-
-            print("server_state", stats.getServerState());
-            print("znode_count", zkdb.getNodeCount());
-
-            print("watch_count", zkdb.getDataTree().getWatchCount());
-            print("ephemerals_count", zkdb.getDataTree().getEphemeralsCount());
-            print("approximate_data_size", zkdb.getDataTree().approximateDataSize());
-
-            OSMXBean osMbean = new OSMXBean();
-            if (osMbean != null && osMbean.getUnix() == true) {
-                print("open_file_descriptor_count", osMbean.getOpenFileDescriptorCount());
-                print("max_file_descriptor_count", osMbean.getMaxFileDescriptorCount());
-            }
-          
-            if(stats.getServerState().equals("leader")) {
-                Leader leader = ((LeaderZooKeeperServer)zkServer).getLeader();
-
-                print("followers", leader.getLearners().size());
-                print("synced_followers", leader.getForwardingFollowers().size());
-                print("pending_syncs", leader.getNumPendingSyncs());
-            }
-        }
-
-        private void print(String key, long number) {
-            print(key, "" + number);
-        }
-
-        private void print(String key, String value) {
-            pw.print("zk_");
-            pw.print(key);
-            pw.print("\t");
-            pw.println(value);
-        }
-
-    }
-
-    private class IsroCommand extends CommandThread {
-
-        public IsroCommand(PrintWriter pw) {
-            super(pw);
-        }
-
-        @Override
-        public void commandRun() {
-            if (zkServer == null) {
-                pw.print("null");
-            } else if (zkServer instanceof ReadOnlyZooKeeperServer) {
-                pw.print("ro");
-            } else {
-                pw.print("rw");
-            }
-        }
-    }
-
     /** Return if four letter word found and responded to, otw false **/
     private boolean checkFourLetterWord(final Channel channel,
             ChannelBuffer message, final int len) throws IOException
     {
         // We take advantage of the limited size of the length to look
         // for cmds. They are all 4-bytes which fits inside of an int
-        String cmd = cmd2String.get(len);
+        String cmd = FourLetterCommands.cmd2String.get(len);
         if (cmd == null) {
             return false;
         }
@@ -638,66 +278,20 @@ public class NettyServerCnxn extends Ser
 
         final PrintWriter pwriter = new PrintWriter(
                 new BufferedWriter(new SendBufferWriter()));
-        if (len == ruokCmd) {
-            RuokCommand ruok = new RuokCommand(pwriter);
-            ruok.start();
-            return true;
-        } else if (len == getTraceMaskCmd) {
-            TraceMaskCommand tmask = new TraceMaskCommand(pwriter);
-            tmask.start();
-            return true;
-        } else if (len == setTraceMaskCmd) {
+       if (len == FourLetterCommands.setTraceMaskCmd) {
             ByteBuffer mask = ByteBuffer.allocate(4);
             message.readBytes(mask);
 
             bb.flip();
             long traceMask = mask.getLong();
             ZooTrace.setTextTraceLevel(traceMask);
-            SetTraceMaskCommand setMask = new SetTraceMaskCommand(pwriter, traceMask);
+            SetTraceMaskCommand setMask = new SetTraceMaskCommand(pwriter, this, traceMask);
             setMask.start();
             return true;
-        } else if (len == enviCmd) {
-            EnvCommand env = new EnvCommand(pwriter);
-            env.start();
-            return true;
-        } else if (len == confCmd) {
-            ConfCommand ccmd = new ConfCommand(pwriter);
-            ccmd.start();
-            return true;
-        } else if (len == srstCmd) {
-            StatResetCommand strst = new StatResetCommand(pwriter);
-            strst.start();
-            return true;
-        } else if (len == crstCmd) {
-            CnxnStatResetCommand crst = new CnxnStatResetCommand(pwriter);
-            crst.start();
-            return true;
-        } else if (len == dumpCmd) {
-            DumpCommand dump = new DumpCommand(pwriter);
-            dump.start();
-            return true;
-        } else if (len == statCmd || len == srvrCmd) {
-            StatCommand stat = new StatCommand(pwriter, len);
-            stat.start();
-            return true;
-        } else if (len == consCmd) {
-            ConsCommand cons = new ConsCommand(pwriter);
-            cons.start();
-            return true;
-        } else if (len == wchpCmd || len == wchcCmd || len == wchsCmd) {
-            WatchCommand wcmd = new WatchCommand(pwriter, len);
-            wcmd.start();
-            return true;
-        } else if (len == mntrCmd) {
-            MonitorCommand mntr = new MonitorCommand(pwriter);
-            mntr.start();
-            return true;
-        } else if (len == isroCmd) {
-            IsroCommand isro = new IsroCommand(pwriter);
-            isro.start();
-            return true;
+        } else {
+            CommandExecutor commandExecutor = new CommandExecutor();
+            return commandExecutor.execute(this, pwriter, len, zkServer,factory);
         }
-        return false;
     }
 
     public void receiveMessage(ChannelBuffer message) {
@@ -879,5 +473,4 @@ public class NettyServerCnxn extends Ser
             clientChain = Arrays.copyOf(chain, chain.length);
         }
     }
-
 }

Modified: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/ServerCnxn.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/ServerCnxn.java?rev=1688252&r1=1688251&r2=1688252&view=diff
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/ServerCnxn.java (original)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/ServerCnxn.java Mon Jun 29 15:32:23 2015
@@ -27,7 +27,6 @@ import java.security.cert.Certificate;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
-import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -39,6 +38,8 @@ import org.apache.zookeeper.Watcher;
 import org.apache.zookeeper.data.Id;
 import org.apache.zookeeper.proto.ReplyHeader;
 import org.apache.zookeeper.proto.RequestHeader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Interface to a Server connection - represents a connection from a client
@@ -48,6 +49,7 @@ public abstract class ServerCnxn impleme
     // This is just an arbitrary object to represent requests issued by
     // (aka owned by) this class
     final public static Object me = new Object();
+    private static final Logger LOG = LoggerFactory.getLogger(ServerCnxn.class);
     
     protected ArrayList<Id> authInfo = new ArrayList<Id>();
 
@@ -119,149 +121,6 @@ public abstract class ServerCnxn impleme
         }
     }
 
-    /*
-     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
-     * Zk Admin</a>. this link is for all the commands.
-     */
-    protected final static int confCmd =
-        ByteBuffer.wrap("conf".getBytes()).getInt();
-
-    /*
-     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
-     * Zk Admin</a>. this link is for all the commands.
-     */
-    protected final static int consCmd =
-        ByteBuffer.wrap("cons".getBytes()).getInt();
-
-    /*
-     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
-     * Zk Admin</a>. this link is for all the commands.
-     */
-    protected final static int crstCmd =
-        ByteBuffer.wrap("crst".getBytes()).getInt();
-
-    /*
-     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
-     * Zk Admin</a>. this link is for all the commands.
-     */
-    protected final static int dumpCmd =
-        ByteBuffer.wrap("dump".getBytes()).getInt();
-
-    /*
-     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
-     * Zk Admin</a>. this link is for all the commands.
-     */
-    protected final static int enviCmd =
-        ByteBuffer.wrap("envi".getBytes()).getInt();
-
-    /*
-     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
-     * Zk Admin</a>. this link is for all the commands.
-     */
-    protected final static int getTraceMaskCmd =
-        ByteBuffer.wrap("gtmk".getBytes()).getInt();
-
-    /*
-     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
-     * Zk Admin</a>. this link is for all the commands.
-     */
-    protected final static int ruokCmd =
-        ByteBuffer.wrap("ruok".getBytes()).getInt();
-    /*
-     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
-     * Zk Admin</a>. this link is for all the commands.
-     */
-    protected final static int setTraceMaskCmd =
-        ByteBuffer.wrap("stmk".getBytes()).getInt();
-
-    /*
-     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
-     * Zk Admin</a>. this link is for all the commands.
-     */
-    protected final static int srvrCmd =
-        ByteBuffer.wrap("srvr".getBytes()).getInt();
-
-    /*
-     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
-     * Zk Admin</a>. this link is for all the commands.
-     */
-    protected final static int srstCmd =
-        ByteBuffer.wrap("srst".getBytes()).getInt();
-
-    /*
-     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
-     * Zk Admin</a>. this link is for all the commands.
-     */
-    protected final static int statCmd =
-        ByteBuffer.wrap("stat".getBytes()).getInt();
-
-    /*
-     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
-     * Zk Admin</a>. this link is for all the commands.
-     */
-    protected final static int wchcCmd =
-        ByteBuffer.wrap("wchc".getBytes()).getInt();
-
-    /*
-     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
-     * Zk Admin</a>. this link is for all the commands.
-     */
-    protected final static int wchpCmd =
-        ByteBuffer.wrap("wchp".getBytes()).getInt();
-
-    /*
-     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
-     * Zk Admin</a>. this link is for all the commands.
-     */
-    protected final static int wchsCmd =
-        ByteBuffer.wrap("wchs".getBytes()).getInt();
-
-    /*
-     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
-     * Zk Admin</a>. this link is for all the commands.
-     */
-    protected final static int mntrCmd = ByteBuffer.wrap("mntr".getBytes())
-            .getInt();
-
-    /*
-     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
-     * Zk Admin</a>. this link is for all the commands.
-     */
-    protected final static int isroCmd = ByteBuffer.wrap("isro".getBytes())
-            .getInt();
-
-    /*
-     * The control sequence sent by the telnet program when it closes a
-     * connection. Include simply to keep the logs cleaner (the server would
-     * close the connection anyway because it would parse this as a negative
-     * length).
-     */
-    protected final static int telnetCloseCmd = 0xfff4fffd;
-
-    protected final static HashMap<Integer, String> cmd2String =
-        new HashMap<Integer, String>();
-
-    // specify all of the commands that are available
-    static {
-        cmd2String.put(confCmd, "conf");
-        cmd2String.put(consCmd, "cons");
-        cmd2String.put(crstCmd, "crst");
-        cmd2String.put(dumpCmd, "dump");
-        cmd2String.put(enviCmd, "envi");
-        cmd2String.put(getTraceMaskCmd, "gtmk");
-        cmd2String.put(ruokCmd, "ruok");
-        cmd2String.put(setTraceMaskCmd, "stmk");
-        cmd2String.put(srstCmd, "srst");
-        cmd2String.put(srvrCmd, "srvr");
-        cmd2String.put(statCmd, "stat");
-        cmd2String.put(wchcCmd, "wchc");
-        cmd2String.put(wchpCmd, "wchp");
-        cmd2String.put(wchsCmd, "wchs");
-        cmd2String.put(mntrCmd, "mntr");
-        cmd2String.put(isroCmd, "isro");
-        cmd2String.put(telnetCloseCmd, "telnet close");
-    }
-
     protected void packetReceived() {
         incrPacketsReceived();
         ServerStats serverStats = serverStats();
@@ -417,7 +276,7 @@ public abstract class ServerCnxn impleme
      * @param brief iff true prints brief details, otw full detail
      * @return information about this connection
      */
-    protected synchronized void
+    public synchronized void
     dumpConnectionInfo(PrintWriter pwriter, boolean brief) {
         pwriter.print(" ");
         pwriter.print(getRemoteSocketAddress());
@@ -486,4 +345,28 @@ public abstract class ServerCnxn impleme
         }
         return info;
     }
+
+    /**
+     * clean up the socket related to a command and also make sure we flush the
+     * data before we do that
+     *
+     * @param pwriter
+     *            the pwriter for a command socket
+     */
+    public void cleanupWriterSocket(PrintWriter pwriter) {
+        try {
+            if (pwriter != null) {
+                pwriter.flush();
+                pwriter.close();
+            }
+        } catch (Exception e) {
+            LOG.info("Error closing PrintWriter ", e);
+        } finally {
+            try {
+                close();
+            } catch (Exception e) {
+                LOG.error("Error closing a command socket ", e);
+            }
+        }
+    }
 }

Added: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/AbstractFourLetterCommand.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/AbstractFourLetterCommand.java?rev=1688252&view=auto
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/AbstractFourLetterCommand.java (added)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/AbstractFourLetterCommand.java Mon Jun 29 15:32:23 2015
@@ -0,0 +1,72 @@
+/**
+ * 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.server.command;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import org.apache.zookeeper.server.ServerCnxn;
+import org.apache.zookeeper.server.ServerCnxnFactory;
+import org.apache.zookeeper.server.ZooKeeperServer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Set of threads for command ports. All the 4 letter commands are run via a
+ * thread. Each class maps to a correspoding 4 letter command. CommandThread is
+ * the abstract class from which all the others inherit.
+ */
+public abstract class AbstractFourLetterCommand {
+    private static final Logger LOG = LoggerFactory
+        .getLogger(AbstractFourLetterCommand.class);
+    protected static final String ZK_NOT_SERVING = "This ZooKeeper instance is not currently serving requests";
+    protected PrintWriter pw;
+    protected ServerCnxn serverCnxn;
+    protected ZooKeeperServer zkServer;
+    protected ServerCnxnFactory factory;
+
+    public AbstractFourLetterCommand(PrintWriter pw, ServerCnxn serverCnxn) {
+        this.pw = pw;
+        this.serverCnxn = serverCnxn;
+    }
+
+    public void start() {
+        run();
+    }
+
+    public void run() {
+        try {
+            commandRun();
+        } catch (IOException ie) {
+            LOG.error("Error in running command ", ie);
+        } finally {
+            serverCnxn.cleanupWriterSocket(pw);
+        }
+    }
+
+    public void setZkServer(ZooKeeperServer zkServer) {
+        this.zkServer = zkServer;
+    }
+
+    public void setFactory(ServerCnxnFactory factory) {
+        this.factory = factory;
+    }
+
+    public abstract void commandRun() throws IOException;
+}

Added: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/CnxnStatResetCommand.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/CnxnStatResetCommand.java?rev=1688252&view=auto
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/CnxnStatResetCommand.java (added)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/CnxnStatResetCommand.java Mon Jun 29 15:32:23 2015
@@ -0,0 +1,39 @@
+/**
+ * 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.server.command;
+
+import java.io.PrintWriter;
+
+import org.apache.zookeeper.server.ServerCnxn;
+
+public class CnxnStatResetCommand extends AbstractFourLetterCommand {
+    public CnxnStatResetCommand(PrintWriter pw, ServerCnxn serverCnxn) {
+        super(pw, serverCnxn);
+    }
+
+    @Override
+    public void commandRun() {
+        if (zkServer == null) {
+            pw.println(ZK_NOT_SERVING);
+        } else {
+            factory.resetAllConnectionStats();
+            pw.println("Connection stats reset.");
+        }
+    }
+}

Added: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/CommandExecutor.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/CommandExecutor.java?rev=1688252&view=auto
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/CommandExecutor.java (added)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/CommandExecutor.java Mon Jun 29 15:32:23 2015
@@ -0,0 +1,79 @@
+/**
+ * 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.server.command;
+
+import java.io.PrintWriter;
+
+import org.apache.zookeeper.server.ServerCnxn;
+import org.apache.zookeeper.server.ServerCnxnFactory;
+import org.apache.zookeeper.server.ZooKeeperServer;
+
+public class CommandExecutor {
+    /**
+     * This class decides which command to be executed and then executes
+     */
+    public boolean execute(ServerCnxn serverCnxn, PrintWriter pwriter,
+            final int commandCode, ZooKeeperServer zkServer, ServerCnxnFactory factory) {
+        AbstractFourLetterCommand command = getCommand(serverCnxn,pwriter, commandCode);
+
+        if (command == null) {
+            return false;
+        }
+
+        command.setZkServer(zkServer);
+        command.setFactory(factory);
+        command.start();
+        return true;
+    }
+
+    private AbstractFourLetterCommand getCommand(ServerCnxn serverCnxn,
+            PrintWriter pwriter, final int commandCode) {
+        AbstractFourLetterCommand command = null;
+        if (commandCode == FourLetterCommands.ruokCmd) {
+            command = new RuokCommand(pwriter, serverCnxn);
+        } else if (commandCode == FourLetterCommands.getTraceMaskCmd) {
+            command = new TraceMaskCommand(pwriter, serverCnxn);
+        } else if (commandCode == FourLetterCommands.enviCmd) {
+            command = new EnvCommand(pwriter, serverCnxn);
+        } else if (commandCode == FourLetterCommands.confCmd) {
+            command = new ConfCommand(pwriter, serverCnxn);
+        } else if (commandCode == FourLetterCommands.srstCmd) {
+            command = new StatResetCommand(pwriter, serverCnxn);
+        } else if (commandCode == FourLetterCommands.crstCmd) {
+            command = new CnxnStatResetCommand(pwriter, serverCnxn);
+        } else if (commandCode == FourLetterCommands.dumpCmd) {
+            command = new DumpCommand(pwriter, serverCnxn);
+        } else if (commandCode == FourLetterCommands.statCmd
+                || commandCode == FourLetterCommands.srvrCmd) {
+            command = new StatCommand(pwriter, serverCnxn, commandCode);
+        } else if (commandCode == FourLetterCommands.consCmd) {
+            command = new ConsCommand(pwriter, serverCnxn);
+        } else if (commandCode == FourLetterCommands.wchpCmd
+                || commandCode == FourLetterCommands.wchcCmd
+                || commandCode == FourLetterCommands.wchsCmd) {
+            command = new WatchCommand(pwriter, serverCnxn, commandCode);
+        } else if (commandCode == FourLetterCommands.mntrCmd) {
+            command = new MonitorCommand(pwriter, serverCnxn);
+        } else if (commandCode == FourLetterCommands.isroCmd) {
+            command = new IsroCommand(pwriter, serverCnxn);
+        }
+        return command;
+    }
+
+}

Added: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/ConfCommand.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/ConfCommand.java?rev=1688252&view=auto
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/ConfCommand.java (added)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/ConfCommand.java Mon Jun 29 15:32:23 2015
@@ -0,0 +1,38 @@
+/**
+ * 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.server.command;
+
+import java.io.PrintWriter;
+
+import org.apache.zookeeper.server.ServerCnxn;
+
+public class ConfCommand extends AbstractFourLetterCommand {
+    ConfCommand(PrintWriter pw, ServerCnxn serverCnxn) {
+        super(pw,serverCnxn);
+    }
+
+    @Override
+    public void commandRun() {
+        if (zkServer == null) {
+            pw.println(ZK_NOT_SERVING);
+        } else {
+            zkServer.dumpConf(pw);
+        }
+    }
+}

Added: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/ConsCommand.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/ConsCommand.java?rev=1688252&view=auto
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/ConsCommand.java (added)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/ConsCommand.java Mon Jun 29 15:32:23 2015
@@ -0,0 +1,42 @@
+/**
+ * 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.server.command;
+
+import java.io.PrintWriter;
+
+import org.apache.zookeeper.server.ServerCnxn;
+
+public class ConsCommand extends AbstractFourLetterCommand {
+    public ConsCommand(PrintWriter pw, ServerCnxn serverCnxn) {
+        super(pw, serverCnxn);
+    }
+
+    @Override
+    public void commandRun() {
+        if (zkServer == null) {
+            pw.println(ZK_NOT_SERVING);
+        } else {
+            for (ServerCnxn c : factory.getConnections()) {
+                c.dumpConnectionInfo(pw, false);
+                pw.println();
+            }
+            pw.println();
+        }
+    }
+}

Added: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/DumpCommand.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/DumpCommand.java?rev=1688252&view=auto
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/DumpCommand.java (added)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/DumpCommand.java Mon Jun 29 15:32:23 2015
@@ -0,0 +1,47 @@
+/**
+ * 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.server.command;
+
+import java.io.PrintWriter;
+
+import org.apache.zookeeper.server.NIOServerCnxnFactory;
+import org.apache.zookeeper.server.ServerCnxn;
+
+public class DumpCommand extends AbstractFourLetterCommand {
+    public DumpCommand(PrintWriter pw, ServerCnxn serverCnxn) {
+        super(pw, serverCnxn);
+    }
+
+    @Override
+    public void commandRun() {
+        if (zkServer == null) {
+            pw.println(ZK_NOT_SERVING);
+        } else {
+            pw.println("SessionTracker dump:");
+            zkServer.getSessionTracker().dumpSessions(pw);
+            pw.println("ephemeral nodes dump:");
+            zkServer.dumpEphemerals(pw);
+            pw.println("Connections dump:");
+            //dumpConnections connection is implemented only in NIOServerCnxnFactory
+            if (factory instanceof NIOServerCnxnFactory) {
+                ((NIOServerCnxnFactory)factory).dumpConnections(pw);
+            }
+        }
+    }
+}

Added: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/EnvCommand.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/EnvCommand.java?rev=1688252&view=auto
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/EnvCommand.java (added)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/EnvCommand.java Mon Jun 29 15:32:23 2015
@@ -0,0 +1,43 @@
+/**
+ * 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.server.command;
+
+import java.io.PrintWriter;
+import java.util.List;
+
+import org.apache.zookeeper.Environment;
+import org.apache.zookeeper.server.ServerCnxn;
+
+public class EnvCommand extends AbstractFourLetterCommand {
+    EnvCommand(PrintWriter pw, ServerCnxn serverCnxn) {
+        super(pw, serverCnxn);
+    }
+
+    @Override
+    public void commandRun() {
+        List<Environment.Entry> env = Environment.list();
+
+        pw.println("Environment:");
+        for (Environment.Entry e : env) {
+            pw.print(e.getKey());
+            pw.print("=");
+            pw.println(e.getValue());
+        }
+    }
+}

Added: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/FourLetterCommands.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/FourLetterCommands.java?rev=1688252&view=auto
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/FourLetterCommands.java (added)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/FourLetterCommands.java Mon Jun 29 15:32:23 2015
@@ -0,0 +1,170 @@
+/**
+ * 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.server.command;
+
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+
+/**
+ * This class contains constants for all the four letter commands
+ */
+public class FourLetterCommands {
+    /*
+     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
+     * Zk Admin</a>. this link is for all the commands.
+     */
+    public final static int confCmd =
+        ByteBuffer.wrap("conf".getBytes()).getInt();
+
+    /*
+     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
+     * Zk Admin</a>. this link is for all the commands.
+     */
+    public final static int consCmd =
+        ByteBuffer.wrap("cons".getBytes()).getInt();
+
+    /*
+     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
+     * Zk Admin</a>. this link is for all the commands.
+     */
+    public final static int crstCmd =
+        ByteBuffer.wrap("crst".getBytes()).getInt();
+
+    /*
+     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
+     * Zk Admin</a>. this link is for all the commands.
+     */
+    public final static int dumpCmd =
+        ByteBuffer.wrap("dump".getBytes()).getInt();
+
+    /*
+     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
+     * Zk Admin</a>. this link is for all the commands.
+     */
+    public final static int enviCmd =
+        ByteBuffer.wrap("envi".getBytes()).getInt();
+
+    /*
+     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
+     * Zk Admin</a>. this link is for all the commands.
+     */
+    public final static int getTraceMaskCmd =
+        ByteBuffer.wrap("gtmk".getBytes()).getInt();
+
+    /*
+     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
+     * Zk Admin</a>. this link is for all the commands.
+     */
+    public final static int ruokCmd =
+        ByteBuffer.wrap("ruok".getBytes()).getInt();
+    /*
+     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
+     * Zk Admin</a>. this link is for all the commands.
+     */
+    public final static int setTraceMaskCmd =
+        ByteBuffer.wrap("stmk".getBytes()).getInt();
+
+    /*
+     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
+     * Zk Admin</a>. this link is for all the commands.
+     */
+    public final static int srvrCmd =
+        ByteBuffer.wrap("srvr".getBytes()).getInt();
+
+    /*
+     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
+     * Zk Admin</a>. this link is for all the commands.
+     */
+    public final static int srstCmd =
+        ByteBuffer.wrap("srst".getBytes()).getInt();
+
+    /*
+     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
+     * Zk Admin</a>. this link is for all the commands.
+     */
+    public final static int statCmd =
+        ByteBuffer.wrap("stat".getBytes()).getInt();
+
+    /*
+     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
+     * Zk Admin</a>. this link is for all the commands.
+     */
+    public final static int wchcCmd =
+        ByteBuffer.wrap("wchc".getBytes()).getInt();
+
+    /*
+     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
+     * Zk Admin</a>. this link is for all the commands.
+     */
+    public final static int wchpCmd =
+        ByteBuffer.wrap("wchp".getBytes()).getInt();
+
+    /*
+     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
+     * Zk Admin</a>. this link is for all the commands.
+     */
+    public final static int wchsCmd =
+        ByteBuffer.wrap("wchs".getBytes()).getInt();
+
+    /*
+     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
+     * Zk Admin</a>. this link is for all the commands.
+     */
+    public final static int mntrCmd = ByteBuffer.wrap("mntr".getBytes())
+            .getInt();
+
+    /*
+     * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands">
+     * Zk Admin</a>. this link is for all the commands.
+     */
+    public final static int isroCmd = ByteBuffer.wrap("isro".getBytes())
+            .getInt();
+
+    /*
+     * The control sequence sent by the telnet program when it closes a
+     * connection. Include simply to keep the logs cleaner (the server would
+     * close the connection anyway because it would parse this as a negative
+     * length).
+     */
+    public final static int telnetCloseCmd = 0xfff4fffd;
+
+    public final static HashMap<Integer, String> cmd2String =
+        new HashMap<Integer, String>();
+
+    // specify all of the commands that are available
+    static {
+        cmd2String.put(confCmd, "conf");
+        cmd2String.put(consCmd, "cons");
+        cmd2String.put(crstCmd, "crst");
+        cmd2String.put(dumpCmd, "dump");
+        cmd2String.put(enviCmd, "envi");
+        cmd2String.put(getTraceMaskCmd, "gtmk");
+        cmd2String.put(ruokCmd, "ruok");
+        cmd2String.put(setTraceMaskCmd, "stmk");
+        cmd2String.put(srstCmd, "srst");
+        cmd2String.put(srvrCmd, "srvr");
+        cmd2String.put(statCmd, "stat");
+        cmd2String.put(wchcCmd, "wchc");
+        cmd2String.put(wchpCmd, "wchp");
+        cmd2String.put(wchsCmd, "wchs");
+        cmd2String.put(mntrCmd, "mntr");
+        cmd2String.put(isroCmd, "isro");
+        cmd2String.put(telnetCloseCmd, "telnet close");
+    }
+}

Added: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/IsroCommand.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/IsroCommand.java?rev=1688252&view=auto
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/IsroCommand.java (added)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/IsroCommand.java Mon Jun 29 15:32:23 2015
@@ -0,0 +1,42 @@
+/**
+ * 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.server.command;
+
+import java.io.PrintWriter;
+
+import org.apache.zookeeper.server.ServerCnxn;
+import org.apache.zookeeper.server.quorum.ReadOnlyZooKeeperServer;
+
+public class IsroCommand extends AbstractFourLetterCommand {
+
+    public IsroCommand(PrintWriter pw, ServerCnxn serverCnxn) {
+        super(pw, serverCnxn);
+    }
+
+    @Override
+    public void commandRun() {
+        if (zkServer == null) {
+            pw.print("null");
+        } else if (zkServer instanceof ReadOnlyZooKeeperServer) {
+            pw.print("ro");
+        } else {
+            pw.print("rw");
+        }
+    }
+}

Added: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/MonitorCommand.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/MonitorCommand.java?rev=1688252&view=auto
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/MonitorCommand.java (added)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/MonitorCommand.java Mon Jun 29 15:32:23 2015
@@ -0,0 +1,91 @@
+/**
+ * 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.server.command;
+
+import java.io.PrintWriter;
+
+import org.apache.zookeeper.Version;
+import org.apache.zookeeper.server.ServerCnxn;
+import org.apache.zookeeper.server.ServerStats;
+import org.apache.zookeeper.server.ZKDatabase;
+import org.apache.zookeeper.server.quorum.Leader;
+import org.apache.zookeeper.server.quorum.LeaderZooKeeperServer;
+import org.apache.zookeeper.server.util.OSMXBean;
+
+public class MonitorCommand extends AbstractFourLetterCommand {
+
+    MonitorCommand(PrintWriter pw, ServerCnxn serverCnxn) {
+        super(pw, serverCnxn);
+    }
+
+    @Override
+    public void commandRun() {
+        if (zkServer == null) {
+            pw.println(ZK_NOT_SERVING);
+            return;
+        }
+        ZKDatabase zkdb = zkServer.getZKDatabase();
+        ServerStats stats = zkServer.serverStats();
+
+        print("version", Version.getFullVersion());
+
+        print("avg_latency", stats.getAvgLatency());
+        print("max_latency", stats.getMaxLatency());
+        print("min_latency", stats.getMinLatency());
+
+        print("packets_received", stats.getPacketsReceived());
+        print("packets_sent", stats.getPacketsSent());
+        print("num_alive_connections", stats.getNumAliveClientConnections());
+
+        print("outstanding_requests", stats.getOutstandingRequests());
+
+        print("server_state", stats.getServerState());
+        print("znode_count", zkdb.getNodeCount());
+
+        print("watch_count", zkdb.getDataTree().getWatchCount());
+        print("ephemerals_count", zkdb.getDataTree().getEphemeralsCount());
+        print("approximate_data_size", zkdb.getDataTree().approximateDataSize());
+
+        OSMXBean osMbean = new OSMXBean();
+        if (osMbean != null && osMbean.getUnix() == true) {
+            print("open_file_descriptor_count", osMbean.getOpenFileDescriptorCount());
+            print("max_file_descriptor_count", osMbean.getMaxFileDescriptorCount());
+        }
+
+        if (stats.getServerState().equals("leader")) {
+            Leader leader = ((LeaderZooKeeperServer)zkServer).getLeader();
+
+            print("followers", leader.getLearners().size());
+            print("synced_followers", leader.getForwardingFollowers().size());
+            print("pending_syncs", leader.getNumPendingSyncs());
+        }
+    }
+
+    private void print(String key, long number) {
+        print(key, "" + number);
+    }
+
+    private void print(String key, String value) {
+        pw.print("zk_");
+        pw.print(key);
+        pw.print("\t");
+        pw.println(value);
+    }
+
+}

Added: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/RuokCommand.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/RuokCommand.java?rev=1688252&view=auto
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/RuokCommand.java (added)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/RuokCommand.java Mon Jun 29 15:32:23 2015
@@ -0,0 +1,34 @@
+/**
+ * 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.server.command;
+
+import java.io.PrintWriter;
+
+import org.apache.zookeeper.server.ServerCnxn;
+
+public class RuokCommand extends AbstractFourLetterCommand {
+    public RuokCommand(PrintWriter pw, ServerCnxn serverCnxn) {
+        super(pw, serverCnxn);
+    }
+
+    @Override
+    public void commandRun() {
+        pw.print("imok");
+    }
+}

Added: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/SetTraceMaskCommand.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/SetTraceMaskCommand.java?rev=1688252&view=auto
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/SetTraceMaskCommand.java (added)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/SetTraceMaskCommand.java Mon Jun 29 15:32:23 2015
@@ -0,0 +1,36 @@
+/**
+ * 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.server.command;
+
+import java.io.PrintWriter;
+
+import org.apache.zookeeper.server.ServerCnxn;
+
+public class SetTraceMaskCommand extends AbstractFourLetterCommand {
+    long trace = 0;
+    public SetTraceMaskCommand(PrintWriter pw, ServerCnxn serverCnxn, long trace) {
+        super(pw, serverCnxn);
+        this.trace = trace;
+    }
+
+    @Override
+    public void commandRun() {
+        pw.print(trace);
+    }
+}

Added: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/StatCommand.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/StatCommand.java?rev=1688252&view=auto
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/StatCommand.java (added)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/StatCommand.java Mon Jun 29 15:32:23 2015
@@ -0,0 +1,62 @@
+/**
+ * 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.server.command;
+
+import java.io.PrintWriter;
+
+import org.apache.zookeeper.Version;
+import org.apache.zookeeper.server.ServerCnxn;
+import org.apache.zookeeper.server.quorum.ReadOnlyZooKeeperServer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class StatCommand extends AbstractFourLetterCommand {
+    private static final Logger LOG = LoggerFactory
+            .getLogger(AbstractFourLetterCommand.class);
+    private int len;
+    public StatCommand(PrintWriter pw, ServerCnxn serverCnxn, int len) {
+        super(pw, serverCnxn);
+        this.len = len;
+    }
+
+    @Override
+    public void commandRun() {
+        if (zkServer == null) {
+            pw.println(ZK_NOT_SERVING);
+        } else {
+            pw.print("Zookeeper version: ");
+            pw.println(Version.getFullVersion());
+            if (zkServer instanceof ReadOnlyZooKeeperServer) {
+                pw.println("READ-ONLY mode; serving only read-only clients");
+            }
+            if (len == FourLetterCommands.statCmd) {
+                LOG.info("Stat command output");
+                pw.println("Clients:");
+                for(ServerCnxn c : factory.getConnections()){
+                    c.dumpConnectionInfo(pw, true);
+                    pw.println();
+                }
+                pw.println();
+            }
+            pw.print(zkServer.serverStats().toString());
+            pw.print("Node count: ");
+            pw.println(zkServer.getZKDatabase().getNodeCount());
+        }
+    }
+}

Added: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/StatResetCommand.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/StatResetCommand.java?rev=1688252&view=auto
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/StatResetCommand.java (added)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/StatResetCommand.java Mon Jun 29 15:32:23 2015
@@ -0,0 +1,39 @@
+/**
+ * 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.server.command;
+
+import java.io.PrintWriter;
+
+import org.apache.zookeeper.server.ServerCnxn;
+
+public class StatResetCommand extends AbstractFourLetterCommand {
+    public StatResetCommand(PrintWriter pw, ServerCnxn serverCnxn) {
+        super(pw, serverCnxn);
+    }
+
+    @Override
+    public void commandRun() {
+        if (zkServer == null) {
+            pw.println(ZK_NOT_SERVING);
+        } else {
+            zkServer.serverStats().reset();
+            pw.println("Server stats reset.");
+        }
+    }
+}

Added: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/TraceMaskCommand.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/TraceMaskCommand.java?rev=1688252&view=auto
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/TraceMaskCommand.java (added)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/TraceMaskCommand.java Mon Jun 29 15:32:23 2015
@@ -0,0 +1,36 @@
+/**
+ * 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.server.command;
+
+import java.io.PrintWriter;
+
+import org.apache.zookeeper.server.ServerCnxn;
+import org.apache.zookeeper.server.ZooTrace;
+
+public class TraceMaskCommand extends AbstractFourLetterCommand {
+    TraceMaskCommand(PrintWriter pw, ServerCnxn serverCnxn) {
+        super(pw, serverCnxn);
+    }
+
+    @Override
+    public void commandRun() {
+        long traceMask = ZooTrace.getTextTraceLevel();
+        pw.print(traceMask);
+    }
+}

Added: zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/WatchCommand.java
URL: http://svn.apache.org/viewvc/zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/WatchCommand.java?rev=1688252&view=auto
==============================================================================
--- zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/WatchCommand.java (added)
+++ zookeeper/branches/branch-3.5/src/java/main/org/apache/zookeeper/server/command/WatchCommand.java Mon Jun 29 15:32:23 2015
@@ -0,0 +1,49 @@
+/**
+ * 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.server.command;
+
+import java.io.PrintWriter;
+
+import org.apache.zookeeper.server.DataTree;
+import org.apache.zookeeper.server.ServerCnxn;
+
+public class WatchCommand extends AbstractFourLetterCommand {
+    int len = 0;
+    public WatchCommand(PrintWriter pw, ServerCnxn serverCnxn, int len) {
+        super(pw, serverCnxn);
+        this.len = len;
+    }
+
+    @Override
+    public void commandRun() {
+        if (zkServer == null) {
+            pw.println(ZK_NOT_SERVING);
+        } else {
+            DataTree dt = zkServer.getZKDatabase().getDataTree();
+            if (len == FourLetterCommands.wchsCmd) {
+                dt.dumpWatchesSummary(pw);
+            } else if (len == FourLetterCommands.wchpCmd) {
+                dt.dumpWatches(pw, true);
+            } else {
+                dt.dumpWatches(pw, false);
+            }
+            pw.println();
+        }
+    }
+}