You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by si...@apache.org on 2012/09/07 07:04:34 UTC

svn commit: r1381870 [1/2] - in /zookeeper/bookkeeper/trunk: ./ bookkeeper-server/bin/ bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/ bookkeeper-server/src/main/java/org/apache/bookkeeper/client/ bookkeeper-server/src/main/java/org/apach...

Author: sijie
Date: Fri Sep  7 05:04:33 2012
New Revision: 1381870

URL: http://svn.apache.org/viewvc?rev=1381870&view=rev
Log:
BOOKKEEPER-300: Create Bookie format command (Vinay via sijie)

Modified:
    zookeeper/bookkeeper/trunk/CHANGES.txt
    zookeeper/bookkeeper/trunk/bookkeeper-server/bin/bookkeeper
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieException.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Cookie.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeperAdmin.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/AbstractZkLedgerManager.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/FlatLedgerManagerFactory.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/HierarchicalLedgerManagerFactory.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/LedgerLayout.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/LedgerManagerFactory.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/DataFormats.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/IOUtils.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/ZkUtils.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/proto/DataFormats.proto
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/CookieTest.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/TestLedgerUnderreplicationManager.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/TestReplicationWorker.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/test/TestBackwardCompat.java
    zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/test/ZooKeeperUtil.java

Modified: zookeeper/bookkeeper/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/CHANGES.txt?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/CHANGES.txt (original)
+++ zookeeper/bookkeeper/trunk/CHANGES.txt Fri Sep  7 05:04:33 2012
@@ -122,6 +122,8 @@ Trunk (unreleased changes)
 
         BOOKKEEPER-272: Provide automatic mechanism to know bookie failures (rakeshr via ivank)
 
+        BOOKKEEPER-300: Create Bookie format command (Vinay via sijie)
+
       hedwig-server:
 
         BOOKKEEPER-250: Need a ledger manager like interface to manage metadata operations in Hedwig (sijie via ivank)

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/bin/bookkeeper
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/bin/bookkeeper?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/bin/bookkeeper (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/bin/bookkeeper Fri Sep  7 05:04:33 2012
@@ -80,7 +80,7 @@ where command is one of:
     bookie              Run a bookie server
     localbookie <n>     Run a test ensemble of <n> bookies locally
     upgrade             Upgrade bookie filesystem
-    shell               Run admin shell to read/check bookie files
+    shell               Run shell for admin commands
     help                This help message
 
 or command is the full name of a class with a defined main() method.

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java Fri Sep  7 05:04:33 2012
@@ -46,7 +46,9 @@ import org.apache.bookkeeper.conf.Server
 import org.apache.bookkeeper.jmx.BKMBeanInfo;
 import org.apache.bookkeeper.jmx.BKMBeanRegistry;
 import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.WriteCallback;
+import org.apache.bookkeeper.util.IOUtils;
 import org.apache.bookkeeper.util.MathUtils;
+import org.apache.commons.io.FileUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.zookeeper.KeeperException;
@@ -63,6 +65,8 @@ import org.apache.zookeeper.Watcher.Even
  */
 
 public class Bookie extends Thread {
+    public static final String INSTANCEID = "INSTANCEID";
+
     static Logger LOG = LoggerFactory.getLogger(Bookie.class);
 
     final File journalDirectory;
@@ -274,8 +278,12 @@ public class Bookie extends Thread {
             return;
         }
         try {
+            String instanceId = getInstanceId(zk);
             boolean newEnv = false;
             Cookie masterCookie = Cookie.generateCookie(conf);
+            if (null != instanceId) {
+                masterCookie.setInstanceId(instanceId);
+            }
             try {
                 Cookie zkCookie = Cookie.readFromZooKeeper(zk, conf);
                 masterCookie.verify(zkCookie);
@@ -332,6 +340,19 @@ public class Bookie extends Thread {
         }
     }
 
+    private String getInstanceId(ZooKeeper zk) throws KeeperException,
+            InterruptedException {
+        String instanceId = null;
+        try {
+            byte[] data = zk.getData(conf.getZkLedgersRootPath() + "/"
+                    + INSTANCEID, false, null);
+            instanceId = new String(data);
+        } catch (KeeperException.NoNodeException e) {
+            LOG.warn("INSTANCEID not exists in zookeeper. Not considering it for data verification");
+        }
+        return instanceId;
+    }
+
     public static File getCurrentDirectory(File dir) {
         return new File(dir, CURRENT_DIR);
     }
@@ -793,6 +814,80 @@ public class Bookie extends Thread {
     }
 
     /**
+     * Format the bookie server data
+     * 
+     * @param conf
+     *            ServerConfiguration
+     * @param isInteractive
+     *            Whether format should ask prompt for confirmation if old data
+     *            exists or not.
+     * @param force
+     *            If non interactive and force is true, then old data will be
+     *            removed without confirm prompt.
+     * @return Returns true if the format is success else returns false
+     */
+    public static boolean format(ServerConfiguration conf,
+            boolean isInteractive, boolean force) {
+        File journalDir = conf.getJournalDir();
+        if (journalDir.exists() && journalDir.isDirectory()
+                && journalDir.list().length != 0) {
+            try {
+                boolean confirm = false;
+                if (!isInteractive) {
+                    // If non interactive and force is set, then delete old
+                    // data.
+                    if (force) {
+                        confirm = true;
+                    } else {
+                        confirm = false;
+                    }
+                } else {
+                    confirm = IOUtils
+                            .confirmPrompt("Are you sure to format Bookie data..?");
+                }
+
+                if (!confirm) {
+                    LOG.error("Bookie format aborted!!");
+                    return false;
+                }
+            } catch (IOException e) {
+                LOG.error("Error during bookie format", e);
+                return false;
+            }
+        }
+        if (!cleanDir(journalDir)) {
+            LOG.error("Formatting journal directory failed");
+            return false;
+        }
+
+        File[] ledgerDirs = conf.getLedgerDirs();
+        for (File dir : ledgerDirs) {
+            if (!cleanDir(dir)) {
+                LOG.error("Formatting ledger directory " + dir + " failed");
+                return false;
+            }
+        }
+        LOG.info("Bookie format completed successfully");
+        return true;
+    }
+
+    private static boolean cleanDir(File dir) {
+        if (dir.exists()) {
+            for (File child : dir.listFiles()) {
+                boolean delete = FileUtils.deleteQuietly(child);
+                if (!delete) {
+                    LOG.error("Not able to delete " + child);
+                    return false;
+                }
+            }
+        } else if (!dir.mkdirs()) {
+            LOG.error("Not able to create the directory " + dir);
+            return false;
+        }
+        return true;
+    }
+
+    /**
      * @param args
      * @throws IOException
      * @throws InterruptedException

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieException.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieException.java?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieException.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieException.java Fri Sep  7 05:04:33 2012
@@ -126,7 +126,11 @@ public abstract class BookieException ex
 
     public static class InvalidCookieException extends BookieException {
         public InvalidCookieException() {
-            this(null);
+            this("");
+        }
+
+        public InvalidCookieException(String reason) {
+            super(Code.InvalidCookieException, reason);
         }
 
         public InvalidCookieException(Throwable cause) {

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java Fri Sep  7 05:04:33 2012
@@ -21,6 +21,7 @@ package org.apache.bookkeeper.bookie;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.net.InetSocketAddress;
 import java.nio.ByteBuffer;
 import java.util.Formatter;
 import java.util.HashMap;
@@ -29,6 +30,9 @@ import java.util.Map;
 import org.apache.bookkeeper.bookie.EntryLogger.EntryLogScanner;
 import org.apache.bookkeeper.bookie.Journal.JournalScanner;
 import org.apache.bookkeeper.bookie.Journal.LastLogMark;
+import org.apache.bookkeeper.client.BKException;
+import org.apache.bookkeeper.client.BookKeeperAdmin;
+import org.apache.bookkeeper.conf.ClientConfiguration;
 import org.apache.bookkeeper.conf.ServerConfiguration;
 import org.apache.bookkeeper.util.EntryFormatter;
 import org.apache.bookkeeper.util.Tool;
@@ -36,6 +40,7 @@ import org.apache.commons.configuration.
 import org.apache.commons.configuration.CompositeConfiguration;
 import org.apache.commons.configuration.PropertiesConfiguration;
 import org.apache.commons.cli.BasicParser;
+import org.apache.commons.cli.MissingArgumentException;
 import org.apache.commons.cli.Options;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.HelpFormatter;
@@ -45,7 +50,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Bookie Shell to read/check bookie files.
+ * Bookie Shell is to provide utilities for users to administer a bookkeeper cluster.
  */
 public class BookieShell implements Tool {
 
@@ -53,6 +58,9 @@ public class BookieShell implements Tool
 
     static final String ENTRY_FORMATTER_CLASS = "entryFormatterClass";
 
+    static final String CMD_METAFORMAT = "metaformat";
+    static final String CMD_BOOKIEFORMAT = "bookieformat";
+    static final String CMD_RECOVER = "recover";
     static final String CMD_LEDGER = "ledger";
     static final String CMD_READLOG = "readlog";
     static final String CMD_READJOURNAL = "readjournal";
@@ -109,6 +117,160 @@ public class BookieShell implements Tool
     }
 
     /**
+     * Format the bookkeeper metadata present in zookeeper
+     */
+    class MetaFormatCmd extends MyCommand {
+        Options opts = new Options();
+
+        MetaFormatCmd() {
+            super(CMD_METAFORMAT);
+            opts.addOption("n", "nonInteractive", false,
+                    "Whether to confirm if old data exists..?");
+            opts.addOption("f", "force", false,
+                    "If [nonInteractive] is specified, then whether"
+                            + " to force delete the old data without prompt.");
+        }
+
+        @Override
+        Options getOptions() {
+            return opts;
+        }
+
+        @Override
+        String getDescription() {
+            return "Format bookkeeper metadata in zookeeper";
+        }
+
+        @Override
+        String getUsage() {
+            return "metaformat [-nonInteractive] [-force]";
+        }
+
+        @Override
+        int runCmd(CommandLine cmdLine) throws Exception {
+            boolean interactive = (!cmdLine.hasOption("n"));
+            boolean force = cmdLine.hasOption("f");
+
+            ClientConfiguration adminConf = new ClientConfiguration(bkConf);
+            boolean result = BookKeeperAdmin.format(adminConf, interactive,
+                    force);
+            return (result) ? 0 : 1;
+        }
+    }
+
+    /**
+     * Formats the local data present in current bookie server
+     */
+    class BookieFormatCmd extends MyCommand {
+        Options opts = new Options();
+
+        public BookieFormatCmd() {
+            super(CMD_BOOKIEFORMAT);
+            opts.addOption("n", "nonInteractive", false,
+                    "Whether to confirm if old data exists..?");
+            opts.addOption("f", "force", false,
+                    "If [nonInteractive] is specified, then whether"
+                            + " to force delete the old data without prompt..?");
+        }
+
+        @Override
+        Options getOptions() {
+            return opts;
+        }
+
+        @Override
+        String getDescription() {
+            return "Format the current server contents";
+        }
+
+        @Override
+        String getUsage() {
+            return "bookieformat [-nonInteractive] [-force]";
+        }
+
+        @Override
+        int runCmd(CommandLine cmdLine) throws Exception {
+            boolean interactive = (!cmdLine.hasOption("n"));
+            boolean force = cmdLine.hasOption("f");
+
+            ServerConfiguration conf = new ServerConfiguration(bkConf);
+            boolean result = Bookie.format(conf, interactive, force);
+            return (result) ? 0 : 1;
+        }
+    }
+
+    /**
+     * Recover command for ledger data recovery for failed bookie
+     */
+    class RecoverCmd extends MyCommand {
+        Options opts = new Options();
+
+        public RecoverCmd() {
+            super(CMD_RECOVER);
+        }
+
+        @Override
+        Options getOptions() {
+            return opts;
+        }
+
+        @Override
+        String getDescription() {
+            return "Recover the ledger data for failed bookie";
+        }
+
+        @Override
+        String getUsage() {
+            return "recover <bookieSrc> [bookieDest]";
+        }
+
+        @Override
+        int runCmd(CommandLine cmdLine) throws Exception {
+            String[] args = cmdLine.getArgs();
+            if (args.length < 1) {
+                throw new MissingArgumentException(
+                        "'bookieSrc' argument required");
+            }
+
+            ClientConfiguration adminConf = new ClientConfiguration(bkConf);
+            BookKeeperAdmin admin = new BookKeeperAdmin(adminConf);
+            try {
+                return bkRecovery(admin, args);
+            } finally {
+                if (null != admin) {
+                    admin.close();
+                }
+            }
+        }
+
+        private int bkRecovery(BookKeeperAdmin bkAdmin, String[] args)
+                throws InterruptedException, BKException {
+            final String bookieSrcString[] = args[0].split(":");
+            if (bookieSrcString.length != 2) {
+                System.err.println("BookieSrc inputted has invalid format"
+                        + "(host:port expected): " + args[0]);
+                return -1;
+            }
+            final InetSocketAddress bookieSrc = new InetSocketAddress(
+                    bookieSrcString[0], Integer.parseInt(bookieSrcString[1]));
+            InetSocketAddress bookieDest = null;
+            if (args.length >= 2) {
+                final String bookieDestString[] = args[1].split(":");
+                if (bookieDestString.length < 2) {
+                    System.err.println("BookieDest inputted has invalid format"
+                            + "(host:port expected): " + args[1]);
+                    return -1;
+                }
+                bookieDest = new InetSocketAddress(bookieDestString[0],
+                        Integer.parseInt(bookieDestString[1]));
+            }
+
+            bkAdmin.recoverBookieData(bookieSrc, bookieDest);
+            return 0;
+        }
+    }
+
+    /**
      * Ledger Command Handles ledger related operations
      */
     class LedgerCmd extends MyCommand {
@@ -334,6 +496,9 @@ public class BookieShell implements Tool
     final Map<String, Command> commands;
     {
         commands = new HashMap<String, Command>();
+        commands.put(CMD_METAFORMAT, new MetaFormatCmd());
+        commands.put(CMD_BOOKIEFORMAT, new BookieFormatCmd());
+        commands.put(CMD_RECOVER, new RecoverCmd());
         commands.put(CMD_LEDGER, new LedgerCmd());
         commands.put(CMD_READLOG, new ReadLogCmd());
         commands.put(CMD_READJOURNAL, new ReadJournalCmd());
@@ -355,6 +520,9 @@ public class BookieShell implements Tool
     private static void printShellUsage() {
         System.err.println("Usage: BookieShell [-conf configuration] <command>");
         System.err.println();
+        System.err.println("       metaformat   [-nonInteractive] [-force]");
+        System.err.println("       bookieformat [-nonInteractive] [-force]");
+        System.err.println("       recover      <bookieSrc> [bookieDest]");
         System.err.println("       ledger      [-meta] <ledger_id>");
         System.err.println("       readlog     [-msg] <entry_log_id|entry_log_file_name>");
         System.err.println("       readjournal [-msg] <journal_id|journal_file_name>");

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Cookie.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Cookie.java?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Cookie.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Cookie.java Fri Sep  7 05:04:33 2012
@@ -20,18 +20,19 @@
  */
 package org.apache.bookkeeper.bookie;
 
+import java.io.BufferedReader;
+import java.io.EOFException;
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.FileReader;
 import java.io.OutputStreamWriter;
 import java.io.BufferedWriter;
 import java.io.IOException;
-import java.util.Scanner;
+import java.io.StringReader;
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 
-import java.nio.ByteBuffer;
-
 import org.apache.zookeeper.ZooKeeper;
 import org.apache.zookeeper.data.Stat;
 import org.apache.zookeeper.KeeperException;
@@ -39,10 +40,13 @@ import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.ZooDefs.Ids;
 
 import org.apache.bookkeeper.conf.ServerConfiguration;
+import org.apache.bookkeeper.proto.DataFormats.CookieFormat;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.protobuf.TextFormat;
+
 /**
  * When a bookie starts for the first time it generates  a cookie, and stores
  * the cookie in zookeeper as well as in the each of the local filesystem
@@ -59,7 +63,7 @@ import org.slf4j.LoggerFactory;
 class Cookie {
     static Logger LOG = LoggerFactory.getLogger(Cookie.class);
 
-    static final int CURRENT_COOKIE_LAYOUT_VERSION = 3;
+    static final int CURRENT_COOKIE_LAYOUT_VERSION = 4;
     static final String COOKIE_NODE = "cookies";
     static final String VERSION_FILENAME = "VERSION";
     private int layoutVersion = 0;
@@ -67,22 +71,49 @@ class Cookie {
     private String journalDir = null;
     private String ledgerDirs = null;
     private int znodeVersion = -1;
+    private String instanceId = null;
 
     private Cookie() {
     }
 
-    public void verify(Cookie c)
-            throws BookieException.InvalidCookieException {
-        if (!(c.layoutVersion == layoutVersion
-              && c.layoutVersion >= 3
-              && c.bookieHost.equals(bookieHost)
-              && c.journalDir.equals(journalDir)
-              && c.ledgerDirs.equals(ledgerDirs))) {
-            throw new BookieException.InvalidCookieException();
+    public void verify(Cookie c) throws BookieException.InvalidCookieException {
+        String errMsg;
+        if (c.layoutVersion < 3 && c.layoutVersion != layoutVersion) {
+            errMsg = "Cookie is of too old version " + c.layoutVersion;
+            LOG.error(errMsg);
+            throw new BookieException.InvalidCookieException(errMsg);
+        } else if (!(c.layoutVersion >= 3 && c.bookieHost.equals(bookieHost)
+                && c.journalDir.equals(journalDir) && c.ledgerDirs
+                    .equals(ledgerDirs))) {
+            errMsg = "Cookie [" + this + "] is not matching with [" + c + "]";
+            throw new BookieException.InvalidCookieException(errMsg);
+        } else if ((instanceId == null && c.instanceId != null)
+                || (instanceId != null && !instanceId.equals(c.instanceId))) {
+            // instanceId should be same in both cookies
+            errMsg = "instanceId " + instanceId
+                    + " is not matching with " + c.instanceId;
+            throw new BookieException.InvalidCookieException(errMsg);
         }
     }
 
     public String toString() {
+        if (layoutVersion <= 3) {
+            return toStringVersion3();
+        }
+        CookieFormat.Builder builder = CookieFormat.newBuilder();
+        builder.setBookieHost(bookieHost);
+        builder.setJournalDir(journalDir);
+        builder.setLedgerDirs(ledgerDirs);
+        if (null != instanceId) {
+            builder.setInstanceId(instanceId);
+        }
+        StringBuilder b = new StringBuilder();
+        b.append(CURRENT_COOKIE_LAYOUT_VERSION).append("\n");
+        b.append(TextFormat.printToString(builder.build()));
+        return b.toString();
+    }
+
+    private String toStringVersion3() {
         StringBuilder b = new StringBuilder();
         b.append(CURRENT_COOKIE_LAYOUT_VERSION).append("\n")
             .append(bookieHost).append("\n")
@@ -91,19 +122,34 @@ class Cookie {
         return b.toString();
     }
 
-    private static Cookie parse(Scanner s) throws IOException {
-        Cookie c  = new Cookie();
-        if (!s.hasNextInt()) {
-            throw new IOException("Invalid string, cannot parse cookie.");
-        }
-        c.layoutVersion = s.nextInt();
-        if (c.layoutVersion >= 3) {
-            s.nextLine();
-            c.bookieHost = s.nextLine();
-            c.journalDir = s.nextLine();
-            c.ledgerDirs = s.nextLine();
+    private static Cookie parse(BufferedReader reader) throws IOException {
+        Cookie c = new Cookie();
+        String line = reader.readLine();
+        if (null == line) {
+            throw new EOFException("Exception in parsing cookie");
+        }
+        try {
+            c.layoutVersion = Integer.parseInt(line.trim());
+        } catch (NumberFormatException e) {
+            throw new IOException("Invalid string '" + line.trim()
+                    + "', cannot parse cookie.");
+        }
+        if (c.layoutVersion == 3) {
+            c.bookieHost = reader.readLine();
+            c.journalDir = reader.readLine();
+            c.ledgerDirs = reader.readLine();
+        } else if (c.layoutVersion >= 4) {
+            CookieFormat.Builder builder = CookieFormat.newBuilder();
+            TextFormat.merge(reader, builder);
+            CookieFormat data = builder.build();
+            c.bookieHost = data.getBookieHost();
+            c.journalDir = data.getJournalDir();
+            c.ledgerDirs = data.getLedgerDirs();
+            // Since InstanceId is optional
+            if (null != data.getInstanceId() && !data.getInstanceId().isEmpty()) {
+                c.instanceId = data.getInstanceId();
+            }
         }
-        s.close();
         return c;
     }
 
@@ -178,14 +224,29 @@ class Cookie {
 
         Stat stat = zk.exists(zkPath, false);
         byte[] data = zk.getData(zkPath, false, stat);
-        Cookie c = parse(new Scanner(new String(data)));
-        c.znodeVersion = stat.getVersion();
-        return c;
+        BufferedReader reader = new BufferedReader(new StringReader(new String(
+                data)));
+        try {
+            Cookie c = parse(reader);
+            c.znodeVersion = stat.getVersion();
+            return c;
+        } finally {
+            reader.close();
+        }
     }
 
     static Cookie readFromDirectory(File directory) throws IOException {
         File versionFile = new File(directory, VERSION_FILENAME);
-        return parse(new Scanner(versionFile));
+        BufferedReader reader = new BufferedReader(new FileReader(versionFile));
+        try {
+            return parse(reader);
+        } finally {
+            reader.close();
+        }
+    }
+
+    public void setInstanceId(String instanceId) {
+        this.instanceId = instanceId;
     }
 
     private static String getZkPath(ServerConfiguration conf)

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeperAdmin.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeperAdmin.java?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeperAdmin.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeperAdmin.java Fri Sep  7 05:04:33 2012
@@ -28,9 +28,9 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
+import java.util.UUID;
 
+import org.apache.bookkeeper.bookie.Bookie;
 import org.apache.bookkeeper.client.AsyncCallback.OpenCallback;
 import org.apache.bookkeeper.client.AsyncCallback.RecoverCallback;
 import org.apache.bookkeeper.client.BookKeeper.SyncOpenCallback;
@@ -38,10 +38,13 @@ import org.apache.bookkeeper.client.Ledg
 import org.apache.bookkeeper.conf.ClientConfiguration;
 import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.MultiCallback;
 import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.Processor;
+import org.apache.bookkeeper.util.IOUtils;
+import org.apache.bookkeeper.util.ZkUtils;
 import org.apache.zookeeper.AsyncCallback;
+import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.KeeperException;
-import org.apache.zookeeper.WatchedEvent;
-import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZKUtil;
+import org.apache.zookeeper.ZooDefs.Ids;
 import org.apache.zookeeper.ZooKeeper;
 import org.apache.zookeeper.KeeperException.Code;
 import org.slf4j.Logger;
@@ -115,20 +118,8 @@ public class BookKeeperAdmin {
      */
     public BookKeeperAdmin(ClientConfiguration conf) throws IOException, InterruptedException, KeeperException {
         // Create the ZooKeeper client instance
-        final CountDownLatch latch = new CountDownLatch(1);
-        zk = new ZooKeeper(conf.getZkServers(), conf.getZkTimeout(), new Watcher() {
-            @Override
-            public void process(WatchedEvent event) {
-                latch.countDown();
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("Process: " + event.getType() + " " + event.getPath());
-                }
-            }
-        });
-        if (!latch.await(conf.getZkTimeout(), TimeUnit.MILLISECONDS)
-            || !zk.getState().isConnected()) {
-            throw KeeperException.create(KeeperException.Code.CONNECTIONLOSS);
-        }
+        zk = ZkUtils.createConnectedZookeeperClient(conf.getZkServers(),
+                conf.getZkTimeout());
         // Create the bookie path
         bookiesPath = conf.getZkAvailableBookiesPath();
         // Create the BookKeeper client instance
@@ -690,4 +681,96 @@ public class BookKeeperAdmin {
             sync.dec();
         }
     }
+
+    /**
+     * Format the BookKeeper metadata in zookeeper
+     * 
+     * @param isInteractive
+     *            Whether format should ask prompt for confirmation if old data
+     *            exists or not.
+     * @param force
+     *            If non interactive and force is true, then old data will be
+     *            removed without prompt.
+     * @return Returns true if format succeeds else false.
+     */
+    public static boolean format(ClientConfiguration conf,
+            boolean isInteractive, boolean force) throws Exception {
+
+        ZooKeeper zkc = ZkUtils.createConnectedZookeeperClient(conf.getZkServers(),
+                conf.getZkTimeout());
+        BookKeeper bkc = null;
+        try {
+            boolean ledgerRootExists = null != zkc.exists(
+                    conf.getZkLedgersRootPath(), false);
+            boolean availableNodeExists = null != zkc.exists(
+                    conf.getZkAvailableBookiesPath(), false);
+
+            // Create ledgers root node if not exists
+            if (!ledgerRootExists) {
+                zkc.create(conf.getZkLedgersRootPath(), "".getBytes(),
+                        Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+            }
+            // create available bookies node if not exists
+            if (!availableNodeExists) {
+                zkc.create(conf.getZkAvailableBookiesPath(), "".getBytes(),
+                        Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+            }
+
+            // If old data was there then confirm with admin.
+            if (ledgerRootExists) {
+                boolean confirm = false;
+                if (!isInteractive) {
+                    // If non interactive and force is set, then delete old
+                    // data.
+                    if (force) {
+                        confirm = true;
+                    } else {
+                        confirm = false;
+                    }
+                } else {
+                    // Confirm with the admin.
+                    confirm = IOUtils
+                            .confirmPrompt("Are you sure to format bookkeeper metadata ?");
+                }
+                if (!confirm) {
+                    LOG.error("BookKeeper metadata Format aborted!!");
+                    return false;
+                }
+            }
+            bkc = new BookKeeper(conf, zkc);
+            // Format all ledger metadata layout
+            bkc.ledgerManagerFactory.format(conf, zkc);
+
+            // Clear the cookies
+            try {
+                ZKUtil.deleteRecursive(zkc, conf.getZkLedgersRootPath()
+                        + "/cookies");
+            } catch (KeeperException.NoNodeException e) {
+                LOG.debug("cookies node not exists in zookeeper to delete");
+            }
+
+            // Clear the INSTANCEID
+            try {
+                zkc.delete(conf.getZkLedgersRootPath() + "/" + Bookie.INSTANCEID, -1);
+            } catch (KeeperException.NoNodeException e) {
+                LOG.debug("INSTANCEID not exists in zookeeper to delete");
+            }
+
+            // create INSTANCEID
+            String instanceId = UUID.randomUUID().toString();
+            zkc.create(conf.getZkLedgersRootPath() + "/" + Bookie.INSTANCEID,
+                    instanceId.getBytes(), Ids.OPEN_ACL_UNSAFE,
+                    CreateMode.PERSISTENT);
+
+            LOG.info("Successfully formatted BookKeeper metadata");
+        } finally {
+            if (null != bkc) {
+                bkc.close();
+            }
+            if (null != zkc) {
+                zkc.close();
+            }
+        }
+        return true;
+    }
 }

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/AbstractZkLedgerManager.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/AbstractZkLedgerManager.java?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/AbstractZkLedgerManager.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/AbstractZkLedgerManager.java Fri Sep  7 05:04:33 2012
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.Set;
 import java.util.Map;
 
+import org.apache.bookkeeper.bookie.Bookie;
 import org.apache.bookkeeper.conf.AbstractConfiguration;
 import org.apache.bookkeeper.client.LedgerMetadata;
 import org.apache.bookkeeper.client.BKException;
@@ -358,6 +359,7 @@ abstract class AbstractZkLedgerManager i
         if (AVAILABLE_NODE.equals(znode)
                 || COOKIES_NODE.equals(znode)
                 || LedgerLayout.LAYOUT_ZNODE.equals(znode)
+                || Bookie.INSTANCEID.equals(znode)
                 || ZkLedgerUnderreplicationManager.UNDER_REPLICATION_NODE
                         .equals(znode)) {
             return true;

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/FlatLedgerManagerFactory.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/FlatLedgerManagerFactory.java?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/FlatLedgerManagerFactory.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/FlatLedgerManagerFactory.java Fri Sep  7 05:04:33 2012
@@ -19,8 +19,10 @@ package org.apache.bookkeeper.meta;
  */
 
 import java.io.IOException;
+import java.util.List;
 
 import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.ZKUtil;
 import org.apache.bookkeeper.replication.ReplicationException;
 import org.apache.bookkeeper.conf.AbstractConfiguration;
 import org.apache.zookeeper.ZooKeeper;
@@ -76,4 +78,20 @@ class FlatLedgerManagerFactory extends L
             throws KeeperException, InterruptedException, ReplicationException.CompatibilityException {
         return new ZkLedgerUnderreplicationManager(conf, zk);
     }
+
+    @Override
+    public void format(AbstractConfiguration conf, ZooKeeper zk)
+            throws InterruptedException, KeeperException, IOException {
+        FlatLedgerManager ledgerManager = (FlatLedgerManager) newLedgerManager();
+        String ledgersRootPath = conf.getZkLedgersRootPath();
+        List<String> children = zk.getChildren(ledgersRootPath, false);
+        for (String child : children) {
+            if (ledgerManager.isSpecialZnode(child)) {
+                continue;
+            }
+            ZKUtil.deleteRecursive(zk, ledgersRootPath + "/" + child);
+        }
+        // Delete and recreate the LAYOUT information.
+        super.format(conf, zk);
+    }
 }

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/HierarchicalLedgerManagerFactory.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/HierarchicalLedgerManagerFactory.java?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/HierarchicalLedgerManagerFactory.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/HierarchicalLedgerManagerFactory.java Fri Sep  7 05:04:33 2012
@@ -19,8 +19,10 @@ package org.apache.bookkeeper.meta;
  */
 
 import java.io.IOException;
+import java.util.List;
 
 import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.ZKUtil;
 import org.apache.bookkeeper.replication.ReplicationException;
 import org.apache.bookkeeper.conf.AbstractConfiguration;
 import org.apache.zookeeper.ZooKeeper;
@@ -76,4 +78,21 @@ class HierarchicalLedgerManagerFactory e
             throws KeeperException, InterruptedException, ReplicationException.CompatibilityException{
         return new ZkLedgerUnderreplicationManager(conf, zk);
     }
+
+    @Override
+    public void format(AbstractConfiguration conf, ZooKeeper zk)
+            throws InterruptedException, KeeperException, IOException {
+        HierarchicalLedgerManager ledgerManager = (HierarchicalLedgerManager) newLedgerManager();
+        String ledgersRootPath = conf.getZkLedgersRootPath();
+        List<String> children = zk.getChildren(ledgersRootPath, false);
+        for (String child : children) {
+            if (!HierarchicalLedgerManager.IDGEN_ZNODE.equals(child)
+                    && ledgerManager.isSpecialZnode(child)) {
+                continue;
+            }
+            ZKUtil.deleteRecursive(zk, ledgersRootPath + "/" + child);
+        }
+        // Delete and recreate the LAYOUT information.
+        super.format(conf, zk);
+    }
 }

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/LedgerLayout.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/LedgerLayout.java?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/LedgerLayout.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/LedgerLayout.java Fri Sep  7 05:04:33 2012
@@ -147,6 +147,15 @@ class LedgerLayout {
     }
 
     /**
+     * Delete the LAYOUT from zookeeper
+     */
+    public void delete(final ZooKeeper zk, String ledgersRoot)
+            throws KeeperException, InterruptedException {
+        String ledgersLayout = ledgersRoot + "/" + LAYOUT_ZNODE;
+        zk.delete(ledgersLayout, -1);
+    }
+
+    /**
      * Generates a byte array based on the LedgerLayout object.
      *
      * @return byte[]

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/LedgerManagerFactory.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/LedgerManagerFactory.java?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/LedgerManagerFactory.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/meta/LedgerManagerFactory.java Fri Sep  7 05:04:33 2012
@@ -26,6 +26,7 @@ import org.slf4j.LoggerFactory;
 import org.apache.bookkeeper.replication.ReplicationException;
 import org.apache.bookkeeper.conf.AbstractConfiguration;
 import org.apache.bookkeeper.util.ReflectionUtils;
+import org.apache.commons.configuration.ConfigurationException;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.ZooKeeper;
 
@@ -130,40 +131,9 @@ public abstract class LedgerManagerFacto
         // compatible with the existing layout
         LedgerLayout layout = LedgerLayout.readLayout(zk, ledgerRootPath);
         if (layout == null) { // no existing layout
-            // use default ledger manager factory if no one provided
-            if (factoryClass == null) {
-                // for backward compatibility, check manager type
-                String lmType = conf.getLedgerManagerType();
-                if (lmType == null) {
-                    factoryClass = FlatLedgerManagerFactory.class;
-                } else {
-                    if (FlatLedgerManagerFactory.NAME.equals(lmType)) {
-                        factoryClass = FlatLedgerManagerFactory.class;
-                    } else if (HierarchicalLedgerManagerFactory.NAME.equals(lmType)) {
-                        factoryClass = HierarchicalLedgerManagerFactory.class;
-                    } else {
-                        throw new IOException("Unknown ledger manager type: " + lmType);
-                    }
-                }
-            }
-
-            try {
-                lmFactory = ReflectionUtils.newInstance(factoryClass);
-            } catch (Throwable t) {
-                throw new IOException("Fail to instantiate ledger manager factory class : " + factoryClass, t);
-            }
-            layout = new LedgerLayout(factoryClass.getName(), lmFactory.getCurrentVersion());
-            try {
-                layout.store(zk, ledgerRootPath);
-            } catch (KeeperException.NodeExistsException nee) {
-                LedgerLayout layout2 = LedgerLayout.readLayout(zk, ledgerRootPath);
-                if (!layout2.equals(layout)) {
-                    throw new IOException("Contention writing to layout to zookeeper, "
-                            + " other layout " + layout2 + " is incompatible with our "
-                            + "layout " + layout);
-                }
-            }
-            return lmFactory.initialize(conf, zk, lmFactory.getCurrentVersion());
+            lmFactory = createNewLMFactory(conf, zk, factoryClass);
+            return lmFactory
+                    .initialize(conf, zk, lmFactory.getCurrentVersion());
         }
         LOG.debug("read ledger layout {}", layout);
 
@@ -208,12 +178,81 @@ public abstract class LedgerManagerFacto
             }
         }
         // instantiate a factory
+        lmFactory = ReflectionUtils.newInstance(factoryClass);
+        return lmFactory.initialize(conf, zk, layout.getManagerVersion());
+    }
+
+    /**
+     * Creates the new layout and stores in zookeeper and returns the
+     * LedgerManagerFactory instance.
+     */
+    private static LedgerManagerFactory createNewLMFactory(
+            final AbstractConfiguration conf, final ZooKeeper zk,
+            Class<? extends LedgerManagerFactory> factoryClass)
+            throws IOException, KeeperException, InterruptedException {
+
+        String ledgerRootPath = conf.getZkLedgersRootPath();
+        LedgerManagerFactory lmFactory;
+        LedgerLayout layout;
+        // use default ledger manager factory if no one provided
+        if (factoryClass == null) {
+            // for backward compatibility, check manager type
+            String lmType = conf.getLedgerManagerType();
+            if (lmType == null) {
+                factoryClass = FlatLedgerManagerFactory.class;
+            } else {
+                if (FlatLedgerManagerFactory.NAME.equals(lmType)) {
+                    factoryClass = FlatLedgerManagerFactory.class;
+                } else if (HierarchicalLedgerManagerFactory.NAME.equals(lmType)) {
+                    factoryClass = HierarchicalLedgerManagerFactory.class;
+                } else {
+                    throw new IOException("Unknown ledger manager type: "
+                            + lmType);
+                }
+            }
+        }
+
+        lmFactory = ReflectionUtils.newInstance(factoryClass);
+
+        layout = new LedgerLayout(factoryClass.getName(),
+                lmFactory.getCurrentVersion());
         try {
-            lmFactory = ReflectionUtils.newInstance(factoryClass);
-        } catch (Throwable t) {
-            throw new IOException("Fail to instantiate ledger manager factory class : " + factoryClass, t);
+            layout.store(zk, ledgerRootPath);
+        } catch (KeeperException.NodeExistsException nee) {
+            LedgerLayout layout2 = LedgerLayout.readLayout(zk, ledgerRootPath);
+            if (!layout2.equals(layout)) {
+                throw new IOException(
+                        "Contention writing to layout to zookeeper, "
+                                + " other layout " + layout2
+                                + " is incompatible with our " + "layout "
+                                + layout);
+            }
         }
-        return lmFactory.initialize(conf, zk, layout.getManagerVersion());
+        return lmFactory;
     }
 
+    /**
+     * Format the ledger metadata for LedgerManager
+     * 
+     * @param conf
+     *            Configuration instance
+     * @param zk
+     *            Zookeeper instance
+     */
+    public void format(final AbstractConfiguration conf, final ZooKeeper zk)
+            throws InterruptedException, KeeperException, IOException {
+        
+        Class<? extends LedgerManagerFactory> factoryClass;
+        try {
+            factoryClass = conf.getLedgerManagerFactoryClass();
+        } catch (ConfigurationException e) {
+            throw new IOException("Failed to get ledger manager factory class from configuration : ", e);
+        }
+       
+        LedgerLayout layout = LedgerLayout.readLayout(zk,
+                conf.getZkLedgersRootPath());
+        layout.delete(zk, conf.getZkLedgersRootPath());
+        // Create new layout information again.        
+        createNewLMFactory(conf, zk, factoryClass);
+    }
 }

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/DataFormats.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/DataFormats.java?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/DataFormats.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/DataFormats.java Fri Sep  7 05:04:33 2012
@@ -2461,6 +2461,687 @@ public final class DataFormats {
     // @@protoc_insertion_point(class_scope:UnderreplicatedLedgerFormat)
   }
   
+  public interface CookieFormatOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+    
+    // required string bookieHost = 1;
+    boolean hasBookieHost();
+    String getBookieHost();
+    
+    // required string journalDir = 2;
+    boolean hasJournalDir();
+    String getJournalDir();
+    
+    // required string ledgerDirs = 3;
+    boolean hasLedgerDirs();
+    String getLedgerDirs();
+    
+    // optional string instanceId = 4;
+    boolean hasInstanceId();
+    String getInstanceId();
+  }
+  public static final class CookieFormat extends
+      com.google.protobuf.GeneratedMessage
+      implements CookieFormatOrBuilder {
+    // Use CookieFormat.newBuilder() to construct.
+    private CookieFormat(Builder builder) {
+      super(builder);
+    }
+    private CookieFormat(boolean noInit) {}
+    
+    private static final CookieFormat defaultInstance;
+    public static CookieFormat getDefaultInstance() {
+      return defaultInstance;
+    }
+    
+    public CookieFormat getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+    
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.apache.bookkeeper.proto.DataFormats.internal_static_CookieFormat_descriptor;
+    }
+    
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.apache.bookkeeper.proto.DataFormats.internal_static_CookieFormat_fieldAccessorTable;
+    }
+    
+    private int bitField0_;
+    // required string bookieHost = 1;
+    public static final int BOOKIEHOST_FIELD_NUMBER = 1;
+    private java.lang.Object bookieHost_;
+    public boolean hasBookieHost() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    public String getBookieHost() {
+      java.lang.Object ref = bookieHost_;
+      if (ref instanceof String) {
+        return (String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        String s = bs.toStringUtf8();
+        if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+          bookieHost_ = s;
+        }
+        return s;
+      }
+    }
+    private com.google.protobuf.ByteString getBookieHostBytes() {
+      java.lang.Object ref = bookieHost_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+        bookieHost_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    
+    // required string journalDir = 2;
+    public static final int JOURNALDIR_FIELD_NUMBER = 2;
+    private java.lang.Object journalDir_;
+    public boolean hasJournalDir() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    public String getJournalDir() {
+      java.lang.Object ref = journalDir_;
+      if (ref instanceof String) {
+        return (String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        String s = bs.toStringUtf8();
+        if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+          journalDir_ = s;
+        }
+        return s;
+      }
+    }
+    private com.google.protobuf.ByteString getJournalDirBytes() {
+      java.lang.Object ref = journalDir_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+        journalDir_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    
+    // required string ledgerDirs = 3;
+    public static final int LEDGERDIRS_FIELD_NUMBER = 3;
+    private java.lang.Object ledgerDirs_;
+    public boolean hasLedgerDirs() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    public String getLedgerDirs() {
+      java.lang.Object ref = ledgerDirs_;
+      if (ref instanceof String) {
+        return (String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        String s = bs.toStringUtf8();
+        if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+          ledgerDirs_ = s;
+        }
+        return s;
+      }
+    }
+    private com.google.protobuf.ByteString getLedgerDirsBytes() {
+      java.lang.Object ref = ledgerDirs_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+        ledgerDirs_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    
+    // optional string instanceId = 4;
+    public static final int INSTANCEID_FIELD_NUMBER = 4;
+    private java.lang.Object instanceId_;
+    public boolean hasInstanceId() {
+      return ((bitField0_ & 0x00000008) == 0x00000008);
+    }
+    public String getInstanceId() {
+      java.lang.Object ref = instanceId_;
+      if (ref instanceof String) {
+        return (String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        String s = bs.toStringUtf8();
+        if (com.google.protobuf.Internal.isValidUtf8(bs)) {
+          instanceId_ = s;
+        }
+        return s;
+      }
+    }
+    private com.google.protobuf.ByteString getInstanceIdBytes() {
+      java.lang.Object ref = instanceId_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8((String) ref);
+        instanceId_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    
+    private void initFields() {
+      bookieHost_ = "";
+      journalDir_ = "";
+      ledgerDirs_ = "";
+      instanceId_ = "";
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+      
+      if (!hasBookieHost()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasJournalDir()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasLedgerDirs()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+    
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeBytes(1, getBookieHostBytes());
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeBytes(2, getJournalDirBytes());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeBytes(3, getLedgerDirsBytes());
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        output.writeBytes(4, getInstanceIdBytes());
+      }
+      getUnknownFields().writeTo(output);
+    }
+    
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+    
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(1, getBookieHostBytes());
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(2, getJournalDirBytes());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(3, getLedgerDirsBytes());
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(4, getInstanceIdBytes());
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+    
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+    
+    public static org.apache.bookkeeper.proto.DataFormats.CookieFormat parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return newBuilder().mergeFrom(data).buildParsed();
+    }
+    public static org.apache.bookkeeper.proto.DataFormats.CookieFormat parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return newBuilder().mergeFrom(data, extensionRegistry)
+               .buildParsed();
+    }
+    public static org.apache.bookkeeper.proto.DataFormats.CookieFormat parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return newBuilder().mergeFrom(data).buildParsed();
+    }
+    public static org.apache.bookkeeper.proto.DataFormats.CookieFormat parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return newBuilder().mergeFrom(data, extensionRegistry)
+               .buildParsed();
+    }
+    public static org.apache.bookkeeper.proto.DataFormats.CookieFormat parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return newBuilder().mergeFrom(input).buildParsed();
+    }
+    public static org.apache.bookkeeper.proto.DataFormats.CookieFormat parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return newBuilder().mergeFrom(input, extensionRegistry)
+               .buildParsed();
+    }
+    public static org.apache.bookkeeper.proto.DataFormats.CookieFormat parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      Builder builder = newBuilder();
+      if (builder.mergeDelimitedFrom(input)) {
+        return builder.buildParsed();
+      } else {
+        return null;
+      }
+    }
+    public static org.apache.bookkeeper.proto.DataFormats.CookieFormat parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      Builder builder = newBuilder();
+      if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+        return builder.buildParsed();
+      } else {
+        return null;
+      }
+    }
+    public static org.apache.bookkeeper.proto.DataFormats.CookieFormat parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return newBuilder().mergeFrom(input).buildParsed();
+    }
+    public static org.apache.bookkeeper.proto.DataFormats.CookieFormat parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return newBuilder().mergeFrom(input, extensionRegistry)
+               .buildParsed();
+    }
+    
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.apache.bookkeeper.proto.DataFormats.CookieFormat prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+    
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.apache.bookkeeper.proto.DataFormats.CookieFormatOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.apache.bookkeeper.proto.DataFormats.internal_static_CookieFormat_descriptor;
+      }
+      
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.apache.bookkeeper.proto.DataFormats.internal_static_CookieFormat_fieldAccessorTable;
+      }
+      
+      // Construct using org.apache.bookkeeper.proto.DataFormats.CookieFormat.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+      
+      private Builder(BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+      
+      public Builder clear() {
+        super.clear();
+        bookieHost_ = "";
+        bitField0_ = (bitField0_ & ~0x00000001);
+        journalDir_ = "";
+        bitField0_ = (bitField0_ & ~0x00000002);
+        ledgerDirs_ = "";
+        bitField0_ = (bitField0_ & ~0x00000004);
+        instanceId_ = "";
+        bitField0_ = (bitField0_ & ~0x00000008);
+        return this;
+      }
+      
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+      
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.apache.bookkeeper.proto.DataFormats.CookieFormat.getDescriptor();
+      }
+      
+      public org.apache.bookkeeper.proto.DataFormats.CookieFormat getDefaultInstanceForType() {
+        return org.apache.bookkeeper.proto.DataFormats.CookieFormat.getDefaultInstance();
+      }
+      
+      public org.apache.bookkeeper.proto.DataFormats.CookieFormat build() {
+        org.apache.bookkeeper.proto.DataFormats.CookieFormat result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+      
+      private org.apache.bookkeeper.proto.DataFormats.CookieFormat buildParsed()
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        org.apache.bookkeeper.proto.DataFormats.CookieFormat result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(
+            result).asInvalidProtocolBufferException();
+        }
+        return result;
+      }
+      
+      public org.apache.bookkeeper.proto.DataFormats.CookieFormat buildPartial() {
+        org.apache.bookkeeper.proto.DataFormats.CookieFormat result = new org.apache.bookkeeper.proto.DataFormats.CookieFormat(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.bookieHost_ = bookieHost_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.journalDir_ = journalDir_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.ledgerDirs_ = ledgerDirs_;
+        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+          to_bitField0_ |= 0x00000008;
+        }
+        result.instanceId_ = instanceId_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+      
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.apache.bookkeeper.proto.DataFormats.CookieFormat) {
+          return mergeFrom((org.apache.bookkeeper.proto.DataFormats.CookieFormat)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+      
+      public Builder mergeFrom(org.apache.bookkeeper.proto.DataFormats.CookieFormat other) {
+        if (other == org.apache.bookkeeper.proto.DataFormats.CookieFormat.getDefaultInstance()) return this;
+        if (other.hasBookieHost()) {
+          setBookieHost(other.getBookieHost());
+        }
+        if (other.hasJournalDir()) {
+          setJournalDir(other.getJournalDir());
+        }
+        if (other.hasLedgerDirs()) {
+          setLedgerDirs(other.getLedgerDirs());
+        }
+        if (other.hasInstanceId()) {
+          setInstanceId(other.getInstanceId());
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+      
+      public final boolean isInitialized() {
+        if (!hasBookieHost()) {
+          
+          return false;
+        }
+        if (!hasJournalDir()) {
+          
+          return false;
+        }
+        if (!hasLedgerDirs()) {
+          
+          return false;
+        }
+        return true;
+      }
+      
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder(
+            this.getUnknownFields());
+        while (true) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              this.setUnknownFields(unknownFields.build());
+              onChanged();
+              return this;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                this.setUnknownFields(unknownFields.build());
+                onChanged();
+                return this;
+              }
+              break;
+            }
+            case 10: {
+              bitField0_ |= 0x00000001;
+              bookieHost_ = input.readBytes();
+              break;
+            }
+            case 18: {
+              bitField0_ |= 0x00000002;
+              journalDir_ = input.readBytes();
+              break;
+            }
+            case 26: {
+              bitField0_ |= 0x00000004;
+              ledgerDirs_ = input.readBytes();
+              break;
+            }
+            case 34: {
+              bitField0_ |= 0x00000008;
+              instanceId_ = input.readBytes();
+              break;
+            }
+          }
+        }
+      }
+      
+      private int bitField0_;
+      
+      // required string bookieHost = 1;
+      private java.lang.Object bookieHost_ = "";
+      public boolean hasBookieHost() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      public String getBookieHost() {
+        java.lang.Object ref = bookieHost_;
+        if (!(ref instanceof String)) {
+          String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+          bookieHost_ = s;
+          return s;
+        } else {
+          return (String) ref;
+        }
+      }
+      public Builder setBookieHost(String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        bookieHost_ = value;
+        onChanged();
+        return this;
+      }
+      public Builder clearBookieHost() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        bookieHost_ = getDefaultInstance().getBookieHost();
+        onChanged();
+        return this;
+      }
+      void setBookieHost(com.google.protobuf.ByteString value) {
+        bitField0_ |= 0x00000001;
+        bookieHost_ = value;
+        onChanged();
+      }
+      
+      // required string journalDir = 2;
+      private java.lang.Object journalDir_ = "";
+      public boolean hasJournalDir() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      public String getJournalDir() {
+        java.lang.Object ref = journalDir_;
+        if (!(ref instanceof String)) {
+          String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+          journalDir_ = s;
+          return s;
+        } else {
+          return (String) ref;
+        }
+      }
+      public Builder setJournalDir(String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+        journalDir_ = value;
+        onChanged();
+        return this;
+      }
+      public Builder clearJournalDir() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        journalDir_ = getDefaultInstance().getJournalDir();
+        onChanged();
+        return this;
+      }
+      void setJournalDir(com.google.protobuf.ByteString value) {
+        bitField0_ |= 0x00000002;
+        journalDir_ = value;
+        onChanged();
+      }
+      
+      // required string ledgerDirs = 3;
+      private java.lang.Object ledgerDirs_ = "";
+      public boolean hasLedgerDirs() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      public String getLedgerDirs() {
+        java.lang.Object ref = ledgerDirs_;
+        if (!(ref instanceof String)) {
+          String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+          ledgerDirs_ = s;
+          return s;
+        } else {
+          return (String) ref;
+        }
+      }
+      public Builder setLedgerDirs(String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+        ledgerDirs_ = value;
+        onChanged();
+        return this;
+      }
+      public Builder clearLedgerDirs() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        ledgerDirs_ = getDefaultInstance().getLedgerDirs();
+        onChanged();
+        return this;
+      }
+      void setLedgerDirs(com.google.protobuf.ByteString value) {
+        bitField0_ |= 0x00000004;
+        ledgerDirs_ = value;
+        onChanged();
+      }
+      
+      // optional string instanceId = 4;
+      private java.lang.Object instanceId_ = "";
+      public boolean hasInstanceId() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
+      }
+      public String getInstanceId() {
+        java.lang.Object ref = instanceId_;
+        if (!(ref instanceof String)) {
+          String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
+          instanceId_ = s;
+          return s;
+        } else {
+          return (String) ref;
+        }
+      }
+      public Builder setInstanceId(String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000008;
+        instanceId_ = value;
+        onChanged();
+        return this;
+      }
+      public Builder clearInstanceId() {
+        bitField0_ = (bitField0_ & ~0x00000008);
+        instanceId_ = getDefaultInstance().getInstanceId();
+        onChanged();
+        return this;
+      }
+      void setInstanceId(com.google.protobuf.ByteString value) {
+        bitField0_ |= 0x00000008;
+        instanceId_ = value;
+        onChanged();
+      }
+      
+      // @@protoc_insertion_point(builder_scope:CookieFormat)
+    }
+    
+    static {
+      defaultInstance = new CookieFormat(true);
+      defaultInstance.initFields();
+    }
+    
+    // @@protoc_insertion_point(class_scope:CookieFormat)
+  }
+  
   private static com.google.protobuf.Descriptors.Descriptor
     internal_static_LedgerMetadataFormat_descriptor;
   private static
@@ -2481,6 +3162,11 @@ public final class DataFormats {
   private static
     com.google.protobuf.GeneratedMessage.FieldAccessorTable
       internal_static_UnderreplicatedLedgerFormat_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_CookieFormat_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_CookieFormat_fieldAccessorTable;
   
   public static com.google.protobuf.Descriptors.FileDescriptor
       getDescriptor() {
@@ -2504,7 +3190,10 @@ public final class DataFormats {
       "\n\004HMAC\020\002\"@\n\037LedgerRereplicationLayoutFor" +
       "mat\022\014\n\004type\030\001 \002(\t\022\017\n\007version\030\002 \002(\005\".\n\033Un" +
       "derreplicatedLedgerFormat\022\017\n\007replica\030\001 \003" +
-      "(\tB\037\n\033org.apache.bookkeeper.protoH\001"
+      "(\t\"^\n\014CookieFormat\022\022\n\nbookieHost\030\001 \002(\t\022\022" +
+      "\n\njournalDir\030\002 \002(\t\022\022\n\nledgerDirs\030\003 \002(\t\022\022" +
+      "\n\ninstanceId\030\004 \001(\tB\037\n\033org.apache.bookkee" +
+      "per.protoH\001"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
       new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -2543,6 +3232,14 @@ public final class DataFormats {
               new java.lang.String[] { "Replica", },
               org.apache.bookkeeper.proto.DataFormats.UnderreplicatedLedgerFormat.class,
               org.apache.bookkeeper.proto.DataFormats.UnderreplicatedLedgerFormat.Builder.class);
+          internal_static_CookieFormat_descriptor =
+            getDescriptor().getMessageTypes().get(3);
+          internal_static_CookieFormat_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_CookieFormat_descriptor,
+              new java.lang.String[] { "BookieHost", "JournalDir", "LedgerDirs", "InstanceId", },
+              org.apache.bookkeeper.proto.DataFormats.CookieFormat.class,
+              org.apache.bookkeeper.proto.DataFormats.CookieFormat.Builder.class);
           return null;
         }
       };

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/IOUtils.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/IOUtils.java?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/IOUtils.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/IOUtils.java Fri Sep  7 05:04:33 2012
@@ -52,4 +52,37 @@ public class IOUtils {
         }
     }
 
+    /**
+     * Confirm prompt for the console operations.
+     * 
+     * @param prompt
+     *            Prompt message to be displayed on console
+     * @return Returns true if confirmed as 'Y', returns false if confirmed as
+     *         'N'
+     * @throws IOException
+     */
+    public static boolean confirmPrompt(String prompt) throws IOException {
+        while (true) {
+            System.out.print(prompt + " (Y or N) ");
+            StringBuilder responseBuilder = new StringBuilder();
+            while (true) {
+                int c = System.in.read();
+                if (c == -1 || c == '\r' || c == '\n') {
+                    break;
+                }
+                responseBuilder.append((char) c);
+            }
+
+            String response = responseBuilder.toString();
+            if (response.equalsIgnoreCase("y")
+                    || response.equalsIgnoreCase("yes")) {
+                return true;
+            } else if (response.equalsIgnoreCase("n")
+                    || response.equalsIgnoreCase("no")) {
+                return false;
+            }
+            System.out.println("Invalid input: " + response);
+            // else ask them again
+        }
+    }
 }

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/ZkUtils.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/ZkUtils.java?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/ZkUtils.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/ZkUtils.java Fri Sep  7 05:04:33 2012
@@ -22,19 +22,30 @@
 package org.apache.bookkeeper.util;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.AsyncCallback;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.AsyncCallback.StringCallback;
 import org.apache.zookeeper.KeeperException.Code;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.Watcher.Event.EventType;
+import org.apache.zookeeper.Watcher.Event.KeeperState;
 import org.apache.zookeeper.data.ACL;
 import org.apache.zookeeper.ZooKeeper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Provided utilites for zookeeper access, etc.
  */
 public class ZkUtils {
+    private static final Logger LOG = LoggerFactory.getLogger(ZkUtils.class);
 
     /**
      * Create zookeeper path recursively
@@ -91,4 +102,42 @@ public class ZkUtils {
 
     }
 
+    /**
+     * Get new ZooKeeper client. Waits till the connection is complete. If
+     * connection is not successful within timeout, then throws back exception.
+     * 
+     * @param servers
+     *            ZK servers connection string.
+     * @param timeout
+     *            Session timeout.
+     */
+    public static ZooKeeper createConnectedZookeeperClient(String servers, int timeout)
+            throws IOException, InterruptedException, KeeperException {
+        if (servers == null || servers.isEmpty()) {
+            throw new IllegalArgumentException("servers cannot be empty");
+        }
+        final CountDownLatch zkConnectLatch = new CountDownLatch(1);
+        Watcher connectWatcher = new Watcher() {
+
+            @Override
+            public void process(WatchedEvent event) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Process: " + event.getType() + " "
+                            + event.getPath());
+                }
+                if (event.getType().equals(EventType.None)
+                        && event.getState() == KeeperState.SyncConnected) {
+                    if (zkConnectLatch.getCount() > 0) {
+                        zkConnectLatch.countDown();
+                    }
+                }
+            }
+        };
+        final ZooKeeper newZk = new ZooKeeper(servers, timeout, connectWatcher);
+        if (!zkConnectLatch.await(timeout, TimeUnit.MILLISECONDS)
+                || !newZk.getState().isConnected()) {
+            throw KeeperException.create(KeeperException.Code.CONNECTIONLOSS);
+        }
+        return newZk;
+    }
 }

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/proto/DataFormats.proto
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/proto/DataFormats.proto?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/proto/DataFormats.proto (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/main/proto/DataFormats.proto Fri Sep  7 05:04:33 2012
@@ -55,4 +55,14 @@ message LedgerRereplicationLayoutFormat 
  
 message UnderreplicatedLedgerFormat {
     repeated string replica = 1;
-}
\ No newline at end of file
+}
+
+/**
+* Cookie format for storing cookie information
+*/
+message CookieFormat {
+    required string bookieHost = 1;
+    required string journalDir = 2;
+    required string ledgerDirs = 3;
+    optional string instanceId = 4;
+}

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/CookieTest.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/CookieTest.java?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/CookieTest.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/CookieTest.java Fri Sep  7 05:04:33 2012
@@ -22,14 +22,12 @@
 package org.apache.bookkeeper.bookie;
 
 import org.apache.commons.io.FileUtils;
+import org.apache.bookkeeper.client.BookKeeperAdmin;
+import org.apache.bookkeeper.conf.ClientConfiguration;
 import org.apache.bookkeeper.conf.ServerConfiguration;
 import org.apache.bookkeeper.test.ZooKeeperUtil;
 import org.apache.zookeeper.ZooKeeper;
 
-import java.io.FileOutputStream;
-import java.io.BufferedWriter;
-import java.io.OutputStreamWriter;
-
 import java.io.File;
 import java.io.IOException;
 
@@ -40,9 +38,6 @@ import static org.junit.Assert.*;
 
 import static org.apache.bookkeeper.bookie.UpgradeTest.*;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 public class CookieTest {
     ZooKeeperUtil zkutil;
     ZooKeeper zkc = null;
@@ -279,6 +274,41 @@ public class CookieTest {
         }
     }
 
+    /*
+     * Test Cookie verification with format.
+     */
+    @Test
+    public void testVerifyCookieWithFormat() throws Exception {
+        ClientConfiguration adminConf = new ClientConfiguration();
+        adminConf.setProperty("bookkeeper.format", true);
+        // Format the BK Metadata and generate INSTANCEID
+        BookKeeperAdmin.format(adminConf, false, true);
+
+        ServerConfiguration bookieConf = new ServerConfiguration()
+                .setZkServers(zkutil.getZooKeeperConnectString())
+                .setJournalDirName(newDirectory(false))
+                .setLedgerDirNames(new String[] { newDirectory(false) })
+                .setBookiePort(3181);
+        // Bookie should start successfully for fresh env.
+        new Bookie(bookieConf);
+
+        // Format metadata one more time.
+        BookKeeperAdmin.format(adminConf, false, true);
+        try {
+            new Bookie(bookieConf);
+            fail("Bookie should not start with previous instance id.");
+        } catch (BookieException.InvalidCookieException e) {
+            assertTrue(
+                    "Bookie startup should fail because of invalid instance id",
+                    e.getMessage().contains("instanceId"));
+        }
+
+        // Now format the Bookie and restart.
+        Bookie.format(bookieConf, false, true);
+        // After bookie format bookie should be able to start again.
+        new Bookie(bookieConf);
+    }
+
     /**
      * Test that if a bookie is started with directories with
      * version 2 data, that it will fail to start (it needs upgrade)

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/TestLedgerUnderreplicationManager.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/TestLedgerUnderreplicationManager.java?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/TestLedgerUnderreplicationManager.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/TestLedgerUnderreplicationManager.java Fri Sep  7 05:04:33 2012
@@ -48,6 +48,7 @@ import org.apache.bookkeeper.proto.DataF
 import org.apache.bookkeeper.replication.ReplicationException.CompatibilityException;
 import org.apache.bookkeeper.replication.ReplicationException.UnavailableException;
 import org.apache.bookkeeper.test.ZooKeeperUtil;
+import org.apache.bookkeeper.util.ZkUtils;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.ZooKeeper;
 import org.junit.After;
@@ -85,8 +86,10 @@ public class TestLedgerUnderreplicationM
 
         executor = Executors.newCachedThreadPool();
 
-        zkc1 = zkUtil.getNewZooKeeperClient();
-        zkc2 = zkUtil.getNewZooKeeperClient();
+        zkc1 = ZkUtils.createConnectedZookeeperClient(
+                zkUtil.getZooKeeperConnectString(), 10000);
+        zkc2 = ZkUtils.createConnectedZookeeperClient(
+                zkUtil.getZooKeeperConnectString(), 10000);
         lmf1 = LedgerManagerFactory.newLedgerManagerFactory(conf, zkc1);
         lmf2 = LedgerManagerFactory.newLedgerManagerFactory(conf, zkc2);
         basePath = conf.getZkLedgersRootPath() + '/'

Modified: zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/TestReplicationWorker.java
URL: http://svn.apache.org/viewvc/zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/TestReplicationWorker.java?rev=1381870&r1=1381869&r2=1381870&view=diff
==============================================================================
--- zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/TestReplicationWorker.java (original)
+++ zookeeper/bookkeeper/trunk/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/TestReplicationWorker.java Fri Sep  7 05:04:33 2012
@@ -37,6 +37,7 @@ import org.apache.bookkeeper.meta.Ledger
 import org.apache.bookkeeper.meta.LedgerUnderreplicationManager;
 import org.apache.bookkeeper.meta.ZkLedgerUnderreplicationManager;
 import org.apache.bookkeeper.test.MultiLedgerManagerTestCase;
+import org.apache.bookkeeper.util.ZkUtils;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.ZooKeeper;
 import org.junit.Test;
@@ -225,7 +226,8 @@ public class TestReplicationWorker exten
         InetSocketAddress newBkAddr2 = new InetSocketAddress(InetAddress
                 .getLocalHost().getHostAddress(), startNewBookie2);
         LOG.info("New Bookie addr :" + newBkAddr2);
-        ZooKeeper zkc1 = zkUtil.getNewZooKeeperClient();
+        ZooKeeper zkc1 = ZkUtils.createConnectedZookeeperClient(
+                zkUtil.getZooKeeperConnectString(), 10000);
         ReplicationWorker rw2 = new ReplicationWorker(zkc1, baseClientConf,
                 newBkAddr2);
         rw1.start();