/*
 * 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 the protocol buffer compiler.  DO NOT EDIT!
// source: Coordination.proto

package org.apache.drill.exec.proto;

public final class CoordinationProtos {
  private CoordinationProtos() {}
  public static void registerAllExtensions(
      com.google.protobuf.ExtensionRegistryLite registry) {
  }

  public static void registerAllExtensions(
      com.google.protobuf.ExtensionRegistry registry) {
    registerAllExtensions(
        (com.google.protobuf.ExtensionRegistryLite) registry);
  }
  public interface DrillbitEndpointOrBuilder extends
      // @@protoc_insertion_point(interface_extends:exec.DrillbitEndpoint)
      com.google.protobuf.MessageOrBuilder {

    /**
     * <code>optional string address = 1;</code>
     * @return Whether the address field is set.
     */
    boolean hasAddress();
    /**
     * <code>optional string address = 1;</code>
     * @return The address.
     */
    java.lang.String getAddress();
    /**
     * <code>optional string address = 1;</code>
     * @return The bytes for address.
     */
    com.google.protobuf.ByteString
        getAddressBytes();

    /**
     * <code>optional int32 user_port = 2;</code>
     * @return Whether the userPort field is set.
     */
    boolean hasUserPort();
    /**
     * <code>optional int32 user_port = 2;</code>
     * @return The userPort.
     */
    int getUserPort();

    /**
     * <code>optional int32 control_port = 3;</code>
     * @return Whether the controlPort field is set.
     */
    boolean hasControlPort();
    /**
     * <code>optional int32 control_port = 3;</code>
     * @return The controlPort.
     */
    int getControlPort();

    /**
     * <code>optional int32 data_port = 4;</code>
     * @return Whether the dataPort field is set.
     */
    boolean hasDataPort();
    /**
     * <code>optional int32 data_port = 4;</code>
     * @return The dataPort.
     */
    int getDataPort();

    /**
     * <code>optional .exec.Roles roles = 5;</code>
     * @return Whether the roles field is set.
     */
    boolean hasRoles();
    /**
     * <code>optional .exec.Roles roles = 5;</code>
     * @return The roles.
     */
    org.apache.drill.exec.proto.CoordinationProtos.Roles getRoles();
    /**
     * <code>optional .exec.Roles roles = 5;</code>
     */
    org.apache.drill.exec.proto.CoordinationProtos.RolesOrBuilder getRolesOrBuilder();

    /**
     * <code>optional string version = 6;</code>
     * @return Whether the version field is set.
     */
    boolean hasVersion();
    /**
     * <code>optional string version = 6;</code>
     * @return The version.
     */
    java.lang.String getVersion();
    /**
     * <code>optional string version = 6;</code>
     * @return The bytes for version.
     */
    com.google.protobuf.ByteString
        getVersionBytes();

    /**
     * <code>optional .exec.DrillbitEndpoint.State state = 7;</code>
     * @return Whether the state field is set.
     */
    boolean hasState();
    /**
     * <code>optional .exec.DrillbitEndpoint.State state = 7;</code>
     * @return The state.
     */
    org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.State getState();

    /**
     * <code>optional int32 http_port = 8;</code>
     * @return Whether the httpPort field is set.
     */
    boolean hasHttpPort();
    /**
     * <code>optional int32 http_port = 8;</code>
     * @return The httpPort.
     */
    int getHttpPort();
  }
  /**
   * Protobuf type {@code exec.DrillbitEndpoint}
   */
  public static final class DrillbitEndpoint extends
      com.google.protobuf.GeneratedMessageV3 implements
      // @@protoc_insertion_point(message_implements:exec.DrillbitEndpoint)
      DrillbitEndpointOrBuilder {
  private static final long serialVersionUID = 0L;
    // Use DrillbitEndpoint.newBuilder() to construct.
    private DrillbitEndpoint(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
      super(builder);
    }
    private DrillbitEndpoint() {
      address_ = "";
      version_ = "";
      state_ = 0;
    }

    @java.lang.Override
    @SuppressWarnings({"unused"})
    protected java.lang.Object newInstance(
        UnusedPrivateParameter unused) {
      return new DrillbitEndpoint();
    }

    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
    getUnknownFields() {
      return this.unknownFields;
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.drill.exec.proto.CoordinationProtos.internal_static_exec_DrillbitEndpoint_descriptor;
    }

    @java.lang.Override
    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.drill.exec.proto.CoordinationProtos.internal_static_exec_DrillbitEndpoint_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.class, org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.Builder.class);
    }

    /**
     * Protobuf enum {@code exec.DrillbitEndpoint.State}
     */
    public enum State
        implements com.google.protobuf.ProtocolMessageEnum {
      /**
       * <code>STARTUP = 0;</code>
       */
      STARTUP(0),
      /**
       * <code>ONLINE = 1;</code>
       */
      ONLINE(1),
      /**
       * <code>QUIESCENT = 2;</code>
       */
      QUIESCENT(2),
      /**
       * <code>OFFLINE = 3;</code>
       */
      OFFLINE(3),
      ;

      /**
       * <code>STARTUP = 0;</code>
       */
      public static final int STARTUP_VALUE = 0;
      /**
       * <code>ONLINE = 1;</code>
       */
      public static final int ONLINE_VALUE = 1;
      /**
       * <code>QUIESCENT = 2;</code>
       */
      public static final int QUIESCENT_VALUE = 2;
      /**
       * <code>OFFLINE = 3;</code>
       */
      public static final int OFFLINE_VALUE = 3;


      public final int getNumber() {
        return value;
      }

      /**
       * @param value The numeric wire value of the corresponding enum entry.
       * @return The enum associated with the given numeric wire value.
       * @deprecated Use {@link #forNumber(int)} instead.
       */
      @java.lang.Deprecated
      public static State valueOf(int value) {
        return forNumber(value);
      }

      /**
       * @param value The numeric wire value of the corresponding enum entry.
       * @return The enum associated with the given numeric wire value.
       */
      public static State forNumber(int value) {
        switch (value) {
          case 0: return STARTUP;
          case 1: return ONLINE;
          case 2: return QUIESCENT;
          case 3: return OFFLINE;
          default: return null;
        }
      }

      public static com.google.protobuf.Internal.EnumLiteMap<State>
          internalGetValueMap() {
        return internalValueMap;
      }
      private static final com.google.protobuf.Internal.EnumLiteMap<
          State> internalValueMap =
            new com.google.protobuf.Internal.EnumLiteMap<State>() {
              public State findValueByNumber(int number) {
                return State.forNumber(number);
              }
            };

      public final com.google.protobuf.Descriptors.EnumValueDescriptor
          getValueDescriptor() {
        return getDescriptor().getValues().get(ordinal());
      }
      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.CoordinationProtos.DrillbitEndpoint.getDescriptor().getEnumTypes().get(0);
      }

      private static final State[] VALUES = values();

      public static State 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 value;

      private State(int value) {
        this.value = value;
      }

      // @@protoc_insertion_point(enum_scope:exec.DrillbitEndpoint.State)
    }

    private int bitField0_;
    public static final int ADDRESS_FIELD_NUMBER = 1;
    private volatile java.lang.Object address_;
    /**
     * <code>optional string address = 1;</code>
     * @return Whether the address field is set.
     */
    @java.lang.Override
    public boolean hasAddress() {
      return ((bitField0_ & 0x00000001) != 0);
    }
    /**
     * <code>optional string address = 1;</code>
     * @return The address.
     */
    @java.lang.Override
    public java.lang.String getAddress() {
      java.lang.Object ref = address_;
      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()) {
          address_ = s;
        }
        return s;
      }
    }
    /**
     * <code>optional string address = 1;</code>
     * @return The bytes for address.
     */
    @java.lang.Override
    public com.google.protobuf.ByteString
        getAddressBytes() {
      java.lang.Object ref = address_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        address_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    public static final int USER_PORT_FIELD_NUMBER = 2;
    private int userPort_;
    /**
     * <code>optional int32 user_port = 2;</code>
     * @return Whether the userPort field is set.
     */
    @java.lang.Override
    public boolean hasUserPort() {
      return ((bitField0_ & 0x00000002) != 0);
    }
    /**
     * <code>optional int32 user_port = 2;</code>
     * @return The userPort.
     */
    @java.lang.Override
    public int getUserPort() {
      return userPort_;
    }

    public static final int CONTROL_PORT_FIELD_NUMBER = 3;
    private int controlPort_;
    /**
     * <code>optional int32 control_port = 3;</code>
     * @return Whether the controlPort field is set.
     */
    @java.lang.Override
    public boolean hasControlPort() {
      return ((bitField0_ & 0x00000004) != 0);
    }
    /**
     * <code>optional int32 control_port = 3;</code>
     * @return The controlPort.
     */
    @java.lang.Override
    public int getControlPort() {
      return controlPort_;
    }

    public static final int DATA_PORT_FIELD_NUMBER = 4;
    private int dataPort_;
    /**
     * <code>optional int32 data_port = 4;</code>
     * @return Whether the dataPort field is set.
     */
    @java.lang.Override
    public boolean hasDataPort() {
      return ((bitField0_ & 0x00000008) != 0);
    }
    /**
     * <code>optional int32 data_port = 4;</code>
     * @return The dataPort.
     */
    @java.lang.Override
    public int getDataPort() {
      return dataPort_;
    }

    public static final int ROLES_FIELD_NUMBER = 5;
    private org.apache.drill.exec.proto.CoordinationProtos.Roles roles_;
    /**
     * <code>optional .exec.Roles roles = 5;</code>
     * @return Whether the roles field is set.
     */
    @java.lang.Override
    public boolean hasRoles() {
      return ((bitField0_ & 0x00000010) != 0);
    }
    /**
     * <code>optional .exec.Roles roles = 5;</code>
     * @return The roles.
     */
    @java.lang.Override
    public org.apache.drill.exec.proto.CoordinationProtos.Roles getRoles() {
      return roles_ == null ? org.apache.drill.exec.proto.CoordinationProtos.Roles.getDefaultInstance() : roles_;
    }
    /**
     * <code>optional .exec.Roles roles = 5;</code>
     */
    @java.lang.Override
    public org.apache.drill.exec.proto.CoordinationProtos.RolesOrBuilder getRolesOrBuilder() {
      return roles_ == null ? org.apache.drill.exec.proto.CoordinationProtos.Roles.getDefaultInstance() : roles_;
    }

    public static final int VERSION_FIELD_NUMBER = 6;
    private volatile java.lang.Object version_;
    /**
     * <code>optional string version = 6;</code>
     * @return Whether the version field is set.
     */
    @java.lang.Override
    public boolean hasVersion() {
      return ((bitField0_ & 0x00000020) != 0);
    }
    /**
     * <code>optional string version = 6;</code>
     * @return The version.
     */
    @java.lang.Override
    public java.lang.String getVersion() {
      java.lang.Object ref = version_;
      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()) {
          version_ = s;
        }
        return s;
      }
    }
    /**
     * <code>optional string version = 6;</code>
     * @return The bytes for version.
     */
    @java.lang.Override
    public com.google.protobuf.ByteString
        getVersionBytes() {
      java.lang.Object ref = version_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        version_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    public static final int STATE_FIELD_NUMBER = 7;
    private int state_;
    /**
     * <code>optional .exec.DrillbitEndpoint.State state = 7;</code>
     * @return Whether the state field is set.
     */
    @java.lang.Override public boolean hasState() {
      return ((bitField0_ & 0x00000040) != 0);
    }
    /**
     * <code>optional .exec.DrillbitEndpoint.State state = 7;</code>
     * @return The state.
     */
    @java.lang.Override public org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.State getState() {
      @SuppressWarnings("deprecation")
      org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.State result = org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.State.valueOf(state_);
      return result == null ? org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.State.STARTUP : result;
    }

    public static final int HTTP_PORT_FIELD_NUMBER = 8;
    private int httpPort_;
    /**
     * <code>optional int32 http_port = 8;</code>
     * @return Whether the httpPort field is set.
     */
    @java.lang.Override
    public boolean hasHttpPort() {
      return ((bitField0_ & 0x00000080) != 0);
    }
    /**
     * <code>optional int32 http_port = 8;</code>
     * @return The httpPort.
     */
    @java.lang.Override
    public int getHttpPort() {
      return httpPort_;
    }

    private byte memoizedIsInitialized = -1;
    @java.lang.Override
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized == 1) return true;
      if (isInitialized == 0) return false;

      memoizedIsInitialized = 1;
      return true;
    }

    @java.lang.Override
    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      if (((bitField0_ & 0x00000001) != 0)) {
        com.google.protobuf.GeneratedMessageV3.writeString(output, 1, address_);
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        output.writeInt32(2, userPort_);
      }
      if (((bitField0_ & 0x00000004) != 0)) {
        output.writeInt32(3, controlPort_);
      }
      if (((bitField0_ & 0x00000008) != 0)) {
        output.writeInt32(4, dataPort_);
      }
      if (((bitField0_ & 0x00000010) != 0)) {
        output.writeMessage(5, getRoles());
      }
      if (((bitField0_ & 0x00000020) != 0)) {
        com.google.protobuf.GeneratedMessageV3.writeString(output, 6, version_);
      }
      if (((bitField0_ & 0x00000040) != 0)) {
        output.writeEnum(7, state_);
      }
      if (((bitField0_ & 0x00000080) != 0)) {
        output.writeInt32(8, httpPort_);
      }
      getUnknownFields().writeTo(output);
    }

    @java.lang.Override
    public int getSerializedSize() {
      int size = memoizedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) != 0)) {
        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, address_);
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(2, userPort_);
      }
      if (((bitField0_ & 0x00000004) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(3, controlPort_);
      }
      if (((bitField0_ & 0x00000008) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(4, dataPort_);
      }
      if (((bitField0_ & 0x00000010) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeMessageSize(5, getRoles());
      }
      if (((bitField0_ & 0x00000020) != 0)) {
        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(6, version_);
      }
      if (((bitField0_ & 0x00000040) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeEnumSize(7, state_);
      }
      if (((bitField0_ & 0x00000080) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(8, httpPort_);
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSize = size;
      return size;
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint)) {
        return super.equals(obj);
      }
      org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint other = (org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint) obj;

      if (hasAddress() != other.hasAddress()) return false;
      if (hasAddress()) {
        if (!getAddress()
            .equals(other.getAddress())) return false;
      }
      if (hasUserPort() != other.hasUserPort()) return false;
      if (hasUserPort()) {
        if (getUserPort()
            != other.getUserPort()) return false;
      }
      if (hasControlPort() != other.hasControlPort()) return false;
      if (hasControlPort()) {
        if (getControlPort()
            != other.getControlPort()) return false;
      }
      if (hasDataPort() != other.hasDataPort()) return false;
      if (hasDataPort()) {
        if (getDataPort()
            != other.getDataPort()) return false;
      }
      if (hasRoles() != other.hasRoles()) return false;
      if (hasRoles()) {
        if (!getRoles()
            .equals(other.getRoles())) return false;
      }
      if (hasVersion() != other.hasVersion()) return false;
      if (hasVersion()) {
        if (!getVersion()
            .equals(other.getVersion())) return false;
      }
      if (hasState() != other.hasState()) return false;
      if (hasState()) {
        if (state_ != other.state_) return false;
      }
      if (hasHttpPort() != other.hasHttpPort()) return false;
      if (hasHttpPort()) {
        if (getHttpPort()
            != other.getHttpPort()) return false;
      }
      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
      return true;
    }

    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptor().hashCode();
      if (hasAddress()) {
        hash = (37 * hash) + ADDRESS_FIELD_NUMBER;
        hash = (53 * hash) + getAddress().hashCode();
      }
      if (hasUserPort()) {
        hash = (37 * hash) + USER_PORT_FIELD_NUMBER;
        hash = (53 * hash) + getUserPort();
      }
      if (hasControlPort()) {
        hash = (37 * hash) + CONTROL_PORT_FIELD_NUMBER;
        hash = (53 * hash) + getControlPort();
      }
      if (hasDataPort()) {
        hash = (37 * hash) + DATA_PORT_FIELD_NUMBER;
        hash = (53 * hash) + getDataPort();
      }
      if (hasRoles()) {
        hash = (37 * hash) + ROLES_FIELD_NUMBER;
        hash = (53 * hash) + getRoles().hashCode();
      }
      if (hasVersion()) {
        hash = (37 * hash) + VERSION_FIELD_NUMBER;
        hash = (53 * hash) + getVersion().hashCode();
      }
      if (hasState()) {
        hash = (37 * hash) + STATE_FIELD_NUMBER;
        hash = (53 * hash) + state_;
      }
      if (hasHttpPort()) {
        hash = (37 * hash) + HTTP_PORT_FIELD_NUMBER;
        hash = (53 * hash) + getHttpPort();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint parseFrom(
        java.nio.ByteBuffer data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint parseFrom(
        java.nio.ByteBuffer data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint 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.drill.exec.proto.CoordinationProtos.DrillbitEndpoint parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input, extensionRegistry);
    }

    @java.lang.Override
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder() {
      return DEFAULT_INSTANCE.toBuilder();
    }
    public static Builder newBuilder(org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint prototype) {
      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
    }
    @java.lang.Override
    public Builder toBuilder() {
      return this == DEFAULT_INSTANCE
          ? new Builder() : new Builder().mergeFrom(this);
    }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code exec.DrillbitEndpoint}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
        // @@protoc_insertion_point(builder_implements:exec.DrillbitEndpoint)
        org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpointOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.drill.exec.proto.CoordinationProtos.internal_static_exec_DrillbitEndpoint_descriptor;
      }

      @java.lang.Override
      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.drill.exec.proto.CoordinationProtos.internal_static_exec_DrillbitEndpoint_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.class, org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.Builder.class);
      }

      // Construct using org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessageV3
                .alwaysUseFieldBuilders) {
          getRolesFieldBuilder();
        }
      }
      @java.lang.Override
      public Builder clear() {
        super.clear();
        address_ = "";
        bitField0_ = (bitField0_ & ~0x00000001);
        userPort_ = 0;
        bitField0_ = (bitField0_ & ~0x00000002);
        controlPort_ = 0;
        bitField0_ = (bitField0_ & ~0x00000004);
        dataPort_ = 0;
        bitField0_ = (bitField0_ & ~0x00000008);
        if (rolesBuilder_ == null) {
          roles_ = null;
        } else {
          rolesBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000010);
        version_ = "";
        bitField0_ = (bitField0_ & ~0x00000020);
        state_ = 0;
        bitField0_ = (bitField0_ & ~0x00000040);
        httpPort_ = 0;
        bitField0_ = (bitField0_ & ~0x00000080);
        return this;
      }

      @java.lang.Override
      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.drill.exec.proto.CoordinationProtos.internal_static_exec_DrillbitEndpoint_descriptor;
      }

      @java.lang.Override
      public org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint getDefaultInstanceForType() {
        return org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.getDefaultInstance();
      }

      @java.lang.Override
      public org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint build() {
        org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      @java.lang.Override
      public org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint buildPartial() {
        org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint result = new org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) != 0)) {
          to_bitField0_ |= 0x00000001;
        }
        result.address_ = address_;
        if (((from_bitField0_ & 0x00000002) != 0)) {
          result.userPort_ = userPort_;
          to_bitField0_ |= 0x00000002;
        }
        if (((from_bitField0_ & 0x00000004) != 0)) {
          result.controlPort_ = controlPort_;
          to_bitField0_ |= 0x00000004;
        }
        if (((from_bitField0_ & 0x00000008) != 0)) {
          result.dataPort_ = dataPort_;
          to_bitField0_ |= 0x00000008;
        }
        if (((from_bitField0_ & 0x00000010) != 0)) {
          if (rolesBuilder_ == null) {
            result.roles_ = roles_;
          } else {
            result.roles_ = rolesBuilder_.build();
          }
          to_bitField0_ |= 0x00000010;
        }
        if (((from_bitField0_ & 0x00000020) != 0)) {
          to_bitField0_ |= 0x00000020;
        }
        result.version_ = version_;
        if (((from_bitField0_ & 0x00000040) != 0)) {
          to_bitField0_ |= 0x00000040;
        }
        result.state_ = state_;
        if (((from_bitField0_ & 0x00000080) != 0)) {
          result.httpPort_ = httpPort_;
          to_bitField0_ |= 0x00000080;
        }
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      @java.lang.Override
      public Builder clone() {
        return super.clone();
      }
      @java.lang.Override
      public Builder setField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          java.lang.Object value) {
        return super.setField(field, value);
      }
      @java.lang.Override
      public Builder clearField(
          com.google.protobuf.Descriptors.FieldDescriptor field) {
        return super.clearField(field);
      }
      @java.lang.Override
      public Builder clearOneof(
          com.google.protobuf.Descriptors.OneofDescriptor oneof) {
        return super.clearOneof(oneof);
      }
      @java.lang.Override
      public Builder setRepeatedField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          int index, java.lang.Object value) {
        return super.setRepeatedField(field, index, value);
      }
      @java.lang.Override
      public Builder addRepeatedField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          java.lang.Object value) {
        return super.addRepeatedField(field, value);
      }
      @java.lang.Override
      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint) {
          return mergeFrom((org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint other) {
        if (other == org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.getDefaultInstance()) return this;
        if (other.hasAddress()) {
          bitField0_ |= 0x00000001;
          address_ = other.address_;
          onChanged();
        }
        if (other.hasUserPort()) {
          setUserPort(other.getUserPort());
        }
        if (other.hasControlPort()) {
          setControlPort(other.getControlPort());
        }
        if (other.hasDataPort()) {
          setDataPort(other.getDataPort());
        }
        if (other.hasRoles()) {
          mergeRoles(other.getRoles());
        }
        if (other.hasVersion()) {
          bitField0_ |= 0x00000020;
          version_ = other.version_;
          onChanged();
        }
        if (other.hasState()) {
          setState(other.getState());
        }
        if (other.hasHttpPort()) {
          setHttpPort(other.getHttpPort());
        }
        this.mergeUnknownFields(other.getUnknownFields());
        onChanged();
        return this;
      }

      @java.lang.Override
      public final boolean isInitialized() {
        return true;
      }

      @java.lang.Override
      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        if (extensionRegistry == null) {
          throw new java.lang.NullPointerException();
        }
        try {
          boolean done = false;
          while (!done) {
            int tag = input.readTag();
            switch (tag) {
              case 0:
                done = true;
                break;
              case 10: {
                address_ = input.readBytes();
                bitField0_ |= 0x00000001;
                break;
              } // case 10
              case 16: {
                userPort_ = input.readInt32();
                bitField0_ |= 0x00000002;
                break;
              } // case 16
              case 24: {
                controlPort_ = input.readInt32();
                bitField0_ |= 0x00000004;
                break;
              } // case 24
              case 32: {
                dataPort_ = input.readInt32();
                bitField0_ |= 0x00000008;
                break;
              } // case 32
              case 42: {
                input.readMessage(
                    getRolesFieldBuilder().getBuilder(),
                    extensionRegistry);
                bitField0_ |= 0x00000010;
                break;
              } // case 42
              case 50: {
                version_ = input.readBytes();
                bitField0_ |= 0x00000020;
                break;
              } // case 50
              case 56: {
                int tmpRaw = input.readEnum();
                org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.State tmpValue =
                    org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.State.forNumber(tmpRaw);
                if (tmpValue == null) {
                  mergeUnknownVarintField(7, tmpRaw);
                } else {
                  state_ = tmpRaw;
                  bitField0_ |= 0x00000040;
                }
                break;
              } // case 56
              case 64: {
                httpPort_ = input.readInt32();
                bitField0_ |= 0x00000080;
                break;
              } // case 64
              default: {
                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
                  done = true; // was an endgroup tag
                }
                break;
              } // default:
            } // switch (tag)
          } // while (!done)
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          throw e.unwrapIOException();
        } finally {
          onChanged();
        } // finally
        return this;
      }
      private int bitField0_;

      private java.lang.Object address_ = "";
      /**
       * <code>optional string address = 1;</code>
       * @return Whether the address field is set.
       */
      public boolean hasAddress() {
        return ((bitField0_ & 0x00000001) != 0);
      }
      /**
       * <code>optional string address = 1;</code>
       * @return The address.
       */
      public java.lang.String getAddress() {
        java.lang.Object ref = address_;
        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()) {
            address_ = s;
          }
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>optional string address = 1;</code>
       * @return The bytes for address.
       */
      public com.google.protobuf.ByteString
          getAddressBytes() {
        java.lang.Object ref = address_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          address_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>optional string address = 1;</code>
       * @param value The address to set.
       * @return This builder for chaining.
       */
      public Builder setAddress(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        address_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional string address = 1;</code>
       * @return This builder for chaining.
       */
      public Builder clearAddress() {
        bitField0_ = (bitField0_ & ~0x00000001);
        address_ = getDefaultInstance().getAddress();
        onChanged();
        return this;
      }
      /**
       * <code>optional string address = 1;</code>
       * @param value The bytes for address to set.
       * @return This builder for chaining.
       */
      public Builder setAddressBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        address_ = value;
        onChanged();
        return this;
      }

      private int userPort_ ;
      /**
       * <code>optional int32 user_port = 2;</code>
       * @return Whether the userPort field is set.
       */
      @java.lang.Override
      public boolean hasUserPort() {
        return ((bitField0_ & 0x00000002) != 0);
      }
      /**
       * <code>optional int32 user_port = 2;</code>
       * @return The userPort.
       */
      @java.lang.Override
      public int getUserPort() {
        return userPort_;
      }
      /**
       * <code>optional int32 user_port = 2;</code>
       * @param value The userPort to set.
       * @return This builder for chaining.
       */
      public Builder setUserPort(int value) {
        bitField0_ |= 0x00000002;
        userPort_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional int32 user_port = 2;</code>
       * @return This builder for chaining.
       */
      public Builder clearUserPort() {
        bitField0_ = (bitField0_ & ~0x00000002);
        userPort_ = 0;
        onChanged();
        return this;
      }

      private int controlPort_ ;
      /**
       * <code>optional int32 control_port = 3;</code>
       * @return Whether the controlPort field is set.
       */
      @java.lang.Override
      public boolean hasControlPort() {
        return ((bitField0_ & 0x00000004) != 0);
      }
      /**
       * <code>optional int32 control_port = 3;</code>
       * @return The controlPort.
       */
      @java.lang.Override
      public int getControlPort() {
        return controlPort_;
      }
      /**
       * <code>optional int32 control_port = 3;</code>
       * @param value The controlPort to set.
       * @return This builder for chaining.
       */
      public Builder setControlPort(int value) {
        bitField0_ |= 0x00000004;
        controlPort_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional int32 control_port = 3;</code>
       * @return This builder for chaining.
       */
      public Builder clearControlPort() {
        bitField0_ = (bitField0_ & ~0x00000004);
        controlPort_ = 0;
        onChanged();
        return this;
      }

      private int dataPort_ ;
      /**
       * <code>optional int32 data_port = 4;</code>
       * @return Whether the dataPort field is set.
       */
      @java.lang.Override
      public boolean hasDataPort() {
        return ((bitField0_ & 0x00000008) != 0);
      }
      /**
       * <code>optional int32 data_port = 4;</code>
       * @return The dataPort.
       */
      @java.lang.Override
      public int getDataPort() {
        return dataPort_;
      }
      /**
       * <code>optional int32 data_port = 4;</code>
       * @param value The dataPort to set.
       * @return This builder for chaining.
       */
      public Builder setDataPort(int value) {
        bitField0_ |= 0x00000008;
        dataPort_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional int32 data_port = 4;</code>
       * @return This builder for chaining.
       */
      public Builder clearDataPort() {
        bitField0_ = (bitField0_ & ~0x00000008);
        dataPort_ = 0;
        onChanged();
        return this;
      }

      private org.apache.drill.exec.proto.CoordinationProtos.Roles roles_;
      private com.google.protobuf.SingleFieldBuilderV3<
          org.apache.drill.exec.proto.CoordinationProtos.Roles, org.apache.drill.exec.proto.CoordinationProtos.Roles.Builder, org.apache.drill.exec.proto.CoordinationProtos.RolesOrBuilder> rolesBuilder_;
      /**
       * <code>optional .exec.Roles roles = 5;</code>
       * @return Whether the roles field is set.
       */
      public boolean hasRoles() {
        return ((bitField0_ & 0x00000010) != 0);
      }
      /**
       * <code>optional .exec.Roles roles = 5;</code>
       * @return The roles.
       */
      public org.apache.drill.exec.proto.CoordinationProtos.Roles getRoles() {
        if (rolesBuilder_ == null) {
          return roles_ == null ? org.apache.drill.exec.proto.CoordinationProtos.Roles.getDefaultInstance() : roles_;
        } else {
          return rolesBuilder_.getMessage();
        }
      }
      /**
       * <code>optional .exec.Roles roles = 5;</code>
       */
      public Builder setRoles(org.apache.drill.exec.proto.CoordinationProtos.Roles value) {
        if (rolesBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          roles_ = value;
          onChanged();
        } else {
          rolesBuilder_.setMessage(value);
        }
        bitField0_ |= 0x00000010;
        return this;
      }
      /**
       * <code>optional .exec.Roles roles = 5;</code>
       */
      public Builder setRoles(
          org.apache.drill.exec.proto.CoordinationProtos.Roles.Builder builderForValue) {
        if (rolesBuilder_ == null) {
          roles_ = builderForValue.build();
          onChanged();
        } else {
          rolesBuilder_.setMessage(builderForValue.build());
        }
        bitField0_ |= 0x00000010;
        return this;
      }
      /**
       * <code>optional .exec.Roles roles = 5;</code>
       */
      public Builder mergeRoles(org.apache.drill.exec.proto.CoordinationProtos.Roles value) {
        if (rolesBuilder_ == null) {
          if (((bitField0_ & 0x00000010) != 0) &&
              roles_ != null &&
              roles_ != org.apache.drill.exec.proto.CoordinationProtos.Roles.getDefaultInstance()) {
            roles_ =
              org.apache.drill.exec.proto.CoordinationProtos.Roles.newBuilder(roles_).mergeFrom(value).buildPartial();
          } else {
            roles_ = value;
          }
          onChanged();
        } else {
          rolesBuilder_.mergeFrom(value);
        }
        bitField0_ |= 0x00000010;
        return this;
      }
      /**
       * <code>optional .exec.Roles roles = 5;</code>
       */
      public Builder clearRoles() {
        if (rolesBuilder_ == null) {
          roles_ = null;
          onChanged();
        } else {
          rolesBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000010);
        return this;
      }
      /**
       * <code>optional .exec.Roles roles = 5;</code>
       */
      public org.apache.drill.exec.proto.CoordinationProtos.Roles.Builder getRolesBuilder() {
        bitField0_ |= 0x00000010;
        onChanged();
        return getRolesFieldBuilder().getBuilder();
      }
      /**
       * <code>optional .exec.Roles roles = 5;</code>
       */
      public org.apache.drill.exec.proto.CoordinationProtos.RolesOrBuilder getRolesOrBuilder() {
        if (rolesBuilder_ != null) {
          return rolesBuilder_.getMessageOrBuilder();
        } else {
          return roles_ == null ?
              org.apache.drill.exec.proto.CoordinationProtos.Roles.getDefaultInstance() : roles_;
        }
      }
      /**
       * <code>optional .exec.Roles roles = 5;</code>
       */
      private com.google.protobuf.SingleFieldBuilderV3<
          org.apache.drill.exec.proto.CoordinationProtos.Roles, org.apache.drill.exec.proto.CoordinationProtos.Roles.Builder, org.apache.drill.exec.proto.CoordinationProtos.RolesOrBuilder> 
          getRolesFieldBuilder() {
        if (rolesBuilder_ == null) {
          rolesBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
              org.apache.drill.exec.proto.CoordinationProtos.Roles, org.apache.drill.exec.proto.CoordinationProtos.Roles.Builder, org.apache.drill.exec.proto.CoordinationProtos.RolesOrBuilder>(
                  getRoles(),
                  getParentForChildren(),
                  isClean());
          roles_ = null;
        }
        return rolesBuilder_;
      }

      private java.lang.Object version_ = "";
      /**
       * <code>optional string version = 6;</code>
       * @return Whether the version field is set.
       */
      public boolean hasVersion() {
        return ((bitField0_ & 0x00000020) != 0);
      }
      /**
       * <code>optional string version = 6;</code>
       * @return The version.
       */
      public java.lang.String getVersion() {
        java.lang.Object ref = version_;
        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()) {
            version_ = s;
          }
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>optional string version = 6;</code>
       * @return The bytes for version.
       */
      public com.google.protobuf.ByteString
          getVersionBytes() {
        java.lang.Object ref = version_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          version_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>optional string version = 6;</code>
       * @param value The version to set.
       * @return This builder for chaining.
       */
      public Builder setVersion(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000020;
        version_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional string version = 6;</code>
       * @return This builder for chaining.
       */
      public Builder clearVersion() {
        bitField0_ = (bitField0_ & ~0x00000020);
        version_ = getDefaultInstance().getVersion();
        onChanged();
        return this;
      }
      /**
       * <code>optional string version = 6;</code>
       * @param value The bytes for version to set.
       * @return This builder for chaining.
       */
      public Builder setVersionBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000020;
        version_ = value;
        onChanged();
        return this;
      }

      private int state_ = 0;
      /**
       * <code>optional .exec.DrillbitEndpoint.State state = 7;</code>
       * @return Whether the state field is set.
       */
      @java.lang.Override public boolean hasState() {
        return ((bitField0_ & 0x00000040) != 0);
      }
      /**
       * <code>optional .exec.DrillbitEndpoint.State state = 7;</code>
       * @return The state.
       */
      @java.lang.Override
      public org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.State getState() {
        @SuppressWarnings("deprecation")
        org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.State result = org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.State.valueOf(state_);
        return result == null ? org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.State.STARTUP : result;
      }
      /**
       * <code>optional .exec.DrillbitEndpoint.State state = 7;</code>
       * @param value The state to set.
       * @return This builder for chaining.
       */
      public Builder setState(org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.State value) {
        if (value == null) {
          throw new NullPointerException();
        }
        bitField0_ |= 0x00000040;
        state_ = value.getNumber();
        onChanged();
        return this;
      }
      /**
       * <code>optional .exec.DrillbitEndpoint.State state = 7;</code>
       * @return This builder for chaining.
       */
      public Builder clearState() {
        bitField0_ = (bitField0_ & ~0x00000040);
        state_ = 0;
        onChanged();
        return this;
      }

      private int httpPort_ ;
      /**
       * <code>optional int32 http_port = 8;</code>
       * @return Whether the httpPort field is set.
       */
      @java.lang.Override
      public boolean hasHttpPort() {
        return ((bitField0_ & 0x00000080) != 0);
      }
      /**
       * <code>optional int32 http_port = 8;</code>
       * @return The httpPort.
       */
      @java.lang.Override
      public int getHttpPort() {
        return httpPort_;
      }
      /**
       * <code>optional int32 http_port = 8;</code>
       * @param value The httpPort to set.
       * @return This builder for chaining.
       */
      public Builder setHttpPort(int value) {
        bitField0_ |= 0x00000080;
        httpPort_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional int32 http_port = 8;</code>
       * @return This builder for chaining.
       */
      public Builder clearHttpPort() {
        bitField0_ = (bitField0_ & ~0x00000080);
        httpPort_ = 0;
        onChanged();
        return this;
      }
      @java.lang.Override
      public final Builder setUnknownFields(
          final com.google.protobuf.UnknownFieldSet unknownFields) {
        return super.setUnknownFields(unknownFields);
      }

      @java.lang.Override
      public final Builder mergeUnknownFields(
          final com.google.protobuf.UnknownFieldSet unknownFields) {
        return super.mergeUnknownFields(unknownFields);
      }


      // @@protoc_insertion_point(builder_scope:exec.DrillbitEndpoint)
    }

    // @@protoc_insertion_point(class_scope:exec.DrillbitEndpoint)
    private static final org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint DEFAULT_INSTANCE;
    static {
      DEFAULT_INSTANCE = new org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint();
    }

    public static org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint getDefaultInstance() {
      return DEFAULT_INSTANCE;
    }

    @java.lang.Deprecated public static final com.google.protobuf.Parser<DrillbitEndpoint>
        PARSER = new com.google.protobuf.AbstractParser<DrillbitEndpoint>() {
      @java.lang.Override
      public DrillbitEndpoint parsePartialFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        Builder builder = newBuilder();
        try {
          builder.mergeFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          throw e.setUnfinishedMessage(builder.buildPartial());
        } catch (com.google.protobuf.UninitializedMessageException e) {
          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
        } catch (java.io.IOException e) {
          throw new com.google.protobuf.InvalidProtocolBufferException(e)
              .setUnfinishedMessage(builder.buildPartial());
        }
        return builder.buildPartial();
      }
    };

    public static com.google.protobuf.Parser<DrillbitEndpoint> parser() {
      return PARSER;
    }

    @java.lang.Override
    public com.google.protobuf.Parser<DrillbitEndpoint> getParserForType() {
      return PARSER;
    }

    @java.lang.Override
    public org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint getDefaultInstanceForType() {
      return DEFAULT_INSTANCE;
    }

  }

  public interface DrillServiceInstanceOrBuilder extends
      // @@protoc_insertion_point(interface_extends:exec.DrillServiceInstance)
      com.google.protobuf.MessageOrBuilder {

    /**
     * <code>optional string id = 1;</code>
     * @return Whether the id field is set.
     */
    boolean hasId();
    /**
     * <code>optional string id = 1;</code>
     * @return The id.
     */
    java.lang.String getId();
    /**
     * <code>optional string id = 1;</code>
     * @return The bytes for id.
     */
    com.google.protobuf.ByteString
        getIdBytes();

    /**
     * <code>optional int64 registrationTimeUTC = 2;</code>
     * @return Whether the registrationTimeUTC field is set.
     */
    boolean hasRegistrationTimeUTC();
    /**
     * <code>optional int64 registrationTimeUTC = 2;</code>
     * @return The registrationTimeUTC.
     */
    long getRegistrationTimeUTC();

    /**
     * <code>optional .exec.DrillbitEndpoint endpoint = 3;</code>
     * @return Whether the endpoint field is set.
     */
    boolean hasEndpoint();
    /**
     * <code>optional .exec.DrillbitEndpoint endpoint = 3;</code>
     * @return The endpoint.
     */
    org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint getEndpoint();
    /**
     * <code>optional .exec.DrillbitEndpoint endpoint = 3;</code>
     */
    org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpointOrBuilder getEndpointOrBuilder();
  }
  /**
   * Protobuf type {@code exec.DrillServiceInstance}
   */
  public static final class DrillServiceInstance extends
      com.google.protobuf.GeneratedMessageV3 implements
      // @@protoc_insertion_point(message_implements:exec.DrillServiceInstance)
      DrillServiceInstanceOrBuilder {
  private static final long serialVersionUID = 0L;
    // Use DrillServiceInstance.newBuilder() to construct.
    private DrillServiceInstance(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
      super(builder);
    }
    private DrillServiceInstance() {
      id_ = "";
    }

    @java.lang.Override
    @SuppressWarnings({"unused"})
    protected java.lang.Object newInstance(
        UnusedPrivateParameter unused) {
      return new DrillServiceInstance();
    }

    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
    getUnknownFields() {
      return this.unknownFields;
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.drill.exec.proto.CoordinationProtos.internal_static_exec_DrillServiceInstance_descriptor;
    }

    @java.lang.Override
    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.drill.exec.proto.CoordinationProtos.internal_static_exec_DrillServiceInstance_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance.class, org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance.Builder.class);
    }

    private int bitField0_;
    public static final int ID_FIELD_NUMBER = 1;
    private volatile java.lang.Object id_;
    /**
     * <code>optional string id = 1;</code>
     * @return Whether the id field is set.
     */
    @java.lang.Override
    public boolean hasId() {
      return ((bitField0_ & 0x00000001) != 0);
    }
    /**
     * <code>optional string id = 1;</code>
     * @return The id.
     */
    @java.lang.Override
    public java.lang.String getId() {
      java.lang.Object ref = id_;
      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()) {
          id_ = s;
        }
        return s;
      }
    }
    /**
     * <code>optional string id = 1;</code>
     * @return The bytes for id.
     */
    @java.lang.Override
    public com.google.protobuf.ByteString
        getIdBytes() {
      java.lang.Object ref = id_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        id_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    public static final int REGISTRATIONTIMEUTC_FIELD_NUMBER = 2;
    private long registrationTimeUTC_;
    /**
     * <code>optional int64 registrationTimeUTC = 2;</code>
     * @return Whether the registrationTimeUTC field is set.
     */
    @java.lang.Override
    public boolean hasRegistrationTimeUTC() {
      return ((bitField0_ & 0x00000002) != 0);
    }
    /**
     * <code>optional int64 registrationTimeUTC = 2;</code>
     * @return The registrationTimeUTC.
     */
    @java.lang.Override
    public long getRegistrationTimeUTC() {
      return registrationTimeUTC_;
    }

    public static final int ENDPOINT_FIELD_NUMBER = 3;
    private org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint endpoint_;
    /**
     * <code>optional .exec.DrillbitEndpoint endpoint = 3;</code>
     * @return Whether the endpoint field is set.
     */
    @java.lang.Override
    public boolean hasEndpoint() {
      return ((bitField0_ & 0x00000004) != 0);
    }
    /**
     * <code>optional .exec.DrillbitEndpoint endpoint = 3;</code>
     * @return The endpoint.
     */
    @java.lang.Override
    public org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint getEndpoint() {
      return endpoint_ == null ? org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.getDefaultInstance() : endpoint_;
    }
    /**
     * <code>optional .exec.DrillbitEndpoint endpoint = 3;</code>
     */
    @java.lang.Override
    public org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpointOrBuilder getEndpointOrBuilder() {
      return endpoint_ == null ? org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.getDefaultInstance() : endpoint_;
    }

    private byte memoizedIsInitialized = -1;
    @java.lang.Override
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized == 1) return true;
      if (isInitialized == 0) return false;

      memoizedIsInitialized = 1;
      return true;
    }

    @java.lang.Override
    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      if (((bitField0_ & 0x00000001) != 0)) {
        com.google.protobuf.GeneratedMessageV3.writeString(output, 1, id_);
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        output.writeInt64(2, registrationTimeUTC_);
      }
      if (((bitField0_ & 0x00000004) != 0)) {
        output.writeMessage(3, getEndpoint());
      }
      getUnknownFields().writeTo(output);
    }

    @java.lang.Override
    public int getSerializedSize() {
      int size = memoizedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) != 0)) {
        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, id_);
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt64Size(2, registrationTimeUTC_);
      }
      if (((bitField0_ & 0x00000004) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeMessageSize(3, getEndpoint());
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSize = size;
      return size;
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance)) {
        return super.equals(obj);
      }
      org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance other = (org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance) obj;

      if (hasId() != other.hasId()) return false;
      if (hasId()) {
        if (!getId()
            .equals(other.getId())) return false;
      }
      if (hasRegistrationTimeUTC() != other.hasRegistrationTimeUTC()) return false;
      if (hasRegistrationTimeUTC()) {
        if (getRegistrationTimeUTC()
            != other.getRegistrationTimeUTC()) return false;
      }
      if (hasEndpoint() != other.hasEndpoint()) return false;
      if (hasEndpoint()) {
        if (!getEndpoint()
            .equals(other.getEndpoint())) return false;
      }
      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
      return true;
    }

    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptor().hashCode();
      if (hasId()) {
        hash = (37 * hash) + ID_FIELD_NUMBER;
        hash = (53 * hash) + getId().hashCode();
      }
      if (hasRegistrationTimeUTC()) {
        hash = (37 * hash) + REGISTRATIONTIMEUTC_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
            getRegistrationTimeUTC());
      }
      if (hasEndpoint()) {
        hash = (37 * hash) + ENDPOINT_FIELD_NUMBER;
        hash = (53 * hash) + getEndpoint().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance parseFrom(
        java.nio.ByteBuffer data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance parseFrom(
        java.nio.ByteBuffer data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance 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.drill.exec.proto.CoordinationProtos.DrillServiceInstance parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input, extensionRegistry);
    }

    @java.lang.Override
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder() {
      return DEFAULT_INSTANCE.toBuilder();
    }
    public static Builder newBuilder(org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance prototype) {
      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
    }
    @java.lang.Override
    public Builder toBuilder() {
      return this == DEFAULT_INSTANCE
          ? new Builder() : new Builder().mergeFrom(this);
    }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code exec.DrillServiceInstance}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
        // @@protoc_insertion_point(builder_implements:exec.DrillServiceInstance)
        org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstanceOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.drill.exec.proto.CoordinationProtos.internal_static_exec_DrillServiceInstance_descriptor;
      }

      @java.lang.Override
      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.drill.exec.proto.CoordinationProtos.internal_static_exec_DrillServiceInstance_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance.class, org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance.Builder.class);
      }

      // Construct using org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessageV3
                .alwaysUseFieldBuilders) {
          getEndpointFieldBuilder();
        }
      }
      @java.lang.Override
      public Builder clear() {
        super.clear();
        id_ = "";
        bitField0_ = (bitField0_ & ~0x00000001);
        registrationTimeUTC_ = 0L;
        bitField0_ = (bitField0_ & ~0x00000002);
        if (endpointBuilder_ == null) {
          endpoint_ = null;
        } else {
          endpointBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000004);
        return this;
      }

      @java.lang.Override
      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.drill.exec.proto.CoordinationProtos.internal_static_exec_DrillServiceInstance_descriptor;
      }

      @java.lang.Override
      public org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance getDefaultInstanceForType() {
        return org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance.getDefaultInstance();
      }

      @java.lang.Override
      public org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance build() {
        org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      @java.lang.Override
      public org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance buildPartial() {
        org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance result = new org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) != 0)) {
          to_bitField0_ |= 0x00000001;
        }
        result.id_ = id_;
        if (((from_bitField0_ & 0x00000002) != 0)) {
          result.registrationTimeUTC_ = registrationTimeUTC_;
          to_bitField0_ |= 0x00000002;
        }
        if (((from_bitField0_ & 0x00000004) != 0)) {
          if (endpointBuilder_ == null) {
            result.endpoint_ = endpoint_;
          } else {
            result.endpoint_ = endpointBuilder_.build();
          }
          to_bitField0_ |= 0x00000004;
        }
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      @java.lang.Override
      public Builder clone() {
        return super.clone();
      }
      @java.lang.Override
      public Builder setField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          java.lang.Object value) {
        return super.setField(field, value);
      }
      @java.lang.Override
      public Builder clearField(
          com.google.protobuf.Descriptors.FieldDescriptor field) {
        return super.clearField(field);
      }
      @java.lang.Override
      public Builder clearOneof(
          com.google.protobuf.Descriptors.OneofDescriptor oneof) {
        return super.clearOneof(oneof);
      }
      @java.lang.Override
      public Builder setRepeatedField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          int index, java.lang.Object value) {
        return super.setRepeatedField(field, index, value);
      }
      @java.lang.Override
      public Builder addRepeatedField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          java.lang.Object value) {
        return super.addRepeatedField(field, value);
      }
      @java.lang.Override
      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance) {
          return mergeFrom((org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance other) {
        if (other == org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance.getDefaultInstance()) return this;
        if (other.hasId()) {
          bitField0_ |= 0x00000001;
          id_ = other.id_;
          onChanged();
        }
        if (other.hasRegistrationTimeUTC()) {
          setRegistrationTimeUTC(other.getRegistrationTimeUTC());
        }
        if (other.hasEndpoint()) {
          mergeEndpoint(other.getEndpoint());
        }
        this.mergeUnknownFields(other.getUnknownFields());
        onChanged();
        return this;
      }

      @java.lang.Override
      public final boolean isInitialized() {
        return true;
      }

      @java.lang.Override
      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        if (extensionRegistry == null) {
          throw new java.lang.NullPointerException();
        }
        try {
          boolean done = false;
          while (!done) {
            int tag = input.readTag();
            switch (tag) {
              case 0:
                done = true;
                break;
              case 10: {
                id_ = input.readBytes();
                bitField0_ |= 0x00000001;
                break;
              } // case 10
              case 16: {
                registrationTimeUTC_ = input.readInt64();
                bitField0_ |= 0x00000002;
                break;
              } // case 16
              case 26: {
                input.readMessage(
                    getEndpointFieldBuilder().getBuilder(),
                    extensionRegistry);
                bitField0_ |= 0x00000004;
                break;
              } // case 26
              default: {
                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
                  done = true; // was an endgroup tag
                }
                break;
              } // default:
            } // switch (tag)
          } // while (!done)
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          throw e.unwrapIOException();
        } finally {
          onChanged();
        } // finally
        return this;
      }
      private int bitField0_;

      private java.lang.Object id_ = "";
      /**
       * <code>optional string id = 1;</code>
       * @return Whether the id field is set.
       */
      public boolean hasId() {
        return ((bitField0_ & 0x00000001) != 0);
      }
      /**
       * <code>optional string id = 1;</code>
       * @return The id.
       */
      public java.lang.String getId() {
        java.lang.Object ref = id_;
        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()) {
            id_ = s;
          }
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>optional string id = 1;</code>
       * @return The bytes for id.
       */
      public com.google.protobuf.ByteString
          getIdBytes() {
        java.lang.Object ref = id_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          id_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>optional string id = 1;</code>
       * @param value The id to set.
       * @return This builder for chaining.
       */
      public Builder setId(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        id_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional string id = 1;</code>
       * @return This builder for chaining.
       */
      public Builder clearId() {
        bitField0_ = (bitField0_ & ~0x00000001);
        id_ = getDefaultInstance().getId();
        onChanged();
        return this;
      }
      /**
       * <code>optional string id = 1;</code>
       * @param value The bytes for id to set.
       * @return This builder for chaining.
       */
      public Builder setIdBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        id_ = value;
        onChanged();
        return this;
      }

      private long registrationTimeUTC_ ;
      /**
       * <code>optional int64 registrationTimeUTC = 2;</code>
       * @return Whether the registrationTimeUTC field is set.
       */
      @java.lang.Override
      public boolean hasRegistrationTimeUTC() {
        return ((bitField0_ & 0x00000002) != 0);
      }
      /**
       * <code>optional int64 registrationTimeUTC = 2;</code>
       * @return The registrationTimeUTC.
       */
      @java.lang.Override
      public long getRegistrationTimeUTC() {
        return registrationTimeUTC_;
      }
      /**
       * <code>optional int64 registrationTimeUTC = 2;</code>
       * @param value The registrationTimeUTC to set.
       * @return This builder for chaining.
       */
      public Builder setRegistrationTimeUTC(long value) {
        bitField0_ |= 0x00000002;
        registrationTimeUTC_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional int64 registrationTimeUTC = 2;</code>
       * @return This builder for chaining.
       */
      public Builder clearRegistrationTimeUTC() {
        bitField0_ = (bitField0_ & ~0x00000002);
        registrationTimeUTC_ = 0L;
        onChanged();
        return this;
      }

      private org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint endpoint_;
      private com.google.protobuf.SingleFieldBuilderV3<
          org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint, org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.Builder, org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpointOrBuilder> endpointBuilder_;
      /**
       * <code>optional .exec.DrillbitEndpoint endpoint = 3;</code>
       * @return Whether the endpoint field is set.
       */
      public boolean hasEndpoint() {
        return ((bitField0_ & 0x00000004) != 0);
      }
      /**
       * <code>optional .exec.DrillbitEndpoint endpoint = 3;</code>
       * @return The endpoint.
       */
      public org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint getEndpoint() {
        if (endpointBuilder_ == null) {
          return endpoint_ == null ? org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.getDefaultInstance() : endpoint_;
        } else {
          return endpointBuilder_.getMessage();
        }
      }
      /**
       * <code>optional .exec.DrillbitEndpoint endpoint = 3;</code>
       */
      public Builder setEndpoint(org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint value) {
        if (endpointBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          endpoint_ = value;
          onChanged();
        } else {
          endpointBuilder_.setMessage(value);
        }
        bitField0_ |= 0x00000004;
        return this;
      }
      /**
       * <code>optional .exec.DrillbitEndpoint endpoint = 3;</code>
       */
      public Builder setEndpoint(
          org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.Builder builderForValue) {
        if (endpointBuilder_ == null) {
          endpoint_ = builderForValue.build();
          onChanged();
        } else {
          endpointBuilder_.setMessage(builderForValue.build());
        }
        bitField0_ |= 0x00000004;
        return this;
      }
      /**
       * <code>optional .exec.DrillbitEndpoint endpoint = 3;</code>
       */
      public Builder mergeEndpoint(org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint value) {
        if (endpointBuilder_ == null) {
          if (((bitField0_ & 0x00000004) != 0) &&
              endpoint_ != null &&
              endpoint_ != org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.getDefaultInstance()) {
            endpoint_ =
              org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.newBuilder(endpoint_).mergeFrom(value).buildPartial();
          } else {
            endpoint_ = value;
          }
          onChanged();
        } else {
          endpointBuilder_.mergeFrom(value);
        }
        bitField0_ |= 0x00000004;
        return this;
      }
      /**
       * <code>optional .exec.DrillbitEndpoint endpoint = 3;</code>
       */
      public Builder clearEndpoint() {
        if (endpointBuilder_ == null) {
          endpoint_ = null;
          onChanged();
        } else {
          endpointBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000004);
        return this;
      }
      /**
       * <code>optional .exec.DrillbitEndpoint endpoint = 3;</code>
       */
      public org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.Builder getEndpointBuilder() {
        bitField0_ |= 0x00000004;
        onChanged();
        return getEndpointFieldBuilder().getBuilder();
      }
      /**
       * <code>optional .exec.DrillbitEndpoint endpoint = 3;</code>
       */
      public org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpointOrBuilder getEndpointOrBuilder() {
        if (endpointBuilder_ != null) {
          return endpointBuilder_.getMessageOrBuilder();
        } else {
          return endpoint_ == null ?
              org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.getDefaultInstance() : endpoint_;
        }
      }
      /**
       * <code>optional .exec.DrillbitEndpoint endpoint = 3;</code>
       */
      private com.google.protobuf.SingleFieldBuilderV3<
          org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint, org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.Builder, org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpointOrBuilder> 
          getEndpointFieldBuilder() {
        if (endpointBuilder_ == null) {
          endpointBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
              org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint, org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint.Builder, org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpointOrBuilder>(
                  getEndpoint(),
                  getParentForChildren(),
                  isClean());
          endpoint_ = null;
        }
        return endpointBuilder_;
      }
      @java.lang.Override
      public final Builder setUnknownFields(
          final com.google.protobuf.UnknownFieldSet unknownFields) {
        return super.setUnknownFields(unknownFields);
      }

      @java.lang.Override
      public final Builder mergeUnknownFields(
          final com.google.protobuf.UnknownFieldSet unknownFields) {
        return super.mergeUnknownFields(unknownFields);
      }


      // @@protoc_insertion_point(builder_scope:exec.DrillServiceInstance)
    }

    // @@protoc_insertion_point(class_scope:exec.DrillServiceInstance)
    private static final org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance DEFAULT_INSTANCE;
    static {
      DEFAULT_INSTANCE = new org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance();
    }

    public static org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance getDefaultInstance() {
      return DEFAULT_INSTANCE;
    }

    @java.lang.Deprecated public static final com.google.protobuf.Parser<DrillServiceInstance>
        PARSER = new com.google.protobuf.AbstractParser<DrillServiceInstance>() {
      @java.lang.Override
      public DrillServiceInstance parsePartialFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        Builder builder = newBuilder();
        try {
          builder.mergeFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          throw e.setUnfinishedMessage(builder.buildPartial());
        } catch (com.google.protobuf.UninitializedMessageException e) {
          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
        } catch (java.io.IOException e) {
          throw new com.google.protobuf.InvalidProtocolBufferException(e)
              .setUnfinishedMessage(builder.buildPartial());
        }
        return builder.buildPartial();
      }
    };

    public static com.google.protobuf.Parser<DrillServiceInstance> parser() {
      return PARSER;
    }

    @java.lang.Override
    public com.google.protobuf.Parser<DrillServiceInstance> getParserForType() {
      return PARSER;
    }

    @java.lang.Override
    public org.apache.drill.exec.proto.CoordinationProtos.DrillServiceInstance getDefaultInstanceForType() {
      return DEFAULT_INSTANCE;
    }

  }

  public interface RolesOrBuilder extends
      // @@protoc_insertion_point(interface_extends:exec.Roles)
      com.google.protobuf.MessageOrBuilder {

    /**
     * <code>optional bool sql_query = 1 [default = true];</code>
     * @return Whether the sqlQuery field is set.
     */
    boolean hasSqlQuery();
    /**
     * <code>optional bool sql_query = 1 [default = true];</code>
     * @return The sqlQuery.
     */
    boolean getSqlQuery();

    /**
     * <code>optional bool logical_plan = 2 [default = true];</code>
     * @return Whether the logicalPlan field is set.
     */
    boolean hasLogicalPlan();
    /**
     * <code>optional bool logical_plan = 2 [default = true];</code>
     * @return The logicalPlan.
     */
    boolean getLogicalPlan();

    /**
     * <code>optional bool physical_plan = 3 [default = true];</code>
     * @return Whether the physicalPlan field is set.
     */
    boolean hasPhysicalPlan();
    /**
     * <code>optional bool physical_plan = 3 [default = true];</code>
     * @return The physicalPlan.
     */
    boolean getPhysicalPlan();

    /**
     * <code>optional bool java_executor = 4 [default = true];</code>
     * @return Whether the javaExecutor field is set.
     */
    boolean hasJavaExecutor();
    /**
     * <code>optional bool java_executor = 4 [default = true];</code>
     * @return The javaExecutor.
     */
    boolean getJavaExecutor();

    /**
     * <code>optional bool distributed_cache = 5 [default = true];</code>
     * @return Whether the distributedCache field is set.
     */
    boolean hasDistributedCache();
    /**
     * <code>optional bool distributed_cache = 5 [default = true];</code>
     * @return The distributedCache.
     */
    boolean getDistributedCache();
  }
  /**
   * Protobuf type {@code exec.Roles}
   */
  public static final class Roles extends
      com.google.protobuf.GeneratedMessageV3 implements
      // @@protoc_insertion_point(message_implements:exec.Roles)
      RolesOrBuilder {
  private static final long serialVersionUID = 0L;
    // Use Roles.newBuilder() to construct.
    private Roles(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
      super(builder);
    }
    private Roles() {
      sqlQuery_ = true;
      logicalPlan_ = true;
      physicalPlan_ = true;
      javaExecutor_ = true;
      distributedCache_ = true;
    }

    @java.lang.Override
    @SuppressWarnings({"unused"})
    protected java.lang.Object newInstance(
        UnusedPrivateParameter unused) {
      return new Roles();
    }

    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
    getUnknownFields() {
      return this.unknownFields;
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.drill.exec.proto.CoordinationProtos.internal_static_exec_Roles_descriptor;
    }

    @java.lang.Override
    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.drill.exec.proto.CoordinationProtos.internal_static_exec_Roles_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.drill.exec.proto.CoordinationProtos.Roles.class, org.apache.drill.exec.proto.CoordinationProtos.Roles.Builder.class);
    }

    private int bitField0_;
    public static final int SQL_QUERY_FIELD_NUMBER = 1;
    private boolean sqlQuery_;
    /**
     * <code>optional bool sql_query = 1 [default = true];</code>
     * @return Whether the sqlQuery field is set.
     */
    @java.lang.Override
    public boolean hasSqlQuery() {
      return ((bitField0_ & 0x00000001) != 0);
    }
    /**
     * <code>optional bool sql_query = 1 [default = true];</code>
     * @return The sqlQuery.
     */
    @java.lang.Override
    public boolean getSqlQuery() {
      return sqlQuery_;
    }

    public static final int LOGICAL_PLAN_FIELD_NUMBER = 2;
    private boolean logicalPlan_;
    /**
     * <code>optional bool logical_plan = 2 [default = true];</code>
     * @return Whether the logicalPlan field is set.
     */
    @java.lang.Override
    public boolean hasLogicalPlan() {
      return ((bitField0_ & 0x00000002) != 0);
    }
    /**
     * <code>optional bool logical_plan = 2 [default = true];</code>
     * @return The logicalPlan.
     */
    @java.lang.Override
    public boolean getLogicalPlan() {
      return logicalPlan_;
    }

    public static final int PHYSICAL_PLAN_FIELD_NUMBER = 3;
    private boolean physicalPlan_;
    /**
     * <code>optional bool physical_plan = 3 [default = true];</code>
     * @return Whether the physicalPlan field is set.
     */
    @java.lang.Override
    public boolean hasPhysicalPlan() {
      return ((bitField0_ & 0x00000004) != 0);
    }
    /**
     * <code>optional bool physical_plan = 3 [default = true];</code>
     * @return The physicalPlan.
     */
    @java.lang.Override
    public boolean getPhysicalPlan() {
      return physicalPlan_;
    }

    public static final int JAVA_EXECUTOR_FIELD_NUMBER = 4;
    private boolean javaExecutor_;
    /**
     * <code>optional bool java_executor = 4 [default = true];</code>
     * @return Whether the javaExecutor field is set.
     */
    @java.lang.Override
    public boolean hasJavaExecutor() {
      return ((bitField0_ & 0x00000008) != 0);
    }
    /**
     * <code>optional bool java_executor = 4 [default = true];</code>
     * @return The javaExecutor.
     */
    @java.lang.Override
    public boolean getJavaExecutor() {
      return javaExecutor_;
    }

    public static final int DISTRIBUTED_CACHE_FIELD_NUMBER = 5;
    private boolean distributedCache_;
    /**
     * <code>optional bool distributed_cache = 5 [default = true];</code>
     * @return Whether the distributedCache field is set.
     */
    @java.lang.Override
    public boolean hasDistributedCache() {
      return ((bitField0_ & 0x00000010) != 0);
    }
    /**
     * <code>optional bool distributed_cache = 5 [default = true];</code>
     * @return The distributedCache.
     */
    @java.lang.Override
    public boolean getDistributedCache() {
      return distributedCache_;
    }

    private byte memoizedIsInitialized = -1;
    @java.lang.Override
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized == 1) return true;
      if (isInitialized == 0) return false;

      memoizedIsInitialized = 1;
      return true;
    }

    @java.lang.Override
    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      if (((bitField0_ & 0x00000001) != 0)) {
        output.writeBool(1, sqlQuery_);
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        output.writeBool(2, logicalPlan_);
      }
      if (((bitField0_ & 0x00000004) != 0)) {
        output.writeBool(3, physicalPlan_);
      }
      if (((bitField0_ & 0x00000008) != 0)) {
        output.writeBool(4, javaExecutor_);
      }
      if (((bitField0_ & 0x00000010) != 0)) {
        output.writeBool(5, distributedCache_);
      }
      getUnknownFields().writeTo(output);
    }

    @java.lang.Override
    public int getSerializedSize() {
      int size = memoizedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBoolSize(1, sqlQuery_);
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBoolSize(2, logicalPlan_);
      }
      if (((bitField0_ & 0x00000004) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBoolSize(3, physicalPlan_);
      }
      if (((bitField0_ & 0x00000008) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBoolSize(4, javaExecutor_);
      }
      if (((bitField0_ & 0x00000010) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBoolSize(5, distributedCache_);
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSize = size;
      return size;
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.drill.exec.proto.CoordinationProtos.Roles)) {
        return super.equals(obj);
      }
      org.apache.drill.exec.proto.CoordinationProtos.Roles other = (org.apache.drill.exec.proto.CoordinationProtos.Roles) obj;

      if (hasSqlQuery() != other.hasSqlQuery()) return false;
      if (hasSqlQuery()) {
        if (getSqlQuery()
            != other.getSqlQuery()) return false;
      }
      if (hasLogicalPlan() != other.hasLogicalPlan()) return false;
      if (hasLogicalPlan()) {
        if (getLogicalPlan()
            != other.getLogicalPlan()) return false;
      }
      if (hasPhysicalPlan() != other.hasPhysicalPlan()) return false;
      if (hasPhysicalPlan()) {
        if (getPhysicalPlan()
            != other.getPhysicalPlan()) return false;
      }
      if (hasJavaExecutor() != other.hasJavaExecutor()) return false;
      if (hasJavaExecutor()) {
        if (getJavaExecutor()
            != other.getJavaExecutor()) return false;
      }
      if (hasDistributedCache() != other.hasDistributedCache()) return false;
      if (hasDistributedCache()) {
        if (getDistributedCache()
            != other.getDistributedCache()) return false;
      }
      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
      return true;
    }

    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptor().hashCode();
      if (hasSqlQuery()) {
        hash = (37 * hash) + SQL_QUERY_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(
            getSqlQuery());
      }
      if (hasLogicalPlan()) {
        hash = (37 * hash) + LOGICAL_PLAN_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(
            getLogicalPlan());
      }
      if (hasPhysicalPlan()) {
        hash = (37 * hash) + PHYSICAL_PLAN_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(
            getPhysicalPlan());
      }
      if (hasJavaExecutor()) {
        hash = (37 * hash) + JAVA_EXECUTOR_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(
            getJavaExecutor());
      }
      if (hasDistributedCache()) {
        hash = (37 * hash) + DISTRIBUTED_CACHE_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(
            getDistributedCache());
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.drill.exec.proto.CoordinationProtos.Roles parseFrom(
        java.nio.ByteBuffer data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.Roles parseFrom(
        java.nio.ByteBuffer data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.Roles parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.Roles 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.drill.exec.proto.CoordinationProtos.Roles parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.Roles parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.Roles parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.Roles parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.Roles parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.Roles parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.Roles parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.CoordinationProtos.Roles parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input, extensionRegistry);
    }

    @java.lang.Override
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder() {
      return DEFAULT_INSTANCE.toBuilder();
    }
    public static Builder newBuilder(org.apache.drill.exec.proto.CoordinationProtos.Roles prototype) {
      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
    }
    @java.lang.Override
    public Builder toBuilder() {
      return this == DEFAULT_INSTANCE
          ? new Builder() : new Builder().mergeFrom(this);
    }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code exec.Roles}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
        // @@protoc_insertion_point(builder_implements:exec.Roles)
        org.apache.drill.exec.proto.CoordinationProtos.RolesOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.drill.exec.proto.CoordinationProtos.internal_static_exec_Roles_descriptor;
      }

      @java.lang.Override
      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.drill.exec.proto.CoordinationProtos.internal_static_exec_Roles_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.drill.exec.proto.CoordinationProtos.Roles.class, org.apache.drill.exec.proto.CoordinationProtos.Roles.Builder.class);
      }

      // Construct using org.apache.drill.exec.proto.CoordinationProtos.Roles.newBuilder()
      private Builder() {

      }

      private Builder(
          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
        super(parent);

      }
      @java.lang.Override
      public Builder clear() {
        super.clear();
        sqlQuery_ = true;
        bitField0_ = (bitField0_ & ~0x00000001);
        logicalPlan_ = true;
        bitField0_ = (bitField0_ & ~0x00000002);
        physicalPlan_ = true;
        bitField0_ = (bitField0_ & ~0x00000004);
        javaExecutor_ = true;
        bitField0_ = (bitField0_ & ~0x00000008);
        distributedCache_ = true;
        bitField0_ = (bitField0_ & ~0x00000010);
        return this;
      }

      @java.lang.Override
      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.drill.exec.proto.CoordinationProtos.internal_static_exec_Roles_descriptor;
      }

      @java.lang.Override
      public org.apache.drill.exec.proto.CoordinationProtos.Roles getDefaultInstanceForType() {
        return org.apache.drill.exec.proto.CoordinationProtos.Roles.getDefaultInstance();
      }

      @java.lang.Override
      public org.apache.drill.exec.proto.CoordinationProtos.Roles build() {
        org.apache.drill.exec.proto.CoordinationProtos.Roles result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      @java.lang.Override
      public org.apache.drill.exec.proto.CoordinationProtos.Roles buildPartial() {
        org.apache.drill.exec.proto.CoordinationProtos.Roles result = new org.apache.drill.exec.proto.CoordinationProtos.Roles(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) != 0)) {
          to_bitField0_ |= 0x00000001;
        }
        result.sqlQuery_ = sqlQuery_;
        if (((from_bitField0_ & 0x00000002) != 0)) {
          to_bitField0_ |= 0x00000002;
        }
        result.logicalPlan_ = logicalPlan_;
        if (((from_bitField0_ & 0x00000004) != 0)) {
          to_bitField0_ |= 0x00000004;
        }
        result.physicalPlan_ = physicalPlan_;
        if (((from_bitField0_ & 0x00000008) != 0)) {
          to_bitField0_ |= 0x00000008;
        }
        result.javaExecutor_ = javaExecutor_;
        if (((from_bitField0_ & 0x00000010) != 0)) {
          to_bitField0_ |= 0x00000010;
        }
        result.distributedCache_ = distributedCache_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      @java.lang.Override
      public Builder clone() {
        return super.clone();
      }
      @java.lang.Override
      public Builder setField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          java.lang.Object value) {
        return super.setField(field, value);
      }
      @java.lang.Override
      public Builder clearField(
          com.google.protobuf.Descriptors.FieldDescriptor field) {
        return super.clearField(field);
      }
      @java.lang.Override
      public Builder clearOneof(
          com.google.protobuf.Descriptors.OneofDescriptor oneof) {
        return super.clearOneof(oneof);
      }
      @java.lang.Override
      public Builder setRepeatedField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          int index, java.lang.Object value) {
        return super.setRepeatedField(field, index, value);
      }
      @java.lang.Override
      public Builder addRepeatedField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          java.lang.Object value) {
        return super.addRepeatedField(field, value);
      }
      @java.lang.Override
      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.drill.exec.proto.CoordinationProtos.Roles) {
          return mergeFrom((org.apache.drill.exec.proto.CoordinationProtos.Roles)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.drill.exec.proto.CoordinationProtos.Roles other) {
        if (other == org.apache.drill.exec.proto.CoordinationProtos.Roles.getDefaultInstance()) return this;
        if (other.hasSqlQuery()) {
          setSqlQuery(other.getSqlQuery());
        }
        if (other.hasLogicalPlan()) {
          setLogicalPlan(other.getLogicalPlan());
        }
        if (other.hasPhysicalPlan()) {
          setPhysicalPlan(other.getPhysicalPlan());
        }
        if (other.hasJavaExecutor()) {
          setJavaExecutor(other.getJavaExecutor());
        }
        if (other.hasDistributedCache()) {
          setDistributedCache(other.getDistributedCache());
        }
        this.mergeUnknownFields(other.getUnknownFields());
        onChanged();
        return this;
      }

      @java.lang.Override
      public final boolean isInitialized() {
        return true;
      }

      @java.lang.Override
      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        if (extensionRegistry == null) {
          throw new java.lang.NullPointerException();
        }
        try {
          boolean done = false;
          while (!done) {
            int tag = input.readTag();
            switch (tag) {
              case 0:
                done = true;
                break;
              case 8: {
                sqlQuery_ = input.readBool();
                bitField0_ |= 0x00000001;
                break;
              } // case 8
              case 16: {
                logicalPlan_ = input.readBool();
                bitField0_ |= 0x00000002;
                break;
              } // case 16
              case 24: {
                physicalPlan_ = input.readBool();
                bitField0_ |= 0x00000004;
                break;
              } // case 24
              case 32: {
                javaExecutor_ = input.readBool();
                bitField0_ |= 0x00000008;
                break;
              } // case 32
              case 40: {
                distributedCache_ = input.readBool();
                bitField0_ |= 0x00000010;
                break;
              } // case 40
              default: {
                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
                  done = true; // was an endgroup tag
                }
                break;
              } // default:
            } // switch (tag)
          } // while (!done)
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          throw e.unwrapIOException();
        } finally {
          onChanged();
        } // finally
        return this;
      }
      private int bitField0_;

      private boolean sqlQuery_ = true;
      /**
       * <code>optional bool sql_query = 1 [default = true];</code>
       * @return Whether the sqlQuery field is set.
       */
      @java.lang.Override
      public boolean hasSqlQuery() {
        return ((bitField0_ & 0x00000001) != 0);
      }
      /**
       * <code>optional bool sql_query = 1 [default = true];</code>
       * @return The sqlQuery.
       */
      @java.lang.Override
      public boolean getSqlQuery() {
        return sqlQuery_;
      }
      /**
       * <code>optional bool sql_query = 1 [default = true];</code>
       * @param value The sqlQuery to set.
       * @return This builder for chaining.
       */
      public Builder setSqlQuery(boolean value) {
        bitField0_ |= 0x00000001;
        sqlQuery_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional bool sql_query = 1 [default = true];</code>
       * @return This builder for chaining.
       */
      public Builder clearSqlQuery() {
        bitField0_ = (bitField0_ & ~0x00000001);
        sqlQuery_ = true;
        onChanged();
        return this;
      }

      private boolean logicalPlan_ = true;
      /**
       * <code>optional bool logical_plan = 2 [default = true];</code>
       * @return Whether the logicalPlan field is set.
       */
      @java.lang.Override
      public boolean hasLogicalPlan() {
        return ((bitField0_ & 0x00000002) != 0);
      }
      /**
       * <code>optional bool logical_plan = 2 [default = true];</code>
       * @return The logicalPlan.
       */
      @java.lang.Override
      public boolean getLogicalPlan() {
        return logicalPlan_;
      }
      /**
       * <code>optional bool logical_plan = 2 [default = true];</code>
       * @param value The logicalPlan to set.
       * @return This builder for chaining.
       */
      public Builder setLogicalPlan(boolean value) {
        bitField0_ |= 0x00000002;
        logicalPlan_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional bool logical_plan = 2 [default = true];</code>
       * @return This builder for chaining.
       */
      public Builder clearLogicalPlan() {
        bitField0_ = (bitField0_ & ~0x00000002);
        logicalPlan_ = true;
        onChanged();
        return this;
      }

      private boolean physicalPlan_ = true;
      /**
       * <code>optional bool physical_plan = 3 [default = true];</code>
       * @return Whether the physicalPlan field is set.
       */
      @java.lang.Override
      public boolean hasPhysicalPlan() {
        return ((bitField0_ & 0x00000004) != 0);
      }
      /**
       * <code>optional bool physical_plan = 3 [default = true];</code>
       * @return The physicalPlan.
       */
      @java.lang.Override
      public boolean getPhysicalPlan() {
        return physicalPlan_;
      }
      /**
       * <code>optional bool physical_plan = 3 [default = true];</code>
       * @param value The physicalPlan to set.
       * @return This builder for chaining.
       */
      public Builder setPhysicalPlan(boolean value) {
        bitField0_ |= 0x00000004;
        physicalPlan_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional bool physical_plan = 3 [default = true];</code>
       * @return This builder for chaining.
       */
      public Builder clearPhysicalPlan() {
        bitField0_ = (bitField0_ & ~0x00000004);
        physicalPlan_ = true;
        onChanged();
        return this;
      }

      private boolean javaExecutor_ = true;
      /**
       * <code>optional bool java_executor = 4 [default = true];</code>
       * @return Whether the javaExecutor field is set.
       */
      @java.lang.Override
      public boolean hasJavaExecutor() {
        return ((bitField0_ & 0x00000008) != 0);
      }
      /**
       * <code>optional bool java_executor = 4 [default = true];</code>
       * @return The javaExecutor.
       */
      @java.lang.Override
      public boolean getJavaExecutor() {
        return javaExecutor_;
      }
      /**
       * <code>optional bool java_executor = 4 [default = true];</code>
       * @param value The javaExecutor to set.
       * @return This builder for chaining.
       */
      public Builder setJavaExecutor(boolean value) {
        bitField0_ |= 0x00000008;
        javaExecutor_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional bool java_executor = 4 [default = true];</code>
       * @return This builder for chaining.
       */
      public Builder clearJavaExecutor() {
        bitField0_ = (bitField0_ & ~0x00000008);
        javaExecutor_ = true;
        onChanged();
        return this;
      }

      private boolean distributedCache_ = true;
      /**
       * <code>optional bool distributed_cache = 5 [default = true];</code>
       * @return Whether the distributedCache field is set.
       */
      @java.lang.Override
      public boolean hasDistributedCache() {
        return ((bitField0_ & 0x00000010) != 0);
      }
      /**
       * <code>optional bool distributed_cache = 5 [default = true];</code>
       * @return The distributedCache.
       */
      @java.lang.Override
      public boolean getDistributedCache() {
        return distributedCache_;
      }
      /**
       * <code>optional bool distributed_cache = 5 [default = true];</code>
       * @param value The distributedCache to set.
       * @return This builder for chaining.
       */
      public Builder setDistributedCache(boolean value) {
        bitField0_ |= 0x00000010;
        distributedCache_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional bool distributed_cache = 5 [default = true];</code>
       * @return This builder for chaining.
       */
      public Builder clearDistributedCache() {
        bitField0_ = (bitField0_ & ~0x00000010);
        distributedCache_ = true;
        onChanged();
        return this;
      }
      @java.lang.Override
      public final Builder setUnknownFields(
          final com.google.protobuf.UnknownFieldSet unknownFields) {
        return super.setUnknownFields(unknownFields);
      }

      @java.lang.Override
      public final Builder mergeUnknownFields(
          final com.google.protobuf.UnknownFieldSet unknownFields) {
        return super.mergeUnknownFields(unknownFields);
      }


      // @@protoc_insertion_point(builder_scope:exec.Roles)
    }

    // @@protoc_insertion_point(class_scope:exec.Roles)
    private static final org.apache.drill.exec.proto.CoordinationProtos.Roles DEFAULT_INSTANCE;
    static {
      DEFAULT_INSTANCE = new org.apache.drill.exec.proto.CoordinationProtos.Roles();
    }

    public static org.apache.drill.exec.proto.CoordinationProtos.Roles getDefaultInstance() {
      return DEFAULT_INSTANCE;
    }

    @java.lang.Deprecated public static final com.google.protobuf.Parser<Roles>
        PARSER = new com.google.protobuf.AbstractParser<Roles>() {
      @java.lang.Override
      public Roles parsePartialFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        Builder builder = newBuilder();
        try {
          builder.mergeFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          throw e.setUnfinishedMessage(builder.buildPartial());
        } catch (com.google.protobuf.UninitializedMessageException e) {
          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
        } catch (java.io.IOException e) {
          throw new com.google.protobuf.InvalidProtocolBufferException(e)
              .setUnfinishedMessage(builder.buildPartial());
        }
        return builder.buildPartial();
      }
    };

    public static com.google.protobuf.Parser<Roles> parser() {
      return PARSER;
    }

    @java.lang.Override
    public com.google.protobuf.Parser<Roles> getParserForType() {
      return PARSER;
    }

    @java.lang.Override
    public org.apache.drill.exec.proto.CoordinationProtos.Roles getDefaultInstanceForType() {
      return DEFAULT_INSTANCE;
    }

  }

  private static final com.google.protobuf.Descriptors.Descriptor
    internal_static_exec_DrillbitEndpoint_descriptor;
  private static final 
    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
      internal_static_exec_DrillbitEndpoint_fieldAccessorTable;
  private static final com.google.protobuf.Descriptors.Descriptor
    internal_static_exec_DrillServiceInstance_descriptor;
  private static final 
    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
      internal_static_exec_DrillServiceInstance_fieldAccessorTable;
  private static final com.google.protobuf.Descriptors.Descriptor
    internal_static_exec_Roles_descriptor;
  private static final 
    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
      internal_static_exec_Roles_fieldAccessorTable;

  public static com.google.protobuf.Descriptors.FileDescriptor
      getDescriptor() {
    return descriptor;
  }
  private static  com.google.protobuf.Descriptors.FileDescriptor
      descriptor;
  static {
    java.lang.String[] descriptorData = {
      "\n\022Coordination.proto\022\004exec\"\212\002\n\020DrillbitE" +
      "ndpoint\022\017\n\007address\030\001 \001(\t\022\021\n\tuser_port\030\002 " +
      "\001(\005\022\024\n\014control_port\030\003 \001(\005\022\021\n\tdata_port\030\004" +
      " \001(\005\022\032\n\005roles\030\005 \001(\0132\013.exec.Roles\022\017\n\007vers" +
      "ion\030\006 \001(\t\022+\n\005state\030\007 \001(\0162\034.exec.Drillbit" +
      "Endpoint.State\022\021\n\thttp_port\030\010 \001(\005\"<\n\005Sta" +
      "te\022\013\n\007STARTUP\020\000\022\n\n\006ONLINE\020\001\022\r\n\tQUIESCENT" +
      "\020\002\022\013\n\007OFFLINE\020\003\"i\n\024DrillServiceInstance\022" +
      "\n\n\002id\030\001 \001(\t\022\033\n\023registrationTimeUTC\030\002 \001(\003" +
      "\022(\n\010endpoint\030\003 \001(\0132\026.exec.DrillbitEndpoi" +
      "nt\"\227\001\n\005Roles\022\027\n\tsql_query\030\001 \001(\010:\004true\022\032\n" +
      "\014logical_plan\030\002 \001(\010:\004true\022\033\n\rphysical_pl" +
      "an\030\003 \001(\010:\004true\022\033\n\rjava_executor\030\004 \001(\010:\004t" +
      "rue\022\037\n\021distributed_cache\030\005 \001(\010:\004trueB3\n\033" +
      "org.apache.drill.exec.protoB\022Coordinatio" +
      "nProtosH\001"
    };
    descriptor = com.google.protobuf.Descriptors.FileDescriptor
      .internalBuildGeneratedFileFrom(descriptorData,
        new com.google.protobuf.Descriptors.FileDescriptor[] {
        });
    internal_static_exec_DrillbitEndpoint_descriptor =
      getDescriptor().getMessageTypes().get(0);
    internal_static_exec_DrillbitEndpoint_fieldAccessorTable = new
      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
        internal_static_exec_DrillbitEndpoint_descriptor,
        new java.lang.String[] { "Address", "UserPort", "ControlPort", "DataPort", "Roles", "Version", "State", "HttpPort", });
    internal_static_exec_DrillServiceInstance_descriptor =
      getDescriptor().getMessageTypes().get(1);
    internal_static_exec_DrillServiceInstance_fieldAccessorTable = new
      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
        internal_static_exec_DrillServiceInstance_descriptor,
        new java.lang.String[] { "Id", "RegistrationTimeUTC", "Endpoint", });
    internal_static_exec_Roles_descriptor =
      getDescriptor().getMessageTypes().get(2);
    internal_static_exec_Roles_fieldAccessorTable = new
      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
        internal_static_exec_Roles_descriptor,
        new java.lang.String[] { "SqlQuery", "LogicalPlan", "PhysicalPlan", "JavaExecutor", "DistributedCache", });
  }

  // @@protoc_insertion_point(outer_class_scope)
}
