/*
 * 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: BitData.proto

package org.apache.drill.exec.proto;

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

  public static void registerAllExtensions(
      com.google.protobuf.ExtensionRegistry registry) {
    registerAllExtensions(
        (com.google.protobuf.ExtensionRegistryLite) registry);
  }
  /**
   * Protobuf enum {@code exec.bit.data.RpcType}
   */
  public enum RpcType
      implements com.google.protobuf.ProtocolMessageEnum {
    /**
     * <code>HANDSHAKE = 0;</code>
     */
    HANDSHAKE(0),
    /**
     * <code>ACK = 1;</code>
     */
    ACK(1),
    /**
     * <code>GOODBYE = 2;</code>
     */
    GOODBYE(2),
    /**
     * <pre>
     * send record batch, returns Ack
     * </pre>
     *
     * <code>REQ_RECORD_BATCH = 3;</code>
     */
    REQ_RECORD_BATCH(3),
    /**
     * <pre>
     * both bit request and response
     * </pre>
     *
     * <code>SASL_MESSAGE = 4;</code>
     */
    SASL_MESSAGE(4),
    /**
     * <pre>
     * send runtime filter data from HashJoin to Foreman, from Foreman to Scan nodes.
     * </pre>
     *
     * <code>REQ_RUNTIME_FILTER = 5;</code>
     */
    REQ_RUNTIME_FILTER(5),
    /**
     * <pre>
     * a ack for data tunnel,with a runtime suggested credit as a response.
     * </pre>
     *
     * <code>DATA_ACK_WITH_CREDIT = 6;</code>
     */
    DATA_ACK_WITH_CREDIT(6),
    ;

    /**
     * <code>HANDSHAKE = 0;</code>
     */
    public static final int HANDSHAKE_VALUE = 0;
    /**
     * <code>ACK = 1;</code>
     */
    public static final int ACK_VALUE = 1;
    /**
     * <code>GOODBYE = 2;</code>
     */
    public static final int GOODBYE_VALUE = 2;
    /**
     * <pre>
     * send record batch, returns Ack
     * </pre>
     *
     * <code>REQ_RECORD_BATCH = 3;</code>
     */
    public static final int REQ_RECORD_BATCH_VALUE = 3;
    /**
     * <pre>
     * both bit request and response
     * </pre>
     *
     * <code>SASL_MESSAGE = 4;</code>
     */
    public static final int SASL_MESSAGE_VALUE = 4;
    /**
     * <pre>
     * send runtime filter data from HashJoin to Foreman, from Foreman to Scan nodes.
     * </pre>
     *
     * <code>REQ_RUNTIME_FILTER = 5;</code>
     */
    public static final int REQ_RUNTIME_FILTER_VALUE = 5;
    /**
     * <pre>
     * a ack for data tunnel,with a runtime suggested credit as a response.
     * </pre>
     *
     * <code>DATA_ACK_WITH_CREDIT = 6;</code>
     */
    public static final int DATA_ACK_WITH_CREDIT_VALUE = 6;


    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 RpcType 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 RpcType forNumber(int value) {
      switch (value) {
        case 0: return HANDSHAKE;
        case 1: return ACK;
        case 2: return GOODBYE;
        case 3: return REQ_RECORD_BATCH;
        case 4: return SASL_MESSAGE;
        case 5: return REQ_RUNTIME_FILTER;
        case 6: return DATA_ACK_WITH_CREDIT;
        default: return null;
      }
    }

    public static com.google.protobuf.Internal.EnumLiteMap<RpcType>
        internalGetValueMap() {
      return internalValueMap;
    }
    private static final com.google.protobuf.Internal.EnumLiteMap<
        RpcType> internalValueMap =
          new com.google.protobuf.Internal.EnumLiteMap<RpcType>() {
            public RpcType findValueByNumber(int number) {
              return RpcType.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.BitData.getDescriptor().getEnumTypes().get(0);
    }

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

    public static RpcType 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 RpcType(int value) {
      this.value = value;
    }

    // @@protoc_insertion_point(enum_scope:exec.bit.data.RpcType)
  }

  public interface BitClientHandshakeOrBuilder extends
      // @@protoc_insertion_point(interface_extends:exec.bit.data.BitClientHandshake)
      com.google.protobuf.MessageOrBuilder {

    /**
     * <code>optional int32 rpc_version = 1;</code>
     * @return Whether the rpcVersion field is set.
     */
    boolean hasRpcVersion();
    /**
     * <code>optional int32 rpc_version = 1;</code>
     * @return The rpcVersion.
     */
    int getRpcVersion();

    /**
     * <code>optional .exec.shared.RpcChannel channel = 2 [default = BIT_DATA];</code>
     * @return Whether the channel field is set.
     */
    boolean hasChannel();
    /**
     * <code>optional .exec.shared.RpcChannel channel = 2 [default = BIT_DATA];</code>
     * @return The channel.
     */
    org.apache.drill.exec.proto.UserBitShared.RpcChannel getChannel();
  }
  /**
   * Protobuf type {@code exec.bit.data.BitClientHandshake}
   */
  public static final class BitClientHandshake extends
      com.google.protobuf.GeneratedMessageV3 implements
      // @@protoc_insertion_point(message_implements:exec.bit.data.BitClientHandshake)
      BitClientHandshakeOrBuilder {
  private static final long serialVersionUID = 0L;
    // Use BitClientHandshake.newBuilder() to construct.
    private BitClientHandshake(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
      super(builder);
    }
    private BitClientHandshake() {
      channel_ = 1;
    }

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

    @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.BitData.internal_static_exec_bit_data_BitClientHandshake_descriptor;
    }

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

    private int bitField0_;
    public static final int RPC_VERSION_FIELD_NUMBER = 1;
    private int rpcVersion_;
    /**
     * <code>optional int32 rpc_version = 1;</code>
     * @return Whether the rpcVersion field is set.
     */
    @java.lang.Override
    public boolean hasRpcVersion() {
      return ((bitField0_ & 0x00000001) != 0);
    }
    /**
     * <code>optional int32 rpc_version = 1;</code>
     * @return The rpcVersion.
     */
    @java.lang.Override
    public int getRpcVersion() {
      return rpcVersion_;
    }

    public static final int CHANNEL_FIELD_NUMBER = 2;
    private int channel_;
    /**
     * <code>optional .exec.shared.RpcChannel channel = 2 [default = BIT_DATA];</code>
     * @return Whether the channel field is set.
     */
    @java.lang.Override public boolean hasChannel() {
      return ((bitField0_ & 0x00000002) != 0);
    }
    /**
     * <code>optional .exec.shared.RpcChannel channel = 2 [default = BIT_DATA];</code>
     * @return The channel.
     */
    @java.lang.Override public org.apache.drill.exec.proto.UserBitShared.RpcChannel getChannel() {
      @SuppressWarnings("deprecation")
      org.apache.drill.exec.proto.UserBitShared.RpcChannel result = org.apache.drill.exec.proto.UserBitShared.RpcChannel.valueOf(channel_);
      return result == null ? org.apache.drill.exec.proto.UserBitShared.RpcChannel.BIT_DATA : result;
    }

    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.writeInt32(1, rpcVersion_);
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        output.writeEnum(2, channel_);
      }
      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
          .computeInt32Size(1, rpcVersion_);
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeEnumSize(2, channel_);
      }
      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.BitData.BitClientHandshake)) {
        return super.equals(obj);
      }
      org.apache.drill.exec.proto.BitData.BitClientHandshake other = (org.apache.drill.exec.proto.BitData.BitClientHandshake) obj;

      if (hasRpcVersion() != other.hasRpcVersion()) return false;
      if (hasRpcVersion()) {
        if (getRpcVersion()
            != other.getRpcVersion()) return false;
      }
      if (hasChannel() != other.hasChannel()) return false;
      if (hasChannel()) {
        if (channel_ != other.channel_) 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 (hasRpcVersion()) {
        hash = (37 * hash) + RPC_VERSION_FIELD_NUMBER;
        hash = (53 * hash) + getRpcVersion();
      }
      if (hasChannel()) {
        hash = (37 * hash) + CHANNEL_FIELD_NUMBER;
        hash = (53 * hash) + channel_;
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.drill.exec.proto.BitData.BitClientHandshake parseFrom(
        java.nio.ByteBuffer data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.BitData.BitClientHandshake 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.BitData.BitClientHandshake parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.BitData.BitClientHandshake 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.BitData.BitClientHandshake parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.BitData.BitClientHandshake 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.BitData.BitClientHandshake parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.BitData.BitClientHandshake 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.BitData.BitClientHandshake parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.BitData.BitClientHandshake 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.BitData.BitClientHandshake 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.BitData.BitClientHandshake 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.BitData.BitClientHandshake 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.bit.data.BitClientHandshake}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
        // @@protoc_insertion_point(builder_implements:exec.bit.data.BitClientHandshake)
        org.apache.drill.exec.proto.BitData.BitClientHandshakeOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.drill.exec.proto.BitData.internal_static_exec_bit_data_BitClientHandshake_descriptor;
      }

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

      // Construct using org.apache.drill.exec.proto.BitData.BitClientHandshake.newBuilder()
      private Builder() {

      }

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

      }
      @java.lang.Override
      public Builder clear() {
        super.clear();
        rpcVersion_ = 0;
        bitField0_ = (bitField0_ & ~0x00000001);
        channel_ = 1;
        bitField0_ = (bitField0_ & ~0x00000002);
        return this;
      }

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

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

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

      @java.lang.Override
      public org.apache.drill.exec.proto.BitData.BitClientHandshake buildPartial() {
        org.apache.drill.exec.proto.BitData.BitClientHandshake result = new org.apache.drill.exec.proto.BitData.BitClientHandshake(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) != 0)) {
          result.rpcVersion_ = rpcVersion_;
          to_bitField0_ |= 0x00000001;
        }
        if (((from_bitField0_ & 0x00000002) != 0)) {
          to_bitField0_ |= 0x00000002;
        }
        result.channel_ = channel_;
        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.BitData.BitClientHandshake) {
          return mergeFrom((org.apache.drill.exec.proto.BitData.BitClientHandshake)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.drill.exec.proto.BitData.BitClientHandshake other) {
        if (other == org.apache.drill.exec.proto.BitData.BitClientHandshake.getDefaultInstance()) return this;
        if (other.hasRpcVersion()) {
          setRpcVersion(other.getRpcVersion());
        }
        if (other.hasChannel()) {
          setChannel(other.getChannel());
        }
        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: {
                rpcVersion_ = input.readInt32();
                bitField0_ |= 0x00000001;
                break;
              } // case 8
              case 16: {
                int tmpRaw = input.readEnum();
                org.apache.drill.exec.proto.UserBitShared.RpcChannel tmpValue =
                    org.apache.drill.exec.proto.UserBitShared.RpcChannel.forNumber(tmpRaw);
                if (tmpValue == null) {
                  mergeUnknownVarintField(2, tmpRaw);
                } else {
                  channel_ = tmpRaw;
                  bitField0_ |= 0x00000002;
                }
                break;
              } // case 16
              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 int rpcVersion_ ;
      /**
       * <code>optional int32 rpc_version = 1;</code>
       * @return Whether the rpcVersion field is set.
       */
      @java.lang.Override
      public boolean hasRpcVersion() {
        return ((bitField0_ & 0x00000001) != 0);
      }
      /**
       * <code>optional int32 rpc_version = 1;</code>
       * @return The rpcVersion.
       */
      @java.lang.Override
      public int getRpcVersion() {
        return rpcVersion_;
      }
      /**
       * <code>optional int32 rpc_version = 1;</code>
       * @param value The rpcVersion to set.
       * @return This builder for chaining.
       */
      public Builder setRpcVersion(int value) {
        bitField0_ |= 0x00000001;
        rpcVersion_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional int32 rpc_version = 1;</code>
       * @return This builder for chaining.
       */
      public Builder clearRpcVersion() {
        bitField0_ = (bitField0_ & ~0x00000001);
        rpcVersion_ = 0;
        onChanged();
        return this;
      }

      private int channel_ = 1;
      /**
       * <code>optional .exec.shared.RpcChannel channel = 2 [default = BIT_DATA];</code>
       * @return Whether the channel field is set.
       */
      @java.lang.Override public boolean hasChannel() {
        return ((bitField0_ & 0x00000002) != 0);
      }
      /**
       * <code>optional .exec.shared.RpcChannel channel = 2 [default = BIT_DATA];</code>
       * @return The channel.
       */
      @java.lang.Override
      public org.apache.drill.exec.proto.UserBitShared.RpcChannel getChannel() {
        @SuppressWarnings("deprecation")
        org.apache.drill.exec.proto.UserBitShared.RpcChannel result = org.apache.drill.exec.proto.UserBitShared.RpcChannel.valueOf(channel_);
        return result == null ? org.apache.drill.exec.proto.UserBitShared.RpcChannel.BIT_DATA : result;
      }
      /**
       * <code>optional .exec.shared.RpcChannel channel = 2 [default = BIT_DATA];</code>
       * @param value The channel to set.
       * @return This builder for chaining.
       */
      public Builder setChannel(org.apache.drill.exec.proto.UserBitShared.RpcChannel value) {
        if (value == null) {
          throw new NullPointerException();
        }
        bitField0_ |= 0x00000002;
        channel_ = value.getNumber();
        onChanged();
        return this;
      }
      /**
       * <code>optional .exec.shared.RpcChannel channel = 2 [default = BIT_DATA];</code>
       * @return This builder for chaining.
       */
      public Builder clearChannel() {
        bitField0_ = (bitField0_ & ~0x00000002);
        channel_ = 1;
        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.bit.data.BitClientHandshake)
    }

    // @@protoc_insertion_point(class_scope:exec.bit.data.BitClientHandshake)
    private static final org.apache.drill.exec.proto.BitData.BitClientHandshake DEFAULT_INSTANCE;
    static {
      DEFAULT_INSTANCE = new org.apache.drill.exec.proto.BitData.BitClientHandshake();
    }

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

    @java.lang.Deprecated public static final com.google.protobuf.Parser<BitClientHandshake>
        PARSER = new com.google.protobuf.AbstractParser<BitClientHandshake>() {
      @java.lang.Override
      public BitClientHandshake 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<BitClientHandshake> parser() {
      return PARSER;
    }

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

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

  }

  public interface BitServerHandshakeOrBuilder extends
      // @@protoc_insertion_point(interface_extends:exec.bit.data.BitServerHandshake)
      com.google.protobuf.MessageOrBuilder {

    /**
     * <code>optional int32 rpc_version = 1;</code>
     * @return Whether the rpcVersion field is set.
     */
    boolean hasRpcVersion();
    /**
     * <code>optional int32 rpc_version = 1;</code>
     * @return The rpcVersion.
     */
    int getRpcVersion();

    /**
     * <code>repeated string authenticationMechanisms = 2;</code>
     * @return A list containing the authenticationMechanisms.
     */
    java.util.List<java.lang.String>
        getAuthenticationMechanismsList();
    /**
     * <code>repeated string authenticationMechanisms = 2;</code>
     * @return The count of authenticationMechanisms.
     */
    int getAuthenticationMechanismsCount();
    /**
     * <code>repeated string authenticationMechanisms = 2;</code>
     * @param index The index of the element to return.
     * @return The authenticationMechanisms at the given index.
     */
    java.lang.String getAuthenticationMechanisms(int index);
    /**
     * <code>repeated string authenticationMechanisms = 2;</code>
     * @param index The index of the value to return.
     * @return The bytes of the authenticationMechanisms at the given index.
     */
    com.google.protobuf.ByteString
        getAuthenticationMechanismsBytes(int index);
  }
  /**
   * Protobuf type {@code exec.bit.data.BitServerHandshake}
   */
  public static final class BitServerHandshake extends
      com.google.protobuf.GeneratedMessageV3 implements
      // @@protoc_insertion_point(message_implements:exec.bit.data.BitServerHandshake)
      BitServerHandshakeOrBuilder {
  private static final long serialVersionUID = 0L;
    // Use BitServerHandshake.newBuilder() to construct.
    private BitServerHandshake(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
      super(builder);
    }
    private BitServerHandshake() {
      authenticationMechanisms_ = com.google.protobuf.LazyStringArrayList.EMPTY;
    }

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

    @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.BitData.internal_static_exec_bit_data_BitServerHandshake_descriptor;
    }

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

    private int bitField0_;
    public static final int RPC_VERSION_FIELD_NUMBER = 1;
    private int rpcVersion_;
    /**
     * <code>optional int32 rpc_version = 1;</code>
     * @return Whether the rpcVersion field is set.
     */
    @java.lang.Override
    public boolean hasRpcVersion() {
      return ((bitField0_ & 0x00000001) != 0);
    }
    /**
     * <code>optional int32 rpc_version = 1;</code>
     * @return The rpcVersion.
     */
    @java.lang.Override
    public int getRpcVersion() {
      return rpcVersion_;
    }

    public static final int AUTHENTICATIONMECHANISMS_FIELD_NUMBER = 2;
    private com.google.protobuf.LazyStringList authenticationMechanisms_;
    /**
     * <code>repeated string authenticationMechanisms = 2;</code>
     * @return A list containing the authenticationMechanisms.
     */
    public com.google.protobuf.ProtocolStringList
        getAuthenticationMechanismsList() {
      return authenticationMechanisms_;
    }
    /**
     * <code>repeated string authenticationMechanisms = 2;</code>
     * @return The count of authenticationMechanisms.
     */
    public int getAuthenticationMechanismsCount() {
      return authenticationMechanisms_.size();
    }
    /**
     * <code>repeated string authenticationMechanisms = 2;</code>
     * @param index The index of the element to return.
     * @return The authenticationMechanisms at the given index.
     */
    public java.lang.String getAuthenticationMechanisms(int index) {
      return authenticationMechanisms_.get(index);
    }
    /**
     * <code>repeated string authenticationMechanisms = 2;</code>
     * @param index The index of the value to return.
     * @return The bytes of the authenticationMechanisms at the given index.
     */
    public com.google.protobuf.ByteString
        getAuthenticationMechanismsBytes(int index) {
      return authenticationMechanisms_.getByteString(index);
    }

    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.writeInt32(1, rpcVersion_);
      }
      for (int i = 0; i < authenticationMechanisms_.size(); i++) {
        com.google.protobuf.GeneratedMessageV3.writeString(output, 2, authenticationMechanisms_.getRaw(i));
      }
      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
          .computeInt32Size(1, rpcVersion_);
      }
      {
        int dataSize = 0;
        for (int i = 0; i < authenticationMechanisms_.size(); i++) {
          dataSize += computeStringSizeNoTag(authenticationMechanisms_.getRaw(i));
        }
        size += dataSize;
        size += 1 * getAuthenticationMechanismsList().size();
      }
      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.BitData.BitServerHandshake)) {
        return super.equals(obj);
      }
      org.apache.drill.exec.proto.BitData.BitServerHandshake other = (org.apache.drill.exec.proto.BitData.BitServerHandshake) obj;

      if (hasRpcVersion() != other.hasRpcVersion()) return false;
      if (hasRpcVersion()) {
        if (getRpcVersion()
            != other.getRpcVersion()) return false;
      }
      if (!getAuthenticationMechanismsList()
          .equals(other.getAuthenticationMechanismsList())) 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 (hasRpcVersion()) {
        hash = (37 * hash) + RPC_VERSION_FIELD_NUMBER;
        hash = (53 * hash) + getRpcVersion();
      }
      if (getAuthenticationMechanismsCount() > 0) {
        hash = (37 * hash) + AUTHENTICATIONMECHANISMS_FIELD_NUMBER;
        hash = (53 * hash) + getAuthenticationMechanismsList().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.drill.exec.proto.BitData.BitServerHandshake parseFrom(
        java.nio.ByteBuffer data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.BitData.BitServerHandshake 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.BitData.BitServerHandshake parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.BitData.BitServerHandshake 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.BitData.BitServerHandshake parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.BitData.BitServerHandshake 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.BitData.BitServerHandshake parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.BitData.BitServerHandshake 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.BitData.BitServerHandshake parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.BitData.BitServerHandshake 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.BitData.BitServerHandshake 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.BitData.BitServerHandshake 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.BitData.BitServerHandshake 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.bit.data.BitServerHandshake}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
        // @@protoc_insertion_point(builder_implements:exec.bit.data.BitServerHandshake)
        org.apache.drill.exec.proto.BitData.BitServerHandshakeOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.drill.exec.proto.BitData.internal_static_exec_bit_data_BitServerHandshake_descriptor;
      }

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

      // Construct using org.apache.drill.exec.proto.BitData.BitServerHandshake.newBuilder()
      private Builder() {

      }

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

      }
      @java.lang.Override
      public Builder clear() {
        super.clear();
        rpcVersion_ = 0;
        bitField0_ = (bitField0_ & ~0x00000001);
        authenticationMechanisms_ = com.google.protobuf.LazyStringArrayList.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000002);
        return this;
      }

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

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

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

      @java.lang.Override
      public org.apache.drill.exec.proto.BitData.BitServerHandshake buildPartial() {
        org.apache.drill.exec.proto.BitData.BitServerHandshake result = new org.apache.drill.exec.proto.BitData.BitServerHandshake(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) != 0)) {
          result.rpcVersion_ = rpcVersion_;
          to_bitField0_ |= 0x00000001;
        }
        if (((bitField0_ & 0x00000002) != 0)) {
          authenticationMechanisms_ = authenticationMechanisms_.getUnmodifiableView();
          bitField0_ = (bitField0_ & ~0x00000002);
        }
        result.authenticationMechanisms_ = authenticationMechanisms_;
        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.BitData.BitServerHandshake) {
          return mergeFrom((org.apache.drill.exec.proto.BitData.BitServerHandshake)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.drill.exec.proto.BitData.BitServerHandshake other) {
        if (other == org.apache.drill.exec.proto.BitData.BitServerHandshake.getDefaultInstance()) return this;
        if (other.hasRpcVersion()) {
          setRpcVersion(other.getRpcVersion());
        }
        if (!other.authenticationMechanisms_.isEmpty()) {
          if (authenticationMechanisms_.isEmpty()) {
            authenticationMechanisms_ = other.authenticationMechanisms_;
            bitField0_ = (bitField0_ & ~0x00000002);
          } else {
            ensureAuthenticationMechanismsIsMutable();
            authenticationMechanisms_.addAll(other.authenticationMechanisms_);
          }
          onChanged();
        }
        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: {
                rpcVersion_ = input.readInt32();
                bitField0_ |= 0x00000001;
                break;
              } // case 8
              case 18: {
                com.google.protobuf.ByteString bs = input.readBytes();
                ensureAuthenticationMechanismsIsMutable();
                authenticationMechanisms_.add(bs);
                break;
              } // case 18
              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 int rpcVersion_ ;
      /**
       * <code>optional int32 rpc_version = 1;</code>
       * @return Whether the rpcVersion field is set.
       */
      @java.lang.Override
      public boolean hasRpcVersion() {
        return ((bitField0_ & 0x00000001) != 0);
      }
      /**
       * <code>optional int32 rpc_version = 1;</code>
       * @return The rpcVersion.
       */
      @java.lang.Override
      public int getRpcVersion() {
        return rpcVersion_;
      }
      /**
       * <code>optional int32 rpc_version = 1;</code>
       * @param value The rpcVersion to set.
       * @return This builder for chaining.
       */
      public Builder setRpcVersion(int value) {
        bitField0_ |= 0x00000001;
        rpcVersion_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional int32 rpc_version = 1;</code>
       * @return This builder for chaining.
       */
      public Builder clearRpcVersion() {
        bitField0_ = (bitField0_ & ~0x00000001);
        rpcVersion_ = 0;
        onChanged();
        return this;
      }

      private com.google.protobuf.LazyStringList authenticationMechanisms_ = com.google.protobuf.LazyStringArrayList.EMPTY;
      private void ensureAuthenticationMechanismsIsMutable() {
        if (!((bitField0_ & 0x00000002) != 0)) {
          authenticationMechanisms_ = new com.google.protobuf.LazyStringArrayList(authenticationMechanisms_);
          bitField0_ |= 0x00000002;
         }
      }
      /**
       * <code>repeated string authenticationMechanisms = 2;</code>
       * @return A list containing the authenticationMechanisms.
       */
      public com.google.protobuf.ProtocolStringList
          getAuthenticationMechanismsList() {
        return authenticationMechanisms_.getUnmodifiableView();
      }
      /**
       * <code>repeated string authenticationMechanisms = 2;</code>
       * @return The count of authenticationMechanisms.
       */
      public int getAuthenticationMechanismsCount() {
        return authenticationMechanisms_.size();
      }
      /**
       * <code>repeated string authenticationMechanisms = 2;</code>
       * @param index The index of the element to return.
       * @return The authenticationMechanisms at the given index.
       */
      public java.lang.String getAuthenticationMechanisms(int index) {
        return authenticationMechanisms_.get(index);
      }
      /**
       * <code>repeated string authenticationMechanisms = 2;</code>
       * @param index The index of the value to return.
       * @return The bytes of the authenticationMechanisms at the given index.
       */
      public com.google.protobuf.ByteString
          getAuthenticationMechanismsBytes(int index) {
        return authenticationMechanisms_.getByteString(index);
      }
      /**
       * <code>repeated string authenticationMechanisms = 2;</code>
       * @param index The index to set the value at.
       * @param value The authenticationMechanisms to set.
       * @return This builder for chaining.
       */
      public Builder setAuthenticationMechanisms(
          int index, java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureAuthenticationMechanismsIsMutable();
        authenticationMechanisms_.set(index, value);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string authenticationMechanisms = 2;</code>
       * @param value The authenticationMechanisms to add.
       * @return This builder for chaining.
       */
      public Builder addAuthenticationMechanisms(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureAuthenticationMechanismsIsMutable();
        authenticationMechanisms_.add(value);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string authenticationMechanisms = 2;</code>
       * @param values The authenticationMechanisms to add.
       * @return This builder for chaining.
       */
      public Builder addAllAuthenticationMechanisms(
          java.lang.Iterable<java.lang.String> values) {
        ensureAuthenticationMechanismsIsMutable();
        com.google.protobuf.AbstractMessageLite.Builder.addAll(
            values, authenticationMechanisms_);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string authenticationMechanisms = 2;</code>
       * @return This builder for chaining.
       */
      public Builder clearAuthenticationMechanisms() {
        authenticationMechanisms_ = com.google.protobuf.LazyStringArrayList.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000002);
        onChanged();
        return this;
      }
      /**
       * <code>repeated string authenticationMechanisms = 2;</code>
       * @param value The bytes of the authenticationMechanisms to add.
       * @return This builder for chaining.
       */
      public Builder addAuthenticationMechanismsBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureAuthenticationMechanismsIsMutable();
        authenticationMechanisms_.add(value);
        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.bit.data.BitServerHandshake)
    }

    // @@protoc_insertion_point(class_scope:exec.bit.data.BitServerHandshake)
    private static final org.apache.drill.exec.proto.BitData.BitServerHandshake DEFAULT_INSTANCE;
    static {
      DEFAULT_INSTANCE = new org.apache.drill.exec.proto.BitData.BitServerHandshake();
    }

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

    @java.lang.Deprecated public static final com.google.protobuf.Parser<BitServerHandshake>
        PARSER = new com.google.protobuf.AbstractParser<BitServerHandshake>() {
      @java.lang.Override
      public BitServerHandshake 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<BitServerHandshake> parser() {
      return PARSER;
    }

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

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

  }

  public interface FragmentRecordBatchOrBuilder extends
      // @@protoc_insertion_point(interface_extends:exec.bit.data.FragmentRecordBatch)
      com.google.protobuf.MessageOrBuilder {

    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     * @return Whether the queryId field is set.
     */
    boolean hasQueryId();
    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     * @return The queryId.
     */
    org.apache.drill.exec.proto.UserBitShared.QueryId getQueryId();
    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     */
    org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder getQueryIdOrBuilder();

    /**
     * <code>optional int32 receiving_major_fragment_id = 2;</code>
     * @return Whether the receivingMajorFragmentId field is set.
     */
    boolean hasReceivingMajorFragmentId();
    /**
     * <code>optional int32 receiving_major_fragment_id = 2;</code>
     * @return The receivingMajorFragmentId.
     */
    int getReceivingMajorFragmentId();

    /**
     * <code>repeated int32 receiving_minor_fragment_id = 3;</code>
     * @return A list containing the receivingMinorFragmentId.
     */
    java.util.List<java.lang.Integer> getReceivingMinorFragmentIdList();
    /**
     * <code>repeated int32 receiving_minor_fragment_id = 3;</code>
     * @return The count of receivingMinorFragmentId.
     */
    int getReceivingMinorFragmentIdCount();
    /**
     * <code>repeated int32 receiving_minor_fragment_id = 3;</code>
     * @param index The index of the element to return.
     * @return The receivingMinorFragmentId at the given index.
     */
    int getReceivingMinorFragmentId(int index);

    /**
     * <code>optional int32 sending_major_fragment_id = 4;</code>
     * @return Whether the sendingMajorFragmentId field is set.
     */
    boolean hasSendingMajorFragmentId();
    /**
     * <code>optional int32 sending_major_fragment_id = 4;</code>
     * @return The sendingMajorFragmentId.
     */
    int getSendingMajorFragmentId();

    /**
     * <code>optional int32 sending_minor_fragment_id = 5;</code>
     * @return Whether the sendingMinorFragmentId field is set.
     */
    boolean hasSendingMinorFragmentId();
    /**
     * <code>optional int32 sending_minor_fragment_id = 5;</code>
     * @return The sendingMinorFragmentId.
     */
    int getSendingMinorFragmentId();

    /**
     * <code>optional .exec.shared.RecordBatchDef def = 6;</code>
     * @return Whether the def field is set.
     */
    boolean hasDef();
    /**
     * <code>optional .exec.shared.RecordBatchDef def = 6;</code>
     * @return The def.
     */
    org.apache.drill.exec.proto.UserBitShared.RecordBatchDef getDef();
    /**
     * <code>optional .exec.shared.RecordBatchDef def = 6;</code>
     */
    org.apache.drill.exec.proto.UserBitShared.RecordBatchDefOrBuilder getDefOrBuilder();

    /**
     * <code>optional bool isLastBatch = 7;</code>
     * @return Whether the isLastBatch field is set.
     */
    boolean hasIsLastBatch();
    /**
     * <code>optional bool isLastBatch = 7;</code>
     * @return The isLastBatch.
     */
    boolean getIsLastBatch();
  }
  /**
   * Protobuf type {@code exec.bit.data.FragmentRecordBatch}
   */
  public static final class FragmentRecordBatch extends
      com.google.protobuf.GeneratedMessageV3 implements
      // @@protoc_insertion_point(message_implements:exec.bit.data.FragmentRecordBatch)
      FragmentRecordBatchOrBuilder {
  private static final long serialVersionUID = 0L;
    // Use FragmentRecordBatch.newBuilder() to construct.
    private FragmentRecordBatch(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
      super(builder);
    }
    private FragmentRecordBatch() {
      receivingMinorFragmentId_ = emptyIntList();
    }

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

    @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.BitData.internal_static_exec_bit_data_FragmentRecordBatch_descriptor;
    }

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

    private int bitField0_;
    public static final int QUERY_ID_FIELD_NUMBER = 1;
    private org.apache.drill.exec.proto.UserBitShared.QueryId queryId_;
    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     * @return Whether the queryId field is set.
     */
    @java.lang.Override
    public boolean hasQueryId() {
      return ((bitField0_ & 0x00000001) != 0);
    }
    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     * @return The queryId.
     */
    @java.lang.Override
    public org.apache.drill.exec.proto.UserBitShared.QueryId getQueryId() {
      return queryId_ == null ? org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance() : queryId_;
    }
    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     */
    @java.lang.Override
    public org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder getQueryIdOrBuilder() {
      return queryId_ == null ? org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance() : queryId_;
    }

    public static final int RECEIVING_MAJOR_FRAGMENT_ID_FIELD_NUMBER = 2;
    private int receivingMajorFragmentId_;
    /**
     * <code>optional int32 receiving_major_fragment_id = 2;</code>
     * @return Whether the receivingMajorFragmentId field is set.
     */
    @java.lang.Override
    public boolean hasReceivingMajorFragmentId() {
      return ((bitField0_ & 0x00000002) != 0);
    }
    /**
     * <code>optional int32 receiving_major_fragment_id = 2;</code>
     * @return The receivingMajorFragmentId.
     */
    @java.lang.Override
    public int getReceivingMajorFragmentId() {
      return receivingMajorFragmentId_;
    }

    public static final int RECEIVING_MINOR_FRAGMENT_ID_FIELD_NUMBER = 3;
    private com.google.protobuf.Internal.IntList receivingMinorFragmentId_;
    /**
     * <code>repeated int32 receiving_minor_fragment_id = 3;</code>
     * @return A list containing the receivingMinorFragmentId.
     */
    @java.lang.Override
    public java.util.List<java.lang.Integer>
        getReceivingMinorFragmentIdList() {
      return receivingMinorFragmentId_;
    }
    /**
     * <code>repeated int32 receiving_minor_fragment_id = 3;</code>
     * @return The count of receivingMinorFragmentId.
     */
    public int getReceivingMinorFragmentIdCount() {
      return receivingMinorFragmentId_.size();
    }
    /**
     * <code>repeated int32 receiving_minor_fragment_id = 3;</code>
     * @param index The index of the element to return.
     * @return The receivingMinorFragmentId at the given index.
     */
    public int getReceivingMinorFragmentId(int index) {
      return receivingMinorFragmentId_.getInt(index);
    }

    public static final int SENDING_MAJOR_FRAGMENT_ID_FIELD_NUMBER = 4;
    private int sendingMajorFragmentId_;
    /**
     * <code>optional int32 sending_major_fragment_id = 4;</code>
     * @return Whether the sendingMajorFragmentId field is set.
     */
    @java.lang.Override
    public boolean hasSendingMajorFragmentId() {
      return ((bitField0_ & 0x00000004) != 0);
    }
    /**
     * <code>optional int32 sending_major_fragment_id = 4;</code>
     * @return The sendingMajorFragmentId.
     */
    @java.lang.Override
    public int getSendingMajorFragmentId() {
      return sendingMajorFragmentId_;
    }

    public static final int SENDING_MINOR_FRAGMENT_ID_FIELD_NUMBER = 5;
    private int sendingMinorFragmentId_;
    /**
     * <code>optional int32 sending_minor_fragment_id = 5;</code>
     * @return Whether the sendingMinorFragmentId field is set.
     */
    @java.lang.Override
    public boolean hasSendingMinorFragmentId() {
      return ((bitField0_ & 0x00000008) != 0);
    }
    /**
     * <code>optional int32 sending_minor_fragment_id = 5;</code>
     * @return The sendingMinorFragmentId.
     */
    @java.lang.Override
    public int getSendingMinorFragmentId() {
      return sendingMinorFragmentId_;
    }

    public static final int DEF_FIELD_NUMBER = 6;
    private org.apache.drill.exec.proto.UserBitShared.RecordBatchDef def_;
    /**
     * <code>optional .exec.shared.RecordBatchDef def = 6;</code>
     * @return Whether the def field is set.
     */
    @java.lang.Override
    public boolean hasDef() {
      return ((bitField0_ & 0x00000010) != 0);
    }
    /**
     * <code>optional .exec.shared.RecordBatchDef def = 6;</code>
     * @return The def.
     */
    @java.lang.Override
    public org.apache.drill.exec.proto.UserBitShared.RecordBatchDef getDef() {
      return def_ == null ? org.apache.drill.exec.proto.UserBitShared.RecordBatchDef.getDefaultInstance() : def_;
    }
    /**
     * <code>optional .exec.shared.RecordBatchDef def = 6;</code>
     */
    @java.lang.Override
    public org.apache.drill.exec.proto.UserBitShared.RecordBatchDefOrBuilder getDefOrBuilder() {
      return def_ == null ? org.apache.drill.exec.proto.UserBitShared.RecordBatchDef.getDefaultInstance() : def_;
    }

    public static final int ISLASTBATCH_FIELD_NUMBER = 7;
    private boolean isLastBatch_;
    /**
     * <code>optional bool isLastBatch = 7;</code>
     * @return Whether the isLastBatch field is set.
     */
    @java.lang.Override
    public boolean hasIsLastBatch() {
      return ((bitField0_ & 0x00000020) != 0);
    }
    /**
     * <code>optional bool isLastBatch = 7;</code>
     * @return The isLastBatch.
     */
    @java.lang.Override
    public boolean getIsLastBatch() {
      return isLastBatch_;
    }

    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.writeMessage(1, getQueryId());
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        output.writeInt32(2, receivingMajorFragmentId_);
      }
      for (int i = 0; i < receivingMinorFragmentId_.size(); i++) {
        output.writeInt32(3, receivingMinorFragmentId_.getInt(i));
      }
      if (((bitField0_ & 0x00000004) != 0)) {
        output.writeInt32(4, sendingMajorFragmentId_);
      }
      if (((bitField0_ & 0x00000008) != 0)) {
        output.writeInt32(5, sendingMinorFragmentId_);
      }
      if (((bitField0_ & 0x00000010) != 0)) {
        output.writeMessage(6, getDef());
      }
      if (((bitField0_ & 0x00000020) != 0)) {
        output.writeBool(7, isLastBatch_);
      }
      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
          .computeMessageSize(1, getQueryId());
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(2, receivingMajorFragmentId_);
      }
      {
        int dataSize = 0;
        for (int i = 0; i < receivingMinorFragmentId_.size(); i++) {
          dataSize += com.google.protobuf.CodedOutputStream
            .computeInt32SizeNoTag(receivingMinorFragmentId_.getInt(i));
        }
        size += dataSize;
        size += 1 * getReceivingMinorFragmentIdList().size();
      }
      if (((bitField0_ & 0x00000004) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(4, sendingMajorFragmentId_);
      }
      if (((bitField0_ & 0x00000008) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(5, sendingMinorFragmentId_);
      }
      if (((bitField0_ & 0x00000010) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeMessageSize(6, getDef());
      }
      if (((bitField0_ & 0x00000020) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBoolSize(7, isLastBatch_);
      }
      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.BitData.FragmentRecordBatch)) {
        return super.equals(obj);
      }
      org.apache.drill.exec.proto.BitData.FragmentRecordBatch other = (org.apache.drill.exec.proto.BitData.FragmentRecordBatch) obj;

      if (hasQueryId() != other.hasQueryId()) return false;
      if (hasQueryId()) {
        if (!getQueryId()
            .equals(other.getQueryId())) return false;
      }
      if (hasReceivingMajorFragmentId() != other.hasReceivingMajorFragmentId()) return false;
      if (hasReceivingMajorFragmentId()) {
        if (getReceivingMajorFragmentId()
            != other.getReceivingMajorFragmentId()) return false;
      }
      if (!getReceivingMinorFragmentIdList()
          .equals(other.getReceivingMinorFragmentIdList())) return false;
      if (hasSendingMajorFragmentId() != other.hasSendingMajorFragmentId()) return false;
      if (hasSendingMajorFragmentId()) {
        if (getSendingMajorFragmentId()
            != other.getSendingMajorFragmentId()) return false;
      }
      if (hasSendingMinorFragmentId() != other.hasSendingMinorFragmentId()) return false;
      if (hasSendingMinorFragmentId()) {
        if (getSendingMinorFragmentId()
            != other.getSendingMinorFragmentId()) return false;
      }
      if (hasDef() != other.hasDef()) return false;
      if (hasDef()) {
        if (!getDef()
            .equals(other.getDef())) return false;
      }
      if (hasIsLastBatch() != other.hasIsLastBatch()) return false;
      if (hasIsLastBatch()) {
        if (getIsLastBatch()
            != other.getIsLastBatch()) 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 (hasQueryId()) {
        hash = (37 * hash) + QUERY_ID_FIELD_NUMBER;
        hash = (53 * hash) + getQueryId().hashCode();
      }
      if (hasReceivingMajorFragmentId()) {
        hash = (37 * hash) + RECEIVING_MAJOR_FRAGMENT_ID_FIELD_NUMBER;
        hash = (53 * hash) + getReceivingMajorFragmentId();
      }
      if (getReceivingMinorFragmentIdCount() > 0) {
        hash = (37 * hash) + RECEIVING_MINOR_FRAGMENT_ID_FIELD_NUMBER;
        hash = (53 * hash) + getReceivingMinorFragmentIdList().hashCode();
      }
      if (hasSendingMajorFragmentId()) {
        hash = (37 * hash) + SENDING_MAJOR_FRAGMENT_ID_FIELD_NUMBER;
        hash = (53 * hash) + getSendingMajorFragmentId();
      }
      if (hasSendingMinorFragmentId()) {
        hash = (37 * hash) + SENDING_MINOR_FRAGMENT_ID_FIELD_NUMBER;
        hash = (53 * hash) + getSendingMinorFragmentId();
      }
      if (hasDef()) {
        hash = (37 * hash) + DEF_FIELD_NUMBER;
        hash = (53 * hash) + getDef().hashCode();
      }
      if (hasIsLastBatch()) {
        hash = (37 * hash) + ISLASTBATCH_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(
            getIsLastBatch());
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.drill.exec.proto.BitData.FragmentRecordBatch parseFrom(
        java.nio.ByteBuffer data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.BitData.FragmentRecordBatch 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.BitData.FragmentRecordBatch parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.BitData.FragmentRecordBatch 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.BitData.FragmentRecordBatch parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.BitData.FragmentRecordBatch 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.BitData.FragmentRecordBatch parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.BitData.FragmentRecordBatch 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.BitData.FragmentRecordBatch parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.BitData.FragmentRecordBatch 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.BitData.FragmentRecordBatch 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.BitData.FragmentRecordBatch 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.BitData.FragmentRecordBatch 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.bit.data.FragmentRecordBatch}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
        // @@protoc_insertion_point(builder_implements:exec.bit.data.FragmentRecordBatch)
        org.apache.drill.exec.proto.BitData.FragmentRecordBatchOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.drill.exec.proto.BitData.internal_static_exec_bit_data_FragmentRecordBatch_descriptor;
      }

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

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

      private Builder(
          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessageV3
                .alwaysUseFieldBuilders) {
          getQueryIdFieldBuilder();
          getDefFieldBuilder();
        }
      }
      @java.lang.Override
      public Builder clear() {
        super.clear();
        if (queryIdBuilder_ == null) {
          queryId_ = null;
        } else {
          queryIdBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000001);
        receivingMajorFragmentId_ = 0;
        bitField0_ = (bitField0_ & ~0x00000002);
        receivingMinorFragmentId_ = emptyIntList();
        bitField0_ = (bitField0_ & ~0x00000004);
        sendingMajorFragmentId_ = 0;
        bitField0_ = (bitField0_ & ~0x00000008);
        sendingMinorFragmentId_ = 0;
        bitField0_ = (bitField0_ & ~0x00000010);
        if (defBuilder_ == null) {
          def_ = null;
        } else {
          defBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000020);
        isLastBatch_ = false;
        bitField0_ = (bitField0_ & ~0x00000040);
        return this;
      }

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

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

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

      @java.lang.Override
      public org.apache.drill.exec.proto.BitData.FragmentRecordBatch buildPartial() {
        org.apache.drill.exec.proto.BitData.FragmentRecordBatch result = new org.apache.drill.exec.proto.BitData.FragmentRecordBatch(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) != 0)) {
          if (queryIdBuilder_ == null) {
            result.queryId_ = queryId_;
          } else {
            result.queryId_ = queryIdBuilder_.build();
          }
          to_bitField0_ |= 0x00000001;
        }
        if (((from_bitField0_ & 0x00000002) != 0)) {
          result.receivingMajorFragmentId_ = receivingMajorFragmentId_;
          to_bitField0_ |= 0x00000002;
        }
        if (((bitField0_ & 0x00000004) != 0)) {
          receivingMinorFragmentId_.makeImmutable();
          bitField0_ = (bitField0_ & ~0x00000004);
        }
        result.receivingMinorFragmentId_ = receivingMinorFragmentId_;
        if (((from_bitField0_ & 0x00000008) != 0)) {
          result.sendingMajorFragmentId_ = sendingMajorFragmentId_;
          to_bitField0_ |= 0x00000004;
        }
        if (((from_bitField0_ & 0x00000010) != 0)) {
          result.sendingMinorFragmentId_ = sendingMinorFragmentId_;
          to_bitField0_ |= 0x00000008;
        }
        if (((from_bitField0_ & 0x00000020) != 0)) {
          if (defBuilder_ == null) {
            result.def_ = def_;
          } else {
            result.def_ = defBuilder_.build();
          }
          to_bitField0_ |= 0x00000010;
        }
        if (((from_bitField0_ & 0x00000040) != 0)) {
          result.isLastBatch_ = isLastBatch_;
          to_bitField0_ |= 0x00000020;
        }
        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.BitData.FragmentRecordBatch) {
          return mergeFrom((org.apache.drill.exec.proto.BitData.FragmentRecordBatch)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.drill.exec.proto.BitData.FragmentRecordBatch other) {
        if (other == org.apache.drill.exec.proto.BitData.FragmentRecordBatch.getDefaultInstance()) return this;
        if (other.hasQueryId()) {
          mergeQueryId(other.getQueryId());
        }
        if (other.hasReceivingMajorFragmentId()) {
          setReceivingMajorFragmentId(other.getReceivingMajorFragmentId());
        }
        if (!other.receivingMinorFragmentId_.isEmpty()) {
          if (receivingMinorFragmentId_.isEmpty()) {
            receivingMinorFragmentId_ = other.receivingMinorFragmentId_;
            bitField0_ = (bitField0_ & ~0x00000004);
          } else {
            ensureReceivingMinorFragmentIdIsMutable();
            receivingMinorFragmentId_.addAll(other.receivingMinorFragmentId_);
          }
          onChanged();
        }
        if (other.hasSendingMajorFragmentId()) {
          setSendingMajorFragmentId(other.getSendingMajorFragmentId());
        }
        if (other.hasSendingMinorFragmentId()) {
          setSendingMinorFragmentId(other.getSendingMinorFragmentId());
        }
        if (other.hasDef()) {
          mergeDef(other.getDef());
        }
        if (other.hasIsLastBatch()) {
          setIsLastBatch(other.getIsLastBatch());
        }
        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: {
                input.readMessage(
                    getQueryIdFieldBuilder().getBuilder(),
                    extensionRegistry);
                bitField0_ |= 0x00000001;
                break;
              } // case 10
              case 16: {
                receivingMajorFragmentId_ = input.readInt32();
                bitField0_ |= 0x00000002;
                break;
              } // case 16
              case 24: {
                int v = input.readInt32();
                ensureReceivingMinorFragmentIdIsMutable();
                receivingMinorFragmentId_.addInt(v);
                break;
              } // case 24
              case 26: {
                int length = input.readRawVarint32();
                int limit = input.pushLimit(length);
                ensureReceivingMinorFragmentIdIsMutable();
                while (input.getBytesUntilLimit() > 0) {
                  receivingMinorFragmentId_.addInt(input.readInt32());
                }
                input.popLimit(limit);
                break;
              } // case 26
              case 32: {
                sendingMajorFragmentId_ = input.readInt32();
                bitField0_ |= 0x00000008;
                break;
              } // case 32
              case 40: {
                sendingMinorFragmentId_ = input.readInt32();
                bitField0_ |= 0x00000010;
                break;
              } // case 40
              case 50: {
                input.readMessage(
                    getDefFieldBuilder().getBuilder(),
                    extensionRegistry);
                bitField0_ |= 0x00000020;
                break;
              } // case 50
              case 56: {
                isLastBatch_ = input.readBool();
                bitField0_ |= 0x00000040;
                break;
              } // case 56
              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 org.apache.drill.exec.proto.UserBitShared.QueryId queryId_;
      private com.google.protobuf.SingleFieldBuilderV3<
          org.apache.drill.exec.proto.UserBitShared.QueryId, org.apache.drill.exec.proto.UserBitShared.QueryId.Builder, org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder> queryIdBuilder_;
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       * @return Whether the queryId field is set.
       */
      public boolean hasQueryId() {
        return ((bitField0_ & 0x00000001) != 0);
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       * @return The queryId.
       */
      public org.apache.drill.exec.proto.UserBitShared.QueryId getQueryId() {
        if (queryIdBuilder_ == null) {
          return queryId_ == null ? org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance() : queryId_;
        } else {
          return queryIdBuilder_.getMessage();
        }
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public Builder setQueryId(org.apache.drill.exec.proto.UserBitShared.QueryId value) {
        if (queryIdBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          queryId_ = value;
          onChanged();
        } else {
          queryIdBuilder_.setMessage(value);
        }
        bitField0_ |= 0x00000001;
        return this;
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public Builder setQueryId(
          org.apache.drill.exec.proto.UserBitShared.QueryId.Builder builderForValue) {
        if (queryIdBuilder_ == null) {
          queryId_ = builderForValue.build();
          onChanged();
        } else {
          queryIdBuilder_.setMessage(builderForValue.build());
        }
        bitField0_ |= 0x00000001;
        return this;
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public Builder mergeQueryId(org.apache.drill.exec.proto.UserBitShared.QueryId value) {
        if (queryIdBuilder_ == null) {
          if (((bitField0_ & 0x00000001) != 0) &&
              queryId_ != null &&
              queryId_ != org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance()) {
            queryId_ =
              org.apache.drill.exec.proto.UserBitShared.QueryId.newBuilder(queryId_).mergeFrom(value).buildPartial();
          } else {
            queryId_ = value;
          }
          onChanged();
        } else {
          queryIdBuilder_.mergeFrom(value);
        }
        bitField0_ |= 0x00000001;
        return this;
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public Builder clearQueryId() {
        if (queryIdBuilder_ == null) {
          queryId_ = null;
          onChanged();
        } else {
          queryIdBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public org.apache.drill.exec.proto.UserBitShared.QueryId.Builder getQueryIdBuilder() {
        bitField0_ |= 0x00000001;
        onChanged();
        return getQueryIdFieldBuilder().getBuilder();
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder getQueryIdOrBuilder() {
        if (queryIdBuilder_ != null) {
          return queryIdBuilder_.getMessageOrBuilder();
        } else {
          return queryId_ == null ?
              org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance() : queryId_;
        }
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      private com.google.protobuf.SingleFieldBuilderV3<
          org.apache.drill.exec.proto.UserBitShared.QueryId, org.apache.drill.exec.proto.UserBitShared.QueryId.Builder, org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder> 
          getQueryIdFieldBuilder() {
        if (queryIdBuilder_ == null) {
          queryIdBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
              org.apache.drill.exec.proto.UserBitShared.QueryId, org.apache.drill.exec.proto.UserBitShared.QueryId.Builder, org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder>(
                  getQueryId(),
                  getParentForChildren(),
                  isClean());
          queryId_ = null;
        }
        return queryIdBuilder_;
      }

      private int receivingMajorFragmentId_ ;
      /**
       * <code>optional int32 receiving_major_fragment_id = 2;</code>
       * @return Whether the receivingMajorFragmentId field is set.
       */
      @java.lang.Override
      public boolean hasReceivingMajorFragmentId() {
        return ((bitField0_ & 0x00000002) != 0);
      }
      /**
       * <code>optional int32 receiving_major_fragment_id = 2;</code>
       * @return The receivingMajorFragmentId.
       */
      @java.lang.Override
      public int getReceivingMajorFragmentId() {
        return receivingMajorFragmentId_;
      }
      /**
       * <code>optional int32 receiving_major_fragment_id = 2;</code>
       * @param value The receivingMajorFragmentId to set.
       * @return This builder for chaining.
       */
      public Builder setReceivingMajorFragmentId(int value) {
        bitField0_ |= 0x00000002;
        receivingMajorFragmentId_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional int32 receiving_major_fragment_id = 2;</code>
       * @return This builder for chaining.
       */
      public Builder clearReceivingMajorFragmentId() {
        bitField0_ = (bitField0_ & ~0x00000002);
        receivingMajorFragmentId_ = 0;
        onChanged();
        return this;
      }

      private com.google.protobuf.Internal.IntList receivingMinorFragmentId_ = emptyIntList();
      private void ensureReceivingMinorFragmentIdIsMutable() {
        if (!((bitField0_ & 0x00000004) != 0)) {
          receivingMinorFragmentId_ = mutableCopy(receivingMinorFragmentId_);
          bitField0_ |= 0x00000004;
         }
      }
      /**
       * <code>repeated int32 receiving_minor_fragment_id = 3;</code>
       * @return A list containing the receivingMinorFragmentId.
       */
      public java.util.List<java.lang.Integer>
          getReceivingMinorFragmentIdList() {
        return ((bitField0_ & 0x00000004) != 0) ?
                 java.util.Collections.unmodifiableList(receivingMinorFragmentId_) : receivingMinorFragmentId_;
      }
      /**
       * <code>repeated int32 receiving_minor_fragment_id = 3;</code>
       * @return The count of receivingMinorFragmentId.
       */
      public int getReceivingMinorFragmentIdCount() {
        return receivingMinorFragmentId_.size();
      }
      /**
       * <code>repeated int32 receiving_minor_fragment_id = 3;</code>
       * @param index The index of the element to return.
       * @return The receivingMinorFragmentId at the given index.
       */
      public int getReceivingMinorFragmentId(int index) {
        return receivingMinorFragmentId_.getInt(index);
      }
      /**
       * <code>repeated int32 receiving_minor_fragment_id = 3;</code>
       * @param index The index to set the value at.
       * @param value The receivingMinorFragmentId to set.
       * @return This builder for chaining.
       */
      public Builder setReceivingMinorFragmentId(
          int index, int value) {
        ensureReceivingMinorFragmentIdIsMutable();
        receivingMinorFragmentId_.setInt(index, value);
        onChanged();
        return this;
      }
      /**
       * <code>repeated int32 receiving_minor_fragment_id = 3;</code>
       * @param value The receivingMinorFragmentId to add.
       * @return This builder for chaining.
       */
      public Builder addReceivingMinorFragmentId(int value) {
        ensureReceivingMinorFragmentIdIsMutable();
        receivingMinorFragmentId_.addInt(value);
        onChanged();
        return this;
      }
      /**
       * <code>repeated int32 receiving_minor_fragment_id = 3;</code>
       * @param values The receivingMinorFragmentId to add.
       * @return This builder for chaining.
       */
      public Builder addAllReceivingMinorFragmentId(
          java.lang.Iterable<? extends java.lang.Integer> values) {
        ensureReceivingMinorFragmentIdIsMutable();
        com.google.protobuf.AbstractMessageLite.Builder.addAll(
            values, receivingMinorFragmentId_);
        onChanged();
        return this;
      }
      /**
       * <code>repeated int32 receiving_minor_fragment_id = 3;</code>
       * @return This builder for chaining.
       */
      public Builder clearReceivingMinorFragmentId() {
        receivingMinorFragmentId_ = emptyIntList();
        bitField0_ = (bitField0_ & ~0x00000004);
        onChanged();
        return this;
      }

      private int sendingMajorFragmentId_ ;
      /**
       * <code>optional int32 sending_major_fragment_id = 4;</code>
       * @return Whether the sendingMajorFragmentId field is set.
       */
      @java.lang.Override
      public boolean hasSendingMajorFragmentId() {
        return ((bitField0_ & 0x00000008) != 0);
      }
      /**
       * <code>optional int32 sending_major_fragment_id = 4;</code>
       * @return The sendingMajorFragmentId.
       */
      @java.lang.Override
      public int getSendingMajorFragmentId() {
        return sendingMajorFragmentId_;
      }
      /**
       * <code>optional int32 sending_major_fragment_id = 4;</code>
       * @param value The sendingMajorFragmentId to set.
       * @return This builder for chaining.
       */
      public Builder setSendingMajorFragmentId(int value) {
        bitField0_ |= 0x00000008;
        sendingMajorFragmentId_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional int32 sending_major_fragment_id = 4;</code>
       * @return This builder for chaining.
       */
      public Builder clearSendingMajorFragmentId() {
        bitField0_ = (bitField0_ & ~0x00000008);
        sendingMajorFragmentId_ = 0;
        onChanged();
        return this;
      }

      private int sendingMinorFragmentId_ ;
      /**
       * <code>optional int32 sending_minor_fragment_id = 5;</code>
       * @return Whether the sendingMinorFragmentId field is set.
       */
      @java.lang.Override
      public boolean hasSendingMinorFragmentId() {
        return ((bitField0_ & 0x00000010) != 0);
      }
      /**
       * <code>optional int32 sending_minor_fragment_id = 5;</code>
       * @return The sendingMinorFragmentId.
       */
      @java.lang.Override
      public int getSendingMinorFragmentId() {
        return sendingMinorFragmentId_;
      }
      /**
       * <code>optional int32 sending_minor_fragment_id = 5;</code>
       * @param value The sendingMinorFragmentId to set.
       * @return This builder for chaining.
       */
      public Builder setSendingMinorFragmentId(int value) {
        bitField0_ |= 0x00000010;
        sendingMinorFragmentId_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional int32 sending_minor_fragment_id = 5;</code>
       * @return This builder for chaining.
       */
      public Builder clearSendingMinorFragmentId() {
        bitField0_ = (bitField0_ & ~0x00000010);
        sendingMinorFragmentId_ = 0;
        onChanged();
        return this;
      }

      private org.apache.drill.exec.proto.UserBitShared.RecordBatchDef def_;
      private com.google.protobuf.SingleFieldBuilderV3<
          org.apache.drill.exec.proto.UserBitShared.RecordBatchDef, org.apache.drill.exec.proto.UserBitShared.RecordBatchDef.Builder, org.apache.drill.exec.proto.UserBitShared.RecordBatchDefOrBuilder> defBuilder_;
      /**
       * <code>optional .exec.shared.RecordBatchDef def = 6;</code>
       * @return Whether the def field is set.
       */
      public boolean hasDef() {
        return ((bitField0_ & 0x00000020) != 0);
      }
      /**
       * <code>optional .exec.shared.RecordBatchDef def = 6;</code>
       * @return The def.
       */
      public org.apache.drill.exec.proto.UserBitShared.RecordBatchDef getDef() {
        if (defBuilder_ == null) {
          return def_ == null ? org.apache.drill.exec.proto.UserBitShared.RecordBatchDef.getDefaultInstance() : def_;
        } else {
          return defBuilder_.getMessage();
        }
      }
      /**
       * <code>optional .exec.shared.RecordBatchDef def = 6;</code>
       */
      public Builder setDef(org.apache.drill.exec.proto.UserBitShared.RecordBatchDef value) {
        if (defBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          def_ = value;
          onChanged();
        } else {
          defBuilder_.setMessage(value);
        }
        bitField0_ |= 0x00000020;
        return this;
      }
      /**
       * <code>optional .exec.shared.RecordBatchDef def = 6;</code>
       */
      public Builder setDef(
          org.apache.drill.exec.proto.UserBitShared.RecordBatchDef.Builder builderForValue) {
        if (defBuilder_ == null) {
          def_ = builderForValue.build();
          onChanged();
        } else {
          defBuilder_.setMessage(builderForValue.build());
        }
        bitField0_ |= 0x00000020;
        return this;
      }
      /**
       * <code>optional .exec.shared.RecordBatchDef def = 6;</code>
       */
      public Builder mergeDef(org.apache.drill.exec.proto.UserBitShared.RecordBatchDef value) {
        if (defBuilder_ == null) {
          if (((bitField0_ & 0x00000020) != 0) &&
              def_ != null &&
              def_ != org.apache.drill.exec.proto.UserBitShared.RecordBatchDef.getDefaultInstance()) {
            def_ =
              org.apache.drill.exec.proto.UserBitShared.RecordBatchDef.newBuilder(def_).mergeFrom(value).buildPartial();
          } else {
            def_ = value;
          }
          onChanged();
        } else {
          defBuilder_.mergeFrom(value);
        }
        bitField0_ |= 0x00000020;
        return this;
      }
      /**
       * <code>optional .exec.shared.RecordBatchDef def = 6;</code>
       */
      public Builder clearDef() {
        if (defBuilder_ == null) {
          def_ = null;
          onChanged();
        } else {
          defBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000020);
        return this;
      }
      /**
       * <code>optional .exec.shared.RecordBatchDef def = 6;</code>
       */
      public org.apache.drill.exec.proto.UserBitShared.RecordBatchDef.Builder getDefBuilder() {
        bitField0_ |= 0x00000020;
        onChanged();
        return getDefFieldBuilder().getBuilder();
      }
      /**
       * <code>optional .exec.shared.RecordBatchDef def = 6;</code>
       */
      public org.apache.drill.exec.proto.UserBitShared.RecordBatchDefOrBuilder getDefOrBuilder() {
        if (defBuilder_ != null) {
          return defBuilder_.getMessageOrBuilder();
        } else {
          return def_ == null ?
              org.apache.drill.exec.proto.UserBitShared.RecordBatchDef.getDefaultInstance() : def_;
        }
      }
      /**
       * <code>optional .exec.shared.RecordBatchDef def = 6;</code>
       */
      private com.google.protobuf.SingleFieldBuilderV3<
          org.apache.drill.exec.proto.UserBitShared.RecordBatchDef, org.apache.drill.exec.proto.UserBitShared.RecordBatchDef.Builder, org.apache.drill.exec.proto.UserBitShared.RecordBatchDefOrBuilder> 
          getDefFieldBuilder() {
        if (defBuilder_ == null) {
          defBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
              org.apache.drill.exec.proto.UserBitShared.RecordBatchDef, org.apache.drill.exec.proto.UserBitShared.RecordBatchDef.Builder, org.apache.drill.exec.proto.UserBitShared.RecordBatchDefOrBuilder>(
                  getDef(),
                  getParentForChildren(),
                  isClean());
          def_ = null;
        }
        return defBuilder_;
      }

      private boolean isLastBatch_ ;
      /**
       * <code>optional bool isLastBatch = 7;</code>
       * @return Whether the isLastBatch field is set.
       */
      @java.lang.Override
      public boolean hasIsLastBatch() {
        return ((bitField0_ & 0x00000040) != 0);
      }
      /**
       * <code>optional bool isLastBatch = 7;</code>
       * @return The isLastBatch.
       */
      @java.lang.Override
      public boolean getIsLastBatch() {
        return isLastBatch_;
      }
      /**
       * <code>optional bool isLastBatch = 7;</code>
       * @param value The isLastBatch to set.
       * @return This builder for chaining.
       */
      public Builder setIsLastBatch(boolean value) {
        bitField0_ |= 0x00000040;
        isLastBatch_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional bool isLastBatch = 7;</code>
       * @return This builder for chaining.
       */
      public Builder clearIsLastBatch() {
        bitField0_ = (bitField0_ & ~0x00000040);
        isLastBatch_ = false;
        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.bit.data.FragmentRecordBatch)
    }

    // @@protoc_insertion_point(class_scope:exec.bit.data.FragmentRecordBatch)
    private static final org.apache.drill.exec.proto.BitData.FragmentRecordBatch DEFAULT_INSTANCE;
    static {
      DEFAULT_INSTANCE = new org.apache.drill.exec.proto.BitData.FragmentRecordBatch();
    }

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

    @java.lang.Deprecated public static final com.google.protobuf.Parser<FragmentRecordBatch>
        PARSER = new com.google.protobuf.AbstractParser<FragmentRecordBatch>() {
      @java.lang.Override
      public FragmentRecordBatch 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<FragmentRecordBatch> parser() {
      return PARSER;
    }

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

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

  }

  public interface RuntimeFilterBDefOrBuilder extends
      // @@protoc_insertion_point(interface_extends:exec.bit.data.RuntimeFilterBDef)
      com.google.protobuf.MessageOrBuilder {

    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     * @return Whether the queryId field is set.
     */
    boolean hasQueryId();
    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     * @return The queryId.
     */
    org.apache.drill.exec.proto.UserBitShared.QueryId getQueryId();
    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     */
    org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder getQueryIdOrBuilder();

    /**
     * <code>optional int32 major_fragment_id = 2;</code>
     * @return Whether the majorFragmentId field is set.
     */
    boolean hasMajorFragmentId();
    /**
     * <code>optional int32 major_fragment_id = 2;</code>
     * @return The majorFragmentId.
     */
    int getMajorFragmentId();

    /**
     * <code>optional int32 minor_fragment_id = 3;</code>
     * @return Whether the minorFragmentId field is set.
     */
    boolean hasMinorFragmentId();
    /**
     * <code>optional int32 minor_fragment_id = 3;</code>
     * @return The minorFragmentId.
     */
    int getMinorFragmentId();

    /**
     * <pre>
     * true means sending to foreman,false means sending to scan nodes
     * </pre>
     *
     * <code>optional bool to_foreman = 4;</code>
     * @return Whether the toForeman field is set.
     */
    boolean hasToForeman();
    /**
     * <pre>
     * true means sending to foreman,false means sending to scan nodes
     * </pre>
     *
     * <code>optional bool to_foreman = 4;</code>
     * @return The toForeman.
     */
    boolean getToForeman();

    /**
     * <code>repeated int32 bloom_filter_size_in_bytes = 5;</code>
     * @return A list containing the bloomFilterSizeInBytes.
     */
    java.util.List<java.lang.Integer> getBloomFilterSizeInBytesList();
    /**
     * <code>repeated int32 bloom_filter_size_in_bytes = 5;</code>
     * @return The count of bloomFilterSizeInBytes.
     */
    int getBloomFilterSizeInBytesCount();
    /**
     * <code>repeated int32 bloom_filter_size_in_bytes = 5;</code>
     * @param index The index of the element to return.
     * @return The bloomFilterSizeInBytes at the given index.
     */
    int getBloomFilterSizeInBytes(int index);

    /**
     * <pre>
     * probe fields with corresponding BloomFilters
     * </pre>
     *
     * <code>repeated string probe_fields = 6;</code>
     * @return A list containing the probeFields.
     */
    java.util.List<java.lang.String>
        getProbeFieldsList();
    /**
     * <pre>
     * probe fields with corresponding BloomFilters
     * </pre>
     *
     * <code>repeated string probe_fields = 6;</code>
     * @return The count of probeFields.
     */
    int getProbeFieldsCount();
    /**
     * <pre>
     * probe fields with corresponding BloomFilters
     * </pre>
     *
     * <code>repeated string probe_fields = 6;</code>
     * @param index The index of the element to return.
     * @return The probeFields at the given index.
     */
    java.lang.String getProbeFields(int index);
    /**
     * <pre>
     * probe fields with corresponding BloomFilters
     * </pre>
     *
     * <code>repeated string probe_fields = 6;</code>
     * @param index The index of the value to return.
     * @return The bytes of the probeFields at the given index.
     */
    com.google.protobuf.ByteString
        getProbeFieldsBytes(int index);

    /**
     * <pre>
     * the operator id of the HashJoin which generates this RuntimeFilter
     * </pre>
     *
     * <code>optional int32 hj_op_id = 7;</code>
     * @return Whether the hjOpId field is set.
     */
    boolean hasHjOpId();
    /**
     * <pre>
     * the operator id of the HashJoin which generates this RuntimeFilter
     * </pre>
     *
     * <code>optional int32 hj_op_id = 7;</code>
     * @return The hjOpId.
     */
    int getHjOpId();

    /**
     * <pre>
     * the runtime filter identifier
     * </pre>
     *
     * <code>optional int64 rf_identifier = 8;</code>
     * @return Whether the rfIdentifier field is set.
     */
    boolean hasRfIdentifier();
    /**
     * <pre>
     * the runtime filter identifier
     * </pre>
     *
     * <code>optional int64 rf_identifier = 8;</code>
     * @return The rfIdentifier.
     */
    long getRfIdentifier();
  }
  /**
   * Protobuf type {@code exec.bit.data.RuntimeFilterBDef}
   */
  public static final class RuntimeFilterBDef extends
      com.google.protobuf.GeneratedMessageV3 implements
      // @@protoc_insertion_point(message_implements:exec.bit.data.RuntimeFilterBDef)
      RuntimeFilterBDefOrBuilder {
  private static final long serialVersionUID = 0L;
    // Use RuntimeFilterBDef.newBuilder() to construct.
    private RuntimeFilterBDef(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
      super(builder);
    }
    private RuntimeFilterBDef() {
      bloomFilterSizeInBytes_ = emptyIntList();
      probeFields_ = com.google.protobuf.LazyStringArrayList.EMPTY;
    }

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

    @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.BitData.internal_static_exec_bit_data_RuntimeFilterBDef_descriptor;
    }

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

    private int bitField0_;
    public static final int QUERY_ID_FIELD_NUMBER = 1;
    private org.apache.drill.exec.proto.UserBitShared.QueryId queryId_;
    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     * @return Whether the queryId field is set.
     */
    @java.lang.Override
    public boolean hasQueryId() {
      return ((bitField0_ & 0x00000001) != 0);
    }
    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     * @return The queryId.
     */
    @java.lang.Override
    public org.apache.drill.exec.proto.UserBitShared.QueryId getQueryId() {
      return queryId_ == null ? org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance() : queryId_;
    }
    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     */
    @java.lang.Override
    public org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder getQueryIdOrBuilder() {
      return queryId_ == null ? org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance() : queryId_;
    }

    public static final int MAJOR_FRAGMENT_ID_FIELD_NUMBER = 2;
    private int majorFragmentId_;
    /**
     * <code>optional int32 major_fragment_id = 2;</code>
     * @return Whether the majorFragmentId field is set.
     */
    @java.lang.Override
    public boolean hasMajorFragmentId() {
      return ((bitField0_ & 0x00000002) != 0);
    }
    /**
     * <code>optional int32 major_fragment_id = 2;</code>
     * @return The majorFragmentId.
     */
    @java.lang.Override
    public int getMajorFragmentId() {
      return majorFragmentId_;
    }

    public static final int MINOR_FRAGMENT_ID_FIELD_NUMBER = 3;
    private int minorFragmentId_;
    /**
     * <code>optional int32 minor_fragment_id = 3;</code>
     * @return Whether the minorFragmentId field is set.
     */
    @java.lang.Override
    public boolean hasMinorFragmentId() {
      return ((bitField0_ & 0x00000004) != 0);
    }
    /**
     * <code>optional int32 minor_fragment_id = 3;</code>
     * @return The minorFragmentId.
     */
    @java.lang.Override
    public int getMinorFragmentId() {
      return minorFragmentId_;
    }

    public static final int TO_FOREMAN_FIELD_NUMBER = 4;
    private boolean toForeman_;
    /**
     * <pre>
     * true means sending to foreman,false means sending to scan nodes
     * </pre>
     *
     * <code>optional bool to_foreman = 4;</code>
     * @return Whether the toForeman field is set.
     */
    @java.lang.Override
    public boolean hasToForeman() {
      return ((bitField0_ & 0x00000008) != 0);
    }
    /**
     * <pre>
     * true means sending to foreman,false means sending to scan nodes
     * </pre>
     *
     * <code>optional bool to_foreman = 4;</code>
     * @return The toForeman.
     */
    @java.lang.Override
    public boolean getToForeman() {
      return toForeman_;
    }

    public static final int BLOOM_FILTER_SIZE_IN_BYTES_FIELD_NUMBER = 5;
    private com.google.protobuf.Internal.IntList bloomFilterSizeInBytes_;
    /**
     * <code>repeated int32 bloom_filter_size_in_bytes = 5;</code>
     * @return A list containing the bloomFilterSizeInBytes.
     */
    @java.lang.Override
    public java.util.List<java.lang.Integer>
        getBloomFilterSizeInBytesList() {
      return bloomFilterSizeInBytes_;
    }
    /**
     * <code>repeated int32 bloom_filter_size_in_bytes = 5;</code>
     * @return The count of bloomFilterSizeInBytes.
     */
    public int getBloomFilterSizeInBytesCount() {
      return bloomFilterSizeInBytes_.size();
    }
    /**
     * <code>repeated int32 bloom_filter_size_in_bytes = 5;</code>
     * @param index The index of the element to return.
     * @return The bloomFilterSizeInBytes at the given index.
     */
    public int getBloomFilterSizeInBytes(int index) {
      return bloomFilterSizeInBytes_.getInt(index);
    }

    public static final int PROBE_FIELDS_FIELD_NUMBER = 6;
    private com.google.protobuf.LazyStringList probeFields_;
    /**
     * <pre>
     * probe fields with corresponding BloomFilters
     * </pre>
     *
     * <code>repeated string probe_fields = 6;</code>
     * @return A list containing the probeFields.
     */
    public com.google.protobuf.ProtocolStringList
        getProbeFieldsList() {
      return probeFields_;
    }
    /**
     * <pre>
     * probe fields with corresponding BloomFilters
     * </pre>
     *
     * <code>repeated string probe_fields = 6;</code>
     * @return The count of probeFields.
     */
    public int getProbeFieldsCount() {
      return probeFields_.size();
    }
    /**
     * <pre>
     * probe fields with corresponding BloomFilters
     * </pre>
     *
     * <code>repeated string probe_fields = 6;</code>
     * @param index The index of the element to return.
     * @return The probeFields at the given index.
     */
    public java.lang.String getProbeFields(int index) {
      return probeFields_.get(index);
    }
    /**
     * <pre>
     * probe fields with corresponding BloomFilters
     * </pre>
     *
     * <code>repeated string probe_fields = 6;</code>
     * @param index The index of the value to return.
     * @return The bytes of the probeFields at the given index.
     */
    public com.google.protobuf.ByteString
        getProbeFieldsBytes(int index) {
      return probeFields_.getByteString(index);
    }

    public static final int HJ_OP_ID_FIELD_NUMBER = 7;
    private int hjOpId_;
    /**
     * <pre>
     * the operator id of the HashJoin which generates this RuntimeFilter
     * </pre>
     *
     * <code>optional int32 hj_op_id = 7;</code>
     * @return Whether the hjOpId field is set.
     */
    @java.lang.Override
    public boolean hasHjOpId() {
      return ((bitField0_ & 0x00000010) != 0);
    }
    /**
     * <pre>
     * the operator id of the HashJoin which generates this RuntimeFilter
     * </pre>
     *
     * <code>optional int32 hj_op_id = 7;</code>
     * @return The hjOpId.
     */
    @java.lang.Override
    public int getHjOpId() {
      return hjOpId_;
    }

    public static final int RF_IDENTIFIER_FIELD_NUMBER = 8;
    private long rfIdentifier_;
    /**
     * <pre>
     * the runtime filter identifier
     * </pre>
     *
     * <code>optional int64 rf_identifier = 8;</code>
     * @return Whether the rfIdentifier field is set.
     */
    @java.lang.Override
    public boolean hasRfIdentifier() {
      return ((bitField0_ & 0x00000020) != 0);
    }
    /**
     * <pre>
     * the runtime filter identifier
     * </pre>
     *
     * <code>optional int64 rf_identifier = 8;</code>
     * @return The rfIdentifier.
     */
    @java.lang.Override
    public long getRfIdentifier() {
      return rfIdentifier_;
    }

    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.writeMessage(1, getQueryId());
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        output.writeInt32(2, majorFragmentId_);
      }
      if (((bitField0_ & 0x00000004) != 0)) {
        output.writeInt32(3, minorFragmentId_);
      }
      if (((bitField0_ & 0x00000008) != 0)) {
        output.writeBool(4, toForeman_);
      }
      for (int i = 0; i < bloomFilterSizeInBytes_.size(); i++) {
        output.writeInt32(5, bloomFilterSizeInBytes_.getInt(i));
      }
      for (int i = 0; i < probeFields_.size(); i++) {
        com.google.protobuf.GeneratedMessageV3.writeString(output, 6, probeFields_.getRaw(i));
      }
      if (((bitField0_ & 0x00000010) != 0)) {
        output.writeInt32(7, hjOpId_);
      }
      if (((bitField0_ & 0x00000020) != 0)) {
        output.writeInt64(8, rfIdentifier_);
      }
      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
          .computeMessageSize(1, getQueryId());
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(2, majorFragmentId_);
      }
      if (((bitField0_ & 0x00000004) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(3, minorFragmentId_);
      }
      if (((bitField0_ & 0x00000008) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeBoolSize(4, toForeman_);
      }
      {
        int dataSize = 0;
        for (int i = 0; i < bloomFilterSizeInBytes_.size(); i++) {
          dataSize += com.google.protobuf.CodedOutputStream
            .computeInt32SizeNoTag(bloomFilterSizeInBytes_.getInt(i));
        }
        size += dataSize;
        size += 1 * getBloomFilterSizeInBytesList().size();
      }
      {
        int dataSize = 0;
        for (int i = 0; i < probeFields_.size(); i++) {
          dataSize += computeStringSizeNoTag(probeFields_.getRaw(i));
        }
        size += dataSize;
        size += 1 * getProbeFieldsList().size();
      }
      if (((bitField0_ & 0x00000010) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(7, hjOpId_);
      }
      if (((bitField0_ & 0x00000020) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt64Size(8, rfIdentifier_);
      }
      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.BitData.RuntimeFilterBDef)) {
        return super.equals(obj);
      }
      org.apache.drill.exec.proto.BitData.RuntimeFilterBDef other = (org.apache.drill.exec.proto.BitData.RuntimeFilterBDef) obj;

      if (hasQueryId() != other.hasQueryId()) return false;
      if (hasQueryId()) {
        if (!getQueryId()
            .equals(other.getQueryId())) return false;
      }
      if (hasMajorFragmentId() != other.hasMajorFragmentId()) return false;
      if (hasMajorFragmentId()) {
        if (getMajorFragmentId()
            != other.getMajorFragmentId()) return false;
      }
      if (hasMinorFragmentId() != other.hasMinorFragmentId()) return false;
      if (hasMinorFragmentId()) {
        if (getMinorFragmentId()
            != other.getMinorFragmentId()) return false;
      }
      if (hasToForeman() != other.hasToForeman()) return false;
      if (hasToForeman()) {
        if (getToForeman()
            != other.getToForeman()) return false;
      }
      if (!getBloomFilterSizeInBytesList()
          .equals(other.getBloomFilterSizeInBytesList())) return false;
      if (!getProbeFieldsList()
          .equals(other.getProbeFieldsList())) return false;
      if (hasHjOpId() != other.hasHjOpId()) return false;
      if (hasHjOpId()) {
        if (getHjOpId()
            != other.getHjOpId()) return false;
      }
      if (hasRfIdentifier() != other.hasRfIdentifier()) return false;
      if (hasRfIdentifier()) {
        if (getRfIdentifier()
            != other.getRfIdentifier()) 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 (hasQueryId()) {
        hash = (37 * hash) + QUERY_ID_FIELD_NUMBER;
        hash = (53 * hash) + getQueryId().hashCode();
      }
      if (hasMajorFragmentId()) {
        hash = (37 * hash) + MAJOR_FRAGMENT_ID_FIELD_NUMBER;
        hash = (53 * hash) + getMajorFragmentId();
      }
      if (hasMinorFragmentId()) {
        hash = (37 * hash) + MINOR_FRAGMENT_ID_FIELD_NUMBER;
        hash = (53 * hash) + getMinorFragmentId();
      }
      if (hasToForeman()) {
        hash = (37 * hash) + TO_FOREMAN_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(
            getToForeman());
      }
      if (getBloomFilterSizeInBytesCount() > 0) {
        hash = (37 * hash) + BLOOM_FILTER_SIZE_IN_BYTES_FIELD_NUMBER;
        hash = (53 * hash) + getBloomFilterSizeInBytesList().hashCode();
      }
      if (getProbeFieldsCount() > 0) {
        hash = (37 * hash) + PROBE_FIELDS_FIELD_NUMBER;
        hash = (53 * hash) + getProbeFieldsList().hashCode();
      }
      if (hasHjOpId()) {
        hash = (37 * hash) + HJ_OP_ID_FIELD_NUMBER;
        hash = (53 * hash) + getHjOpId();
      }
      if (hasRfIdentifier()) {
        hash = (37 * hash) + RF_IDENTIFIER_FIELD_NUMBER;
        hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
            getRfIdentifier());
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.drill.exec.proto.BitData.RuntimeFilterBDef parseFrom(
        java.nio.ByteBuffer data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.BitData.RuntimeFilterBDef 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.BitData.RuntimeFilterBDef parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.BitData.RuntimeFilterBDef 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.BitData.RuntimeFilterBDef parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.BitData.RuntimeFilterBDef 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.BitData.RuntimeFilterBDef parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.BitData.RuntimeFilterBDef 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.BitData.RuntimeFilterBDef parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.BitData.RuntimeFilterBDef 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.BitData.RuntimeFilterBDef 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.BitData.RuntimeFilterBDef 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.BitData.RuntimeFilterBDef 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.bit.data.RuntimeFilterBDef}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
        // @@protoc_insertion_point(builder_implements:exec.bit.data.RuntimeFilterBDef)
        org.apache.drill.exec.proto.BitData.RuntimeFilterBDefOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.drill.exec.proto.BitData.internal_static_exec_bit_data_RuntimeFilterBDef_descriptor;
      }

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

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

      private Builder(
          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessageV3
                .alwaysUseFieldBuilders) {
          getQueryIdFieldBuilder();
        }
      }
      @java.lang.Override
      public Builder clear() {
        super.clear();
        if (queryIdBuilder_ == null) {
          queryId_ = null;
        } else {
          queryIdBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000001);
        majorFragmentId_ = 0;
        bitField0_ = (bitField0_ & ~0x00000002);
        minorFragmentId_ = 0;
        bitField0_ = (bitField0_ & ~0x00000004);
        toForeman_ = false;
        bitField0_ = (bitField0_ & ~0x00000008);
        bloomFilterSizeInBytes_ = emptyIntList();
        bitField0_ = (bitField0_ & ~0x00000010);
        probeFields_ = com.google.protobuf.LazyStringArrayList.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000020);
        hjOpId_ = 0;
        bitField0_ = (bitField0_ & ~0x00000040);
        rfIdentifier_ = 0L;
        bitField0_ = (bitField0_ & ~0x00000080);
        return this;
      }

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

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

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

      @java.lang.Override
      public org.apache.drill.exec.proto.BitData.RuntimeFilterBDef buildPartial() {
        org.apache.drill.exec.proto.BitData.RuntimeFilterBDef result = new org.apache.drill.exec.proto.BitData.RuntimeFilterBDef(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) != 0)) {
          if (queryIdBuilder_ == null) {
            result.queryId_ = queryId_;
          } else {
            result.queryId_ = queryIdBuilder_.build();
          }
          to_bitField0_ |= 0x00000001;
        }
        if (((from_bitField0_ & 0x00000002) != 0)) {
          result.majorFragmentId_ = majorFragmentId_;
          to_bitField0_ |= 0x00000002;
        }
        if (((from_bitField0_ & 0x00000004) != 0)) {
          result.minorFragmentId_ = minorFragmentId_;
          to_bitField0_ |= 0x00000004;
        }
        if (((from_bitField0_ & 0x00000008) != 0)) {
          result.toForeman_ = toForeman_;
          to_bitField0_ |= 0x00000008;
        }
        if (((bitField0_ & 0x00000010) != 0)) {
          bloomFilterSizeInBytes_.makeImmutable();
          bitField0_ = (bitField0_ & ~0x00000010);
        }
        result.bloomFilterSizeInBytes_ = bloomFilterSizeInBytes_;
        if (((bitField0_ & 0x00000020) != 0)) {
          probeFields_ = probeFields_.getUnmodifiableView();
          bitField0_ = (bitField0_ & ~0x00000020);
        }
        result.probeFields_ = probeFields_;
        if (((from_bitField0_ & 0x00000040) != 0)) {
          result.hjOpId_ = hjOpId_;
          to_bitField0_ |= 0x00000010;
        }
        if (((from_bitField0_ & 0x00000080) != 0)) {
          result.rfIdentifier_ = rfIdentifier_;
          to_bitField0_ |= 0x00000020;
        }
        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.BitData.RuntimeFilterBDef) {
          return mergeFrom((org.apache.drill.exec.proto.BitData.RuntimeFilterBDef)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.drill.exec.proto.BitData.RuntimeFilterBDef other) {
        if (other == org.apache.drill.exec.proto.BitData.RuntimeFilterBDef.getDefaultInstance()) return this;
        if (other.hasQueryId()) {
          mergeQueryId(other.getQueryId());
        }
        if (other.hasMajorFragmentId()) {
          setMajorFragmentId(other.getMajorFragmentId());
        }
        if (other.hasMinorFragmentId()) {
          setMinorFragmentId(other.getMinorFragmentId());
        }
        if (other.hasToForeman()) {
          setToForeman(other.getToForeman());
        }
        if (!other.bloomFilterSizeInBytes_.isEmpty()) {
          if (bloomFilterSizeInBytes_.isEmpty()) {
            bloomFilterSizeInBytes_ = other.bloomFilterSizeInBytes_;
            bitField0_ = (bitField0_ & ~0x00000010);
          } else {
            ensureBloomFilterSizeInBytesIsMutable();
            bloomFilterSizeInBytes_.addAll(other.bloomFilterSizeInBytes_);
          }
          onChanged();
        }
        if (!other.probeFields_.isEmpty()) {
          if (probeFields_.isEmpty()) {
            probeFields_ = other.probeFields_;
            bitField0_ = (bitField0_ & ~0x00000020);
          } else {
            ensureProbeFieldsIsMutable();
            probeFields_.addAll(other.probeFields_);
          }
          onChanged();
        }
        if (other.hasHjOpId()) {
          setHjOpId(other.getHjOpId());
        }
        if (other.hasRfIdentifier()) {
          setRfIdentifier(other.getRfIdentifier());
        }
        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: {
                input.readMessage(
                    getQueryIdFieldBuilder().getBuilder(),
                    extensionRegistry);
                bitField0_ |= 0x00000001;
                break;
              } // case 10
              case 16: {
                majorFragmentId_ = input.readInt32();
                bitField0_ |= 0x00000002;
                break;
              } // case 16
              case 24: {
                minorFragmentId_ = input.readInt32();
                bitField0_ |= 0x00000004;
                break;
              } // case 24
              case 32: {
                toForeman_ = input.readBool();
                bitField0_ |= 0x00000008;
                break;
              } // case 32
              case 40: {
                int v = input.readInt32();
                ensureBloomFilterSizeInBytesIsMutable();
                bloomFilterSizeInBytes_.addInt(v);
                break;
              } // case 40
              case 42: {
                int length = input.readRawVarint32();
                int limit = input.pushLimit(length);
                ensureBloomFilterSizeInBytesIsMutable();
                while (input.getBytesUntilLimit() > 0) {
                  bloomFilterSizeInBytes_.addInt(input.readInt32());
                }
                input.popLimit(limit);
                break;
              } // case 42
              case 50: {
                com.google.protobuf.ByteString bs = input.readBytes();
                ensureProbeFieldsIsMutable();
                probeFields_.add(bs);
                break;
              } // case 50
              case 56: {
                hjOpId_ = input.readInt32();
                bitField0_ |= 0x00000040;
                break;
              } // case 56
              case 64: {
                rfIdentifier_ = input.readInt64();
                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 org.apache.drill.exec.proto.UserBitShared.QueryId queryId_;
      private com.google.protobuf.SingleFieldBuilderV3<
          org.apache.drill.exec.proto.UserBitShared.QueryId, org.apache.drill.exec.proto.UserBitShared.QueryId.Builder, org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder> queryIdBuilder_;
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       * @return Whether the queryId field is set.
       */
      public boolean hasQueryId() {
        return ((bitField0_ & 0x00000001) != 0);
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       * @return The queryId.
       */
      public org.apache.drill.exec.proto.UserBitShared.QueryId getQueryId() {
        if (queryIdBuilder_ == null) {
          return queryId_ == null ? org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance() : queryId_;
        } else {
          return queryIdBuilder_.getMessage();
        }
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public Builder setQueryId(org.apache.drill.exec.proto.UserBitShared.QueryId value) {
        if (queryIdBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          queryId_ = value;
          onChanged();
        } else {
          queryIdBuilder_.setMessage(value);
        }
        bitField0_ |= 0x00000001;
        return this;
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public Builder setQueryId(
          org.apache.drill.exec.proto.UserBitShared.QueryId.Builder builderForValue) {
        if (queryIdBuilder_ == null) {
          queryId_ = builderForValue.build();
          onChanged();
        } else {
          queryIdBuilder_.setMessage(builderForValue.build());
        }
        bitField0_ |= 0x00000001;
        return this;
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public Builder mergeQueryId(org.apache.drill.exec.proto.UserBitShared.QueryId value) {
        if (queryIdBuilder_ == null) {
          if (((bitField0_ & 0x00000001) != 0) &&
              queryId_ != null &&
              queryId_ != org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance()) {
            queryId_ =
              org.apache.drill.exec.proto.UserBitShared.QueryId.newBuilder(queryId_).mergeFrom(value).buildPartial();
          } else {
            queryId_ = value;
          }
          onChanged();
        } else {
          queryIdBuilder_.mergeFrom(value);
        }
        bitField0_ |= 0x00000001;
        return this;
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public Builder clearQueryId() {
        if (queryIdBuilder_ == null) {
          queryId_ = null;
          onChanged();
        } else {
          queryIdBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public org.apache.drill.exec.proto.UserBitShared.QueryId.Builder getQueryIdBuilder() {
        bitField0_ |= 0x00000001;
        onChanged();
        return getQueryIdFieldBuilder().getBuilder();
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder getQueryIdOrBuilder() {
        if (queryIdBuilder_ != null) {
          return queryIdBuilder_.getMessageOrBuilder();
        } else {
          return queryId_ == null ?
              org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance() : queryId_;
        }
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      private com.google.protobuf.SingleFieldBuilderV3<
          org.apache.drill.exec.proto.UserBitShared.QueryId, org.apache.drill.exec.proto.UserBitShared.QueryId.Builder, org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder> 
          getQueryIdFieldBuilder() {
        if (queryIdBuilder_ == null) {
          queryIdBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
              org.apache.drill.exec.proto.UserBitShared.QueryId, org.apache.drill.exec.proto.UserBitShared.QueryId.Builder, org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder>(
                  getQueryId(),
                  getParentForChildren(),
                  isClean());
          queryId_ = null;
        }
        return queryIdBuilder_;
      }

      private int majorFragmentId_ ;
      /**
       * <code>optional int32 major_fragment_id = 2;</code>
       * @return Whether the majorFragmentId field is set.
       */
      @java.lang.Override
      public boolean hasMajorFragmentId() {
        return ((bitField0_ & 0x00000002) != 0);
      }
      /**
       * <code>optional int32 major_fragment_id = 2;</code>
       * @return The majorFragmentId.
       */
      @java.lang.Override
      public int getMajorFragmentId() {
        return majorFragmentId_;
      }
      /**
       * <code>optional int32 major_fragment_id = 2;</code>
       * @param value The majorFragmentId to set.
       * @return This builder for chaining.
       */
      public Builder setMajorFragmentId(int value) {
        bitField0_ |= 0x00000002;
        majorFragmentId_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional int32 major_fragment_id = 2;</code>
       * @return This builder for chaining.
       */
      public Builder clearMajorFragmentId() {
        bitField0_ = (bitField0_ & ~0x00000002);
        majorFragmentId_ = 0;
        onChanged();
        return this;
      }

      private int minorFragmentId_ ;
      /**
       * <code>optional int32 minor_fragment_id = 3;</code>
       * @return Whether the minorFragmentId field is set.
       */
      @java.lang.Override
      public boolean hasMinorFragmentId() {
        return ((bitField0_ & 0x00000004) != 0);
      }
      /**
       * <code>optional int32 minor_fragment_id = 3;</code>
       * @return The minorFragmentId.
       */
      @java.lang.Override
      public int getMinorFragmentId() {
        return minorFragmentId_;
      }
      /**
       * <code>optional int32 minor_fragment_id = 3;</code>
       * @param value The minorFragmentId to set.
       * @return This builder for chaining.
       */
      public Builder setMinorFragmentId(int value) {
        bitField0_ |= 0x00000004;
        minorFragmentId_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional int32 minor_fragment_id = 3;</code>
       * @return This builder for chaining.
       */
      public Builder clearMinorFragmentId() {
        bitField0_ = (bitField0_ & ~0x00000004);
        minorFragmentId_ = 0;
        onChanged();
        return this;
      }

      private boolean toForeman_ ;
      /**
       * <pre>
       * true means sending to foreman,false means sending to scan nodes
       * </pre>
       *
       * <code>optional bool to_foreman = 4;</code>
       * @return Whether the toForeman field is set.
       */
      @java.lang.Override
      public boolean hasToForeman() {
        return ((bitField0_ & 0x00000008) != 0);
      }
      /**
       * <pre>
       * true means sending to foreman,false means sending to scan nodes
       * </pre>
       *
       * <code>optional bool to_foreman = 4;</code>
       * @return The toForeman.
       */
      @java.lang.Override
      public boolean getToForeman() {
        return toForeman_;
      }
      /**
       * <pre>
       * true means sending to foreman,false means sending to scan nodes
       * </pre>
       *
       * <code>optional bool to_foreman = 4;</code>
       * @param value The toForeman to set.
       * @return This builder for chaining.
       */
      public Builder setToForeman(boolean value) {
        bitField0_ |= 0x00000008;
        toForeman_ = value;
        onChanged();
        return this;
      }
      /**
       * <pre>
       * true means sending to foreman,false means sending to scan nodes
       * </pre>
       *
       * <code>optional bool to_foreman = 4;</code>
       * @return This builder for chaining.
       */
      public Builder clearToForeman() {
        bitField0_ = (bitField0_ & ~0x00000008);
        toForeman_ = false;
        onChanged();
        return this;
      }

      private com.google.protobuf.Internal.IntList bloomFilterSizeInBytes_ = emptyIntList();
      private void ensureBloomFilterSizeInBytesIsMutable() {
        if (!((bitField0_ & 0x00000010) != 0)) {
          bloomFilterSizeInBytes_ = mutableCopy(bloomFilterSizeInBytes_);
          bitField0_ |= 0x00000010;
         }
      }
      /**
       * <code>repeated int32 bloom_filter_size_in_bytes = 5;</code>
       * @return A list containing the bloomFilterSizeInBytes.
       */
      public java.util.List<java.lang.Integer>
          getBloomFilterSizeInBytesList() {
        return ((bitField0_ & 0x00000010) != 0) ?
                 java.util.Collections.unmodifiableList(bloomFilterSizeInBytes_) : bloomFilterSizeInBytes_;
      }
      /**
       * <code>repeated int32 bloom_filter_size_in_bytes = 5;</code>
       * @return The count of bloomFilterSizeInBytes.
       */
      public int getBloomFilterSizeInBytesCount() {
        return bloomFilterSizeInBytes_.size();
      }
      /**
       * <code>repeated int32 bloom_filter_size_in_bytes = 5;</code>
       * @param index The index of the element to return.
       * @return The bloomFilterSizeInBytes at the given index.
       */
      public int getBloomFilterSizeInBytes(int index) {
        return bloomFilterSizeInBytes_.getInt(index);
      }
      /**
       * <code>repeated int32 bloom_filter_size_in_bytes = 5;</code>
       * @param index The index to set the value at.
       * @param value The bloomFilterSizeInBytes to set.
       * @return This builder for chaining.
       */
      public Builder setBloomFilterSizeInBytes(
          int index, int value) {
        ensureBloomFilterSizeInBytesIsMutable();
        bloomFilterSizeInBytes_.setInt(index, value);
        onChanged();
        return this;
      }
      /**
       * <code>repeated int32 bloom_filter_size_in_bytes = 5;</code>
       * @param value The bloomFilterSizeInBytes to add.
       * @return This builder for chaining.
       */
      public Builder addBloomFilterSizeInBytes(int value) {
        ensureBloomFilterSizeInBytesIsMutable();
        bloomFilterSizeInBytes_.addInt(value);
        onChanged();
        return this;
      }
      /**
       * <code>repeated int32 bloom_filter_size_in_bytes = 5;</code>
       * @param values The bloomFilterSizeInBytes to add.
       * @return This builder for chaining.
       */
      public Builder addAllBloomFilterSizeInBytes(
          java.lang.Iterable<? extends java.lang.Integer> values) {
        ensureBloomFilterSizeInBytesIsMutable();
        com.google.protobuf.AbstractMessageLite.Builder.addAll(
            values, bloomFilterSizeInBytes_);
        onChanged();
        return this;
      }
      /**
       * <code>repeated int32 bloom_filter_size_in_bytes = 5;</code>
       * @return This builder for chaining.
       */
      public Builder clearBloomFilterSizeInBytes() {
        bloomFilterSizeInBytes_ = emptyIntList();
        bitField0_ = (bitField0_ & ~0x00000010);
        onChanged();
        return this;
      }

      private com.google.protobuf.LazyStringList probeFields_ = com.google.protobuf.LazyStringArrayList.EMPTY;
      private void ensureProbeFieldsIsMutable() {
        if (!((bitField0_ & 0x00000020) != 0)) {
          probeFields_ = new com.google.protobuf.LazyStringArrayList(probeFields_);
          bitField0_ |= 0x00000020;
         }
      }
      /**
       * <pre>
       * probe fields with corresponding BloomFilters
       * </pre>
       *
       * <code>repeated string probe_fields = 6;</code>
       * @return A list containing the probeFields.
       */
      public com.google.protobuf.ProtocolStringList
          getProbeFieldsList() {
        return probeFields_.getUnmodifiableView();
      }
      /**
       * <pre>
       * probe fields with corresponding BloomFilters
       * </pre>
       *
       * <code>repeated string probe_fields = 6;</code>
       * @return The count of probeFields.
       */
      public int getProbeFieldsCount() {
        return probeFields_.size();
      }
      /**
       * <pre>
       * probe fields with corresponding BloomFilters
       * </pre>
       *
       * <code>repeated string probe_fields = 6;</code>
       * @param index The index of the element to return.
       * @return The probeFields at the given index.
       */
      public java.lang.String getProbeFields(int index) {
        return probeFields_.get(index);
      }
      /**
       * <pre>
       * probe fields with corresponding BloomFilters
       * </pre>
       *
       * <code>repeated string probe_fields = 6;</code>
       * @param index The index of the value to return.
       * @return The bytes of the probeFields at the given index.
       */
      public com.google.protobuf.ByteString
          getProbeFieldsBytes(int index) {
        return probeFields_.getByteString(index);
      }
      /**
       * <pre>
       * probe fields with corresponding BloomFilters
       * </pre>
       *
       * <code>repeated string probe_fields = 6;</code>
       * @param index The index to set the value at.
       * @param value The probeFields to set.
       * @return This builder for chaining.
       */
      public Builder setProbeFields(
          int index, java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureProbeFieldsIsMutable();
        probeFields_.set(index, value);
        onChanged();
        return this;
      }
      /**
       * <pre>
       * probe fields with corresponding BloomFilters
       * </pre>
       *
       * <code>repeated string probe_fields = 6;</code>
       * @param value The probeFields to add.
       * @return This builder for chaining.
       */
      public Builder addProbeFields(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureProbeFieldsIsMutable();
        probeFields_.add(value);
        onChanged();
        return this;
      }
      /**
       * <pre>
       * probe fields with corresponding BloomFilters
       * </pre>
       *
       * <code>repeated string probe_fields = 6;</code>
       * @param values The probeFields to add.
       * @return This builder for chaining.
       */
      public Builder addAllProbeFields(
          java.lang.Iterable<java.lang.String> values) {
        ensureProbeFieldsIsMutable();
        com.google.protobuf.AbstractMessageLite.Builder.addAll(
            values, probeFields_);
        onChanged();
        return this;
      }
      /**
       * <pre>
       * probe fields with corresponding BloomFilters
       * </pre>
       *
       * <code>repeated string probe_fields = 6;</code>
       * @return This builder for chaining.
       */
      public Builder clearProbeFields() {
        probeFields_ = com.google.protobuf.LazyStringArrayList.EMPTY;
        bitField0_ = (bitField0_ & ~0x00000020);
        onChanged();
        return this;
      }
      /**
       * <pre>
       * probe fields with corresponding BloomFilters
       * </pre>
       *
       * <code>repeated string probe_fields = 6;</code>
       * @param value The bytes of the probeFields to add.
       * @return This builder for chaining.
       */
      public Builder addProbeFieldsBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  ensureProbeFieldsIsMutable();
        probeFields_.add(value);
        onChanged();
        return this;
      }

      private int hjOpId_ ;
      /**
       * <pre>
       * the operator id of the HashJoin which generates this RuntimeFilter
       * </pre>
       *
       * <code>optional int32 hj_op_id = 7;</code>
       * @return Whether the hjOpId field is set.
       */
      @java.lang.Override
      public boolean hasHjOpId() {
        return ((bitField0_ & 0x00000040) != 0);
      }
      /**
       * <pre>
       * the operator id of the HashJoin which generates this RuntimeFilter
       * </pre>
       *
       * <code>optional int32 hj_op_id = 7;</code>
       * @return The hjOpId.
       */
      @java.lang.Override
      public int getHjOpId() {
        return hjOpId_;
      }
      /**
       * <pre>
       * the operator id of the HashJoin which generates this RuntimeFilter
       * </pre>
       *
       * <code>optional int32 hj_op_id = 7;</code>
       * @param value The hjOpId to set.
       * @return This builder for chaining.
       */
      public Builder setHjOpId(int value) {
        bitField0_ |= 0x00000040;
        hjOpId_ = value;
        onChanged();
        return this;
      }
      /**
       * <pre>
       * the operator id of the HashJoin which generates this RuntimeFilter
       * </pre>
       *
       * <code>optional int32 hj_op_id = 7;</code>
       * @return This builder for chaining.
       */
      public Builder clearHjOpId() {
        bitField0_ = (bitField0_ & ~0x00000040);
        hjOpId_ = 0;
        onChanged();
        return this;
      }

      private long rfIdentifier_ ;
      /**
       * <pre>
       * the runtime filter identifier
       * </pre>
       *
       * <code>optional int64 rf_identifier = 8;</code>
       * @return Whether the rfIdentifier field is set.
       */
      @java.lang.Override
      public boolean hasRfIdentifier() {
        return ((bitField0_ & 0x00000080) != 0);
      }
      /**
       * <pre>
       * the runtime filter identifier
       * </pre>
       *
       * <code>optional int64 rf_identifier = 8;</code>
       * @return The rfIdentifier.
       */
      @java.lang.Override
      public long getRfIdentifier() {
        return rfIdentifier_;
      }
      /**
       * <pre>
       * the runtime filter identifier
       * </pre>
       *
       * <code>optional int64 rf_identifier = 8;</code>
       * @param value The rfIdentifier to set.
       * @return This builder for chaining.
       */
      public Builder setRfIdentifier(long value) {
        bitField0_ |= 0x00000080;
        rfIdentifier_ = value;
        onChanged();
        return this;
      }
      /**
       * <pre>
       * the runtime filter identifier
       * </pre>
       *
       * <code>optional int64 rf_identifier = 8;</code>
       * @return This builder for chaining.
       */
      public Builder clearRfIdentifier() {
        bitField0_ = (bitField0_ & ~0x00000080);
        rfIdentifier_ = 0L;
        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.bit.data.RuntimeFilterBDef)
    }

    // @@protoc_insertion_point(class_scope:exec.bit.data.RuntimeFilterBDef)
    private static final org.apache.drill.exec.proto.BitData.RuntimeFilterBDef DEFAULT_INSTANCE;
    static {
      DEFAULT_INSTANCE = new org.apache.drill.exec.proto.BitData.RuntimeFilterBDef();
    }

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

    @java.lang.Deprecated public static final com.google.protobuf.Parser<RuntimeFilterBDef>
        PARSER = new com.google.protobuf.AbstractParser<RuntimeFilterBDef>() {
      @java.lang.Override
      public RuntimeFilterBDef 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<RuntimeFilterBDef> parser() {
      return PARSER;
    }

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

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

  }

  public interface AckWithCreditOrBuilder extends
      // @@protoc_insertion_point(interface_extends:exec.bit.data.AckWithCredit)
      com.google.protobuf.MessageOrBuilder {

    /**
     * <pre>
     * the credit allowed the sender to send in batch granularity
     * </pre>
     *
     * <code>optional int32 allowed_credit = 1;</code>
     * @return Whether the allowedCredit field is set.
     */
    boolean hasAllowedCredit();
    /**
     * <pre>
     * the credit allowed the sender to send in batch granularity
     * </pre>
     *
     * <code>optional int32 allowed_credit = 1;</code>
     * @return The allowedCredit.
     */
    int getAllowedCredit();
  }
  /**
   * Protobuf type {@code exec.bit.data.AckWithCredit}
   */
  public static final class AckWithCredit extends
      com.google.protobuf.GeneratedMessageV3 implements
      // @@protoc_insertion_point(message_implements:exec.bit.data.AckWithCredit)
      AckWithCreditOrBuilder {
  private static final long serialVersionUID = 0L;
    // Use AckWithCredit.newBuilder() to construct.
    private AckWithCredit(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
      super(builder);
    }
    private AckWithCredit() {
    }

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

    @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.BitData.internal_static_exec_bit_data_AckWithCredit_descriptor;
    }

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

    private int bitField0_;
    public static final int ALLOWED_CREDIT_FIELD_NUMBER = 1;
    private int allowedCredit_;
    /**
     * <pre>
     * the credit allowed the sender to send in batch granularity
     * </pre>
     *
     * <code>optional int32 allowed_credit = 1;</code>
     * @return Whether the allowedCredit field is set.
     */
    @java.lang.Override
    public boolean hasAllowedCredit() {
      return ((bitField0_ & 0x00000001) != 0);
    }
    /**
     * <pre>
     * the credit allowed the sender to send in batch granularity
     * </pre>
     *
     * <code>optional int32 allowed_credit = 1;</code>
     * @return The allowedCredit.
     */
    @java.lang.Override
    public int getAllowedCredit() {
      return allowedCredit_;
    }

    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.writeInt32(1, allowedCredit_);
      }
      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
          .computeInt32Size(1, allowedCredit_);
      }
      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.BitData.AckWithCredit)) {
        return super.equals(obj);
      }
      org.apache.drill.exec.proto.BitData.AckWithCredit other = (org.apache.drill.exec.proto.BitData.AckWithCredit) obj;

      if (hasAllowedCredit() != other.hasAllowedCredit()) return false;
      if (hasAllowedCredit()) {
        if (getAllowedCredit()
            != other.getAllowedCredit()) 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 (hasAllowedCredit()) {
        hash = (37 * hash) + ALLOWED_CREDIT_FIELD_NUMBER;
        hash = (53 * hash) + getAllowedCredit();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.drill.exec.proto.BitData.AckWithCredit parseFrom(
        java.nio.ByteBuffer data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.BitData.AckWithCredit 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.BitData.AckWithCredit parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.BitData.AckWithCredit 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.BitData.AckWithCredit parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.BitData.AckWithCredit 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.BitData.AckWithCredit parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.BitData.AckWithCredit 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.BitData.AckWithCredit parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.BitData.AckWithCredit 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.BitData.AckWithCredit 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.BitData.AckWithCredit 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.BitData.AckWithCredit 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.bit.data.AckWithCredit}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
        // @@protoc_insertion_point(builder_implements:exec.bit.data.AckWithCredit)
        org.apache.drill.exec.proto.BitData.AckWithCreditOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.drill.exec.proto.BitData.internal_static_exec_bit_data_AckWithCredit_descriptor;
      }

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

      // Construct using org.apache.drill.exec.proto.BitData.AckWithCredit.newBuilder()
      private Builder() {

      }

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

      }
      @java.lang.Override
      public Builder clear() {
        super.clear();
        allowedCredit_ = 0;
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }

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

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

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

      @java.lang.Override
      public org.apache.drill.exec.proto.BitData.AckWithCredit buildPartial() {
        org.apache.drill.exec.proto.BitData.AckWithCredit result = new org.apache.drill.exec.proto.BitData.AckWithCredit(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) != 0)) {
          result.allowedCredit_ = allowedCredit_;
          to_bitField0_ |= 0x00000001;
        }
        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.BitData.AckWithCredit) {
          return mergeFrom((org.apache.drill.exec.proto.BitData.AckWithCredit)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.drill.exec.proto.BitData.AckWithCredit other) {
        if (other == org.apache.drill.exec.proto.BitData.AckWithCredit.getDefaultInstance()) return this;
        if (other.hasAllowedCredit()) {
          setAllowedCredit(other.getAllowedCredit());
        }
        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: {
                allowedCredit_ = input.readInt32();
                bitField0_ |= 0x00000001;
                break;
              } // case 8
              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 int allowedCredit_ ;
      /**
       * <pre>
       * the credit allowed the sender to send in batch granularity
       * </pre>
       *
       * <code>optional int32 allowed_credit = 1;</code>
       * @return Whether the allowedCredit field is set.
       */
      @java.lang.Override
      public boolean hasAllowedCredit() {
        return ((bitField0_ & 0x00000001) != 0);
      }
      /**
       * <pre>
       * the credit allowed the sender to send in batch granularity
       * </pre>
       *
       * <code>optional int32 allowed_credit = 1;</code>
       * @return The allowedCredit.
       */
      @java.lang.Override
      public int getAllowedCredit() {
        return allowedCredit_;
      }
      /**
       * <pre>
       * the credit allowed the sender to send in batch granularity
       * </pre>
       *
       * <code>optional int32 allowed_credit = 1;</code>
       * @param value The allowedCredit to set.
       * @return This builder for chaining.
       */
      public Builder setAllowedCredit(int value) {
        bitField0_ |= 0x00000001;
        allowedCredit_ = value;
        onChanged();
        return this;
      }
      /**
       * <pre>
       * the credit allowed the sender to send in batch granularity
       * </pre>
       *
       * <code>optional int32 allowed_credit = 1;</code>
       * @return This builder for chaining.
       */
      public Builder clearAllowedCredit() {
        bitField0_ = (bitField0_ & ~0x00000001);
        allowedCredit_ = 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.bit.data.AckWithCredit)
    }

    // @@protoc_insertion_point(class_scope:exec.bit.data.AckWithCredit)
    private static final org.apache.drill.exec.proto.BitData.AckWithCredit DEFAULT_INSTANCE;
    static {
      DEFAULT_INSTANCE = new org.apache.drill.exec.proto.BitData.AckWithCredit();
    }

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

    @java.lang.Deprecated public static final com.google.protobuf.Parser<AckWithCredit>
        PARSER = new com.google.protobuf.AbstractParser<AckWithCredit>() {
      @java.lang.Override
      public AckWithCredit 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<AckWithCredit> parser() {
      return PARSER;
    }

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

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

  }

  private static final com.google.protobuf.Descriptors.Descriptor
    internal_static_exec_bit_data_BitClientHandshake_descriptor;
  private static final 
    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
      internal_static_exec_bit_data_BitClientHandshake_fieldAccessorTable;
  private static final com.google.protobuf.Descriptors.Descriptor
    internal_static_exec_bit_data_BitServerHandshake_descriptor;
  private static final 
    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
      internal_static_exec_bit_data_BitServerHandshake_fieldAccessorTable;
  private static final com.google.protobuf.Descriptors.Descriptor
    internal_static_exec_bit_data_FragmentRecordBatch_descriptor;
  private static final 
    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
      internal_static_exec_bit_data_FragmentRecordBatch_fieldAccessorTable;
  private static final com.google.protobuf.Descriptors.Descriptor
    internal_static_exec_bit_data_RuntimeFilterBDef_descriptor;
  private static final 
    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
      internal_static_exec_bit_data_RuntimeFilterBDef_fieldAccessorTable;
  private static final com.google.protobuf.Descriptors.Descriptor
    internal_static_exec_bit_data_AckWithCredit_descriptor;
  private static final 
    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
      internal_static_exec_bit_data_AckWithCredit_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\rBitData.proto\022\rexec.bit.data\032\025Executio" +
      "nProtos.proto\032\022Coordination.proto\032\023UserB" +
      "itShared.proto\"]\n\022BitClientHandshake\022\023\n\013" +
      "rpc_version\030\001 \001(\005\0222\n\007channel\030\002 \001(\0162\027.exe" +
      "c.shared.RpcChannel:\010BIT_DATA\"K\n\022BitServ" +
      "erHandshake\022\023\n\013rpc_version\030\001 \001(\005\022 \n\030auth" +
      "enticationMechanisms\030\002 \003(\t\"\214\002\n\023FragmentR" +
      "ecordBatch\022&\n\010query_id\030\001 \001(\0132\024.exec.shar" +
      "ed.QueryId\022#\n\033receiving_major_fragment_i" +
      "d\030\002 \001(\005\022#\n\033receiving_minor_fragment_id\030\003" +
      " \003(\005\022!\n\031sending_major_fragment_id\030\004 \001(\005\022" +
      "!\n\031sending_minor_fragment_id\030\005 \001(\005\022(\n\003de" +
      "f\030\006 \001(\0132\033.exec.shared.RecordBatchDef\022\023\n\013" +
      "isLastBatch\030\007 \001(\010\"\350\001\n\021RuntimeFilterBDef\022" +
      "&\n\010query_id\030\001 \001(\0132\024.exec.shared.QueryId\022" +
      "\031\n\021major_fragment_id\030\002 \001(\005\022\031\n\021minor_frag" +
      "ment_id\030\003 \001(\005\022\022\n\nto_foreman\030\004 \001(\010\022\"\n\032blo" +
      "om_filter_size_in_bytes\030\005 \003(\005\022\024\n\014probe_f" +
      "ields\030\006 \003(\t\022\020\n\010hj_op_id\030\007 \001(\005\022\025\n\rrf_iden" +
      "tifier\030\010 \001(\003\"\'\n\rAckWithCredit\022\026\n\016allowed" +
      "_credit\030\001 \001(\005*\210\001\n\007RpcType\022\r\n\tHANDSHAKE\020\000" +
      "\022\007\n\003ACK\020\001\022\013\n\007GOODBYE\020\002\022\024\n\020REQ_RECORD_BAT" +
      "CH\020\003\022\020\n\014SASL_MESSAGE\020\004\022\026\n\022REQ_RUNTIME_FI" +
      "LTER\020\005\022\030\n\024DATA_ACK_WITH_CREDIT\020\006B(\n\033org." +
      "apache.drill.exec.protoB\007BitDataH\001"
    };
    descriptor = com.google.protobuf.Descriptors.FileDescriptor
      .internalBuildGeneratedFileFrom(descriptorData,
        new com.google.protobuf.Descriptors.FileDescriptor[] {
          org.apache.drill.exec.proto.ExecProtos.getDescriptor(),
          org.apache.drill.exec.proto.CoordinationProtos.getDescriptor(),
          org.apache.drill.exec.proto.UserBitShared.getDescriptor(),
        });
    internal_static_exec_bit_data_BitClientHandshake_descriptor =
      getDescriptor().getMessageTypes().get(0);
    internal_static_exec_bit_data_BitClientHandshake_fieldAccessorTable = new
      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
        internal_static_exec_bit_data_BitClientHandshake_descriptor,
        new java.lang.String[] { "RpcVersion", "Channel", });
    internal_static_exec_bit_data_BitServerHandshake_descriptor =
      getDescriptor().getMessageTypes().get(1);
    internal_static_exec_bit_data_BitServerHandshake_fieldAccessorTable = new
      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
        internal_static_exec_bit_data_BitServerHandshake_descriptor,
        new java.lang.String[] { "RpcVersion", "AuthenticationMechanisms", });
    internal_static_exec_bit_data_FragmentRecordBatch_descriptor =
      getDescriptor().getMessageTypes().get(2);
    internal_static_exec_bit_data_FragmentRecordBatch_fieldAccessorTable = new
      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
        internal_static_exec_bit_data_FragmentRecordBatch_descriptor,
        new java.lang.String[] { "QueryId", "ReceivingMajorFragmentId", "ReceivingMinorFragmentId", "SendingMajorFragmentId", "SendingMinorFragmentId", "Def", "IsLastBatch", });
    internal_static_exec_bit_data_RuntimeFilterBDef_descriptor =
      getDescriptor().getMessageTypes().get(3);
    internal_static_exec_bit_data_RuntimeFilterBDef_fieldAccessorTable = new
      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
        internal_static_exec_bit_data_RuntimeFilterBDef_descriptor,
        new java.lang.String[] { "QueryId", "MajorFragmentId", "MinorFragmentId", "ToForeman", "BloomFilterSizeInBytes", "ProbeFields", "HjOpId", "RfIdentifier", });
    internal_static_exec_bit_data_AckWithCredit_descriptor =
      getDescriptor().getMessageTypes().get(4);
    internal_static_exec_bit_data_AckWithCredit_fieldAccessorTable = new
      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
        internal_static_exec_bit_data_AckWithCredit_descriptor,
        new java.lang.String[] { "AllowedCredit", });
    org.apache.drill.exec.proto.ExecProtos.getDescriptor();
    org.apache.drill.exec.proto.CoordinationProtos.getDescriptor();
    org.apache.drill.exec.proto.UserBitShared.getDescriptor();
  }

  // @@protoc_insertion_point(outer_class_scope)
}
