You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bookkeeper.apache.org by si...@apache.org on 2017/08/01 22:49:59 UTC

[bookkeeper] branch master updated: BOOKKEEPER-588: SSL Support for Bookkeeper

This is an automated email from the ASF dual-hosted git repository.

sijie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/bookkeeper.git


The following commit(s) were added to refs/heads/master by this push:
     new 8e0bd2c  BOOKKEEPER-588: SSL Support for Bookkeeper
8e0bd2c is described below

commit 8e0bd2c3d81b522e97434d8646915f36422a104b
Author: kishorekasi <kk...@gmail.com>
AuthorDate: Tue Aug 1 15:49:46 2017 -0700

    BOOKKEEPER-588: SSL Support for Bookkeeper
    
    + Merged changes from eoliville
    + Mutual Authentication
    
    Author: kishorekasi <kk...@gmail.com>
    Author: Kishore Kasi Udayashankar <ku...@salesforce.com>
    Author: Kishore Udayashankar <ku...@salesforce.com>
    
    Reviewers: Sijie Guo <si...@apache.org>
    
    This patch had conflicts when merged, resolved by
    Committer: Sijie Guo <si...@apache.org>
    
    This closes #183 from kishorekasi/BOOKKEEPER-588-kishore
---
 bookkeeper-server/conf/bk_server.conf              |   27 +
 bookkeeper-server/pom.xml                          |   11 +
 .../auth/AuthProviderFactoryFactory.java           |    1 -
 .../apache/bookkeeper/auth/BookieAuthProvider.java |    7 +
 .../apache/bookkeeper/auth/ClientAuthProvider.java |    7 +
 .../java/org/apache/bookkeeper/bookie/Bookie.java  |    7 +-
 .../org/apache/bookkeeper/client/BKException.java  |   10 +
 .../bookkeeper/client/BookKeeperClientStats.java   |    1 +
 .../org/apache/bookkeeper/client/PendingAddOp.java |    2 +-
 .../bookkeeper/conf/AbstractConfiguration.java     |  151 +-
 .../bookkeeper/conf/ClientConfiguration.java       |  147 +
 .../bookkeeper/conf/ServerConfiguration.java       |  123 +
 .../org/apache/bookkeeper/proto/AuthHandler.java   |  142 +-
 .../org/apache/bookkeeper/proto/BookieClient.java  |   14 +-
 .../apache/bookkeeper/proto/BookieNettyServer.java |  158 +-
 .../bookkeeper/proto/BookieRequestHandler.java     |    3 +-
 .../bookkeeper/proto/BookieRequestProcessor.java   |   90 +-
 .../org/apache/bookkeeper/proto/BookieServer.java  |   16 +-
 .../proto/BookkeeperInternalCallbacks.java         |    4 +
 .../bookkeeper/proto/BookkeeperProtocol.java       | 8426 +++++++++++---------
 .../apache/bookkeeper/proto/ConnectionPeer.java    |    6 +
 .../proto/DefaultPerChannelBookieClientPool.java   |   22 +-
 .../bookkeeper/proto/PerChannelBookieClient.java   |  401 +-
 .../proto/PerChannelBookieClientFactory.java       |    6 +-
 .../apache/bookkeeper/tls/SecurityException.java   |   34 +
 .../bookkeeper/tls/SecurityHandlerFactory.java     |   35 +
 .../tls/SecurityProviderFactoryFactory.java        |   45 +
 .../apache/bookkeeper/tls/TLSContextFactory.java   |  293 +
 .../apache/bookkeeper/util/LocalBookKeeper.java    |   11 +-
 .../src/main/proto/BookkeeperProtocol.proto        |    9 +
 .../java/org/apache/bookkeeper/auth/TestAuth.java  |    2 -
 .../bookie/BookieInitializationTest.java           |    3 +-
 .../replication/AuthAutoRecoveryTest.java          |    3 +-
 .../java/org/apache/bookkeeper/tls/TestTLS.java    |  501 ++
 bookkeeper-server/src/test/resources/cacerts       |  Bin 0 -> 110225 bytes
 bookkeeper-server/src/test/resources/client.jks    |  Bin 0 -> 1416 bytes
 .../src/test/resources/keyStoreClientPassword.txt  |    1 +
 .../src/test/resources/keyStoreServerPassword.txt  |    1 +
 bookkeeper-server/src/test/resources/server.jks    |  Bin 0 -> 1393 bytes
 .../src/test/resources/trustStorePassword.txt      |    1 +
 pom.xml                                            |    5 +-
 41 files changed, 6784 insertions(+), 3942 deletions(-)

diff --git a/bookkeeper-server/conf/bk_server.conf b/bookkeeper-server/conf/bk_server.conf
index 57b31bf..11d7244 100644
--- a/bookkeeper-server/conf/bk_server.conf
+++ b/bookkeeper-server/conf/bk_server.conf
@@ -332,6 +332,33 @@ zkEnableSecurity=false
 # Stats Provider Class (if statistics are enabled)
 #statsProviderClass=org.apache.bookkeeper.stats.CodahaleMetricsProvider
 
+# SSL Provider (JDK or OpenSSL)
+# sslProvider=OpenSSL
+
+# The path to class that provides security.
+#sslProviderFactoryClass=org.apache.bookkeeper.security.SSLContextFactory
+
+# Type of security used by server
+#sslClientAuthentication=true
+
+# Bookie Keystore type
+#sslKeyStoreType=JKS
+
+# Bookie Keystore location (path)
+#sslKeyStore=
+
+# Bookie Keystore password path, if the keystore is protected by a password
+#sslKeyStorePasswordPath=
+
+# Bookie Truststore type
+#sslTrustStoreType=
+
+# Bookie Truststore location (path)
+#sslTrustStore=
+
+# Bookie Truststore password path, if the truststore is protected by a password
+#sslTrustStorePasswordPath=
+
 # Minimum safe Usable size to be available in index directory for Bookie to create Index File while replaying 
 # journal at the time of Bookie Start in Readonly Mode (in bytes)
 # minUsableSizeForIndexFileCreation=1073741824
diff --git a/bookkeeper-server/pom.xml b/bookkeeper-server/pom.xml
index 8647d5e..d1e74b5 100644
--- a/bookkeeper-server/pom.xml
+++ b/bookkeeper-server/pom.xml
@@ -221,6 +221,11 @@
         <version>2.7.3</version>
         <scope>test</scope>
     </dependency>          
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-tcnative-boringssl-static</artifactId>
+      <version>${netty-boringssl.version}</version>
+    </dependency>
   </dependencies>
   <build>
     <plugins>
@@ -334,6 +339,12 @@
             <exclude>**/.gitignore</exclude>
             <exclude>**/.project</exclude>
             <exclude>**/.settings/*</exclude>
+            <exclude>certs/keyStoreClientPassword.txt</exclude>
+            <exclude>certs/keyStoreServerPassword.txt</exclude>
+            <exclude>certs/trustStorePassword.txt</exclude>
+            <exclude>src/test/resources/keyStoreClientPassword.txt</exclude>
+            <exclude>src/test/resources/keyStoreServerPassword.txt</exclude>
+            <exclude>src/test/resources/trustStorePassword.txt</exclude>
           </excludes>
         </configuration>
       </plugin>
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/AuthProviderFactoryFactory.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/AuthProviderFactoryFactory.java
index 585ecd5..c5906fe 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/AuthProviderFactoryFactory.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/AuthProviderFactoryFactory.java
@@ -106,5 +106,4 @@ public class AuthProviderFactoryFactory {
             };
         }
     }
-
 }
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/BookieAuthProvider.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/BookieAuthProvider.java
index c360c49..4570d10 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/BookieAuthProvider.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/BookieAuthProvider.java
@@ -78,6 +78,13 @@ public interface BookieAuthProvider {
     }
 
     /**
+     * Callback to let the provider know that the underlying protocol is changed.
+     * For instance this will happen when a START_TLS operation succeeds
+     */
+    default void onProtocolUpgrade() {
+    }
+
+    /**
      * Process a request from the client. cb will receive the next
      * message to be sent to the client. If there are no more messages
      * to send to the client, cb should not be called, and completeCb
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/ClientAuthProvider.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/ClientAuthProvider.java
index 8939afc..8737d60 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/ClientAuthProvider.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/ClientAuthProvider.java
@@ -82,6 +82,13 @@ public interface ClientAuthProvider {
     void init(AuthCallbacks.GenericCallback<AuthToken> cb);
 
     /**
+     * Callback to let the provider know that the underlying protocol is changed.
+     * For instance this will happen when a START_TLS operation succeeds
+     */
+    default void onProtocolUpgrade() {
+    }
+
+    /**
      * Process a response from the server. cb will receive the next
      * message to be sent to the server. If there are no more messages
      * to send to the server, cb should not be called, and completeCb
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java
index a9901c0..c05d25d 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/Bookie.java
@@ -576,7 +576,12 @@ public class Bookie extends BookieCriticalThread {
         if (iface == null) {
             iface = "default";
         }
-        InetSocketAddress inetAddr = new InetSocketAddress(DNS.getDefaultHost(iface), conf.getBookiePort());
+        String hostName = DNS.getDefaultHost(iface);
+        InetSocketAddress inetAddr = new InetSocketAddress(hostName, conf.getBookiePort());
+        if (inetAddr.isUnresolved()) {
+            throw new UnknownHostException("Unable to resolve default hostname: "
+                    + hostName + " for interface: " + iface);
+        }
         String hostAddress = inetAddr.getAddress().getHostAddress();
         if (conf.getUseHostNameAsBookieID()) {
             hostAddress = inetAddr.getAddress().getCanonicalHostName();
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BKException.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BKException.java
index 1c4cec8..406d552 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BKException.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BKException.java
@@ -103,6 +103,8 @@ public abstract class BKException extends Exception {
             return new BKTimeoutException();
         case Code.LedgerIdOverflowException:
             return new BKLedgerIdOverflowException();
+        case Code.SecurityException:
+            return new BKSecurityException();
         default:
             return new BKUnexpectedConditionException();
         }
@@ -174,6 +176,7 @@ public abstract class BKException extends Exception {
          * @since 4.5
          */
         int TimeoutException = -23;
+        int SecurityException = -24;
 
         /**
          * Operation is illegal.
@@ -286,11 +289,18 @@ public abstract class BKException extends Exception {
             return "Add entry quorum wait timed out";
         case Code.TimeoutException:
             return "Bookie operation timeout";
+        case Code.SecurityException:
+            return "Failed to establish a secure connection";
         default:
             return "Unexpected condition";
         }
     }
 
+    public static class BKSecurityException extends BKException {
+        public BKSecurityException() {
+            super(Code.SecurityException);
+        }
+    }
     public static class BKReadException extends BKException {
         public BKReadException() {
             super(Code.ReadException);
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeperClientStats.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeperClientStats.java
index 40d9bbc..a0389c1 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeperClientStats.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeperClientStats.java
@@ -62,4 +62,5 @@ public interface BookKeeperClientStats {
     public final static String CHANNEL_READ_LAC_OP = "READ_LAC";
     public final static String CHANNEL_TIMEOUT_READ_LAC = "TIMEOUT_READ_LAC";
     public final static String TIMEOUT_GET_BOOKIE_INFO = "TIMEOUT_GET_BOOKIE_INFO";
+    public final static String CHANNEL_START_TLS_OP = "START_TLS";
 }
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/PendingAddOp.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/PendingAddOp.java
index 130e1e2..5ab2435 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/PendingAddOp.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/PendingAddOp.java
@@ -297,7 +297,7 @@ class PendingAddOp implements WriteCallback, TimerTask {
         ReferenceCountUtil.release(toSend);
 
         if (LOG.isDebugEnabled()) {
-            LOG.debug("Submit callback (lid:{}, eid: {}). rc:{}", new Object[] { lh.getId(), entryId, rc });
+            LOG.debug("Submit callback (lid:{}, eid: {}). rc:{}", lh.getId(), entryId, rc);
         }
 
         long latencyNanos = MathUtils.elapsedNanos(requestTimeNanos);
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/AbstractConfiguration.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/AbstractConfiguration.java
index 9ae542c..5a081ce 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/AbstractConfiguration.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/AbstractConfiguration.java
@@ -18,6 +18,12 @@
 package org.apache.bookkeeper.conf;
 
 import java.net.URL;
+import javax.net.ssl.SSLEngine;
+
+import org.apache.bookkeeper.feature.Feature;
+import org.apache.bookkeeper.meta.LedgerManagerFactory;
+import org.apache.bookkeeper.util.ReflectionUtils;
+import static org.apache.bookkeeper.conf.ClientConfiguration.CLIENT_AUTH_PROVIDER_FACTORY_CLASS;
 
 import org.apache.commons.configuration.CompositeConfiguration;
 import org.apache.commons.configuration.Configuration;
@@ -25,10 +31,6 @@ import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.PropertiesConfiguration;
 import org.apache.commons.configuration.SystemConfiguration;
 
-import org.apache.bookkeeper.feature.Feature;
-import org.apache.bookkeeper.meta.LedgerManagerFactory;
-import org.apache.bookkeeper.util.ReflectionUtils;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -67,8 +69,27 @@ public abstract class AbstractConfiguration extends CompositeConfiguration {
     protected final static String METASTORE_IMPL_CLASS = "metastoreImplClass";
     protected final static String METASTORE_MAX_ENTRIES_PER_SCAN = "metastoreMaxEntriesPerScan";
 
-    // Client auth provider factory class name. It must be configured on Bookies to for the Auditor
-    protected final static String CLIENT_AUTH_PROVIDER_FACTORY_CLASS = "clientAuthProviderFactoryClass";
+    // Common TLS configuration
+    // TLS Provider (JDK or OpenSSL)
+    protected final static String TLS_PROVIDER = "tlsProvider";
+
+    // TLS provider factory class name
+    protected final static String TLS_PROVIDER_FACTORY_CLASS = "tlsProviderFactoryClass";
+
+    // Enable authentication of the other connection end point (mutual authentication)
+    protected final static String TLS_CLIENT_AUTHENTICATION = "tlsClientAuthentication";
+
+    /**
+     * This list will be passed to {@link SSLEngine#setEnabledCipherSuites(java.lang.String[]) }.
+     * Please refer to official JDK JavaDocs
+    */
+    protected final static String TLS_ENABLED_CIPHER_SUITES = "tlsEnabledCipherSuites";
+
+    /**
+     * This list will be passed to {@link SSLEngine#setEnabledProtocols(java.lang.String[]) }.
+     * Please refer to official JDK JavaDocs
+    */
+    protected final static String TLS_ENABLED_PROTOCOLS = "tlsEnabledProtocols";
 
     //Netty configuration
     protected final static String NETTY_MAX_FRAME_SIZE = "nettyMaxFrameSizeBytes";
@@ -323,8 +344,8 @@ public abstract class AbstractConfiguration extends CompositeConfiguration {
     }
 
     /**
-     * Get the client authentication provider factory class name. If this returns null, no authentication will take
-     * place.
+     * Get the client authentication provider factory class name.
+     * If this returns null, no authentication will take place.
      *
      * @return the client authentication provider factory class name or null.
      */
@@ -354,4 +375,118 @@ public abstract class AbstractConfiguration extends CompositeConfiguration {
         setProperty(NETTY_MAX_FRAME_SIZE, String.valueOf(maxSize));
         return this;
     }
+
+    /**
+     * Get the security provider factory class name. If this returns null, no security will be enforced on the channel.
+     *
+     * @return the security provider factory class name or null.
+     */
+    public String getTLSProviderFactoryClass() {
+        return getString(TLS_PROVIDER_FACTORY_CLASS, null);
+    }
+
+    /**
+     * Set the client security provider factory class name. If this is not set, no security will be used on the channel.
+     *
+     * @param factoryClass
+     *            the client security provider factory class name
+     * @return client configuration
+     */
+    public AbstractConfiguration setTLSProviderFactoryClass(String factoryClass) {
+        setProperty(TLS_PROVIDER_FACTORY_CLASS, factoryClass);
+        return this;
+    }
+
+    /**
+     * Get TLS Provider (JDK or OpenSSL)
+     * 
+     * @return the TLS provider to use in creating TLS Context
+     */
+    public String getTLSProvider() {
+        return getString(TLS_PROVIDER, "OpenSSL");
+    }
+
+    /**
+     * Set TLS Provider (JDK or OpenSSL)
+     * 
+     * @param provider
+     *            TLS Provider type
+     * @return Client Configuration
+     */
+    public AbstractConfiguration setTLSProvider(String provider) {
+        setProperty(TLS_PROVIDER, provider);
+        return this;
+    }
+
+    /**
+     * Whether the client will send an TLS certificate on TLS-handshake
+     * 
+     * @see #setTLSAuthentication(boolean)
+     * @return whether TLS is enabled on the bookie or not.
+     */
+    public boolean getTLSClientAuthentication() {
+        return getBoolean(TLS_CLIENT_AUTHENTICATION, false);
+    }
+
+    /**
+     * Specify whether the client will send an TLS certificate on TLS-handshake
+     * 
+     * @param enabled
+     *            Whether to send a certificate or not
+     * @return client configuration
+     */
+    public AbstractConfiguration setTLSClientAuthentication(boolean enabled) {
+        setProperty(TLS_CLIENT_AUTHENTICATION, enabled);
+        return this;
+    }
+
+    /**
+     * Set the list of enabled TLS cipher suites. Leave null not to override default JDK list. This list will be passed
+     * to {@link SSLEngine#setEnabledCipherSuites(java.lang.String[]) }. Please refer to official JDK JavaDocs
+     *
+     * @param list
+     *            comma separated list of enabled TLS cipher suites
+     * @return current configuration
+     */
+    public AbstractConfiguration setTLSEnabledCipherSuites(
+            String list) {
+        setProperty(TLS_ENABLED_CIPHER_SUITES, list);
+        return this;
+    }
+
+    /**
+     * Get the list of enabled TLS cipher suites
+     *
+     * @return this list of enabled TLS cipher suites
+     *
+     * @see #setTLSEnabledCipherSuites(java.lang.String)
+     */
+    public String getTLSEnabledCipherSuites() {
+        return getString(TLS_ENABLED_CIPHER_SUITES, null);
+    }
+
+    /**
+     * Set the list of enabled TLS protocols. Leave null not to override default JDK list. This list will be passed to
+     * {@link SSLEngine#setEnabledProtocols(java.lang.String[]) }. Please refer to official JDK JavaDocs
+     *
+     * @param list
+     *            comma separated list of enabled TLS cipher suites
+     * @return current configuration
+     */
+    public AbstractConfiguration setTLSEnabledProtocols(
+            String list) {
+        setProperty(TLS_ENABLED_PROTOCOLS, list);
+        return this;
+    }
+
+    /**
+     * Get the list of enabled TLS protocols
+     *
+     * @return the list of enabled TLS protocols.
+     *
+     * @see #setTLSEnabledProtocols(java.lang.String)
+     */
+    public String getTLSEnabledProtocols() {
+        return getString(TLS_ENABLED_PROTOCOLS, null);
+    }
 }
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/ClientConfiguration.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/ClientConfiguration.java
index 8c2b260..6e11f94 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/ClientConfiguration.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/ClientConfiguration.java
@@ -35,6 +35,7 @@ import org.apache.bookkeeper.util.ReflectionUtils;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.lang.StringUtils;
 
+
 /**
  * Configuration settings for client side
  */
@@ -103,6 +104,7 @@ public class ClientConfiguration extends AbstractConfiguration {
     protected final static String GET_BOOKIE_INFO_RETRY_INTERVAL_SECONDS = "getBookieInfoRetryIntervalSeconds";
     protected final static String BOOKIE_MAX_MULTIPLE_FOR_WEIGHTED_PLACEMENT = "bookieMaxMultipleForWeightBasedPlacement";
     protected final static String GET_BOOKIE_INFO_TIMEOUT_SECS = "getBookieInfoTimeoutSecs";
+    protected final static String START_TLS_TIMEOUT_SECS = "startTLSTimeoutSecs";
 
     // Number Woker Threads
     protected final static String NUM_WORKER_THREADS = "numWorkerThreads";
@@ -135,6 +137,17 @@ public class ClientConfiguration extends AbstractConfiguration {
      */
     public final static String CLIENT_ROLE_SYSTEM = "system";
 
+    // Client auth provider factory class name. It must be configured on Bookies to for the Auditor
+    protected final static String CLIENT_AUTH_PROVIDER_FACTORY_CLASS = "clientAuthProviderFactoryClass";
+
+    // Client TLS
+    protected final static String TLS_KEYSTORE_TYPE = "clientKeyStoreType";
+    protected final static String TLS_KEYSTORE = "clientKeyStore";
+    protected final static String TLS_KEYSTORE_PASSWORD_PATH = "clientKeyStorePasswordPath";
+    protected final static String TLS_TRUSTSTORE_TYPE = "clientTrustStoreType";
+    protected final static String TLS_TRUSTSTORE = "clientTrustStore";
+    protected final static String TLS_TRUSTSTORE_PASSWORD_PATH = "clientTrustStorePasswordPath";
+
     /**
      * Construct a default client-side configuration
      */
@@ -1275,6 +1288,14 @@ public class ClientConfiguration extends AbstractConfiguration {
     }
 
     /**
+     * Return the timeout value for startTLS request
+     * @return
+     */
+    public int getStartTLSTimeout() {
+        return getInteger(START_TLS_TIMEOUT_SECS, 10);
+    }
+
+    /**
      * Set whether or not disk weight based placement is enabled.
      *
      * @param isEnabled - boolean indicating enabled or not
@@ -1331,6 +1352,16 @@ public class ClientConfiguration extends AbstractConfiguration {
     }
 
     /**
+     * Set the timeout value in secs for the START_TLS request
+     * @param timeout
+     * @return client configuration
+     */
+    public ClientConfiguration setStartTLSTimeout(int timeoutSecs) {
+        setProperty(START_TLS_TIMEOUT_SECS, timeoutSecs);
+        return this;
+    }
+
+    /**
      * Set the client role
      *
      * @param role defines how the client will act
@@ -1361,6 +1392,122 @@ public class ClientConfiguration extends AbstractConfiguration {
     }
 
     /**
+     * Get the keystore type for client. Default is JKS.
+     * 
+     * @return
+     */
+    public String getTLSKeyStoreType() {
+        return getString(TLS_KEYSTORE_TYPE, "JKS");
+    }
+
+
+    /**
+     * Set the keystore type for client.
+     * 
+     * @return
+     */
+    public ClientConfiguration setTLSKeyStoreType(String arg) {
+        setProperty(TLS_KEYSTORE_TYPE, arg);
+        return this;
+    }
+
+    /**
+     * Get the keystore path for the client.
+     * 
+     * @return
+     */
+    public String getTLSKeyStore() {
+        return getString(TLS_KEYSTORE, null);
+    }
+
+    /**
+     * Set the keystore path for the client.
+     * 
+     * @return
+     */
+    public ClientConfiguration setTLSKeyStore(String arg) {
+        setProperty(TLS_KEYSTORE, arg);
+        return this;
+    }
+
+    /**
+     * Get the path to file containing keystore password, if the client keystore is password protected. Default is null.
+     * 
+     * @return
+     */
+    public String getTLSKeyStorePasswordPath() {
+        return getString(TLS_KEYSTORE_PASSWORD_PATH, null);
+    }
+
+    /**
+     * Set the path to file containing keystore password, if the client keystore is password protected.
+     * 
+     * @return
+     */
+    public ClientConfiguration setTLSKeyStorePasswordPath(String arg) {
+        setProperty(TLS_KEYSTORE_PASSWORD_PATH, arg);
+        return this;
+    }
+
+    /**
+     * Get the truststore type for client. Default is JKS.
+     * 
+     * @return
+     */
+    public String getTLSTrustStoreType() {
+        return getString(TLS_TRUSTSTORE_TYPE, "JKS");
+    }
+
+    /**
+     * Set the truststore type for client.
+     * 
+     * @return
+     */
+    public ClientConfiguration setTLSTrustStoreType(String arg) {
+        setProperty(TLS_TRUSTSTORE_TYPE, arg);
+        return this;
+    }
+
+    /**
+     * Get the truststore path for the client.
+     * 
+     * @return
+     */
+    public String getTLSTrustStore() {
+        return getString(TLS_TRUSTSTORE, null);
+    }
+
+    /**
+     * Set the truststore path for the client.
+     * 
+     * @return
+     */
+    public ClientConfiguration setTLSTrustStore(String arg) {
+        setProperty(TLS_TRUSTSTORE, arg);
+        return this;
+    }
+
+    /**
+     * Get the path to file containing truststore password, if the client truststore is password protected. Default is
+     * null.
+     * 
+     * @return
+     */
+    public String getTLSTrustStorePasswordPath() {
+        return getString(TLS_TRUSTSTORE_PASSWORD_PATH, null);
+    }
+
+    /**
+     * Set the path to file containing truststore password, if the client truststore is password protected.
+     * 
+     * @return
+     */
+    public ClientConfiguration setTLSTrustStorePasswordPath(String arg) {
+        setProperty(TLS_TRUSTSTORE_PASSWORD_PATH, arg);
+        return this;
+    }
+
+    /**
      * Whether to delay ensemble change or not?
      *
      * @return true if to delay ensemble change, otherwise false.
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/ServerConfiguration.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/ServerConfiguration.java
index 17ff7ee..177c966 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/ServerConfiguration.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/ServerConfiguration.java
@@ -154,6 +154,14 @@ public class ServerConfiguration extends AbstractConfiguration {
 
     protected final static String ALLOW_MULTIPLEDIRS_UNDER_SAME_DISKPARTITION = "allowMultipleDirsUnderSameDiskPartition";
 
+    protected final static String TLS_CLIENT_AUTHENTICATION = "tlsClientAuthentication";
+    protected final static String TLS_KEYSTORE_TYPE = "tlsKeyStoreType";
+    protected final static String TLS_KEYSTORE = "tlsKeyStore";
+    protected final static String TLS_KEYSTORE_PASSWORD_PATH = "tlsKeyStorePasswordPath";
+    protected final static String TLS_TRUSTSTORE_TYPE = "tlsTrustStoreType";
+    protected final static String TLS_TRUSTSTORE = "tlsTrustStore";
+    protected final static String TLS_TRUSTSTORE_PASSWORD_PATH = "tlsTrustStorePasswordPath";
+
     /**
      * Construct a default configuration object
      */
@@ -2052,6 +2060,121 @@ public class ServerConfiguration extends AbstractConfiguration {
     }
 
     /**
+     * Get the truststore type for client. Default is JKS.
+     * 
+     * @return
+     */
+    public String getTLSTrustStoreType() {
+        return getString(TLS_TRUSTSTORE_TYPE, "JKS");
+    }
+
+    /**
+     * Set the keystore type for client.
+     * 
+     * @return
+     */
+    public ServerConfiguration setTLSKeyStoreType(String arg) {
+        setProperty(TLS_KEYSTORE_TYPE, arg);
+        return this;
+    }
+
+    /**
+     * Get the keystore path for the client.
+     * 
+     * @return
+     */
+    public String getTLSKeyStore() {
+        return getString(TLS_KEYSTORE, null);
+    }
+
+    /**
+     * Set the keystore path for the client.
+     * 
+     * @return
+     */
+    public ServerConfiguration setTLSKeyStore(String arg) {
+        setProperty(TLS_KEYSTORE, arg);
+        return this;
+    }
+
+    /**
+     * Get the path to file containing keystore password if the client keystore is password protected. Default is null.
+     * 
+     * @return
+     */
+    public String getTLSKeyStorePasswordPath() {
+        return getString(TLS_KEYSTORE_PASSWORD_PATH, null);
+    }
+
+    /**
+     * Set the path to file containing keystore password, if the client keystore is password protected.
+     * 
+     * @return
+     */
+    public ServerConfiguration setTLSKeyStorePasswordPath(String arg) {
+        setProperty(TLS_KEYSTORE_PASSWORD_PATH, arg);
+        return this;
+    }
+
+    /**
+     * Get the keystore type for client. Default is JKS.
+     * 
+     * @return
+     */
+    public String getTLSKeyStoreType() {
+        return getString(TLS_KEYSTORE_TYPE, "JKS");
+    }
+
+    /**
+     * Set the truststore type for client.
+     * 
+     * @return
+     */
+    public ServerConfiguration setTLSTrustStoreType(String arg) {
+        setProperty(TLS_TRUSTSTORE_TYPE, arg);
+        return this;
+    }
+
+    /**
+     * Get the truststore path for the client.
+     * 
+     * @return
+     */
+    public String getTLSTrustStore() {
+        return getString(TLS_TRUSTSTORE, null);
+    }
+
+    /**
+     * Set the truststore path for the client.
+     * 
+     * @return
+     */
+    public ServerConfiguration setTLSTrustStore(String arg) {
+        setProperty(TLS_TRUSTSTORE, arg);
+        return this;
+    }
+
+    /**
+     * Get the path to file containing truststore password if the client truststore is password protected. Default is
+     * null.
+     * 
+     * @return
+     */
+    public String getTLSTrustStorePasswordPath() {
+        return getString(TLS_TRUSTSTORE_PASSWORD_PATH, null);
+    }
+
+    /**
+     * Set the path to file containing truststore password, if the client truststore is password protected.
+     * 
+     * @return
+     */
+    public ServerConfiguration setTLSTrustStorePasswordPath(String arg) {
+        setProperty(TLS_TRUSTSTORE_PASSWORD_PATH, arg);
+        return this;
+    }
+
+    /**
      * Gets the minimum safe Usable size to be available in index directory for Bookie to create Index File while replaying 
      * journal at the time of Bookie Start in Readonly Mode (in bytes)
      * 
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/AuthHandler.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/AuthHandler.java
index 6a4dff7..409fe4b 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/AuthHandler.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/AuthHandler.java
@@ -124,7 +124,10 @@ class AuthHandler {
                         .getPayload()
                         .toByteArray();
                     authProvider.process(AuthToken.wrap(payload),
-                                         new AuthResponseCallback(req, ctx.channel(), authProviderFactory.getPluginName()));
+                            new AuthResponseCallback(req, ctx.channel(), authProviderFactory.getPluginName()));
+                } else if (req.getHeader().getOperation() == BookkeeperProtocol.OperationType.START_TLS
+                        && req.hasStartTLSRequest()) {
+                    super.channelRead(ctx, msg);
                 } else {
                     BookkeeperProtocol.Response.Builder builder
                         = BookkeeperProtocol.Response.newBuilder()
@@ -140,11 +143,9 @@ class AuthHandler {
         }
 
         private boolean checkAuthPlugin(AuthMessage am, final Channel src) {
-            if (!am.hasAuthPluginName()
-                || !am.getAuthPluginName().equals(authProviderFactory.getPluginName())) {
-                LOG.error("Received message from incompatible auth plugin. Local = {},"
-                          + " Remote = {}, Channel = {}",
-                          authProviderFactory.getPluginName(), am.getAuthPluginName());
+            if (!am.hasAuthPluginName() || !am.getAuthPluginName().equals(authProviderFactory.getPluginName())) {
+                LOG.error("Received message from incompatible auth plugin. Local = {}," + " Remote = {}, Channel = {}",
+                        authProviderFactory.getPluginName(), am.getAuthPluginName());
                 return false;
             }
             return true;
@@ -165,14 +166,9 @@ class AuthHandler {
                     channel.close();
                     return;
                 }
-                AuthMessage message =
-                    AuthMessage
-                        .newBuilder()
-                        .setAuthPluginName(req.authMessage.getAuthPluginName())
-                        .setPayload(ByteString.copyFrom(newam.getData()))
-                        .build();
-                channel.writeAndFlush(new BookieProtocol.AuthResponse(req.getProtocolVersion(),
-                                                              message));
+                AuthMessage message = AuthMessage.newBuilder().setAuthPluginName(req.authMessage.getAuthPluginName())
+                        .setPayload(ByteString.copyFrom(newam.getData())).build();
+                channel.writeAndFlush(new BookieProtocol.AuthResponse(req.getProtocolVersion(), message));
             }
         }
 
@@ -188,9 +184,8 @@ class AuthHandler {
             }
 
             public void operationComplete(int rc, AuthToken newam) {
-                BookkeeperProtocol.Response.Builder builder
-                    = BookkeeperProtocol.Response.newBuilder()
-                    .setHeader(req.getHeader());
+                BookkeeperProtocol.Response.Builder builder = BookkeeperProtocol.Response.newBuilder()
+                        .setHeader(req.getHeader());
 
                 if (rc != BKException.Code.OK) {
                     LOG.error("Error processing auth message, closing connection");
@@ -200,14 +195,9 @@ class AuthHandler {
                     channel.close();
                     return;
                 } else {
-                    AuthMessage message =
-                        AuthMessage
-                            .newBuilder()
-                            .setAuthPluginName(pluginName)
-                            .setPayload(ByteString.copyFrom(newam.getData()))
-                            .build();
-                    builder.setStatus(BookkeeperProtocol.StatusCode.EOK)
-                        .setAuthResponse(message);
+                    AuthMessage message = AuthMessage.newBuilder().setAuthPluginName(pluginName)
+                            .setPayload(ByteString.copyFrom(newam.getData())).build();
+                    builder.setStatus(BookkeeperProtocol.StatusCode.EOK).setAuthResponse(message);
                     channel.writeAndFlush(builder.build());
                 }
             }
@@ -236,9 +226,12 @@ class AuthHandler {
         final Queue<Object> waitingForAuth = new ConcurrentLinkedQueue<>();
         final ClientConnectionPeer connectionPeer;
 
-        ClientSideHandler(ClientAuthProvider.Factory authProviderFactory,
-                          AtomicLong transactionIdGenerator,
-                          ClientConnectionPeer connectionPeer) {
+        public ClientAuthProvider getAuthProvider() {
+            return authProvider;
+        }
+
+        ClientSideHandler(ClientAuthProvider.Factory authProviderFactory, AtomicLong transactionIdGenerator,
+                ClientConnectionPeer connectionPeer) {
             this.authProviderFactory = authProviderFactory;
             this.transactionIdGenerator = transactionIdGenerator;
             this.connectionPeer = connectionPeer;
@@ -247,8 +240,7 @@ class AuthHandler {
 
         @Override
         public void channelActive(ChannelHandlerContext ctx) throws Exception {
-            authProvider = authProviderFactory.newProvider(connectionPeer,
-                        new AuthHandshakeCompleteCallback(ctx));
+            authProvider = authProviderFactory.newProvider(connectionPeer, new AuthHandshakeCompleteCallback(ctx));
             authProvider.init(new AuthRequestCallback(ctx, authProviderFactory.getPluginName()));
 
             super.channelActive(ctx);
@@ -270,28 +262,40 @@ class AuthHandler {
                 super.channelRead(ctx, msg);
             } else if (msg instanceof BookkeeperProtocol.Response) {
                 BookkeeperProtocol.Response resp = (BookkeeperProtocol.Response) msg;
-                if (resp.getHeader().getOperation() == BookkeeperProtocol.OperationType.AUTH) {
-                    if (resp.getStatus() != BookkeeperProtocol.StatusCode.EOK) {
-                        authenticationError(ctx, resp.getStatus().getNumber());
-                    } else {
-                        assert (resp.hasAuthResponse());
-                        BookkeeperProtocol.AuthMessage am = resp.getAuthResponse();
-                        if (AuthProviderFactoryFactory.AUTHENTICATION_DISABLED_PLUGIN_NAME.equals(am.getAuthPluginName())){
-                            SocketAddress remote  = ctx.channel().remoteAddress();
-                            LOG.info("Authentication is not enabled."
-                                + "Considering this client {0} authenticated", remote);
-                            AuthHandshakeCompleteCallback authHandshakeCompleteCallback
-                                = new AuthHandshakeCompleteCallback(ctx);
-                            authHandshakeCompleteCallback.operationComplete(BKException.Code.OK, null);
-                            return;
+                if (null == resp.getHeader().getOperation()) {
+                    LOG.info("dropping received malformed message {} from bookie {}", msg, ctx.channel());
+                    // drop the message without header
+                } else {
+                    switch (resp.getHeader().getOperation()) {
+                    case START_TLS:
+                        super.channelRead(ctx, msg);
+                        break;
+                    case AUTH:
+                        if (resp.getStatus() != BookkeeperProtocol.StatusCode.EOK) {
+                            authenticationError(ctx, resp.getStatus().getNumber());
+                        } else {
+                            assert (resp.hasAuthResponse());
+                            BookkeeperProtocol.AuthMessage am = resp.getAuthResponse();
+                            if (AuthProviderFactoryFactory.AUTHENTICATION_DISABLED_PLUGIN_NAME.equals(am.getAuthPluginName())){
+                                SocketAddress remote = ctx.channel().remoteAddress();
+                                LOG.info("Authentication is not enabled."
+                                    + "Considering this client {0} authenticated", remote);
+                                AuthHandshakeCompleteCallback authHandshakeCompleteCallback
+                                    = new AuthHandshakeCompleteCallback(ctx);
+                                authHandshakeCompleteCallback.operationComplete(BKException.Code.OK, null);
+                                return;
+                            }
+                            byte[] payload = am.getPayload().toByteArray();
+                            authProvider.process(AuthToken.wrap(payload), new AuthRequestCallback(ctx,
+                                authProviderFactory.getPluginName()));
                         }
-                        byte[] payload = am.getPayload().toByteArray();
-                        authProvider.process(AuthToken.wrap(payload), new AuthRequestCallback(ctx,
-                            authProviderFactory.getPluginName()));
+                        break;
+                    default:
+                        LOG.warn("dropping received message {} from bookie {}", msg, ctx.channel());
+                        // else just drop the message,
+                        // we're not authenticated so nothing should be coming through
+                        break;
                     }
-                } else {
-                    // else just drop the message,
-                    // we're not authenticated so nothing should be coming through
                 }
             }
         }
@@ -301,12 +305,15 @@ class AuthHandler {
             synchronized (this) {
                 if (authenticated) {
                     super.write(ctx, msg, promise);
+                    super.flush(ctx);
                 } else if (msg instanceof BookkeeperProtocol.Request) {
                     // let auth messages through, queue the rest
                     BookkeeperProtocol.Request req = (BookkeeperProtocol.Request) msg;
                     if (req.getHeader().getOperation()
-                            == BookkeeperProtocol.OperationType.AUTH) {
+                            == BookkeeperProtocol.OperationType.AUTH
+                        || req.getHeader().getOperation() == BookkeeperProtocol.OperationType.START_TLS) {
                         super.write(ctx, msg, promise);
+                        super.flush(ctx);
                     } else {
                         waitingForAuth.add(msg);
                     }
@@ -315,10 +322,13 @@ class AuthHandler {
                     BookieProtocol.Request req = (BookieProtocol.Request)msg;
                     if (BookkeeperProtocol.OperationType.AUTH.getNumber() == req.getOpCode()) {
                         super.write(ctx, msg, promise);
+                        super.flush(ctx);
                     } else {
                         waitingForAuth.add(msg);
                     }
-                } // else just drop
+                } else {
+                    LOG.info("dropping write of message {}", msg);
+                }
             }
         }
 
@@ -347,21 +357,14 @@ class AuthHandler {
                     authenticationError(ctx, rc);
                     return;
                 }
-                AuthMessage message = AuthMessage
-                    .newBuilder()
-                    .setAuthPluginName(pluginName)
-                    .setPayload(ByteString.copyFrom(newam.getData()))
-                    .build();
-
-                BookkeeperProtocol.BKPacketHeader header
-                    = BookkeeperProtocol.BKPacketHeader.newBuilder()
-                    .setVersion(BookkeeperProtocol.ProtocolVersion.VERSION_THREE)
-                    .setOperation(BookkeeperProtocol.OperationType.AUTH)
-                    .setTxnId(newTxnId()).build();
-                BookkeeperProtocol.Request.Builder builder
-                    = BookkeeperProtocol.Request.newBuilder()
-                    .setHeader(header)
-                    .setAuthRequest(message);
+                AuthMessage message = AuthMessage.newBuilder().setAuthPluginName(pluginName)
+                        .setPayload(ByteString.copyFrom(newam.getData())).build();
+
+                BookkeeperProtocol.BKPacketHeader header = BookkeeperProtocol.BKPacketHeader.newBuilder()
+                        .setVersion(BookkeeperProtocol.ProtocolVersion.VERSION_THREE)
+                        .setOperation(BookkeeperProtocol.OperationType.AUTH).setTxnId(newTxnId()).build();
+                BookkeeperProtocol.Request.Builder builder = BookkeeperProtocol.Request.newBuilder().setHeader(header)
+                        .setAuthRequest(message);
 
                 channel.writeAndFlush(builder.build());
             }
@@ -369,6 +372,7 @@ class AuthHandler {
 
         class AuthHandshakeCompleteCallback implements AuthCallbacks.GenericCallback<Void> {
             ChannelHandlerContext ctx;
+
             AuthHandshakeCompleteCallback(ChannelHandlerContext ctx) {
                 this.ctx = ctx;
             }
@@ -385,10 +389,8 @@ class AuthHandler {
                         }
                     }
                 } else {
+                    LOG.warn("Client authentication failed");
                     authenticationError(ctx, rc);
-                    if (LOG.isDebugEnabled()) {
-                        LOG.debug("Authentication failed on server side");
-                    }
                 }
             }
         }
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieClient.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieClient.java
index 4cbd814..d763f57 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieClient.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieClient.java
@@ -41,9 +41,11 @@ import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.GetBookieInfoCall
 import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.ReadEntryCallback;
 import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.ReadLacCallback;
 import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.WriteLacCallback;
-import org.apache.bookkeeper.stats.NullStatsLogger;
 import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.WriteCallback;
+import org.apache.bookkeeper.stats.NullStatsLogger;
 import org.apache.bookkeeper.stats.StatsLogger;
+import org.apache.bookkeeper.tls.SecurityException;
+import org.apache.bookkeeper.tls.SecurityHandlerFactory;
 import org.apache.bookkeeper.util.OrderedSafeExecutor;
 import org.apache.bookkeeper.util.SafeRunnable;
 import org.slf4j.Logger;
@@ -139,9 +141,10 @@ public class BookieClient implements PerChannelBookieClientFactory {
     }
 
     @Override
-    public PerChannelBookieClient create(BookieSocketAddress address, PerChannelBookieClientPool pcbcPool) {
+    public PerChannelBookieClient create(BookieSocketAddress address, PerChannelBookieClientPool pcbcPool,
+            SecurityHandlerFactory shFactory) throws SecurityException {
         return new PerChannelBookieClient(conf, executor, eventLoopGroup, address, requestTimer, statsLogger,
-                authProviderFactory, registry, pcbcPool);
+                authProviderFactory, registry, pcbcPool, shFactory);
     }
 
     private PerChannelBookieClientPool lookupClient(BookieSocketAddress addr, Object key) {
@@ -153,7 +156,7 @@ public class BookieClient implements PerChannelBookieClientFactory {
                     return null;
                 }
                 PerChannelBookieClientPool newClientPool =
-                    new DefaultPerChannelBookieClientPool(this, addr, numConnectionsPerBookie);
+                    new DefaultPerChannelBookieClientPool(conf, this, addr, numConnectionsPerBookie);
                 PerChannelBookieClientPool oldClientPool = channels.putIfAbsent(addr, newClientPool);
                 if (null == oldClientPool) {
                     clientPool = newClientPool;
@@ -163,6 +166,9 @@ public class BookieClient implements PerChannelBookieClientFactory {
                     clientPool = oldClientPool;
                     newClientPool.close(false);
                 }
+            } catch (SecurityException e) {
+                LOG.error("Security Exception in creating new default PCBC pool: ", e);
+                return null;
             } finally {
                 closeLock.readLock().unlock();
             }
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieNettyServer.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieNettyServer.java
index 7dd8f6e..17fbbcb 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieNettyServer.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieNettyServer.java
@@ -62,11 +62,17 @@ import io.netty.channel.socket.SocketChannel;
 import io.netty.channel.socket.nio.NioServerSocketChannel;
 import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
 import io.netty.handler.codec.LengthFieldPrepender;
+import io.netty.handler.ssl.SslHandler;
 
 import com.google.common.annotations.VisibleForTesting;
 import java.net.SocketAddress;
 import java.util.Collection;
 import java.util.Collections;
+import java.security.cert.Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.net.ssl.SSLPeerUnverifiedException;
 import org.apache.bookkeeper.auth.BookKeeperPrincipal;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import org.apache.bookkeeper.net.BookieSocketAddress;
@@ -89,6 +95,7 @@ class BookieNettyServer {
     volatile boolean suspended = false;
     ChannelGroup allChannels;
     final BookieSocketAddress bookieAddress;
+    final InetSocketAddress bindAddress;
 
     final BookieAuthProvider.Factory authProviderFactory;
     final ExtensionRegistry registry = ExtensionRegistry.newInstance();
@@ -130,13 +137,11 @@ class BookieNettyServer {
         }
 
         bookieAddress = Bookie.getBookieAddress(conf);
-        InetSocketAddress bindAddress;
         if (conf.getListeningInterface() == null) {
             bindAddress = new InetSocketAddress(conf.getBookiePort());
         } else {
             bindAddress = bookieAddress.getSocketAddress();
         }
-        listenOn(bindAddress, bookieAddress);
     }
 
     public BookieNettyServer setRequestProcessor(RequestProcessor processor) {
@@ -179,8 +184,92 @@ class BookieNettyServer {
         }
     }
 
-    private void listenOn(InetSocketAddress address, BookieSocketAddress bookieAddress)
-            throws InterruptedException {
+    class BookieSideConnectionPeerContextHandler extends ChannelInboundHandlerAdapter {
+
+        final BookieConnectionPeer connectionPeer;
+        volatile Channel channel;
+        volatile BookKeeperPrincipal authorizedId = BookKeeperPrincipal.ANONYMOUS;
+
+        public BookieSideConnectionPeerContextHandler() {
+            this.connectionPeer = new BookieConnectionPeer() {
+                @Override
+                public SocketAddress getRemoteAddr() {
+                    Channel c = channel;
+                    if (c != null) {
+                        return c.remoteAddress();
+                    } else {
+                        return null;
+                    }
+                }
+
+                @Override
+                public Collection<Object> getProtocolPrincipals() {
+                    Channel c = channel;
+                    if (c == null) {
+                        return Collections.emptyList();
+                    } else {
+                        SslHandler ssl = c.pipeline().get(SslHandler.class);
+                        if (ssl == null) {
+                            return Collections.emptyList();
+                        }
+                        try {
+                            Certificate[] certificates = ssl.engine().getSession().getPeerCertificates();
+                            if (certificates == null) {
+                                return Collections.emptyList();
+                            }
+                            List<Object> result = new ArrayList<>();
+                            result.addAll(Arrays.asList(certificates));
+                            return result;
+                        } catch (SSLPeerUnverifiedException err) {
+                            return Collections.emptyList();
+                        }
+
+                    }
+                }
+
+                @Override
+                public void disconnect() {
+                    Channel c = channel;
+                    if (c != null) {
+                        c.close();
+                    }
+                    LOG.info("authplugin disconnected channel {}", channel);
+                }
+
+                @Override
+                public BookKeeperPrincipal getAuthorizedId() {
+                    return authorizedId;
+                }
+
+                @Override
+                public void setAuthorizedId(BookKeeperPrincipal principal) {
+                    LOG.info("connection {} authenticated as {}", channel, principal);
+                    authorizedId = principal;
+                }
+
+                @Override
+                public boolean isSecure() {
+                    Channel c = channel;
+                    if (c == null) {
+                        return false;
+                    } else {
+                        return c.pipeline().get("tls") != null;
+                    }
+                }
+            };
+        }
+
+        public BookieConnectionPeer getConnectionPeer() {
+            return connectionPeer;
+        }
+
+        @Override
+        public void channelActive(ChannelHandlerContext ctx) throws Exception {
+            channel = ctx.channel();
+        }
+    }
+
+    private void listenOn(InetSocketAddress address, BookieSocketAddress bookieAddress) throws InterruptedException {
         if (!conf.isDisableServerSocketBind()) {
             ServerBootstrap bootstrap = new ServerBootstrap();
             bootstrap.childOption(ChannelOption.ALLOCATOR, new PooledByteBufAllocator(true));
@@ -220,6 +309,7 @@ class BookieNettyServer {
                             ? new BookieRequestHandler(conf, requestProcessor, allChannels) : new RejectRequestHandler();
                     pipeline.addLast("bookieRequestHandler", requestHandler);
 
+                    pipeline.addLast("contextHandler", contextHandler);
                 }
             });
 
@@ -283,7 +373,8 @@ class BookieNettyServer {
         }
     }
 
-    void start() {
+    void start() throws InterruptedException {
+        listenOn(bindAddress, bookieAddress);
         isRunning.set(true);
     }
 
@@ -313,63 +404,6 @@ class BookieNettyServer {
         authProviderFactory.close();
     }
 
-    class BookieSideConnectionPeerContextHandler extends ChannelInboundHandlerAdapter {
-
-        final BookieConnectionPeer connectionPeer;
-        volatile Channel channel;
-        volatile BookKeeperPrincipal authorizedId = BookKeeperPrincipal.ANONYMOUS;
-
-        public BookieSideConnectionPeerContextHandler() {
-            this.connectionPeer = new BookieConnectionPeer() {
-                @Override
-                public SocketAddress getRemoteAddr() {
-                    Channel c = channel;
-                    if (c != null) {
-                        return c.remoteAddress();
-                    } else {
-                        return null;
-                    }
-                }
-
-                @Override
-                public Collection<Object> getProtocolPrincipals() {
-                    return Collections.emptyList();
-                }
-
-                @Override
-                public void disconnect() {
-                    Channel c = channel;
-                    if (c != null) {
-                        c.close();
-                    }
-                    LOG.info("authplugin disconnected channel {}", channel);
-                }
-
-                @Override
-                public BookKeeperPrincipal getAuthorizedId() {
-                    return authorizedId;
-                }
-
-                @Override
-                public void setAuthorizedId(BookKeeperPrincipal principal) {
-                    LOG.info("connection {} authenticated as {}", channel, principal);
-                    authorizedId = principal;
-                }
-
-            };
-        }
-
-        public BookieConnectionPeer getConnectionPeer() {
-            return connectionPeer;
-        }
-
-        @Override
-        public void channelActive(ChannelHandlerContext ctx) throws Exception {
-            channel = ctx.channel();
-        }
-
-    }
-
     private static class RejectRequestHandler extends ChannelInboundHandlerAdapter {
         @Override
         public void channelActive(ChannelHandlerContext ctx) throws Exception {
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieRequestHandler.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieRequestHandler.java
index b1bc081..1315dc9 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieRequestHandler.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieRequestHandler.java
@@ -48,7 +48,8 @@ class BookieRequestHandler extends ChannelInboundHandlerAdapter {
 
     @Override
     public void channelActive(ChannelHandlerContext ctx) throws Exception {
-        LOG.info("Channel connected: {}", ctx.channel());
+        LOG.info("Channel connected  {}", ctx.channel());
+        super.channelActive(ctx);
     }
 
     @Override
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieRequestProcessor.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieRequestProcessor.java
index 90a0524..8d719e6 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieRequestProcessor.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieRequestProcessor.java
@@ -23,6 +23,9 @@ package org.apache.bookkeeper.proto;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import com.google.protobuf.ByteString;
 import io.netty.channel.Channel;
+import io.netty.handler.ssl.SslHandler;
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.GenericFutureListener;
 import io.netty.util.HashedWheelTimer;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -34,6 +37,9 @@ import org.apache.bookkeeper.processor.RequestProcessor;
 import org.apache.bookkeeper.stats.Counter;
 import org.apache.bookkeeper.stats.OpStatsLogger;
 import org.apache.bookkeeper.stats.StatsLogger;
+import org.apache.bookkeeper.tls.SecurityException;
+import org.apache.bookkeeper.tls.SecurityHandlerFactory;
+import org.apache.bookkeeper.tls.SecurityHandlerFactory.NodeType;
 import org.apache.bookkeeper.util.OrderedSafeExecutor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -56,6 +62,7 @@ import static org.apache.bookkeeper.bookie.BookKeeperServerStats.READ_LAC_REQUES
 import static org.apache.bookkeeper.bookie.BookKeeperServerStats.READ_LAST_ENTRY_NOENTRY_ERROR;
 import static org.apache.bookkeeper.bookie.BookKeeperServerStats.WRITE_LAC;
 import static org.apache.bookkeeper.bookie.BookKeeperServerStats.READ_LAC;
+import static org.apache.bookkeeper.bookie.BookKeeperServerStats.WRITE_LAC;
 import static org.apache.bookkeeper.bookie.BookKeeperServerStats.GET_BOOKIE_INFO;
 import static org.apache.bookkeeper.bookie.BookKeeperServerStats.WRITE_LAC_REQUEST;
 
@@ -85,6 +92,11 @@ public class BookieRequestProcessor implements RequestProcessor {
     private final OrderedSafeExecutor writeThreadPool;
 
     /**
+     * TLS management
+     */
+    private final SecurityHandlerFactory shFactory;
+
+    /**
      * The threadpool used to execute all long poll requests issued to this server
      * after they are done waiting
      */
@@ -120,7 +132,7 @@ public class BookieRequestProcessor implements RequestProcessor {
     final OpStatsLogger channelWriteStats;
 
     public BookieRequestProcessor(ServerConfiguration serverCfg, Bookie bookie,
-                                  StatsLogger statsLogger) {
+            StatsLogger statsLogger, SecurityHandlerFactory shFactory) throws SecurityException {
         this.serverCfg = serverCfg;
         this.bookie = bookie;
         this.readThreadPool = createExecutor(this.serverCfg.getNumReadWorkerThreads(), "BookieReadThread-" + serverCfg.getBookiePort());
@@ -133,6 +145,10 @@ public class BookieRequestProcessor implements RequestProcessor {
             new ThreadFactoryBuilder().setNameFormat("BookieRequestTimer-%d").build(),
             this.serverCfg.getRequestTimerTickDurationMs(),
             TimeUnit.MILLISECONDS, this.serverCfg.getRequestTimerNumTicks());
+        this.shFactory = shFactory;
+        if (shFactory != null) {
+            shFactory.init(NodeType.Server, serverCfg);
+        }
 
         // Expose Stats
         this.statsEnabled = serverCfg.isStatisticsEnabled();
@@ -214,6 +230,9 @@ public class BookieRequestProcessor implements RequestProcessor {
                 case GET_BOOKIE_INFO:
                     processGetBookieInfoRequestV3(r,c);
                     break;
+                case START_TLS:
+                    processStartTLSRequestV3(r, c);
+                    break;
                 default:
                     LOG.info("Unknown operation type {}", header.getOperation());
                     BookkeeperProtocol.Response.Builder response =
@@ -246,6 +265,24 @@ public class BookieRequestProcessor implements RequestProcessor {
         }
     }
 
+     private void processWriteLacRequestV3(final BookkeeperProtocol.Request r, final Channel c) {
+        WriteLacProcessorV3 writeLac = new WriteLacProcessorV3(r, c, this);
+        if (null == writeThreadPool) {
+            writeLac.run();
+        } else {
+            writeThreadPool.submitOrdered(r.getAddRequest().getLedgerId(), writeLac);
+        }
+    }
+
+    private void processReadLacRequestV3(final BookkeeperProtocol.Request r, final Channel c) {
+        ReadLacProcessorV3 readLac = new ReadLacProcessorV3(r, c, this);
+        if (null == readThreadPool) {
+            readLac.run();
+        } else {
+            readThreadPool.submitOrdered(r.getAddRequest().getLedgerId(), readLac);
+        }
+    }
+
     private void processAddRequestV3(final BookkeeperProtocol.Request r, final Channel c) {
         WriteEntryProcessorV3 write = new WriteEntryProcessorV3(r, c, this);
         if (null == writeThreadPool) {
@@ -284,21 +321,46 @@ public class BookieRequestProcessor implements RequestProcessor {
         }
     }
 
-    private void processWriteLacRequestV3(final BookkeeperProtocol.Request r, final Channel c) {
-        WriteLacProcessorV3 writeLac = new WriteLacProcessorV3(r, c, this);
-        if (null == writeThreadPool) {
-            writeLac.run();
+    private void processStartTLSRequestV3(final BookkeeperProtocol.Request r, final Channel c) {
+        BookkeeperProtocol.Response.Builder response = BookkeeperProtocol.Response.newBuilder();
+        BookkeeperProtocol.BKPacketHeader.Builder header = BookkeeperProtocol.BKPacketHeader.newBuilder();
+        header.setVersion(BookkeeperProtocol.ProtocolVersion.VERSION_THREE);
+        header.setOperation(r.getHeader().getOperation());
+        header.setTxnId(r.getHeader().getTxnId());
+        response.setHeader(header.build());
+        if (shFactory == null) {
+            LOG.error("Got StartTLS request but TLS not configured");
+            response.setStatus(BookkeeperProtocol.StatusCode.EBADREQ);
+            c.writeAndFlush(response.build());
         } else {
-            writeThreadPool.submit(writeLac);
-        }
-    }
+            // there is no need to execute in a different thread as this operation is light
+            SslHandler sslHandler = shFactory.newTLSHandler();
+            c.pipeline().addFirst("tls", sslHandler);
 
-    private void processReadLacRequestV3(final BookkeeperProtocol.Request r, final Channel c) {
-        ReadLacProcessorV3 readLac = new ReadLacProcessorV3(r, c, this);
-        if (null == readThreadPool) {
-            readLac.run();
-        } else {
-            readThreadPool.submit(readLac);
+            response.setStatus(BookkeeperProtocol.StatusCode.EOK);
+            BookkeeperProtocol.StartTLSResponse.Builder builder = BookkeeperProtocol.StartTLSResponse.newBuilder();
+            response.setStartTLSResponse(builder.build());
+            sslHandler.handshakeFuture().addListener(new GenericFutureListener<Future<Channel>>() {
+                @Override
+                public void operationComplete(Future<Channel> future) throws Exception {
+                    // notify the AuthPlugin the completion of the handshake, even in case of failure
+                    AuthHandler.ServerSideHandler authHandler = c.pipeline()
+                            .get(AuthHandler.ServerSideHandler.class);
+                    authHandler.authProvider.onProtocolUpgrade();
+                    if (future.isSuccess()) {
+                        LOG.info("Session is protected by: {}", sslHandler.engine().getSession().getCipherSuite());
+                    } else {
+                        LOG.error("TLS Handshake failure: {}", future.cause());
+                        BookkeeperProtocol.Response.Builder errResponse = BookkeeperProtocol.Response.newBuilder()
+                                .setHeader(r.getHeader()).setStatus(BookkeeperProtocol.StatusCode.EIO);
+                        c.writeAndFlush(errResponse.build());
+                        if (statsEnabled) {
+                            bkStats.getOpStats(BKStats.STATS_UNKNOWN).incrementFailedOps();
+                        }
+                    }
+                }
+            });
+            c.writeAndFlush(response.build());
         }
     }
 
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieServer.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieServer.java
index d764126..bda022c 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieServer.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieServer.java
@@ -41,6 +41,9 @@ import org.apache.bookkeeper.replication.ReplicationException.UnavailableExcepti
 import org.apache.bookkeeper.stats.NullStatsLogger;
 import org.apache.bookkeeper.stats.StatsLogger;
 import org.apache.bookkeeper.stats.StatsProvider;
+import org.apache.bookkeeper.tls.SecurityException;
+import org.apache.bookkeeper.tls.SecurityHandlerFactory;
+import org.apache.bookkeeper.tls.SecurityProviderFactoryFactory;
 import org.apache.bookkeeper.util.ReflectionUtils;
 import org.apache.commons.cli.BasicParser;
 import org.apache.commons.cli.CommandLine;
@@ -83,13 +86,13 @@ public class BookieServer {
 
     public BookieServer(ServerConfiguration conf) throws IOException,
             KeeperException, InterruptedException, BookieException,
-            UnavailableException, CompatibilityException {
+            UnavailableException, CompatibilityException, SecurityException {
         this(conf, NullStatsLogger.INSTANCE);
     }
 
     public BookieServer(ServerConfiguration conf, StatsLogger statsLogger)
             throws IOException, KeeperException, InterruptedException,
-            BookieException, UnavailableException, CompatibilityException {
+            BookieException, UnavailableException, CompatibilityException, SecurityException {
         this.conf = conf;
         this.statsLogger = statsLogger;
         this.nettyServer = new BookieNettyServer(this.conf, null);
@@ -100,9 +103,14 @@ public class BookieServer {
             this.nettyServer.shutdown();
             throw e;
         }
+        final SecurityHandlerFactory shFactory;
+
+        shFactory = SecurityProviderFactoryFactory
+                .getSecurityProviderFactory(conf.getTLSProviderFactoryClass());
         this.requestProcessor = new BookieRequestProcessor(conf, bookie,
-                statsLogger.scope(SERVER_SCOPE));
+                statsLogger.scope(SERVER_SCOPE), shFactory);
         this.nettyServer.setRequestProcessor(this.requestProcessor);
+
         isAutoRecoveryDaemonEnabled = conf.isAutoRecoveryDaemonEnabled();
         if (isAutoRecoveryDaemonEnabled) {
             this.autoRecoveryMain = new AutoRecoveryMain(conf, statsLogger.scope(REPLICATION_SCOPE));
@@ -116,7 +124,7 @@ public class BookieServer {
                 new Bookie(conf, statsLogger.scope(BOOKIE_SCOPE));
     }
 
-    public void start() throws IOException, UnavailableException {
+    public void start() throws IOException, UnavailableException, InterruptedException {
         this.bookie.start();
         // fail fast, when bookie startup is not successful
         if (!this.bookie.isRunning()) {
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookkeeperInternalCallbacks.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookkeeperInternalCallbacks.java
index 79790c4..ab160ce 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookkeeperInternalCallbacks.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookkeeperInternalCallbacks.java
@@ -79,6 +79,10 @@ public class BookkeeperInternalCallbacks {
         void writeLacComplete(int rc, long ledgerId, BookieSocketAddress addr, Object ctx);
     }
 
+    public interface StartTLSCallback {
+        void startTLSComplete(int rc, Object ctx);
+    }
+
     public interface GenericCallback<T> {
         void operationComplete(int rc, T result);
     }
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookkeeperProtocol.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookkeeperProtocol.java
index fb78b87..4f054c0 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookkeeperProtocol.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookkeeperProtocol.java
@@ -316,6 +316,10 @@ public final class BookkeeperProtocol {
      * <code>GET_BOOKIE_INFO = 8;</code>
      */
     GET_BOOKIE_INFO(7, 8),
+    /**
+     * <code>START_TLS = 9;</code>
+     */
+    START_TLS(8, 9),
     ;
 
     /**
@@ -354,6 +358,10 @@ public final class BookkeeperProtocol {
      * <code>GET_BOOKIE_INFO = 8;</code>
      */
     public static final int GET_BOOKIE_INFO_VALUE = 8;
+    /**
+     * <code>START_TLS = 9;</code>
+     */
+    public static final int START_TLS_VALUE = 9;
 
 
     public final int getNumber() { return value; }
@@ -368,6 +376,7 @@ public final class BookkeeperProtocol {
         case 6: return WRITE_LAC;
         case 7: return READ_LAC;
         case 8: return GET_BOOKIE_INFO;
+        case 9: return START_TLS;
         default: return null;
       }
     }
@@ -1130,6 +1139,19 @@ public final class BookkeeperProtocol {
      * <code>optional .GetBookieInfoRequest getBookieInfoRequest = 105;</code>
      */
     org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequestOrBuilder getGetBookieInfoRequestOrBuilder();
+
+    /**
+     * <code>optional .StartTLSRequest startTLSRequest = 106;</code>
+     */
+    boolean hasStartTLSRequest();
+    /**
+     * <code>optional .StartTLSRequest startTLSRequest = 106;</code>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest getStartTLSRequest();
+    /**
+     * <code>optional .StartTLSRequest startTLSRequest = 106;</code>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequestOrBuilder getStartTLSRequestOrBuilder();
   }
   /**
    * Protobuf type {@code Request}
@@ -1274,6 +1296,19 @@ public final class BookkeeperProtocol {
               bitField0_ |= 0x00000040;
               break;
             }
+            case 850: {
+              org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.Builder subBuilder = null;
+              if (((bitField0_ & 0x00000080) == 0x00000080)) {
+                subBuilder = startTLSRequest_.toBuilder();
+              }
+              startTLSRequest_ = input.readMessage(org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.PARSER, extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(startTLSRequest_);
+                startTLSRequest_ = subBuilder.buildPartial();
+              }
+              bitField0_ |= 0x00000080;
+              break;
+            }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -1473,6 +1508,27 @@ public final class BookkeeperProtocol {
       return getBookieInfoRequest_;
     }
 
+    public static final int STARTTLSREQUEST_FIELD_NUMBER = 106;
+    private org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest startTLSRequest_;
+    /**
+     * <code>optional .StartTLSRequest startTLSRequest = 106;</code>
+     */
+    public boolean hasStartTLSRequest() {
+      return ((bitField0_ & 0x00000080) == 0x00000080);
+    }
+    /**
+     * <code>optional .StartTLSRequest startTLSRequest = 106;</code>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest getStartTLSRequest() {
+      return startTLSRequest_;
+    }
+    /**
+     * <code>optional .StartTLSRequest startTLSRequest = 106;</code>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequestOrBuilder getStartTLSRequestOrBuilder() {
+      return startTLSRequest_;
+    }
+
     private void initFields() {
       header_ = org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.getDefaultInstance();
       readRequest_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadRequest.getDefaultInstance();
@@ -1481,6 +1537,7 @@ public final class BookkeeperProtocol {
       writeLacRequest_ = org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest.getDefaultInstance();
       readLacRequest_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest.getDefaultInstance();
       getBookieInfoRequest_ = org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest.getDefaultInstance();
+      startTLSRequest_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.getDefaultInstance();
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
@@ -1554,6 +1611,9 @@ public final class BookkeeperProtocol {
       if (((bitField0_ & 0x00000040) == 0x00000040)) {
         output.writeMessage(105, getBookieInfoRequest_);
       }
+      if (((bitField0_ & 0x00000080) == 0x00000080)) {
+        output.writeMessage(106, startTLSRequest_);
+      }
       getUnknownFields().writeTo(output);
     }
 
@@ -1591,6 +1651,10 @@ public final class BookkeeperProtocol {
         size += com.google.protobuf.CodedOutputStream
           .computeMessageSize(105, getBookieInfoRequest_);
       }
+      if (((bitField0_ & 0x00000080) == 0x00000080)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(106, startTLSRequest_);
+      }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
       return size;
@@ -1707,6 +1771,7 @@ public final class BookkeeperProtocol {
           getWriteLacRequestFieldBuilder();
           getReadLacRequestFieldBuilder();
           getGetBookieInfoRequestFieldBuilder();
+          getStartTLSRequestFieldBuilder();
         }
       }
       private static Builder create() {
@@ -1757,6 +1822,12 @@ public final class BookkeeperProtocol {
           getBookieInfoRequestBuilder_.clear();
         }
         bitField0_ = (bitField0_ & ~0x00000040);
+        if (startTLSRequestBuilder_ == null) {
+          startTLSRequest_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.getDefaultInstance();
+        } else {
+          startTLSRequestBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000080);
         return this;
       }
 
@@ -1841,6 +1912,14 @@ public final class BookkeeperProtocol {
         } else {
           result.getBookieInfoRequest_ = getBookieInfoRequestBuilder_.build();
         }
+        if (((from_bitField0_ & 0x00000080) == 0x00000080)) {
+          to_bitField0_ |= 0x00000080;
+        }
+        if (startTLSRequestBuilder_ == null) {
+          result.startTLSRequest_ = startTLSRequest_;
+        } else {
+          result.startTLSRequest_ = startTLSRequestBuilder_.build();
+        }
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
@@ -1878,6 +1957,9 @@ public final class BookkeeperProtocol {
         if (other.hasGetBookieInfoRequest()) {
           mergeGetBookieInfoRequest(other.getGetBookieInfoRequest());
         }
+        if (other.hasStartTLSRequest()) {
+          mergeStartTLSRequest(other.getStartTLSRequest());
+        }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
@@ -2791,6 +2873,122 @@ public final class BookkeeperProtocol {
         return getBookieInfoRequestBuilder_;
       }
 
+      private org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest startTLSRequest_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.getDefaultInstance();
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest, org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequestOrBuilder> startTLSRequestBuilder_;
+      /**
+       * <code>optional .StartTLSRequest startTLSRequest = 106;</code>
+       */
+      public boolean hasStartTLSRequest() {
+        return ((bitField0_ & 0x00000080) == 0x00000080);
+      }
+      /**
+       * <code>optional .StartTLSRequest startTLSRequest = 106;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest getStartTLSRequest() {
+        if (startTLSRequestBuilder_ == null) {
+          return startTLSRequest_;
+        } else {
+          return startTLSRequestBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>optional .StartTLSRequest startTLSRequest = 106;</code>
+       */
+      public Builder setStartTLSRequest(org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest value) {
+        if (startTLSRequestBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          startTLSRequest_ = value;
+          onChanged();
+        } else {
+          startTLSRequestBuilder_.setMessage(value);
+        }
+        bitField0_ |= 0x00000080;
+        return this;
+      }
+      /**
+       * <code>optional .StartTLSRequest startTLSRequest = 106;</code>
+       */
+      public Builder setStartTLSRequest(
+          org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.Builder builderForValue) {
+        if (startTLSRequestBuilder_ == null) {
+          startTLSRequest_ = builderForValue.build();
+          onChanged();
+        } else {
+          startTLSRequestBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000080;
+        return this;
+      }
+      /**
+       * <code>optional .StartTLSRequest startTLSRequest = 106;</code>
+       */
+      public Builder mergeStartTLSRequest(org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest value) {
+        if (startTLSRequestBuilder_ == null) {
+          if (((bitField0_ & 0x00000080) == 0x00000080) &&
+              startTLSRequest_ != org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.getDefaultInstance()) {
+            startTLSRequest_ =
+              org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.newBuilder(startTLSRequest_).mergeFrom(value).buildPartial();
+          } else {
+            startTLSRequest_ = value;
+          }
+          onChanged();
+        } else {
+          startTLSRequestBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00000080;
+        return this;
+      }
+      /**
+       * <code>optional .StartTLSRequest startTLSRequest = 106;</code>
+       */
+      public Builder clearStartTLSRequest() {
+        if (startTLSRequestBuilder_ == null) {
+          startTLSRequest_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.getDefaultInstance();
+          onChanged();
+        } else {
+          startTLSRequestBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000080);
+        return this;
+      }
+      /**
+       * <code>optional .StartTLSRequest startTLSRequest = 106;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.Builder getStartTLSRequestBuilder() {
+        bitField0_ |= 0x00000080;
+        onChanged();
+        return getStartTLSRequestFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>optional .StartTLSRequest startTLSRequest = 106;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequestOrBuilder getStartTLSRequestOrBuilder() {
+        if (startTLSRequestBuilder_ != null) {
+          return startTLSRequestBuilder_.getMessageOrBuilder();
+        } else {
+          return startTLSRequest_;
+        }
+      }
+      /**
+       * <code>optional .StartTLSRequest startTLSRequest = 106;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest, org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequestOrBuilder> 
+          getStartTLSRequestFieldBuilder() {
+        if (startTLSRequestBuilder_ == null) {
+          startTLSRequestBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest, org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequestOrBuilder>(
+                  getStartTLSRequest(),
+                  getParentForChildren(),
+                  isClean());
+          startTLSRequest_ = null;
+        }
+        return startTLSRequestBuilder_;
+      }
+
       // @@protoc_insertion_point(builder_scope:Request)
     }
 
@@ -2879,7 +3077,7 @@ public final class BookkeeperProtocol {
      * <code>optional int64 timeOut = 5;</code>
      *
      * <pre>
-     * Used as a timeout for the long polling request
+     * Used as a timeout (in milliseconds) for the long polling request
      * </pre>
      */
     boolean hasTimeOut();
@@ -2887,7 +3085,7 @@ public final class BookkeeperProtocol {
      * <code>optional int64 timeOut = 5;</code>
      *
      * <pre>
-     * Used as a timeout for the long polling request
+     * Used as a timeout (in milliseconds) for the long polling request
      * </pre>
      */
     long getTimeOut();
@@ -3207,7 +3405,7 @@ public final class BookkeeperProtocol {
      * <code>optional int64 timeOut = 5;</code>
      *
      * <pre>
-     * Used as a timeout for the long polling request
+     * Used as a timeout (in milliseconds) for the long polling request
      * </pre>
      */
     public boolean hasTimeOut() {
@@ -3217,7 +3415,7 @@ public final class BookkeeperProtocol {
      * <code>optional int64 timeOut = 5;</code>
      *
      * <pre>
-     * Used as a timeout for the long polling request
+     * Used as a timeout (in milliseconds) for the long polling request
      * </pre>
      */
     public long getTimeOut() {
@@ -3773,7 +3971,7 @@ public final class BookkeeperProtocol {
        * <code>optional int64 timeOut = 5;</code>
        *
        * <pre>
-       * Used as a timeout for the long polling request
+       * Used as a timeout (in milliseconds) for the long polling request
        * </pre>
        */
       public boolean hasTimeOut() {
@@ -3783,7 +3981,7 @@ public final class BookkeeperProtocol {
        * <code>optional int64 timeOut = 5;</code>
        *
        * <pre>
-       * Used as a timeout for the long polling request
+       * Used as a timeout (in milliseconds) for the long polling request
        * </pre>
        */
       public long getTimeOut() {
@@ -3793,7 +3991,7 @@ public final class BookkeeperProtocol {
        * <code>optional int64 timeOut = 5;</code>
        *
        * <pre>
-       * Used as a timeout for the long polling request
+       * Used as a timeout (in milliseconds) for the long polling request
        * </pre>
        */
       public Builder setTimeOut(long value) {
@@ -3806,7 +4004,7 @@ public final class BookkeeperProtocol {
        * <code>optional int64 timeOut = 5;</code>
        *
        * <pre>
-       * Used as a timeout for the long polling request
+       * Used as a timeout (in milliseconds) for the long polling request
        * </pre>
        */
       public Builder clearTimeOut() {
@@ -4656,66 +4854,30 @@ public final class BookkeeperProtocol {
     // @@protoc_insertion_point(class_scope:AddRequest)
   }
 
-  public interface WriteLacRequestOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:WriteLacRequest)
+  public interface StartTLSRequestOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:StartTLSRequest)
       com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <code>required int64 ledgerId = 1;</code>
-     */
-    boolean hasLedgerId();
-    /**
-     * <code>required int64 ledgerId = 1;</code>
-     */
-    long getLedgerId();
-
-    /**
-     * <code>required int64 lac = 2;</code>
-     */
-    boolean hasLac();
-    /**
-     * <code>required int64 lac = 2;</code>
-     */
-    long getLac();
-
-    /**
-     * <code>required bytes masterKey = 3;</code>
-     */
-    boolean hasMasterKey();
-    /**
-     * <code>required bytes masterKey = 3;</code>
-     */
-    com.google.protobuf.ByteString getMasterKey();
-
-    /**
-     * <code>required bytes body = 4;</code>
-     */
-    boolean hasBody();
-    /**
-     * <code>required bytes body = 4;</code>
-     */
-    com.google.protobuf.ByteString getBody();
   }
   /**
-   * Protobuf type {@code WriteLacRequest}
+   * Protobuf type {@code StartTLSRequest}
    */
-  public static final class WriteLacRequest extends
+  public static final class StartTLSRequest extends
       com.google.protobuf.GeneratedMessage implements
-      // @@protoc_insertion_point(message_implements:WriteLacRequest)
-      WriteLacRequestOrBuilder {
-    // Use WriteLacRequest.newBuilder() to construct.
-    private WriteLacRequest(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      // @@protoc_insertion_point(message_implements:StartTLSRequest)
+      StartTLSRequestOrBuilder {
+    // Use StartTLSRequest.newBuilder() to construct.
+    private StartTLSRequest(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
       super(builder);
       this.unknownFields = builder.getUnknownFields();
     }
-    private WriteLacRequest(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+    private StartTLSRequest(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
 
-    private static final WriteLacRequest defaultInstance;
-    public static WriteLacRequest getDefaultInstance() {
+    private static final StartTLSRequest defaultInstance;
+    public static StartTLSRequest getDefaultInstance() {
       return defaultInstance;
     }
 
-    public WriteLacRequest getDefaultInstanceForType() {
+    public StartTLSRequest getDefaultInstanceForType() {
       return defaultInstance;
     }
 
@@ -4725,12 +4887,11 @@ public final class BookkeeperProtocol {
         getUnknownFields() {
       return this.unknownFields;
     }
-    private WriteLacRequest(
+    private StartTLSRequest(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       initFields();
-      int mutable_bitField0_ = 0;
       com.google.protobuf.UnknownFieldSet.Builder unknownFields =
           com.google.protobuf.UnknownFieldSet.newBuilder();
       try {
@@ -4748,26 +4909,6 @@ public final class BookkeeperProtocol {
               }
               break;
             }
-            case 8: {
-              bitField0_ |= 0x00000001;
-              ledgerId_ = input.readInt64();
-              break;
-            }
-            case 16: {
-              bitField0_ |= 0x00000002;
-              lac_ = input.readInt64();
-              break;
-            }
-            case 26: {
-              bitField0_ |= 0x00000004;
-              masterKey_ = input.readBytes();
-              break;
-            }
-            case 34: {
-              bitField0_ |= 0x00000008;
-              body_ = input.readBytes();
-              break;
-            }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -4782,97 +4923,32 @@ public final class BookkeeperProtocol {
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacRequest_descriptor;
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_StartTLSRequest_descriptor;
     }
 
     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacRequest_fieldAccessorTable
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_StartTLSRequest_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest.class, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest.Builder.class);
+              org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.class, org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.Builder.class);
     }
 
-    public static com.google.protobuf.Parser<WriteLacRequest> PARSER =
-        new com.google.protobuf.AbstractParser<WriteLacRequest>() {
-      public WriteLacRequest parsePartialFrom(
+    public static com.google.protobuf.Parser<StartTLSRequest> PARSER =
+        new com.google.protobuf.AbstractParser<StartTLSRequest>() {
+      public StartTLSRequest parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new WriteLacRequest(input, extensionRegistry);
+        return new StartTLSRequest(input, extensionRegistry);
       }
     };
 
     @java.lang.Override
-    public com.google.protobuf.Parser<WriteLacRequest> getParserForType() {
+    public com.google.protobuf.Parser<StartTLSRequest> getParserForType() {
       return PARSER;
     }
 
-    private int bitField0_;
-    public static final int LEDGERID_FIELD_NUMBER = 1;
-    private long ledgerId_;
-    /**
-     * <code>required int64 ledgerId = 1;</code>
-     */
-    public boolean hasLedgerId() {
-      return ((bitField0_ & 0x00000001) == 0x00000001);
-    }
-    /**
-     * <code>required int64 ledgerId = 1;</code>
-     */
-    public long getLedgerId() {
-      return ledgerId_;
-    }
-
-    public static final int LAC_FIELD_NUMBER = 2;
-    private long lac_;
-    /**
-     * <code>required int64 lac = 2;</code>
-     */
-    public boolean hasLac() {
-      return ((bitField0_ & 0x00000002) == 0x00000002);
-    }
-    /**
-     * <code>required int64 lac = 2;</code>
-     */
-    public long getLac() {
-      return lac_;
-    }
-
-    public static final int MASTERKEY_FIELD_NUMBER = 3;
-    private com.google.protobuf.ByteString masterKey_;
-    /**
-     * <code>required bytes masterKey = 3;</code>
-     */
-    public boolean hasMasterKey() {
-      return ((bitField0_ & 0x00000004) == 0x00000004);
-    }
-    /**
-     * <code>required bytes masterKey = 3;</code>
-     */
-    public com.google.protobuf.ByteString getMasterKey() {
-      return masterKey_;
-    }
-
-    public static final int BODY_FIELD_NUMBER = 4;
-    private com.google.protobuf.ByteString body_;
-    /**
-     * <code>required bytes body = 4;</code>
-     */
-    public boolean hasBody() {
-      return ((bitField0_ & 0x00000008) == 0x00000008);
-    }
-    /**
-     * <code>required bytes body = 4;</code>
-     */
-    public com.google.protobuf.ByteString getBody() {
-      return body_;
-    }
-
     private void initFields() {
-      ledgerId_ = 0L;
-      lac_ = 0L;
-      masterKey_ = com.google.protobuf.ByteString.EMPTY;
-      body_ = com.google.protobuf.ByteString.EMPTY;
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
@@ -4880,22 +4956,6 @@ public final class BookkeeperProtocol {
       if (isInitialized == 1) return true;
       if (isInitialized == 0) return false;
 
-      if (!hasLedgerId()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      if (!hasLac()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      if (!hasMasterKey()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      if (!hasBody()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
       memoizedIsInitialized = 1;
       return true;
     }
@@ -4903,18 +4963,6 @@ public final class BookkeeperProtocol {
     public void writeTo(com.google.protobuf.CodedOutputStream output)
                         throws java.io.IOException {
       getSerializedSize();
-      if (((bitField0_ & 0x00000001) == 0x00000001)) {
-        output.writeInt64(1, ledgerId_);
-      }
-      if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        output.writeInt64(2, lac_);
-      }
-      if (((bitField0_ & 0x00000004) == 0x00000004)) {
-        output.writeBytes(3, masterKey_);
-      }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
-        output.writeBytes(4, body_);
-      }
       getUnknownFields().writeTo(output);
     }
 
@@ -4924,22 +4972,6 @@ public final class BookkeeperProtocol {
       if (size != -1) return size;
 
       size = 0;
-      if (((bitField0_ & 0x00000001) == 0x00000001)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(1, ledgerId_);
-      }
-      if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(2, lac_);
-      }
-      if (((bitField0_ & 0x00000004) == 0x00000004)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeBytesSize(3, masterKey_);
-      }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeBytesSize(4, body_);
-      }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
       return size;
@@ -4952,53 +4984,53 @@ public final class BookkeeperProtocol {
       return super.writeReplace();
     }
 
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseFrom(byte[] data)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseDelimitedFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseDelimitedFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -5007,7 +5039,7 @@ public final class BookkeeperProtocol {
 
     public static Builder newBuilder() { return Builder.create(); }
     public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest prototype) {
+    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest prototype) {
       return newBuilder().mergeFrom(prototype);
     }
     public Builder toBuilder() { return newBuilder(this); }
@@ -5019,25 +5051,25 @@ public final class BookkeeperProtocol {
       return builder;
     }
     /**
-     * Protobuf type {@code WriteLacRequest}
+     * Protobuf type {@code StartTLSRequest}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:WriteLacRequest)
-        org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequestOrBuilder {
+        // @@protoc_insertion_point(builder_implements:StartTLSRequest)
+        org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequestOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacRequest_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_StartTLSRequest_descriptor;
       }
 
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacRequest_fieldAccessorTable
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_StartTLSRequest_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest.class, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest.Builder.class);
+                org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.class, org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.Builder.class);
       }
 
-      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest.newBuilder()
+      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -5057,14 +5089,6 @@ public final class BookkeeperProtocol {
 
       public Builder clear() {
         super.clear();
-        ledgerId_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000001);
-        lac_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000002);
-        masterKey_ = com.google.protobuf.ByteString.EMPTY;
-        bitField0_ = (bitField0_ & ~0x00000004);
-        body_ = com.google.protobuf.ByteString.EMPTY;
-        bitField0_ = (bitField0_ & ~0x00000008);
         return this;
       }
 
@@ -5074,90 +5098,43 @@ public final class BookkeeperProtocol {
 
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacRequest_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_StartTLSRequest_descriptor;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest getDefaultInstanceForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest.getDefaultInstance();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest getDefaultInstanceForType() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.getDefaultInstance();
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest build() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest result = buildPartial();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest build() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
         return result;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest buildPartial() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest result = new org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest(this);
-        int from_bitField0_ = bitField0_;
-        int to_bitField0_ = 0;
-        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
-          to_bitField0_ |= 0x00000001;
-        }
-        result.ledgerId_ = ledgerId_;
-        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
-          to_bitField0_ |= 0x00000002;
-        }
-        result.lac_ = lac_;
-        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
-          to_bitField0_ |= 0x00000004;
-        }
-        result.masterKey_ = masterKey_;
-        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
-          to_bitField0_ |= 0x00000008;
-        }
-        result.body_ = body_;
-        result.bitField0_ = to_bitField0_;
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest buildPartial() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest result = new org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest(this);
         onBuilt();
         return result;
       }
 
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest) {
-          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest)other);
+        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest) {
+          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest other) {
-        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest.getDefaultInstance()) return this;
-        if (other.hasLedgerId()) {
-          setLedgerId(other.getLedgerId());
-        }
-        if (other.hasLac()) {
-          setLac(other.getLac());
-        }
-        if (other.hasMasterKey()) {
-          setMasterKey(other.getMasterKey());
-        }
-        if (other.hasBody()) {
-          setBody(other.getBody());
-        }
+      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest other) {
+        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest.getDefaultInstance()) return this;
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
 
       public final boolean isInitialized() {
-        if (!hasLedgerId()) {
-          
-          return false;
-        }
-        if (!hasLac()) {
-          
-          return false;
-        }
-        if (!hasMasterKey()) {
-          
-          return false;
-        }
-        if (!hasBody()) {
-          
-          return false;
-        }
         return true;
       }
 
@@ -5165,11 +5142,11 @@ public final class BookkeeperProtocol {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parsedMessage = null;
+        org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest) e.getUnfinishedMessage();
+          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSRequest) e.getUnfinishedMessage();
           throw e;
         } finally {
           if (parsedMessage != null) {
@@ -5178,155 +5155,20 @@ public final class BookkeeperProtocol {
         }
         return this;
       }
-      private int bitField0_;
 
-      private long ledgerId_ ;
-      /**
-       * <code>required int64 ledgerId = 1;</code>
-       */
-      public boolean hasLedgerId() {
-        return ((bitField0_ & 0x00000001) == 0x00000001);
-      }
-      /**
-       * <code>required int64 ledgerId = 1;</code>
-       */
-      public long getLedgerId() {
-        return ledgerId_;
-      }
-      /**
-       * <code>required int64 ledgerId = 1;</code>
-       */
-      public Builder setLedgerId(long value) {
-        bitField0_ |= 0x00000001;
-        ledgerId_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required int64 ledgerId = 1;</code>
-       */
-      public Builder clearLedgerId() {
-        bitField0_ = (bitField0_ & ~0x00000001);
-        ledgerId_ = 0L;
-        onChanged();
-        return this;
-      }
+      // @@protoc_insertion_point(builder_scope:StartTLSRequest)
+    }
 
-      private long lac_ ;
-      /**
-       * <code>required int64 lac = 2;</code>
-       */
-      public boolean hasLac() {
-        return ((bitField0_ & 0x00000002) == 0x00000002);
-      }
-      /**
-       * <code>required int64 lac = 2;</code>
-       */
-      public long getLac() {
-        return lac_;
-      }
-      /**
-       * <code>required int64 lac = 2;</code>
-       */
-      public Builder setLac(long value) {
-        bitField0_ |= 0x00000002;
-        lac_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required int64 lac = 2;</code>
-       */
-      public Builder clearLac() {
-        bitField0_ = (bitField0_ & ~0x00000002);
-        lac_ = 0L;
-        onChanged();
-        return this;
-      }
+    static {
+      defaultInstance = new StartTLSRequest(true);
+      defaultInstance.initFields();
+    }
 
-      private com.google.protobuf.ByteString masterKey_ = com.google.protobuf.ByteString.EMPTY;
-      /**
-       * <code>required bytes masterKey = 3;</code>
-       */
-      public boolean hasMasterKey() {
-        return ((bitField0_ & 0x00000004) == 0x00000004);
-      }
-      /**
-       * <code>required bytes masterKey = 3;</code>
-       */
-      public com.google.protobuf.ByteString getMasterKey() {
-        return masterKey_;
-      }
-      /**
-       * <code>required bytes masterKey = 3;</code>
-       */
-      public Builder setMasterKey(com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
+    // @@protoc_insertion_point(class_scope:StartTLSRequest)
   }
-  bitField0_ |= 0x00000004;
-        masterKey_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required bytes masterKey = 3;</code>
-       */
-      public Builder clearMasterKey() {
-        bitField0_ = (bitField0_ & ~0x00000004);
-        masterKey_ = getDefaultInstance().getMasterKey();
-        onChanged();
-        return this;
-      }
 
-      private com.google.protobuf.ByteString body_ = com.google.protobuf.ByteString.EMPTY;
-      /**
-       * <code>required bytes body = 4;</code>
-       */
-      public boolean hasBody() {
-        return ((bitField0_ & 0x00000008) == 0x00000008);
-      }
-      /**
-       * <code>required bytes body = 4;</code>
-       */
-      public com.google.protobuf.ByteString getBody() {
-        return body_;
-      }
-      /**
-       * <code>required bytes body = 4;</code>
-       */
-      public Builder setBody(com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000008;
-        body_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required bytes body = 4;</code>
-       */
-      public Builder clearBody() {
-        bitField0_ = (bitField0_ & ~0x00000008);
-        body_ = getDefaultInstance().getBody();
-        onChanged();
-        return this;
-      }
-
-      // @@protoc_insertion_point(builder_scope:WriteLacRequest)
-    }
-
-    static {
-      defaultInstance = new WriteLacRequest(true);
-      defaultInstance.initFields();
-    }
-
-    // @@protoc_insertion_point(class_scope:WriteLacRequest)
-  }
-
-  public interface ReadLacRequestOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:ReadLacRequest)
+  public interface WriteLacRequestOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:WriteLacRequest)
       com.google.protobuf.MessageOrBuilder {
 
     /**
@@ -5337,27 +5179,54 @@ public final class BookkeeperProtocol {
      * <code>required int64 ledgerId = 1;</code>
      */
     long getLedgerId();
+
+    /**
+     * <code>required int64 lac = 2;</code>
+     */
+    boolean hasLac();
+    /**
+     * <code>required int64 lac = 2;</code>
+     */
+    long getLac();
+
+    /**
+     * <code>required bytes masterKey = 3;</code>
+     */
+    boolean hasMasterKey();
+    /**
+     * <code>required bytes masterKey = 3;</code>
+     */
+    com.google.protobuf.ByteString getMasterKey();
+
+    /**
+     * <code>required bytes body = 4;</code>
+     */
+    boolean hasBody();
+    /**
+     * <code>required bytes body = 4;</code>
+     */
+    com.google.protobuf.ByteString getBody();
   }
   /**
-   * Protobuf type {@code ReadLacRequest}
+   * Protobuf type {@code WriteLacRequest}
    */
-  public static final class ReadLacRequest extends
+  public static final class WriteLacRequest extends
       com.google.protobuf.GeneratedMessage implements
-      // @@protoc_insertion_point(message_implements:ReadLacRequest)
-      ReadLacRequestOrBuilder {
-    // Use ReadLacRequest.newBuilder() to construct.
-    private ReadLacRequest(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      // @@protoc_insertion_point(message_implements:WriteLacRequest)
+      WriteLacRequestOrBuilder {
+    // Use WriteLacRequest.newBuilder() to construct.
+    private WriteLacRequest(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
       super(builder);
       this.unknownFields = builder.getUnknownFields();
     }
-    private ReadLacRequest(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+    private WriteLacRequest(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
 
-    private static final ReadLacRequest defaultInstance;
-    public static ReadLacRequest getDefaultInstance() {
+    private static final WriteLacRequest defaultInstance;
+    public static WriteLacRequest getDefaultInstance() {
       return defaultInstance;
     }
 
-    public ReadLacRequest getDefaultInstanceForType() {
+    public WriteLacRequest getDefaultInstanceForType() {
       return defaultInstance;
     }
 
@@ -5367,7 +5236,7 @@ public final class BookkeeperProtocol {
         getUnknownFields() {
       return this.unknownFields;
     }
-    private ReadLacRequest(
+    private WriteLacRequest(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -5395,6 +5264,21 @@ public final class BookkeeperProtocol {
               ledgerId_ = input.readInt64();
               break;
             }
+            case 16: {
+              bitField0_ |= 0x00000002;
+              lac_ = input.readInt64();
+              break;
+            }
+            case 26: {
+              bitField0_ |= 0x00000004;
+              masterKey_ = input.readBytes();
+              break;
+            }
+            case 34: {
+              bitField0_ |= 0x00000008;
+              body_ = input.readBytes();
+              break;
+            }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -5409,28 +5293,28 @@ public final class BookkeeperProtocol {
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacRequest_descriptor;
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacRequest_descriptor;
     }
 
     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacRequest_fieldAccessorTable
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacRequest_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest.class, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest.Builder.class);
+              org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest.class, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest.Builder.class);
     }
 
-    public static com.google.protobuf.Parser<ReadLacRequest> PARSER =
-        new com.google.protobuf.AbstractParser<ReadLacRequest>() {
-      public ReadLacRequest parsePartialFrom(
+    public static com.google.protobuf.Parser<WriteLacRequest> PARSER =
+        new com.google.protobuf.AbstractParser<WriteLacRequest>() {
+      public WriteLacRequest parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new ReadLacRequest(input, extensionRegistry);
+        return new WriteLacRequest(input, extensionRegistry);
       }
     };
 
     @java.lang.Override
-    public com.google.protobuf.Parser<ReadLacRequest> getParserForType() {
+    public com.google.protobuf.Parser<WriteLacRequest> getParserForType() {
       return PARSER;
     }
 
@@ -5450,8 +5334,56 @@ public final class BookkeeperProtocol {
       return ledgerId_;
     }
 
+    public static final int LAC_FIELD_NUMBER = 2;
+    private long lac_;
+    /**
+     * <code>required int64 lac = 2;</code>
+     */
+    public boolean hasLac() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>required int64 lac = 2;</code>
+     */
+    public long getLac() {
+      return lac_;
+    }
+
+    public static final int MASTERKEY_FIELD_NUMBER = 3;
+    private com.google.protobuf.ByteString masterKey_;
+    /**
+     * <code>required bytes masterKey = 3;</code>
+     */
+    public boolean hasMasterKey() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>required bytes masterKey = 3;</code>
+     */
+    public com.google.protobuf.ByteString getMasterKey() {
+      return masterKey_;
+    }
+
+    public static final int BODY_FIELD_NUMBER = 4;
+    private com.google.protobuf.ByteString body_;
+    /**
+     * <code>required bytes body = 4;</code>
+     */
+    public boolean hasBody() {
+      return ((bitField0_ & 0x00000008) == 0x00000008);
+    }
+    /**
+     * <code>required bytes body = 4;</code>
+     */
+    public com.google.protobuf.ByteString getBody() {
+      return body_;
+    }
+
     private void initFields() {
       ledgerId_ = 0L;
+      lac_ = 0L;
+      masterKey_ = com.google.protobuf.ByteString.EMPTY;
+      body_ = com.google.protobuf.ByteString.EMPTY;
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
@@ -5463,6 +5395,18 @@ public final class BookkeeperProtocol {
         memoizedIsInitialized = 0;
         return false;
       }
+      if (!hasLac()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasMasterKey()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasBody()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
       memoizedIsInitialized = 1;
       return true;
     }
@@ -5473,6 +5417,15 @@ public final class BookkeeperProtocol {
       if (((bitField0_ & 0x00000001) == 0x00000001)) {
         output.writeInt64(1, ledgerId_);
       }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeInt64(2, lac_);
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeBytes(3, masterKey_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        output.writeBytes(4, body_);
+      }
       getUnknownFields().writeTo(output);
     }
 
@@ -5486,6 +5439,18 @@ public final class BookkeeperProtocol {
         size += com.google.protobuf.CodedOutputStream
           .computeInt64Size(1, ledgerId_);
       }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(2, lac_);
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(3, masterKey_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(4, body_);
+      }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
       return size;
@@ -5498,53 +5463,53 @@ public final class BookkeeperProtocol {
       return super.writeReplace();
     }
 
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseFrom(byte[] data)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseDelimitedFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseDelimitedFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -5553,7 +5518,7 @@ public final class BookkeeperProtocol {
 
     public static Builder newBuilder() { return Builder.create(); }
     public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest prototype) {
+    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest prototype) {
       return newBuilder().mergeFrom(prototype);
     }
     public Builder toBuilder() { return newBuilder(this); }
@@ -5565,25 +5530,25 @@ public final class BookkeeperProtocol {
       return builder;
     }
     /**
-     * Protobuf type {@code ReadLacRequest}
+     * Protobuf type {@code WriteLacRequest}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:ReadLacRequest)
-        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequestOrBuilder {
+        // @@protoc_insertion_point(builder_implements:WriteLacRequest)
+        org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequestOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacRequest_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacRequest_descriptor;
       }
 
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacRequest_fieldAccessorTable
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacRequest_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest.class, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest.Builder.class);
+                org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest.class, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest.Builder.class);
       }
 
-      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest.newBuilder()
+      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -5605,6 +5570,12 @@ public final class BookkeeperProtocol {
         super.clear();
         ledgerId_ = 0L;
         bitField0_ = (bitField0_ & ~0x00000001);
+        lac_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000002);
+        masterKey_ = com.google.protobuf.ByteString.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000004);
+        body_ = com.google.protobuf.ByteString.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000008);
         return this;
       }
 
@@ -5614,48 +5585,69 @@ public final class BookkeeperProtocol {
 
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacRequest_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacRequest_descriptor;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest getDefaultInstanceForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest.getDefaultInstance();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest getDefaultInstanceForType() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest.getDefaultInstance();
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest build() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest result = buildPartial();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest build() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
         return result;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest buildPartial() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest result = new org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest(this);
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest buildPartial() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest result = new org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest(this);
         int from_bitField0_ = bitField0_;
         int to_bitField0_ = 0;
         if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
           to_bitField0_ |= 0x00000001;
         }
         result.ledgerId_ = ledgerId_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.lac_ = lac_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.masterKey_ = masterKey_;
+        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+          to_bitField0_ |= 0x00000008;
+        }
+        result.body_ = body_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
       }
 
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest) {
-          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest)other);
+        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest) {
+          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest other) {
-        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest.getDefaultInstance()) return this;
-        if (other.hasLedgerId()) {
+      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest other) {
+        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest.getDefaultInstance()) return this;
+        if (other.hasLedgerId()) {
           setLedgerId(other.getLedgerId());
         }
+        if (other.hasLac()) {
+          setLac(other.getLac());
+        }
+        if (other.hasMasterKey()) {
+          setMasterKey(other.getMasterKey());
+        }
+        if (other.hasBody()) {
+          setBody(other.getBody());
+        }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
@@ -5665,6 +5657,18 @@ public final class BookkeeperProtocol {
           
           return false;
         }
+        if (!hasLac()) {
+          
+          return false;
+        }
+        if (!hasMasterKey()) {
+          
+          return false;
+        }
+        if (!hasBody()) {
+          
+          return false;
+        }
         return true;
       }
 
@@ -5672,11 +5676,11 @@ public final class BookkeeperProtocol {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parsedMessage = null;
+        org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest) e.getUnfinishedMessage();
+          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacRequest) e.getUnfinishedMessage();
           throw e;
         } finally {
           if (parsedMessage != null) {
@@ -5719,58 +5723,152 @@ public final class BookkeeperProtocol {
         return this;
       }
 
-      // @@protoc_insertion_point(builder_scope:ReadLacRequest)
+      private long lac_ ;
+      /**
+       * <code>required int64 lac = 2;</code>
+       */
+      public boolean hasLac() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>required int64 lac = 2;</code>
+       */
+      public long getLac() {
+        return lac_;
+      }
+      /**
+       * <code>required int64 lac = 2;</code>
+       */
+      public Builder setLac(long value) {
+        bitField0_ |= 0x00000002;
+        lac_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required int64 lac = 2;</code>
+       */
+      public Builder clearLac() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        lac_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      private com.google.protobuf.ByteString masterKey_ = com.google.protobuf.ByteString.EMPTY;
+      /**
+       * <code>required bytes masterKey = 3;</code>
+       */
+      public boolean hasMasterKey() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>required bytes masterKey = 3;</code>
+       */
+      public com.google.protobuf.ByteString getMasterKey() {
+        return masterKey_;
+      }
+      /**
+       * <code>required bytes masterKey = 3;</code>
+       */
+      public Builder setMasterKey(com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+        masterKey_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required bytes masterKey = 3;</code>
+       */
+      public Builder clearMasterKey() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        masterKey_ = getDefaultInstance().getMasterKey();
+        onChanged();
+        return this;
+      }
+
+      private com.google.protobuf.ByteString body_ = com.google.protobuf.ByteString.EMPTY;
+      /**
+       * <code>required bytes body = 4;</code>
+       */
+      public boolean hasBody() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
+      }
+      /**
+       * <code>required bytes body = 4;</code>
+       */
+      public com.google.protobuf.ByteString getBody() {
+        return body_;
+      }
+      /**
+       * <code>required bytes body = 4;</code>
+       */
+      public Builder setBody(com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000008;
+        body_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required bytes body = 4;</code>
+       */
+      public Builder clearBody() {
+        bitField0_ = (bitField0_ & ~0x00000008);
+        body_ = getDefaultInstance().getBody();
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:WriteLacRequest)
     }
 
     static {
-      defaultInstance = new ReadLacRequest(true);
+      defaultInstance = new WriteLacRequest(true);
       defaultInstance.initFields();
     }
 
-    // @@protoc_insertion_point(class_scope:ReadLacRequest)
+    // @@protoc_insertion_point(class_scope:WriteLacRequest)
   }
 
-  public interface GetBookieInfoRequestOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:GetBookieInfoRequest)
+  public interface ReadLacRequestOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:ReadLacRequest)
       com.google.protobuf.MessageOrBuilder {
 
     /**
-     * <code>optional int64 requested = 1;</code>
-     *
-     * <pre>
-     * bitwise OR of Flags
-     * </pre>
+     * <code>required int64 ledgerId = 1;</code>
      */
-    boolean hasRequested();
+    boolean hasLedgerId();
     /**
-     * <code>optional int64 requested = 1;</code>
-     *
-     * <pre>
-     * bitwise OR of Flags
-     * </pre>
+     * <code>required int64 ledgerId = 1;</code>
      */
-    long getRequested();
+    long getLedgerId();
   }
   /**
-   * Protobuf type {@code GetBookieInfoRequest}
+   * Protobuf type {@code ReadLacRequest}
    */
-  public static final class GetBookieInfoRequest extends
+  public static final class ReadLacRequest extends
       com.google.protobuf.GeneratedMessage implements
-      // @@protoc_insertion_point(message_implements:GetBookieInfoRequest)
-      GetBookieInfoRequestOrBuilder {
-    // Use GetBookieInfoRequest.newBuilder() to construct.
-    private GetBookieInfoRequest(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      // @@protoc_insertion_point(message_implements:ReadLacRequest)
+      ReadLacRequestOrBuilder {
+    // Use ReadLacRequest.newBuilder() to construct.
+    private ReadLacRequest(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
       super(builder);
       this.unknownFields = builder.getUnknownFields();
     }
-    private GetBookieInfoRequest(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+    private ReadLacRequest(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
 
-    private static final GetBookieInfoRequest defaultInstance;
-    public static GetBookieInfoRequest getDefaultInstance() {
+    private static final ReadLacRequest defaultInstance;
+    public static ReadLacRequest getDefaultInstance() {
       return defaultInstance;
     }
 
-    public GetBookieInfoRequest getDefaultInstanceForType() {
+    public ReadLacRequest getDefaultInstanceForType() {
       return defaultInstance;
     }
 
@@ -5780,7 +5878,7 @@ public final class BookkeeperProtocol {
         getUnknownFields() {
       return this.unknownFields;
     }
-    private GetBookieInfoRequest(
+    private ReadLacRequest(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -5805,7 +5903,7 @@ public final class BookkeeperProtocol {
             }
             case 8: {
               bitField0_ |= 0x00000001;
-              requested_ = input.readInt64();
+              ledgerId_ = input.readInt64();
               break;
             }
           }
@@ -5822,155 +5920,69 @@ public final class BookkeeperProtocol {
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoRequest_descriptor;
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacRequest_descriptor;
     }
 
     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoRequest_fieldAccessorTable
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacRequest_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest.class, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest.Builder.class);
+              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest.class, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest.Builder.class);
     }
 
-    public static com.google.protobuf.Parser<GetBookieInfoRequest> PARSER =
-        new com.google.protobuf.AbstractParser<GetBookieInfoRequest>() {
-      public GetBookieInfoRequest parsePartialFrom(
+    public static com.google.protobuf.Parser<ReadLacRequest> PARSER =
+        new com.google.protobuf.AbstractParser<ReadLacRequest>() {
+      public ReadLacRequest parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new GetBookieInfoRequest(input, extensionRegistry);
+        return new ReadLacRequest(input, extensionRegistry);
       }
     };
 
     @java.lang.Override
-    public com.google.protobuf.Parser<GetBookieInfoRequest> getParserForType() {
+    public com.google.protobuf.Parser<ReadLacRequest> getParserForType() {
       return PARSER;
     }
 
+    private int bitField0_;
+    public static final int LEDGERID_FIELD_NUMBER = 1;
+    private long ledgerId_;
     /**
-     * Protobuf enum {@code GetBookieInfoRequest.Flags}
+     * <code>required int64 ledgerId = 1;</code>
      */
-    public enum Flags
-        implements com.google.protobuf.ProtocolMessageEnum {
-      /**
-       * <code>TOTAL_DISK_CAPACITY = 1;</code>
-       */
-      TOTAL_DISK_CAPACITY(0, 1),
-      /**
-       * <code>FREE_DISK_SPACE = 2;</code>
-       */
-      FREE_DISK_SPACE(1, 2),
-      ;
-
-      /**
-       * <code>TOTAL_DISK_CAPACITY = 1;</code>
-       */
-      public static final int TOTAL_DISK_CAPACITY_VALUE = 1;
-      /**
-       * <code>FREE_DISK_SPACE = 2;</code>
-       */
-      public static final int FREE_DISK_SPACE_VALUE = 2;
-
+    public boolean hasLedgerId() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required int64 ledgerId = 1;</code>
+     */
+    public long getLedgerId() {
+      return ledgerId_;
+    }
 
-      public final int getNumber() { return value; }
+    private void initFields() {
+      ledgerId_ = 0L;
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
 
-      public static Flags valueOf(int value) {
-        switch (value) {
-          case 1: return TOTAL_DISK_CAPACITY;
-          case 2: return FREE_DISK_SPACE;
-          default: return null;
-        }
+      if (!hasLedgerId()) {
+        memoizedIsInitialized = 0;
+        return false;
       }
-
-      public static com.google.protobuf.Internal.EnumLiteMap<Flags>
-          internalGetValueMap() {
-        return internalValueMap;
-      }
-      private static com.google.protobuf.Internal.EnumLiteMap<Flags>
-          internalValueMap =
-            new com.google.protobuf.Internal.EnumLiteMap<Flags>() {
-              public Flags findValueByNumber(int number) {
-                return Flags.valueOf(number);
-              }
-            };
-
-      public final com.google.protobuf.Descriptors.EnumValueDescriptor
-          getValueDescriptor() {
-        return getDescriptor().getValues().get(index);
-      }
-      public final com.google.protobuf.Descriptors.EnumDescriptor
-          getDescriptorForType() {
-        return getDescriptor();
-      }
-      public static final com.google.protobuf.Descriptors.EnumDescriptor
-          getDescriptor() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest.getDescriptor().getEnumTypes().get(0);
-      }
-
-      private static final Flags[] VALUES = values();
-
-      public static Flags valueOf(
-          com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
-        if (desc.getType() != getDescriptor()) {
-          throw new java.lang.IllegalArgumentException(
-            "EnumValueDescriptor is not for this type.");
-        }
-        return VALUES[desc.getIndex()];
-      }
-
-      private final int index;
-      private final int value;
-
-      private Flags(int index, int value) {
-        this.index = index;
-        this.value = value;
-      }
-
-      // @@protoc_insertion_point(enum_scope:GetBookieInfoRequest.Flags)
-    }
-
-    private int bitField0_;
-    public static final int REQUESTED_FIELD_NUMBER = 1;
-    private long requested_;
-    /**
-     * <code>optional int64 requested = 1;</code>
-     *
-     * <pre>
-     * bitwise OR of Flags
-     * </pre>
-     */
-    public boolean hasRequested() {
-      return ((bitField0_ & 0x00000001) == 0x00000001);
-    }
-    /**
-     * <code>optional int64 requested = 1;</code>
-     *
-     * <pre>
-     * bitwise OR of Flags
-     * </pre>
-     */
-    public long getRequested() {
-      return requested_;
-    }
-
-    private void initFields() {
-      requested_ = 0L;
-    }
-    private byte memoizedIsInitialized = -1;
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      memoizedIsInitialized = 1;
-      return true;
-    }
+      memoizedIsInitialized = 1;
+      return true;
+    }
 
     public void writeTo(com.google.protobuf.CodedOutputStream output)
                         throws java.io.IOException {
       getSerializedSize();
       if (((bitField0_ & 0x00000001) == 0x00000001)) {
-        output.writeInt64(1, requested_);
+        output.writeInt64(1, ledgerId_);
       }
       getUnknownFields().writeTo(output);
     }
@@ -5983,7 +5995,7 @@ public final class BookkeeperProtocol {
       size = 0;
       if (((bitField0_ & 0x00000001) == 0x00000001)) {
         size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(1, requested_);
+          .computeInt64Size(1, ledgerId_);
       }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
@@ -5997,53 +6009,53 @@ public final class BookkeeperProtocol {
       return super.writeReplace();
     }
 
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseFrom(byte[] data)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseDelimitedFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseDelimitedFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -6052,7 +6064,7 @@ public final class BookkeeperProtocol {
 
     public static Builder newBuilder() { return Builder.create(); }
     public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest prototype) {
+    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest prototype) {
       return newBuilder().mergeFrom(prototype);
     }
     public Builder toBuilder() { return newBuilder(this); }
@@ -6064,25 +6076,25 @@ public final class BookkeeperProtocol {
       return builder;
     }
     /**
-     * Protobuf type {@code GetBookieInfoRequest}
+     * Protobuf type {@code ReadLacRequest}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:GetBookieInfoRequest)
-        org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequestOrBuilder {
+        // @@protoc_insertion_point(builder_implements:ReadLacRequest)
+        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequestOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoRequest_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacRequest_descriptor;
       }
 
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoRequest_fieldAccessorTable
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacRequest_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest.class, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest.Builder.class);
+                org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest.class, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest.Builder.class);
       }
 
-      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest.newBuilder()
+      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -6102,7 +6114,7 @@ public final class BookkeeperProtocol {
 
       public Builder clear() {
         super.clear();
-        requested_ = 0L;
+        ledgerId_ = 0L;
         bitField0_ = (bitField0_ & ~0x00000001);
         return this;
       }
@@ -6113,53 +6125,57 @@ public final class BookkeeperProtocol {
 
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoRequest_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacRequest_descriptor;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest getDefaultInstanceForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest.getDefaultInstance();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest getDefaultInstanceForType() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest.getDefaultInstance();
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest build() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest result = buildPartial();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest build() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
         return result;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest buildPartial() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest result = new org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest(this);
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest buildPartial() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest result = new org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest(this);
         int from_bitField0_ = bitField0_;
         int to_bitField0_ = 0;
         if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
           to_bitField0_ |= 0x00000001;
         }
-        result.requested_ = requested_;
+        result.ledgerId_ = ledgerId_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
       }
 
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest) {
-          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest)other);
+        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest) {
+          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest other) {
-        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest.getDefaultInstance()) return this;
-        if (other.hasRequested()) {
-          setRequested(other.getRequested());
+      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest other) {
+        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest.getDefaultInstance()) return this;
+        if (other.hasLedgerId()) {
+          setLedgerId(other.getLedgerId());
         }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
 
       public final boolean isInitialized() {
+        if (!hasLedgerId()) {
+          
+          return false;
+        }
         return true;
       }
 
@@ -6167,11 +6183,11 @@ public final class BookkeeperProtocol {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parsedMessage = null;
+        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest) e.getUnfinishedMessage();
+          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacRequest) e.getUnfinishedMessage();
           throw e;
         } finally {
           if (parsedMessage != null) {
@@ -6182,211 +6198,90 @@ public final class BookkeeperProtocol {
       }
       private int bitField0_;
 
-      private long requested_ ;
+      private long ledgerId_ ;
       /**
-       * <code>optional int64 requested = 1;</code>
-       *
-       * <pre>
-       * bitwise OR of Flags
-       * </pre>
+       * <code>required int64 ledgerId = 1;</code>
        */
-      public boolean hasRequested() {
+      public boolean hasLedgerId() {
         return ((bitField0_ & 0x00000001) == 0x00000001);
       }
       /**
-       * <code>optional int64 requested = 1;</code>
-       *
-       * <pre>
-       * bitwise OR of Flags
-       * </pre>
+       * <code>required int64 ledgerId = 1;</code>
        */
-      public long getRequested() {
-        return requested_;
+      public long getLedgerId() {
+        return ledgerId_;
       }
       /**
-       * <code>optional int64 requested = 1;</code>
-       *
-       * <pre>
-       * bitwise OR of Flags
-       * </pre>
+       * <code>required int64 ledgerId = 1;</code>
        */
-      public Builder setRequested(long value) {
+      public Builder setLedgerId(long value) {
         bitField0_ |= 0x00000001;
-        requested_ = value;
+        ledgerId_ = value;
         onChanged();
         return this;
       }
       /**
-       * <code>optional int64 requested = 1;</code>
-       *
-       * <pre>
-       * bitwise OR of Flags
-       * </pre>
+       * <code>required int64 ledgerId = 1;</code>
        */
-      public Builder clearRequested() {
+      public Builder clearLedgerId() {
         bitField0_ = (bitField0_ & ~0x00000001);
-        requested_ = 0L;
+        ledgerId_ = 0L;
         onChanged();
         return this;
       }
 
-      // @@protoc_insertion_point(builder_scope:GetBookieInfoRequest)
+      // @@protoc_insertion_point(builder_scope:ReadLacRequest)
     }
 
     static {
-      defaultInstance = new GetBookieInfoRequest(true);
+      defaultInstance = new ReadLacRequest(true);
       defaultInstance.initFields();
     }
 
-    // @@protoc_insertion_point(class_scope:GetBookieInfoRequest)
+    // @@protoc_insertion_point(class_scope:ReadLacRequest)
   }
 
-  public interface ResponseOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:Response)
+  public interface GetBookieInfoRequestOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:GetBookieInfoRequest)
       com.google.protobuf.MessageOrBuilder {
 
     /**
-     * <code>required .BKPacketHeader header = 1;</code>
-     */
-    boolean hasHeader();
-    /**
-     * <code>required .BKPacketHeader header = 1;</code>
-     */
-    org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader getHeader();
-    /**
-     * <code>required .BKPacketHeader header = 1;</code>
-     */
-    org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeaderOrBuilder getHeaderOrBuilder();
-
-    /**
-     * <code>required .StatusCode status = 2;</code>
+     * <code>optional int64 requested = 1;</code>
      *
      * <pre>
-     * EOK if the underlying request succeeded. Each individual response
-     * has a more meaningful status. EBADREQ if we have an unsupported request.
+     * bitwise OR of Flags
      * </pre>
      */
-    boolean hasStatus();
+    boolean hasRequested();
     /**
-     * <code>required .StatusCode status = 2;</code>
+     * <code>optional int64 requested = 1;</code>
      *
      * <pre>
-     * EOK if the underlying request succeeded. Each individual response
-     * has a more meaningful status. EBADREQ if we have an unsupported request.
+     * bitwise OR of Flags
      * </pre>
      */
-    org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus();
+    long getRequested();
+  }
+  /**
+   * Protobuf type {@code GetBookieInfoRequest}
+   */
+  public static final class GetBookieInfoRequest extends
+      com.google.protobuf.GeneratedMessage implements
+      // @@protoc_insertion_point(message_implements:GetBookieInfoRequest)
+      GetBookieInfoRequestOrBuilder {
+    // Use GetBookieInfoRequest.newBuilder() to construct.
+    private GetBookieInfoRequest(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private GetBookieInfoRequest(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
 
-    /**
-     * <code>optional .ReadResponse readResponse = 100;</code>
-     *
-     * <pre>
-     * Response
-     * </pre>
-     */
-    boolean hasReadResponse();
-    /**
-     * <code>optional .ReadResponse readResponse = 100;</code>
-     *
-     * <pre>
-     * Response
-     * </pre>
-     */
-    org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse getReadResponse();
-    /**
-     * <code>optional .ReadResponse readResponse = 100;</code>
-     *
-     * <pre>
-     * Response
-     * </pre>
-     */
-    org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponseOrBuilder getReadResponseOrBuilder();
-
-    /**
-     * <code>optional .AddResponse addResponse = 101;</code>
-     */
-    boolean hasAddResponse();
-    /**
-     * <code>optional .AddResponse addResponse = 101;</code>
-     */
-    org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse getAddResponse();
-    /**
-     * <code>optional .AddResponse addResponse = 101;</code>
-     */
-    org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponseOrBuilder getAddResponseOrBuilder();
-
-    /**
-     * <code>optional .AuthMessage authResponse = 102;</code>
-     */
-    boolean hasAuthResponse();
-    /**
-     * <code>optional .AuthMessage authResponse = 102;</code>
-     */
-    org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage getAuthResponse();
-    /**
-     * <code>optional .AuthMessage authResponse = 102;</code>
-     */
-    org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessageOrBuilder getAuthResponseOrBuilder();
-
-    /**
-     * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
-     */
-    boolean hasWriteLacResponse();
-    /**
-     * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
-     */
-    org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse getWriteLacResponse();
-    /**
-     * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
-     */
-    org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponseOrBuilder getWriteLacResponseOrBuilder();
-
-    /**
-     * <code>optional .ReadLacResponse readLacResponse = 104;</code>
-     */
-    boolean hasReadLacResponse();
-    /**
-     * <code>optional .ReadLacResponse readLacResponse = 104;</code>
-     */
-    org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse getReadLacResponse();
-    /**
-     * <code>optional .ReadLacResponse readLacResponse = 104;</code>
-     */
-    org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponseOrBuilder getReadLacResponseOrBuilder();
-
-    /**
-     * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
-     */
-    boolean hasGetBookieInfoResponse();
-    /**
-     * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
-     */
-    org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse getGetBookieInfoResponse();
-    /**
-     * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
-     */
-    org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponseOrBuilder getGetBookieInfoResponseOrBuilder();
-  }
-  /**
-   * Protobuf type {@code Response}
-   */
-  public static final class Response extends
-      com.google.protobuf.GeneratedMessage implements
-      // @@protoc_insertion_point(message_implements:Response)
-      ResponseOrBuilder {
-    // Use Response.newBuilder() to construct.
-    private Response(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
-      super(builder);
-      this.unknownFields = builder.getUnknownFields();
-    }
-    private Response(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
-
-    private static final Response defaultInstance;
-    public static Response getDefaultInstance() {
+    private static final GetBookieInfoRequest defaultInstance;
+    public static GetBookieInfoRequest getDefaultInstance() {
       return defaultInstance;
     }
 
-    public Response getDefaultInstanceForType() {
+    public GetBookieInfoRequest getDefaultInstanceForType() {
       return defaultInstance;
     }
 
@@ -6396,7 +6291,7 @@ public final class BookkeeperProtocol {
         getUnknownFields() {
       return this.unknownFields;
     }
-    private Response(
+    private GetBookieInfoRequest(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -6419,106 +6314,9 @@ public final class BookkeeperProtocol {
               }
               break;
             }
-            case 10: {
-              org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.Builder subBuilder = null;
-              if (((bitField0_ & 0x00000001) == 0x00000001)) {
-                subBuilder = header_.toBuilder();
-              }
-              header_ = input.readMessage(org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.PARSER, extensionRegistry);
-              if (subBuilder != null) {
-                subBuilder.mergeFrom(header_);
-                header_ = subBuilder.buildPartial();
-              }
+            case 8: {
               bitField0_ |= 0x00000001;
-              break;
-            }
-            case 16: {
-              int rawValue = input.readEnum();
-              org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode value = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.valueOf(rawValue);
-              if (value == null) {
-                unknownFields.mergeVarintField(2, rawValue);
-              } else {
-                bitField0_ |= 0x00000002;
-                status_ = value;
-              }
-              break;
-            }
-            case 802: {
-              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.Builder subBuilder = null;
-              if (((bitField0_ & 0x00000004) == 0x00000004)) {
-                subBuilder = readResponse_.toBuilder();
-              }
-              readResponse_ = input.readMessage(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.PARSER, extensionRegistry);
-              if (subBuilder != null) {
-                subBuilder.mergeFrom(readResponse_);
-                readResponse_ = subBuilder.buildPartial();
-              }
-              bitField0_ |= 0x00000004;
-              break;
-            }
-            case 810: {
-              org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.Builder subBuilder = null;
-              if (((bitField0_ & 0x00000008) == 0x00000008)) {
-                subBuilder = addResponse_.toBuilder();
-              }
-              addResponse_ = input.readMessage(org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.PARSER, extensionRegistry);
-              if (subBuilder != null) {
-                subBuilder.mergeFrom(addResponse_);
-                addResponse_ = subBuilder.buildPartial();
-              }
-              bitField0_ |= 0x00000008;
-              break;
-            }
-            case 818: {
-              org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.Builder subBuilder = null;
-              if (((bitField0_ & 0x00000010) == 0x00000010)) {
-                subBuilder = authResponse_.toBuilder();
-              }
-              authResponse_ = input.readMessage(org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.PARSER, extensionRegistry);
-              if (subBuilder != null) {
-                subBuilder.mergeFrom(authResponse_);
-                authResponse_ = subBuilder.buildPartial();
-              }
-              bitField0_ |= 0x00000010;
-              break;
-            }
-            case 826: {
-              org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.Builder subBuilder = null;
-              if (((bitField0_ & 0x00000020) == 0x00000020)) {
-                subBuilder = writeLacResponse_.toBuilder();
-              }
-              writeLacResponse_ = input.readMessage(org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.PARSER, extensionRegistry);
-              if (subBuilder != null) {
-                subBuilder.mergeFrom(writeLacResponse_);
-                writeLacResponse_ = subBuilder.buildPartial();
-              }
-              bitField0_ |= 0x00000020;
-              break;
-            }
-            case 834: {
-              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.Builder subBuilder = null;
-              if (((bitField0_ & 0x00000040) == 0x00000040)) {
-                subBuilder = readLacResponse_.toBuilder();
-              }
-              readLacResponse_ = input.readMessage(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.PARSER, extensionRegistry);
-              if (subBuilder != null) {
-                subBuilder.mergeFrom(readLacResponse_);
-                readLacResponse_ = subBuilder.buildPartial();
-              }
-              bitField0_ |= 0x00000040;
-              break;
-            }
-            case 842: {
-              org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.Builder subBuilder = null;
-              if (((bitField0_ & 0x00000080) == 0x00000080)) {
-                subBuilder = getBookieInfoResponse_.toBuilder();
-              }
-              getBookieInfoResponse_ = input.readMessage(org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.PARSER, extensionRegistry);
-              if (subBuilder != null) {
-                subBuilder.mergeFrom(getBookieInfoResponse_);
-                getBookieInfoResponse_ = subBuilder.buildPartial();
-              }
-              bitField0_ |= 0x00000080;
+              requested_ = input.readInt64();
               break;
             }
           }
@@ -6535,411 +6333,228 @@ public final class BookkeeperProtocol {
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_Response_descriptor;
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoRequest_descriptor;
     }
 
     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_Response_fieldAccessorTable
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoRequest_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              org.apache.bookkeeper.proto.BookkeeperProtocol.Response.class, org.apache.bookkeeper.proto.BookkeeperProtocol.Response.Builder.class);
+              org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest.class, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest.Builder.class);
     }
 
-    public static com.google.protobuf.Parser<Response> PARSER =
-        new com.google.protobuf.AbstractParser<Response>() {
-      public Response parsePartialFrom(
+    public static com.google.protobuf.Parser<GetBookieInfoRequest> PARSER =
+        new com.google.protobuf.AbstractParser<GetBookieInfoRequest>() {
+      public GetBookieInfoRequest parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new Response(input, extensionRegistry);
+        return new GetBookieInfoRequest(input, extensionRegistry);
       }
     };
 
     @java.lang.Override
-    public com.google.protobuf.Parser<Response> getParserForType() {
+    public com.google.protobuf.Parser<GetBookieInfoRequest> getParserForType() {
       return PARSER;
     }
 
-    private int bitField0_;
-    public static final int HEADER_FIELD_NUMBER = 1;
-    private org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader header_;
-    /**
-     * <code>required .BKPacketHeader header = 1;</code>
-     */
-    public boolean hasHeader() {
-      return ((bitField0_ & 0x00000001) == 0x00000001);
-    }
-    /**
-     * <code>required .BKPacketHeader header = 1;</code>
-     */
-    public org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader getHeader() {
-      return header_;
-    }
     /**
-     * <code>required .BKPacketHeader header = 1;</code>
+     * Protobuf enum {@code GetBookieInfoRequest.Flags}
      */
-    public org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeaderOrBuilder getHeaderOrBuilder() {
-      return header_;
-    }
+    public enum Flags
+        implements com.google.protobuf.ProtocolMessageEnum {
+      /**
+       * <code>TOTAL_DISK_CAPACITY = 1;</code>
+       */
+      TOTAL_DISK_CAPACITY(0, 1),
+      /**
+       * <code>FREE_DISK_SPACE = 2;</code>
+       */
+      FREE_DISK_SPACE(1, 2),
+      ;
 
-    public static final int STATUS_FIELD_NUMBER = 2;
-    private org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode status_;
-    /**
-     * <code>required .StatusCode status = 2;</code>
-     *
-     * <pre>
-     * EOK if the underlying request succeeded. Each individual response
-     * has a more meaningful status. EBADREQ if we have an unsupported request.
-     * </pre>
-     */
-    public boolean hasStatus() {
-      return ((bitField0_ & 0x00000002) == 0x00000002);
-    }
-    /**
-     * <code>required .StatusCode status = 2;</code>
-     *
-     * <pre>
-     * EOK if the underlying request succeeded. Each individual response
-     * has a more meaningful status. EBADREQ if we have an unsupported request.
-     * </pre>
-     */
-    public org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus() {
-      return status_;
+      /**
+       * <code>TOTAL_DISK_CAPACITY = 1;</code>
+       */
+      public static final int TOTAL_DISK_CAPACITY_VALUE = 1;
+      /**
+       * <code>FREE_DISK_SPACE = 2;</code>
+       */
+      public static final int FREE_DISK_SPACE_VALUE = 2;
+
+
+      public final int getNumber() { return value; }
+
+      public static Flags valueOf(int value) {
+        switch (value) {
+          case 1: return TOTAL_DISK_CAPACITY;
+          case 2: return FREE_DISK_SPACE;
+          default: return null;
+        }
+      }
+
+      public static com.google.protobuf.Internal.EnumLiteMap<Flags>
+          internalGetValueMap() {
+        return internalValueMap;
+      }
+      private static com.google.protobuf.Internal.EnumLiteMap<Flags>
+          internalValueMap =
+            new com.google.protobuf.Internal.EnumLiteMap<Flags>() {
+              public Flags findValueByNumber(int number) {
+                return Flags.valueOf(number);
+              }
+            };
+
+      public final com.google.protobuf.Descriptors.EnumValueDescriptor
+          getValueDescriptor() {
+        return getDescriptor().getValues().get(index);
+      }
+      public final com.google.protobuf.Descriptors.EnumDescriptor
+          getDescriptorForType() {
+        return getDescriptor();
+      }
+      public static final com.google.protobuf.Descriptors.EnumDescriptor
+          getDescriptor() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest.getDescriptor().getEnumTypes().get(0);
+      }
+
+      private static final Flags[] VALUES = values();
+
+      public static Flags valueOf(
+          com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
+        if (desc.getType() != getDescriptor()) {
+          throw new java.lang.IllegalArgumentException(
+            "EnumValueDescriptor is not for this type.");
+        }
+        return VALUES[desc.getIndex()];
+      }
+
+      private final int index;
+      private final int value;
+
+      private Flags(int index, int value) {
+        this.index = index;
+        this.value = value;
+      }
+
+      // @@protoc_insertion_point(enum_scope:GetBookieInfoRequest.Flags)
     }
 
-    public static final int READRESPONSE_FIELD_NUMBER = 100;
-    private org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse readResponse_;
+    private int bitField0_;
+    public static final int REQUESTED_FIELD_NUMBER = 1;
+    private long requested_;
     /**
-     * <code>optional .ReadResponse readResponse = 100;</code>
+     * <code>optional int64 requested = 1;</code>
      *
      * <pre>
-     * Response
+     * bitwise OR of Flags
      * </pre>
      */
-    public boolean hasReadResponse() {
-      return ((bitField0_ & 0x00000004) == 0x00000004);
+    public boolean hasRequested() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
     }
     /**
-     * <code>optional .ReadResponse readResponse = 100;</code>
+     * <code>optional int64 requested = 1;</code>
      *
      * <pre>
-     * Response
+     * bitwise OR of Flags
      * </pre>
      */
-    public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse getReadResponse() {
-      return readResponse_;
+    public long getRequested() {
+      return requested_;
     }
-    /**
-     * <code>optional .ReadResponse readResponse = 100;</code>
-     *
-     * <pre>
-     * Response
-     * </pre>
-     */
-    public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponseOrBuilder getReadResponseOrBuilder() {
-      return readResponse_;
+
+    private void initFields() {
+      requested_ = 0L;
     }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
 
-    public static final int ADDRESPONSE_FIELD_NUMBER = 101;
-    private org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse addResponse_;
-    /**
-     * <code>optional .AddResponse addResponse = 101;</code>
-     */
-    public boolean hasAddResponse() {
-      return ((bitField0_ & 0x00000008) == 0x00000008);
+      memoizedIsInitialized = 1;
+      return true;
     }
-    /**
-     * <code>optional .AddResponse addResponse = 101;</code>
-     */
-    public org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse getAddResponse() {
-      return addResponse_;
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeInt64(1, requested_);
+      }
+      getUnknownFields().writeTo(output);
     }
-    /**
-     * <code>optional .AddResponse addResponse = 101;</code>
-     */
-    public org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponseOrBuilder getAddResponseOrBuilder() {
-      return addResponse_;
+
+    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
+          .computeInt64Size(1, requested_);
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
     }
 
-    public static final int AUTHRESPONSE_FIELD_NUMBER = 102;
-    private org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage authResponse_;
-    /**
-     * <code>optional .AuthMessage authResponse = 102;</code>
-     */
-    public boolean hasAuthResponse() {
-      return ((bitField0_ & 0x00000010) == 0x00000010);
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
     }
-    /**
-     * <code>optional .AuthMessage authResponse = 102;</code>
-     */
-    public org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage getAuthResponse() {
-      return authResponse_;
+
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
     }
-    /**
-     * <code>optional .AuthMessage authResponse = 102;</code>
-     */
-    public org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessageOrBuilder getAuthResponseOrBuilder() {
-      return authResponse_;
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
     }
-
-    public static final int WRITELACRESPONSE_FIELD_NUMBER = 103;
-    private org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse writeLacResponse_;
-    /**
-     * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
-     */
-    public boolean hasWriteLacResponse() {
-      return ((bitField0_ & 0x00000020) == 0x00000020);
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
     }
-    /**
-     * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
-     */
-    public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse getWriteLacResponse() {
-      return writeLacResponse_;
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
     }
-    /**
-     * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
-     */
-    public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponseOrBuilder getWriteLacResponseOrBuilder() {
-      return writeLacResponse_;
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
     }
-
-    public static final int READLACRESPONSE_FIELD_NUMBER = 104;
-    private org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse readLacResponse_;
-    /**
-     * <code>optional .ReadLacResponse readLacResponse = 104;</code>
-     */
-    public boolean hasReadLacResponse() {
-      return ((bitField0_ & 0x00000040) == 0x00000040);
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
     }
-    /**
-     * <code>optional .ReadLacResponse readLacResponse = 104;</code>
-     */
-    public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse getReadLacResponse() {
-      return readLacResponse_;
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
     }
-    /**
-     * <code>optional .ReadLacResponse readLacResponse = 104;</code>
-     */
-    public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponseOrBuilder getReadLacResponseOrBuilder() {
-      return readLacResponse_;
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
     }
-
-    public static final int GETBOOKIEINFORESPONSE_FIELD_NUMBER = 105;
-    private org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse getBookieInfoResponse_;
-    /**
-     * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
-     */
-    public boolean hasGetBookieInfoResponse() {
-      return ((bitField0_ & 0x00000080) == 0x00000080);
-    }
-    /**
-     * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
-     */
-    public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse getGetBookieInfoResponse() {
-      return getBookieInfoResponse_;
-    }
-    /**
-     * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
-     */
-    public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponseOrBuilder getGetBookieInfoResponseOrBuilder() {
-      return getBookieInfoResponse_;
-    }
-
-    private void initFields() {
-      header_ = org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.getDefaultInstance();
-      status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
-      readResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.getDefaultInstance();
-      addResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.getDefaultInstance();
-      authResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.getDefaultInstance();
-      writeLacResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.getDefaultInstance();
-      readLacResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.getDefaultInstance();
-      getBookieInfoResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.getDefaultInstance();
-    }
-    private byte memoizedIsInitialized = -1;
-    public final boolean isInitialized() {
-      byte isInitialized = memoizedIsInitialized;
-      if (isInitialized == 1) return true;
-      if (isInitialized == 0) return false;
-
-      if (!hasHeader()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      if (!hasStatus()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      if (!getHeader().isInitialized()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      if (hasReadResponse()) {
-        if (!getReadResponse().isInitialized()) {
-          memoizedIsInitialized = 0;
-          return false;
-        }
-      }
-      if (hasAddResponse()) {
-        if (!getAddResponse().isInitialized()) {
-          memoizedIsInitialized = 0;
-          return false;
-        }
-      }
-      if (hasAuthResponse()) {
-        if (!getAuthResponse().isInitialized()) {
-          memoizedIsInitialized = 0;
-          return false;
-        }
-      }
-      if (hasWriteLacResponse()) {
-        if (!getWriteLacResponse().isInitialized()) {
-          memoizedIsInitialized = 0;
-          return false;
-        }
-      }
-      if (hasReadLacResponse()) {
-        if (!getReadLacResponse().isInitialized()) {
-          memoizedIsInitialized = 0;
-          return false;
-        }
-      }
-      if (hasGetBookieInfoResponse()) {
-        if (!getGetBookieInfoResponse().isInitialized()) {
-          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.writeMessage(1, header_);
-      }
-      if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        output.writeEnum(2, status_.getNumber());
-      }
-      if (((bitField0_ & 0x00000004) == 0x00000004)) {
-        output.writeMessage(100, readResponse_);
-      }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
-        output.writeMessage(101, addResponse_);
-      }
-      if (((bitField0_ & 0x00000010) == 0x00000010)) {
-        output.writeMessage(102, authResponse_);
-      }
-      if (((bitField0_ & 0x00000020) == 0x00000020)) {
-        output.writeMessage(103, writeLacResponse_);
-      }
-      if (((bitField0_ & 0x00000040) == 0x00000040)) {
-        output.writeMessage(104, readLacResponse_);
-      }
-      if (((bitField0_ & 0x00000080) == 0x00000080)) {
-        output.writeMessage(105, getBookieInfoResponse_);
-      }
-      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
-          .computeMessageSize(1, header_);
-      }
-      if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeEnumSize(2, status_.getNumber());
-      }
-      if (((bitField0_ & 0x00000004) == 0x00000004)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(100, readResponse_);
-      }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(101, addResponse_);
-      }
-      if (((bitField0_ & 0x00000010) == 0x00000010)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(102, authResponse_);
-      }
-      if (((bitField0_ & 0x00000020) == 0x00000020)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(103, writeLacResponse_);
-      }
-      if (((bitField0_ & 0x00000040) == 0x00000040)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(104, readLacResponse_);
-      }
-      if (((bitField0_ & 0x00000080) == 0x00000080)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(105, getBookieInfoResponse_);
-      }
-      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.BookkeeperProtocol.Response parseFrom(
-        com.google.protobuf.ByteString data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseFrom(
-        com.google.protobuf.ByteString data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseFrom(byte[] data)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data);
-    }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseFrom(
-        byte[] data,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws com.google.protobuf.InvalidProtocolBufferException {
-      return PARSER.parseFrom(data, extensionRegistry);
-    }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return PARSER.parseFrom(input);
-    }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return PARSER.parseFrom(input, extensionRegistry);
-    }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseDelimitedFrom(java.io.InputStream input)
-        throws java.io.IOException {
-      return PARSER.parseDelimitedFrom(input);
-    }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseDelimitedFrom(
-        java.io.InputStream input,
-        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-        throws java.io.IOException {
-      return PARSER.parseDelimitedFrom(input, extensionRegistry);
-    }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -6948,7 +6563,7 @@ public final class BookkeeperProtocol {
 
     public static Builder newBuilder() { return Builder.create(); }
     public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.Response prototype) {
+    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest prototype) {
       return newBuilder().mergeFrom(prototype);
     }
     public Builder toBuilder() { return newBuilder(this); }
@@ -6960,25 +6575,25 @@ public final class BookkeeperProtocol {
       return builder;
     }
     /**
-     * Protobuf type {@code Response}
+     * Protobuf type {@code GetBookieInfoRequest}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:Response)
-        org.apache.bookkeeper.proto.BookkeeperProtocol.ResponseOrBuilder {
+        // @@protoc_insertion_point(builder_implements:GetBookieInfoRequest)
+        org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequestOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_Response_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoRequest_descriptor;
       }
 
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_Response_fieldAccessorTable
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoRequest_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                org.apache.bookkeeper.proto.BookkeeperProtocol.Response.class, org.apache.bookkeeper.proto.BookkeeperProtocol.Response.Builder.class);
+                org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest.class, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest.Builder.class);
       }
 
-      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.Response.newBuilder()
+      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -6990,13 +6605,6 @@ public final class BookkeeperProtocol {
       }
       private void maybeForceBuilderInitialization() {
         if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
-          getHeaderFieldBuilder();
-          getReadResponseFieldBuilder();
-          getAddResponseFieldBuilder();
-          getAuthResponseFieldBuilder();
-          getWriteLacResponseFieldBuilder();
-          getReadLacResponseFieldBuilder();
-          getGetBookieInfoResponseFieldBuilder();
         }
       }
       private static Builder create() {
@@ -7005,50 +6613,8 @@ public final class BookkeeperProtocol {
 
       public Builder clear() {
         super.clear();
-        if (headerBuilder_ == null) {
-          header_ = org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.getDefaultInstance();
-        } else {
-          headerBuilder_.clear();
-        }
+        requested_ = 0L;
         bitField0_ = (bitField0_ & ~0x00000001);
-        status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
-        bitField0_ = (bitField0_ & ~0x00000002);
-        if (readResponseBuilder_ == null) {
-          readResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.getDefaultInstance();
-        } else {
-          readResponseBuilder_.clear();
-        }
-        bitField0_ = (bitField0_ & ~0x00000004);
-        if (addResponseBuilder_ == null) {
-          addResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.getDefaultInstance();
-        } else {
-          addResponseBuilder_.clear();
-        }
-        bitField0_ = (bitField0_ & ~0x00000008);
-        if (authResponseBuilder_ == null) {
-          authResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.getDefaultInstance();
-        } else {
-          authResponseBuilder_.clear();
-        }
-        bitField0_ = (bitField0_ & ~0x00000010);
-        if (writeLacResponseBuilder_ == null) {
-          writeLacResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.getDefaultInstance();
-        } else {
-          writeLacResponseBuilder_.clear();
-        }
-        bitField0_ = (bitField0_ & ~0x00000020);
-        if (readLacResponseBuilder_ == null) {
-          readLacResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.getDefaultInstance();
-        } else {
-          readLacResponseBuilder_.clear();
-        }
-        bitField0_ = (bitField0_ & ~0x00000040);
-        if (getBookieInfoResponseBuilder_ == null) {
-          getBookieInfoResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.getDefaultInstance();
-        } else {
-          getBookieInfoResponseBuilder_.clear();
-        }
-        bitField0_ = (bitField0_ & ~0x00000080);
         return this;
       }
 
@@ -7058,178 +6624,53 @@ public final class BookkeeperProtocol {
 
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_Response_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoRequest_descriptor;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.Response getDefaultInstanceForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.Response.getDefaultInstance();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest getDefaultInstanceForType() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest.getDefaultInstance();
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.Response build() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.Response result = buildPartial();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest build() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
         return result;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.Response buildPartial() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.Response result = new org.apache.bookkeeper.proto.BookkeeperProtocol.Response(this);
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest buildPartial() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest result = new org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest(this);
         int from_bitField0_ = bitField0_;
         int to_bitField0_ = 0;
         if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
           to_bitField0_ |= 0x00000001;
         }
-        if (headerBuilder_ == null) {
-          result.header_ = header_;
-        } else {
-          result.header_ = headerBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
-          to_bitField0_ |= 0x00000002;
-        }
-        result.status_ = status_;
-        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
-          to_bitField0_ |= 0x00000004;
-        }
-        if (readResponseBuilder_ == null) {
-          result.readResponse_ = readResponse_;
-        } else {
-          result.readResponse_ = readResponseBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
-          to_bitField0_ |= 0x00000008;
-        }
-        if (addResponseBuilder_ == null) {
-          result.addResponse_ = addResponse_;
-        } else {
-          result.addResponse_ = addResponseBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
-          to_bitField0_ |= 0x00000010;
-        }
-        if (authResponseBuilder_ == null) {
-          result.authResponse_ = authResponse_;
-        } else {
-          result.authResponse_ = authResponseBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
-          to_bitField0_ |= 0x00000020;
-        }
-        if (writeLacResponseBuilder_ == null) {
-          result.writeLacResponse_ = writeLacResponse_;
-        } else {
-          result.writeLacResponse_ = writeLacResponseBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000040) == 0x00000040)) {
-          to_bitField0_ |= 0x00000040;
-        }
-        if (readLacResponseBuilder_ == null) {
-          result.readLacResponse_ = readLacResponse_;
-        } else {
-          result.readLacResponse_ = readLacResponseBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000080) == 0x00000080)) {
-          to_bitField0_ |= 0x00000080;
-        }
-        if (getBookieInfoResponseBuilder_ == null) {
-          result.getBookieInfoResponse_ = getBookieInfoResponse_;
-        } else {
-          result.getBookieInfoResponse_ = getBookieInfoResponseBuilder_.build();
-        }
+        result.requested_ = requested_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
       }
 
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.Response) {
-          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.Response)other);
+        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest) {
+          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.Response other) {
-        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.Response.getDefaultInstance()) return this;
-        if (other.hasHeader()) {
-          mergeHeader(other.getHeader());
-        }
-        if (other.hasStatus()) {
-          setStatus(other.getStatus());
-        }
-        if (other.hasReadResponse()) {
-          mergeReadResponse(other.getReadResponse());
-        }
-        if (other.hasAddResponse()) {
-          mergeAddResponse(other.getAddResponse());
-        }
-        if (other.hasAuthResponse()) {
-          mergeAuthResponse(other.getAuthResponse());
-        }
-        if (other.hasWriteLacResponse()) {
-          mergeWriteLacResponse(other.getWriteLacResponse());
-        }
-        if (other.hasReadLacResponse()) {
-          mergeReadLacResponse(other.getReadLacResponse());
-        }
-        if (other.hasGetBookieInfoResponse()) {
-          mergeGetBookieInfoResponse(other.getGetBookieInfoResponse());
+      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest other) {
+        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest.getDefaultInstance()) return this;
+        if (other.hasRequested()) {
+          setRequested(other.getRequested());
         }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
 
       public final boolean isInitialized() {
-        if (!hasHeader()) {
-          
-          return false;
-        }
-        if (!hasStatus()) {
-          
-          return false;
-        }
-        if (!getHeader().isInitialized()) {
-          
-          return false;
-        }
-        if (hasReadResponse()) {
-          if (!getReadResponse().isInitialized()) {
-            
-            return false;
-          }
-        }
-        if (hasAddResponse()) {
-          if (!getAddResponse().isInitialized()) {
-            
-            return false;
-          }
-        }
-        if (hasAuthResponse()) {
-          if (!getAuthResponse().isInitialized()) {
-            
-            return false;
-          }
-        }
-        if (hasWriteLacResponse()) {
-          if (!getWriteLacResponse().isInitialized()) {
-            
-            return false;
-          }
-        }
-        if (hasReadLacResponse()) {
-          if (!getReadLacResponse().isInitialized()) {
-            
-            return false;
-          }
-        }
-        if (hasGetBookieInfoResponse()) {
-          if (!getGetBookieInfoResponse().isInitialized()) {
-            
-            return false;
-          }
-        }
         return true;
       }
 
@@ -7237,11 +6678,11 @@ public final class BookkeeperProtocol {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.Response parsedMessage = null;
+        org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.Response) e.getUnfinishedMessage();
+          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoRequest) e.getUnfinishedMessage();
           throw e;
         } finally {
           if (parsedMessage != null) {
@@ -7252,922 +6693,3036 @@ public final class BookkeeperProtocol {
       }
       private int bitField0_;
 
-      private org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader header_ = org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.getDefaultInstance();
-      private com.google.protobuf.SingleFieldBuilder<
-          org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader, org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeaderOrBuilder> headerBuilder_;
+      private long requested_ ;
       /**
-       * <code>required .BKPacketHeader header = 1;</code>
+       * <code>optional int64 requested = 1;</code>
+       *
+       * <pre>
+       * bitwise OR of Flags
+       * </pre>
        */
-      public boolean hasHeader() {
+      public boolean hasRequested() {
         return ((bitField0_ & 0x00000001) == 0x00000001);
       }
       /**
-       * <code>required .BKPacketHeader header = 1;</code>
+       * <code>optional int64 requested = 1;</code>
+       *
+       * <pre>
+       * bitwise OR of Flags
+       * </pre>
        */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader getHeader() {
-        if (headerBuilder_ == null) {
-          return header_;
-        } else {
-          return headerBuilder_.getMessage();
-        }
+      public long getRequested() {
+        return requested_;
       }
       /**
-       * <code>required .BKPacketHeader header = 1;</code>
+       * <code>optional int64 requested = 1;</code>
+       *
+       * <pre>
+       * bitwise OR of Flags
+       * </pre>
        */
-      public Builder setHeader(org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader value) {
-        if (headerBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          header_ = value;
-          onChanged();
-        } else {
-          headerBuilder_.setMessage(value);
-        }
+      public Builder setRequested(long value) {
         bitField0_ |= 0x00000001;
+        requested_ = value;
+        onChanged();
         return this;
       }
       /**
-       * <code>required .BKPacketHeader header = 1;</code>
+       * <code>optional int64 requested = 1;</code>
+       *
+       * <pre>
+       * bitwise OR of Flags
+       * </pre>
        */
-      public Builder setHeader(
-          org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.Builder builderForValue) {
-        if (headerBuilder_ == null) {
-          header_ = builderForValue.build();
-          onChanged();
-        } else {
-          headerBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000001;
+      public Builder clearRequested() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        requested_ = 0L;
+        onChanged();
         return this;
       }
-      /**
-       * <code>required .BKPacketHeader header = 1;</code>
-       */
-      public Builder mergeHeader(org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader value) {
-        if (headerBuilder_ == null) {
-          if (((bitField0_ & 0x00000001) == 0x00000001) &&
-              header_ != org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.getDefaultInstance()) {
-            header_ =
-              org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.newBuilder(header_).mergeFrom(value).buildPartial();
+
+      // @@protoc_insertion_point(builder_scope:GetBookieInfoRequest)
+    }
+
+    static {
+      defaultInstance = new GetBookieInfoRequest(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:GetBookieInfoRequest)
+  }
+
+  public interface ResponseOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:Response)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <code>required .BKPacketHeader header = 1;</code>
+     */
+    boolean hasHeader();
+    /**
+     * <code>required .BKPacketHeader header = 1;</code>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader getHeader();
+    /**
+     * <code>required .BKPacketHeader header = 1;</code>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeaderOrBuilder getHeaderOrBuilder();
+
+    /**
+     * <code>required .StatusCode status = 2;</code>
+     *
+     * <pre>
+     * EOK if the underlying request succeeded. Each individual response
+     * has a more meaningful status. EBADREQ if we have an unsupported request.
+     * </pre>
+     */
+    boolean hasStatus();
+    /**
+     * <code>required .StatusCode status = 2;</code>
+     *
+     * <pre>
+     * EOK if the underlying request succeeded. Each individual response
+     * has a more meaningful status. EBADREQ if we have an unsupported request.
+     * </pre>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus();
+
+    /**
+     * <code>optional .ReadResponse readResponse = 100;</code>
+     *
+     * <pre>
+     * Response
+     * </pre>
+     */
+    boolean hasReadResponse();
+    /**
+     * <code>optional .ReadResponse readResponse = 100;</code>
+     *
+     * <pre>
+     * Response
+     * </pre>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse getReadResponse();
+    /**
+     * <code>optional .ReadResponse readResponse = 100;</code>
+     *
+     * <pre>
+     * Response
+     * </pre>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponseOrBuilder getReadResponseOrBuilder();
+
+    /**
+     * <code>optional .AddResponse addResponse = 101;</code>
+     */
+    boolean hasAddResponse();
+    /**
+     * <code>optional .AddResponse addResponse = 101;</code>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse getAddResponse();
+    /**
+     * <code>optional .AddResponse addResponse = 101;</code>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponseOrBuilder getAddResponseOrBuilder();
+
+    /**
+     * <code>optional .AuthMessage authResponse = 102;</code>
+     */
+    boolean hasAuthResponse();
+    /**
+     * <code>optional .AuthMessage authResponse = 102;</code>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage getAuthResponse();
+    /**
+     * <code>optional .AuthMessage authResponse = 102;</code>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessageOrBuilder getAuthResponseOrBuilder();
+
+    /**
+     * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+     */
+    boolean hasWriteLacResponse();
+    /**
+     * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse getWriteLacResponse();
+    /**
+     * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponseOrBuilder getWriteLacResponseOrBuilder();
+
+    /**
+     * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+     */
+    boolean hasReadLacResponse();
+    /**
+     * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse getReadLacResponse();
+    /**
+     * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponseOrBuilder getReadLacResponseOrBuilder();
+
+    /**
+     * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+     */
+    boolean hasGetBookieInfoResponse();
+    /**
+     * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse getGetBookieInfoResponse();
+    /**
+     * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponseOrBuilder getGetBookieInfoResponseOrBuilder();
+
+    /**
+     * <code>optional .StartTLSResponse startTLSResponse = 106;</code>
+     */
+    boolean hasStartTLSResponse();
+    /**
+     * <code>optional .StartTLSResponse startTLSResponse = 106;</code>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse getStartTLSResponse();
+    /**
+     * <code>optional .StartTLSResponse startTLSResponse = 106;</code>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponseOrBuilder getStartTLSResponseOrBuilder();
+  }
+  /**
+   * Protobuf type {@code Response}
+   */
+  public static final class Response extends
+      com.google.protobuf.GeneratedMessage implements
+      // @@protoc_insertion_point(message_implements:Response)
+      ResponseOrBuilder {
+    // Use Response.newBuilder() to construct.
+    private Response(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private Response(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final Response defaultInstance;
+    public static Response getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public Response getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private Response(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.Builder subBuilder = null;
+              if (((bitField0_ & 0x00000001) == 0x00000001)) {
+                subBuilder = header_.toBuilder();
+              }
+              header_ = input.readMessage(org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.PARSER, extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(header_);
+                header_ = subBuilder.buildPartial();
+              }
+              bitField0_ |= 0x00000001;
+              break;
+            }
+            case 16: {
+              int rawValue = input.readEnum();
+              org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode value = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.valueOf(rawValue);
+              if (value == null) {
+                unknownFields.mergeVarintField(2, rawValue);
+              } else {
+                bitField0_ |= 0x00000002;
+                status_ = value;
+              }
+              break;
+            }
+            case 802: {
+              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.Builder subBuilder = null;
+              if (((bitField0_ & 0x00000004) == 0x00000004)) {
+                subBuilder = readResponse_.toBuilder();
+              }
+              readResponse_ = input.readMessage(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.PARSER, extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(readResponse_);
+                readResponse_ = subBuilder.buildPartial();
+              }
+              bitField0_ |= 0x00000004;
+              break;
+            }
+            case 810: {
+              org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.Builder subBuilder = null;
+              if (((bitField0_ & 0x00000008) == 0x00000008)) {
+                subBuilder = addResponse_.toBuilder();
+              }
+              addResponse_ = input.readMessage(org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.PARSER, extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(addResponse_);
+                addResponse_ = subBuilder.buildPartial();
+              }
+              bitField0_ |= 0x00000008;
+              break;
+            }
+            case 818: {
+              org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.Builder subBuilder = null;
+              if (((bitField0_ & 0x00000010) == 0x00000010)) {
+                subBuilder = authResponse_.toBuilder();
+              }
+              authResponse_ = input.readMessage(org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.PARSER, extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(authResponse_);
+                authResponse_ = subBuilder.buildPartial();
+              }
+              bitField0_ |= 0x00000010;
+              break;
+            }
+            case 826: {
+              org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.Builder subBuilder = null;
+              if (((bitField0_ & 0x00000020) == 0x00000020)) {
+                subBuilder = writeLacResponse_.toBuilder();
+              }
+              writeLacResponse_ = input.readMessage(org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.PARSER, extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(writeLacResponse_);
+                writeLacResponse_ = subBuilder.buildPartial();
+              }
+              bitField0_ |= 0x00000020;
+              break;
+            }
+            case 834: {
+              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.Builder subBuilder = null;
+              if (((bitField0_ & 0x00000040) == 0x00000040)) {
+                subBuilder = readLacResponse_.toBuilder();
+              }
+              readLacResponse_ = input.readMessage(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.PARSER, extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(readLacResponse_);
+                readLacResponse_ = subBuilder.buildPartial();
+              }
+              bitField0_ |= 0x00000040;
+              break;
+            }
+            case 842: {
+              org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.Builder subBuilder = null;
+              if (((bitField0_ & 0x00000080) == 0x00000080)) {
+                subBuilder = getBookieInfoResponse_.toBuilder();
+              }
+              getBookieInfoResponse_ = input.readMessage(org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.PARSER, extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(getBookieInfoResponse_);
+                getBookieInfoResponse_ = subBuilder.buildPartial();
+              }
+              bitField0_ |= 0x00000080;
+              break;
+            }
+            case 850: {
+              org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.Builder subBuilder = null;
+              if (((bitField0_ & 0x00000100) == 0x00000100)) {
+                subBuilder = startTLSResponse_.toBuilder();
+              }
+              startTLSResponse_ = input.readMessage(org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.PARSER, extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(startTLSResponse_);
+                startTLSResponse_ = subBuilder.buildPartial();
+              }
+              bitField0_ |= 0x00000100;
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_Response_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_Response_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.apache.bookkeeper.proto.BookkeeperProtocol.Response.class, org.apache.bookkeeper.proto.BookkeeperProtocol.Response.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<Response> PARSER =
+        new com.google.protobuf.AbstractParser<Response>() {
+      public Response parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new Response(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<Response> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    public static final int HEADER_FIELD_NUMBER = 1;
+    private org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader header_;
+    /**
+     * <code>required .BKPacketHeader header = 1;</code>
+     */
+    public boolean hasHeader() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required .BKPacketHeader header = 1;</code>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader getHeader() {
+      return header_;
+    }
+    /**
+     * <code>required .BKPacketHeader header = 1;</code>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeaderOrBuilder getHeaderOrBuilder() {
+      return header_;
+    }
+
+    public static final int STATUS_FIELD_NUMBER = 2;
+    private org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode status_;
+    /**
+     * <code>required .StatusCode status = 2;</code>
+     *
+     * <pre>
+     * EOK if the underlying request succeeded. Each individual response
+     * has a more meaningful status. EBADREQ if we have an unsupported request.
+     * </pre>
+     */
+    public boolean hasStatus() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>required .StatusCode status = 2;</code>
+     *
+     * <pre>
+     * EOK if the underlying request succeeded. Each individual response
+     * has a more meaningful status. EBADREQ if we have an unsupported request.
+     * </pre>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus() {
+      return status_;
+    }
+
+    public static final int READRESPONSE_FIELD_NUMBER = 100;
+    private org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse readResponse_;
+    /**
+     * <code>optional .ReadResponse readResponse = 100;</code>
+     *
+     * <pre>
+     * Response
+     * </pre>
+     */
+    public boolean hasReadResponse() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>optional .ReadResponse readResponse = 100;</code>
+     *
+     * <pre>
+     * Response
+     * </pre>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse getReadResponse() {
+      return readResponse_;
+    }
+    /**
+     * <code>optional .ReadResponse readResponse = 100;</code>
+     *
+     * <pre>
+     * Response
+     * </pre>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponseOrBuilder getReadResponseOrBuilder() {
+      return readResponse_;
+    }
+
+    public static final int ADDRESPONSE_FIELD_NUMBER = 101;
+    private org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse addResponse_;
+    /**
+     * <code>optional .AddResponse addResponse = 101;</code>
+     */
+    public boolean hasAddResponse() {
+      return ((bitField0_ & 0x00000008) == 0x00000008);
+    }
+    /**
+     * <code>optional .AddResponse addResponse = 101;</code>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse getAddResponse() {
+      return addResponse_;
+    }
+    /**
+     * <code>optional .AddResponse addResponse = 101;</code>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponseOrBuilder getAddResponseOrBuilder() {
+      return addResponse_;
+    }
+
+    public static final int AUTHRESPONSE_FIELD_NUMBER = 102;
+    private org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage authResponse_;
+    /**
+     * <code>optional .AuthMessage authResponse = 102;</code>
+     */
+    public boolean hasAuthResponse() {
+      return ((bitField0_ & 0x00000010) == 0x00000010);
+    }
+    /**
+     * <code>optional .AuthMessage authResponse = 102;</code>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage getAuthResponse() {
+      return authResponse_;
+    }
+    /**
+     * <code>optional .AuthMessage authResponse = 102;</code>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessageOrBuilder getAuthResponseOrBuilder() {
+      return authResponse_;
+    }
+
+    public static final int WRITELACRESPONSE_FIELD_NUMBER = 103;
+    private org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse writeLacResponse_;
+    /**
+     * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+     */
+    public boolean hasWriteLacResponse() {
+      return ((bitField0_ & 0x00000020) == 0x00000020);
+    }
+    /**
+     * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse getWriteLacResponse() {
+      return writeLacResponse_;
+    }
+    /**
+     * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponseOrBuilder getWriteLacResponseOrBuilder() {
+      return writeLacResponse_;
+    }
+
+    public static final int READLACRESPONSE_FIELD_NUMBER = 104;
+    private org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse readLacResponse_;
+    /**
+     * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+     */
+    public boolean hasReadLacResponse() {
+      return ((bitField0_ & 0x00000040) == 0x00000040);
+    }
+    /**
+     * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse getReadLacResponse() {
+      return readLacResponse_;
+    }
+    /**
+     * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponseOrBuilder getReadLacResponseOrBuilder() {
+      return readLacResponse_;
+    }
+
+    public static final int GETBOOKIEINFORESPONSE_FIELD_NUMBER = 105;
+    private org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse getBookieInfoResponse_;
+    /**
+     * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+     */
+    public boolean hasGetBookieInfoResponse() {
+      return ((bitField0_ & 0x00000080) == 0x00000080);
+    }
+    /**
+     * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse getGetBookieInfoResponse() {
+      return getBookieInfoResponse_;
+    }
+    /**
+     * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponseOrBuilder getGetBookieInfoResponseOrBuilder() {
+      return getBookieInfoResponse_;
+    }
+
+    public static final int STARTTLSRESPONSE_FIELD_NUMBER = 106;
+    private org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse startTLSResponse_;
+    /**
+     * <code>optional .StartTLSResponse startTLSResponse = 106;</code>
+     */
+    public boolean hasStartTLSResponse() {
+      return ((bitField0_ & 0x00000100) == 0x00000100);
+    }
+    /**
+     * <code>optional .StartTLSResponse startTLSResponse = 106;</code>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse getStartTLSResponse() {
+      return startTLSResponse_;
+    }
+    /**
+     * <code>optional .StartTLSResponse startTLSResponse = 106;</code>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponseOrBuilder getStartTLSResponseOrBuilder() {
+      return startTLSResponse_;
+    }
+
+    private void initFields() {
+      header_ = org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.getDefaultInstance();
+      status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
+      readResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.getDefaultInstance();
+      addResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.getDefaultInstance();
+      authResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.getDefaultInstance();
+      writeLacResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.getDefaultInstance();
+      readLacResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.getDefaultInstance();
+      getBookieInfoResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.getDefaultInstance();
+      startTLSResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.getDefaultInstance();
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      if (!hasHeader()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasStatus()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!getHeader().isInitialized()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (hasReadResponse()) {
+        if (!getReadResponse().isInitialized()) {
+          memoizedIsInitialized = 0;
+          return false;
+        }
+      }
+      if (hasAddResponse()) {
+        if (!getAddResponse().isInitialized()) {
+          memoizedIsInitialized = 0;
+          return false;
+        }
+      }
+      if (hasAuthResponse()) {
+        if (!getAuthResponse().isInitialized()) {
+          memoizedIsInitialized = 0;
+          return false;
+        }
+      }
+      if (hasWriteLacResponse()) {
+        if (!getWriteLacResponse().isInitialized()) {
+          memoizedIsInitialized = 0;
+          return false;
+        }
+      }
+      if (hasReadLacResponse()) {
+        if (!getReadLacResponse().isInitialized()) {
+          memoizedIsInitialized = 0;
+          return false;
+        }
+      }
+      if (hasGetBookieInfoResponse()) {
+        if (!getGetBookieInfoResponse().isInitialized()) {
+          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.writeMessage(1, header_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeEnum(2, status_.getNumber());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeMessage(100, readResponse_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        output.writeMessage(101, addResponse_);
+      }
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        output.writeMessage(102, authResponse_);
+      }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        output.writeMessage(103, writeLacResponse_);
+      }
+      if (((bitField0_ & 0x00000040) == 0x00000040)) {
+        output.writeMessage(104, readLacResponse_);
+      }
+      if (((bitField0_ & 0x00000080) == 0x00000080)) {
+        output.writeMessage(105, getBookieInfoResponse_);
+      }
+      if (((bitField0_ & 0x00000100) == 0x00000100)) {
+        output.writeMessage(106, startTLSResponse_);
+      }
+      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
+          .computeMessageSize(1, header_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeEnumSize(2, status_.getNumber());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(100, readResponse_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(101, addResponse_);
+      }
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(102, authResponse_);
+      }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(103, writeLacResponse_);
+      }
+      if (((bitField0_ & 0x00000040) == 0x00000040)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(104, readLacResponse_);
+      }
+      if (((bitField0_ & 0x00000080) == 0x00000080)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(105, getBookieInfoResponse_);
+      }
+      if (((bitField0_ & 0x00000100) == 0x00000100)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(106, startTLSResponse_);
+      }
+      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.BookkeeperProtocol.Response parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.Response parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.Response 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;
+    }
+    /**
+     * Protobuf type {@code Response}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:Response)
+        org.apache.bookkeeper.proto.BookkeeperProtocol.ResponseOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_Response_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_Response_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.apache.bookkeeper.proto.BookkeeperProtocol.Response.class, org.apache.bookkeeper.proto.BookkeeperProtocol.Response.Builder.class);
+      }
+
+      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.Response.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+          getHeaderFieldBuilder();
+          getReadResponseFieldBuilder();
+          getAddResponseFieldBuilder();
+          getAuthResponseFieldBuilder();
+          getWriteLacResponseFieldBuilder();
+          getReadLacResponseFieldBuilder();
+          getGetBookieInfoResponseFieldBuilder();
+          getStartTLSResponseFieldBuilder();
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        if (headerBuilder_ == null) {
+          header_ = org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.getDefaultInstance();
+        } else {
+          headerBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000001);
+        status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
+        bitField0_ = (bitField0_ & ~0x00000002);
+        if (readResponseBuilder_ == null) {
+          readResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.getDefaultInstance();
+        } else {
+          readResponseBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000004);
+        if (addResponseBuilder_ == null) {
+          addResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.getDefaultInstance();
+        } else {
+          addResponseBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000008);
+        if (authResponseBuilder_ == null) {
+          authResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.getDefaultInstance();
+        } else {
+          authResponseBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000010);
+        if (writeLacResponseBuilder_ == null) {
+          writeLacResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.getDefaultInstance();
+        } else {
+          writeLacResponseBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000020);
+        if (readLacResponseBuilder_ == null) {
+          readLacResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.getDefaultInstance();
+        } else {
+          readLacResponseBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000040);
+        if (getBookieInfoResponseBuilder_ == null) {
+          getBookieInfoResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.getDefaultInstance();
+        } else {
+          getBookieInfoResponseBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000080);
+        if (startTLSResponseBuilder_ == null) {
+          startTLSResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.getDefaultInstance();
+        } else {
+          startTLSResponseBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000100);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_Response_descriptor;
+      }
+
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.Response getDefaultInstanceForType() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.Response.getDefaultInstance();
+      }
+
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.Response build() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.Response result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.Response buildPartial() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.Response result = new org.apache.bookkeeper.proto.BookkeeperProtocol.Response(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        if (headerBuilder_ == null) {
+          result.header_ = header_;
+        } else {
+          result.header_ = headerBuilder_.build();
+        }
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.status_ = status_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        if (readResponseBuilder_ == null) {
+          result.readResponse_ = readResponse_;
+        } else {
+          result.readResponse_ = readResponseBuilder_.build();
+        }
+        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+          to_bitField0_ |= 0x00000008;
+        }
+        if (addResponseBuilder_ == null) {
+          result.addResponse_ = addResponse_;
+        } else {
+          result.addResponse_ = addResponseBuilder_.build();
+        }
+        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+          to_bitField0_ |= 0x00000010;
+        }
+        if (authResponseBuilder_ == null) {
+          result.authResponse_ = authResponse_;
+        } else {
+          result.authResponse_ = authResponseBuilder_.build();
+        }
+        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
+          to_bitField0_ |= 0x00000020;
+        }
+        if (writeLacResponseBuilder_ == null) {
+          result.writeLacResponse_ = writeLacResponse_;
+        } else {
+          result.writeLacResponse_ = writeLacResponseBuilder_.build();
+        }
+        if (((from_bitField0_ & 0x00000040) == 0x00000040)) {
+          to_bitField0_ |= 0x00000040;
+        }
+        if (readLacResponseBuilder_ == null) {
+          result.readLacResponse_ = readLacResponse_;
+        } else {
+          result.readLacResponse_ = readLacResponseBuilder_.build();
+        }
+        if (((from_bitField0_ & 0x00000080) == 0x00000080)) {
+          to_bitField0_ |= 0x00000080;
+        }
+        if (getBookieInfoResponseBuilder_ == null) {
+          result.getBookieInfoResponse_ = getBookieInfoResponse_;
+        } else {
+          result.getBookieInfoResponse_ = getBookieInfoResponseBuilder_.build();
+        }
+        if (((from_bitField0_ & 0x00000100) == 0x00000100)) {
+          to_bitField0_ |= 0x00000100;
+        }
+        if (startTLSResponseBuilder_ == null) {
+          result.startTLSResponse_ = startTLSResponse_;
+        } else {
+          result.startTLSResponse_ = startTLSResponseBuilder_.build();
+        }
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.Response) {
+          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.Response)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.Response other) {
+        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.Response.getDefaultInstance()) return this;
+        if (other.hasHeader()) {
+          mergeHeader(other.getHeader());
+        }
+        if (other.hasStatus()) {
+          setStatus(other.getStatus());
+        }
+        if (other.hasReadResponse()) {
+          mergeReadResponse(other.getReadResponse());
+        }
+        if (other.hasAddResponse()) {
+          mergeAddResponse(other.getAddResponse());
+        }
+        if (other.hasAuthResponse()) {
+          mergeAuthResponse(other.getAuthResponse());
+        }
+        if (other.hasWriteLacResponse()) {
+          mergeWriteLacResponse(other.getWriteLacResponse());
+        }
+        if (other.hasReadLacResponse()) {
+          mergeReadLacResponse(other.getReadLacResponse());
+        }
+        if (other.hasGetBookieInfoResponse()) {
+          mergeGetBookieInfoResponse(other.getGetBookieInfoResponse());
+        }
+        if (other.hasStartTLSResponse()) {
+          mergeStartTLSResponse(other.getStartTLSResponse());
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasHeader()) {
+          
+          return false;
+        }
+        if (!hasStatus()) {
+          
+          return false;
+        }
+        if (!getHeader().isInitialized()) {
+          
+          return false;
+        }
+        if (hasReadResponse()) {
+          if (!getReadResponse().isInitialized()) {
+            
+            return false;
+          }
+        }
+        if (hasAddResponse()) {
+          if (!getAddResponse().isInitialized()) {
+            
+            return false;
+          }
+        }
+        if (hasAuthResponse()) {
+          if (!getAuthResponse().isInitialized()) {
+            
+            return false;
+          }
+        }
+        if (hasWriteLacResponse()) {
+          if (!getWriteLacResponse().isInitialized()) {
+            
+            return false;
+          }
+        }
+        if (hasReadLacResponse()) {
+          if (!getReadLacResponse().isInitialized()) {
+            
+            return false;
+          }
+        }
+        if (hasGetBookieInfoResponse()) {
+          if (!getGetBookieInfoResponse().isInitialized()) {
+            
+            return false;
+          }
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.Response parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.Response) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      private org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader header_ = org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.getDefaultInstance();
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader, org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeaderOrBuilder> headerBuilder_;
+      /**
+       * <code>required .BKPacketHeader header = 1;</code>
+       */
+      public boolean hasHeader() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required .BKPacketHeader header = 1;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader getHeader() {
+        if (headerBuilder_ == null) {
+          return header_;
+        } else {
+          return headerBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>required .BKPacketHeader header = 1;</code>
+       */
+      public Builder setHeader(org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader value) {
+        if (headerBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          header_ = value;
+          onChanged();
+        } else {
+          headerBuilder_.setMessage(value);
+        }
+        bitField0_ |= 0x00000001;
+        return this;
+      }
+      /**
+       * <code>required .BKPacketHeader header = 1;</code>
+       */
+      public Builder setHeader(
+          org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.Builder builderForValue) {
+        if (headerBuilder_ == null) {
+          header_ = builderForValue.build();
+          onChanged();
+        } else {
+          headerBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000001;
+        return this;
+      }
+      /**
+       * <code>required .BKPacketHeader header = 1;</code>
+       */
+      public Builder mergeHeader(org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader value) {
+        if (headerBuilder_ == null) {
+          if (((bitField0_ & 0x00000001) == 0x00000001) &&
+              header_ != org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.getDefaultInstance()) {
+            header_ =
+              org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.newBuilder(header_).mergeFrom(value).buildPartial();
+          } else {
+            header_ = value;
+          }
+          onChanged();
+        } else {
+          headerBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00000001;
+        return this;
+      }
+      /**
+       * <code>required .BKPacketHeader header = 1;</code>
+       */
+      public Builder clearHeader() {
+        if (headerBuilder_ == null) {
+          header_ = org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.getDefaultInstance();
+          onChanged();
+        } else {
+          headerBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000001);
+        return this;
+      }
+      /**
+       * <code>required .BKPacketHeader header = 1;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.Builder getHeaderBuilder() {
+        bitField0_ |= 0x00000001;
+        onChanged();
+        return getHeaderFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>required .BKPacketHeader header = 1;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeaderOrBuilder getHeaderOrBuilder() {
+        if (headerBuilder_ != null) {
+          return headerBuilder_.getMessageOrBuilder();
+        } else {
+          return header_;
+        }
+      }
+      /**
+       * <code>required .BKPacketHeader header = 1;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader, org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeaderOrBuilder> 
+          getHeaderFieldBuilder() {
+        if (headerBuilder_ == null) {
+          headerBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader, org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeaderOrBuilder>(
+                  getHeader(),
+                  getParentForChildren(),
+                  isClean());
+          header_ = null;
+        }
+        return headerBuilder_;
+      }
+
+      private org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
+      /**
+       * <code>required .StatusCode status = 2;</code>
+       *
+       * <pre>
+       * EOK if the underlying request succeeded. Each individual response
+       * has a more meaningful status. EBADREQ if we have an unsupported request.
+       * </pre>
+       */
+      public boolean hasStatus() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>required .StatusCode status = 2;</code>
+       *
+       * <pre>
+       * EOK if the underlying request succeeded. Each individual response
+       * has a more meaningful status. EBADREQ if we have an unsupported request.
+       * </pre>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus() {
+        return status_;
+      }
+      /**
+       * <code>required .StatusCode status = 2;</code>
+       *
+       * <pre>
+       * EOK if the underlying request succeeded. Each individual response
+       * has a more meaningful status. EBADREQ if we have an unsupported request.
+       * </pre>
+       */
+      public Builder setStatus(org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode value) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        bitField0_ |= 0x00000002;
+        status_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required .StatusCode status = 2;</code>
+       *
+       * <pre>
+       * EOK if the underlying request succeeded. Each individual response
+       * has a more meaningful status. EBADREQ if we have an unsupported request.
+       * </pre>
+       */
+      public Builder clearStatus() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
+        onChanged();
+        return this;
+      }
+
+      private org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse readResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.getDefaultInstance();
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponseOrBuilder> readResponseBuilder_;
+      /**
+       * <code>optional .ReadResponse readResponse = 100;</code>
+       *
+       * <pre>
+       * Response
+       * </pre>
+       */
+      public boolean hasReadResponse() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>optional .ReadResponse readResponse = 100;</code>
+       *
+       * <pre>
+       * Response
+       * </pre>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse getReadResponse() {
+        if (readResponseBuilder_ == null) {
+          return readResponse_;
+        } else {
+          return readResponseBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>optional .ReadResponse readResponse = 100;</code>
+       *
+       * <pre>
+       * Response
+       * </pre>
+       */
+      public Builder setReadResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse value) {
+        if (readResponseBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          readResponse_ = value;
+          onChanged();
+        } else {
+          readResponseBuilder_.setMessage(value);
+        }
+        bitField0_ |= 0x00000004;
+        return this;
+      }
+      /**
+       * <code>optional .ReadResponse readResponse = 100;</code>
+       *
+       * <pre>
+       * Response
+       * </pre>
+       */
+      public Builder setReadResponse(
+          org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.Builder builderForValue) {
+        if (readResponseBuilder_ == null) {
+          readResponse_ = builderForValue.build();
+          onChanged();
+        } else {
+          readResponseBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000004;
+        return this;
+      }
+      /**
+       * <code>optional .ReadResponse readResponse = 100;</code>
+       *
+       * <pre>
+       * Response
+       * </pre>
+       */
+      public Builder mergeReadResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse value) {
+        if (readResponseBuilder_ == null) {
+          if (((bitField0_ & 0x00000004) == 0x00000004) &&
+              readResponse_ != org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.getDefaultInstance()) {
+            readResponse_ =
+              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.newBuilder(readResponse_).mergeFrom(value).buildPartial();
+          } else {
+            readResponse_ = value;
+          }
+          onChanged();
+        } else {
+          readResponseBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00000004;
+        return this;
+      }
+      /**
+       * <code>optional .ReadResponse readResponse = 100;</code>
+       *
+       * <pre>
+       * Response
+       * </pre>
+       */
+      public Builder clearReadResponse() {
+        if (readResponseBuilder_ == null) {
+          readResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.getDefaultInstance();
+          onChanged();
+        } else {
+          readResponseBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000004);
+        return this;
+      }
+      /**
+       * <code>optional .ReadResponse readResponse = 100;</code>
+       *
+       * <pre>
+       * Response
+       * </pre>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.Builder getReadResponseBuilder() {
+        bitField0_ |= 0x00000004;
+        onChanged();
+        return getReadResponseFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>optional .ReadResponse readResponse = 100;</code>
+       *
+       * <pre>
+       * Response
+       * </pre>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponseOrBuilder getReadResponseOrBuilder() {
+        if (readResponseBuilder_ != null) {
+          return readResponseBuilder_.getMessageOrBuilder();
+        } else {
+          return readResponse_;
+        }
+      }
+      /**
+       * <code>optional .ReadResponse readResponse = 100;</code>
+       *
+       * <pre>
+       * Response
+       * </pre>
+       */
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponseOrBuilder> 
+          getReadResponseFieldBuilder() {
+        if (readResponseBuilder_ == null) {
+          readResponseBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponseOrBuilder>(
+                  getReadResponse(),
+                  getParentForChildren(),
+                  isClean());
+          readResponse_ = null;
+        }
+        return readResponseBuilder_;
+      }
+
+      private org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse addResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.getDefaultInstance();
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponseOrBuilder> addResponseBuilder_;
+      /**
+       * <code>optional .AddResponse addResponse = 101;</code>
+       */
+      public boolean hasAddResponse() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
+      }
+      /**
+       * <code>optional .AddResponse addResponse = 101;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse getAddResponse() {
+        if (addResponseBuilder_ == null) {
+          return addResponse_;
+        } else {
+          return addResponseBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>optional .AddResponse addResponse = 101;</code>
+       */
+      public Builder setAddResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse value) {
+        if (addResponseBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          addResponse_ = value;
+          onChanged();
+        } else {
+          addResponseBuilder_.setMessage(value);
+        }
+        bitField0_ |= 0x00000008;
+        return this;
+      }
+      /**
+       * <code>optional .AddResponse addResponse = 101;</code>
+       */
+      public Builder setAddResponse(
+          org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.Builder builderForValue) {
+        if (addResponseBuilder_ == null) {
+          addResponse_ = builderForValue.build();
+          onChanged();
+        } else {
+          addResponseBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000008;
+        return this;
+      }
+      /**
+       * <code>optional .AddResponse addResponse = 101;</code>
+       */
+      public Builder mergeAddResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse value) {
+        if (addResponseBuilder_ == null) {
+          if (((bitField0_ & 0x00000008) == 0x00000008) &&
+              addResponse_ != org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.getDefaultInstance()) {
+            addResponse_ =
+              org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.newBuilder(addResponse_).mergeFrom(value).buildPartial();
+          } else {
+            addResponse_ = value;
+          }
+          onChanged();
+        } else {
+          addResponseBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00000008;
+        return this;
+      }
+      /**
+       * <code>optional .AddResponse addResponse = 101;</code>
+       */
+      public Builder clearAddResponse() {
+        if (addResponseBuilder_ == null) {
+          addResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.getDefaultInstance();
+          onChanged();
+        } else {
+          addResponseBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000008);
+        return this;
+      }
+      /**
+       * <code>optional .AddResponse addResponse = 101;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.Builder getAddResponseBuilder() {
+        bitField0_ |= 0x00000008;
+        onChanged();
+        return getAddResponseFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>optional .AddResponse addResponse = 101;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponseOrBuilder getAddResponseOrBuilder() {
+        if (addResponseBuilder_ != null) {
+          return addResponseBuilder_.getMessageOrBuilder();
+        } else {
+          return addResponse_;
+        }
+      }
+      /**
+       * <code>optional .AddResponse addResponse = 101;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponseOrBuilder> 
+          getAddResponseFieldBuilder() {
+        if (addResponseBuilder_ == null) {
+          addResponseBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponseOrBuilder>(
+                  getAddResponse(),
+                  getParentForChildren(),
+                  isClean());
+          addResponse_ = null;
+        }
+        return addResponseBuilder_;
+      }
+
+      private org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage authResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.getDefaultInstance();
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage, org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessageOrBuilder> authResponseBuilder_;
+      /**
+       * <code>optional .AuthMessage authResponse = 102;</code>
+       */
+      public boolean hasAuthResponse() {
+        return ((bitField0_ & 0x00000010) == 0x00000010);
+      }
+      /**
+       * <code>optional .AuthMessage authResponse = 102;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage getAuthResponse() {
+        if (authResponseBuilder_ == null) {
+          return authResponse_;
+        } else {
+          return authResponseBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>optional .AuthMessage authResponse = 102;</code>
+       */
+      public Builder setAuthResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage value) {
+        if (authResponseBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          authResponse_ = value;
+          onChanged();
+        } else {
+          authResponseBuilder_.setMessage(value);
+        }
+        bitField0_ |= 0x00000010;
+        return this;
+      }
+      /**
+       * <code>optional .AuthMessage authResponse = 102;</code>
+       */
+      public Builder setAuthResponse(
+          org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.Builder builderForValue) {
+        if (authResponseBuilder_ == null) {
+          authResponse_ = builderForValue.build();
+          onChanged();
+        } else {
+          authResponseBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000010;
+        return this;
+      }
+      /**
+       * <code>optional .AuthMessage authResponse = 102;</code>
+       */
+      public Builder mergeAuthResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage value) {
+        if (authResponseBuilder_ == null) {
+          if (((bitField0_ & 0x00000010) == 0x00000010) &&
+              authResponse_ != org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.getDefaultInstance()) {
+            authResponse_ =
+              org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.newBuilder(authResponse_).mergeFrom(value).buildPartial();
+          } else {
+            authResponse_ = value;
+          }
+          onChanged();
+        } else {
+          authResponseBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00000010;
+        return this;
+      }
+      /**
+       * <code>optional .AuthMessage authResponse = 102;</code>
+       */
+      public Builder clearAuthResponse() {
+        if (authResponseBuilder_ == null) {
+          authResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.getDefaultInstance();
+          onChanged();
+        } else {
+          authResponseBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000010);
+        return this;
+      }
+      /**
+       * <code>optional .AuthMessage authResponse = 102;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.Builder getAuthResponseBuilder() {
+        bitField0_ |= 0x00000010;
+        onChanged();
+        return getAuthResponseFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>optional .AuthMessage authResponse = 102;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessageOrBuilder getAuthResponseOrBuilder() {
+        if (authResponseBuilder_ != null) {
+          return authResponseBuilder_.getMessageOrBuilder();
+        } else {
+          return authResponse_;
+        }
+      }
+      /**
+       * <code>optional .AuthMessage authResponse = 102;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage, org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessageOrBuilder> 
+          getAuthResponseFieldBuilder() {
+        if (authResponseBuilder_ == null) {
+          authResponseBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage, org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessageOrBuilder>(
+                  getAuthResponse(),
+                  getParentForChildren(),
+                  isClean());
+          authResponse_ = null;
+        }
+        return authResponseBuilder_;
+      }
+
+      private org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse writeLacResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.getDefaultInstance();
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponseOrBuilder> writeLacResponseBuilder_;
+      /**
+       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+       */
+      public boolean hasWriteLacResponse() {
+        return ((bitField0_ & 0x00000020) == 0x00000020);
+      }
+      /**
+       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse getWriteLacResponse() {
+        if (writeLacResponseBuilder_ == null) {
+          return writeLacResponse_;
+        } else {
+          return writeLacResponseBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+       */
+      public Builder setWriteLacResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse value) {
+        if (writeLacResponseBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          writeLacResponse_ = value;
+          onChanged();
+        } else {
+          writeLacResponseBuilder_.setMessage(value);
+        }
+        bitField0_ |= 0x00000020;
+        return this;
+      }
+      /**
+       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+       */
+      public Builder setWriteLacResponse(
+          org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.Builder builderForValue) {
+        if (writeLacResponseBuilder_ == null) {
+          writeLacResponse_ = builderForValue.build();
+          onChanged();
+        } else {
+          writeLacResponseBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000020;
+        return this;
+      }
+      /**
+       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+       */
+      public Builder mergeWriteLacResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse value) {
+        if (writeLacResponseBuilder_ == null) {
+          if (((bitField0_ & 0x00000020) == 0x00000020) &&
+              writeLacResponse_ != org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.getDefaultInstance()) {
+            writeLacResponse_ =
+              org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.newBuilder(writeLacResponse_).mergeFrom(value).buildPartial();
+          } else {
+            writeLacResponse_ = value;
+          }
+          onChanged();
+        } else {
+          writeLacResponseBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00000020;
+        return this;
+      }
+      /**
+       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+       */
+      public Builder clearWriteLacResponse() {
+        if (writeLacResponseBuilder_ == null) {
+          writeLacResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.getDefaultInstance();
+          onChanged();
+        } else {
+          writeLacResponseBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000020);
+        return this;
+      }
+      /**
+       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.Builder getWriteLacResponseBuilder() {
+        bitField0_ |= 0x00000020;
+        onChanged();
+        return getWriteLacResponseFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponseOrBuilder getWriteLacResponseOrBuilder() {
+        if (writeLacResponseBuilder_ != null) {
+          return writeLacResponseBuilder_.getMessageOrBuilder();
+        } else {
+          return writeLacResponse_;
+        }
+      }
+      /**
+       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponseOrBuilder> 
+          getWriteLacResponseFieldBuilder() {
+        if (writeLacResponseBuilder_ == null) {
+          writeLacResponseBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponseOrBuilder>(
+                  getWriteLacResponse(),
+                  getParentForChildren(),
+                  isClean());
+          writeLacResponse_ = null;
+        }
+        return writeLacResponseBuilder_;
+      }
+
+      private org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse readLacResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.getDefaultInstance();
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponseOrBuilder> readLacResponseBuilder_;
+      /**
+       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       */
+      public boolean hasReadLacResponse() {
+        return ((bitField0_ & 0x00000040) == 0x00000040);
+      }
+      /**
+       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse getReadLacResponse() {
+        if (readLacResponseBuilder_ == null) {
+          return readLacResponse_;
+        } else {
+          return readLacResponseBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       */
+      public Builder setReadLacResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse value) {
+        if (readLacResponseBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          readLacResponse_ = value;
+          onChanged();
+        } else {
+          readLacResponseBuilder_.setMessage(value);
+        }
+        bitField0_ |= 0x00000040;
+        return this;
+      }
+      /**
+       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       */
+      public Builder setReadLacResponse(
+          org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.Builder builderForValue) {
+        if (readLacResponseBuilder_ == null) {
+          readLacResponse_ = builderForValue.build();
+          onChanged();
+        } else {
+          readLacResponseBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000040;
+        return this;
+      }
+      /**
+       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       */
+      public Builder mergeReadLacResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse value) {
+        if (readLacResponseBuilder_ == null) {
+          if (((bitField0_ & 0x00000040) == 0x00000040) &&
+              readLacResponse_ != org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.getDefaultInstance()) {
+            readLacResponse_ =
+              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.newBuilder(readLacResponse_).mergeFrom(value).buildPartial();
+          } else {
+            readLacResponse_ = value;
+          }
+          onChanged();
+        } else {
+          readLacResponseBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00000040;
+        return this;
+      }
+      /**
+       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       */
+      public Builder clearReadLacResponse() {
+        if (readLacResponseBuilder_ == null) {
+          readLacResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.getDefaultInstance();
+          onChanged();
+        } else {
+          readLacResponseBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000040);
+        return this;
+      }
+      /**
+       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.Builder getReadLacResponseBuilder() {
+        bitField0_ |= 0x00000040;
+        onChanged();
+        return getReadLacResponseFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponseOrBuilder getReadLacResponseOrBuilder() {
+        if (readLacResponseBuilder_ != null) {
+          return readLacResponseBuilder_.getMessageOrBuilder();
+        } else {
+          return readLacResponse_;
+        }
+      }
+      /**
+       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponseOrBuilder> 
+          getReadLacResponseFieldBuilder() {
+        if (readLacResponseBuilder_ == null) {
+          readLacResponseBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponseOrBuilder>(
+                  getReadLacResponse(),
+                  getParentForChildren(),
+                  isClean());
+          readLacResponse_ = null;
+        }
+        return readLacResponseBuilder_;
+      }
+
+      private org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse getBookieInfoResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.getDefaultInstance();
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponseOrBuilder> getBookieInfoResponseBuilder_;
+      /**
+       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+       */
+      public boolean hasGetBookieInfoResponse() {
+        return ((bitField0_ & 0x00000080) == 0x00000080);
+      }
+      /**
+       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse getGetBookieInfoResponse() {
+        if (getBookieInfoResponseBuilder_ == null) {
+          return getBookieInfoResponse_;
+        } else {
+          return getBookieInfoResponseBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+       */
+      public Builder setGetBookieInfoResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse value) {
+        if (getBookieInfoResponseBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          getBookieInfoResponse_ = value;
+          onChanged();
+        } else {
+          getBookieInfoResponseBuilder_.setMessage(value);
+        }
+        bitField0_ |= 0x00000080;
+        return this;
+      }
+      /**
+       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+       */
+      public Builder setGetBookieInfoResponse(
+          org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.Builder builderForValue) {
+        if (getBookieInfoResponseBuilder_ == null) {
+          getBookieInfoResponse_ = builderForValue.build();
+          onChanged();
+        } else {
+          getBookieInfoResponseBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000080;
+        return this;
+      }
+      /**
+       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+       */
+      public Builder mergeGetBookieInfoResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse value) {
+        if (getBookieInfoResponseBuilder_ == null) {
+          if (((bitField0_ & 0x00000080) == 0x00000080) &&
+              getBookieInfoResponse_ != org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.getDefaultInstance()) {
+            getBookieInfoResponse_ =
+              org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.newBuilder(getBookieInfoResponse_).mergeFrom(value).buildPartial();
           } else {
-            header_ = value;
+            getBookieInfoResponse_ = value;
+          }
+          onChanged();
+        } else {
+          getBookieInfoResponseBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00000080;
+        return this;
+      }
+      /**
+       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+       */
+      public Builder clearGetBookieInfoResponse() {
+        if (getBookieInfoResponseBuilder_ == null) {
+          getBookieInfoResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.getDefaultInstance();
+          onChanged();
+        } else {
+          getBookieInfoResponseBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000080);
+        return this;
+      }
+      /**
+       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.Builder getGetBookieInfoResponseBuilder() {
+        bitField0_ |= 0x00000080;
+        onChanged();
+        return getGetBookieInfoResponseFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponseOrBuilder getGetBookieInfoResponseOrBuilder() {
+        if (getBookieInfoResponseBuilder_ != null) {
+          return getBookieInfoResponseBuilder_.getMessageOrBuilder();
+        } else {
+          return getBookieInfoResponse_;
+        }
+      }
+      /**
+       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponseOrBuilder> 
+          getGetBookieInfoResponseFieldBuilder() {
+        if (getBookieInfoResponseBuilder_ == null) {
+          getBookieInfoResponseBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponseOrBuilder>(
+                  getGetBookieInfoResponse(),
+                  getParentForChildren(),
+                  isClean());
+          getBookieInfoResponse_ = null;
+        }
+        return getBookieInfoResponseBuilder_;
+      }
+
+      private org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse startTLSResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.getDefaultInstance();
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponseOrBuilder> startTLSResponseBuilder_;
+      /**
+       * <code>optional .StartTLSResponse startTLSResponse = 106;</code>
+       */
+      public boolean hasStartTLSResponse() {
+        return ((bitField0_ & 0x00000100) == 0x00000100);
+      }
+      /**
+       * <code>optional .StartTLSResponse startTLSResponse = 106;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse getStartTLSResponse() {
+        if (startTLSResponseBuilder_ == null) {
+          return startTLSResponse_;
+        } else {
+          return startTLSResponseBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>optional .StartTLSResponse startTLSResponse = 106;</code>
+       */
+      public Builder setStartTLSResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse value) {
+        if (startTLSResponseBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          startTLSResponse_ = value;
+          onChanged();
+        } else {
+          startTLSResponseBuilder_.setMessage(value);
+        }
+        bitField0_ |= 0x00000100;
+        return this;
+      }
+      /**
+       * <code>optional .StartTLSResponse startTLSResponse = 106;</code>
+       */
+      public Builder setStartTLSResponse(
+          org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.Builder builderForValue) {
+        if (startTLSResponseBuilder_ == null) {
+          startTLSResponse_ = builderForValue.build();
+          onChanged();
+        } else {
+          startTLSResponseBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000100;
+        return this;
+      }
+      /**
+       * <code>optional .StartTLSResponse startTLSResponse = 106;</code>
+       */
+      public Builder mergeStartTLSResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse value) {
+        if (startTLSResponseBuilder_ == null) {
+          if (((bitField0_ & 0x00000100) == 0x00000100) &&
+              startTLSResponse_ != org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.getDefaultInstance()) {
+            startTLSResponse_ =
+              org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.newBuilder(startTLSResponse_).mergeFrom(value).buildPartial();
+          } else {
+            startTLSResponse_ = value;
+          }
+          onChanged();
+        } else {
+          startTLSResponseBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00000100;
+        return this;
+      }
+      /**
+       * <code>optional .StartTLSResponse startTLSResponse = 106;</code>
+       */
+      public Builder clearStartTLSResponse() {
+        if (startTLSResponseBuilder_ == null) {
+          startTLSResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.getDefaultInstance();
+          onChanged();
+        } else {
+          startTLSResponseBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000100);
+        return this;
+      }
+      /**
+       * <code>optional .StartTLSResponse startTLSResponse = 106;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.Builder getStartTLSResponseBuilder() {
+        bitField0_ |= 0x00000100;
+        onChanged();
+        return getStartTLSResponseFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>optional .StartTLSResponse startTLSResponse = 106;</code>
+       */
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponseOrBuilder getStartTLSResponseOrBuilder() {
+        if (startTLSResponseBuilder_ != null) {
+          return startTLSResponseBuilder_.getMessageOrBuilder();
+        } else {
+          return startTLSResponse_;
+        }
+      }
+      /**
+       * <code>optional .StartTLSResponse startTLSResponse = 106;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponseOrBuilder> 
+          getStartTLSResponseFieldBuilder() {
+        if (startTLSResponseBuilder_ == null) {
+          startTLSResponseBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponseOrBuilder>(
+                  getStartTLSResponse(),
+                  getParentForChildren(),
+                  isClean());
+          startTLSResponse_ = null;
+        }
+        return startTLSResponseBuilder_;
+      }
+
+      // @@protoc_insertion_point(builder_scope:Response)
+    }
+
+    static {
+      defaultInstance = new Response(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:Response)
+  }
+
+  public interface ReadResponseOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:ReadResponse)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <code>required .StatusCode status = 1;</code>
+     */
+    boolean hasStatus();
+    /**
+     * <code>required .StatusCode status = 1;</code>
+     */
+    org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus();
+
+    /**
+     * <code>required int64 ledgerId = 2;</code>
+     */
+    boolean hasLedgerId();
+    /**
+     * <code>required int64 ledgerId = 2;</code>
+     */
+    long getLedgerId();
+
+    /**
+     * <code>required int64 entryId = 3;</code>
+     */
+    boolean hasEntryId();
+    /**
+     * <code>required int64 entryId = 3;</code>
+     */
+    long getEntryId();
+
+    /**
+     * <code>optional bytes body = 4;</code>
+     */
+    boolean hasBody();
+    /**
+     * <code>optional bytes body = 4;</code>
+     */
+    com.google.protobuf.ByteString getBody();
+
+    /**
+     * <code>optional int64 maxLAC = 5;</code>
+     *
+     * <pre>
+     * Piggyback LAC
+     * </pre>
+     */
+    boolean hasMaxLAC();
+    /**
+     * <code>optional int64 maxLAC = 5;</code>
+     *
+     * <pre>
+     * Piggyback LAC
+     * </pre>
+     */
+    long getMaxLAC();
+
+    /**
+     * <code>optional int64 lacUpdateTimestamp = 6;</code>
+     */
+    boolean hasLacUpdateTimestamp();
+    /**
+     * <code>optional int64 lacUpdateTimestamp = 6;</code>
+     */
+    long getLacUpdateTimestamp();
+  }
+  /**
+   * Protobuf type {@code ReadResponse}
+   */
+  public static final class ReadResponse extends
+      com.google.protobuf.GeneratedMessage implements
+      // @@protoc_insertion_point(message_implements:ReadResponse)
+      ReadResponseOrBuilder {
+    // Use ReadResponse.newBuilder() to construct.
+    private ReadResponse(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private ReadResponse(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final ReadResponse defaultInstance;
+    public static ReadResponse getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public ReadResponse getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private ReadResponse(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 8: {
+              int rawValue = input.readEnum();
+              org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode value = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.valueOf(rawValue);
+              if (value == null) {
+                unknownFields.mergeVarintField(1, rawValue);
+              } else {
+                bitField0_ |= 0x00000001;
+                status_ = value;
+              }
+              break;
+            }
+            case 16: {
+              bitField0_ |= 0x00000002;
+              ledgerId_ = input.readInt64();
+              break;
+            }
+            case 24: {
+              bitField0_ |= 0x00000004;
+              entryId_ = input.readInt64();
+              break;
+            }
+            case 34: {
+              bitField0_ |= 0x00000008;
+              body_ = input.readBytes();
+              break;
+            }
+            case 40: {
+              bitField0_ |= 0x00000010;
+              maxLAC_ = input.readInt64();
+              break;
+            }
+            case 48: {
+              bitField0_ |= 0x00000020;
+              lacUpdateTimestamp_ = input.readInt64();
+              break;
+            }
           }
-          onChanged();
-        } else {
-          headerBuilder_.mergeFrom(value);
         }
-        bitField0_ |= 0x00000001;
-        return this;
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
       }
-      /**
-       * <code>required .BKPacketHeader header = 1;</code>
-       */
-      public Builder clearHeader() {
-        if (headerBuilder_ == null) {
-          header_ = org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.getDefaultInstance();
-          onChanged();
-        } else {
-          headerBuilder_.clear();
-        }
-        bitField0_ = (bitField0_ & ~0x00000001);
-        return this;
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadResponse_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadResponse_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<ReadResponse> PARSER =
+        new com.google.protobuf.AbstractParser<ReadResponse>() {
+      public ReadResponse parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new ReadResponse(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<ReadResponse> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    public static final int STATUS_FIELD_NUMBER = 1;
+    private org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode status_;
+    /**
+     * <code>required .StatusCode status = 1;</code>
+     */
+    public boolean hasStatus() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required .StatusCode status = 1;</code>
+     */
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus() {
+      return status_;
+    }
+
+    public static final int LEDGERID_FIELD_NUMBER = 2;
+    private long ledgerId_;
+    /**
+     * <code>required int64 ledgerId = 2;</code>
+     */
+    public boolean hasLedgerId() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>required int64 ledgerId = 2;</code>
+     */
+    public long getLedgerId() {
+      return ledgerId_;
+    }
+
+    public static final int ENTRYID_FIELD_NUMBER = 3;
+    private long entryId_;
+    /**
+     * <code>required int64 entryId = 3;</code>
+     */
+    public boolean hasEntryId() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>required int64 entryId = 3;</code>
+     */
+    public long getEntryId() {
+      return entryId_;
+    }
+
+    public static final int BODY_FIELD_NUMBER = 4;
+    private com.google.protobuf.ByteString body_;
+    /**
+     * <code>optional bytes body = 4;</code>
+     */
+    public boolean hasBody() {
+      return ((bitField0_ & 0x00000008) == 0x00000008);
+    }
+    /**
+     * <code>optional bytes body = 4;</code>
+     */
+    public com.google.protobuf.ByteString getBody() {
+      return body_;
+    }
+
+    public static final int MAXLAC_FIELD_NUMBER = 5;
+    private long maxLAC_;
+    /**
+     * <code>optional int64 maxLAC = 5;</code>
+     *
+     * <pre>
+     * Piggyback LAC
+     * </pre>
+     */
+    public boolean hasMaxLAC() {
+      return ((bitField0_ & 0x00000010) == 0x00000010);
+    }
+    /**
+     * <code>optional int64 maxLAC = 5;</code>
+     *
+     * <pre>
+     * Piggyback LAC
+     * </pre>
+     */
+    public long getMaxLAC() {
+      return maxLAC_;
+    }
+
+    public static final int LACUPDATETIMESTAMP_FIELD_NUMBER = 6;
+    private long lacUpdateTimestamp_;
+    /**
+     * <code>optional int64 lacUpdateTimestamp = 6;</code>
+     */
+    public boolean hasLacUpdateTimestamp() {
+      return ((bitField0_ & 0x00000020) == 0x00000020);
+    }
+    /**
+     * <code>optional int64 lacUpdateTimestamp = 6;</code>
+     */
+    public long getLacUpdateTimestamp() {
+      return lacUpdateTimestamp_;
+    }
+
+    private void initFields() {
+      status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
+      ledgerId_ = 0L;
+      entryId_ = 0L;
+      body_ = com.google.protobuf.ByteString.EMPTY;
+      maxLAC_ = 0L;
+      lacUpdateTimestamp_ = 0L;
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      if (!hasStatus()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasLedgerId()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasEntryId()) {
+        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.writeEnum(1, status_.getNumber());
       }
-      /**
-       * <code>required .BKPacketHeader header = 1;</code>
-       */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.Builder getHeaderBuilder() {
-        bitField0_ |= 0x00000001;
-        onChanged();
-        return getHeaderFieldBuilder().getBuilder();
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeInt64(2, ledgerId_);
       }
-      /**
-       * <code>required .BKPacketHeader header = 1;</code>
-       */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeaderOrBuilder getHeaderOrBuilder() {
-        if (headerBuilder_ != null) {
-          return headerBuilder_.getMessageOrBuilder();
-        } else {
-          return header_;
-        }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeInt64(3, entryId_);
       }
-      /**
-       * <code>required .BKPacketHeader header = 1;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilder<
-          org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader, org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeaderOrBuilder> 
-          getHeaderFieldBuilder() {
-        if (headerBuilder_ == null) {
-          headerBuilder_ = new com.google.protobuf.SingleFieldBuilder<
-              org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader, org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeaderOrBuilder>(
-                  getHeader(),
-                  getParentForChildren(),
-                  isClean());
-          header_ = null;
-        }
-        return headerBuilder_;
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        output.writeBytes(4, body_);
+      }
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        output.writeInt64(5, maxLAC_);
+      }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        output.writeInt64(6, lacUpdateTimestamp_);
       }
+      getUnknownFields().writeTo(output);
+    }
 
-      private org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
-      /**
-       * <code>required .StatusCode status = 2;</code>
-       *
-       * <pre>
-       * EOK if the underlying request succeeded. Each individual response
-       * has a more meaningful status. EBADREQ if we have an unsupported request.
-       * </pre>
-       */
-      public boolean hasStatus() {
-        return ((bitField0_ & 0x00000002) == 0x00000002);
+    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
+          .computeEnumSize(1, status_.getNumber());
       }
-      /**
-       * <code>required .StatusCode status = 2;</code>
-       *
-       * <pre>
-       * EOK if the underlying request succeeded. Each individual response
-       * has a more meaningful status. EBADREQ if we have an unsupported request.
-       * </pre>
-       */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus() {
-        return status_;
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(2, ledgerId_);
       }
-      /**
-       * <code>required .StatusCode status = 2;</code>
-       *
-       * <pre>
-       * EOK if the underlying request succeeded. Each individual response
-       * has a more meaningful status. EBADREQ if we have an unsupported request.
-       * </pre>
-       */
-      public Builder setStatus(org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode value) {
-        if (value == null) {
-          throw new NullPointerException();
-        }
-        bitField0_ |= 0x00000002;
-        status_ = value;
-        onChanged();
-        return this;
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(3, entryId_);
       }
-      /**
-       * <code>required .StatusCode status = 2;</code>
-       *
-       * <pre>
-       * EOK if the underlying request succeeded. Each individual response
-       * has a more meaningful status. EBADREQ if we have an unsupported request.
-       * </pre>
-       */
-      public Builder clearStatus() {
-        bitField0_ = (bitField0_ & ~0x00000002);
-        status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
-        onChanged();
-        return this;
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(4, body_);
       }
-
-      private org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse readResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.getDefaultInstance();
-      private com.google.protobuf.SingleFieldBuilder<
-          org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponseOrBuilder> readResponseBuilder_;
-      /**
-       * <code>optional .ReadResponse readResponse = 100;</code>
-       *
-       * <pre>
-       * Response
-       * </pre>
-       */
-      public boolean hasReadResponse() {
-        return ((bitField0_ & 0x00000004) == 0x00000004);
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(5, maxLAC_);
       }
-      /**
-       * <code>optional .ReadResponse readResponse = 100;</code>
-       *
-       * <pre>
-       * Response
-       * </pre>
-       */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse getReadResponse() {
-        if (readResponseBuilder_ == null) {
-          return readResponse_;
-        } else {
-          return readResponseBuilder_.getMessage();
-        }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(6, lacUpdateTimestamp_);
       }
-      /**
-       * <code>optional .ReadResponse readResponse = 100;</code>
-       *
-       * <pre>
-       * Response
-       * </pre>
-       */
-      public Builder setReadResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse value) {
-        if (readResponseBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          readResponse_ = value;
-          onChanged();
-        } else {
-          readResponseBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000004;
-        return this;
+      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.BookkeeperProtocol.ReadResponse parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse 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;
+    }
+    /**
+     * Protobuf type {@code ReadResponse}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:ReadResponse)
+        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponseOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadResponse_descriptor;
       }
-      /**
-       * <code>optional .ReadResponse readResponse = 100;</code>
-       *
-       * <pre>
-       * Response
-       * </pre>
-       */
-      public Builder setReadResponse(
-          org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.Builder builderForValue) {
-        if (readResponseBuilder_ == null) {
-          readResponse_ = builderForValue.build();
-          onChanged();
-        } else {
-          readResponseBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000004;
-        return this;
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadResponse_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.Builder.class);
       }
-      /**
-       * <code>optional .ReadResponse readResponse = 100;</code>
-       *
-       * <pre>
-       * Response
-       * </pre>
-       */
-      public Builder mergeReadResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse value) {
-        if (readResponseBuilder_ == null) {
-          if (((bitField0_ & 0x00000004) == 0x00000004) &&
-              readResponse_ != org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.getDefaultInstance()) {
-            readResponse_ =
-              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.newBuilder(readResponse_).mergeFrom(value).buildPartial();
-          } else {
-            readResponse_ = value;
-          }
-          onChanged();
-        } else {
-          readResponseBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000004;
-        return this;
+
+      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
       }
-      /**
-       * <code>optional .ReadResponse readResponse = 100;</code>
-       *
-       * <pre>
-       * Response
-       * </pre>
-       */
-      public Builder clearReadResponse() {
-        if (readResponseBuilder_ == null) {
-          readResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.getDefaultInstance();
-          onChanged();
-        } else {
-          readResponseBuilder_.clear();
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.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();
+        status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
+        bitField0_ = (bitField0_ & ~0x00000001);
+        ledgerId_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000002);
+        entryId_ = 0L;
         bitField0_ = (bitField0_ & ~0x00000004);
+        body_ = com.google.protobuf.ByteString.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000008);
+        maxLAC_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000010);
+        lacUpdateTimestamp_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000020);
         return this;
       }
-      /**
-       * <code>optional .ReadResponse readResponse = 100;</code>
-       *
-       * <pre>
-       * Response
-       * </pre>
-       */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.Builder getReadResponseBuilder() {
-        bitField0_ |= 0x00000004;
-        onChanged();
-        return getReadResponseFieldBuilder().getBuilder();
-      }
-      /**
-       * <code>optional .ReadResponse readResponse = 100;</code>
-       *
-       * <pre>
-       * Response
-       * </pre>
-       */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponseOrBuilder getReadResponseOrBuilder() {
-        if (readResponseBuilder_ != null) {
-          return readResponseBuilder_.getMessageOrBuilder();
-        } else {
-          return readResponse_;
-        }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
       }
-      /**
-       * <code>optional .ReadResponse readResponse = 100;</code>
-       *
-       * <pre>
-       * Response
-       * </pre>
-       */
-      private com.google.protobuf.SingleFieldBuilder<
-          org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponseOrBuilder> 
-          getReadResponseFieldBuilder() {
-        if (readResponseBuilder_ == null) {
-          readResponseBuilder_ = new com.google.protobuf.SingleFieldBuilder<
-              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponseOrBuilder>(
-                  getReadResponse(),
-                  getParentForChildren(),
-                  isClean());
-          readResponse_ = null;
-        }
-        return readResponseBuilder_;
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadResponse_descriptor;
       }
 
-      private org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse addResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.getDefaultInstance();
-      private com.google.protobuf.SingleFieldBuilder<
-          org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponseOrBuilder> addResponseBuilder_;
-      /**
-       * <code>optional .AddResponse addResponse = 101;</code>
-       */
-      public boolean hasAddResponse() {
-        return ((bitField0_ & 0x00000008) == 0x00000008);
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse getDefaultInstanceForType() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.getDefaultInstance();
       }
-      /**
-       * <code>optional .AddResponse addResponse = 101;</code>
-       */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse getAddResponse() {
-        if (addResponseBuilder_ == null) {
-          return addResponse_;
-        } else {
-          return addResponseBuilder_.getMessage();
+
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse build() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
         }
+        return result;
       }
-      /**
-       * <code>optional .AddResponse addResponse = 101;</code>
-       */
-      public Builder setAddResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse value) {
-        if (addResponseBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          addResponse_ = value;
-          onChanged();
-        } else {
-          addResponseBuilder_.setMessage(value);
+
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse buildPartial() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse result = new org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
         }
-        bitField0_ |= 0x00000008;
-        return this;
-      }
-      /**
-       * <code>optional .AddResponse addResponse = 101;</code>
-       */
-      public Builder setAddResponse(
-          org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.Builder builderForValue) {
-        if (addResponseBuilder_ == null) {
-          addResponse_ = builderForValue.build();
-          onChanged();
-        } else {
-          addResponseBuilder_.setMessage(builderForValue.build());
+        result.status_ = status_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
         }
-        bitField0_ |= 0x00000008;
-        return this;
-      }
-      /**
-       * <code>optional .AddResponse addResponse = 101;</code>
-       */
-      public Builder mergeAddResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse value) {
-        if (addResponseBuilder_ == null) {
-          if (((bitField0_ & 0x00000008) == 0x00000008) &&
-              addResponse_ != org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.getDefaultInstance()) {
-            addResponse_ =
-              org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.newBuilder(addResponse_).mergeFrom(value).buildPartial();
-          } else {
-            addResponse_ = value;
-          }
-          onChanged();
-        } else {
-          addResponseBuilder_.mergeFrom(value);
+        result.ledgerId_ = ledgerId_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
         }
-        bitField0_ |= 0x00000008;
-        return this;
-      }
-      /**
-       * <code>optional .AddResponse addResponse = 101;</code>
-       */
-      public Builder clearAddResponse() {
-        if (addResponseBuilder_ == null) {
-          addResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.getDefaultInstance();
-          onChanged();
-        } else {
-          addResponseBuilder_.clear();
+        result.entryId_ = entryId_;
+        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+          to_bitField0_ |= 0x00000008;
         }
-        bitField0_ = (bitField0_ & ~0x00000008);
-        return this;
-      }
-      /**
-       * <code>optional .AddResponse addResponse = 101;</code>
-       */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.Builder getAddResponseBuilder() {
-        bitField0_ |= 0x00000008;
-        onChanged();
-        return getAddResponseFieldBuilder().getBuilder();
-      }
-      /**
-       * <code>optional .AddResponse addResponse = 101;</code>
-       */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponseOrBuilder getAddResponseOrBuilder() {
-        if (addResponseBuilder_ != null) {
-          return addResponseBuilder_.getMessageOrBuilder();
-        } else {
-          return addResponse_;
+        result.body_ = body_;
+        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+          to_bitField0_ |= 0x00000010;
         }
-      }
-      /**
-       * <code>optional .AddResponse addResponse = 101;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilder<
-          org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponseOrBuilder> 
-          getAddResponseFieldBuilder() {
-        if (addResponseBuilder_ == null) {
-          addResponseBuilder_ = new com.google.protobuf.SingleFieldBuilder<
-              org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponseOrBuilder>(
-                  getAddResponse(),
-                  getParentForChildren(),
-                  isClean());
-          addResponse_ = null;
+        result.maxLAC_ = maxLAC_;
+        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
+          to_bitField0_ |= 0x00000020;
         }
-        return addResponseBuilder_;
+        result.lacUpdateTimestamp_ = lacUpdateTimestamp_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
       }
 
-      private org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage authResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.getDefaultInstance();
-      private com.google.protobuf.SingleFieldBuilder<
-          org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage, org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessageOrBuilder> authResponseBuilder_;
-      /**
-       * <code>optional .AuthMessage authResponse = 102;</code>
-       */
-      public boolean hasAuthResponse() {
-        return ((bitField0_ & 0x00000010) == 0x00000010);
-      }
-      /**
-       * <code>optional .AuthMessage authResponse = 102;</code>
-       */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage getAuthResponse() {
-        if (authResponseBuilder_ == null) {
-          return authResponse_;
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse) {
+          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse)other);
         } else {
-          return authResponseBuilder_.getMessage();
+          super.mergeFrom(other);
+          return this;
         }
       }
-      /**
-       * <code>optional .AuthMessage authResponse = 102;</code>
-       */
-      public Builder setAuthResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage value) {
-        if (authResponseBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          authResponse_ = value;
-          onChanged();
-        } else {
-          authResponseBuilder_.setMessage(value);
+
+      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse other) {
+        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.getDefaultInstance()) return this;
+        if (other.hasStatus()) {
+          setStatus(other.getStatus());
         }
-        bitField0_ |= 0x00000010;
-        return this;
-      }
-      /**
-       * <code>optional .AuthMessage authResponse = 102;</code>
-       */
-      public Builder setAuthResponse(
-          org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.Builder builderForValue) {
-        if (authResponseBuilder_ == null) {
-          authResponse_ = builderForValue.build();
-          onChanged();
-        } else {
-          authResponseBuilder_.setMessage(builderForValue.build());
+        if (other.hasLedgerId()) {
+          setLedgerId(other.getLedgerId());
         }
-        bitField0_ |= 0x00000010;
-        return this;
-      }
-      /**
-       * <code>optional .AuthMessage authResponse = 102;</code>
-       */
-      public Builder mergeAuthResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage value) {
-        if (authResponseBuilder_ == null) {
-          if (((bitField0_ & 0x00000010) == 0x00000010) &&
-              authResponse_ != org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.getDefaultInstance()) {
-            authResponse_ =
-              org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.newBuilder(authResponse_).mergeFrom(value).buildPartial();
-          } else {
-            authResponse_ = value;
-          }
-          onChanged();
-        } else {
-          authResponseBuilder_.mergeFrom(value);
+        if (other.hasEntryId()) {
+          setEntryId(other.getEntryId());
         }
-        bitField0_ |= 0x00000010;
-        return this;
-      }
-      /**
-       * <code>optional .AuthMessage authResponse = 102;</code>
-       */
-      public Builder clearAuthResponse() {
-        if (authResponseBuilder_ == null) {
-          authResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.getDefaultInstance();
-          onChanged();
-        } else {
-          authResponseBuilder_.clear();
+        if (other.hasBody()) {
+          setBody(other.getBody());
         }
-        bitField0_ = (bitField0_ & ~0x00000010);
-        return this;
-      }
-      /**
-       * <code>optional .AuthMessage authResponse = 102;</code>
-       */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.Builder getAuthResponseBuilder() {
-        bitField0_ |= 0x00000010;
-        onChanged();
-        return getAuthResponseFieldBuilder().getBuilder();
-      }
-      /**
-       * <code>optional .AuthMessage authResponse = 102;</code>
-       */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessageOrBuilder getAuthResponseOrBuilder() {
-        if (authResponseBuilder_ != null) {
-          return authResponseBuilder_.getMessageOrBuilder();
-        } else {
-          return authResponse_;
+        if (other.hasMaxLAC()) {
+          setMaxLAC(other.getMaxLAC());
         }
-      }
-      /**
-       * <code>optional .AuthMessage authResponse = 102;</code>
-       */
-      private com.google.protobuf.SingleFieldBuilder<
-          org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage, org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessageOrBuilder> 
-          getAuthResponseFieldBuilder() {
-        if (authResponseBuilder_ == null) {
-          authResponseBuilder_ = new com.google.protobuf.SingleFieldBuilder<
-              org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage, org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessageOrBuilder>(
-                  getAuthResponse(),
-                  getParentForChildren(),
-                  isClean());
-          authResponse_ = null;
+        if (other.hasLacUpdateTimestamp()) {
+          setLacUpdateTimestamp(other.getLacUpdateTimestamp());
         }
-        return authResponseBuilder_;
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
       }
 
-      private org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse writeLacResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.getDefaultInstance();
-      private com.google.protobuf.SingleFieldBuilder<
-          org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponseOrBuilder> writeLacResponseBuilder_;
-      /**
-       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
-       */
-      public boolean hasWriteLacResponse() {
-        return ((bitField0_ & 0x00000020) == 0x00000020);
-      }
-      /**
-       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
-       */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse getWriteLacResponse() {
-        if (writeLacResponseBuilder_ == null) {
-          return writeLacResponse_;
-        } else {
-          return writeLacResponseBuilder_.getMessage();
+      public final boolean isInitialized() {
+        if (!hasStatus()) {
+          
+          return false;
+        }
+        if (!hasLedgerId()) {
+          
+          return false;
+        }
+        if (!hasEntryId()) {
+          
+          return false;
         }
+        return true;
       }
-      /**
-       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
-       */
-      public Builder setWriteLacResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse value) {
-        if (writeLacResponseBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
           }
-          writeLacResponse_ = value;
-          onChanged();
-        } else {
-          writeLacResponseBuilder_.setMessage(value);
         }
-        bitField0_ |= 0x00000020;
         return this;
       }
+      private int bitField0_;
+
+      private org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
       /**
-       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+       * <code>required .StatusCode status = 1;</code>
        */
-      public Builder setWriteLacResponse(
-          org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.Builder builderForValue) {
-        if (writeLacResponseBuilder_ == null) {
-          writeLacResponse_ = builderForValue.build();
-          onChanged();
-        } else {
-          writeLacResponseBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000020;
-        return this;
+      public boolean hasStatus() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
       }
       /**
-       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+       * <code>required .StatusCode status = 1;</code>
        */
-      public Builder mergeWriteLacResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse value) {
-        if (writeLacResponseBuilder_ == null) {
-          if (((bitField0_ & 0x00000020) == 0x00000020) &&
-              writeLacResponse_ != org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.getDefaultInstance()) {
-            writeLacResponse_ =
-              org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.newBuilder(writeLacResponse_).mergeFrom(value).buildPartial();
-          } else {
-            writeLacResponse_ = value;
-          }
-          onChanged();
-        } else {
-          writeLacResponseBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000020;
-        return this;
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus() {
+        return status_;
       }
       /**
-       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+       * <code>required .StatusCode status = 1;</code>
        */
-      public Builder clearWriteLacResponse() {
-        if (writeLacResponseBuilder_ == null) {
-          writeLacResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.getDefaultInstance();
-          onChanged();
-        } else {
-          writeLacResponseBuilder_.clear();
+      public Builder setStatus(org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode value) {
+        if (value == null) {
+          throw new NullPointerException();
         }
-        bitField0_ = (bitField0_ & ~0x00000020);
+        bitField0_ |= 0x00000001;
+        status_ = value;
+        onChanged();
         return this;
       }
       /**
-       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+       * <code>required .StatusCode status = 1;</code>
        */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.Builder getWriteLacResponseBuilder() {
-        bitField0_ |= 0x00000020;
+      public Builder clearStatus() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
         onChanged();
-        return getWriteLacResponseFieldBuilder().getBuilder();
+        return this;
       }
+
+      private long ledgerId_ ;
       /**
-       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+       * <code>required int64 ledgerId = 2;</code>
        */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponseOrBuilder getWriteLacResponseOrBuilder() {
-        if (writeLacResponseBuilder_ != null) {
-          return writeLacResponseBuilder_.getMessageOrBuilder();
-        } else {
-          return writeLacResponse_;
-        }
+      public boolean hasLedgerId() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
       }
       /**
-       * <code>optional .WriteLacResponse writeLacResponse = 103;</code>
+       * <code>required int64 ledgerId = 2;</code>
        */
-      private com.google.protobuf.SingleFieldBuilder<
-          org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponseOrBuilder> 
-          getWriteLacResponseFieldBuilder() {
-        if (writeLacResponseBuilder_ == null) {
-          writeLacResponseBuilder_ = new com.google.protobuf.SingleFieldBuilder<
-              org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponseOrBuilder>(
-                  getWriteLacResponse(),
-                  getParentForChildren(),
-                  isClean());
-          writeLacResponse_ = null;
-        }
-        return writeLacResponseBuilder_;
+      public long getLedgerId() {
+        return ledgerId_;
       }
-
-      private org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse readLacResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.getDefaultInstance();
-      private com.google.protobuf.SingleFieldBuilder<
-          org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponseOrBuilder> readLacResponseBuilder_;
       /**
-       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       * <code>required int64 ledgerId = 2;</code>
        */
-      public boolean hasReadLacResponse() {
-        return ((bitField0_ & 0x00000040) == 0x00000040);
+      public Builder setLedgerId(long value) {
+        bitField0_ |= 0x00000002;
+        ledgerId_ = value;
+        onChanged();
+        return this;
       }
       /**
-       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       * <code>required int64 ledgerId = 2;</code>
        */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse getReadLacResponse() {
-        if (readLacResponseBuilder_ == null) {
-          return readLacResponse_;
-        } else {
-          return readLacResponseBuilder_.getMessage();
-        }
+      public Builder clearLedgerId() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        ledgerId_ = 0L;
+        onChanged();
+        return this;
       }
+
+      private long entryId_ ;
       /**
-       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       * <code>required int64 entryId = 3;</code>
        */
-      public Builder setReadLacResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse value) {
-        if (readLacResponseBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          readLacResponse_ = value;
-          onChanged();
-        } else {
-          readLacResponseBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000040;
-        return this;
+      public boolean hasEntryId() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
       }
       /**
-       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       * <code>required int64 entryId = 3;</code>
        */
-      public Builder setReadLacResponse(
-          org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.Builder builderForValue) {
-        if (readLacResponseBuilder_ == null) {
-          readLacResponse_ = builderForValue.build();
-          onChanged();
-        } else {
-          readLacResponseBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000040;
-        return this;
+      public long getEntryId() {
+        return entryId_;
       }
       /**
-       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       * <code>required int64 entryId = 3;</code>
        */
-      public Builder mergeReadLacResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse value) {
-        if (readLacResponseBuilder_ == null) {
-          if (((bitField0_ & 0x00000040) == 0x00000040) &&
-              readLacResponse_ != org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.getDefaultInstance()) {
-            readLacResponse_ =
-              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.newBuilder(readLacResponse_).mergeFrom(value).buildPartial();
-          } else {
-            readLacResponse_ = value;
-          }
-          onChanged();
-        } else {
-          readLacResponseBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000040;
+      public Builder setEntryId(long value) {
+        bitField0_ |= 0x00000004;
+        entryId_ = value;
+        onChanged();
         return this;
       }
       /**
-       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       * <code>required int64 entryId = 3;</code>
        */
-      public Builder clearReadLacResponse() {
-        if (readLacResponseBuilder_ == null) {
-          readLacResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.getDefaultInstance();
-          onChanged();
-        } else {
-          readLacResponseBuilder_.clear();
-        }
-        bitField0_ = (bitField0_ & ~0x00000040);
+      public Builder clearEntryId() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        entryId_ = 0L;
+        onChanged();
         return this;
       }
+
+      private com.google.protobuf.ByteString body_ = com.google.protobuf.ByteString.EMPTY;
       /**
-       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       * <code>optional bytes body = 4;</code>
        */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.Builder getReadLacResponseBuilder() {
-        bitField0_ |= 0x00000040;
-        onChanged();
-        return getReadLacResponseFieldBuilder().getBuilder();
+      public boolean hasBody() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
       }
       /**
-       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       * <code>optional bytes body = 4;</code>
        */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponseOrBuilder getReadLacResponseOrBuilder() {
-        if (readLacResponseBuilder_ != null) {
-          return readLacResponseBuilder_.getMessageOrBuilder();
-        } else {
-          return readLacResponse_;
-        }
+      public com.google.protobuf.ByteString getBody() {
+        return body_;
       }
       /**
-       * <code>optional .ReadLacResponse readLacResponse = 104;</code>
+       * <code>optional bytes body = 4;</code>
        */
-      private com.google.protobuf.SingleFieldBuilder<
-          org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponseOrBuilder> 
-          getReadLacResponseFieldBuilder() {
-        if (readLacResponseBuilder_ == null) {
-          readLacResponseBuilder_ = new com.google.protobuf.SingleFieldBuilder<
-              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponseOrBuilder>(
-                  getReadLacResponse(),
-                  getParentForChildren(),
-                  isClean());
-          readLacResponse_ = null;
-        }
-        return readLacResponseBuilder_;
+      public Builder setBody(com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000008;
+        body_ = value;
+        onChanged();
+        return this;
       }
-
-      private org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse getBookieInfoResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.getDefaultInstance();
-      private com.google.protobuf.SingleFieldBuilder<
-          org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponseOrBuilder> getBookieInfoResponseBuilder_;
       /**
-       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+       * <code>optional bytes body = 4;</code>
        */
-      public boolean hasGetBookieInfoResponse() {
-        return ((bitField0_ & 0x00000080) == 0x00000080);
+      public Builder clearBody() {
+        bitField0_ = (bitField0_ & ~0x00000008);
+        body_ = getDefaultInstance().getBody();
+        onChanged();
+        return this;
       }
+
+      private long maxLAC_ ;
       /**
-       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+       * <code>optional int64 maxLAC = 5;</code>
+       *
+       * <pre>
+       * Piggyback LAC
+       * </pre>
        */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse getGetBookieInfoResponse() {
-        if (getBookieInfoResponseBuilder_ == null) {
-          return getBookieInfoResponse_;
-        } else {
-          return getBookieInfoResponseBuilder_.getMessage();
-        }
+      public boolean hasMaxLAC() {
+        return ((bitField0_ & 0x00000010) == 0x00000010);
       }
       /**
-       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+       * <code>optional int64 maxLAC = 5;</code>
+       *
+       * <pre>
+       * Piggyback LAC
+       * </pre>
        */
-      public Builder setGetBookieInfoResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse value) {
-        if (getBookieInfoResponseBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          getBookieInfoResponse_ = value;
-          onChanged();
-        } else {
-          getBookieInfoResponseBuilder_.setMessage(value);
-        }
-        bitField0_ |= 0x00000080;
-        return this;
+      public long getMaxLAC() {
+        return maxLAC_;
       }
       /**
-       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+       * <code>optional int64 maxLAC = 5;</code>
+       *
+       * <pre>
+       * Piggyback LAC
+       * </pre>
        */
-      public Builder setGetBookieInfoResponse(
-          org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.Builder builderForValue) {
-        if (getBookieInfoResponseBuilder_ == null) {
-          getBookieInfoResponse_ = builderForValue.build();
-          onChanged();
-        } else {
-          getBookieInfoResponseBuilder_.setMessage(builderForValue.build());
-        }
-        bitField0_ |= 0x00000080;
+      public Builder setMaxLAC(long value) {
+        bitField0_ |= 0x00000010;
+        maxLAC_ = value;
+        onChanged();
         return this;
       }
       /**
-       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
-       */
-      public Builder mergeGetBookieInfoResponse(org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse value) {
-        if (getBookieInfoResponseBuilder_ == null) {
-          if (((bitField0_ & 0x00000080) == 0x00000080) &&
-              getBookieInfoResponse_ != org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.getDefaultInstance()) {
-            getBookieInfoResponse_ =
-              org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.newBuilder(getBookieInfoResponse_).mergeFrom(value).buildPartial();
-          } else {
-            getBookieInfoResponse_ = value;
-          }
-          onChanged();
-        } else {
-          getBookieInfoResponseBuilder_.mergeFrom(value);
-        }
-        bitField0_ |= 0x00000080;
+       * <code>optional int64 maxLAC = 5;</code>
+       *
+       * <pre>
+       * Piggyback LAC
+       * </pre>
+       */
+      public Builder clearMaxLAC() {
+        bitField0_ = (bitField0_ & ~0x00000010);
+        maxLAC_ = 0L;
+        onChanged();
         return this;
       }
+
+      private long lacUpdateTimestamp_ ;
       /**
-       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+       * <code>optional int64 lacUpdateTimestamp = 6;</code>
        */
-      public Builder clearGetBookieInfoResponse() {
-        if (getBookieInfoResponseBuilder_ == null) {
-          getBookieInfoResponse_ = org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.getDefaultInstance();
-          onChanged();
-        } else {
-          getBookieInfoResponseBuilder_.clear();
-        }
-        bitField0_ = (bitField0_ & ~0x00000080);
-        return this;
+      public boolean hasLacUpdateTimestamp() {
+        return ((bitField0_ & 0x00000020) == 0x00000020);
       }
       /**
-       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+       * <code>optional int64 lacUpdateTimestamp = 6;</code>
        */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.Builder getGetBookieInfoResponseBuilder() {
-        bitField0_ |= 0x00000080;
-        onChanged();
-        return getGetBookieInfoResponseFieldBuilder().getBuilder();
+      public long getLacUpdateTimestamp() {
+        return lacUpdateTimestamp_;
       }
       /**
-       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+       * <code>optional int64 lacUpdateTimestamp = 6;</code>
        */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponseOrBuilder getGetBookieInfoResponseOrBuilder() {
-        if (getBookieInfoResponseBuilder_ != null) {
-          return getBookieInfoResponseBuilder_.getMessageOrBuilder();
-        } else {
-          return getBookieInfoResponse_;
-        }
+      public Builder setLacUpdateTimestamp(long value) {
+        bitField0_ |= 0x00000020;
+        lacUpdateTimestamp_ = value;
+        onChanged();
+        return this;
       }
       /**
-       * <code>optional .GetBookieInfoResponse getBookieInfoResponse = 105;</code>
+       * <code>optional int64 lacUpdateTimestamp = 6;</code>
        */
-      private com.google.protobuf.SingleFieldBuilder<
-          org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponseOrBuilder> 
-          getGetBookieInfoResponseFieldBuilder() {
-        if (getBookieInfoResponseBuilder_ == null) {
-          getBookieInfoResponseBuilder_ = new com.google.protobuf.SingleFieldBuilder<
-              org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.Builder, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponseOrBuilder>(
-                  getGetBookieInfoResponse(),
-                  getParentForChildren(),
-                  isClean());
-          getBookieInfoResponse_ = null;
-        }
-        return getBookieInfoResponseBuilder_;
+      public Builder clearLacUpdateTimestamp() {
+        bitField0_ = (bitField0_ & ~0x00000020);
+        lacUpdateTimestamp_ = 0L;
+        onChanged();
+        return this;
       }
 
-      // @@protoc_insertion_point(builder_scope:Response)
+      // @@protoc_insertion_point(builder_scope:ReadResponse)
     }
 
     static {
-      defaultInstance = new Response(true);
+      defaultInstance = new ReadResponse(true);
       defaultInstance.initFields();
     }
 
-    // @@protoc_insertion_point(class_scope:Response)
+    // @@protoc_insertion_point(class_scope:ReadResponse)
   }
 
-  public interface ReadResponseOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:ReadResponse)
+  public interface AddResponseOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:AddResponse)
       com.google.protobuf.MessageOrBuilder {
 
     /**
@@ -8196,62 +9751,27 @@ public final class BookkeeperProtocol {
      * <code>required int64 entryId = 3;</code>
      */
     long getEntryId();
-
-    /**
-     * <code>optional bytes body = 4;</code>
-     */
-    boolean hasBody();
-    /**
-     * <code>optional bytes body = 4;</code>
-     */
-    com.google.protobuf.ByteString getBody();
-
-    /**
-     * <code>optional int64 maxLAC = 5;</code>
-     *
-     * <pre>
-     * Piggyback LAC
-     * </pre>
-     */
-    boolean hasMaxLAC();
-    /**
-     * <code>optional int64 maxLAC = 5;</code>
-     *
-     * <pre>
-     * Piggyback LAC
-     * </pre>
-     */
-    long getMaxLAC();
-
-    /**
-     * <code>optional int64 lacUpdateTimestamp = 6;</code>
-     */
-    boolean hasLacUpdateTimestamp();
-    /**
-     * <code>optional int64 lacUpdateTimestamp = 6;</code>
-     */
-    long getLacUpdateTimestamp();
   }
   /**
-   * Protobuf type {@code ReadResponse}
+   * Protobuf type {@code AddResponse}
    */
-  public static final class ReadResponse extends
+  public static final class AddResponse extends
       com.google.protobuf.GeneratedMessage implements
-      // @@protoc_insertion_point(message_implements:ReadResponse)
-      ReadResponseOrBuilder {
-    // Use ReadResponse.newBuilder() to construct.
-    private ReadResponse(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      // @@protoc_insertion_point(message_implements:AddResponse)
+      AddResponseOrBuilder {
+    // Use AddResponse.newBuilder() to construct.
+    private AddResponse(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
       super(builder);
       this.unknownFields = builder.getUnknownFields();
     }
-    private ReadResponse(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+    private AddResponse(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
 
-    private static final ReadResponse defaultInstance;
-    public static ReadResponse getDefaultInstance() {
+    private static final AddResponse defaultInstance;
+    public static AddResponse getDefaultInstance() {
       return defaultInstance;
     }
 
-    public ReadResponse getDefaultInstanceForType() {
+    public AddResponse getDefaultInstanceForType() {
       return defaultInstance;
     }
 
@@ -8261,7 +9781,7 @@ public final class BookkeeperProtocol {
         getUnknownFields() {
       return this.unknownFields;
     }
-    private ReadResponse(
+    private AddResponse(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -8305,21 +9825,6 @@ public final class BookkeeperProtocol {
               entryId_ = input.readInt64();
               break;
             }
-            case 34: {
-              bitField0_ |= 0x00000008;
-              body_ = input.readBytes();
-              break;
-            }
-            case 40: {
-              bitField0_ |= 0x00000010;
-              maxLAC_ = input.readInt64();
-              break;
-            }
-            case 48: {
-              bitField0_ |= 0x00000020;
-              lacUpdateTimestamp_ = input.readInt64();
-              break;
-            }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -8334,28 +9839,28 @@ public final class BookkeeperProtocol {
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadResponse_descriptor;
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AddResponse_descriptor;
     }
 
     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadResponse_fieldAccessorTable
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AddResponse_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.Builder.class);
+              org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.Builder.class);
     }
 
-    public static com.google.protobuf.Parser<ReadResponse> PARSER =
-        new com.google.protobuf.AbstractParser<ReadResponse>() {
-      public ReadResponse parsePartialFrom(
+    public static com.google.protobuf.Parser<AddResponse> PARSER =
+        new com.google.protobuf.AbstractParser<AddResponse>() {
+      public AddResponse parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new ReadResponse(input, extensionRegistry);
+        return new AddResponse(input, extensionRegistry);
       }
     };
 
     @java.lang.Override
-    public com.google.protobuf.Parser<ReadResponse> getParserForType() {
+    public com.google.protobuf.Parser<AddResponse> getParserForType() {
       return PARSER;
     }
 
@@ -8405,66 +9910,10 @@ public final class BookkeeperProtocol {
       return entryId_;
     }
 
-    public static final int BODY_FIELD_NUMBER = 4;
-    private com.google.protobuf.ByteString body_;
-    /**
-     * <code>optional bytes body = 4;</code>
-     */
-    public boolean hasBody() {
-      return ((bitField0_ & 0x00000008) == 0x00000008);
-    }
-    /**
-     * <code>optional bytes body = 4;</code>
-     */
-    public com.google.protobuf.ByteString getBody() {
-      return body_;
-    }
-
-    public static final int MAXLAC_FIELD_NUMBER = 5;
-    private long maxLAC_;
-    /**
-     * <code>optional int64 maxLAC = 5;</code>
-     *
-     * <pre>
-     * Piggyback LAC
-     * </pre>
-     */
-    public boolean hasMaxLAC() {
-      return ((bitField0_ & 0x00000010) == 0x00000010);
-    }
-    /**
-     * <code>optional int64 maxLAC = 5;</code>
-     *
-     * <pre>
-     * Piggyback LAC
-     * </pre>
-     */
-    public long getMaxLAC() {
-      return maxLAC_;
-    }
-
-    public static final int LACUPDATETIMESTAMP_FIELD_NUMBER = 6;
-    private long lacUpdateTimestamp_;
-    /**
-     * <code>optional int64 lacUpdateTimestamp = 6;</code>
-     */
-    public boolean hasLacUpdateTimestamp() {
-      return ((bitField0_ & 0x00000020) == 0x00000020);
-    }
-    /**
-     * <code>optional int64 lacUpdateTimestamp = 6;</code>
-     */
-    public long getLacUpdateTimestamp() {
-      return lacUpdateTimestamp_;
-    }
-
     private void initFields() {
       status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
       ledgerId_ = 0L;
       entryId_ = 0L;
-      body_ = com.google.protobuf.ByteString.EMPTY;
-      maxLAC_ = 0L;
-      lacUpdateTimestamp_ = 0L;
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
@@ -8500,15 +9949,6 @@ public final class BookkeeperProtocol {
       if (((bitField0_ & 0x00000004) == 0x00000004)) {
         output.writeInt64(3, entryId_);
       }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
-        output.writeBytes(4, body_);
-      }
-      if (((bitField0_ & 0x00000010) == 0x00000010)) {
-        output.writeInt64(5, maxLAC_);
-      }
-      if (((bitField0_ & 0x00000020) == 0x00000020)) {
-        output.writeInt64(6, lacUpdateTimestamp_);
-      }
       getUnknownFields().writeTo(output);
     }
 
@@ -8530,18 +9970,6 @@ public final class BookkeeperProtocol {
         size += com.google.protobuf.CodedOutputStream
           .computeInt64Size(3, entryId_);
       }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeBytesSize(4, body_);
-      }
-      if (((bitField0_ & 0x00000010) == 0x00000010)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(5, maxLAC_);
-      }
-      if (((bitField0_ & 0x00000020) == 0x00000020)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(6, lacUpdateTimestamp_);
-      }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
       return size;
@@ -8554,53 +9982,53 @@ public final class BookkeeperProtocol {
       return super.writeReplace();
     }
 
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseFrom(byte[] data)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseDelimitedFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseDelimitedFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -8609,7 +10037,7 @@ public final class BookkeeperProtocol {
 
     public static Builder newBuilder() { return Builder.create(); }
     public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse prototype) {
+    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse prototype) {
       return newBuilder().mergeFrom(prototype);
     }
     public Builder toBuilder() { return newBuilder(this); }
@@ -8621,25 +10049,25 @@ public final class BookkeeperProtocol {
       return builder;
     }
     /**
-     * Protobuf type {@code ReadResponse}
+     * Protobuf type {@code AddResponse}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:ReadResponse)
-        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponseOrBuilder {
+        // @@protoc_insertion_point(builder_implements:AddResponse)
+        org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponseOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadResponse_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AddResponse_descriptor;
       }
 
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadResponse_fieldAccessorTable
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AddResponse_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.Builder.class);
+                org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.Builder.class);
       }
 
-      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.newBuilder()
+      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -8665,12 +10093,6 @@ public final class BookkeeperProtocol {
         bitField0_ = (bitField0_ & ~0x00000002);
         entryId_ = 0L;
         bitField0_ = (bitField0_ & ~0x00000004);
-        body_ = com.google.protobuf.ByteString.EMPTY;
-        bitField0_ = (bitField0_ & ~0x00000008);
-        maxLAC_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000010);
-        lacUpdateTimestamp_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000020);
         return this;
       }
 
@@ -8680,23 +10102,23 @@ public final class BookkeeperProtocol {
 
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadResponse_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AddResponse_descriptor;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse getDefaultInstanceForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.getDefaultInstance();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse getDefaultInstanceForType() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.getDefaultInstance();
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse build() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse result = buildPartial();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse build() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
         return result;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse buildPartial() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse result = new org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse(this);
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse buildPartial() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse result = new org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse(this);
         int from_bitField0_ = bitField0_;
         int to_bitField0_ = 0;
         if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
@@ -8711,34 +10133,22 @@ public final class BookkeeperProtocol {
           to_bitField0_ |= 0x00000004;
         }
         result.entryId_ = entryId_;
-        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
-          to_bitField0_ |= 0x00000008;
-        }
-        result.body_ = body_;
-        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
-          to_bitField0_ |= 0x00000010;
-        }
-        result.maxLAC_ = maxLAC_;
-        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
-          to_bitField0_ |= 0x00000020;
-        }
-        result.lacUpdateTimestamp_ = lacUpdateTimestamp_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
       }
 
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse) {
-          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse)other);
+        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse) {
+          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse other) {
-        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse.getDefaultInstance()) return this;
+      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse other) {
+        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.getDefaultInstance()) return this;
         if (other.hasStatus()) {
           setStatus(other.getStatus());
         }
@@ -8748,15 +10158,6 @@ public final class BookkeeperProtocol {
         if (other.hasEntryId()) {
           setEntryId(other.getEntryId());
         }
-        if (other.hasBody()) {
-          setBody(other.getBody());
-        }
-        if (other.hasMaxLAC()) {
-          setMaxLAC(other.getMaxLAC());
-        }
-        if (other.hasLacUpdateTimestamp()) {
-          setLacUpdateTimestamp(other.getLacUpdateTimestamp());
-        }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
@@ -8781,11 +10182,11 @@ public final class BookkeeperProtocol {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse parsedMessage = null;
+        org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.ReadResponse) e.getUnfinishedMessage();
+          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse) e.getUnfinishedMessage();
           throw e;
         } finally {
           if (parsedMessage != null) {
@@ -8895,183 +10296,64 @@ public final class BookkeeperProtocol {
         return this;
       }
 
-      private com.google.protobuf.ByteString body_ = com.google.protobuf.ByteString.EMPTY;
-      /**
-       * <code>optional bytes body = 4;</code>
-       */
-      public boolean hasBody() {
-        return ((bitField0_ & 0x00000008) == 0x00000008);
-      }
-      /**
-       * <code>optional bytes body = 4;</code>
-       */
-      public com.google.protobuf.ByteString getBody() {
-        return body_;
-      }
-      /**
-       * <code>optional bytes body = 4;</code>
-       */
-      public Builder setBody(com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000008;
-        body_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>optional bytes body = 4;</code>
-       */
-      public Builder clearBody() {
-        bitField0_ = (bitField0_ & ~0x00000008);
-        body_ = getDefaultInstance().getBody();
-        onChanged();
-        return this;
-      }
-
-      private long maxLAC_ ;
-      /**
-       * <code>optional int64 maxLAC = 5;</code>
-       *
-       * <pre>
-       * Piggyback LAC
-       * </pre>
-       */
-      public boolean hasMaxLAC() {
-        return ((bitField0_ & 0x00000010) == 0x00000010);
-      }
-      /**
-       * <code>optional int64 maxLAC = 5;</code>
-       *
-       * <pre>
-       * Piggyback LAC
-       * </pre>
-       */
-      public long getMaxLAC() {
-        return maxLAC_;
-      }
-      /**
-       * <code>optional int64 maxLAC = 5;</code>
-       *
-       * <pre>
-       * Piggyback LAC
-       * </pre>
-       */
-      public Builder setMaxLAC(long value) {
-        bitField0_ |= 0x00000010;
-        maxLAC_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>optional int64 maxLAC = 5;</code>
-       *
-       * <pre>
-       * Piggyback LAC
-       * </pre>
-       */
-      public Builder clearMaxLAC() {
-        bitField0_ = (bitField0_ & ~0x00000010);
-        maxLAC_ = 0L;
-        onChanged();
-        return this;
-      }
-
-      private long lacUpdateTimestamp_ ;
-      /**
-       * <code>optional int64 lacUpdateTimestamp = 6;</code>
-       */
-      public boolean hasLacUpdateTimestamp() {
-        return ((bitField0_ & 0x00000020) == 0x00000020);
-      }
-      /**
-       * <code>optional int64 lacUpdateTimestamp = 6;</code>
-       */
-      public long getLacUpdateTimestamp() {
-        return lacUpdateTimestamp_;
-      }
-      /**
-       * <code>optional int64 lacUpdateTimestamp = 6;</code>
-       */
-      public Builder setLacUpdateTimestamp(long value) {
-        bitField0_ |= 0x00000020;
-        lacUpdateTimestamp_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>optional int64 lacUpdateTimestamp = 6;</code>
-       */
-      public Builder clearLacUpdateTimestamp() {
-        bitField0_ = (bitField0_ & ~0x00000020);
-        lacUpdateTimestamp_ = 0L;
-        onChanged();
-        return this;
-      }
-
-      // @@protoc_insertion_point(builder_scope:ReadResponse)
+      // @@protoc_insertion_point(builder_scope:AddResponse)
     }
 
     static {
-      defaultInstance = new ReadResponse(true);
+      defaultInstance = new AddResponse(true);
       defaultInstance.initFields();
     }
 
-    // @@protoc_insertion_point(class_scope:ReadResponse)
+    // @@protoc_insertion_point(class_scope:AddResponse)
   }
 
-  public interface AddResponseOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:AddResponse)
+  public interface AuthMessageOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:AuthMessage)
       com.google.protobuf.MessageOrBuilder {
 
     /**
-     * <code>required .StatusCode status = 1;</code>
-     */
-    boolean hasStatus();
-    /**
-     * <code>required .StatusCode status = 1;</code>
+     * <code>required string authPluginName = 1;</code>
      */
-    org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus();
-
+    boolean hasAuthPluginName();
     /**
-     * <code>required int64 ledgerId = 2;</code>
+     * <code>required string authPluginName = 1;</code>
      */
-    boolean hasLedgerId();
+    java.lang.String getAuthPluginName();
     /**
-     * <code>required int64 ledgerId = 2;</code>
+     * <code>required string authPluginName = 1;</code>
      */
-    long getLedgerId();
+    com.google.protobuf.ByteString
+        getAuthPluginNameBytes();
 
     /**
-     * <code>required int64 entryId = 3;</code>
+     * <code>required bytes payload = 2;</code>
      */
-    boolean hasEntryId();
+    boolean hasPayload();
     /**
-     * <code>required int64 entryId = 3;</code>
+     * <code>required bytes payload = 2;</code>
      */
-    long getEntryId();
+    com.google.protobuf.ByteString getPayload();
   }
   /**
-   * Protobuf type {@code AddResponse}
+   * Protobuf type {@code AuthMessage}
    */
-  public static final class AddResponse extends
+  public static final class AuthMessage extends
       com.google.protobuf.GeneratedMessage implements
-      // @@protoc_insertion_point(message_implements:AddResponse)
-      AddResponseOrBuilder {
-    // Use AddResponse.newBuilder() to construct.
-    private AddResponse(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      // @@protoc_insertion_point(message_implements:AuthMessage)
+      AuthMessageOrBuilder {
+    // Use AuthMessage.newBuilder() to construct.
+    private AuthMessage(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
       super(builder);
       this.unknownFields = builder.getUnknownFields();
     }
-    private AddResponse(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+    private AuthMessage(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
 
-    private static final AddResponse defaultInstance;
-    public static AddResponse getDefaultInstance() {
+    private static final AuthMessage defaultInstance;
+    public static AuthMessage getDefaultInstance() {
       return defaultInstance;
     }
 
-    public AddResponse getDefaultInstanceForType() {
+    public AuthMessage getDefaultInstanceForType() {
       return defaultInstance;
     }
 
@@ -9081,7 +10363,7 @@ public final class BookkeeperProtocol {
         getUnknownFields() {
       return this.unknownFields;
     }
-    private AddResponse(
+    private AuthMessage(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -9104,25 +10386,15 @@ public final class BookkeeperProtocol {
               }
               break;
             }
-            case 8: {
-              int rawValue = input.readEnum();
-              org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode value = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.valueOf(rawValue);
-              if (value == null) {
-                unknownFields.mergeVarintField(1, rawValue);
-              } else {
-                bitField0_ |= 0x00000001;
-                status_ = value;
-              }
+            case 10: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000001;
+              authPluginName_ = bs;
               break;
             }
-            case 16: {
+            case 18: {
               bitField0_ |= 0x00000002;
-              ledgerId_ = input.readInt64();
-              break;
-            }
-            case 24: {
-              bitField0_ |= 0x00000004;
-              entryId_ = input.readInt64();
+              payload_ = input.readBytes();
               break;
             }
           }
@@ -9139,81 +10411,92 @@ public final class BookkeeperProtocol {
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AddResponse_descriptor;
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AuthMessage_descriptor;
     }
 
     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AddResponse_fieldAccessorTable
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AuthMessage_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.Builder.class);
+              org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.class, org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.Builder.class);
     }
 
-    public static com.google.protobuf.Parser<AddResponse> PARSER =
-        new com.google.protobuf.AbstractParser<AddResponse>() {
-      public AddResponse parsePartialFrom(
+    public static com.google.protobuf.Parser<AuthMessage> PARSER =
+        new com.google.protobuf.AbstractParser<AuthMessage>() {
+      public AuthMessage parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new AddResponse(input, extensionRegistry);
+        return new AuthMessage(input, extensionRegistry);
       }
     };
 
     @java.lang.Override
-    public com.google.protobuf.Parser<AddResponse> getParserForType() {
+    public com.google.protobuf.Parser<AuthMessage> getParserForType() {
       return PARSER;
     }
 
     private int bitField0_;
-    public static final int STATUS_FIELD_NUMBER = 1;
-    private org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode status_;
+    public static final int AUTHPLUGINNAME_FIELD_NUMBER = 1;
+    private java.lang.Object authPluginName_;
     /**
-     * <code>required .StatusCode status = 1;</code>
+     * <code>required string authPluginName = 1;</code>
      */
-    public boolean hasStatus() {
+    public boolean hasAuthPluginName() {
       return ((bitField0_ & 0x00000001) == 0x00000001);
     }
     /**
-     * <code>required .StatusCode status = 1;</code>
-     */
-    public org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus() {
-      return status_;
-    }
-
-    public static final int LEDGERID_FIELD_NUMBER = 2;
-    private long ledgerId_;
-    /**
-     * <code>required int64 ledgerId = 2;</code>
+     * <code>required string authPluginName = 1;</code>
      */
-    public boolean hasLedgerId() {
-      return ((bitField0_ & 0x00000002) == 0x00000002);
+    public java.lang.String getAuthPluginName() {
+      java.lang.Object ref = authPluginName_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          authPluginName_ = s;
+        }
+        return s;
+      }
     }
     /**
-     * <code>required int64 ledgerId = 2;</code>
+     * <code>required string authPluginName = 1;</code>
      */
-    public long getLedgerId() {
-      return ledgerId_;
+    public com.google.protobuf.ByteString
+        getAuthPluginNameBytes() {
+      java.lang.Object ref = authPluginName_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        authPluginName_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
     }
 
-    public static final int ENTRYID_FIELD_NUMBER = 3;
-    private long entryId_;
+    public static final int PAYLOAD_FIELD_NUMBER = 2;
+    private com.google.protobuf.ByteString payload_;
     /**
-     * <code>required int64 entryId = 3;</code>
+     * <code>required bytes payload = 2;</code>
      */
-    public boolean hasEntryId() {
-      return ((bitField0_ & 0x00000004) == 0x00000004);
+    public boolean hasPayload() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
     }
     /**
-     * <code>required int64 entryId = 3;</code>
+     * <code>required bytes payload = 2;</code>
      */
-    public long getEntryId() {
-      return entryId_;
+    public com.google.protobuf.ByteString getPayload() {
+      return payload_;
     }
 
     private void initFields() {
-      status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
-      ledgerId_ = 0L;
-      entryId_ = 0L;
+      authPluginName_ = "";
+      payload_ = com.google.protobuf.ByteString.EMPTY;
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
@@ -9221,15 +10504,11 @@ public final class BookkeeperProtocol {
       if (isInitialized == 1) return true;
       if (isInitialized == 0) return false;
 
-      if (!hasStatus()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      if (!hasLedgerId()) {
+      if (!hasAuthPluginName()) {
         memoizedIsInitialized = 0;
         return false;
       }
-      if (!hasEntryId()) {
+      if (!hasPayload()) {
         memoizedIsInitialized = 0;
         return false;
       }
@@ -9241,13 +10520,10 @@ public final class BookkeeperProtocol {
                         throws java.io.IOException {
       getSerializedSize();
       if (((bitField0_ & 0x00000001) == 0x00000001)) {
-        output.writeEnum(1, status_.getNumber());
+        output.writeBytes(1, getAuthPluginNameBytes());
       }
       if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        output.writeInt64(2, ledgerId_);
-      }
-      if (((bitField0_ & 0x00000004) == 0x00000004)) {
-        output.writeInt64(3, entryId_);
+        output.writeBytes(2, payload_);
       }
       getUnknownFields().writeTo(output);
     }
@@ -9260,15 +10536,11 @@ public final class BookkeeperProtocol {
       size = 0;
       if (((bitField0_ & 0x00000001) == 0x00000001)) {
         size += com.google.protobuf.CodedOutputStream
-          .computeEnumSize(1, status_.getNumber());
+          .computeBytesSize(1, getAuthPluginNameBytes());
       }
       if (((bitField0_ & 0x00000002) == 0x00000002)) {
         size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(2, ledgerId_);
-      }
-      if (((bitField0_ & 0x00000004) == 0x00000004)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(3, entryId_);
+          .computeBytesSize(2, payload_);
       }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
@@ -9282,53 +10554,53 @@ public final class BookkeeperProtocol {
       return super.writeReplace();
     }
 
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseFrom(byte[] data)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseDelimitedFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseDelimitedFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -9337,7 +10609,7 @@ public final class BookkeeperProtocol {
 
     public static Builder newBuilder() { return Builder.create(); }
     public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse prototype) {
+    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage prototype) {
       return newBuilder().mergeFrom(prototype);
     }
     public Builder toBuilder() { return newBuilder(this); }
@@ -9349,25 +10621,25 @@ public final class BookkeeperProtocol {
       return builder;
     }
     /**
-     * Protobuf type {@code AddResponse}
+     * Protobuf type {@code AuthMessage}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:AddResponse)
-        org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponseOrBuilder {
+        // @@protoc_insertion_point(builder_implements:AuthMessage)
+        org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessageOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AddResponse_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AuthMessage_descriptor;
       }
 
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AddResponse_fieldAccessorTable
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AuthMessage_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.Builder.class);
+                org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.class, org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.Builder.class);
       }
 
-      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.newBuilder()
+      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -9387,12 +10659,10 @@ public final class BookkeeperProtocol {
 
       public Builder clear() {
         super.clear();
-        status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
+        authPluginName_ = "";
         bitField0_ = (bitField0_ & ~0x00000001);
-        ledgerId_ = 0L;
+        payload_ = com.google.protobuf.ByteString.EMPTY;
         bitField0_ = (bitField0_ & ~0x00000002);
-        entryId_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000004);
         return this;
       }
 
@@ -9402,76 +10672,67 @@ public final class BookkeeperProtocol {
 
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AddResponse_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AuthMessage_descriptor;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse getDefaultInstanceForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.getDefaultInstance();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage getDefaultInstanceForType() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.getDefaultInstance();
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse build() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse result = buildPartial();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage build() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
         return result;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse buildPartial() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse result = new org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse(this);
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage buildPartial() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage result = new org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage(this);
         int from_bitField0_ = bitField0_;
         int to_bitField0_ = 0;
         if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
           to_bitField0_ |= 0x00000001;
         }
-        result.status_ = status_;
+        result.authPluginName_ = authPluginName_;
         if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
           to_bitField0_ |= 0x00000002;
         }
-        result.ledgerId_ = ledgerId_;
-        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
-          to_bitField0_ |= 0x00000004;
-        }
-        result.entryId_ = entryId_;
+        result.payload_ = payload_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
       }
 
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse) {
-          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse)other);
+        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage) {
+          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse other) {
-        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse.getDefaultInstance()) return this;
-        if (other.hasStatus()) {
-          setStatus(other.getStatus());
-        }
-        if (other.hasLedgerId()) {
-          setLedgerId(other.getLedgerId());
+      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage other) {
+        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.getDefaultInstance()) return this;
+        if (other.hasAuthPluginName()) {
+          bitField0_ |= 0x00000001;
+          authPluginName_ = other.authPluginName_;
+          onChanged();
         }
-        if (other.hasEntryId()) {
-          setEntryId(other.getEntryId());
+        if (other.hasPayload()) {
+          setPayload(other.getPayload());
         }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
 
       public final boolean isInitialized() {
-        if (!hasStatus()) {
-          
-          return false;
-        }
-        if (!hasLedgerId()) {
+        if (!hasAuthPluginName()) {
           
           return false;
         }
-        if (!hasEntryId()) {
+        if (!hasPayload()) {
           
           return false;
         }
@@ -9482,11 +10743,11 @@ public final class BookkeeperProtocol {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse parsedMessage = null;
+        org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse) e.getUnfinishedMessage();
+          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage) e.getUnfinishedMessage();
           throw e;
         } finally {
           if (parsedMessage != null) {
@@ -9497,163 +10758,170 @@ public final class BookkeeperProtocol {
       }
       private int bitField0_;
 
-      private org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
+      private java.lang.Object authPluginName_ = "";
       /**
-       * <code>required .StatusCode status = 1;</code>
+       * <code>required string authPluginName = 1;</code>
        */
-      public boolean hasStatus() {
+      public boolean hasAuthPluginName() {
         return ((bitField0_ & 0x00000001) == 0x00000001);
       }
       /**
-       * <code>required .StatusCode status = 1;</code>
+       * <code>required string authPluginName = 1;</code>
        */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus() {
-        return status_;
+      public java.lang.String getAuthPluginName() {
+        java.lang.Object ref = authPluginName_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            authPluginName_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>required string authPluginName = 1;</code>
+       */
+      public com.google.protobuf.ByteString
+          getAuthPluginNameBytes() {
+        java.lang.Object ref = authPluginName_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          authPluginName_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
       }
       /**
-       * <code>required .StatusCode status = 1;</code>
+       * <code>required string authPluginName = 1;</code>
        */
-      public Builder setStatus(org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode value) {
+      public Builder setAuthPluginName(
+          java.lang.String value) {
         if (value == null) {
-          throw new NullPointerException();
-        }
-        bitField0_ |= 0x00000001;
-        status_ = value;
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        authPluginName_ = value;
         onChanged();
         return this;
       }
       /**
-       * <code>required .StatusCode status = 1;</code>
+       * <code>required string authPluginName = 1;</code>
        */
-      public Builder clearStatus() {
+      public Builder clearAuthPluginName() {
         bitField0_ = (bitField0_ & ~0x00000001);
-        status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
-        onChanged();
-        return this;
-      }
-
-      private long ledgerId_ ;
-      /**
-       * <code>required int64 ledgerId = 2;</code>
-       */
-      public boolean hasLedgerId() {
-        return ((bitField0_ & 0x00000002) == 0x00000002);
-      }
-      /**
-       * <code>required int64 ledgerId = 2;</code>
-       */
-      public long getLedgerId() {
-        return ledgerId_;
-      }
-      /**
-       * <code>required int64 ledgerId = 2;</code>
-       */
-      public Builder setLedgerId(long value) {
-        bitField0_ |= 0x00000002;
-        ledgerId_ = value;
+        authPluginName_ = getDefaultInstance().getAuthPluginName();
         onChanged();
         return this;
       }
       /**
-       * <code>required int64 ledgerId = 2;</code>
+       * <code>required string authPluginName = 1;</code>
        */
-      public Builder clearLedgerId() {
-        bitField0_ = (bitField0_ & ~0x00000002);
-        ledgerId_ = 0L;
+      public Builder setAuthPluginNameBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        authPluginName_ = value;
         onChanged();
         return this;
       }
 
-      private long entryId_ ;
+      private com.google.protobuf.ByteString payload_ = com.google.protobuf.ByteString.EMPTY;
       /**
-       * <code>required int64 entryId = 3;</code>
+       * <code>required bytes payload = 2;</code>
        */
-      public boolean hasEntryId() {
-        return ((bitField0_ & 0x00000004) == 0x00000004);
+      public boolean hasPayload() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
       }
       /**
-       * <code>required int64 entryId = 3;</code>
+       * <code>required bytes payload = 2;</code>
        */
-      public long getEntryId() {
-        return entryId_;
+      public com.google.protobuf.ByteString getPayload() {
+        return payload_;
       }
       /**
-       * <code>required int64 entryId = 3;</code>
+       * <code>required bytes payload = 2;</code>
        */
-      public Builder setEntryId(long value) {
-        bitField0_ |= 0x00000004;
-        entryId_ = value;
+      public Builder setPayload(com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+        payload_ = value;
         onChanged();
         return this;
       }
       /**
-       * <code>required int64 entryId = 3;</code>
+       * <code>required bytes payload = 2;</code>
        */
-      public Builder clearEntryId() {
-        bitField0_ = (bitField0_ & ~0x00000004);
-        entryId_ = 0L;
+      public Builder clearPayload() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        payload_ = getDefaultInstance().getPayload();
         onChanged();
         return this;
       }
 
-      // @@protoc_insertion_point(builder_scope:AddResponse)
+      // @@protoc_insertion_point(builder_scope:AuthMessage)
     }
 
     static {
-      defaultInstance = new AddResponse(true);
+      defaultInstance = new AuthMessage(true);
       defaultInstance.initFields();
     }
 
-    // @@protoc_insertion_point(class_scope:AddResponse)
+    // @@protoc_insertion_point(class_scope:AuthMessage)
   }
 
-  public interface AuthMessageOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:AuthMessage)
+  public interface WriteLacResponseOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:WriteLacResponse)
       com.google.protobuf.MessageOrBuilder {
 
     /**
-     * <code>required string authPluginName = 1;</code>
-     */
-    boolean hasAuthPluginName();
-    /**
-     * <code>required string authPluginName = 1;</code>
+     * <code>required .StatusCode status = 1;</code>
      */
-    java.lang.String getAuthPluginName();
+    boolean hasStatus();
     /**
-     * <code>required string authPluginName = 1;</code>
+     * <code>required .StatusCode status = 1;</code>
      */
-    com.google.protobuf.ByteString
-        getAuthPluginNameBytes();
+    org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus();
 
     /**
-     * <code>required bytes payload = 2;</code>
+     * <code>required int64 ledgerId = 2;</code>
      */
-    boolean hasPayload();
+    boolean hasLedgerId();
     /**
-     * <code>required bytes payload = 2;</code>
+     * <code>required int64 ledgerId = 2;</code>
      */
-    com.google.protobuf.ByteString getPayload();
+    long getLedgerId();
   }
   /**
-   * Protobuf type {@code AuthMessage}
+   * Protobuf type {@code WriteLacResponse}
    */
-  public static final class AuthMessage extends
+  public static final class WriteLacResponse extends
       com.google.protobuf.GeneratedMessage implements
-      // @@protoc_insertion_point(message_implements:AuthMessage)
-      AuthMessageOrBuilder {
-    // Use AuthMessage.newBuilder() to construct.
-    private AuthMessage(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      // @@protoc_insertion_point(message_implements:WriteLacResponse)
+      WriteLacResponseOrBuilder {
+    // Use WriteLacResponse.newBuilder() to construct.
+    private WriteLacResponse(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
       super(builder);
       this.unknownFields = builder.getUnknownFields();
     }
-    private AuthMessage(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+    private WriteLacResponse(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
 
-    private static final AuthMessage defaultInstance;
-    public static AuthMessage getDefaultInstance() {
+    private static final WriteLacResponse defaultInstance;
+    public static WriteLacResponse getDefaultInstance() {
       return defaultInstance;
     }
 
-    public AuthMessage getDefaultInstanceForType() {
+    public WriteLacResponse getDefaultInstanceForType() {
       return defaultInstance;
     }
 
@@ -9663,7 +10931,7 @@ public final class BookkeeperProtocol {
         getUnknownFields() {
       return this.unknownFields;
     }
-    private AuthMessage(
+    private WriteLacResponse(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -9686,15 +10954,20 @@ public final class BookkeeperProtocol {
               }
               break;
             }
-            case 10: {
-              com.google.protobuf.ByteString bs = input.readBytes();
-              bitField0_ |= 0x00000001;
-              authPluginName_ = bs;
+            case 8: {
+              int rawValue = input.readEnum();
+              org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode value = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.valueOf(rawValue);
+              if (value == null) {
+                unknownFields.mergeVarintField(1, rawValue);
+              } else {
+                bitField0_ |= 0x00000001;
+                status_ = value;
+              }
               break;
             }
-            case 18: {
+            case 16: {
               bitField0_ |= 0x00000002;
-              payload_ = input.readBytes();
+              ledgerId_ = input.readInt64();
               break;
             }
           }
@@ -9711,92 +10984,65 @@ public final class BookkeeperProtocol {
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AuthMessage_descriptor;
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacResponse_descriptor;
     }
 
     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AuthMessage_fieldAccessorTable
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacResponse_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.class, org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.Builder.class);
+              org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.Builder.class);
     }
 
-    public static com.google.protobuf.Parser<AuthMessage> PARSER =
-        new com.google.protobuf.AbstractParser<AuthMessage>() {
-      public AuthMessage parsePartialFrom(
+    public static com.google.protobuf.Parser<WriteLacResponse> PARSER =
+        new com.google.protobuf.AbstractParser<WriteLacResponse>() {
+      public WriteLacResponse parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new AuthMessage(input, extensionRegistry);
+        return new WriteLacResponse(input, extensionRegistry);
       }
     };
 
     @java.lang.Override
-    public com.google.protobuf.Parser<AuthMessage> getParserForType() {
+    public com.google.protobuf.Parser<WriteLacResponse> getParserForType() {
       return PARSER;
     }
 
     private int bitField0_;
-    public static final int AUTHPLUGINNAME_FIELD_NUMBER = 1;
-    private java.lang.Object authPluginName_;
+    public static final int STATUS_FIELD_NUMBER = 1;
+    private org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode status_;
     /**
-     * <code>required string authPluginName = 1;</code>
+     * <code>required .StatusCode status = 1;</code>
      */
-    public boolean hasAuthPluginName() {
+    public boolean hasStatus() {
       return ((bitField0_ & 0x00000001) == 0x00000001);
     }
     /**
-     * <code>required string authPluginName = 1;</code>
-     */
-    public java.lang.String getAuthPluginName() {
-      java.lang.Object ref = authPluginName_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        if (bs.isValidUtf8()) {
-          authPluginName_ = s;
-        }
-        return s;
-      }
-    }
-    /**
-     * <code>required string authPluginName = 1;</code>
+     * <code>required .StatusCode status = 1;</code>
      */
-    public com.google.protobuf.ByteString
-        getAuthPluginNameBytes() {
-      java.lang.Object ref = authPluginName_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        authPluginName_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
+    public org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus() {
+      return status_;
     }
 
-    public static final int PAYLOAD_FIELD_NUMBER = 2;
-    private com.google.protobuf.ByteString payload_;
+    public static final int LEDGERID_FIELD_NUMBER = 2;
+    private long ledgerId_;
     /**
-     * <code>required bytes payload = 2;</code>
+     * <code>required int64 ledgerId = 2;</code>
      */
-    public boolean hasPayload() {
+    public boolean hasLedgerId() {
       return ((bitField0_ & 0x00000002) == 0x00000002);
     }
     /**
-     * <code>required bytes payload = 2;</code>
+     * <code>required int64 ledgerId = 2;</code>
      */
-    public com.google.protobuf.ByteString getPayload() {
-      return payload_;
+    public long getLedgerId() {
+      return ledgerId_;
     }
 
     private void initFields() {
-      authPluginName_ = "";
-      payload_ = com.google.protobuf.ByteString.EMPTY;
+      status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
+      ledgerId_ = 0L;
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
@@ -9804,11 +11050,11 @@ public final class BookkeeperProtocol {
       if (isInitialized == 1) return true;
       if (isInitialized == 0) return false;
 
-      if (!hasAuthPluginName()) {
+      if (!hasStatus()) {
         memoizedIsInitialized = 0;
         return false;
       }
-      if (!hasPayload()) {
+      if (!hasLedgerId()) {
         memoizedIsInitialized = 0;
         return false;
       }
@@ -9820,10 +11066,10 @@ public final class BookkeeperProtocol {
                         throws java.io.IOException {
       getSerializedSize();
       if (((bitField0_ & 0x00000001) == 0x00000001)) {
-        output.writeBytes(1, getAuthPluginNameBytes());
+        output.writeEnum(1, status_.getNumber());
       }
       if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        output.writeBytes(2, payload_);
+        output.writeInt64(2, ledgerId_);
       }
       getUnknownFields().writeTo(output);
     }
@@ -9836,11 +11082,11 @@ public final class BookkeeperProtocol {
       size = 0;
       if (((bitField0_ & 0x00000001) == 0x00000001)) {
         size += com.google.protobuf.CodedOutputStream
-          .computeBytesSize(1, getAuthPluginNameBytes());
+          .computeEnumSize(1, status_.getNumber());
       }
       if (((bitField0_ & 0x00000002) == 0x00000002)) {
         size += com.google.protobuf.CodedOutputStream
-          .computeBytesSize(2, payload_);
+          .computeInt64Size(2, ledgerId_);
       }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
@@ -9854,53 +11100,53 @@ public final class BookkeeperProtocol {
       return super.writeReplace();
     }
 
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseFrom(byte[] data)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseDelimitedFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseDelimitedFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -9909,7 +11155,7 @@ public final class BookkeeperProtocol {
 
     public static Builder newBuilder() { return Builder.create(); }
     public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage prototype) {
+    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse prototype) {
       return newBuilder().mergeFrom(prototype);
     }
     public Builder toBuilder() { return newBuilder(this); }
@@ -9921,25 +11167,25 @@ public final class BookkeeperProtocol {
       return builder;
     }
     /**
-     * Protobuf type {@code AuthMessage}
+     * Protobuf type {@code WriteLacResponse}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:AuthMessage)
-        org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessageOrBuilder {
+        // @@protoc_insertion_point(builder_implements:WriteLacResponse)
+        org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponseOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AuthMessage_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacResponse_descriptor;
       }
 
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AuthMessage_fieldAccessorTable
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacResponse_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.class, org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.Builder.class);
+                org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.Builder.class);
       }
 
-      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.newBuilder()
+      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -9959,9 +11205,9 @@ public final class BookkeeperProtocol {
 
       public Builder clear() {
         super.clear();
-        authPluginName_ = "";
+        status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
         bitField0_ = (bitField0_ & ~0x00000001);
-        payload_ = com.google.protobuf.ByteString.EMPTY;
+        ledgerId_ = 0L;
         bitField0_ = (bitField0_ & ~0x00000002);
         return this;
       }
@@ -9972,67 +11218,65 @@ public final class BookkeeperProtocol {
 
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_AuthMessage_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacResponse_descriptor;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage getDefaultInstanceForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.getDefaultInstance();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse getDefaultInstanceForType() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.getDefaultInstance();
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage build() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage result = buildPartial();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse build() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
         return result;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage buildPartial() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage result = new org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage(this);
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse buildPartial() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse result = new org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse(this);
         int from_bitField0_ = bitField0_;
         int to_bitField0_ = 0;
         if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
           to_bitField0_ |= 0x00000001;
         }
-        result.authPluginName_ = authPluginName_;
+        result.status_ = status_;
         if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
           to_bitField0_ |= 0x00000002;
         }
-        result.payload_ = payload_;
+        result.ledgerId_ = ledgerId_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
       }
 
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage) {
-          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage)other);
+        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse) {
+          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage other) {
-        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage.getDefaultInstance()) return this;
-        if (other.hasAuthPluginName()) {
-          bitField0_ |= 0x00000001;
-          authPluginName_ = other.authPluginName_;
-          onChanged();
+      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse other) {
+        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.getDefaultInstance()) return this;
+        if (other.hasStatus()) {
+          setStatus(other.getStatus());
         }
-        if (other.hasPayload()) {
-          setPayload(other.getPayload());
+        if (other.hasLedgerId()) {
+          setLedgerId(other.getLedgerId());
         }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
 
       public final boolean isInitialized() {
-        if (!hasAuthPluginName()) {
+        if (!hasStatus()) {
           
           return false;
         }
-        if (!hasPayload()) {
+        if (!hasLedgerId()) {
           
           return false;
         }
@@ -10043,11 +11287,11 @@ public final class BookkeeperProtocol {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage parsedMessage = null;
+        org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage) e.getUnfinishedMessage();
+          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse) e.getUnfinishedMessage();
           throw e;
         } finally {
           if (parsedMessage != null) {
@@ -10058,130 +11302,86 @@ public final class BookkeeperProtocol {
       }
       private int bitField0_;
 
-      private java.lang.Object authPluginName_ = "";
+      private org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
       /**
-       * <code>required string authPluginName = 1;</code>
+       * <code>required .StatusCode status = 1;</code>
        */
-      public boolean hasAuthPluginName() {
+      public boolean hasStatus() {
         return ((bitField0_ & 0x00000001) == 0x00000001);
       }
       /**
-       * <code>required string authPluginName = 1;</code>
-       */
-      public java.lang.String getAuthPluginName() {
-        java.lang.Object ref = authPluginName_;
-        if (!(ref instanceof java.lang.String)) {
-          com.google.protobuf.ByteString bs =
-              (com.google.protobuf.ByteString) ref;
-          java.lang.String s = bs.toStringUtf8();
-          if (bs.isValidUtf8()) {
-            authPluginName_ = s;
-          }
-          return s;
-        } else {
-          return (java.lang.String) ref;
-        }
-      }
-      /**
-       * <code>required string authPluginName = 1;</code>
+       * <code>required .StatusCode status = 1;</code>
        */
-      public com.google.protobuf.ByteString
-          getAuthPluginNameBytes() {
-        java.lang.Object ref = authPluginName_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          authPluginName_ = b;
-          return b;
-        } else {
-          return (com.google.protobuf.ByteString) ref;
-        }
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus() {
+        return status_;
       }
       /**
-       * <code>required string authPluginName = 1;</code>
+       * <code>required .StatusCode status = 1;</code>
        */
-      public Builder setAuthPluginName(
-          java.lang.String value) {
+      public Builder setStatus(org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode value) {
         if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000001;
-        authPluginName_ = value;
+          throw new NullPointerException();
+        }
+        bitField0_ |= 0x00000001;
+        status_ = value;
         onChanged();
         return this;
       }
       /**
-       * <code>required string authPluginName = 1;</code>
+       * <code>required .StatusCode status = 1;</code>
        */
-      public Builder clearAuthPluginName() {
+      public Builder clearStatus() {
         bitField0_ = (bitField0_ & ~0x00000001);
-        authPluginName_ = getDefaultInstance().getAuthPluginName();
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required string authPluginName = 1;</code>
-       */
-      public Builder setAuthPluginNameBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000001;
-        authPluginName_ = value;
+        status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
         onChanged();
         return this;
       }
 
-      private com.google.protobuf.ByteString payload_ = com.google.protobuf.ByteString.EMPTY;
+      private long ledgerId_ ;
       /**
-       * <code>required bytes payload = 2;</code>
+       * <code>required int64 ledgerId = 2;</code>
        */
-      public boolean hasPayload() {
+      public boolean hasLedgerId() {
         return ((bitField0_ & 0x00000002) == 0x00000002);
       }
       /**
-       * <code>required bytes payload = 2;</code>
+       * <code>required int64 ledgerId = 2;</code>
        */
-      public com.google.protobuf.ByteString getPayload() {
-        return payload_;
+      public long getLedgerId() {
+        return ledgerId_;
       }
       /**
-       * <code>required bytes payload = 2;</code>
+       * <code>required int64 ledgerId = 2;</code>
        */
-      public Builder setPayload(com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000002;
-        payload_ = value;
+      public Builder setLedgerId(long value) {
+        bitField0_ |= 0x00000002;
+        ledgerId_ = value;
         onChanged();
         return this;
       }
       /**
-       * <code>required bytes payload = 2;</code>
+       * <code>required int64 ledgerId = 2;</code>
        */
-      public Builder clearPayload() {
+      public Builder clearLedgerId() {
         bitField0_ = (bitField0_ & ~0x00000002);
-        payload_ = getDefaultInstance().getPayload();
+        ledgerId_ = 0L;
         onChanged();
         return this;
       }
 
-      // @@protoc_insertion_point(builder_scope:AuthMessage)
+      // @@protoc_insertion_point(builder_scope:WriteLacResponse)
     }
 
     static {
-      defaultInstance = new AuthMessage(true);
+      defaultInstance = new WriteLacResponse(true);
       defaultInstance.initFields();
     }
 
-    // @@protoc_insertion_point(class_scope:AuthMessage)
+    // @@protoc_insertion_point(class_scope:WriteLacResponse)
   }
 
-  public interface WriteLacResponseOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:WriteLacResponse)
+  public interface ReadLacResponseOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:ReadLacResponse)
       com.google.protobuf.MessageOrBuilder {
 
     /**
@@ -10201,27 +11401,61 @@ public final class BookkeeperProtocol {
      * <code>required int64 ledgerId = 2;</code>
      */
     long getLedgerId();
+
+    /**
+     * <code>optional bytes lacBody = 3;</code>
+     *
+     * <pre>
+     * lac sent by PutLacRequest
+     * </pre>
+     */
+    boolean hasLacBody();
+    /**
+     * <code>optional bytes lacBody = 3;</code>
+     *
+     * <pre>
+     * lac sent by PutLacRequest
+     * </pre>
+     */
+    com.google.protobuf.ByteString getLacBody();
+
+    /**
+     * <code>optional bytes lastEntryBody = 4;</code>
+     *
+     * <pre>
+     * Actual last entry on the disk
+     * </pre>
+     */
+    boolean hasLastEntryBody();
+    /**
+     * <code>optional bytes lastEntryBody = 4;</code>
+     *
+     * <pre>
+     * Actual last entry on the disk
+     * </pre>
+     */
+    com.google.protobuf.ByteString getLastEntryBody();
   }
   /**
-   * Protobuf type {@code WriteLacResponse}
+   * Protobuf type {@code ReadLacResponse}
    */
-  public static final class WriteLacResponse extends
+  public static final class ReadLacResponse extends
       com.google.protobuf.GeneratedMessage implements
-      // @@protoc_insertion_point(message_implements:WriteLacResponse)
-      WriteLacResponseOrBuilder {
-    // Use WriteLacResponse.newBuilder() to construct.
-    private WriteLacResponse(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      // @@protoc_insertion_point(message_implements:ReadLacResponse)
+      ReadLacResponseOrBuilder {
+    // Use ReadLacResponse.newBuilder() to construct.
+    private ReadLacResponse(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
       super(builder);
       this.unknownFields = builder.getUnknownFields();
     }
-    private WriteLacResponse(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+    private ReadLacResponse(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
 
-    private static final WriteLacResponse defaultInstance;
-    public static WriteLacResponse getDefaultInstance() {
+    private static final ReadLacResponse defaultInstance;
+    public static ReadLacResponse getDefaultInstance() {
       return defaultInstance;
     }
 
-    public WriteLacResponse getDefaultInstanceForType() {
+    public ReadLacResponse getDefaultInstanceForType() {
       return defaultInstance;
     }
 
@@ -10231,7 +11465,7 @@ public final class BookkeeperProtocol {
         getUnknownFields() {
       return this.unknownFields;
     }
-    private WriteLacResponse(
+    private ReadLacResponse(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -10270,6 +11504,16 @@ public final class BookkeeperProtocol {
               ledgerId_ = input.readInt64();
               break;
             }
+            case 26: {
+              bitField0_ |= 0x00000004;
+              lacBody_ = input.readBytes();
+              break;
+            }
+            case 34: {
+              bitField0_ |= 0x00000008;
+              lastEntryBody_ = input.readBytes();
+              break;
+            }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -10284,28 +11528,28 @@ public final class BookkeeperProtocol {
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacResponse_descriptor;
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacResponse_descriptor;
     }
 
     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacResponse_fieldAccessorTable
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacResponse_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.Builder.class);
+              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.Builder.class);
     }
 
-    public static com.google.protobuf.Parser<WriteLacResponse> PARSER =
-        new com.google.protobuf.AbstractParser<WriteLacResponse>() {
-      public WriteLacResponse parsePartialFrom(
+    public static com.google.protobuf.Parser<ReadLacResponse> PARSER =
+        new com.google.protobuf.AbstractParser<ReadLacResponse>() {
+      public ReadLacResponse parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new WriteLacResponse(input, extensionRegistry);
+        return new ReadLacResponse(input, extensionRegistry);
       }
     };
 
     @java.lang.Override
-    public com.google.protobuf.Parser<WriteLacResponse> getParserForType() {
+    public com.google.protobuf.Parser<ReadLacResponse> getParserForType() {
       return PARSER;
     }
 
@@ -10340,9 +11584,57 @@ public final class BookkeeperProtocol {
       return ledgerId_;
     }
 
+    public static final int LACBODY_FIELD_NUMBER = 3;
+    private com.google.protobuf.ByteString lacBody_;
+    /**
+     * <code>optional bytes lacBody = 3;</code>
+     *
+     * <pre>
+     * lac sent by PutLacRequest
+     * </pre>
+     */
+    public boolean hasLacBody() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>optional bytes lacBody = 3;</code>
+     *
+     * <pre>
+     * lac sent by PutLacRequest
+     * </pre>
+     */
+    public com.google.protobuf.ByteString getLacBody() {
+      return lacBody_;
+    }
+
+    public static final int LASTENTRYBODY_FIELD_NUMBER = 4;
+    private com.google.protobuf.ByteString lastEntryBody_;
+    /**
+     * <code>optional bytes lastEntryBody = 4;</code>
+     *
+     * <pre>
+     * Actual last entry on the disk
+     * </pre>
+     */
+    public boolean hasLastEntryBody() {
+      return ((bitField0_ & 0x00000008) == 0x00000008);
+    }
+    /**
+     * <code>optional bytes lastEntryBody = 4;</code>
+     *
+     * <pre>
+     * Actual last entry on the disk
+     * </pre>
+     */
+    public com.google.protobuf.ByteString getLastEntryBody() {
+      return lastEntryBody_;
+    }
+
     private void initFields() {
       status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
       ledgerId_ = 0L;
+      lacBody_ = com.google.protobuf.ByteString.EMPTY;
+      lastEntryBody_ = com.google.protobuf.ByteString.EMPTY;
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
@@ -10371,6 +11663,12 @@ public final class BookkeeperProtocol {
       if (((bitField0_ & 0x00000002) == 0x00000002)) {
         output.writeInt64(2, ledgerId_);
       }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeBytes(3, lacBody_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        output.writeBytes(4, lastEntryBody_);
+      }
       getUnknownFields().writeTo(output);
     }
 
@@ -10388,6 +11686,14 @@ public final class BookkeeperProtocol {
         size += com.google.protobuf.CodedOutputStream
           .computeInt64Size(2, ledgerId_);
       }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(3, lacBody_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(4, lastEntryBody_);
+      }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
       return size;
@@ -10400,53 +11706,53 @@ public final class BookkeeperProtocol {
       return super.writeReplace();
     }
 
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseFrom(byte[] data)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseDelimitedFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseDelimitedFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -10455,7 +11761,7 @@ public final class BookkeeperProtocol {
 
     public static Builder newBuilder() { return Builder.create(); }
     public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse prototype) {
+    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse prototype) {
       return newBuilder().mergeFrom(prototype);
     }
     public Builder toBuilder() { return newBuilder(this); }
@@ -10467,25 +11773,25 @@ public final class BookkeeperProtocol {
       return builder;
     }
     /**
-     * Protobuf type {@code WriteLacResponse}
+     * Protobuf type {@code ReadLacResponse}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:WriteLacResponse)
-        org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponseOrBuilder {
+        // @@protoc_insertion_point(builder_implements:ReadLacResponse)
+        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponseOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacResponse_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacResponse_descriptor;
       }
 
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacResponse_fieldAccessorTable
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacResponse_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.Builder.class);
+                org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.Builder.class);
       }
 
-      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.newBuilder()
+      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -10509,6 +11815,10 @@ public final class BookkeeperProtocol {
         bitField0_ = (bitField0_ & ~0x00000001);
         ledgerId_ = 0L;
         bitField0_ = (bitField0_ & ~0x00000002);
+        lacBody_ = com.google.protobuf.ByteString.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000004);
+        lastEntryBody_ = com.google.protobuf.ByteString.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000008);
         return this;
       }
 
@@ -10518,23 +11828,23 @@ public final class BookkeeperProtocol {
 
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_WriteLacResponse_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacResponse_descriptor;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse getDefaultInstanceForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.getDefaultInstance();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse getDefaultInstanceForType() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.getDefaultInstance();
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse build() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse result = buildPartial();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse build() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
         return result;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse buildPartial() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse result = new org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse(this);
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse buildPartial() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse result = new org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse(this);
         int from_bitField0_ = bitField0_;
         int to_bitField0_ = 0;
         if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
@@ -10545,28 +11855,42 @@ public final class BookkeeperProtocol {
           to_bitField0_ |= 0x00000002;
         }
         result.ledgerId_ = ledgerId_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.lacBody_ = lacBody_;
+        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+          to_bitField0_ |= 0x00000008;
+        }
+        result.lastEntryBody_ = lastEntryBody_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
       }
 
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse) {
-          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse)other);
+        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse) {
+          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse other) {
-        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse.getDefaultInstance()) return this;
+      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse other) {
+        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.getDefaultInstance()) return this;
         if (other.hasStatus()) {
           setStatus(other.getStatus());
         }
         if (other.hasLedgerId()) {
           setLedgerId(other.getLedgerId());
         }
+        if (other.hasLacBody()) {
+          setLacBody(other.getLacBody());
+        }
+        if (other.hasLastEntryBody()) {
+          setLastEntryBody(other.getLastEntryBody());
+        }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
@@ -10587,11 +11911,11 @@ public final class BookkeeperProtocol {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse parsedMessage = null;
+        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse) e.getUnfinishedMessage();
+          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse) e.getUnfinishedMessage();
           throw e;
         } finally {
           if (parsedMessage != null) {
@@ -10669,19 +11993,121 @@ public final class BookkeeperProtocol {
         return this;
       }
 
-      // @@protoc_insertion_point(builder_scope:WriteLacResponse)
+      private com.google.protobuf.ByteString lacBody_ = com.google.protobuf.ByteString.EMPTY;
+      /**
+       * <code>optional bytes lacBody = 3;</code>
+       *
+       * <pre>
+       * lac sent by PutLacRequest
+       * </pre>
+       */
+      public boolean hasLacBody() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>optional bytes lacBody = 3;</code>
+       *
+       * <pre>
+       * lac sent by PutLacRequest
+       * </pre>
+       */
+      public com.google.protobuf.ByteString getLacBody() {
+        return lacBody_;
+      }
+      /**
+       * <code>optional bytes lacBody = 3;</code>
+       *
+       * <pre>
+       * lac sent by PutLacRequest
+       * </pre>
+       */
+      public Builder setLacBody(com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+        lacBody_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional bytes lacBody = 3;</code>
+       *
+       * <pre>
+       * lac sent by PutLacRequest
+       * </pre>
+       */
+      public Builder clearLacBody() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        lacBody_ = getDefaultInstance().getLacBody();
+        onChanged();
+        return this;
+      }
+
+      private com.google.protobuf.ByteString lastEntryBody_ = com.google.protobuf.ByteString.EMPTY;
+      /**
+       * <code>optional bytes lastEntryBody = 4;</code>
+       *
+       * <pre>
+       * Actual last entry on the disk
+       * </pre>
+       */
+      public boolean hasLastEntryBody() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
+      }
+      /**
+       * <code>optional bytes lastEntryBody = 4;</code>
+       *
+       * <pre>
+       * Actual last entry on the disk
+       * </pre>
+       */
+      public com.google.protobuf.ByteString getLastEntryBody() {
+        return lastEntryBody_;
+      }
+      /**
+       * <code>optional bytes lastEntryBody = 4;</code>
+       *
+       * <pre>
+       * Actual last entry on the disk
+       * </pre>
+       */
+      public Builder setLastEntryBody(com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000008;
+        lastEntryBody_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional bytes lastEntryBody = 4;</code>
+       *
+       * <pre>
+       * Actual last entry on the disk
+       * </pre>
+       */
+      public Builder clearLastEntryBody() {
+        bitField0_ = (bitField0_ & ~0x00000008);
+        lastEntryBody_ = getDefaultInstance().getLastEntryBody();
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:ReadLacResponse)
     }
 
     static {
-      defaultInstance = new WriteLacResponse(true);
+      defaultInstance = new ReadLacResponse(true);
       defaultInstance.initFields();
     }
 
-    // @@protoc_insertion_point(class_scope:WriteLacResponse)
+    // @@protoc_insertion_point(class_scope:ReadLacResponse)
   }
 
-  public interface ReadLacResponseOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:ReadLacResponse)
+  public interface GetBookieInfoResponseOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:GetBookieInfoResponse)
       com.google.protobuf.MessageOrBuilder {
 
     /**
@@ -10694,68 +12120,43 @@ public final class BookkeeperProtocol {
     org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus();
 
     /**
-     * <code>required int64 ledgerId = 2;</code>
-     */
-    boolean hasLedgerId();
-    /**
-     * <code>required int64 ledgerId = 2;</code>
-     */
-    long getLedgerId();
-
-    /**
-     * <code>optional bytes lacBody = 3;</code>
-     *
-     * <pre>
-     * lac sent by PutLacRequest
-     * </pre>
+     * <code>optional int64 totalDiskCapacity = 2;</code>
      */
-    boolean hasLacBody();
+    boolean hasTotalDiskCapacity();
     /**
-     * <code>optional bytes lacBody = 3;</code>
-     *
-     * <pre>
-     * lac sent by PutLacRequest
-     * </pre>
+     * <code>optional int64 totalDiskCapacity = 2;</code>
      */
-    com.google.protobuf.ByteString getLacBody();
+    long getTotalDiskCapacity();
 
     /**
-     * <code>optional bytes lastEntryBody = 4;</code>
-     *
-     * <pre>
-     * Actual last entry on the disk
-     * </pre>
+     * <code>optional int64 freeDiskSpace = 3;</code>
      */
-    boolean hasLastEntryBody();
+    boolean hasFreeDiskSpace();
     /**
-     * <code>optional bytes lastEntryBody = 4;</code>
-     *
-     * <pre>
-     * Actual last entry on the disk
-     * </pre>
+     * <code>optional int64 freeDiskSpace = 3;</code>
      */
-    com.google.protobuf.ByteString getLastEntryBody();
+    long getFreeDiskSpace();
   }
   /**
-   * Protobuf type {@code ReadLacResponse}
+   * Protobuf type {@code GetBookieInfoResponse}
    */
-  public static final class ReadLacResponse extends
+  public static final class GetBookieInfoResponse extends
       com.google.protobuf.GeneratedMessage implements
-      // @@protoc_insertion_point(message_implements:ReadLacResponse)
-      ReadLacResponseOrBuilder {
-    // Use ReadLacResponse.newBuilder() to construct.
-    private ReadLacResponse(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      // @@protoc_insertion_point(message_implements:GetBookieInfoResponse)
+      GetBookieInfoResponseOrBuilder {
+    // Use GetBookieInfoResponse.newBuilder() to construct.
+    private GetBookieInfoResponse(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
       super(builder);
       this.unknownFields = builder.getUnknownFields();
     }
-    private ReadLacResponse(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+    private GetBookieInfoResponse(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
 
-    private static final ReadLacResponse defaultInstance;
-    public static ReadLacResponse getDefaultInstance() {
+    private static final GetBookieInfoResponse defaultInstance;
+    public static GetBookieInfoResponse getDefaultInstance() {
       return defaultInstance;
     }
 
-    public ReadLacResponse getDefaultInstanceForType() {
+    public GetBookieInfoResponse getDefaultInstanceForType() {
       return defaultInstance;
     }
 
@@ -10765,7 +12166,7 @@ public final class BookkeeperProtocol {
         getUnknownFields() {
       return this.unknownFields;
     }
-    private ReadLacResponse(
+    private GetBookieInfoResponse(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -10801,17 +12202,12 @@ public final class BookkeeperProtocol {
             }
             case 16: {
               bitField0_ |= 0x00000002;
-              ledgerId_ = input.readInt64();
+              totalDiskCapacity_ = input.readInt64();
               break;
             }
-            case 26: {
+            case 24: {
               bitField0_ |= 0x00000004;
-              lacBody_ = input.readBytes();
-              break;
-            }
-            case 34: {
-              bitField0_ |= 0x00000008;
-              lastEntryBody_ = input.readBytes();
+              freeDiskSpace_ = input.readInt64();
               break;
             }
           }
@@ -10828,28 +12224,28 @@ public final class BookkeeperProtocol {
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacResponse_descriptor;
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoResponse_descriptor;
     }
 
     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacResponse_fieldAccessorTable
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoResponse_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.Builder.class);
+              org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.Builder.class);
     }
 
-    public static com.google.protobuf.Parser<ReadLacResponse> PARSER =
-        new com.google.protobuf.AbstractParser<ReadLacResponse>() {
-      public ReadLacResponse parsePartialFrom(
+    public static com.google.protobuf.Parser<GetBookieInfoResponse> PARSER =
+        new com.google.protobuf.AbstractParser<GetBookieInfoResponse>() {
+      public GetBookieInfoResponse parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new ReadLacResponse(input, extensionRegistry);
+        return new GetBookieInfoResponse(input, extensionRegistry);
       }
     };
 
     @java.lang.Override
-    public com.google.protobuf.Parser<ReadLacResponse> getParserForType() {
+    public com.google.protobuf.Parser<GetBookieInfoResponse> getParserForType() {
       return PARSER;
     }
 
@@ -10869,72 +12265,40 @@ public final class BookkeeperProtocol {
       return status_;
     }
 
-    public static final int LEDGERID_FIELD_NUMBER = 2;
-    private long ledgerId_;
+    public static final int TOTALDISKCAPACITY_FIELD_NUMBER = 2;
+    private long totalDiskCapacity_;
     /**
-     * <code>required int64 ledgerId = 2;</code>
+     * <code>optional int64 totalDiskCapacity = 2;</code>
      */
-    public boolean hasLedgerId() {
+    public boolean hasTotalDiskCapacity() {
       return ((bitField0_ & 0x00000002) == 0x00000002);
     }
     /**
-     * <code>required int64 ledgerId = 2;</code>
+     * <code>optional int64 totalDiskCapacity = 2;</code>
      */
-    public long getLedgerId() {
-      return ledgerId_;
+    public long getTotalDiskCapacity() {
+      return totalDiskCapacity_;
     }
 
-    public static final int LACBODY_FIELD_NUMBER = 3;
-    private com.google.protobuf.ByteString lacBody_;
+    public static final int FREEDISKSPACE_FIELD_NUMBER = 3;
+    private long freeDiskSpace_;
     /**
-     * <code>optional bytes lacBody = 3;</code>
-     *
-     * <pre>
-     * lac sent by PutLacRequest
-     * </pre>
+     * <code>optional int64 freeDiskSpace = 3;</code>
      */
-    public boolean hasLacBody() {
+    public boolean hasFreeDiskSpace() {
       return ((bitField0_ & 0x00000004) == 0x00000004);
     }
     /**
-     * <code>optional bytes lacBody = 3;</code>
-     *
-     * <pre>
-     * lac sent by PutLacRequest
-     * </pre>
-     */
-    public com.google.protobuf.ByteString getLacBody() {
-      return lacBody_;
-    }
-
-    public static final int LASTENTRYBODY_FIELD_NUMBER = 4;
-    private com.google.protobuf.ByteString lastEntryBody_;
-    /**
-     * <code>optional bytes lastEntryBody = 4;</code>
-     *
-     * <pre>
-     * Actual last entry on the disk
-     * </pre>
-     */
-    public boolean hasLastEntryBody() {
-      return ((bitField0_ & 0x00000008) == 0x00000008);
-    }
-    /**
-     * <code>optional bytes lastEntryBody = 4;</code>
-     *
-     * <pre>
-     * Actual last entry on the disk
-     * </pre>
+     * <code>optional int64 freeDiskSpace = 3;</code>
      */
-    public com.google.protobuf.ByteString getLastEntryBody() {
-      return lastEntryBody_;
+    public long getFreeDiskSpace() {
+      return freeDiskSpace_;
     }
 
     private void initFields() {
       status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
-      ledgerId_ = 0L;
-      lacBody_ = com.google.protobuf.ByteString.EMPTY;
-      lastEntryBody_ = com.google.protobuf.ByteString.EMPTY;
+      totalDiskCapacity_ = 0L;
+      freeDiskSpace_ = 0L;
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
@@ -10946,10 +12310,6 @@ public final class BookkeeperProtocol {
         memoizedIsInitialized = 0;
         return false;
       }
-      if (!hasLedgerId()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
       memoizedIsInitialized = 1;
       return true;
     }
@@ -10961,13 +12321,10 @@ public final class BookkeeperProtocol {
         output.writeEnum(1, status_.getNumber());
       }
       if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        output.writeInt64(2, ledgerId_);
+        output.writeInt64(2, totalDiskCapacity_);
       }
       if (((bitField0_ & 0x00000004) == 0x00000004)) {
-        output.writeBytes(3, lacBody_);
-      }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
-        output.writeBytes(4, lastEntryBody_);
+        output.writeInt64(3, freeDiskSpace_);
       }
       getUnknownFields().writeTo(output);
     }
@@ -10984,15 +12341,11 @@ public final class BookkeeperProtocol {
       }
       if (((bitField0_ & 0x00000002) == 0x00000002)) {
         size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(2, ledgerId_);
+          .computeInt64Size(2, totalDiskCapacity_);
       }
       if (((bitField0_ & 0x00000004) == 0x00000004)) {
         size += com.google.protobuf.CodedOutputStream
-          .computeBytesSize(3, lacBody_);
-      }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeBytesSize(4, lastEntryBody_);
+          .computeInt64Size(3, freeDiskSpace_);
       }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
@@ -11006,53 +12359,53 @@ public final class BookkeeperProtocol {
       return super.writeReplace();
     }
 
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseFrom(byte[] data)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseDelimitedFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseDelimitedFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -11061,7 +12414,7 @@ public final class BookkeeperProtocol {
 
     public static Builder newBuilder() { return Builder.create(); }
     public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse prototype) {
+    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse prototype) {
       return newBuilder().mergeFrom(prototype);
     }
     public Builder toBuilder() { return newBuilder(this); }
@@ -11073,25 +12426,25 @@ public final class BookkeeperProtocol {
       return builder;
     }
     /**
-     * Protobuf type {@code ReadLacResponse}
+     * Protobuf type {@code GetBookieInfoResponse}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:ReadLacResponse)
-        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponseOrBuilder {
+        // @@protoc_insertion_point(builder_implements:GetBookieInfoResponse)
+        org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponseOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacResponse_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoResponse_descriptor;
       }
 
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacResponse_fieldAccessorTable
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoResponse_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.Builder.class);
+                org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.Builder.class);
       }
 
-      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.newBuilder()
+      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -11113,12 +12466,10 @@ public final class BookkeeperProtocol {
         super.clear();
         status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
         bitField0_ = (bitField0_ & ~0x00000001);
-        ledgerId_ = 0L;
+        totalDiskCapacity_ = 0L;
         bitField0_ = (bitField0_ & ~0x00000002);
-        lacBody_ = com.google.protobuf.ByteString.EMPTY;
+        freeDiskSpace_ = 0L;
         bitField0_ = (bitField0_ & ~0x00000004);
-        lastEntryBody_ = com.google.protobuf.ByteString.EMPTY;
-        bitField0_ = (bitField0_ & ~0x00000008);
         return this;
       }
 
@@ -11128,23 +12479,23 @@ public final class BookkeeperProtocol {
 
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_ReadLacResponse_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoResponse_descriptor;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse getDefaultInstanceForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.getDefaultInstance();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse getDefaultInstanceForType() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.getDefaultInstance();
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse build() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse result = buildPartial();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse build() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
         return result;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse buildPartial() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse result = new org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse(this);
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse buildPartial() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse result = new org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse(this);
         int from_bitField0_ = bitField0_;
         int to_bitField0_ = 0;
         if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
@@ -11154,42 +12505,35 @@ public final class BookkeeperProtocol {
         if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
           to_bitField0_ |= 0x00000002;
         }
-        result.ledgerId_ = ledgerId_;
+        result.totalDiskCapacity_ = totalDiskCapacity_;
         if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
           to_bitField0_ |= 0x00000004;
         }
-        result.lacBody_ = lacBody_;
-        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
-          to_bitField0_ |= 0x00000008;
-        }
-        result.lastEntryBody_ = lastEntryBody_;
+        result.freeDiskSpace_ = freeDiskSpace_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
       }
 
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse) {
-          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse)other);
+        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse) {
+          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse other) {
-        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse.getDefaultInstance()) return this;
+      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse other) {
+        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.getDefaultInstance()) return this;
         if (other.hasStatus()) {
           setStatus(other.getStatus());
         }
-        if (other.hasLedgerId()) {
-          setLedgerId(other.getLedgerId());
-        }
-        if (other.hasLacBody()) {
-          setLacBody(other.getLacBody());
+        if (other.hasTotalDiskCapacity()) {
+          setTotalDiskCapacity(other.getTotalDiskCapacity());
         }
-        if (other.hasLastEntryBody()) {
-          setLastEntryBody(other.getLastEntryBody());
+        if (other.hasFreeDiskSpace()) {
+          setFreeDiskSpace(other.getFreeDiskSpace());
         }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
@@ -11200,10 +12544,6 @@ public final class BookkeeperProtocol {
           
           return false;
         }
-        if (!hasLedgerId()) {
-          
-          return false;
-        }
         return true;
       }
 
@@ -11211,11 +12551,11 @@ public final class BookkeeperProtocol {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse parsedMessage = null;
+        org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.ReadLacResponse) e.getUnfinishedMessage();
+          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse) e.getUnfinishedMessage();
           throw e;
         } finally {
           if (parsedMessage != null) {
@@ -11261,202 +12601,105 @@ public final class BookkeeperProtocol {
         return this;
       }
 
-      private long ledgerId_ ;
+      private long totalDiskCapacity_ ;
       /**
-       * <code>required int64 ledgerId = 2;</code>
+       * <code>optional int64 totalDiskCapacity = 2;</code>
        */
-      public boolean hasLedgerId() {
+      public boolean hasTotalDiskCapacity() {
         return ((bitField0_ & 0x00000002) == 0x00000002);
       }
       /**
-       * <code>required int64 ledgerId = 2;</code>
+       * <code>optional int64 totalDiskCapacity = 2;</code>
        */
-      public long getLedgerId() {
-        return ledgerId_;
+      public long getTotalDiskCapacity() {
+        return totalDiskCapacity_;
       }
       /**
-       * <code>required int64 ledgerId = 2;</code>
+       * <code>optional int64 totalDiskCapacity = 2;</code>
        */
-      public Builder setLedgerId(long value) {
+      public Builder setTotalDiskCapacity(long value) {
         bitField0_ |= 0x00000002;
-        ledgerId_ = value;
+        totalDiskCapacity_ = value;
         onChanged();
         return this;
       }
       /**
-       * <code>required int64 ledgerId = 2;</code>
+       * <code>optional int64 totalDiskCapacity = 2;</code>
        */
-      public Builder clearLedgerId() {
+      public Builder clearTotalDiskCapacity() {
         bitField0_ = (bitField0_ & ~0x00000002);
-        ledgerId_ = 0L;
+        totalDiskCapacity_ = 0L;
         onChanged();
         return this;
       }
 
-      private com.google.protobuf.ByteString lacBody_ = com.google.protobuf.ByteString.EMPTY;
+      private long freeDiskSpace_ ;
       /**
-       * <code>optional bytes lacBody = 3;</code>
-       *
-       * <pre>
-       * lac sent by PutLacRequest
-       * </pre>
+       * <code>optional int64 freeDiskSpace = 3;</code>
        */
-      public boolean hasLacBody() {
+      public boolean hasFreeDiskSpace() {
         return ((bitField0_ & 0x00000004) == 0x00000004);
       }
       /**
-       * <code>optional bytes lacBody = 3;</code>
-       *
-       * <pre>
-       * lac sent by PutLacRequest
-       * </pre>
+       * <code>optional int64 freeDiskSpace = 3;</code>
        */
-      public com.google.protobuf.ByteString getLacBody() {
-        return lacBody_;
+      public long getFreeDiskSpace() {
+        return freeDiskSpace_;
       }
       /**
-       * <code>optional bytes lacBody = 3;</code>
-       *
-       * <pre>
-       * lac sent by PutLacRequest
-       * </pre>
+       * <code>optional int64 freeDiskSpace = 3;</code>
        */
-      public Builder setLacBody(com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000004;
-        lacBody_ = value;
+      public Builder setFreeDiskSpace(long value) {
+        bitField0_ |= 0x00000004;
+        freeDiskSpace_ = value;
         onChanged();
         return this;
       }
       /**
-       * <code>optional bytes lacBody = 3;</code>
-       *
-       * <pre>
-       * lac sent by PutLacRequest
-       * </pre>
+       * <code>optional int64 freeDiskSpace = 3;</code>
        */
-      public Builder clearLacBody() {
+      public Builder clearFreeDiskSpace() {
         bitField0_ = (bitField0_ & ~0x00000004);
-        lacBody_ = getDefaultInstance().getLacBody();
-        onChanged();
-        return this;
-      }
-
-      private com.google.protobuf.ByteString lastEntryBody_ = com.google.protobuf.ByteString.EMPTY;
-      /**
-       * <code>optional bytes lastEntryBody = 4;</code>
-       *
-       * <pre>
-       * Actual last entry on the disk
-       * </pre>
-       */
-      public boolean hasLastEntryBody() {
-        return ((bitField0_ & 0x00000008) == 0x00000008);
-      }
-      /**
-       * <code>optional bytes lastEntryBody = 4;</code>
-       *
-       * <pre>
-       * Actual last entry on the disk
-       * </pre>
-       */
-      public com.google.protobuf.ByteString getLastEntryBody() {
-        return lastEntryBody_;
-      }
-      /**
-       * <code>optional bytes lastEntryBody = 4;</code>
-       *
-       * <pre>
-       * Actual last entry on the disk
-       * </pre>
-       */
-      public Builder setLastEntryBody(com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000008;
-        lastEntryBody_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>optional bytes lastEntryBody = 4;</code>
-       *
-       * <pre>
-       * Actual last entry on the disk
-       * </pre>
-       */
-      public Builder clearLastEntryBody() {
-        bitField0_ = (bitField0_ & ~0x00000008);
-        lastEntryBody_ = getDefaultInstance().getLastEntryBody();
+        freeDiskSpace_ = 0L;
         onChanged();
         return this;
       }
 
-      // @@protoc_insertion_point(builder_scope:ReadLacResponse)
+      // @@protoc_insertion_point(builder_scope:GetBookieInfoResponse)
     }
 
     static {
-      defaultInstance = new ReadLacResponse(true);
+      defaultInstance = new GetBookieInfoResponse(true);
       defaultInstance.initFields();
     }
 
-    // @@protoc_insertion_point(class_scope:ReadLacResponse)
+    // @@protoc_insertion_point(class_scope:GetBookieInfoResponse)
   }
 
-  public interface GetBookieInfoResponseOrBuilder extends
-      // @@protoc_insertion_point(interface_extends:GetBookieInfoResponse)
+  public interface StartTLSResponseOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:StartTLSResponse)
       com.google.protobuf.MessageOrBuilder {
-
-    /**
-     * <code>required .StatusCode status = 1;</code>
-     */
-    boolean hasStatus();
-    /**
-     * <code>required .StatusCode status = 1;</code>
-     */
-    org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus();
-
-    /**
-     * <code>optional int64 totalDiskCapacity = 2;</code>
-     */
-    boolean hasTotalDiskCapacity();
-    /**
-     * <code>optional int64 totalDiskCapacity = 2;</code>
-     */
-    long getTotalDiskCapacity();
-
-    /**
-     * <code>optional int64 freeDiskSpace = 3;</code>
-     */
-    boolean hasFreeDiskSpace();
-    /**
-     * <code>optional int64 freeDiskSpace = 3;</code>
-     */
-    long getFreeDiskSpace();
   }
   /**
-   * Protobuf type {@code GetBookieInfoResponse}
+   * Protobuf type {@code StartTLSResponse}
    */
-  public static final class GetBookieInfoResponse extends
+  public static final class StartTLSResponse extends
       com.google.protobuf.GeneratedMessage implements
-      // @@protoc_insertion_point(message_implements:GetBookieInfoResponse)
-      GetBookieInfoResponseOrBuilder {
-    // Use GetBookieInfoResponse.newBuilder() to construct.
-    private GetBookieInfoResponse(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      // @@protoc_insertion_point(message_implements:StartTLSResponse)
+      StartTLSResponseOrBuilder {
+    // Use StartTLSResponse.newBuilder() to construct.
+    private StartTLSResponse(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
       super(builder);
       this.unknownFields = builder.getUnknownFields();
     }
-    private GetBookieInfoResponse(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+    private StartTLSResponse(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
 
-    private static final GetBookieInfoResponse defaultInstance;
-    public static GetBookieInfoResponse getDefaultInstance() {
+    private static final StartTLSResponse defaultInstance;
+    public static StartTLSResponse getDefaultInstance() {
       return defaultInstance;
     }
 
-    public GetBookieInfoResponse getDefaultInstanceForType() {
+    public StartTLSResponse getDefaultInstanceForType() {
       return defaultInstance;
     }
 
@@ -11466,12 +12709,11 @@ public final class BookkeeperProtocol {
         getUnknownFields() {
       return this.unknownFields;
     }
-    private GetBookieInfoResponse(
+    private StartTLSResponse(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       initFields();
-      int mutable_bitField0_ = 0;
       com.google.protobuf.UnknownFieldSet.Builder unknownFields =
           com.google.protobuf.UnknownFieldSet.newBuilder();
       try {
@@ -11489,27 +12731,6 @@ public final class BookkeeperProtocol {
               }
               break;
             }
-            case 8: {
-              int rawValue = input.readEnum();
-              org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode value = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.valueOf(rawValue);
-              if (value == null) {
-                unknownFields.mergeVarintField(1, rawValue);
-              } else {
-                bitField0_ |= 0x00000001;
-                status_ = value;
-              }
-              break;
-            }
-            case 16: {
-              bitField0_ |= 0x00000002;
-              totalDiskCapacity_ = input.readInt64();
-              break;
-            }
-            case 24: {
-              bitField0_ |= 0x00000004;
-              freeDiskSpace_ = input.readInt64();
-              break;
-            }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -11520,85 +12741,36 @@ public final class BookkeeperProtocol {
       } finally {
         this.unknownFields = unknownFields.build();
         makeExtensionsImmutable();
-      }
-    }
-    public static final com.google.protobuf.Descriptors.Descriptor
-        getDescriptor() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoResponse_descriptor;
-    }
-
-    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
-        internalGetFieldAccessorTable() {
-      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoResponse_fieldAccessorTable
-          .ensureFieldAccessorsInitialized(
-              org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.Builder.class);
-    }
-
-    public static com.google.protobuf.Parser<GetBookieInfoResponse> PARSER =
-        new com.google.protobuf.AbstractParser<GetBookieInfoResponse>() {
-      public GetBookieInfoResponse parsePartialFrom(
-          com.google.protobuf.CodedInputStream input,
-          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
-          throws com.google.protobuf.InvalidProtocolBufferException {
-        return new GetBookieInfoResponse(input, extensionRegistry);
-      }
-    };
-
-    @java.lang.Override
-    public com.google.protobuf.Parser<GetBookieInfoResponse> getParserForType() {
-      return PARSER;
-    }
-
-    private int bitField0_;
-    public static final int STATUS_FIELD_NUMBER = 1;
-    private org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode status_;
-    /**
-     * <code>required .StatusCode status = 1;</code>
-     */
-    public boolean hasStatus() {
-      return ((bitField0_ & 0x00000001) == 0x00000001);
-    }
-    /**
-     * <code>required .StatusCode status = 1;</code>
-     */
-    public org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus() {
-      return status_;
-    }
-
-    public static final int TOTALDISKCAPACITY_FIELD_NUMBER = 2;
-    private long totalDiskCapacity_;
-    /**
-     * <code>optional int64 totalDiskCapacity = 2;</code>
-     */
-    public boolean hasTotalDiskCapacity() {
-      return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
     }
-    /**
-     * <code>optional int64 totalDiskCapacity = 2;</code>
-     */
-    public long getTotalDiskCapacity() {
-      return totalDiskCapacity_;
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_StartTLSResponse_descriptor;
     }
 
-    public static final int FREEDISKSPACE_FIELD_NUMBER = 3;
-    private long freeDiskSpace_;
-    /**
-     * <code>optional int64 freeDiskSpace = 3;</code>
-     */
-    public boolean hasFreeDiskSpace() {
-      return ((bitField0_ & 0x00000004) == 0x00000004);
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_StartTLSResponse_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.Builder.class);
     }
-    /**
-     * <code>optional int64 freeDiskSpace = 3;</code>
-     */
-    public long getFreeDiskSpace() {
-      return freeDiskSpace_;
+
+    public static com.google.protobuf.Parser<StartTLSResponse> PARSER =
+        new com.google.protobuf.AbstractParser<StartTLSResponse>() {
+      public StartTLSResponse parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new StartTLSResponse(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<StartTLSResponse> getParserForType() {
+      return PARSER;
     }
 
     private void initFields() {
-      status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
-      totalDiskCapacity_ = 0L;
-      freeDiskSpace_ = 0L;
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
@@ -11606,10 +12778,6 @@ public final class BookkeeperProtocol {
       if (isInitialized == 1) return true;
       if (isInitialized == 0) return false;
 
-      if (!hasStatus()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
       memoizedIsInitialized = 1;
       return true;
     }
@@ -11617,15 +12785,6 @@ public final class BookkeeperProtocol {
     public void writeTo(com.google.protobuf.CodedOutputStream output)
                         throws java.io.IOException {
       getSerializedSize();
-      if (((bitField0_ & 0x00000001) == 0x00000001)) {
-        output.writeEnum(1, status_.getNumber());
-      }
-      if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        output.writeInt64(2, totalDiskCapacity_);
-      }
-      if (((bitField0_ & 0x00000004) == 0x00000004)) {
-        output.writeInt64(3, freeDiskSpace_);
-      }
       getUnknownFields().writeTo(output);
     }
 
@@ -11635,18 +12794,6 @@ public final class BookkeeperProtocol {
       if (size != -1) return size;
 
       size = 0;
-      if (((bitField0_ & 0x00000001) == 0x00000001)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeEnumSize(1, status_.getNumber());
-      }
-      if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(2, totalDiskCapacity_);
-      }
-      if (((bitField0_ & 0x00000004) == 0x00000004)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeInt64Size(3, freeDiskSpace_);
-      }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
       return size;
@@ -11659,53 +12806,53 @@ public final class BookkeeperProtocol {
       return super.writeReplace();
     }
 
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseFrom(byte[] data)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseDelimitedFrom(java.io.InputStream input)
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseDelimitedFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input, extensionRegistry);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parseFrom(
+    public static org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -11714,7 +12861,7 @@ public final class BookkeeperProtocol {
 
     public static Builder newBuilder() { return Builder.create(); }
     public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse prototype) {
+    public static Builder newBuilder(org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse prototype) {
       return newBuilder().mergeFrom(prototype);
     }
     public Builder toBuilder() { return newBuilder(this); }
@@ -11726,25 +12873,25 @@ public final class BookkeeperProtocol {
       return builder;
     }
     /**
-     * Protobuf type {@code GetBookieInfoResponse}
+     * Protobuf type {@code StartTLSResponse}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder<Builder> implements
-        // @@protoc_insertion_point(builder_implements:GetBookieInfoResponse)
-        org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponseOrBuilder {
+        // @@protoc_insertion_point(builder_implements:StartTLSResponse)
+        org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponseOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoResponse_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_StartTLSResponse_descriptor;
       }
 
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoResponse_fieldAccessorTable
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_StartTLSResponse_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.Builder.class);
+                org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.class, org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.Builder.class);
       }
 
-      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.newBuilder()
+      // Construct using org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -11764,12 +12911,6 @@ public final class BookkeeperProtocol {
 
       public Builder clear() {
         super.clear();
-        status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
-        bitField0_ = (bitField0_ & ~0x00000001);
-        totalDiskCapacity_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000002);
-        freeDiskSpace_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000004);
         return this;
       }
 
@@ -11779,71 +12920,43 @@ public final class BookkeeperProtocol {
 
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_GetBookieInfoResponse_descriptor;
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.internal_static_StartTLSResponse_descriptor;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse getDefaultInstanceForType() {
-        return org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.getDefaultInstance();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse getDefaultInstanceForType() {
+        return org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.getDefaultInstance();
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse build() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse result = buildPartial();
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse build() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
         return result;
       }
 
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse buildPartial() {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse result = new org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse(this);
-        int from_bitField0_ = bitField0_;
-        int to_bitField0_ = 0;
-        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
-          to_bitField0_ |= 0x00000001;
-        }
-        result.status_ = status_;
-        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
-          to_bitField0_ |= 0x00000002;
-        }
-        result.totalDiskCapacity_ = totalDiskCapacity_;
-        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
-          to_bitField0_ |= 0x00000004;
-        }
-        result.freeDiskSpace_ = freeDiskSpace_;
-        result.bitField0_ = to_bitField0_;
+      public org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse buildPartial() {
+        org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse result = new org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse(this);
         onBuilt();
         return result;
       }
 
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse) {
-          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse)other);
+        if (other instanceof org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse) {
+          return mergeFrom((org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse other) {
-        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse.getDefaultInstance()) return this;
-        if (other.hasStatus()) {
-          setStatus(other.getStatus());
-        }
-        if (other.hasTotalDiskCapacity()) {
-          setTotalDiskCapacity(other.getTotalDiskCapacity());
-        }
-        if (other.hasFreeDiskSpace()) {
-          setFreeDiskSpace(other.getFreeDiskSpace());
-        }
+      public Builder mergeFrom(org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse other) {
+        if (other == org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse.getDefaultInstance()) return this;
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
 
       public final boolean isInitialized() {
-        if (!hasStatus()) {
-          
-          return false;
-        }
         return true;
       }
 
@@ -11851,11 +12964,11 @@ public final class BookkeeperProtocol {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse parsedMessage = null;
+        org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.GetBookieInfoResponse) e.getUnfinishedMessage();
+          parsedMessage = (org.apache.bookkeeper.proto.BookkeeperProtocol.StartTLSResponse) e.getUnfinishedMessage();
           throw e;
         } finally {
           if (parsedMessage != null) {
@@ -11864,116 +12977,16 @@ public final class BookkeeperProtocol {
         }
         return this;
       }
-      private int bitField0_;
-
-      private org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
-      /**
-       * <code>required .StatusCode status = 1;</code>
-       */
-      public boolean hasStatus() {
-        return ((bitField0_ & 0x00000001) == 0x00000001);
-      }
-      /**
-       * <code>required .StatusCode status = 1;</code>
-       */
-      public org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode getStatus() {
-        return status_;
-      }
-      /**
-       * <code>required .StatusCode status = 1;</code>
-       */
-      public Builder setStatus(org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode value) {
-        if (value == null) {
-          throw new NullPointerException();
-        }
-        bitField0_ |= 0x00000001;
-        status_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>required .StatusCode status = 1;</code>
-       */
-      public Builder clearStatus() {
-        bitField0_ = (bitField0_ & ~0x00000001);
-        status_ = org.apache.bookkeeper.proto.BookkeeperProtocol.StatusCode.EOK;
-        onChanged();
-        return this;
-      }
-
-      private long totalDiskCapacity_ ;
-      /**
-       * <code>optional int64 totalDiskCapacity = 2;</code>
-       */
-      public boolean hasTotalDiskCapacity() {
-        return ((bitField0_ & 0x00000002) == 0x00000002);
-      }
-      /**
-       * <code>optional int64 totalDiskCapacity = 2;</code>
-       */
-      public long getTotalDiskCapacity() {
-        return totalDiskCapacity_;
-      }
-      /**
-       * <code>optional int64 totalDiskCapacity = 2;</code>
-       */
-      public Builder setTotalDiskCapacity(long value) {
-        bitField0_ |= 0x00000002;
-        totalDiskCapacity_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>optional int64 totalDiskCapacity = 2;</code>
-       */
-      public Builder clearTotalDiskCapacity() {
-        bitField0_ = (bitField0_ & ~0x00000002);
-        totalDiskCapacity_ = 0L;
-        onChanged();
-        return this;
-      }
-
-      private long freeDiskSpace_ ;
-      /**
-       * <code>optional int64 freeDiskSpace = 3;</code>
-       */
-      public boolean hasFreeDiskSpace() {
-        return ((bitField0_ & 0x00000004) == 0x00000004);
-      }
-      /**
-       * <code>optional int64 freeDiskSpace = 3;</code>
-       */
-      public long getFreeDiskSpace() {
-        return freeDiskSpace_;
-      }
-      /**
-       * <code>optional int64 freeDiskSpace = 3;</code>
-       */
-      public Builder setFreeDiskSpace(long value) {
-        bitField0_ |= 0x00000004;
-        freeDiskSpace_ = value;
-        onChanged();
-        return this;
-      }
-      /**
-       * <code>optional int64 freeDiskSpace = 3;</code>
-       */
-      public Builder clearFreeDiskSpace() {
-        bitField0_ = (bitField0_ & ~0x00000004);
-        freeDiskSpace_ = 0L;
-        onChanged();
-        return this;
-      }
 
-      // @@protoc_insertion_point(builder_scope:GetBookieInfoResponse)
+      // @@protoc_insertion_point(builder_scope:StartTLSResponse)
     }
 
     static {
-      defaultInstance = new GetBookieInfoResponse(true);
+      defaultInstance = new StartTLSResponse(true);
       defaultInstance.initFields();
     }
 
-    // @@protoc_insertion_point(class_scope:GetBookieInfoResponse)
+    // @@protoc_insertion_point(class_scope:StartTLSResponse)
   }
 
   private static final com.google.protobuf.Descriptors.Descriptor
@@ -11997,6 +13010,11 @@ public final class BookkeeperProtocol {
     com.google.protobuf.GeneratedMessage.FieldAccessorTable
       internal_static_AddRequest_fieldAccessorTable;
   private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_StartTLSRequest_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_StartTLSRequest_fieldAccessorTable;
+  private static final com.google.protobuf.Descriptors.Descriptor
     internal_static_WriteLacRequest_descriptor;
   private static
     com.google.protobuf.GeneratedMessage.FieldAccessorTable
@@ -12046,6 +13064,11 @@ public final class BookkeeperProtocol {
   private static
     com.google.protobuf.GeneratedMessage.FieldAccessorTable
       internal_static_GetBookieInfoResponse_fieldAccessorTable;
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_StartTLSResponse_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_StartTLSResponse_fieldAccessorTable;
 
   public static com.google.protobuf.Descriptors.FileDescriptor
       getDescriptor() {
@@ -12058,60 +13081,63 @@ public final class BookkeeperProtocol {
       "\n\'src/main/proto/BookkeeperProtocol.prot" +
       "o\"e\n\016BKPacketHeader\022!\n\007version\030\001 \002(\0162\020.P" +
       "rotocolVersion\022!\n\toperation\030\002 \002(\0162\016.Oper" +
-      "ationType\022\r\n\005txnId\030\003 \002(\004\"\232\002\n\007Request\022\037\n\006" +
+      "ationType\022\r\n\005txnId\030\003 \002(\004\"\305\002\n\007Request\022\037\n\006" +
       "header\030\001 \002(\0132\017.BKPacketHeader\022!\n\013readReq" +
       "uest\030d \001(\0132\014.ReadRequest\022\037\n\naddRequest\030e" +
       " \001(\0132\013.AddRequest\022!\n\013authRequest\030f \001(\0132\014" +
       ".AuthMessage\022)\n\017writeLacRequest\030g \001(\0132\020." +
       "WriteLacRequest\022\'\n\016readLacRequest\030h \001(\0132" +
       "\017.ReadLacRequest\0223\n\024getBookieInfoRequest",
-      "\030i \001(\0132\025.GetBookieInfoRequest\"\271\001\n\013ReadRe" +
-      "quest\022\037\n\004flag\030d \001(\0162\021.ReadRequest.Flag\022\020" +
-      "\n\010ledgerId\030\001 \002(\003\022\017\n\007entryId\030\002 \002(\003\022\021\n\tmas" +
-      "terKey\030\003 \001(\014\022\023\n\013previousLAC\030\004 \001(\003\022\017\n\007tim" +
-      "eOut\030\005 \001(\003\"-\n\004Flag\022\020\n\014FENCE_LEDGER\020\001\022\023\n\017" +
-      "ENTRY_PIGGYBACK\020\002\"\212\001\n\nAddRequest\022\036\n\004flag" +
-      "\030d \001(\0162\020.AddRequest.Flag\022\020\n\010ledgerId\030\001 \002" +
-      "(\003\022\017\n\007entryId\030\002 \002(\003\022\021\n\tmasterKey\030\003 \002(\014\022\014" +
-      "\n\004body\030\004 \002(\014\"\030\n\004Flag\022\020\n\014RECOVERY_ADD\020\001\"Q" +
-      "\n\017WriteLacRequest\022\020\n\010ledgerId\030\001 \002(\003\022\013\n\003l",
-      "ac\030\002 \002(\003\022\021\n\tmasterKey\030\003 \002(\014\022\014\n\004body\030\004 \002(" +
-      "\014\"\"\n\016ReadLacRequest\022\020\n\010ledgerId\030\001 \002(\003\"`\n" +
-      "\024GetBookieInfoRequest\022\021\n\trequested\030\001 \001(\003" +
-      "\"5\n\005Flags\022\027\n\023TOTAL_DISK_CAPACITY\020\001\022\023\n\017FR" +
-      "EE_DISK_SPACE\020\002\"\303\002\n\010Response\022\037\n\006header\030\001" +
-      " \002(\0132\017.BKPacketHeader\022\033\n\006status\030\002 \002(\0162\013." +
-      "StatusCode\022#\n\014readResponse\030d \001(\0132\r.ReadR" +
-      "esponse\022!\n\013addResponse\030e \001(\0132\014.AddRespon" +
-      "se\022\"\n\014authResponse\030f \001(\0132\014.AuthMessage\022+" +
-      "\n\020writeLacResponse\030g \001(\0132\021.WriteLacRespo",
-      "nse\022)\n\017readLacResponse\030h \001(\0132\020.ReadLacRe" +
-      "sponse\0225\n\025getBookieInfoResponse\030i \001(\0132\026." +
-      "GetBookieInfoResponse\"\210\001\n\014ReadResponse\022\033" +
-      "\n\006status\030\001 \002(\0162\013.StatusCode\022\020\n\010ledgerId\030" +
-      "\002 \002(\003\022\017\n\007entryId\030\003 \002(\003\022\014\n\004body\030\004 \001(\014\022\016\n\006" +
-      "maxLAC\030\005 \001(\003\022\032\n\022lacUpdateTimestamp\030\006 \001(\003" +
-      "\"M\n\013AddResponse\022\033\n\006status\030\001 \002(\0162\013.Status" +
-      "Code\022\020\n\010ledgerId\030\002 \002(\003\022\017\n\007entryId\030\003 \002(\003\"" +
-      "6\n\013AuthMessage\022\026\n\016authPluginName\030\001 \002(\t\022\017" +
-      "\n\007payload\030\002 \002(\014\"A\n\020WriteLacResponse\022\033\n\006s",
-      "tatus\030\001 \002(\0162\013.StatusCode\022\020\n\010ledgerId\030\002 \002" +
-      "(\003\"h\n\017ReadLacResponse\022\033\n\006status\030\001 \002(\0162\013." +
-      "StatusCode\022\020\n\010ledgerId\030\002 \002(\003\022\017\n\007lacBody\030" +
-      "\003 \001(\014\022\025\n\rlastEntryBody\030\004 \001(\014\"f\n\025GetBooki" +
-      "eInfoResponse\022\033\n\006status\030\001 \002(\0162\013.StatusCo" +
-      "de\022\031\n\021totalDiskCapacity\030\002 \001(\003\022\025\n\rfreeDis" +
-      "kSpace\030\003 \001(\003*F\n\017ProtocolVersion\022\017\n\013VERSI" +
-      "ON_ONE\020\001\022\017\n\013VERSION_TWO\020\002\022\021\n\rVERSION_THR" +
-      "EE\020\003*\206\001\n\nStatusCode\022\007\n\003EOK\020\000\022\016\n\tENOLEDGE" +
-      "R\020\222\003\022\r\n\010ENOENTRY\020\223\003\022\014\n\007EBADREQ\020\224\003\022\010\n\003EIO",
-      "\020\365\003\022\010\n\003EUA\020\366\003\022\020\n\013EBADVERSION\020\367\003\022\014\n\007EFENC" +
-      "ED\020\370\003\022\016\n\tEREADONLY\020\371\003*\225\001\n\rOperationType\022" +
-      "\016\n\nREAD_ENTRY\020\001\022\r\n\tADD_ENTRY\020\002\022\024\n\020RANGE_" +
-      "READ_ENTRY\020\003\022\023\n\017RANGE_ADD_ENTRY\020\004\022\010\n\004AUT" +
-      "H\020\005\022\r\n\tWRITE_LAC\020\006\022\014\n\010READ_LAC\020\007\022\023\n\017GET_" +
-      "BOOKIE_INFO\020\010B\037\n\033org.apache.bookkeeper.p" +
-      "rotoH\001"
+      "\030i \001(\0132\025.GetBookieInfoRequest\022)\n\017startTL" +
+      "SRequest\030j \001(\0132\020.StartTLSRequest\"\271\001\n\013Rea" +
+      "dRequest\022\037\n\004flag\030d \001(\0162\021.ReadRequest.Fla" +
+      "g\022\020\n\010ledgerId\030\001 \002(\003\022\017\n\007entryId\030\002 \002(\003\022\021\n\t" +
+      "masterKey\030\003 \001(\014\022\023\n\013previousLAC\030\004 \001(\003\022\017\n\007" +
+      "timeOut\030\005 \001(\003\"-\n\004Flag\022\020\n\014FENCE_LEDGER\020\001\022" +
+      "\023\n\017ENTRY_PIGGYBACK\020\002\"\212\001\n\nAddRequest\022\036\n\004f" +
+      "lag\030d \001(\0162\020.AddRequest.Flag\022\020\n\010ledgerId\030" +
+      "\001 \002(\003\022\017\n\007entryId\030\002 \002(\003\022\021\n\tmasterKey\030\003 \002(" +
+      "\014\022\014\n\004body\030\004 \002(\014\"\030\n\004Flag\022\020\n\014RECOVERY_ADD\020",
+      "\001\"\021\n\017StartTLSRequest\"Q\n\017WriteLacRequest\022" +
+      "\020\n\010ledgerId\030\001 \002(\003\022\013\n\003lac\030\002 \002(\003\022\021\n\tmaster" +
+      "Key\030\003 \002(\014\022\014\n\004body\030\004 \002(\014\"\"\n\016ReadLacReques" +
+      "t\022\020\n\010ledgerId\030\001 \002(\003\"`\n\024GetBookieInfoRequ" +
+      "est\022\021\n\trequested\030\001 \001(\003\"5\n\005Flags\022\027\n\023TOTAL" +
+      "_DISK_CAPACITY\020\001\022\023\n\017FREE_DISK_SPACE\020\002\"\360\002" +
+      "\n\010Response\022\037\n\006header\030\001 \002(\0132\017.BKPacketHea" +
+      "der\022\033\n\006status\030\002 \002(\0162\013.StatusCode\022#\n\014read" +
+      "Response\030d \001(\0132\r.ReadResponse\022!\n\013addResp" +
+      "onse\030e \001(\0132\014.AddResponse\022\"\n\014authResponse",
+      "\030f \001(\0132\014.AuthMessage\022+\n\020writeLacResponse" +
+      "\030g \001(\0132\021.WriteLacResponse\022)\n\017readLacResp" +
+      "onse\030h \001(\0132\020.ReadLacResponse\0225\n\025getBooki" +
+      "eInfoResponse\030i \001(\0132\026.GetBookieInfoRespo" +
+      "nse\022+\n\020startTLSResponse\030j \001(\0132\021.StartTLS" +
+      "Response\"\210\001\n\014ReadResponse\022\033\n\006status\030\001 \002(" +
+      "\0162\013.StatusCode\022\020\n\010ledgerId\030\002 \002(\003\022\017\n\007entr" +
+      "yId\030\003 \002(\003\022\014\n\004body\030\004 \001(\014\022\016\n\006maxLAC\030\005 \001(\003\022" +
+      "\032\n\022lacUpdateTimestamp\030\006 \001(\003\"M\n\013AddRespon" +
+      "se\022\033\n\006status\030\001 \002(\0162\013.StatusCode\022\020\n\010ledge",
+      "rId\030\002 \002(\003\022\017\n\007entryId\030\003 \002(\003\"6\n\013AuthMessag" +
+      "e\022\026\n\016authPluginName\030\001 \002(\t\022\017\n\007payload\030\002 \002" +
+      "(\014\"A\n\020WriteLacResponse\022\033\n\006status\030\001 \002(\0162\013" +
+      ".StatusCode\022\020\n\010ledgerId\030\002 \002(\003\"h\n\017ReadLac" +
+      "Response\022\033\n\006status\030\001 \002(\0162\013.StatusCode\022\020\n" +
+      "\010ledgerId\030\002 \002(\003\022\017\n\007lacBody\030\003 \001(\014\022\025\n\rlast" +
+      "EntryBody\030\004 \001(\014\"f\n\025GetBookieInfoResponse" +
+      "\022\033\n\006status\030\001 \002(\0162\013.StatusCode\022\031\n\021totalDi" +
+      "skCapacity\030\002 \001(\003\022\025\n\rfreeDiskSpace\030\003 \001(\003\"" +
+      "\022\n\020StartTLSResponse*F\n\017ProtocolVersion\022\017",
+      "\n\013VERSION_ONE\020\001\022\017\n\013VERSION_TWO\020\002\022\021\n\rVERS" +
+      "ION_THREE\020\003*\206\001\n\nStatusCode\022\007\n\003EOK\020\000\022\016\n\tE" +
+      "NOLEDGER\020\222\003\022\r\n\010ENOENTRY\020\223\003\022\014\n\007EBADREQ\020\224\003" +
+      "\022\010\n\003EIO\020\365\003\022\010\n\003EUA\020\366\003\022\020\n\013EBADVERSION\020\367\003\022\014" +
+      "\n\007EFENCED\020\370\003\022\016\n\tEREADONLY\020\371\003*\244\001\n\rOperati" +
+      "onType\022\016\n\nREAD_ENTRY\020\001\022\r\n\tADD_ENTRY\020\002\022\024\n" +
+      "\020RANGE_READ_ENTRY\020\003\022\023\n\017RANGE_ADD_ENTRY\020\004" +
+      "\022\010\n\004AUTH\020\005\022\r\n\tWRITE_LAC\020\006\022\014\n\010READ_LAC\020\007\022" +
+      "\023\n\017GET_BOOKIE_INFO\020\010\022\r\n\tSTART_TLS\020\tB\037\n\033o" +
+      "rg.apache.bookkeeper.protoH\001"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
         new com.google.protobuf.Descriptors.FileDescriptor.    InternalDescriptorAssigner() {
@@ -12136,7 +13162,7 @@ public final class BookkeeperProtocol {
     internal_static_Request_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessage.FieldAccessorTable(
         internal_static_Request_descriptor,
-        new java.lang.String[] { "Header", "ReadRequest", "AddRequest", "AuthRequest", "WriteLacRequest", "ReadLacRequest", "GetBookieInfoRequest", });
+        new java.lang.String[] { "Header", "ReadRequest", "AddRequest", "AuthRequest", "WriteLacRequest", "ReadLacRequest", "GetBookieInfoRequest", "StartTLSRequest", });
     internal_static_ReadRequest_descriptor =
       getDescriptor().getMessageTypes().get(2);
     internal_static_ReadRequest_fieldAccessorTable = new
@@ -12149,66 +13175,78 @@ public final class BookkeeperProtocol {
       com.google.protobuf.GeneratedMessage.FieldAccessorTable(
         internal_static_AddRequest_descriptor,
         new java.lang.String[] { "Flag", "LedgerId", "EntryId", "MasterKey", "Body", });
-    internal_static_WriteLacRequest_descriptor =
+    internal_static_StartTLSRequest_descriptor =
       getDescriptor().getMessageTypes().get(4);
+    internal_static_StartTLSRequest_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_StartTLSRequest_descriptor,
+        new java.lang.String[] { });
+    internal_static_WriteLacRequest_descriptor =
+      getDescriptor().getMessageTypes().get(5);
     internal_static_WriteLacRequest_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessage.FieldAccessorTable(
         internal_static_WriteLacRequest_descriptor,
         new java.lang.String[] { "LedgerId", "Lac", "MasterKey", "Body", });
     internal_static_ReadLacRequest_descriptor =
-      getDescriptor().getMessageTypes().get(5);
+      getDescriptor().getMessageTypes().get(6);
     internal_static_ReadLacRequest_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessage.FieldAccessorTable(
         internal_static_ReadLacRequest_descriptor,
         new java.lang.String[] { "LedgerId", });
     internal_static_GetBookieInfoRequest_descriptor =
-      getDescriptor().getMessageTypes().get(6);
+      getDescriptor().getMessageTypes().get(7);
     internal_static_GetBookieInfoRequest_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessage.FieldAccessorTable(
         internal_static_GetBookieInfoRequest_descriptor,
         new java.lang.String[] { "Requested", });
     internal_static_Response_descriptor =
-      getDescriptor().getMessageTypes().get(7);
+      getDescriptor().getMessageTypes().get(8);
     internal_static_Response_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessage.FieldAccessorTable(
         internal_static_Response_descriptor,
-        new java.lang.String[] { "Header", "Status", "ReadResponse", "AddResponse", "AuthResponse", "WriteLacResponse", "ReadLacResponse", "GetBookieInfoResponse", });
+        new java.lang.String[] { "Header", "Status", "ReadResponse", "AddResponse", "AuthResponse", "WriteLacResponse", "ReadLacResponse", "GetBookieInfoResponse", "StartTLSResponse", });
     internal_static_ReadResponse_descriptor =
-      getDescriptor().getMessageTypes().get(8);
+      getDescriptor().getMessageTypes().get(9);
     internal_static_ReadResponse_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessage.FieldAccessorTable(
         internal_static_ReadResponse_descriptor,
         new java.lang.String[] { "Status", "LedgerId", "EntryId", "Body", "MaxLAC", "LacUpdateTimestamp", });
     internal_static_AddResponse_descriptor =
-      getDescriptor().getMessageTypes().get(9);
+      getDescriptor().getMessageTypes().get(10);
     internal_static_AddResponse_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessage.FieldAccessorTable(
         internal_static_AddResponse_descriptor,
         new java.lang.String[] { "Status", "LedgerId", "EntryId", });
     internal_static_AuthMessage_descriptor =
-      getDescriptor().getMessageTypes().get(10);
+      getDescriptor().getMessageTypes().get(11);
     internal_static_AuthMessage_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessage.FieldAccessorTable(
         internal_static_AuthMessage_descriptor,
         new java.lang.String[] { "AuthPluginName", "Payload", });
     internal_static_WriteLacResponse_descriptor =
-      getDescriptor().getMessageTypes().get(11);
+      getDescriptor().getMessageTypes().get(12);
     internal_static_WriteLacResponse_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessage.FieldAccessorTable(
         internal_static_WriteLacResponse_descriptor,
         new java.lang.String[] { "Status", "LedgerId", });
     internal_static_ReadLacResponse_descriptor =
-      getDescriptor().getMessageTypes().get(12);
+      getDescriptor().getMessageTypes().get(13);
     internal_static_ReadLacResponse_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessage.FieldAccessorTable(
         internal_static_ReadLacResponse_descriptor,
         new java.lang.String[] { "Status", "LedgerId", "LacBody", "LastEntryBody", });
     internal_static_GetBookieInfoResponse_descriptor =
-      getDescriptor().getMessageTypes().get(13);
+      getDescriptor().getMessageTypes().get(14);
     internal_static_GetBookieInfoResponse_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessage.FieldAccessorTable(
         internal_static_GetBookieInfoResponse_descriptor,
         new java.lang.String[] { "Status", "TotalDiskCapacity", "FreeDiskSpace", });
+    internal_static_StartTLSResponse_descriptor =
+      getDescriptor().getMessageTypes().get(15);
+    internal_static_StartTLSResponse_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_StartTLSResponse_descriptor,
+        new java.lang.String[] { });
   }
 
   // @@protoc_insertion_point(outer_class_scope)
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/ConnectionPeer.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/ConnectionPeer.java
index 11a1eb5..b5a1837 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/ConnectionPeer.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/ConnectionPeer.java
@@ -60,4 +60,10 @@ public interface ConnectionPeer {
      * @see #getAuthorizedId()
      */
     public void setAuthorizedId(BookKeeperPrincipal principal);
+
+    /**
+     * This flag returns true if a 'secure' channel in use, like TLS
+     * @return true if the channel is 'secure'
+     */
+    public boolean isSecure();
 }
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/DefaultPerChannelBookieClientPool.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/DefaultPerChannelBookieClientPool.java
index 36a26ef..ba1b444 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/DefaultPerChannelBookieClientPool.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/DefaultPerChannelBookieClientPool.java
@@ -22,8 +22,12 @@ package org.apache.bookkeeper.proto;
 
 import java.util.concurrent.atomic.AtomicLong;
 
+import org.apache.bookkeeper.conf.ClientConfiguration;
 import org.apache.bookkeeper.net.BookieSocketAddress;
 import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.GenericCallback;
+import org.apache.bookkeeper.tls.SecurityException;
+import org.apache.bookkeeper.tls.SecurityHandlerFactory;
+import org.apache.bookkeeper.tls.SecurityProviderFactoryFactory;
 import org.apache.bookkeeper.util.MathUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -39,23 +43,33 @@ import com.google.common.base.Preconditions;
 class DefaultPerChannelBookieClientPool implements PerChannelBookieClientPool,
         GenericCallback<PerChannelBookieClient> {
 
-    static final Logger logger = LoggerFactory.getLogger(DefaultPerChannelBookieClientPool.class);
+    static final Logger LOG = LoggerFactory.getLogger(DefaultPerChannelBookieClientPool.class);
 
     final PerChannelBookieClientFactory factory;
     final BookieSocketAddress address;
+
     final PerChannelBookieClient[] clients;
+
+    final ClientConfiguration conf;
+    SecurityHandlerFactory shFactory;
+
     final AtomicInteger counter = new AtomicInteger(0);
     final AtomicLong errorCounter = new AtomicLong(0);
 
-    DefaultPerChannelBookieClientPool(PerChannelBookieClientFactory factory,
+    DefaultPerChannelBookieClientPool(ClientConfiguration conf, PerChannelBookieClientFactory factory,
                                       BookieSocketAddress address,
-                                      int coreSize) {
+                                      int coreSize) throws SecurityException {
         Preconditions.checkArgument(coreSize > 0);
         this.factory = factory;
         this.address = address;
+        this.conf = conf;
+
+        this.shFactory = SecurityProviderFactoryFactory
+                .getSecurityProviderFactory(conf.getTLSProviderFactoryClass());
+
         this.clients = new PerChannelBookieClient[coreSize];
         for (int i = 0; i < coreSize; i++) {
-            this.clients[i] = factory.create(address, this);
+            this.clients[i] = factory.create(address, this, shFactory);
         }
     }
 
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClient.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClient.java
index d2f4dc5..20f601c 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClient.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClient.java
@@ -48,9 +48,13 @@ import io.netty.handler.codec.CorruptedFrameException;
 import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
 import io.netty.handler.codec.LengthFieldPrepender;
 import io.netty.handler.codec.TooLongFrameException;
+import io.netty.handler.ssl.SslHandler;
 import io.netty.util.HashedWheelTimer;
 import io.netty.util.Timeout;
 import io.netty.util.TimerTask;
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.GenericFutureListener;
+
 import java.io.IOException;
 import java.net.SocketAddress;
 import java.nio.channels.ClosedChannelException;
@@ -78,6 +82,7 @@ import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.GetBookieInfoCall
 import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.WriteCallback;
 import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.WriteLacCallback;
 import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.ReadLacCallback;
+import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.StartTLSCallback;
 import org.apache.bookkeeper.proto.BookkeeperProtocol.AddRequest;
 import org.apache.bookkeeper.proto.BookkeeperProtocol.AddResponse;
 import org.apache.bookkeeper.proto.BookkeeperProtocol.BKPacketHeader;
@@ -97,12 +102,29 @@ import org.apache.bookkeeper.proto.BookkeeperProtocol.WriteLacResponse;
 import org.apache.bookkeeper.stats.NullStatsLogger;
 import org.apache.bookkeeper.stats.OpStatsLogger;
 import org.apache.bookkeeper.stats.StatsLogger;
+import org.apache.bookkeeper.tls.SecurityException;
+import org.apache.bookkeeper.tls.SecurityHandlerFactory;
+import org.apache.bookkeeper.tls.SecurityHandlerFactory.NodeType;
 import org.apache.bookkeeper.util.MathUtils;
 import org.apache.bookkeeper.util.OrderedSafeExecutor;
 import org.apache.bookkeeper.util.SafeRunnable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.Sets;
+import com.google.protobuf.ExtensionRegistry;
+import io.netty.buffer.ByteBufAllocator;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import java.net.SocketAddress;
+
+import java.net.SocketAddress;
+import java.security.cert.Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import org.apache.bookkeeper.auth.BookKeeperPrincipal;
+
 /**
  * This class manages all details of connection to a particular bookie. It also
  * has reconnect logic if a connection to a bookie fails.
@@ -132,6 +154,7 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
     final int readEntryTimeout;
     final int maxFrameSize;
     final int getBookieInfoTimeout;
+    final int startTLSTimeout;
 
     private final ConcurrentHashMap<CompletionKey, CompletionValue> completionObjects = new ConcurrentHashMap<CompletionKey, CompletionValue>();
 
@@ -146,6 +169,7 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
     private final OpStatsLogger readLacTimeoutOpLogger;
     private final OpStatsLogger getBookieInfoOpLogger;
     private final OpStatsLogger getBookieInfoTimeoutOpLogger;
+    private final OpStatsLogger startTLSOpLogger;
 
     private final boolean useV2WireProtocol;
 
@@ -160,7 +184,7 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
     private volatile BookKeeperPrincipal authorizedId = BookKeeperPrincipal.ANONYMOUS;
 
     enum ConnectionState {
-        DISCONNECTED, CONNECTING, CONNECTED, CLOSED
+        DISCONNECTED, CONNECTING, CONNECTED, CLOSED, START_TLS
     }
 
     volatile ConnectionState state;
@@ -170,9 +194,10 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
     private final PerChannelBookieClientPool pcbcPool;
     private final ClientAuthProvider.Factory authProviderFactory;
     private final ExtensionRegistry extRegistry;
+    private final SecurityHandlerFactory shFactory;
 
     public PerChannelBookieClient(OrderedSafeExecutor executor, EventLoopGroup eventLoopGroup,
-                                  BookieSocketAddress addr) {
+                                  BookieSocketAddress addr) throws SecurityException {
         this(new ClientConfiguration(), executor, eventLoopGroup, addr, null, NullStatsLogger.INSTANCE, null, null,
                 null);
     }
@@ -180,17 +205,28 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
     public PerChannelBookieClient(OrderedSafeExecutor executor, EventLoopGroup eventLoopGroup,
                                   BookieSocketAddress addr,
                                   ClientAuthProvider.Factory authProviderFactory,
-                                  ExtensionRegistry extRegistry) {
+                                  ExtensionRegistry extRegistry) throws SecurityException {
         this(new ClientConfiguration(), executor, eventLoopGroup, addr, null, NullStatsLogger.INSTANCE,
                 authProviderFactory, extRegistry, null);
     }
 
     public PerChannelBookieClient(ClientConfiguration conf, OrderedSafeExecutor executor,
-            EventLoopGroup eventLoopGroup, BookieSocketAddress addr,
+                                  EventLoopGroup eventLoopGroup, BookieSocketAddress addr,
+                                  HashedWheelTimer requestTimer, StatsLogger parentStatsLogger,
+                                  ClientAuthProvider.Factory authProviderFactory,
+                                  ExtensionRegistry extRegistry,
+                                  PerChannelBookieClientPool pcbcPool) throws SecurityException {
+       this(conf, executor, eventLoopGroup, addr, null, NullStatsLogger.INSTANCE,
+                authProviderFactory, extRegistry, pcbcPool, null);
+    }
+
+    public PerChannelBookieClient(ClientConfiguration conf, OrderedSafeExecutor executor,
+                                  EventLoopGroup eventLoopGroup, BookieSocketAddress addr,
                                   HashedWheelTimer requestTimer, StatsLogger parentStatsLogger,
                                   ClientAuthProvider.Factory authProviderFactory,
                                   ExtensionRegistry extRegistry,
-                                  PerChannelBookieClientPool pcbcPool) {
+                                  PerChannelBookieClientPool pcbcPool,
+                                  SecurityHandlerFactory shFactory) throws SecurityException {
         this.maxFrameSize = conf.getNettyMaxFrameSizeBytes();
         this.conf = conf;
         this.addr = addr;
@@ -205,10 +241,15 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
         this.addEntryTimeout = conf.getAddEntryTimeout();
         this.readEntryTimeout = conf.getReadEntryTimeout();
         this.getBookieInfoTimeout = conf.getBookieInfoTimeout();
+        this.startTLSTimeout = conf.getStartTLSTimeout();
         this.useV2WireProtocol = conf.getUseV2WireProtocol();
 
         this.authProviderFactory = authProviderFactory;
         this.extRegistry = extRegistry;
+        this.shFactory = shFactory;
+        if (shFactory != null) {
+            shFactory.init(NodeType.Client, conf);
+        }
 
         StringBuilder nameBuilder = new StringBuilder();
         nameBuilder.append(addr.getHostName().replace('.', '_').replace('-', '_'))
@@ -227,6 +268,7 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
         writeLacTimeoutOpLogger = statsLogger.getOpStatsLogger(BookKeeperClientStats.CHANNEL_TIMEOUT_WRITE_LAC);
         readLacTimeoutOpLogger = statsLogger.getOpStatsLogger(BookKeeperClientStats.CHANNEL_TIMEOUT_READ_LAC);
         getBookieInfoTimeoutOpLogger = statsLogger.getOpStatsLogger(BookKeeperClientStats.TIMEOUT_GET_BOOKIE_INFO);
+        startTLSOpLogger = statsLogger.getOpStatsLogger(BookKeeperClientStats.CHANNEL_START_TLS_OP);
 
         this.pcbcPool = pcbcPool;
 
@@ -244,7 +286,25 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
 
             @Override
             public Collection<Object> getProtocolPrincipals() {
-                return Collections.emptyList();
+                Channel c = channel;
+                if (c == null) {
+                    return Collections.emptyList();
+                }
+                SslHandler ssl = c.pipeline().get(SslHandler.class);
+                if (ssl == null) {
+                    return Collections.emptyList();
+                }
+                try {
+                    Certificate[] certificates = ssl.engine().getSession().getPeerCertificates();
+                    if (certificates == null) {
+                        return Collections.emptyList();
+                    }
+                    List<Object> result = new ArrayList<>();
+                    result.addAll(Arrays.asList(certificates));
+                    return result;
+                } catch (SSLPeerUnverifiedException err) {
+                     return Collections.emptyList();
+                }
             }
 
             @Override
@@ -267,6 +327,16 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
                 return authorizedId;
             }
 
+            @Override
+            public boolean isSecure() {
+               Channel c = channel;
+               if (c == null) {
+                    return false;
+               } else {
+                    return c.pipeline().get(SslHandler.class) != null;
+               }
+            }
+
         };
     }
 
@@ -351,63 +421,15 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
         }
 
         ChannelFuture future = bootstrap.connect(bookieAddr);
-        future.addListener(new ChannelFutureListener() {
-            @Override
-            public void operationComplete(ChannelFuture future) throws Exception {
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("Channel connected ({}) {}", future.isSuccess(), future.channel());
-                }
-                int rc;
-                Queue<GenericCallback<PerChannelBookieClient>> oldPendingOps;
-
-                synchronized (PerChannelBookieClient.this) {
-                    if (future.isSuccess() && state == ConnectionState.CONNECTING) {
-                        LOG.info("Successfully connected to bookie: {}", future.channel());
-                        rc = BKException.Code.OK;
-                        channel = future.channel();
-                        state = ConnectionState.CONNECTED;
-                    } else if (future.isSuccess() && (state == ConnectionState.CLOSED
-                                                      || state == ConnectionState.DISCONNECTED)) {
-                        LOG.warn("Closed before connection completed, clean up: {}, current state {}",
-                                future.channel(), state);
-                        closeChannel(future.channel());
-                        rc = BKException.Code.BookieHandleNotAvailableException;
-                        channel = null;
-                    } else if (future.isSuccess() && state == ConnectionState.CONNECTED) {
-                        if (LOG.isDebugEnabled()) {
-                            LOG.debug("Already connected with another channel({}), so close the new channel({})",
-                                    channel, future.channel());
-                        }
-                        closeChannel(future.channel());
-                        return; // pendingOps should have been completed when other channel connected
-                    } else {
-                        LOG.error("Could not connect to bookie: {}/{}, current state {} : ",
-                                new Object[] { future.channel(), addr, state, future.cause() });
-                        rc = BKException.Code.BookieHandleNotAvailableException;
-                        closeChannel(future.channel());
-                        channel = null;
-                        if (state != ConnectionState.CLOSED) {
-                            state = ConnectionState.DISCONNECTED;
-                        }
-                    }
-
-                    // trick to not do operations under the lock, take the list
-                    // of pending ops and assign it to a new variable, while
-                    // emptying the pending ops by just assigning it to a new
-                    // list
-                    oldPendingOps = pendingOps;
-                    pendingOps = new ArrayDeque<GenericCallback<PerChannelBookieClient>>();
-                }
-
-                for (GenericCallback<PerChannelBookieClient> pendingOp : oldPendingOps) {
-                    completeOperation(pendingOp, rc);
-                }
-            }
-        });
-
+        future.addListener(new ConnectionFutureListener());
         return future;
     }
 
+    void cleanDisconnectAndClose() {
+        disconnect();
+        close();
+    }
+
     void connectIfNeededAndDoOp(GenericCallback<PerChannelBookieClient> op) {
         boolean completeOpNow = false;
         int opRc = BKException.Code.OK;
@@ -431,9 +453,9 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
                     // connection attempt either fails or succeeds
                     pendingOps.add(op);
 
-                    if (state == ConnectionState.CONNECTING) {
-                        // just return as connection request has already send
-                        // and waiting for the response.
+                    if (state == ConnectionState.CONNECTING
+                        || state == ConnectionState.START_TLS) {
+                        // the connection request has already been sent and it is waiting for the response.
                         return;
                     }
                     // switch state to connecting and do connection attempt
@@ -958,6 +980,10 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
         return c.close();
     }
 
+    void errorStartTLS(int rc) {
+        failTLS(rc);
+    }
+
     void errorOutReadKey(final CompletionKey key) {
         errorOutReadKey(key, BKException.Code.BookieHandleNotAvailableException);
     }
@@ -1139,6 +1165,9 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
                 case GET_BOOKIE_INFO:
                     errorOutGetBookieInfoKey(key, rc);
                     break;
+                case START_TLS:
+                    errorStartTLS(rc);
+                    break;
                 default:
                     break;
             }
@@ -1333,8 +1362,8 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
         if (null == completionValue) {
             // Unexpected response, so log it. The txnId should have been present.
             if (LOG.isDebugEnabled()) {
-                LOG.debug("Unexpected response received from bookie : " + addr + " for type : " + header.             getOperation() +
-                        " and txnId : " + header.getTxnId());
+                LOG.debug("Unexpected response received from bookie : " + addr + " for type : "
+                        + header.getOperation() + " and txnId : " + header.getTxnId());
             }
         } else {
             long orderingKey = completionValue.ledgerId;
@@ -1396,6 +1425,11 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
                             handleGetBookieInfoResponse(getBookieInfoResponse.getFreeDiskSpace(), getBookieInfoResponse.getTotalDiskCapacity(), status, completionValue);
                             break;
                         }
+                        case START_TLS: {
+                            StatusCode status = response.getStatus();
+                            handleStartTLSResponse(status, completionValue);
+                            break;
+                        }
                         default:
                             LOG.error("Unexpected response, type:{} received from bookie:{}, ignoring",
                                       type, addr);
@@ -1413,6 +1447,98 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
         }
     }
 
+    void handleStartTLSResponse(StatusCode status, CompletionValue completionValue) {
+        StartTLSCompletion tlsCompletion = (StartTLSCompletion) completionValue;
+
+        // convert to BKException code because thats what the upper
+        // layers expect. This is UGLY, there should just be one set of
+        // error codes.
+        Integer rcToRet = statusCodeToExceptionCode(status);
+        if (null == rcToRet) {
+            LOG.error("START_TLS failed on bookie:{}", addr);
+            rcToRet = BKException.Code.SecurityException;
+        } else {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Received START_TLS response from {} rc: {}", addr, rcToRet);
+            }
+        }
+
+        // Cancel START_TLS request timeout
+        tlsCompletion.cb.startTLSComplete(rcToRet, tlsCompletion.ctx);
+
+        if (state != ConnectionState.START_TLS) {
+            LOG.error("Connection state changed before TLS response received");
+            failTLS(BKException.Code.BookieHandleNotAvailableException);
+        } else if (status != StatusCode.EOK) {
+            LOG.error("Client received error {} during TLS negotiation", status);
+            failTLS(BKException.Code.SecurityException);
+        } else {
+            // create TLS handler
+            PerChannelBookieClient parentObj = PerChannelBookieClient.this;
+            SslHandler handler = parentObj.shFactory.newTLSHandler();
+            channel.pipeline().addFirst(parentObj.shFactory.getHandlerName(), handler);
+            handler.handshakeFuture().addListener(new GenericFutureListener<Future<Channel>>() {
+                @Override
+                public void operationComplete(Future<Channel> future) throws Exception {
+                    int rc;
+                    Queue<GenericCallback<PerChannelBookieClient>> oldPendingOps;
+
+                    synchronized (PerChannelBookieClient.this) {
+                        if (future.isSuccess() && state == ConnectionState.CONNECTING) {
+                            LOG.error("Connection state changed before TLS handshake completed {}/{}", addr, state);
+                            rc = BKException.Code.BookieHandleNotAvailableException;
+                            closeChannel(future.get());
+                            channel = null;
+                            if (state != ConnectionState.CLOSED) {
+                                state = ConnectionState.DISCONNECTED;
+                            }
+                        } else if (future.isSuccess() && state == ConnectionState.START_TLS) {
+                            rc = BKException.Code.OK;
+                            LOG.info("Successfully connected to bookie using TLS: " + addr);
+
+                            state = ConnectionState.CONNECTED;
+                            AuthHandler.ClientSideHandler authHandler = future.get().pipeline()
+                                    .get(AuthHandler.ClientSideHandler.class);
+                            authHandler.authProvider.onProtocolUpgrade();
+                        } else if (future.isSuccess()
+                                && (state == ConnectionState.CLOSED || state == ConnectionState.DISCONNECTED)) {
+                            LOG.warn("Closed before TLS handshake completed, clean up: {}, current state {}",
+                                    future.get(), state);
+                            closeChannel(future.get());
+                            rc = BKException.Code.BookieHandleNotAvailableException;
+                            channel = null;
+                        } else if (future.isSuccess() && state == ConnectionState.CONNECTED) {
+                            LOG.debug("Already connected with another channel({}), so close the new channel({})",
+                                    channel, future.get());
+                            closeChannel(future.get());
+                            return; // pendingOps should have been completed when other channel connected
+                        } else {
+                            LOG.error("TLS handshake failed with bookie: {}/{}, current state {} : ",
+                                    new Object[] { future.get(), addr, state, future.cause() });
+                            rc = BKException.Code.SecurityException;
+                            closeChannel(future.get());
+                            channel = null;
+                            if (state != ConnectionState.CLOSED) {
+                                state = ConnectionState.DISCONNECTED;
+                            }
+                        }
+
+                        // trick to not do operations under the lock, take the list
+                        // of pending ops and assign it to a new variable, while
+                        // emptying the pending ops by just assigning it to a new
+                        // list
+                        oldPendingOps = pendingOps;
+                        pendingOps = new ArrayDeque<>();
+                    }
+
+                    for (GenericCallback<PerChannelBookieClient> pendingOp : oldPendingOps) {
+                        pendingOp.operationComplete(rc, PerChannelBookieClient.this);
+                    }
+                }
+            });
+        }
+    }
+
     void handleWriteLacResponse(long ledgerId, StatusCode status, CompletionValue completionValue) {
         // The completion value should always be an instance of an WriteLacCompletion object when we reach here.
         WriteLacCompletion plc = (WriteLacCompletion)completionValue;
@@ -1657,6 +1783,42 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
         }
     }
 
+    static class StartTLSCompletion extends CompletionValue {
+        final StartTLSCallback cb;
+
+        public StartTLSCompletion(final PerChannelBookieClient pcbc, StartTLSCallback cb, Object ctx) {
+            this(pcbc, null, cb, ctx, null);
+        }
+
+        public StartTLSCompletion(final PerChannelBookieClient pcbc, final OpStatsLogger startTLSOpLogger,
+                                  final StartTLSCallback originalCallback, final Object originalCtx, final Timeout timeout) {
+            super(originalCtx, -1, -1, timeout);
+            final long startTime = MathUtils.nowInNano();
+            this.cb = new StartTLSCallback() {
+                @Override
+                public void startTLSComplete(int rc, Object ctx) {
+                    cancelTimeout();
+                    if (startTLSOpLogger != null) {
+                        long latency = MathUtils.elapsedNanos(startTime);
+                        if (rc != BKException.Code.OK) {
+                            startTLSOpLogger.registerFailedEvent(latency, TimeUnit.NANOSECONDS);
+                        } else {
+                            startTLSOpLogger.registerSuccessfulEvent(latency, TimeUnit.NANOSECONDS);
+                        }
+                    }
+
+                    if (rc != BKException.Code.OK && !expectedBkOperationErrors.contains(rc)) {
+                        pcbc.recordError();
+                    }
+
+                    if (originalCallback != null) {
+                        originalCallback.startTLSComplete(rc, originalCtx);
+                    }
+                }
+            };
+        }
+    }
+
     // visible for testing
     static class GetBookieInfoCompletion extends CompletionValue {
         final GetBookieInfoCallback cb;
@@ -1803,11 +1965,16 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
             } else if (OperationType.READ_LAC == operationType) {
                 errorOutReadLacKey(this, BKException.Code.TimeoutException);
                 readLacTimeoutOpLogger.registerSuccessfulEvent(elapsedTime(), TimeUnit.NANOSECONDS);
+            } else if (OperationType.GET_BOOKIE_INFO == operationType) {
+                errorOutGetBookieInfoKey(this, BKException.Code.TimeoutException);
+                getBookieInfoTimeoutOpLogger.registerSuccessfulEvent(elapsedTime(), TimeUnit.NANOSECONDS);
+            } else if (OperationType.START_TLS == operationType) {
+                errorStartTLS(BKException.Code.TimeoutException);
             } else {
                 errorOutGetBookieInfoKey(this, BKException.Code.TimeoutException);
                 getBookieInfoTimeoutOpLogger.registerSuccessfulEvent(elapsedTime(), TimeUnit.NANOSECONDS);
             }
-	}
+        }
     }
 
 
@@ -1884,4 +2051,106 @@ public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
             return String.format("%d:%d %s", ledgerId, entryId, operationType);
         }
     }
+    
+    public class ConnectionFutureListener implements ChannelFutureListener {
+        @Override
+        public void operationComplete(ChannelFuture future) throws Exception {
+            LOG.debug("Channel connected ({}) {}", future.isSuccess(), future.channel());
+            int rc;
+            Queue<GenericCallback<PerChannelBookieClient>> oldPendingOps;
+
+            synchronized (PerChannelBookieClient.this) {
+                if (future.isSuccess() && state == ConnectionState.CONNECTING) {
+                    LOG.info("Successfully connected to bookie: {}", future.channel());
+                    rc = BKException.Code.OK;
+                    channel = future.channel();
+                    if (shFactory != null) {
+                        initiateTLS();
+                        return;
+                    } else {
+                        LOG.info("Successfully connected to bookie: " + addr);
+                        state = ConnectionState.CONNECTED;
+                    }
+                } else if (future.isSuccess() && state == ConnectionState.START_TLS) {
+                    rc = BKException.Code.OK;
+                    LOG.info("Successfully connected to bookie using TLS: " + addr);
+
+                    state = ConnectionState.CONNECTED;
+                    AuthHandler.ClientSideHandler authHandler = future.channel().pipeline()
+                            .get(AuthHandler.ClientSideHandler.class);
+                    authHandler.authProvider.onProtocolUpgrade();
+                } else if (future.isSuccess() && (state == ConnectionState.CLOSED
+                    || state == ConnectionState.DISCONNECTED)) {
+                    LOG.warn("Closed before connection completed, clean up: {}, current state {}",
+                            future.channel(), state);
+                    closeChannel(future.channel());
+                    rc = BKException.Code.BookieHandleNotAvailableException;
+                    channel = null;
+                } else if (future.isSuccess() && state == ConnectionState.CONNECTED) {
+                    LOG.debug("Already connected with another channel({}), so close the new channel({})",
+                            channel, future.channel());
+                    closeChannel(future.channel());
+                    return; // pendingOps should have been completed when other channel connected
+                } else {
+                    LOG.error("Could not connect to bookie: {}/{}, current state {} : ",
+                            new Object[] { future.channel(), addr, state, future.cause() });
+                    rc = BKException.Code.BookieHandleNotAvailableException;
+                    closeChannel(future.channel());
+                    channel = null;
+                    if (state != ConnectionState.CLOSED) {
+                        state = ConnectionState.DISCONNECTED;
+                    }
+                }
+
+                // trick to not do operations under the lock, take the list
+                // of pending ops and assign it to a new variable, while
+                // emptying the pending ops by just assigning it to a new
+                // list
+                oldPendingOps = pendingOps;
+                pendingOps = new ArrayDeque<>();
+            }
+
+            for (GenericCallback<PerChannelBookieClient> pendingOp : oldPendingOps) {
+                pendingOp.operationComplete(rc, PerChannelBookieClient.this);
+            }
+        }
+    }
+
+    private void initiateTLS() {
+        LOG.info("Initializing TLS to {}",channel);
+        assert state == ConnectionState.CONNECTING;
+        final long txnId = getTxnId();
+        final CompletionKey completionKey = new V3CompletionKey(txnId, OperationType.START_TLS);
+        completionObjects.put(completionKey, new StartTLSCompletion(this, startTLSOpLogger, null, null,
+                scheduleTimeout(completionKey, startTLSTimeout)));
+        BookkeeperProtocol.Request.Builder h = BookkeeperProtocol.Request.newBuilder();
+        BKPacketHeader.Builder headerBuilder = BKPacketHeader.newBuilder()
+                .setVersion(ProtocolVersion.VERSION_THREE)
+                .setOperation(OperationType.START_TLS)
+                .setTxnId(txnId);
+        h.setHeader(headerBuilder.build());
+        h.setStartTLSRequest(BookkeeperProtocol.StartTLSRequest.newBuilder().build());
+        state = ConnectionState.START_TLS;
+        channel.writeAndFlush(h.build()).addListener(new ChannelFutureListener() {
+            @Override
+            public void operationComplete(ChannelFuture future) throws Exception {
+                if (!future.isSuccess()) {
+                    LOG.error("Failed to send START_TLS request");
+                    failTLS(BKException.Code.SecurityException);
+                }
+            }
+        });
+    }
+    private void failTLS(int rc) {
+        LOG.error("TLS failure on: {}, rc: {}", channel, rc);
+        Queue<GenericCallback<PerChannelBookieClient>> oldPendingOps;
+        synchronized(this) {
+            disconnect();
+            oldPendingOps = pendingOps;
+            pendingOps = new ArrayDeque<>();
+        }
+        for (GenericCallback<PerChannelBookieClient> pendingOp : oldPendingOps) {
+            pendingOp.operationComplete(rc, null);
+        }
+    }
 }
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClientFactory.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClientFactory.java
index 69d559e..17abb56 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClientFactory.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClientFactory.java
@@ -21,6 +21,8 @@
 package org.apache.bookkeeper.proto;
 
 import org.apache.bookkeeper.net.BookieSocketAddress;
+import org.apache.bookkeeper.tls.SecurityException;
+import org.apache.bookkeeper.tls.SecurityHandlerFactory;
 
 /**
  * Factory to create {@link org.apache.bookkeeper.proto.PerChannelBookieClient}.
@@ -32,6 +34,8 @@ interface PerChannelBookieClientFactory {
      * <i>address</i>.
      *
      * @return the client connected to address.
+     * @throws SecurityException
      */
-    PerChannelBookieClient create(BookieSocketAddress address, PerChannelBookieClientPool pcbcPool);
+    PerChannelBookieClient create(BookieSocketAddress address,
+            PerChannelBookieClientPool pcbcPool, SecurityHandlerFactory shFactory) throws SecurityException;
 }
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/tls/SecurityException.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/tls/SecurityException.java
new file mode 100644
index 0000000..166513e
--- /dev/null
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/tls/SecurityException.java
@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bookkeeper.tls;
+
+public class SecurityException extends Exception {
+    public SecurityException() {}
+
+    public SecurityException(String message) {
+        super(message);
+    }
+
+    public SecurityException(Throwable cause) {
+        super(cause);
+    }
+
+    public SecurityException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/tls/SecurityHandlerFactory.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/tls/SecurityHandlerFactory.java
new file mode 100644
index 0000000..84a3a5e
--- /dev/null
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/tls/SecurityHandlerFactory.java
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bookkeeper.tls;
+
+import org.apache.bookkeeper.conf.AbstractConfiguration;
+
+import io.netty.handler.ssl.SslHandler;
+
+public interface SecurityHandlerFactory {
+    public enum NodeType {
+        Unknown,
+        Client,
+        Server,
+    }
+
+    public abstract String getHandlerName();
+
+    public abstract void init(NodeType type, AbstractConfiguration conf) throws SecurityException;
+    public SslHandler newTLSHandler();
+}
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/tls/SecurityProviderFactoryFactory.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/tls/SecurityProviderFactoryFactory.java
new file mode 100644
index 0000000..38376d8
--- /dev/null
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/tls/SecurityProviderFactoryFactory.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bookkeeper.tls;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class SecurityProviderFactoryFactory {
+    private final static Logger LOG = LoggerFactory.getLogger(SecurityProviderFactoryFactory.class);
+
+    public static SecurityHandlerFactory getSecurityProviderFactory(String securityHandler)
+            throws SecurityException {
+        if ((securityHandler == null) || (securityHandler.equals(""))) {
+            return null;
+        }
+
+        ClassLoader classLoader = SecurityProviderFactoryFactory.class.getClassLoader();
+        SecurityHandlerFactory shFactory = null;
+        try {
+            Class<?> shFactoryClass = classLoader.loadClass(securityHandler);
+            shFactory = (SecurityHandlerFactory) shFactoryClass.newInstance();
+            LOG.info("Loaded security handler for {}", securityHandler);
+        } catch (Exception e) {
+            LOG.error("Unable to load security handler for {}: ", securityHandler, e);
+            throw new SecurityException(e);
+        }
+        return shFactory;
+    }
+
+}
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/tls/TLSContextFactory.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/tls/TLSContextFactory.java
new file mode 100644
index 0000000..eda5aec
--- /dev/null
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/tls/TLSContextFactory.java
@@ -0,0 +1,293 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bookkeeper.tls;
+
+import org.apache.bookkeeper.conf.AbstractConfiguration;
+import org.apache.bookkeeper.conf.ClientConfiguration;
+import org.apache.bookkeeper.conf.ServerConfiguration;
+import org.apache.commons.io.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Strings;
+
+import io.netty.buffer.PooledByteBufAllocator;
+import io.netty.handler.ssl.ClientAuth;
+import io.netty.handler.ssl.OpenSsl;
+import io.netty.handler.ssl.SslContext;
+import io.netty.handler.ssl.SslContextBuilder;
+import io.netty.handler.ssl.SslHandler;
+import io.netty.handler.ssl.SslProvider;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.TrustManagerFactory;
+
+public class TLSContextFactory implements SecurityHandlerFactory {
+    private final static Logger LOG = LoggerFactory.getLogger(TLSContextFactory.class);
+    private final static String TLSCONTEXT_HANDLER_NAME = "tls";
+    private String[] protocols;
+    private String[] ciphers;
+    private SslContext sslContext;
+
+    private String getPasswordFromFile(String path) throws IOException {
+        FileInputStream pwdin = new FileInputStream(path);
+        byte[] pwd;
+        try {
+            File passwdFile = new File(path);
+            if (passwdFile.length() == 0) {
+                return "";
+            }
+            pwd = FileUtils.readFileToByteArray(passwdFile);
+        } finally {
+            pwdin.close();
+        }
+        return new String(pwd, "UTF-8");
+    }
+
+    private KeyStore loadKeyStore(String keyStoreType, String keyStoreLocation, String keyStorePassword)
+            throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
+        KeyStore ks = KeyStore.getInstance(keyStoreType);
+        FileInputStream ksin = new FileInputStream(keyStoreLocation);
+        try {
+            ks.load(ksin, keyStorePassword.trim().toCharArray());
+        } finally {
+            ksin.close();
+        }
+        return ks;
+    }
+
+    public String getHandlerName() {
+        return TLSCONTEXT_HANDLER_NAME;
+    }
+
+    private KeyManagerFactory initKeyManagerFactory(String keyStoreType, String keyStoreLocation,
+            String keyStorePasswordPath) throws SecurityException, KeyStoreException, NoSuchAlgorithmException,
+            CertificateException, IOException, UnrecoverableKeyException {
+        KeyManagerFactory kmf = null;
+
+        if (Strings.isNullOrEmpty(keyStoreLocation)) {
+            LOG.error("Key store location cannot be empty when Mutual Authentication is enabled!");
+            throw new SecurityException("Key store location cannot be empty when Mutual Authentication is enabled!");
+        }
+
+        String keyStorePassword = "";
+        if (!Strings.isNullOrEmpty(keyStorePasswordPath)) {
+            keyStorePassword = getPasswordFromFile(keyStorePasswordPath);
+        }
+
+        // Initialize key store
+        KeyStore ks = loadKeyStore(keyStoreType, keyStoreLocation, keyStorePassword);
+        kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+        kmf.init(ks, keyStorePassword.trim().toCharArray());
+
+        return kmf;
+    }
+
+    private TrustManagerFactory initTrustManagerFactory(String trustStoreType, String trustStoreLocation,
+            String trustStorePasswordPath)
+            throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, SecurityException {
+        TrustManagerFactory tmf;
+
+        if (Strings.isNullOrEmpty(trustStoreLocation)) {
+            LOG.error("Trust Store location cannot be empty!");
+            throw new SecurityException("Trust Store location cannot be empty!");
+        }
+
+        String trustStorePassword = "";
+        if (!Strings.isNullOrEmpty(trustStorePasswordPath)) {
+            trustStorePassword = getPasswordFromFile(trustStorePasswordPath);
+        }
+
+        // Initialize trust store
+        KeyStore ts = loadKeyStore(trustStoreType, trustStoreLocation, trustStorePassword);
+        tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+        tmf.init(ts);
+
+        return tmf;
+    }
+
+    private SslProvider getTLSProvider(String sslProvider) {
+        if (sslProvider.trim().equalsIgnoreCase("OpenSSL")) {
+            if (OpenSsl.isAvailable()) {
+                LOG.info("Security provider - OpenSSL");
+                return SslProvider.OPENSSL;
+            }
+
+            Throwable causeUnavailable = OpenSsl.unavailabilityCause();
+            LOG.warn("OpenSSL Unavailable: ", causeUnavailable);
+
+            LOG.info("Security provider - JDK");
+            return SslProvider.JDK;
+        }
+
+        LOG.info("Security provider - JDK");
+        return SslProvider.JDK;
+    }
+
+    private void createClientContext(AbstractConfiguration conf) throws SecurityException, KeyStoreException, NoSuchAlgorithmException,
+            CertificateException, IOException, UnrecoverableKeyException {
+        final SslContextBuilder sslContextBuilder;
+        final ClientConfiguration clientConf;
+        final SslProvider provider;
+        final boolean Authentication;
+
+        KeyManagerFactory kmf = null;
+        TrustManagerFactory tmf = null;
+
+        // get key-store and trust-store locations and passwords
+        if (!(conf instanceof ClientConfiguration)) {
+            throw new SecurityException("Client configruation not provided");
+        }
+
+        clientConf = (ClientConfiguration) conf;
+        provider = getTLSProvider(clientConf.getTLSProvider());
+        Authentication = clientConf.getTLSClientAuthentication();
+
+        tmf = initTrustManagerFactory(clientConf.getTLSTrustStoreType(), clientConf.getTLSTrustStore(),
+                clientConf.getTLSTrustStorePasswordPath());
+
+        if (Authentication) {
+            kmf = initKeyManagerFactory(clientConf.getTLSKeyStoreType(), clientConf.getTLSKeyStore(),
+                    clientConf.getTLSKeyStorePasswordPath());
+        }
+
+        // Build Ssl context
+        sslContextBuilder = SslContextBuilder.forClient()
+                                            .trustManager(tmf)
+                                            .ciphers(null)
+                                            .sessionCacheSize(0)
+                                            .sessionTimeout(0)
+                                            .sslProvider(provider)
+                                            .clientAuth(ClientAuth.REQUIRE);
+
+        /* if mutual authentication is enabled */
+        if (Authentication) {
+            sslContextBuilder.keyManager(kmf);
+        }
+
+        sslContext = sslContextBuilder.build();
+    }
+
+    private void createServerContext(AbstractConfiguration conf) throws SecurityException, KeyStoreException, NoSuchAlgorithmException,
+            CertificateException, IOException, UnrecoverableKeyException {
+        final SslContextBuilder sslContextBuilder;
+        final ServerConfiguration serverConf;
+        final SslProvider provider;
+        final boolean Authentication;
+
+        KeyManagerFactory kmf = null;
+        TrustManagerFactory tmf = null;
+
+        // get key-store and trust-store locations and passwords
+        if (!(conf instanceof ServerConfiguration)) {
+            throw new SecurityException("Server configruation not provided");
+        }
+
+        serverConf = (ServerConfiguration) conf;
+        provider = getTLSProvider(serverConf.getTLSProvider());
+        Authentication = serverConf.getTLSClientAuthentication();
+
+        kmf = initKeyManagerFactory(serverConf.getTLSKeyStoreType(), serverConf.getTLSKeyStore(),
+                serverConf.getTLSKeyStorePasswordPath());
+
+        if (Authentication) {
+            tmf = initTrustManagerFactory(serverConf.getTLSTrustStoreType(), serverConf.getTLSTrustStore(),
+                    serverConf.getTLSTrustStorePasswordPath());
+        }
+
+        // Build Ssl context
+        sslContextBuilder = SslContextBuilder.forServer(kmf)
+                                            .ciphers(null)
+                                            .sessionCacheSize(0)
+                                            .sessionTimeout(0)
+                                            .sslProvider(provider)
+                                            .startTls(true);
+
+        /* if mutual authentication is enabled */
+        if (Authentication) {
+            sslContextBuilder.trustManager(tmf)
+                            .clientAuth(ClientAuth.REQUIRE);
+        }
+
+        sslContext = sslContextBuilder.build();
+    }
+
+    @Override
+    public synchronized void init(NodeType type, AbstractConfiguration conf) throws SecurityException {
+        final String enabledProtocols;
+        final String enabledCiphers;
+
+        enabledCiphers = conf.getTLSEnabledCipherSuites();
+        enabledProtocols = conf.getTLSEnabledProtocols();
+
+        try {
+            switch (type) {
+            case Client:
+                createClientContext(conf);
+                break;
+            case Server:
+                createServerContext(conf);
+                break;
+            default:
+                throw new SecurityException(new IllegalArgumentException("Invalid NodeType"));
+            }
+
+            if (enabledProtocols != null && !enabledProtocols.isEmpty()) {
+                protocols = enabledProtocols.split(",");
+            }
+
+            if (enabledCiphers != null && !enabledCiphers.isEmpty()) {
+                ciphers = enabledCiphers.split(",");
+            }
+        } catch (KeyStoreException e) {
+            throw new RuntimeException("Standard keystore type missing", e);
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException("Standard algorithm missing", e);
+        } catch (CertificateException e) {
+            throw new SecurityException("Unable to load keystore", e);
+        } catch (IOException e) {
+            throw new SecurityException("Error initializing TLSContext", e);
+        } catch (UnrecoverableKeyException e) {
+            throw new SecurityException("Unable to load key manager, possibly wrong password given", e);
+        }
+    }
+
+    @Override
+    public SslHandler newTLSHandler() {
+        SslHandler sslHandler = sslContext.newHandler(PooledByteBufAllocator.DEFAULT);
+
+        if (protocols != null && protocols.length != 0) {
+            sslHandler.engine().setEnabledProtocols(protocols);
+        }
+
+        if (ciphers != null && ciphers.length != 0) {
+            sslHandler.engine().setEnabledCipherSuites(ciphers);
+        }
+
+        return sslHandler;
+    }
+}
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/LocalBookKeeper.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/LocalBookKeeper.java
index b5f8d72..77ce25f 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/LocalBookKeeper.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/LocalBookKeeper.java
@@ -36,6 +36,9 @@ import org.apache.bookkeeper.conf.ServerConfiguration;
 import org.apache.bookkeeper.proto.BookieServer;
 import org.apache.bookkeeper.replication.ReplicationException.CompatibilityException;
 import org.apache.bookkeeper.replication.ReplicationException.UnavailableException;
+import org.apache.bookkeeper.stats.StatsLogger;
+import org.apache.bookkeeper.stats.StatsProvider;
+import org.apache.bookkeeper.tls.SecurityException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.zookeeper.CreateMode;
@@ -129,7 +132,7 @@ public class LocalBookKeeper {
 
     private List<File> runBookies(ServerConfiguration baseConf, String dirSuffix)
             throws IOException, KeeperException, InterruptedException, BookieException,
-            UnavailableException, CompatibilityException {
+            UnavailableException, CompatibilityException, SecurityException {
         List<File> tempDirs = new ArrayList<File>();
         try {
             runBookies(baseConf, tempDirs, dirSuffix);
@@ -157,8 +160,8 @@ public class LocalBookKeeper {
 
     @SuppressWarnings("deprecation")
     private void runBookies(ServerConfiguration baseConf, List<File> tempDirs, String dirSuffix)
-            throws IOException, KeeperException, InterruptedException, BookieException,
-            UnavailableException, CompatibilityException {
+            throws IOException, KeeperException, InterruptedException, BookieException, UnavailableException,
+            CompatibilityException, SecurityException {
         LOG.info("Starting Bookie(s)");
         // Create Bookie Servers (B1, B2, B3)
 
@@ -311,7 +314,7 @@ public class LocalBookKeeper {
         }
     }
 
-    public static void main(String[] args) throws Exception {
+    public static void main(String[] args) throws Exception, SecurityException {
         if(args.length < 1) {
             usage();
             System.exit(-1);
diff --git a/bookkeeper-server/src/main/proto/BookkeeperProtocol.proto b/bookkeeper-server/src/main/proto/BookkeeperProtocol.proto
index fcd02aa..309987c 100644
--- a/bookkeeper-server/src/main/proto/BookkeeperProtocol.proto
+++ b/bookkeeper-server/src/main/proto/BookkeeperProtocol.proto
@@ -60,6 +60,7 @@ enum OperationType {
     WRITE_LAC = 6;
     READ_LAC = 7;
     GET_BOOKIE_INFO = 8;
+    START_TLS = 9;
 }
 
 /**
@@ -80,6 +81,7 @@ message Request {
     optional WriteLacRequest writeLacRequest = 103;
     optional ReadLacRequest readLacRequest = 104;
     optional GetBookieInfoRequest getBookieInfoRequest = 105;
+    optional StartTLSRequest startTLSRequest = 106;
 }
 
 message ReadRequest {
@@ -110,6 +112,9 @@ message AddRequest {
     required bytes body = 4;
 }
 
+message StartTLSRequest {
+}
+
 message WriteLacRequest {
     required int64 ledgerId = 1;
     required int64 lac = 2;
@@ -143,6 +148,7 @@ message Response {
     optional WriteLacResponse writeLacResponse = 103;
     optional ReadLacResponse readLacResponse = 104;
     optional GetBookieInfoResponse getBookieInfoResponse = 105;
+    optional StartTLSResponse startTLSResponse = 106;
 }
 
 message ReadResponse {
@@ -183,3 +189,6 @@ message GetBookieInfoResponse {
     optional int64 totalDiskCapacity = 2;
     optional int64 freeDiskSpace = 3;
 }
+
+message StartTLSResponse {
+}
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/auth/TestAuth.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/auth/TestAuth.java
index 62a07da..2d112c6 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/auth/TestAuth.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/auth/TestAuth.java
@@ -488,7 +488,6 @@ public class TestAuth extends BookKeeperClusterTestCase {
         @Override
         public BookieAuthProvider newProvider(BookieConnectionPeer connection, AuthCallbacks.GenericCallback<Void> completeCb) {
             return new BookieAuthProvider() {
-
                 {
                     completeCb.operationComplete(BKException.Code.OK, null);
                     initCountersOnConnections.incrementAndGet();
@@ -496,7 +495,6 @@ public class TestAuth extends BookKeeperClusterTestCase {
 
                 @Override
                 public void process(AuthToken m, AuthCallbacks.GenericCallback<AuthToken> cb) {
-
                 }
 
                 @Override
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/BookieInitializationTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/BookieInitializationTest.java
index a410e37..455c908 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/BookieInitializationTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/BookieInitializationTest.java
@@ -45,6 +45,7 @@ import org.apache.bookkeeper.stats.NullStatsLogger;
 import org.apache.bookkeeper.stats.StatsLogger;
 import org.apache.bookkeeper.test.BookKeeperClusterTestCase;
 import org.apache.bookkeeper.test.PortManager;
+import org.apache.bookkeeper.tls.SecurityException;
 import org.apache.bookkeeper.util.DiskChecker;
 import org.apache.bookkeeper.zookeeper.ZooKeeperClient;
 import org.apache.zookeeper.KeeperException;
@@ -456,7 +457,7 @@ public class BookieInitializationTest extends BookKeeperClusterTestCase {
         ServerConfiguration conf;
 
         public MockBookieServer(ServerConfiguration conf) throws IOException, KeeperException, InterruptedException,
-                BookieException, UnavailableException, CompatibilityException {
+                BookieException, UnavailableException, CompatibilityException, SecurityException {
             super(conf);
             this.conf = conf;
         }
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuthAutoRecoveryTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuthAutoRecoveryTest.java
index 75ea9c8..654a0aa 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuthAutoRecoveryTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuthAutoRecoveryTest.java
@@ -66,10 +66,9 @@ public class AuthAutoRecoveryTest extends BookKeeperClusterTestCase {
             final AuthCallbacks.GenericCallback<Void> completeCb) {
             return new ClientAuthProvider() {
                 public void init(AuthCallbacks.GenericCallback<AuthToken> cb) {
-
                     completeCb.operationComplete(BKException.Code.OK, null);
                 }
-
+                
                 public void process(AuthToken m, AuthCallbacks.GenericCallback<AuthToken> cb) {
                 }
             };
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/tls/TestTLS.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/tls/TestTLS.java
new file mode 100644
index 0000000..61e78b5
--- /dev/null
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/tls/TestTLS.java
@@ -0,0 +1,501 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bookkeeper.tls;
+
+import org.junit.*;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.Enumeration;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.apache.bookkeeper.conf.ClientConfiguration;
+import org.apache.bookkeeper.conf.ServerConfiguration;
+import org.apache.bookkeeper.net.BookieSocketAddress;
+import org.apache.bookkeeper.test.BookKeeperClusterTestCase;
+import org.apache.bookkeeper.tls.SecurityException;
+import org.apache.bookkeeper.tls.TLSContextFactory;
+import org.apache.bookkeeper.client.LedgerHandle;
+import org.apache.bookkeeper.client.LedgerEntry;
+import org.apache.bookkeeper.client.BookKeeper;
+import org.apache.bookkeeper.client.BKException;
+import org.apache.bookkeeper.client.BookKeeper.DigestType;
+
+import java.io.IOException;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.bookkeeper.auth.AuthCallbacks;
+import org.apache.bookkeeper.auth.AuthToken;
+import org.apache.bookkeeper.auth.BookieAuthProvider;
+import org.apache.bookkeeper.auth.ClientAuthProvider;
+import org.apache.bookkeeper.client.BookKeeperAdmin;
+import org.apache.bookkeeper.client.LedgerMetadata;
+import org.apache.bookkeeper.proto.BookieConnectionPeer;
+import org.apache.bookkeeper.proto.ClientConnectionPeer;
+import org.apache.bookkeeper.proto.TestPerChannelBookieClient;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Tests with TLS enabled.
+ */
+public class TestTLS extends BookKeeperClusterTestCase {
+
+    static Logger LOG = LoggerFactory.getLogger(TestPerChannelBookieClient.class);
+
+    private static boolean secureClientSideChannel = false;
+    private static Collection<Object> secureClientSideChannelPrincipals = null;
+
+    private static boolean secureBookieSideChannel = false;
+    private static Collection<Object> secureBookieSideChannelPrincipals = null;
+
+
+    public TestTLS() {
+        super(3);
+    }
+
+    @Before
+    @Override
+    public void setUp() throws Exception {
+        /* client configuration */
+        baseClientConf.setTLSProviderFactoryClass(TLSContextFactory.class.getName());
+        baseClientConf.setTLSClientAuthentication(true);
+        baseClientConf.setTLSKeyStoreType("JKS");
+        baseClientConf.setTLSKeyStore(this.getClass().getClassLoader().getResource("client.jks").getPath());
+        baseClientConf.setTLSKeyStorePasswordPath(
+                this.getClass().getClassLoader().getResource("keyStoreClientPassword.txt").getPath());
+        baseClientConf.setTLSTrustStoreType("JKS");
+        baseClientConf.setTLSTrustStore(this.getClass().getClassLoader().getResource("cacerts").getPath());
+        baseClientConf.setTLSTrustStorePasswordPath(
+                this.getClass().getClassLoader().getResource("trustStorePassword.txt").getPath());
+
+        /* server configuration */
+        baseConf.setTLSProviderFactoryClass(TLSContextFactory.class.getName());
+        baseConf.setTLSClientAuthentication(true);
+        baseConf.setTLSKeyStoreType("JKS");
+        baseConf.setTLSKeyStore(this.getClass().getClassLoader().getResource("server.jks").getPath());
+        baseConf.setTLSKeyStorePasswordPath(
+                this.getClass().getClassLoader().getResource("keyStoreServerPassword.txt").getPath());
+        baseConf.setTLSTrustStoreType("JKS");
+        baseConf.setTLSTrustStore(this.getClass().getClassLoader().getResource("cacerts").getPath());
+        baseConf.setTLSTrustStorePasswordPath(
+                this.getClass().getClassLoader().getResource("trustStorePassword.txt").getPath());
+
+        super.setUp();
+    }
+
+    @After
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Verify that a server will not start if tls is enabled but no cert is specified
+     */
+    @Test(timeout = 60000)
+    public void testStartTLSServerNoKeyStore() throws Exception {
+        ServerConfiguration bookieConf = newServerConfiguration().setTLSKeyStore(null);
+
+        try {
+            bs.add(startBookie(bookieConf));
+            fail("Shouldn't have been able to start");
+        } catch (SecurityException se) {
+            assertTrue(true);
+        }
+    }
+
+    /**
+     * Verify that a server will not start if tls is enabled but the cert password is incorrect
+     */
+    @Test(timeout = 60000)
+    public void testStartTLSServerBadPassword() throws Exception {
+        ServerConfiguration bookieConf = newServerConfiguration().setTLSKeyStorePasswordPath("badpassword");
+        try {
+            bs.add(startBookie(bookieConf));
+            fail("Shouldn't have been able to start");
+        } catch (SecurityException se) {
+            assertTrue(true);
+        }
+    }
+
+    private LedgerMetadata testClient(ClientConfiguration conf, int clusterSize) throws Exception {
+        try (BookKeeper client = new BookKeeper(conf);) {
+            byte[] passwd = "testPassword".getBytes();
+            int numEntries = 100;
+            long lid;
+            byte[] testEntry = "testEntry".getBytes();
+            try (LedgerHandle lh = client.createLedger(clusterSize, clusterSize, DigestType.CRC32, passwd);) {
+                for (int i = 0; i <= numEntries; i++) {
+                    lh.addEntry(testEntry);
+                }
+                lid = lh.getId();
+            }
+            try (LedgerHandle lh = client.openLedger(lid, DigestType.CRC32, passwd);) {
+                Enumeration<LedgerEntry> entries = lh.readEntries(0, numEntries);
+                while (entries.hasMoreElements()) {
+                    LedgerEntry e = entries.nextElement();
+                    assertTrue("Entry contents incorrect", Arrays.equals(e.getEntry(), testEntry));
+                }
+                BookKeeperAdmin admin = new BookKeeperAdmin(client);
+                return admin.getLedgerMetadata(lh);
+            }
+        }
+    }
+
+    /**
+     * Verify the basic use of TLS. TLS client, TLS servers
+     */
+    @Test(timeout = 60000)
+    public void testConnectToTLSClusterTLSClient() throws Exception {
+        ClientConfiguration clientConf = new ClientConfiguration(baseClientConf);
+        testClient(clientConf, numBookies);
+    }
+
+
+    /**
+     * Multiple clients, some with TLS, and some without TLS
+     */
+    @Test(timeout = 60000)
+    public void testConnectToTLSClusterMixedClient() throws Exception {
+        ClientConfiguration confWithTLS = new ClientConfiguration(baseClientConf);
+        testClient(confWithTLS, numBookies);
+
+        ClientConfiguration confNoTLS = new ClientConfiguration(baseClientConf);
+        confNoTLS.setTLSProviderFactoryClass(null);
+        testClient(confNoTLS, numBookies);
+    }
+
+    /**
+     * Verify the basic use of TLS. TLS client, TLS servers. No Mutual Authentication.
+     */
+    @Test(timeout = 60000)
+    public void testConnectToTLSClusterTLSClientWithTLSNoAuthentication() throws Exception {
+        ServerConfiguration serverConf = new ServerConfiguration(baseConf);
+        serverConf.setTLSClientAuthentication(false);
+        restartBookies(serverConf);
+
+        ClientConfiguration conf = new ClientConfiguration(baseClientConf);
+        testClient(conf, numBookies);
+    }
+
+    /**
+     * Verify the basic use of TLS. TLS client, TLS servers with mutual Auth.
+     */
+    @Test(timeout = 60000)
+    public void testConnectToTLSClusterTLSClientWithAuthentication() throws Exception {
+        ClientConfiguration conf = new ClientConfiguration(baseClientConf);
+        try {
+            testClient(conf, numBookies);
+        } catch (BKException.BKNotEnoughBookiesException nnbe) {
+            fail("Client should be able to connect to bookie");
+        }
+    }
+
+    /**
+     * Verify that a client without tls enabled can connect to a cluster with TLS
+     */
+    @Test(timeout = 60000)
+    public void testConnectToTLSClusterNonTLSClient() throws Exception {
+        ClientConfiguration conf = new ClientConfiguration(baseClientConf);
+        conf.setTLSProviderFactoryClass(null);
+        try {
+            testClient(conf, numBookies);
+        } catch (BKException.BKNotEnoughBookiesException nnbe) {
+            fail("non tls client should be able to connect to tls enabled bookies");
+        }
+    }
+
+    /**
+     * Verify that a client will fail to connect to a server if it has asked for TLS, but it is not available.
+     */
+    @Test(timeout = 60000)
+    public void testClientWantsTLSNoServersHaveIt() throws Exception {
+        ServerConfiguration serverConf = new ServerConfiguration(baseConf);
+        serverConf.setTLSProviderFactoryClass(null);
+        restartBookies(serverConf);
+
+        ClientConfiguration clientConf = new ClientConfiguration(baseClientConf);
+        try {
+            testClient(clientConf, numBookies);
+            fail("Shouldn't be able to connect");
+        } catch (BKException.BKNotEnoughBookiesException nnbe) {
+            // correct response
+        }
+    }
+
+    /**
+     * Verify that a client will be able to connect to a bookie cluster if it has asked for TLS, and there are enough
+     * bookies with TLS enabled in the cluster, although few bookies do not have TLS enabled.
+     */
+    @Test(timeout = 60000)
+    public void testTLSClientButOnlyFewTLSServers() throws Exception {
+        // disable TLS on initial set of bookies
+        ServerConfiguration serverConf = new ServerConfiguration(baseConf);
+        serverConf.setTLSProviderFactoryClass(null);
+        restartBookies(serverConf);
+
+        // add two bookies which support TLS
+        baseConf.setTLSProviderFactoryClass(TLSContextFactory.class.getName());
+
+        Set<Integer> tlsBookiePorts = new HashSet<>();
+        tlsBookiePorts.add(startNewBookie());
+        tlsBookiePorts.add(startNewBookie());
+
+        ClientConfiguration clientConf = new ClientConfiguration(baseClientConf);
+        LedgerMetadata metadata = testClient(clientConf, 2);
+        assertTrue(metadata.getEnsembles().size() > 0);
+        Collection<ArrayList<BookieSocketAddress>> ensembles = metadata.getEnsembles().values();
+        for (ArrayList<BookieSocketAddress> bookies : ensembles) {
+            for (BookieSocketAddress bookieAddress : bookies) {
+                int port = bookieAddress.getPort();
+                assertTrue(tlsBookiePorts.contains(port));
+            }
+        }
+    }
+
+    /**
+     * Verify that a client-side Auth plugin can access server certificates
+     */
+    @Test(timeout = 60000)
+    public void testClientAuthPlugin() throws Exception {
+        secureClientSideChannel = false;
+        secureClientSideChannelPrincipals = null;
+        ClientConfiguration clientConf = new ClientConfiguration(baseClientConf);
+
+        clientConf.setClientAuthProviderFactoryClass(AllowOnlyBookiesWithX509Certificates.class.getName());
+
+        testClient(clientConf, numBookies);
+        assertTrue(secureClientSideChannel);
+        assertNotNull(secureClientSideChannelPrincipals);
+        assertTrue(!secureClientSideChannelPrincipals.isEmpty());
+        assertTrue(secureClientSideChannelPrincipals.iterator().next() instanceof Certificate);
+        Certificate cert = (Certificate) secureClientSideChannelPrincipals.iterator().next();
+        assertTrue(cert instanceof X509Certificate);
+    }
+
+    /**
+     * Verify that a bookie-side Auth plugin can access server certificates
+     */
+    @Test(timeout = 60000)
+    public void testBookieAuthPluginRequireClientTLSAuthentication() throws Exception {
+        ServerConfiguration serverConf = new ServerConfiguration(baseConf);
+        serverConf.setBookieAuthProviderFactoryClass(AllowOnlyClientsWithX509Certificates.class.getName());
+        restartBookies(serverConf);
+
+        secureBookieSideChannel = false;
+        secureBookieSideChannelPrincipals = null;
+        ClientConfiguration clientConf = new ClientConfiguration(baseClientConf);
+
+        testClient(clientConf, numBookies);
+        assertTrue(secureBookieSideChannel);
+        assertNotNull(secureBookieSideChannelPrincipals);
+        assertTrue(!secureBookieSideChannelPrincipals.isEmpty());
+        assertTrue(secureBookieSideChannelPrincipals.iterator().next() instanceof Certificate);
+        Certificate cert = (Certificate) secureBookieSideChannelPrincipals.iterator().next();
+        assertTrue(cert instanceof X509Certificate);
+    }
+
+    /**
+     * Verify that a bookie-side Auth plugin can access server certificates
+     */
+    @Test(timeout = 60000)
+    public void testBookieAuthPluginDenyAccesstoClientWithoutTLSAuthentication() throws Exception {
+        ServerConfiguration serverConf = new ServerConfiguration(baseConf);
+        serverConf.setTLSClientAuthentication(false);
+        serverConf.setBookieAuthProviderFactoryClass(AllowOnlyClientsWithX509Certificates.class.getName());
+        restartBookies(serverConf);
+
+        secureBookieSideChannel = false;
+        secureBookieSideChannelPrincipals = null;
+        ClientConfiguration clientConf = new ClientConfiguration(baseClientConf);
+        clientConf.setTLSClientAuthentication(false);
+
+        try {
+            testClient(clientConf, numBookies);
+            fail("Shouldn't be able to connect");
+        } catch (BKException.BKUnauthorizedAccessException authFailed) {
+        }
+
+        assertTrue(secureBookieSideChannel);
+        assertNotNull(secureBookieSideChannelPrincipals);
+        assertTrue(secureBookieSideChannelPrincipals.isEmpty());
+    }
+
+    /**
+     * Verify that a bookie-side Auth plugin can access server certificates
+     */
+    @Test(timeout = 60000)
+    public void testBookieAuthPluginDenyAccessToClientWithoutTLS() throws Exception {
+        ServerConfiguration serverConf = new ServerConfiguration(baseConf);
+        serverConf.setBookieAuthProviderFactoryClass(AllowOnlyClientsWithX509Certificates.class.getName());
+        restartBookies(serverConf);
+
+        secureBookieSideChannel = false;
+        secureBookieSideChannelPrincipals = null;
+        ClientConfiguration clientConf = new ClientConfiguration(baseClientConf);
+        clientConf.setTLSProviderFactoryClass("");
+
+        try {
+            testClient(clientConf, numBookies);
+            fail("Shouldn't be able to connect");
+        } catch (BKException.BKUnauthorizedAccessException authFailed) {
+        }
+
+        assertFalse(secureBookieSideChannel);
+        assertNull(secureBookieSideChannelPrincipals);
+    }
+
+    private static class AllowOnlyBookiesWithX509Certificates implements ClientAuthProvider.Factory {
+
+        @Override
+        public String getPluginName() {
+            return "tls";
+        }
+
+        @Override
+        public void init(ClientConfiguration conf) {
+        }
+
+        @Override
+        public ClientAuthProvider newProvider(ClientConnectionPeer addr,
+                final AuthCallbacks.GenericCallback<Void> completeCb) {
+            return new ClientAuthProvider() {
+
+                AuthCallbacks.GenericCallback<AuthToken> completeCallback;
+
+                @Override
+                public void init(AuthCallbacks.GenericCallback<AuthToken> cb) {
+                    this.completeCallback = cb;
+                }
+
+                @Override
+                public void onProtocolUpgrade() {
+                    secureClientSideChannel = addr.isSecure();
+                    secureClientSideChannelPrincipals = addr.getProtocolPrincipals();
+                    Collection<Object> certificates = addr.getProtocolPrincipals();
+                    if (addr.isSecure() && !certificates.isEmpty()) {
+                        assertTrue(certificates.iterator().next() instanceof X509Certificate);
+                        completeCallback.operationComplete(BKException.Code.OK, AuthToken.NULL);
+                    } else {
+                        completeCallback.operationComplete(BKException.Code.UnauthorizedAccessException,
+                                AuthToken.NULL);
+                    }
+                }
+
+                @Override
+                public void process(AuthToken m, AuthCallbacks.GenericCallback<AuthToken> cb) {
+                }
+            };
+        }
+    }
+
+    private static class AllowOnlyClientsWithX509Certificates implements BookieAuthProvider.Factory {
+
+        @Override
+        public String getPluginName() {
+            return "tls";
+        }
+
+        @Override
+        public void init(ServerConfiguration conf) throws IOException {
+        }
+
+        @Override
+        public BookieAuthProvider newProvider(BookieConnectionPeer addr,
+                final AuthCallbacks.GenericCallback<Void> completeCb) {
+            return new BookieAuthProvider() {
+
+                AuthCallbacks.GenericCallback<Void> completeCallback = completeCb;
+
+                @Override
+                public void onProtocolUpgrade() {
+                    secureBookieSideChannel = addr.isSecure();
+                    secureBookieSideChannelPrincipals = addr.getProtocolPrincipals();
+                    Collection<Object> certificates = addr.getProtocolPrincipals();
+                    if (addr.isSecure() && !certificates.isEmpty()) {
+                        assertTrue(certificates.iterator().next() instanceof X509Certificate);
+                        completeCallback.operationComplete(BKException.Code.OK, null);
+                    } else {
+                        completeCallback.operationComplete(BKException.Code.UnauthorizedAccessException, null);
+                    }
+                }
+
+                @Override
+                public void process(AuthToken m, AuthCallbacks.GenericCallback<AuthToken> cb) {
+                }
+            };
+        }
+    }
+
+    /**
+     * Verify that a client will fail to connect to a server if it has asked for TLS, but it is not available. Verify
+     * that if there are enough TLS servers to fill the ensemble, it will eventually use those rather than the non-TLS
+     */
+    @Test(timeout = 60000)
+    public void testMixedCluster() throws Exception {
+        ClientConfiguration clientConf = new ClientConfiguration(baseClientConf);
+        int origNumBookies = numBookies;
+
+        ServerConfiguration bookieConf = newServerConfiguration();
+        /*
+        bookieConf.setTLSProviderFactoryClass(null);
+        bs.add(startBookie(bookieConf));
+        try {
+            testClient(clientConf, origNumBookies + 1);
+            fail("Shouldn't be able to connect");
+        } catch (BKException.BKNotEnoughBookiesException nnbe) {
+            // correct response
+        }
+
+        bookieConf = newServerConfiguration();
+        */
+        bookieConf.setTLSProviderFactoryClass(TLSContextFactory.class.getName());
+        bs.add(startBookie(bookieConf));
+        testClient(clientConf, origNumBookies + 1);
+    }
+
+    /**
+     * Verify that if the server hangs while an TLS client is trying to connect, the client can continue.
+     */
+    @Test(timeout = 60000)
+    public void testHungServer() throws Exception {
+        ClientConfiguration clientConf = new ClientConfiguration(baseClientConf);
+        CountDownLatch latch = new CountDownLatch(1);
+        sleepBookie(getBookie(0), latch);
+        try {
+            testClient(clientConf, numBookies);
+            fail("Shouldn't be able to connect");
+        } catch (BKException.BKNotEnoughBookiesException nnbe) {
+            // correct response
+        }
+        LOG.info("latch countdown");
+        latch.countDown();
+    }
+}
diff --git a/bookkeeper-server/src/test/resources/cacerts b/bookkeeper-server/src/test/resources/cacerts
new file mode 100644
index 0000000..5016b0c
Binary files /dev/null and b/bookkeeper-server/src/test/resources/cacerts differ
diff --git a/bookkeeper-server/src/test/resources/client.jks b/bookkeeper-server/src/test/resources/client.jks
new file mode 100644
index 0000000..a959a9b
Binary files /dev/null and b/bookkeeper-server/src/test/resources/client.jks differ
diff --git a/bookkeeper-server/src/test/resources/keyStoreClientPassword.txt b/bookkeeper-server/src/test/resources/keyStoreClientPassword.txt
new file mode 100644
index 0000000..b051c6c
--- /dev/null
+++ b/bookkeeper-server/src/test/resources/keyStoreClientPassword.txt
@@ -0,0 +1 @@
+client
diff --git a/bookkeeper-server/src/test/resources/keyStoreServerPassword.txt b/bookkeeper-server/src/test/resources/keyStoreServerPassword.txt
new file mode 100644
index 0000000..254defd
--- /dev/null
+++ b/bookkeeper-server/src/test/resources/keyStoreServerPassword.txt
@@ -0,0 +1 @@
+server
diff --git a/bookkeeper-server/src/test/resources/server.jks b/bookkeeper-server/src/test/resources/server.jks
new file mode 100644
index 0000000..aa582e6
Binary files /dev/null and b/bookkeeper-server/src/test/resources/server.jks differ
diff --git a/bookkeeper-server/src/test/resources/trustStorePassword.txt b/bookkeeper-server/src/test/resources/trustStorePassword.txt
new file mode 100644
index 0000000..1d40192
--- /dev/null
+++ b/bookkeeper-server/src/test/resources/trustStorePassword.txt
@@ -0,0 +1 @@
+changeit
diff --git a/pom.xml b/pom.xml
index 8e78dd9..613c4cf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -96,8 +96,9 @@
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
     <guava.version>20.0</guava.version>
-    <netty.version>4.1.10.Final</netty.version>
     <protobuf.version>2.6.1</protobuf.version>
+    <netty.version>4.1.12.Final</netty.version>
+    <netty-boringssl.version>2.0.3.Final</netty-boringssl.version>
     <slf4j.version>1.7.25</slf4j.version>
     <zookeeper.version>3.5.3-beta</zookeeper.version>
     <!-- plugin dependencies -->
@@ -303,7 +304,7 @@
             <groupId>org.apache.maven.plugins</groupId>
             <artifactId>maven-surefire-plugin</artifactId>
             <configuration>
-	      <redirectTestOutputToFile>false</redirectTestOutputToFile>
+	      <redirectTestOutputToFile>true</redirectTestOutputToFile>
             </configuration>
 	  </plugin>
 	</plugins>

-- 
To stop receiving notification emails like this one, please contact
['"commits@bookkeeper.apache.org" <co...@bookkeeper.apache.org>'].