You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@drill.apache.org by pa...@apache.org on 2015/04/04 04:37:32 UTC

[6/9] drill git commit: DRILL-2673: Update UserServer <==> UserClient RPC to better handle handshake response

DRILL-2673: Update UserServer <==> UserClient RPC to better handle handshake response


Project: http://git-wip-us.apache.org/repos/asf/drill/repo
Commit: http://git-wip-us.apache.org/repos/asf/drill/commit/a218ee3f
Tree: http://git-wip-us.apache.org/repos/asf/drill/tree/a218ee3f
Diff: http://git-wip-us.apache.org/repos/asf/drill/diff/a218ee3f

Branch: refs/heads/master
Commit: a218ee3fdd4403c0e1f4478cacf320f0947ea902
Parents: 1d9d82b
Author: vkorukanti <ve...@gmail.com>
Authored: Thu Apr 2 00:23:29 2015 -0700
Committer: Parth Chandra <pc...@maprtech.com>
Committed: Fri Apr 3 18:40:52 2015 -0700

----------------------------------------------------------------------
 .../apache/drill/exec/client/DrillClient.java   |   4 +-
 .../exec/rpc/AbstractHandshakeHandler.java      |  33 +-
 .../org/apache/drill/exec/rpc/BasicServer.java  |   2 +-
 .../apache/drill/exec/rpc/user/UserClient.java  |  12 +-
 .../drill/exec/rpc/user/UserRpcConfig.java      |   2 +-
 .../apache/drill/exec/rpc/user/UserServer.java  |  67 ++-
 .../apache/drill/jdbc/DrillConnectionImpl.java  |   2 +-
 .../drill/exec/proto/SchemaUserProtos.java      |  21 +
 .../org/apache/drill/exec/proto/UserProtos.java | 559 ++++++++++++++++++-
 .../exec/proto/beans/BitToUserHandshake.java    |  66 +++
 .../drill/exec/proto/beans/HandshakeStatus.java |  53 ++
 protocol/src/main/protobuf/User.proto           |  10 +
 12 files changed, 789 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/drill/blob/a218ee3f/exec/java-exec/src/main/java/org/apache/drill/exec/client/DrillClient.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/client/DrillClient.java b/exec/java-exec/src/main/java/org/apache/drill/exec/client/DrillClient.java
index 650a2eb..9a948fb 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/client/DrillClient.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/client/DrillClient.java
@@ -135,7 +135,7 @@ public class DrillClient implements Closeable, ConnectionThrottle {
    * @throws RpcException
    */
   public void connect() throws RpcException {
-    connect(null, new Properties());
+    connect(null, null);
   }
 
   public void connect(Properties props) throws RpcException {
@@ -365,7 +365,7 @@ public class DrillClient implements Closeable, ConnectionThrottle {
 
     @Override
     public void connectionFailed(FailureType type, Throwable t) {
-      getInner().setException(new RpcException(String.format("Failure connecting to server. Failure of type %s.", type.name()), t));
+      getInner().setException(new RpcException(String.format("%s : %s", type.name(), t.getMessage()), t));
     }
 
     private SettableFuture<Void> getInner() {

http://git-wip-us.apache.org/repos/asf/drill/blob/a218ee3f/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractHandshakeHandler.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractHandshakeHandler.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractHandshakeHandler.java
index 9048241..9f426e4 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractHandshakeHandler.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractHandshakeHandler.java
@@ -42,23 +42,26 @@ public abstract class AbstractHandshakeHandler<T extends MessageLite> extends Me
 
   @Override
   protected void decode(ChannelHandlerContext ctx, InboundRpcMessage inbound, List<Object> outputs) throws Exception {
-    if (RpcConstants.EXTRA_DEBUGGING) {
-      logger.debug("Received handshake {}", inbound);
-    }
-    this.coordinationId = inbound.coordinationId;
-    ctx.channel().pipeline().remove(this);
-    if (inbound.rpcType != handshakeType.getNumber()) {
-      throw new RpcException(String.format("Handshake failure.  Expected %s[%d] but received number [%d]",
-          handshakeType, handshakeType.getNumber(), inbound.rpcType));
-    }
+    try {
+      if (RpcConstants.EXTRA_DEBUGGING) {
+        logger.debug("Received handshake {}", inbound);
+      }
+      this.coordinationId = inbound.coordinationId;
+      ctx.channel().pipeline().remove(this);
+      if (inbound.rpcType != handshakeType.getNumber()) {
+        throw new RpcException(String.format("Handshake failure.  Expected %s[%d] but received number [%d]",
+            handshakeType, handshakeType.getNumber(), inbound.rpcType));
+      }
 
-    T msg = parser.parseFrom(inbound.getProtobufBodyAsIS());
-    consumeHandshake(ctx, msg);
-    inbound.pBody.release();
-    if (inbound.dBody != null) {
-      inbound.dBody.release();
+      T msg = parser.parseFrom(inbound.getProtobufBodyAsIS());
+      consumeHandshake(ctx, msg);
+    } finally {
+      // Consuming a handshake may result in exceptions, so make sure to release the message buffers.
+      inbound.pBody.release();
+      if (inbound.dBody != null) {
+        inbound.dBody.release();
+      }
     }
-
   }
 
   protected abstract void consumeHandshake(ChannelHandlerContext ctx, T msg) throws Exception;

http://git-wip-us.apache.org/repos/asf/drill/blob/a218ee3f/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/BasicServer.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/BasicServer.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/BasicServer.java
index 0e0398d..3a7032b 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/BasicServer.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/BasicServer.java
@@ -108,7 +108,7 @@ public abstract class BasicServer<T extends EnumLite, C extends RemoteConnection
     }
 
     @Override
-    protected final void consumeHandshake(ChannelHandlerContext ctx, T inbound) throws Exception {
+    protected void consumeHandshake(ChannelHandlerContext ctx, T inbound) throws Exception {
       OutboundRpcMessage msg = new OutboundRpcMessage(RpcMode.RESPONSE, this.handshakeType, coordinationId,
           getHandshakeResponse(inbound));
       ctx.writeAndFlush(msg);

http://git-wip-us.apache.org/repos/asf/drill/blob/a218ee3f/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java
index fd82699..8022c95 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java
@@ -28,6 +28,7 @@ import org.apache.drill.exec.proto.UserBitShared.QueryId;
 import org.apache.drill.exec.proto.UserBitShared.QueryResult;
 import org.apache.drill.exec.proto.UserBitShared.QueryData;
 import org.apache.drill.exec.proto.UserProtos.BitToUserHandshake;
+import org.apache.drill.exec.proto.UserProtos.HandshakeStatus;
 import org.apache.drill.exec.proto.UserProtos.RpcType;
 import org.apache.drill.exec.proto.UserProtos.RunQuery;
 import org.apache.drill.exec.proto.UserProtos.UserProperties;
@@ -42,7 +43,7 @@ import org.apache.drill.exec.rpc.RpcException;
 import com.google.protobuf.MessageLite;
 
 public class UserClient extends BasicClientWithConnection<RpcType, UserToBitHandshake, BitToUserHandshake> {
-//  private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(UserClient.class);
+  private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(UserClient.class);
 
   private final QueryResultHandler queryResultHandler = new QueryResultHandler();
 
@@ -107,11 +108,12 @@ public class UserClient extends BasicClientWithConnection<RpcType, UserToBitHand
   @Override
   protected void validateHandshake(BitToUserHandshake inbound) throws RpcException {
 //    logger.debug("Handling handshake from bit to user. {}", inbound);
-    if (inbound.getRpcVersion() != UserRpcConfig.RPC_VERSION) {
-      throw new RpcException(String.format("Invalid rpc version.  Expected %d, actual %d.", inbound.getRpcVersion(),
-          UserRpcConfig.RPC_VERSION));
+    if (inbound.getStatus() != HandshakeStatus.SUCCESS) {
+      final String errMsg = String.format("Status: %s, Error Id: %s, Error message: %s",
+          inbound.getStatus(), inbound.getErrorId(), inbound.getErrorMessage());
+      logger.error(errMsg);
+      throw new RpcException(errMsg);
     }
-
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/drill/blob/a218ee3f/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcConfig.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcConfig.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcConfig.java
index 9fb8bdb..88592d4 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcConfig.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcConfig.java
@@ -38,5 +38,5 @@ public class UserRpcConfig {
       .add(RpcType.QUERY_RESULT, QueryResult.class, RpcType.ACK, Ack.class) //bit to user
       .build();
 
-  public static int RPC_VERSION = 4;
+  public static int RPC_VERSION = 5;
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/a218ee3f/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServer.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServer.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServer.java
index 5b2433b..17f189d 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServer.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServer.java
@@ -20,21 +20,26 @@ package org.apache.drill.exec.rpc.user;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufInputStream;
 import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.EventLoopGroup;
 
 import java.io.IOException;
+import java.util.UUID;
 
 import org.apache.drill.exec.memory.BufferAllocator;
 import org.apache.drill.exec.physical.impl.materialize.QueryWritableBatch;
 import org.apache.drill.exec.proto.GeneralRPCProtos.Ack;
+import org.apache.drill.exec.proto.GeneralRPCProtos.RpcMode;
 import org.apache.drill.exec.proto.UserBitShared.QueryId;
 import org.apache.drill.exec.proto.UserBitShared.QueryResult;
 import org.apache.drill.exec.proto.UserProtos.BitToUserHandshake;
+import org.apache.drill.exec.proto.UserProtos.HandshakeStatus;
 import org.apache.drill.exec.proto.UserProtos.RpcType;
 import org.apache.drill.exec.proto.UserProtos.RunQuery;
 import org.apache.drill.exec.proto.UserProtos.UserToBitHandshake;
 import org.apache.drill.exec.rpc.BasicServer;
 import org.apache.drill.exec.rpc.OutOfMemoryHandler;
+import org.apache.drill.exec.rpc.OutboundRpcMessage;
 import org.apache.drill.exec.rpc.ProtobufLengthDecoder;
 import org.apache.drill.exec.rpc.RemoteConnection;
 import org.apache.drill.exec.rpc.Response;
@@ -149,19 +154,67 @@ public class UserServer extends BasicServer<RpcType, UserServer.UserClientConnec
     return new ServerHandshakeHandler<UserToBitHandshake>(RpcType.HANDSHAKE, UserToBitHandshake.PARSER){
 
       @Override
-      public MessageLite getHandshakeResponse(UserToBitHandshake inbound) throws Exception {
-        logger.trace("Handling handshake from user to bit. {}", inbound);
-        if(inbound.getRpcVersion() != UserRpcConfig.RPC_VERSION) {
-          throw new RpcException(String.format("Invalid rpc version. Expected %d, actual %d.", inbound.getRpcVersion(), UserRpcConfig.RPC_VERSION));
+      protected void consumeHandshake(ChannelHandlerContext ctx, UserToBitHandshake inbound) throws Exception {
+        BitToUserHandshake handshakeResp = getHandshakeResponse(inbound);
+        OutboundRpcMessage msg = new OutboundRpcMessage(RpcMode.RESPONSE, this.handshakeType, coordinationId, handshakeResp);
+        ctx.writeAndFlush(msg);
+
+        if (handshakeResp.getStatus() != HandshakeStatus.SUCCESS) {
+          // If handling handshake results in an error, throw an exception to terminate the connection.
+          throw new RpcException("Handshake request failed: " + handshakeResp.getErrorMessage());
         }
+      }
 
-        connection.setUser(inbound);
+      @Override
+      public BitToUserHandshake getHandshakeResponse(UserToBitHandshake inbound) throws Exception {
+        logger.trace("Handling handshake from user to bit. {}", inbound);
 
-        return BitToUserHandshake.newBuilder().setRpcVersion(UserRpcConfig.RPC_VERSION).build();
-      }
+        BitToUserHandshake.Builder respBuilder = BitToUserHandshake.newBuilder()
+            .setRpcVersion(UserRpcConfig.RPC_VERSION);
+
+        try {
+          if (inbound.getRpcVersion() != UserRpcConfig.RPC_VERSION) {
+            final String errMsg = String.format("Invalid rpc version. Expected %d, actual %d.",
+                UserRpcConfig.RPC_VERSION, inbound.getRpcVersion());
+
+            return handleFailure(respBuilder, HandshakeStatus.RPC_VERSION_MISMATCH, errMsg, null);
+          }
 
+          connection.setUser(inbound);
+
+          return respBuilder.setStatus(HandshakeStatus.SUCCESS).build();
+        } catch (Exception e) {
+          return handleFailure(respBuilder, HandshakeStatus.UNKNOWN_FAILURE, e.getMessage(), e);
+        }
+      }
     };
+  }
+
+  /**
+   * Complete building the given builder for <i>BitToUserHandshake</i> message with given status and error details.
+   *
+   * @param respBuilder Instance of {@link org.apache.drill.exec.proto.UserProtos.BitToUserHandshake} builder which
+   *                    has RPC version field already set.
+   * @param status  Status of handling handshake request.
+   * @param errMsg  Error message.
+   * @param exception Optional exception.
+   * @return
+   */
+  private static BitToUserHandshake handleFailure(BitToUserHandshake.Builder respBuilder, HandshakeStatus status,
+      String errMsg, Exception exception) {
+    final String errorId = UUID.randomUUID().toString();
+
+    if (exception != null) {
+      logger.error("Error {} in Handling handshake request: {}, {}", errorId, status, errMsg, exception);
+    } else {
+      logger.error("Error {} in Handling handshake request: {}, {}", errorId, status, errMsg);
+    }
 
+    return respBuilder
+        .setStatus(status)
+        .setErrorId(errorId)
+        .setErrorMessage(errMsg)
+        .build();
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/drill/blob/a218ee3f/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillConnectionImpl.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillConnectionImpl.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillConnectionImpl.java
index e590778..8caeb3f 100644
--- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillConnectionImpl.java
+++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillConnectionImpl.java
@@ -98,7 +98,7 @@ abstract class DrillConnectionImpl extends AvaticaConnection implements DrillCon
         this.client.connect(config.getZookeeperConnectionString(), info);
       }
     } catch (RpcException e) {
-      throw new SQLException("Failure while attempting to connect to Drill.", e);
+      throw new SQLException("Failure while attempting to connect to Drill: " + e.getMessage(), e);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/drill/blob/a218ee3f/protocol/src/main/java/org/apache/drill/exec/proto/SchemaUserProtos.java
----------------------------------------------------------------------
diff --git a/protocol/src/main/java/org/apache/drill/exec/proto/SchemaUserProtos.java b/protocol/src/main/java/org/apache/drill/exec/proto/SchemaUserProtos.java
index 3b056cf..d587dfc 100644
--- a/protocol/src/main/java/org/apache/drill/exec/proto/SchemaUserProtos.java
+++ b/protocol/src/main/java/org/apache/drill/exec/proto/SchemaUserProtos.java
@@ -663,6 +663,12 @@ public final class SchemaUserProtos
             {
                 if(message.hasRpcVersion())
                     output.writeInt32(2, message.getRpcVersion(), false);
+                if(message.hasStatus())
+                    output.writeEnum(3, message.getStatus().getNumber(), false);
+                if(message.hasErrorId())
+                    output.writeString(4, message.getErrorId(), false);
+                if(message.hasErrorMessage())
+                    output.writeString(5, message.getErrorMessage(), false);
             }
             public boolean isInitialized(org.apache.drill.exec.proto.UserProtos.BitToUserHandshake message)
             {
@@ -705,6 +711,15 @@ public final class SchemaUserProtos
                         case 2:
                             builder.setRpcVersion(input.readInt32());
                             break;
+                        case 3:
+                            builder.setStatus(org.apache.drill.exec.proto.UserProtos.HandshakeStatus.valueOf(input.readEnum()));
+                            break;
+                        case 4:
+                            builder.setErrorId(input.readString());
+                            break;
+                        case 5:
+                            builder.setErrorMessage(input.readString());
+                            break;
                         default:
                             input.handleUnknownField(number, this);
                     }
@@ -746,6 +761,9 @@ public final class SchemaUserProtos
             switch(number)
             {
                 case 2: return "rpcVersion";
+                case 3: return "status";
+                case 4: return "errorId";
+                case 5: return "errorMessage";
                 default: return null;
             }
         }
@@ -758,6 +776,9 @@ public final class SchemaUserProtos
         static
         {
             fieldMap.put("rpcVersion", 2);
+            fieldMap.put("status", 3);
+            fieldMap.put("errorId", 4);
+            fieldMap.put("errorMessage", 5);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/drill/blob/a218ee3f/protocol/src/main/java/org/apache/drill/exec/proto/UserProtos.java
----------------------------------------------------------------------
diff --git a/protocol/src/main/java/org/apache/drill/exec/proto/UserProtos.java b/protocol/src/main/java/org/apache/drill/exec/proto/UserProtos.java
index 0b81926..c072a47 100644
--- a/protocol/src/main/java/org/apache/drill/exec/proto/UserProtos.java
+++ b/protocol/src/main/java/org/apache/drill/exec/proto/UserProtos.java
@@ -305,6 +305,138 @@ public final class UserProtos {
     // @@protoc_insertion_point(enum_scope:exec.user.QueryResultsMode)
   }
 
+  /**
+   * Protobuf enum {@code exec.user.HandshakeStatus}
+   */
+  public enum HandshakeStatus
+      implements com.google.protobuf.ProtocolMessageEnum {
+    /**
+     * <code>SUCCESS = 1;</code>
+     *
+     * <pre>
+     * Handshake is successful (including authentication if any)
+     * </pre>
+     */
+    SUCCESS(0, 1),
+    /**
+     * <code>RPC_VERSION_MISMATCH = 2;</code>
+     *
+     * <pre>
+     * Client and Server RPC versions are different
+     * </pre>
+     */
+    RPC_VERSION_MISMATCH(1, 2),
+    /**
+     * <code>AUTH_FAILED = 3;</code>
+     *
+     * <pre>
+     * User authentication failed
+     * </pre>
+     */
+    AUTH_FAILED(2, 3),
+    /**
+     * <code>UNKNOWN_FAILURE = 4;</code>
+     *
+     * <pre>
+     * Unknown failure, refer to the error message for more details
+     * </pre>
+     */
+    UNKNOWN_FAILURE(3, 4),
+    ;
+
+    /**
+     * <code>SUCCESS = 1;</code>
+     *
+     * <pre>
+     * Handshake is successful (including authentication if any)
+     * </pre>
+     */
+    public static final int SUCCESS_VALUE = 1;
+    /**
+     * <code>RPC_VERSION_MISMATCH = 2;</code>
+     *
+     * <pre>
+     * Client and Server RPC versions are different
+     * </pre>
+     */
+    public static final int RPC_VERSION_MISMATCH_VALUE = 2;
+    /**
+     * <code>AUTH_FAILED = 3;</code>
+     *
+     * <pre>
+     * User authentication failed
+     * </pre>
+     */
+    public static final int AUTH_FAILED_VALUE = 3;
+    /**
+     * <code>UNKNOWN_FAILURE = 4;</code>
+     *
+     * <pre>
+     * Unknown failure, refer to the error message for more details
+     * </pre>
+     */
+    public static final int UNKNOWN_FAILURE_VALUE = 4;
+
+
+    public final int getNumber() { return value; }
+
+    public static HandshakeStatus valueOf(int value) {
+      switch (value) {
+        case 1: return SUCCESS;
+        case 2: return RPC_VERSION_MISMATCH;
+        case 3: return AUTH_FAILED;
+        case 4: return UNKNOWN_FAILURE;
+        default: return null;
+      }
+    }
+
+    public static com.google.protobuf.Internal.EnumLiteMap<HandshakeStatus>
+        internalGetValueMap() {
+      return internalValueMap;
+    }
+    private static com.google.protobuf.Internal.EnumLiteMap<HandshakeStatus>
+        internalValueMap =
+          new com.google.protobuf.Internal.EnumLiteMap<HandshakeStatus>() {
+            public HandshakeStatus findValueByNumber(int number) {
+              return HandshakeStatus.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.drill.exec.proto.UserProtos.getDescriptor().getEnumTypes().get(2);
+    }
+
+    private static final HandshakeStatus[] VALUES = values();
+
+    public static HandshakeStatus 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 HandshakeStatus(int index, int value) {
+      this.index = index;
+      this.value = value;
+    }
+
+    // @@protoc_insertion_point(enum_scope:exec.user.HandshakeStatus)
+  }
+
   public interface PropertyOrBuilder
       extends com.google.protobuf.MessageOrBuilder {
 
@@ -3929,6 +4061,46 @@ public final class UserProtos {
      * <code>optional int32 rpc_version = 2;</code>
      */
     int getRpcVersion();
+
+    // optional .exec.user.HandshakeStatus status = 3;
+    /**
+     * <code>optional .exec.user.HandshakeStatus status = 3;</code>
+     */
+    boolean hasStatus();
+    /**
+     * <code>optional .exec.user.HandshakeStatus status = 3;</code>
+     */
+    org.apache.drill.exec.proto.UserProtos.HandshakeStatus getStatus();
+
+    // optional string errorId = 4;
+    /**
+     * <code>optional string errorId = 4;</code>
+     */
+    boolean hasErrorId();
+    /**
+     * <code>optional string errorId = 4;</code>
+     */
+    java.lang.String getErrorId();
+    /**
+     * <code>optional string errorId = 4;</code>
+     */
+    com.google.protobuf.ByteString
+        getErrorIdBytes();
+
+    // optional string errorMessage = 5;
+    /**
+     * <code>optional string errorMessage = 5;</code>
+     */
+    boolean hasErrorMessage();
+    /**
+     * <code>optional string errorMessage = 5;</code>
+     */
+    java.lang.String getErrorMessage();
+    /**
+     * <code>optional string errorMessage = 5;</code>
+     */
+    com.google.protobuf.ByteString
+        getErrorMessageBytes();
   }
   /**
    * Protobuf type {@code exec.user.BitToUserHandshake}
@@ -3986,6 +4158,27 @@ public final class UserProtos {
               rpcVersion_ = input.readInt32();
               break;
             }
+            case 24: {
+              int rawValue = input.readEnum();
+              org.apache.drill.exec.proto.UserProtos.HandshakeStatus value = org.apache.drill.exec.proto.UserProtos.HandshakeStatus.valueOf(rawValue);
+              if (value == null) {
+                unknownFields.mergeVarintField(3, rawValue);
+              } else {
+                bitField0_ |= 0x00000002;
+                status_ = value;
+              }
+              break;
+            }
+            case 34: {
+              bitField0_ |= 0x00000004;
+              errorId_ = input.readBytes();
+              break;
+            }
+            case 42: {
+              bitField0_ |= 0x00000008;
+              errorMessage_ = input.readBytes();
+              break;
+            }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -4042,8 +4235,113 @@ public final class UserProtos {
       return rpcVersion_;
     }
 
+    // optional .exec.user.HandshakeStatus status = 3;
+    public static final int STATUS_FIELD_NUMBER = 3;
+    private org.apache.drill.exec.proto.UserProtos.HandshakeStatus status_;
+    /**
+     * <code>optional .exec.user.HandshakeStatus status = 3;</code>
+     */
+    public boolean hasStatus() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>optional .exec.user.HandshakeStatus status = 3;</code>
+     */
+    public org.apache.drill.exec.proto.UserProtos.HandshakeStatus getStatus() {
+      return status_;
+    }
+
+    // optional string errorId = 4;
+    public static final int ERRORID_FIELD_NUMBER = 4;
+    private java.lang.Object errorId_;
+    /**
+     * <code>optional string errorId = 4;</code>
+     */
+    public boolean hasErrorId() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>optional string errorId = 4;</code>
+     */
+    public java.lang.String getErrorId() {
+      java.lang.Object ref = errorId_;
+      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()) {
+          errorId_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string errorId = 4;</code>
+     */
+    public com.google.protobuf.ByteString
+        getErrorIdBytes() {
+      java.lang.Object ref = errorId_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        errorId_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    // optional string errorMessage = 5;
+    public static final int ERRORMESSAGE_FIELD_NUMBER = 5;
+    private java.lang.Object errorMessage_;
+    /**
+     * <code>optional string errorMessage = 5;</code>
+     */
+    public boolean hasErrorMessage() {
+      return ((bitField0_ & 0x00000008) == 0x00000008);
+    }
+    /**
+     * <code>optional string errorMessage = 5;</code>
+     */
+    public java.lang.String getErrorMessage() {
+      java.lang.Object ref = errorMessage_;
+      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()) {
+          errorMessage_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string errorMessage = 5;</code>
+     */
+    public com.google.protobuf.ByteString
+        getErrorMessageBytes() {
+      java.lang.Object ref = errorMessage_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        errorMessage_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
     private void initFields() {
       rpcVersion_ = 0;
+      status_ = org.apache.drill.exec.proto.UserProtos.HandshakeStatus.SUCCESS;
+      errorId_ = "";
+      errorMessage_ = "";
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
@@ -4060,6 +4358,15 @@ public final class UserProtos {
       if (((bitField0_ & 0x00000001) == 0x00000001)) {
         output.writeInt32(2, rpcVersion_);
       }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeEnum(3, status_.getNumber());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeBytes(4, getErrorIdBytes());
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        output.writeBytes(5, getErrorMessageBytes());
+      }
       getUnknownFields().writeTo(output);
     }
 
@@ -4073,6 +4380,18 @@ public final class UserProtos {
         size += com.google.protobuf.CodedOutputStream
           .computeInt32Size(2, rpcVersion_);
       }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeEnumSize(3, status_.getNumber());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(4, getErrorIdBytes());
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(5, getErrorMessageBytes());
+      }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
       return size;
@@ -4191,6 +4510,12 @@ public final class UserProtos {
         super.clear();
         rpcVersion_ = 0;
         bitField0_ = (bitField0_ & ~0x00000001);
+        status_ = org.apache.drill.exec.proto.UserProtos.HandshakeStatus.SUCCESS;
+        bitField0_ = (bitField0_ & ~0x00000002);
+        errorId_ = "";
+        bitField0_ = (bitField0_ & ~0x00000004);
+        errorMessage_ = "";
+        bitField0_ = (bitField0_ & ~0x00000008);
         return this;
       }
 
@@ -4223,6 +4548,18 @@ public final class UserProtos {
           to_bitField0_ |= 0x00000001;
         }
         result.rpcVersion_ = rpcVersion_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.status_ = status_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.errorId_ = errorId_;
+        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+          to_bitField0_ |= 0x00000008;
+        }
+        result.errorMessage_ = errorMessage_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
@@ -4242,6 +4579,19 @@ public final class UserProtos {
         if (other.hasRpcVersion()) {
           setRpcVersion(other.getRpcVersion());
         }
+        if (other.hasStatus()) {
+          setStatus(other.getStatus());
+        }
+        if (other.hasErrorId()) {
+          bitField0_ |= 0x00000004;
+          errorId_ = other.errorId_;
+          onChanged();
+        }
+        if (other.hasErrorMessage()) {
+          bitField0_ |= 0x00000008;
+          errorMessage_ = other.errorMessage_;
+          onChanged();
+        }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
@@ -4302,6 +4652,190 @@ public final class UserProtos {
         return this;
       }
 
+      // optional .exec.user.HandshakeStatus status = 3;
+      private org.apache.drill.exec.proto.UserProtos.HandshakeStatus status_ = org.apache.drill.exec.proto.UserProtos.HandshakeStatus.SUCCESS;
+      /**
+       * <code>optional .exec.user.HandshakeStatus status = 3;</code>
+       */
+      public boolean hasStatus() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>optional .exec.user.HandshakeStatus status = 3;</code>
+       */
+      public org.apache.drill.exec.proto.UserProtos.HandshakeStatus getStatus() {
+        return status_;
+      }
+      /**
+       * <code>optional .exec.user.HandshakeStatus status = 3;</code>
+       */
+      public Builder setStatus(org.apache.drill.exec.proto.UserProtos.HandshakeStatus value) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        bitField0_ |= 0x00000002;
+        status_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional .exec.user.HandshakeStatus status = 3;</code>
+       */
+      public Builder clearStatus() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        status_ = org.apache.drill.exec.proto.UserProtos.HandshakeStatus.SUCCESS;
+        onChanged();
+        return this;
+      }
+
+      // optional string errorId = 4;
+      private java.lang.Object errorId_ = "";
+      /**
+       * <code>optional string errorId = 4;</code>
+       */
+      public boolean hasErrorId() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>optional string errorId = 4;</code>
+       */
+      public java.lang.String getErrorId() {
+        java.lang.Object ref = errorId_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          errorId_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string errorId = 4;</code>
+       */
+      public com.google.protobuf.ByteString
+          getErrorIdBytes() {
+        java.lang.Object ref = errorId_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          errorId_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string errorId = 4;</code>
+       */
+      public Builder setErrorId(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+        errorId_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string errorId = 4;</code>
+       */
+      public Builder clearErrorId() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        errorId_ = getDefaultInstance().getErrorId();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string errorId = 4;</code>
+       */
+      public Builder setErrorIdBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+        errorId_ = value;
+        onChanged();
+        return this;
+      }
+
+      // optional string errorMessage = 5;
+      private java.lang.Object errorMessage_ = "";
+      /**
+       * <code>optional string errorMessage = 5;</code>
+       */
+      public boolean hasErrorMessage() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
+      }
+      /**
+       * <code>optional string errorMessage = 5;</code>
+       */
+      public java.lang.String getErrorMessage() {
+        java.lang.Object ref = errorMessage_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          errorMessage_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string errorMessage = 5;</code>
+       */
+      public com.google.protobuf.ByteString
+          getErrorMessageBytes() {
+        java.lang.Object ref = errorMessage_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          errorMessage_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string errorMessage = 5;</code>
+       */
+      public Builder setErrorMessage(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000008;
+        errorMessage_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string errorMessage = 5;</code>
+       */
+      public Builder clearErrorMessage() {
+        bitField0_ = (bitField0_ & ~0x00000008);
+        errorMessage_ = getDefaultInstance().getErrorMessage();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string errorMessage = 5;</code>
+       */
+      public Builder setErrorMessageBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000008;
+        errorMessage_ = value;
+        onChanged();
+        return this;
+      }
+
       // @@protoc_insertion_point(builder_scope:exec.user.BitToUserHandshake)
     }
 
@@ -4367,15 +4901,20 @@ public final class UserProtos {
       "imum_responses\030\002 \001(\005\"q\n\010RunQuery\0221\n\014resu" +
       "lts_mode\030\001 \001(\0162\033.exec.user.QueryResultsM" +
       "ode\022$\n\004type\030\002 \001(\0162\026.exec.shared.QueryTyp" +
-      "e\022\014\n\004plan\030\003 \001(\t\")\n\022BitToUserHandshake\022\023\n" +
-      "\013rpc_version\030\002 \001(\005*\310\001\n\007RpcType\022\r\n\tHANDSH" +
-      "AKE\020\000\022\007\n\003ACK\020\001\022\013\n\007GOODBYE\020\002\022\r\n\tRUN_QUERY" +
-      "\020\003\022\020\n\014CANCEL_QUERY\020\004\022\023\n\017REQUEST_RESULTS\020" +
-      "\005\022\016\n\nQUERY_DATA\020\006\022\020\n\014QUERY_HANDLE\020\007\022\026\n\022R",
-      "EQ_META_FUNCTIONS\020\010\022\026\n\022RESP_FUNCTION_LIS" +
-      "T\020\t\022\020\n\014QUERY_RESULT\020\n*#\n\020QueryResultsMod" +
-      "e\022\017\n\013STREAM_FULL\020\001B+\n\033org.apache.drill.e" +
-      "xec.protoB\nUserProtosH\001"
+      "e\022\014\n\004plan\030\003 \001(\t\"|\n\022BitToUserHandshake\022\023\n" +
+      "\013rpc_version\030\002 \001(\005\022*\n\006status\030\003 \001(\0162\032.exe" +
+      "c.user.HandshakeStatus\022\017\n\007errorId\030\004 \001(\t\022" +
+      "\024\n\014errorMessage\030\005 \001(\t*\310\001\n\007RpcType\022\r\n\tHAN" +
+      "DSHAKE\020\000\022\007\n\003ACK\020\001\022\013\n\007GOODBYE\020\002\022\r\n\tRUN_QU",
+      "ERY\020\003\022\020\n\014CANCEL_QUERY\020\004\022\023\n\017REQUEST_RESUL" +
+      "TS\020\005\022\016\n\nQUERY_DATA\020\006\022\020\n\014QUERY_HANDLE\020\007\022\026" +
+      "\n\022REQ_META_FUNCTIONS\020\010\022\026\n\022RESP_FUNCTION_" +
+      "LIST\020\t\022\020\n\014QUERY_RESULT\020\n*#\n\020QueryResults" +
+      "Mode\022\017\n\013STREAM_FULL\020\001*^\n\017HandshakeStatus" +
+      "\022\013\n\007SUCCESS\020\001\022\030\n\024RPC_VERSION_MISMATCH\020\002\022" +
+      "\017\n\013AUTH_FAILED\020\003\022\023\n\017UNKNOWN_FAILURE\020\004B+\n" +
+      "\033org.apache.drill.exec.protoB\nUserProtos" +
+      "H\001"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
       new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -4417,7 +4956,7 @@ public final class UserProtos {
           internal_static_exec_user_BitToUserHandshake_fieldAccessorTable = new
             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
               internal_static_exec_user_BitToUserHandshake_descriptor,
-              new java.lang.String[] { "RpcVersion", });
+              new java.lang.String[] { "RpcVersion", "Status", "ErrorId", "ErrorMessage", });
           return null;
         }
       };

http://git-wip-us.apache.org/repos/asf/drill/blob/a218ee3f/protocol/src/main/java/org/apache/drill/exec/proto/beans/BitToUserHandshake.java
----------------------------------------------------------------------
diff --git a/protocol/src/main/java/org/apache/drill/exec/proto/beans/BitToUserHandshake.java b/protocol/src/main/java/org/apache/drill/exec/proto/beans/BitToUserHandshake.java
index 813eb1c..20c6de1 100644
--- a/protocol/src/main/java/org/apache/drill/exec/proto/beans/BitToUserHandshake.java
+++ b/protocol/src/main/java/org/apache/drill/exec/proto/beans/BitToUserHandshake.java
@@ -48,6 +48,9 @@ public final class BitToUserHandshake implements Externalizable, Message<BitToUs
 
     
     private int rpcVersion;
+    private HandshakeStatus status;
+    private String errorId;
+    private String errorMessage;
 
     public BitToUserHandshake()
     {
@@ -69,6 +72,45 @@ public final class BitToUserHandshake implements Externalizable, Message<BitToUs
         return this;
     }
 
+    // status
+
+    public HandshakeStatus getStatus()
+    {
+        return status == null ? HandshakeStatus.SUCCESS : status;
+    }
+
+    public BitToUserHandshake setStatus(HandshakeStatus status)
+    {
+        this.status = status;
+        return this;
+    }
+
+    // errorId
+
+    public String getErrorId()
+    {
+        return errorId;
+    }
+
+    public BitToUserHandshake setErrorId(String errorId)
+    {
+        this.errorId = errorId;
+        return this;
+    }
+
+    // errorMessage
+
+    public String getErrorMessage()
+    {
+        return errorMessage;
+    }
+
+    public BitToUserHandshake setErrorMessage(String errorMessage)
+    {
+        this.errorMessage = errorMessage;
+        return this;
+    }
+
     // java serialization
 
     public void readExternal(ObjectInput in) throws IOException
@@ -126,6 +168,15 @@ public final class BitToUserHandshake implements Externalizable, Message<BitToUs
                 case 2:
                     message.rpcVersion = input.readInt32();
                     break;
+                case 3:
+                    message.status = HandshakeStatus.valueOf(input.readEnum());
+                    break;
+                case 4:
+                    message.errorId = input.readString();
+                    break;
+                case 5:
+                    message.errorMessage = input.readString();
+                    break;
                 default:
                     input.handleUnknownField(number, this);
             }   
@@ -137,6 +188,15 @@ public final class BitToUserHandshake implements Externalizable, Message<BitToUs
     {
         if(message.rpcVersion != 0)
             output.writeInt32(2, message.rpcVersion, false);
+
+        if(message.status != null)
+             output.writeEnum(3, message.status.number, false);
+
+        if(message.errorId != null)
+            output.writeString(4, message.errorId, false);
+
+        if(message.errorMessage != null)
+            output.writeString(5, message.errorMessage, false);
     }
 
     public String getFieldName(int number)
@@ -144,6 +204,9 @@ public final class BitToUserHandshake implements Externalizable, Message<BitToUs
         switch(number)
         {
             case 2: return "rpcVersion";
+            case 3: return "status";
+            case 4: return "errorId";
+            case 5: return "errorMessage";
             default: return null;
         }
     }
@@ -158,6 +221,9 @@ public final class BitToUserHandshake implements Externalizable, Message<BitToUs
     static
     {
         __fieldMap.put("rpcVersion", 2);
+        __fieldMap.put("status", 3);
+        __fieldMap.put("errorId", 4);
+        __fieldMap.put("errorMessage", 5);
     }
     
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/a218ee3f/protocol/src/main/java/org/apache/drill/exec/proto/beans/HandshakeStatus.java
----------------------------------------------------------------------
diff --git a/protocol/src/main/java/org/apache/drill/exec/proto/beans/HandshakeStatus.java b/protocol/src/main/java/org/apache/drill/exec/proto/beans/HandshakeStatus.java
new file mode 100644
index 0000000..3b6a7a1
--- /dev/null
+++ b/protocol/src/main/java/org/apache/drill/exec/proto/beans/HandshakeStatus.java
@@ -0,0 +1,53 @@
+/**
+ * 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.
+ */
+// Generated by http://code.google.com/p/protostuff/ ... DO NOT EDIT!
+// Generated from protobuf
+
+package org.apache.drill.exec.proto.beans;
+
+public enum HandshakeStatus implements com.dyuproject.protostuff.EnumLite<HandshakeStatus>
+{
+    SUCCESS(1),
+    RPC_VERSION_MISMATCH(2),
+    AUTH_FAILED(3),
+    UNKNOWN_FAILURE(4);
+    
+    public final int number;
+    
+    private HandshakeStatus (int number)
+    {
+        this.number = number;
+    }
+    
+    public int getNumber()
+    {
+        return number;
+    }
+    
+    public static HandshakeStatus valueOf(int number)
+    {
+        switch(number) 
+        {
+            case 1: return SUCCESS;
+            case 2: return RPC_VERSION_MISMATCH;
+            case 3: return AUTH_FAILED;
+            case 4: return UNKNOWN_FAILURE;
+            default: return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/a218ee3f/protocol/src/main/protobuf/User.proto
----------------------------------------------------------------------
diff --git a/protocol/src/main/protobuf/User.proto b/protocol/src/main/protobuf/User.proto
index a083c59..59e22ae 100644
--- a/protocol/src/main/protobuf/User.proto
+++ b/protocol/src/main/protobuf/User.proto
@@ -63,6 +63,16 @@ enum QueryResultsMode {
   // QUERY_FOR_STATUS = 3; // Client will need to query for status of query.
 }
 
+enum HandshakeStatus {
+  SUCCESS = 1; // Handshake is successful (including authentication if any)
+  RPC_VERSION_MISMATCH = 2; // Client and Server RPC versions are different
+  AUTH_FAILED = 3; // User authentication failed
+  UNKNOWN_FAILURE = 4; // Unknown failure, refer to the error message for more details
+}
+
 message BitToUserHandshake {
   optional int32 rpc_version = 2;
+  optional HandshakeStatus status = 3;
+  optional string errorId = 4;
+  optional string errorMessage = 5;
 }