Browse Source

ZOOKEEPER-3085: define exit codes in enum

Define the used exit codes in one enum. contrib projects are excluded, as they can have seperate exit codes (and they do use it differently then in core ZK).
Some exit codes overlap, but refactoring the exit code used is not backward compatible.

Author: Norbert Kalmar <nkalmar@yahoo.com>

Reviewers: lvfangmin@apache.org, breed@apache.org, andor@apache.org

Closes #572 from nkalmar/ZOOKEEPER-3085 and squashes the following commits:

dbc18a62 [Norbert Kalmar] ZOOKEEPER-3085 change comments to javadoc comment in enum code defs
908c171e [Norbert Kalmar] ZOOKEEPER-3085 add missing enum usage and some renames
c49dcef9 [Norbert Kalmar] ZOOKEEPER-3085 use the enum value in ZooKeeperMain.exitCode as well
611aa4ed [Norbert Kalmar] ZOOKEEPER-3085 define exit codes in enum
Norbert Kalmar 6 years ago
parent
commit
44d2736124
23 changed files with 144 additions and 55 deletions
  1. 3 2
      src/java/main/org/apache/zookeeper/Shell.java
  2. 5 3
      src/java/main/org/apache/zookeeper/Version.java
  3. 3 2
      src/java/main/org/apache/zookeeper/ZooKeeperMain.java
  4. 38 3
      src/java/main/org/apache/zookeeper/server/ExitCode.java
  5. 2 2
      src/java/main/org/apache/zookeeper/server/LogFormatter.java
  6. 1 1
      src/java/main/org/apache/zookeeper/server/PurgeTxnLog.java
  7. 1 1
      src/java/main/org/apache/zookeeper/server/SnapshotFormatter.java
  8. 1 1
      src/java/main/org/apache/zookeeper/server/TraceFormatter.java
  9. 1 1
      src/java/main/org/apache/zookeeper/server/ZooKeeperCriticalThread.java
  10. 1 1
      src/java/main/org/apache/zookeeper/server/ZooKeeperServer.java
  11. 6 6
      src/java/main/org/apache/zookeeper/server/ZooKeeperServerMain.java
  12. 7 6
      src/java/main/org/apache/zookeeper/server/persistence/TxnLogToolkit.java
  13. 2 1
      src/java/main/org/apache/zookeeper/server/quorum/FollowerZooKeeperServer.java
  14. 3 4
      src/java/main/org/apache/zookeeper/server/quorum/Learner.java
  15. 2 1
      src/java/main/org/apache/zookeeper/server/quorum/QuorumCnxManager.java
  16. 7 6
      src/java/main/org/apache/zookeeper/server/quorum/QuorumPeerMain.java
  17. 7 5
      src/java/main/org/apache/zookeeper/version/util/VerGen.java
  18. 3 2
      src/java/systest/org/apache/zookeeper/test/system/GenerateLoad.java
  19. 3 2
      src/java/systest/org/apache/zookeeper/test/system/InstanceContainer.java
  20. 2 1
      src/java/test/org/apache/zookeeper/server/quorum/auth/MiniKdc.java
  21. 3 2
      src/java/test/org/apache/zookeeper/test/IntegrityCheck.java
  22. 3 2
      src/java/test/org/apache/zookeeper/test/SledgeHammer.java
  23. 40 0
      zookeeper-docs/src/documentation/content/xdocs/zookeeperAdmin.xml

+ 3 - 2
src/java/main/org/apache/zookeeper/Shell.java

@@ -40,6 +40,7 @@ import java.util.TimerTask;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.zookeeper.common.Time;
+import org.apache.zookeeper.server.ExitCode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -151,7 +152,7 @@ abstract public class Shell {
   protected void run() throws IOException {
     if (lastTime + interval > Time.currentElapsedTime())
       return;
-    exitCode = 0; // reset for next run
+    exitCode = ExitCode.EXECUTION_FINISHED.getValue(); // reset for next run
     runCommand();
   }
 
@@ -224,7 +225,7 @@ abstract public class Shell {
       completed.set(true);
       //the timeout thread handling
       //taken care in finally block
-      if (exitCode != 0) {
+      if (exitCode != ExitCode.EXECUTION_FINISHED.getValue()) {
         throw new ExitCodeException(exitCode, errMsg.toString());
       }
     } catch (InterruptedException ie) {

+ 5 - 3
src/java/main/org/apache/zookeeper/Version.java

@@ -18,6 +18,8 @@
 
 package org.apache.zookeeper;
 
+import org.apache.zookeeper.server.ExitCode;
+
 public class Version implements org.apache.zookeeper.version.Info {
 
     /*
@@ -57,7 +59,7 @@ public class Version implements org.apache.zookeeper.version.Info {
                 .print("Usage:\tjava -cp ... org.apache.zookeeper.Version "
                         + "[--full | --short | --revision],\n\tPrints --full version "
                         + "info if no arg specified.");
-        System.exit(1);
+        System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
     }
 
     /**
@@ -77,7 +79,7 @@ public class Version implements org.apache.zookeeper.version.Info {
         }
         if (args.length == 0 || (args.length == 1 && args[0].equals("--full"))) {
             System.out.println(getFullVersion());
-            System.exit(0);
+            System.exit(ExitCode.EXECUTION_FINISHED.getValue());
         }
         if (args[0].equals("--short"))
             System.out.println(getVersion());
@@ -85,6 +87,6 @@ public class Version implements org.apache.zookeeper.version.Info {
             System.out.println(getVersionRevision());
         else
             printUsage();
-        System.exit(0);
+        System.exit(ExitCode.EXECUTION_FINISHED.getValue());
     }
 }

+ 3 - 2
src/java/main/org/apache/zookeeper/ZooKeeperMain.java

@@ -68,6 +68,7 @@ import org.apache.zookeeper.cli.StatCommand;
 import org.apache.zookeeper.cli.SyncCommand;
 import org.apache.zookeeper.client.ZKClientConfig;
 import org.apache.zookeeper.admin.ZooKeeperAdmin;
+import org.apache.zookeeper.server.ExitCode;
 
 /**
  * The command line client to ZooKeeper.
@@ -84,7 +85,7 @@ public class ZooKeeperMain {
     protected HashMap<Integer,String> history = new HashMap<Integer,String>( );
     protected int commandCount = 0;
     protected boolean printWatches = true;
-    protected int exitCode = 0;
+    protected int exitCode = ExitCode.EXECUTION_FINISHED.getValue();
 
     protected ZooKeeper zk;
     protected String host = "";
@@ -586,7 +587,7 @@ public class ZooKeeperMain {
         boolean watch = false;
         try {
             watch = processZKCmd(co);
-            exitCode = 0;
+            exitCode = ExitCode.EXECUTION_FINISHED.getValue();
         } catch (CliException ex) {
             exitCode = ex.getExitCode();
             System.err.println(ex.getMessage());

+ 38 - 3
src/java/main/org/apache/zookeeper/server/ExitCode.java

@@ -20,8 +20,43 @@ package org.apache.zookeeper.server;
 /**
  * Exit code used to exit server
  */
-public class ExitCode {
+public enum ExitCode {
+
+    /** Execution finished normally */
+    EXECUTION_FINISHED(0),
+
+    /** Unexpected errors like IO Exceptions */
+    UNEXPECTED_ERROR(1),
+
+    /** Invalid arguments during invocations */
+    INVALID_INVOCATION(2),
+
+    /** Cannot access datadir when trying to replicate server */
+    UNABLE_TO_ACCESS_DATADIR(3),
+
+    /** Unable to start admin server at ZooKeeper startup */
+    ERROR_STARTING_ADMIN_SERVER(4),
+
+    /** Severe error during snapshot IO */
+    TXNLOG_ERROR_TAKING_SNAPSHOT(10),
+
+    /** zxid from COMMIT does not match the one from pendingTxns queue */
+    UNMATCHED_TXN_COMMIT(12),
+
+    /** Unexpected packet from leader, or unable to truncate log on Leader.TRUNC */
+    QUORUM_PACKET_ERROR(13),
+
+    /** Unable to bind to the quorum (election) port after multiple retry */
+    UNABLE_TO_BIND_QUORUM_PORT(14);
+
+    private final int value;
+
+    ExitCode(final int newValue) {
+        value = newValue;
+    }
+
+    public int getValue() {
+        return value;
+    }
 
-    /* Represents unexpected error */
-    public final static int UNEXPECTED_ERROR = 1;
 }

+ 2 - 2
src/java/main/org/apache/zookeeper/server/LogFormatter.java

@@ -46,7 +46,7 @@ public class LogFormatter {
     public static void main(String[] args) throws Exception {
         if (args.length != 1) {
             System.err.println("USAGE: LogFormatter log_file");
-            System.exit(2);
+            System.exit(ExitCode.INVALID_INVOCATION.getValue());
         }
         FileInputStream fis = new FileInputStream(args[0]);
         BinaryInputArchive logStream = BinaryInputArchive.getArchive(fis);
@@ -55,7 +55,7 @@ public class LogFormatter {
 
         if (fhdr.getMagic() != FileTxnLog.TXNLOG_MAGIC) {
             System.err.println("Invalid magic number for " + args[0]);
-            System.exit(2);
+            System.exit(ExitCode.INVALID_INVOCATION.getValue());
         }
         System.out.println("ZooKeeper Transactional Log File with dbid "
                 + fhdr.getDbid() + " txnlog format version "

+ 1 - 1
src/java/main/org/apache/zookeeper/server/PurgeTxnLog.java

@@ -231,6 +231,6 @@ public class PurgeTxnLog {
 
     private static void printUsageThenExit() {
         printUsage();
-        System.exit(1);
+        System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
     }
 }

+ 1 - 1
src/java/main/org/apache/zookeeper/server/SnapshotFormatter.java

@@ -47,7 +47,7 @@ public class SnapshotFormatter {
     public static void main(String[] args) throws Exception {
         if (args.length != 1) {
             System.err.println("USAGE: SnapshotFormatter snapshot_file");
-            System.exit(2);
+            System.exit(ExitCode.INVALID_INVOCATION.getValue());
         }
 
         new SnapshotFormatter().run(args[0]);

+ 1 - 1
src/java/main/org/apache/zookeeper/server/TraceFormatter.java

@@ -83,7 +83,7 @@ public class TraceFormatter {
     public static void main(String[] args) throws IOException {
         if (args.length != 1) {
             System.err.println("USAGE: TraceFormatter trace_file");
-            System.exit(2);
+            System.exit(ExitCode.INVALID_INVOCATION.getValue());
         }
         FileChannel fc = new FileInputStream(args[0]).getChannel();
         while (true) {

+ 1 - 1
src/java/main/org/apache/zookeeper/server/ZooKeeperCriticalThread.java

@@ -46,6 +46,6 @@ public class ZooKeeperCriticalThread extends ZooKeeperThread {
     @Override
     protected void handleException(String threadName, Throwable e) {
         LOG.error("Severe unrecoverable error, from thread : {}", threadName, e);
-        listener.notifyStopping(threadName, ExitCode.UNEXPECTED_ERROR);
+        listener.notifyStopping(threadName, ExitCode.UNEXPECTED_ERROR.getValue());
     }
 }

+ 1 - 1
src/java/main/org/apache/zookeeper/server/ZooKeeperServer.java

@@ -317,7 +317,7 @@ public class ZooKeeperServer implements SessionExpirer, ServerStats.Provider {
             LOG.error("Severe unrecoverable error, exiting", e);
             // This is a severe error that we cannot recover from,
             // so we need to exit
-            System.exit(10);
+            System.exit(ExitCode.TXNLOG_ERROR_TAKING_SNAPSHOT.getValue());
         }
     }
 

+ 6 - 6
src/java/main/org/apache/zookeeper/server/ZooKeeperServerMain.java

@@ -66,25 +66,25 @@ public class ZooKeeperServerMain {
             LOG.error("Invalid arguments, exiting abnormally", e);
             LOG.info(USAGE);
             System.err.println(USAGE);
-            System.exit(2);
+            System.exit(ExitCode.INVALID_INVOCATION.getValue());
         } catch (ConfigException e) {
             LOG.error("Invalid config, exiting abnormally", e);
             System.err.println("Invalid config, exiting abnormally");
-            System.exit(2);
+            System.exit(ExitCode.INVALID_INVOCATION.getValue());
         } catch (DatadirException e) {
             LOG.error("Unable to access datadir, exiting abnormally", e);
             System.err.println("Unable to access datadir, exiting abnormally");
-            System.exit(3);
+            System.exit(ExitCode.UNABLE_TO_ACCESS_DATADIR.getValue());
         } catch (AdminServerException e) {
             LOG.error("Unable to start AdminServer, exiting abnormally", e);
             System.err.println("Unable to start AdminServer, exiting abnormally");
-            System.exit(4);
+            System.exit(ExitCode.ERROR_STARTING_ADMIN_SERVER.getValue());
         } catch (Exception e) {
             LOG.error("Unexpected exception, exiting abnormally", e);
-            System.exit(1);
+            System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
         }
         LOG.info("Exiting normally");
-        System.exit(0);
+        System.exit(ExitCode.EXECUTION_FINISHED.getValue());
     }
 
     protected void initializeAndRun(String[] args)

+ 7 - 6
src/java/main/org/apache/zookeeper/server/persistence/TxnLogToolkit.java

@@ -28,6 +28,7 @@ import org.apache.commons.cli.PosixParser;
 import org.apache.jute.BinaryInputArchive;
 import org.apache.jute.BinaryOutputArchive;
 import org.apache.jute.Record;
+import org.apache.zookeeper.server.ExitCode;
 import org.apache.zookeeper.server.TraceFormatter;
 import org.apache.zookeeper.server.util.SerializeUtils;
 import org.apache.zookeeper.txn.TxnHeader;
@@ -114,12 +115,12 @@ public class TxnLogToolkit implements Closeable {
         this.force = force;
         txnLogFile = new File(txnLogFileName);
         if (!txnLogFile.exists() || !txnLogFile.canRead()) {
-            throw new TxnLogToolkitException(1, "File doesn't exist or not readable: %s", txnLogFile);
+            throw new TxnLogToolkitException(ExitCode.UNEXPECTED_ERROR.getValue(), "File doesn't exist or not readable: %s", txnLogFile);
         }
         if (recoveryMode) {
             recoveryLogFile = new File(txnLogFile.toString() + ".fixed");
             if (recoveryLogFile.exists()) {
-                throw new TxnLogToolkitException(1, "Recovery file %s already exists or not writable", recoveryLogFile);
+                throw new TxnLogToolkitException(ExitCode.UNEXPECTED_ERROR.getValue(), "Recovery file %s already exists or not writable", recoveryLogFile);
             }
         }
 
@@ -135,7 +136,7 @@ public class TxnLogToolkit implements Closeable {
         FileHeader fhdr = new FileHeader();
         fhdr.deserialize(logStream, "fileheader");
         if (fhdr.getMagic() != TXNLOG_MAGIC) {
-            throw new TxnLogToolkitException(2, "Invalid magic number for %s", txnLogFile.getName());
+            throw new TxnLogToolkitException(ExitCode.INVALID_INVOCATION.getValue(), "Invalid magic number for %s", txnLogFile.getName());
         }
         System.out.println("ZooKeeper Transactional Log File with dbid "
                 + fhdr.getDbid() + " txnlog format version "
@@ -187,7 +188,7 @@ public class TxnLogToolkit implements Closeable {
                 printTxn(bytes);
             }
             if (logStream.readByte("EOR") != 'B') {
-                throw new TxnLogToolkitException(1, "Last transaction was partial.");
+                throw new TxnLogToolkitException(ExitCode.UNEXPECTED_ERROR.getValue(), "Last transaction was partial.");
             }
             if (recoveryMode) {
                 filePadding.padFile(recoveryFos.getChannel());
@@ -209,7 +210,7 @@ public class TxnLogToolkit implements Closeable {
                 case 'N':
                     return false;
                 case 'A':
-                    throw new TxnLogToolkitException(0, "Recovery aborted.");
+                    throw new TxnLogToolkitException(ExitCode.EXECUTION_FINISHED.getValue(), "Recovery aborted.");
             }
         }
     }
@@ -289,7 +290,7 @@ public class TxnLogToolkit implements Closeable {
             }
             return new TxnLogToolkit(cli.hasOption("recover"), cli.hasOption("verbose"), cli.getArgs()[0], cli.hasOption("yes"));
         } catch (ParseException e) {
-            throw new TxnLogToolkitParseException(options, 1, e.getMessage());
+            throw new TxnLogToolkitParseException(options, ExitCode.UNEXPECTED_ERROR.getValue(), e.getMessage());
         }
     }
 

+ 2 - 1
src/java/main/org/apache/zookeeper/server/quorum/FollowerZooKeeperServer.java

@@ -25,6 +25,7 @@ import java.util.concurrent.LinkedBlockingQueue;
 import org.apache.jute.Record;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.apache.zookeeper.server.ExitCode;
 import org.apache.zookeeper.server.FinalRequestProcessor;
 import org.apache.zookeeper.server.Request;
 import org.apache.zookeeper.server.RequestProcessor;
@@ -105,7 +106,7 @@ public class FollowerZooKeeperServer extends LearnerZooKeeperServer {
             LOG.error("Committing zxid 0x" + Long.toHexString(zxid)
                     + " but next pending txn 0x"
                     + Long.toHexString(firstElementZxid));
-            System.exit(12);
+            System.exit(ExitCode.UNMATCHED_TXN_COMMIT.getValue());
         }
         Request request = pendingTxns.remove();
         commitProcessor.commit(request);

+ 3 - 4
src/java/main/org/apache/zookeeper/server/quorum/Learner.java

@@ -38,6 +38,7 @@ import org.apache.jute.BinaryOutputArchive;
 import org.apache.jute.InputArchive;
 import org.apache.jute.OutputArchive;
 import org.apache.jute.Record;
+import org.apache.zookeeper.server.ExitCode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.zookeeper.ZooDefs.OpCode;
@@ -50,8 +51,6 @@ import org.apache.zookeeper.server.util.SerializeUtils;
 import org.apache.zookeeper.server.util.ZxidUtils;
 import org.apache.zookeeper.txn.SetDataTxn;
 import org.apache.zookeeper.txn.TxnHeader;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * This class is the superclass of two of the three main actors in a ZK
@@ -409,7 +408,7 @@ public class Learner {
                     // not able to truncate the log
                     LOG.error("Not able to truncate the log "
                             + Long.toHexString(qp.getZxid()));
-                    System.exit(13);
+                    System.exit(ExitCode.QUORUM_PACKET_ERROR.getValue());
                 }
                 zk.getZKDatabase().setlastProcessedZxid(qp.getZxid());
 
@@ -417,7 +416,7 @@ public class Learner {
             else {
                 LOG.error("Got unexpected packet from leader: {}, exiting ... ",
                           LearnerHandler.packetToString(qp));
-                System.exit(13);
+                System.exit(ExitCode.QUORUM_PACKET_ERROR.getValue());
 
             }
             zk.getZKDatabase().initConfigInZKDatabase(self.getQuorumVerifier());

+ 2 - 1
src/java/main/org/apache/zookeeper/server/quorum/QuorumCnxManager.java

@@ -47,6 +47,7 @@ import java.util.NoSuchElementException;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 
+import org.apache.zookeeper.server.ExitCode;
 import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
 import org.apache.zookeeper.server.util.ConfigUtils;
 import org.apache.zookeeper.server.ZooKeeperThread;
@@ -921,7 +922,7 @@ public class QuorumCnxManager {
                     // After leaving listener thread, the host cannot join the
                     // quorum anymore, this is a severe error that we cannot
                     // recover from, so we need to exit
-                    System.exit(14);
+                    System.exit(ExitCode.UNABLE_TO_BIND_QUORUM_PORT.getValue());
                 }
             } else if (ss != null) {
                 // Clean up for shutdown.

+ 7 - 6
src/java/main/org/apache/zookeeper/server/quorum/QuorumPeerMain.java

@@ -26,6 +26,7 @@ import org.apache.yetus.audience.InterfaceAudience;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.zookeeper.jmx.ManagedUtil;
+import org.apache.zookeeper.server.ExitCode;
 import org.apache.zookeeper.server.ServerCnxnFactory;
 import org.apache.zookeeper.server.ZKDatabase;
 import org.apache.zookeeper.server.DatadirCleanupManager;
@@ -84,25 +85,25 @@ public class QuorumPeerMain {
             LOG.error("Invalid arguments, exiting abnormally", e);
             LOG.info(USAGE);
             System.err.println(USAGE);
-            System.exit(2);
+            System.exit(ExitCode.INVALID_INVOCATION.getValue());
         } catch (ConfigException e) {
             LOG.error("Invalid config, exiting abnormally", e);
             System.err.println("Invalid config, exiting abnormally");
-            System.exit(2);
+            System.exit(ExitCode.INVALID_INVOCATION.getValue());
         } catch (DatadirException e) {
             LOG.error("Unable to access datadir, exiting abnormally", e);
             System.err.println("Unable to access datadir, exiting abnormally");
-            System.exit(3);
+            System.exit(ExitCode.UNABLE_TO_ACCESS_DATADIR.getValue());
         } catch (AdminServerException e) {
             LOG.error("Unable to start AdminServer, exiting abnormally", e);
             System.err.println("Unable to start AdminServer, exiting abnormally");
-            System.exit(4);
+            System.exit(ExitCode.ERROR_STARTING_ADMIN_SERVER.getValue());
         } catch (Exception e) {
             LOG.error("Unexpected exception, exiting abnormally", e);
-            System.exit(1);
+            System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
         }
         LOG.info("Exiting normally");
-        System.exit(0);
+        System.exit(ExitCode.EXECUTION_FINISHED.getValue());
     }
 
     protected void initializeAndRun(String[] args)

+ 7 - 5
src/java/main/org/apache/zookeeper/version/util/VerGen.java

@@ -18,6 +18,8 @@
 
 package org.apache.zookeeper.version.util;
 
+import org.apache.zookeeper.server.ExitCode;
+
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
@@ -31,7 +33,7 @@ public class VerGen {
     static void printUsage() {
         System.out.print("Usage:\tjava  -cp <classpath> org.apache.zookeeper."
                 + "version.util.VerGen maj.min.micro[-qualifier] rev buildDate");
-        System.exit(1);
+        System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
     }
 
     public static void generateFile(File outputDir, Version version, String rev, String buildDate)
@@ -43,12 +45,12 @@ public class VerGen {
             boolean ret = pkgdir.mkdirs();
             if (!ret) {
                 System.out.println("Cannnot create directory: " + path);
-                System.exit(1);
+                System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
             }
         } else if (!pkgdir.isDirectory()) {
             // not a directory
             System.out.println(path + " is not a directory.");
-            System.exit(1);
+            System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
         }
 
         try (FileWriter w = new FileWriter(new File(pkgdir, TYPE_NAME + ".java"))) {
@@ -92,7 +94,7 @@ public class VerGen {
         } catch (IOException e) {
             System.out.println("Unable to generate version.Info file: "
                     + e.getMessage());
-            System.exit(1);
+            System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
         }
     }
 
@@ -148,7 +150,7 @@ public class VerGen {
             if (version == null) {
                 System.err.println(
                         "Invalid version number format, must be \"x.y.z(-.*)?\"");
-                System.exit(1);
+                System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
             }
             String rev = args[1];
             if (rev == null || rev.trim().isEmpty()) {

+ 3 - 2
src/java/systest/org/apache/zookeeper/test/system/GenerateLoad.java

@@ -40,6 +40,7 @@ import java.util.Map;
 import java.util.Random;
 import java.util.Set;
 
+import org.apache.zookeeper.server.ExitCode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.zookeeper.AsyncCallback.DataCallback;
@@ -684,7 +685,7 @@ public class GenerateLoad {
                 doUsage();
             } catch (IOException e) {
                 e.printStackTrace();
-                System.exit(2);
+                System.exit(ExitCode.INVALID_INVOCATION.getValue());
             }
         } else {
             doUsage();
@@ -713,6 +714,6 @@ public class GenerateLoad {
     private static void doUsage() {
         System.err.println("USAGE: " + GenerateLoad.class.getName()
                 + " [--leaderOnly] [--leaderServes] zookeeper_host:port containerPrefix #ofServers #ofClients requestSize");
-        System.exit(2);
+        System.exit(ExitCode.INVALID_INVOCATION.getValue());
     }
 }

+ 3 - 2
src/java/systest/org/apache/zookeeper/test/system/InstanceContainer.java

@@ -25,6 +25,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.zookeeper.server.ExitCode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.zookeeper.AsyncCallback;
@@ -205,7 +206,7 @@ public class InstanceContainer implements Watcher, AsyncCallback.ChildrenCallbac
     public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException, KeeperException {
         if (args.length != 3) {
             System.err.println("USAGE: " + InstanceContainer.class.getName() + " name zkHostPort znodePrefix");
-            System.exit(2);
+            System.exit(ExitCode.INVALID_INVOCATION.getValue());
         }
         new InstanceContainer(args[0], args[1], args[2]).run();
         while(true) {
@@ -217,7 +218,7 @@ public class InstanceContainer implements Watcher, AsyncCallback.ChildrenCallbac
         if (KeeperState.Expired == event.getState()) {
             // It's all over
             LOG.error("Lost session");
-            System.exit(4);
+            System.exit(ExitCode.ERROR_STARTING_ADMIN_SERVER.getValue());
         }
         if (event.getPath() != null && event.getPath().equals(assignmentsNode)) {
             // children have changed, so read in the new list

+ 2 - 1
src/java/test/org/apache/zookeeper/server/quorum/auth/MiniKdc.java

@@ -23,6 +23,7 @@ import org.apache.kerby.kerberos.kerb.server.KdcConfigKey;
 import org.apache.kerby.kerberos.kerb.server.SimpleKdcServer;
 import org.apache.kerby.util.IOUtil;
 import org.apache.kerby.util.NetworkUtil;
+import org.apache.zookeeper.server.ExitCode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -86,7 +87,7 @@ public class MiniKdc {
         if (args.length < 4) {
             System.out.println("Arguments: <WORKDIR> <MINIKDCPROPERTIES> " +
                     "<KEYTABFILE> [<PRINCIPALS>]+");
-            System.exit(1);
+            System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
         }
         File workDir = new File(args[0]);
         if (!workDir.exists()) {

+ 3 - 2
src/java/test/org/apache/zookeeper/test/IntegrityCheck.java

@@ -35,6 +35,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.zookeeper.server.ExitCode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.zookeeper.CreateMode;
@@ -167,7 +168,7 @@ public class IntegrityCheck implements StatCallback, DataCallback {
             childrenCount=Integer.parseInt(args[2]);
         } catch (NumberFormatException e) {
             e.printStackTrace();
-            System.exit(1);
+            System.exit(ExitCode.UNEXPECTED_ERROR.getValue());
         }
 
         try{
@@ -187,7 +188,7 @@ public class IntegrityCheck implements StatCallback, DataCallback {
             }
         } catch (Exception e) {
             e.printStackTrace();
-            System.exit(2);
+            System.exit(ExitCode.INVALID_INVOCATION.getValue());
         }
     }
 

+ 3 - 2
src/java/test/org/apache/zookeeper/test/SledgeHammer.java

@@ -27,6 +27,7 @@ import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.ZooKeeper;
 import org.apache.zookeeper.ZooDefs.Ids;
 import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.server.ExitCode;
 
 public class SledgeHammer extends Thread{
     ZooKeeper zk;
@@ -100,11 +101,11 @@ public class SledgeHammer extends Thread{
         if (args.length != 3) {
             System.err
                     .println("USAGE: SledgeHammer zookeeper_server reps reads_per_rep");
-            System.exit(3);
+            System.exit(ExitCode.UNABLE_TO_ACCESS_DATADIR.getValue());
         }
         SledgeHammer h = new SledgeHammer(args[0], Integer.parseInt(args[1]),
                 Integer.parseInt(args[2]));
         h.start();
-        System.exit(0);
+        System.exit(ExitCode.EXECUTION_FINISHED.getValue());
     }
 }

+ 40 - 0
zookeeper-docs/src/documentation/content/xdocs/zookeeperAdmin.xml

@@ -387,6 +387,10 @@ server.3=zoo3:2888:3888</programlisting>
           <para><xref linkend="sc_troubleshooting" /></para>
         </listitem>
 
+        <listitem>
+          <para><xref linkend="sc_exitcodes" /></para>
+        </listitem>
+
         <listitem>
           <para><xref linkend="sc_configuration" /></para>
         </listitem>
@@ -674,6 +678,42 @@ server.3=zoo3:2888:3888</programlisting>
 		</variablelist>
     </section>
 
+    <section id="sc_exitcodes">
+      <title>Exit Codes</title>
+      <para> ZooKeeper has several exit codes. From 3.6.0, these codes will be gathered in ExitCode (excluding contrib projects).
+      As the codes themselves were not changed to keep backward compatibility, some codes may overlap.
+      A good example is error code 1 and 2. They can both indicate invalid arguments passed to ZooKeeper or other
+      runtime errors.
+      </para>
+      <itemizedlist>
+        <listitem>
+          <para>1: Unexpected errors like IO Exceptions</para>
+        </listitem>
+        <listitem>
+          <para>2: Invalid arguments during invocations</para>
+        </listitem>
+        <listitem>
+          <para>3: Cannot access datadir when trying to replicate server</para>
+        </listitem>
+        <listitem>
+          <para>4: Unable to start admin server at ZooKeeper startup</para>
+        </listitem>
+        <listitem>
+          <para>10: Severe error during snapshot IO</para>
+        </listitem>
+        <listitem>
+          <para>12: zxid from COMMIT does not match the one from pendingTxns queue</para>
+        </listitem>
+        <listitem>
+          <para>13: Unexpected packet from leader, or unable to truncate log on Leader.TRUNC</para>
+        </listitem>
+        <listitem>
+          <para>14: After listener thread tried to bind to election port 3 times, it will exit -
+            leaving the server unable to join the quorum</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
     <section id="sc_configuration">
       <title>Configuration Parameters</title>