// 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: ClientProtocol.proto
#pragma warning disable 1591, 0612, 3021
#region Designer generated code

using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Org.Apache.REEF.Bridge.Proto {

  /// <summary>Holder for reflection information generated from ClientProtocol.proto</summary>
  public static partial class ClientProtocolReflection {

    #region Descriptor
    /// <summary>File descriptor for ClientProtocol.proto</summary>
    public static pbr::FileDescriptor Descriptor {
      get { return descriptor; }
    }
    private static pbr::FileDescriptor descriptor;

    static ClientProtocolReflection() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "ChRDbGllbnRQcm90b2NvbC5wcm90bxIMZHJpdmVyYnJpZGdlIoMBChZMb2Nh",
            "bFJ1bnRpbWVQYXJhbWV0ZXJzEiAKGG1heF9udW1iZXJfb2ZfZXZhbHVhdG9y",
            "cxgBIAEoDRIbChNydW50aW1lX3Jvb3RfZm9sZGVyGAIgASgJEhYKDmp2bV9o",
            "ZWFwX3NsYWNrGAMgASgJEhIKCnJhY2tfbmFtZXMYBCADKAkiTwoVWWFyblJ1",
            "bnRpbWVQYXJhbWV0ZXJzEg0KBXF1ZXVlGAEgASgJEicKH2pvYl9zdWJtaXNz",
            "aW9uX2RpcmVjdG9yeV9wcmVmaXgYAiABKAkiHQobQXp1cmVCYXRjaFJ1bnRp",
            "bWVQYXJhbWV0ZXJzIhgKFk1lc29zUnVudGltZVBhcmFtZXRlcnMiygcKGURy",
            "aXZlckNsaWVudENvbmZpZ3VyYXRpb24SDQoFam9iaWQYASABKAkSEQoJY3B1",
            "X2NvcmVzGAIgASgNEhEKCW1lbW9yeV9tYhgDIAEoDRI9Cg1sb2NhbF9ydW50",
            "aW1lGAQgASgLMiQuZHJpdmVyYnJpZGdlLkxvY2FsUnVudGltZVBhcmFtZXRl",
            "cnNIABI7Cgx5YXJuX3J1bnRpbWUYBSABKAsyIy5kcml2ZXJicmlkZ2UuWWFy",
            "blJ1bnRpbWVQYXJhbWV0ZXJzSAASRAoPYXpiYXRjaF9ydW50aW1lGAYgASgL",
            "MikuZHJpdmVyYnJpZGdlLkF6dXJlQmF0Y2hSdW50aW1lUGFyYW1ldGVyc0gA",
            "Ej0KDW1lc29zX3J1bnRpbWUYByABKAsyJC5kcml2ZXJicmlkZ2UuTWVzb3NS",
            "dW50aW1lUGFyYW1ldGVyc0gAEiQKHGRyaXZlcl9jbGllbnRfbGF1bmNoX2Nv",
            "bW1hbmQYCiABKAkSQQoHaGFuZGxlchgLIAMoDjIwLmRyaXZlcmJyaWRnZS5E",
            "cml2ZXJDbGllbnRDb25maWd1cmF0aW9uLkhhbmRsZXJzEhwKFHRjcF9wb3J0",
            "X3JhbmdlX2JlZ2luGA8gASgNEhwKFHRjcF9wb3J0X3JhbmdlX2NvdW50GBAg",
            "ASgNEiAKGHRjcF9wb3J0X3JhbmdlX3RyeV9jb3VudBgRIAEoDRIUCgxnbG9i",
            "YWxfZmlsZXMYFCADKAkSEwoLbG9jYWxfZmlsZXMYFSADKAkSGAoQZ2xvYmFs",
            "X2xpYnJhcmllcxgWIAMoCRIXCg9sb2NhbF9saWJyYXJpZXMYFyADKAkixgIK",
            "CEhhbmRsZXJzEgkKBVNUQVJUEAASCAoEU1RPUBABEhcKE0VWQUxVQVRPUl9B",
            "TExPQ0FURUQQBRIXChNFVkFMVUFUT1JfQ09NUExFVEVEEAYSFAoQRVZBTFVB",
            "VE9SX0ZBSUxFRBAHEhIKDkNPTlRFWFRfQUNUSVZFEAoSEgoOQ09OVEVYVF9D",
            "TE9TRUQQCxISCg5DT05URVhUX0ZBSUxFRBAMEhMKD0NPTlRFWFRfTUVTU0FH",
            "RRANEhAKDFRBU0tfUlVOTklORxAPEg8KC1RBU0tfRkFJTEVEEBASEgoOVEFT",
            "S19DT01QTEVURUQQERIQCgxUQVNLX01FU1NBR0UQEhISCg5DTElFTlRfTUVT",
            "U0FHRRAUEhAKDENMSUVOVF9DTE9TRRAVEh0KGUNMSUVOVF9DTE9TRV9XSVRI",
            "X01FU1NBR0UQFkIJCgdydW50aW1lQk0KHG9yZy5hcGFjaGUucmVlZi5icmlk",
            "Z2UucHJvdG9CDkNsaWVudFByb3RvY29sqgIcT3JnLkFwYWNoZS5SRUVGLkJy",
            "aWRnZS5Qcm90b2IGcHJvdG8z"));
      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
          new pbr::FileDescriptor[] { },
          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
            new pbr::GeneratedClrTypeInfo(typeof(global::Org.Apache.REEF.Bridge.Proto.LocalRuntimeParameters), global::Org.Apache.REEF.Bridge.Proto.LocalRuntimeParameters.Parser, new[]{ "MaxNumberOfEvaluators", "RuntimeRootFolder", "JvmHeapSlack", "RackNames" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Org.Apache.REEF.Bridge.Proto.YarnRuntimeParameters), global::Org.Apache.REEF.Bridge.Proto.YarnRuntimeParameters.Parser, new[]{ "Queue", "JobSubmissionDirectoryPrefix" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Org.Apache.REEF.Bridge.Proto.AzureBatchRuntimeParameters), global::Org.Apache.REEF.Bridge.Proto.AzureBatchRuntimeParameters.Parser, null, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Org.Apache.REEF.Bridge.Proto.MesosRuntimeParameters), global::Org.Apache.REEF.Bridge.Proto.MesosRuntimeParameters.Parser, null, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Org.Apache.REEF.Bridge.Proto.DriverClientConfiguration), global::Org.Apache.REEF.Bridge.Proto.DriverClientConfiguration.Parser, new[]{ "Jobid", "CpuCores", "MemoryMb", "LocalRuntime", "YarnRuntime", "AzbatchRuntime", "MesosRuntime", "DriverClientLaunchCommand", "Handler", "TcpPortRangeBegin", "TcpPortRangeCount", "TcpPortRangeTryCount", "GlobalFiles", "LocalFiles", "GlobalLibraries", "LocalLibraries" }, new[]{ "Runtime" }, new[]{ typeof(global::Org.Apache.REEF.Bridge.Proto.DriverClientConfiguration.Types.Handlers) }, null)
          }));
    }
    #endregion

  }
  #region Messages
  public sealed partial class LocalRuntimeParameters : pb::IMessage<LocalRuntimeParameters> {
    private static readonly pb::MessageParser<LocalRuntimeParameters> _parser = new pb::MessageParser<LocalRuntimeParameters>(() => new LocalRuntimeParameters());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<LocalRuntimeParameters> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Org.Apache.REEF.Bridge.Proto.ClientProtocolReflection.Descriptor.MessageTypes[0]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public LocalRuntimeParameters() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public LocalRuntimeParameters(LocalRuntimeParameters other) : this() {
      maxNumberOfEvaluators_ = other.maxNumberOfEvaluators_;
      runtimeRootFolder_ = other.runtimeRootFolder_;
      jvmHeapSlack_ = other.jvmHeapSlack_;
      rackNames_ = other.rackNames_.Clone();
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public LocalRuntimeParameters Clone() {
      return new LocalRuntimeParameters(this);
    }

    /// <summary>Field number for the "max_number_of_evaluators" field.</summary>
    public const int MaxNumberOfEvaluatorsFieldNumber = 1;
    private uint maxNumberOfEvaluators_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public uint MaxNumberOfEvaluators {
      get { return maxNumberOfEvaluators_; }
      set {
        maxNumberOfEvaluators_ = value;
      }
    }

    /// <summary>Field number for the "runtime_root_folder" field.</summary>
    public const int RuntimeRootFolderFieldNumber = 2;
    private string runtimeRootFolder_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string RuntimeRootFolder {
      get { return runtimeRootFolder_; }
      set {
        runtimeRootFolder_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "jvm_heap_slack" field.</summary>
    public const int JvmHeapSlackFieldNumber = 3;
    private string jvmHeapSlack_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string JvmHeapSlack {
      get { return jvmHeapSlack_; }
      set {
        jvmHeapSlack_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "rack_names" field.</summary>
    public const int RackNamesFieldNumber = 4;
    private static readonly pb::FieldCodec<string> _repeated_rackNames_codec
        = pb::FieldCodec.ForString(34);
    private readonly pbc::RepeatedField<string> rackNames_ = new pbc::RepeatedField<string>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<string> RackNames {
      get { return rackNames_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as LocalRuntimeParameters);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(LocalRuntimeParameters other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (MaxNumberOfEvaluators != other.MaxNumberOfEvaluators) return false;
      if (RuntimeRootFolder != other.RuntimeRootFolder) return false;
      if (JvmHeapSlack != other.JvmHeapSlack) return false;
      if(!rackNames_.Equals(other.rackNames_)) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (MaxNumberOfEvaluators != 0) hash ^= MaxNumberOfEvaluators.GetHashCode();
      if (RuntimeRootFolder.Length != 0) hash ^= RuntimeRootFolder.GetHashCode();
      if (JvmHeapSlack.Length != 0) hash ^= JvmHeapSlack.GetHashCode();
      hash ^= rackNames_.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (MaxNumberOfEvaluators != 0) {
        output.WriteRawTag(8);
        output.WriteUInt32(MaxNumberOfEvaluators);
      }
      if (RuntimeRootFolder.Length != 0) {
        output.WriteRawTag(18);
        output.WriteString(RuntimeRootFolder);
      }
      if (JvmHeapSlack.Length != 0) {
        output.WriteRawTag(26);
        output.WriteString(JvmHeapSlack);
      }
      rackNames_.WriteTo(output, _repeated_rackNames_codec);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (MaxNumberOfEvaluators != 0) {
        size += 1 + pb::CodedOutputStream.ComputeUInt32Size(MaxNumberOfEvaluators);
      }
      if (RuntimeRootFolder.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(RuntimeRootFolder);
      }
      if (JvmHeapSlack.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(JvmHeapSlack);
      }
      size += rackNames_.CalculateSize(_repeated_rackNames_codec);
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(LocalRuntimeParameters other) {
      if (other == null) {
        return;
      }
      if (other.MaxNumberOfEvaluators != 0) {
        MaxNumberOfEvaluators = other.MaxNumberOfEvaluators;
      }
      if (other.RuntimeRootFolder.Length != 0) {
        RuntimeRootFolder = other.RuntimeRootFolder;
      }
      if (other.JvmHeapSlack.Length != 0) {
        JvmHeapSlack = other.JvmHeapSlack;
      }
      rackNames_.Add(other.rackNames_);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 8: {
            MaxNumberOfEvaluators = input.ReadUInt32();
            break;
          }
          case 18: {
            RuntimeRootFolder = input.ReadString();
            break;
          }
          case 26: {
            JvmHeapSlack = input.ReadString();
            break;
          }
          case 34: {
            rackNames_.AddEntriesFrom(input, _repeated_rackNames_codec);
            break;
          }
        }
      }
    }

  }

  public sealed partial class YarnRuntimeParameters : pb::IMessage<YarnRuntimeParameters> {
    private static readonly pb::MessageParser<YarnRuntimeParameters> _parser = new pb::MessageParser<YarnRuntimeParameters>(() => new YarnRuntimeParameters());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<YarnRuntimeParameters> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Org.Apache.REEF.Bridge.Proto.ClientProtocolReflection.Descriptor.MessageTypes[1]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public YarnRuntimeParameters() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public YarnRuntimeParameters(YarnRuntimeParameters other) : this() {
      queue_ = other.queue_;
      jobSubmissionDirectoryPrefix_ = other.jobSubmissionDirectoryPrefix_;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public YarnRuntimeParameters Clone() {
      return new YarnRuntimeParameters(this);
    }

    /// <summary>Field number for the "queue" field.</summary>
    public const int QueueFieldNumber = 1;
    private string queue_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string Queue {
      get { return queue_; }
      set {
        queue_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "job_submission_directory_prefix" field.</summary>
    public const int JobSubmissionDirectoryPrefixFieldNumber = 2;
    private string jobSubmissionDirectoryPrefix_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string JobSubmissionDirectoryPrefix {
      get { return jobSubmissionDirectoryPrefix_; }
      set {
        jobSubmissionDirectoryPrefix_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as YarnRuntimeParameters);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(YarnRuntimeParameters other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Queue != other.Queue) return false;
      if (JobSubmissionDirectoryPrefix != other.JobSubmissionDirectoryPrefix) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Queue.Length != 0) hash ^= Queue.GetHashCode();
      if (JobSubmissionDirectoryPrefix.Length != 0) hash ^= JobSubmissionDirectoryPrefix.GetHashCode();
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (Queue.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(Queue);
      }
      if (JobSubmissionDirectoryPrefix.Length != 0) {
        output.WriteRawTag(18);
        output.WriteString(JobSubmissionDirectoryPrefix);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Queue.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Queue);
      }
      if (JobSubmissionDirectoryPrefix.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(JobSubmissionDirectoryPrefix);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(YarnRuntimeParameters other) {
      if (other == null) {
        return;
      }
      if (other.Queue.Length != 0) {
        Queue = other.Queue;
      }
      if (other.JobSubmissionDirectoryPrefix.Length != 0) {
        JobSubmissionDirectoryPrefix = other.JobSubmissionDirectoryPrefix;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            Queue = input.ReadString();
            break;
          }
          case 18: {
            JobSubmissionDirectoryPrefix = input.ReadString();
            break;
          }
        }
      }
    }

  }

  public sealed partial class AzureBatchRuntimeParameters : pb::IMessage<AzureBatchRuntimeParameters> {
    private static readonly pb::MessageParser<AzureBatchRuntimeParameters> _parser = new pb::MessageParser<AzureBatchRuntimeParameters>(() => new AzureBatchRuntimeParameters());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<AzureBatchRuntimeParameters> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Org.Apache.REEF.Bridge.Proto.ClientProtocolReflection.Descriptor.MessageTypes[2]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public AzureBatchRuntimeParameters() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public AzureBatchRuntimeParameters(AzureBatchRuntimeParameters other) : this() {
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public AzureBatchRuntimeParameters Clone() {
      return new AzureBatchRuntimeParameters(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as AzureBatchRuntimeParameters);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(AzureBatchRuntimeParameters other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(AzureBatchRuntimeParameters other) {
      if (other == null) {
        return;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
        }
      }
    }

  }

  public sealed partial class MesosRuntimeParameters : pb::IMessage<MesosRuntimeParameters> {
    private static readonly pb::MessageParser<MesosRuntimeParameters> _parser = new pb::MessageParser<MesosRuntimeParameters>(() => new MesosRuntimeParameters());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<MesosRuntimeParameters> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Org.Apache.REEF.Bridge.Proto.ClientProtocolReflection.Descriptor.MessageTypes[3]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public MesosRuntimeParameters() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public MesosRuntimeParameters(MesosRuntimeParameters other) : this() {
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public MesosRuntimeParameters Clone() {
      return new MesosRuntimeParameters(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as MesosRuntimeParameters);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(MesosRuntimeParameters other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(MesosRuntimeParameters other) {
      if (other == null) {
        return;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
        }
      }
    }

  }

  public sealed partial class DriverClientConfiguration : pb::IMessage<DriverClientConfiguration> {
    private static readonly pb::MessageParser<DriverClientConfiguration> _parser = new pb::MessageParser<DriverClientConfiguration>(() => new DriverClientConfiguration());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<DriverClientConfiguration> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Org.Apache.REEF.Bridge.Proto.ClientProtocolReflection.Descriptor.MessageTypes[4]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public DriverClientConfiguration() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public DriverClientConfiguration(DriverClientConfiguration other) : this() {
      jobid_ = other.jobid_;
      cpuCores_ = other.cpuCores_;
      memoryMb_ = other.memoryMb_;
      driverClientLaunchCommand_ = other.driverClientLaunchCommand_;
      handler_ = other.handler_.Clone();
      tcpPortRangeBegin_ = other.tcpPortRangeBegin_;
      tcpPortRangeCount_ = other.tcpPortRangeCount_;
      tcpPortRangeTryCount_ = other.tcpPortRangeTryCount_;
      globalFiles_ = other.globalFiles_.Clone();
      localFiles_ = other.localFiles_.Clone();
      globalLibraries_ = other.globalLibraries_.Clone();
      localLibraries_ = other.localLibraries_.Clone();
      switch (other.RuntimeCase) {
        case RuntimeOneofCase.LocalRuntime:
          LocalRuntime = other.LocalRuntime.Clone();
          break;
        case RuntimeOneofCase.YarnRuntime:
          YarnRuntime = other.YarnRuntime.Clone();
          break;
        case RuntimeOneofCase.AzbatchRuntime:
          AzbatchRuntime = other.AzbatchRuntime.Clone();
          break;
        case RuntimeOneofCase.MesosRuntime:
          MesosRuntime = other.MesosRuntime.Clone();
          break;
      }

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public DriverClientConfiguration Clone() {
      return new DriverClientConfiguration(this);
    }

    /// <summary>Field number for the "jobid" field.</summary>
    public const int JobidFieldNumber = 1;
    private string jobid_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string Jobid {
      get { return jobid_; }
      set {
        jobid_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "cpu_cores" field.</summary>
    public const int CpuCoresFieldNumber = 2;
    private uint cpuCores_;
    /// <summary>
    /// driver machine resources
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public uint CpuCores {
      get { return cpuCores_; }
      set {
        cpuCores_ = value;
      }
    }

    /// <summary>Field number for the "memory_mb" field.</summary>
    public const int MemoryMbFieldNumber = 3;
    private uint memoryMb_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public uint MemoryMb {
      get { return memoryMb_; }
      set {
        memoryMb_ = value;
      }
    }

    /// <summary>Field number for the "local_runtime" field.</summary>
    public const int LocalRuntimeFieldNumber = 4;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Org.Apache.REEF.Bridge.Proto.LocalRuntimeParameters LocalRuntime {
      get { return runtimeCase_ == RuntimeOneofCase.LocalRuntime ? (global::Org.Apache.REEF.Bridge.Proto.LocalRuntimeParameters) runtime_ : null; }
      set {
        runtime_ = value;
        runtimeCase_ = value == null ? RuntimeOneofCase.None : RuntimeOneofCase.LocalRuntime;
      }
    }

    /// <summary>Field number for the "yarn_runtime" field.</summary>
    public const int YarnRuntimeFieldNumber = 5;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Org.Apache.REEF.Bridge.Proto.YarnRuntimeParameters YarnRuntime {
      get { return runtimeCase_ == RuntimeOneofCase.YarnRuntime ? (global::Org.Apache.REEF.Bridge.Proto.YarnRuntimeParameters) runtime_ : null; }
      set {
        runtime_ = value;
        runtimeCase_ = value == null ? RuntimeOneofCase.None : RuntimeOneofCase.YarnRuntime;
      }
    }

    /// <summary>Field number for the "azbatch_runtime" field.</summary>
    public const int AzbatchRuntimeFieldNumber = 6;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Org.Apache.REEF.Bridge.Proto.AzureBatchRuntimeParameters AzbatchRuntime {
      get { return runtimeCase_ == RuntimeOneofCase.AzbatchRuntime ? (global::Org.Apache.REEF.Bridge.Proto.AzureBatchRuntimeParameters) runtime_ : null; }
      set {
        runtime_ = value;
        runtimeCase_ = value == null ? RuntimeOneofCase.None : RuntimeOneofCase.AzbatchRuntime;
      }
    }

    /// <summary>Field number for the "mesos_runtime" field.</summary>
    public const int MesosRuntimeFieldNumber = 7;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Org.Apache.REEF.Bridge.Proto.MesosRuntimeParameters MesosRuntime {
      get { return runtimeCase_ == RuntimeOneofCase.MesosRuntime ? (global::Org.Apache.REEF.Bridge.Proto.MesosRuntimeParameters) runtime_ : null; }
      set {
        runtime_ = value;
        runtimeCase_ = value == null ? RuntimeOneofCase.None : RuntimeOneofCase.MesosRuntime;
      }
    }

    /// <summary>Field number for the "driver_client_launch_command" field.</summary>
    public const int DriverClientLaunchCommandFieldNumber = 10;
    private string driverClientLaunchCommand_ = "";
    /// <summary>
    /// The command to launch the driver client
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string DriverClientLaunchCommand {
      get { return driverClientLaunchCommand_; }
      set {
        driverClientLaunchCommand_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "handler" field.</summary>
    public const int HandlerFieldNumber = 11;
    private static readonly pb::FieldCodec<global::Org.Apache.REEF.Bridge.Proto.DriverClientConfiguration.Types.Handlers> _repeated_handler_codec
        = pb::FieldCodec.ForEnum(90, x => (int) x, x => (global::Org.Apache.REEF.Bridge.Proto.DriverClientConfiguration.Types.Handlers) x);
    private readonly pbc::RepeatedField<global::Org.Apache.REEF.Bridge.Proto.DriverClientConfiguration.Types.Handlers> handler_ = new pbc::RepeatedField<global::Org.Apache.REEF.Bridge.Proto.DriverClientConfiguration.Types.Handlers>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<global::Org.Apache.REEF.Bridge.Proto.DriverClientConfiguration.Types.Handlers> Handler {
      get { return handler_; }
    }

    /// <summary>Field number for the "tcp_port_range_begin" field.</summary>
    public const int TcpPortRangeBeginFieldNumber = 15;
    private uint tcpPortRangeBegin_;
    /// <summary>
    /// TCP port range
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public uint TcpPortRangeBegin {
      get { return tcpPortRangeBegin_; }
      set {
        tcpPortRangeBegin_ = value;
      }
    }

    /// <summary>Field number for the "tcp_port_range_count" field.</summary>
    public const int TcpPortRangeCountFieldNumber = 16;
    private uint tcpPortRangeCount_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public uint TcpPortRangeCount {
      get { return tcpPortRangeCount_; }
      set {
        tcpPortRangeCount_ = value;
      }
    }

    /// <summary>Field number for the "tcp_port_range_try_count" field.</summary>
    public const int TcpPortRangeTryCountFieldNumber = 17;
    private uint tcpPortRangeTryCount_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public uint TcpPortRangeTryCount {
      get { return tcpPortRangeTryCount_; }
      set {
        tcpPortRangeTryCount_ = value;
      }
    }

    /// <summary>Field number for the "global_files" field.</summary>
    public const int GlobalFilesFieldNumber = 20;
    private static readonly pb::FieldCodec<string> _repeated_globalFiles_codec
        = pb::FieldCodec.ForString(162);
    private readonly pbc::RepeatedField<string> globalFiles_ = new pbc::RepeatedField<string>();
    /// <summary>
    /// file dependencies
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<string> GlobalFiles {
      get { return globalFiles_; }
    }

    /// <summary>Field number for the "local_files" field.</summary>
    public const int LocalFilesFieldNumber = 21;
    private static readonly pb::FieldCodec<string> _repeated_localFiles_codec
        = pb::FieldCodec.ForString(170);
    private readonly pbc::RepeatedField<string> localFiles_ = new pbc::RepeatedField<string>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<string> LocalFiles {
      get { return localFiles_; }
    }

    /// <summary>Field number for the "global_libraries" field.</summary>
    public const int GlobalLibrariesFieldNumber = 22;
    private static readonly pb::FieldCodec<string> _repeated_globalLibraries_codec
        = pb::FieldCodec.ForString(178);
    private readonly pbc::RepeatedField<string> globalLibraries_ = new pbc::RepeatedField<string>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<string> GlobalLibraries {
      get { return globalLibraries_; }
    }

    /// <summary>Field number for the "local_libraries" field.</summary>
    public const int LocalLibrariesFieldNumber = 23;
    private static readonly pb::FieldCodec<string> _repeated_localLibraries_codec
        = pb::FieldCodec.ForString(186);
    private readonly pbc::RepeatedField<string> localLibraries_ = new pbc::RepeatedField<string>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<string> LocalLibraries {
      get { return localLibraries_; }
    }

    private object runtime_;
    /// <summary>Enum of possible cases for the "runtime" oneof.</summary>
    public enum RuntimeOneofCase {
      None = 0,
      LocalRuntime = 4,
      YarnRuntime = 5,
      AzbatchRuntime = 6,
      MesosRuntime = 7,
    }
    private RuntimeOneofCase runtimeCase_ = RuntimeOneofCase.None;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public RuntimeOneofCase RuntimeCase {
      get { return runtimeCase_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void ClearRuntime() {
      runtimeCase_ = RuntimeOneofCase.None;
      runtime_ = null;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as DriverClientConfiguration);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(DriverClientConfiguration other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Jobid != other.Jobid) return false;
      if (CpuCores != other.CpuCores) return false;
      if (MemoryMb != other.MemoryMb) return false;
      if (!object.Equals(LocalRuntime, other.LocalRuntime)) return false;
      if (!object.Equals(YarnRuntime, other.YarnRuntime)) return false;
      if (!object.Equals(AzbatchRuntime, other.AzbatchRuntime)) return false;
      if (!object.Equals(MesosRuntime, other.MesosRuntime)) return false;
      if (DriverClientLaunchCommand != other.DriverClientLaunchCommand) return false;
      if(!handler_.Equals(other.handler_)) return false;
      if (TcpPortRangeBegin != other.TcpPortRangeBegin) return false;
      if (TcpPortRangeCount != other.TcpPortRangeCount) return false;
      if (TcpPortRangeTryCount != other.TcpPortRangeTryCount) return false;
      if(!globalFiles_.Equals(other.globalFiles_)) return false;
      if(!localFiles_.Equals(other.localFiles_)) return false;
      if(!globalLibraries_.Equals(other.globalLibraries_)) return false;
      if(!localLibraries_.Equals(other.localLibraries_)) return false;
      if (RuntimeCase != other.RuntimeCase) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Jobid.Length != 0) hash ^= Jobid.GetHashCode();
      if (CpuCores != 0) hash ^= CpuCores.GetHashCode();
      if (MemoryMb != 0) hash ^= MemoryMb.GetHashCode();
      if (runtimeCase_ == RuntimeOneofCase.LocalRuntime) hash ^= LocalRuntime.GetHashCode();
      if (runtimeCase_ == RuntimeOneofCase.YarnRuntime) hash ^= YarnRuntime.GetHashCode();
      if (runtimeCase_ == RuntimeOneofCase.AzbatchRuntime) hash ^= AzbatchRuntime.GetHashCode();
      if (runtimeCase_ == RuntimeOneofCase.MesosRuntime) hash ^= MesosRuntime.GetHashCode();
      if (DriverClientLaunchCommand.Length != 0) hash ^= DriverClientLaunchCommand.GetHashCode();
      hash ^= handler_.GetHashCode();
      if (TcpPortRangeBegin != 0) hash ^= TcpPortRangeBegin.GetHashCode();
      if (TcpPortRangeCount != 0) hash ^= TcpPortRangeCount.GetHashCode();
      if (TcpPortRangeTryCount != 0) hash ^= TcpPortRangeTryCount.GetHashCode();
      hash ^= globalFiles_.GetHashCode();
      hash ^= localFiles_.GetHashCode();
      hash ^= globalLibraries_.GetHashCode();
      hash ^= localLibraries_.GetHashCode();
      hash ^= (int) runtimeCase_;
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (Jobid.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(Jobid);
      }
      if (CpuCores != 0) {
        output.WriteRawTag(16);
        output.WriteUInt32(CpuCores);
      }
      if (MemoryMb != 0) {
        output.WriteRawTag(24);
        output.WriteUInt32(MemoryMb);
      }
      if (runtimeCase_ == RuntimeOneofCase.LocalRuntime) {
        output.WriteRawTag(34);
        output.WriteMessage(LocalRuntime);
      }
      if (runtimeCase_ == RuntimeOneofCase.YarnRuntime) {
        output.WriteRawTag(42);
        output.WriteMessage(YarnRuntime);
      }
      if (runtimeCase_ == RuntimeOneofCase.AzbatchRuntime) {
        output.WriteRawTag(50);
        output.WriteMessage(AzbatchRuntime);
      }
      if (runtimeCase_ == RuntimeOneofCase.MesosRuntime) {
        output.WriteRawTag(58);
        output.WriteMessage(MesosRuntime);
      }
      if (DriverClientLaunchCommand.Length != 0) {
        output.WriteRawTag(82);
        output.WriteString(DriverClientLaunchCommand);
      }
      handler_.WriteTo(output, _repeated_handler_codec);
      if (TcpPortRangeBegin != 0) {
        output.WriteRawTag(120);
        output.WriteUInt32(TcpPortRangeBegin);
      }
      if (TcpPortRangeCount != 0) {
        output.WriteRawTag(128, 1);
        output.WriteUInt32(TcpPortRangeCount);
      }
      if (TcpPortRangeTryCount != 0) {
        output.WriteRawTag(136, 1);
        output.WriteUInt32(TcpPortRangeTryCount);
      }
      globalFiles_.WriteTo(output, _repeated_globalFiles_codec);
      localFiles_.WriteTo(output, _repeated_localFiles_codec);
      globalLibraries_.WriteTo(output, _repeated_globalLibraries_codec);
      localLibraries_.WriteTo(output, _repeated_localLibraries_codec);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Jobid.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Jobid);
      }
      if (CpuCores != 0) {
        size += 1 + pb::CodedOutputStream.ComputeUInt32Size(CpuCores);
      }
      if (MemoryMb != 0) {
        size += 1 + pb::CodedOutputStream.ComputeUInt32Size(MemoryMb);
      }
      if (runtimeCase_ == RuntimeOneofCase.LocalRuntime) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(LocalRuntime);
      }
      if (runtimeCase_ == RuntimeOneofCase.YarnRuntime) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(YarnRuntime);
      }
      if (runtimeCase_ == RuntimeOneofCase.AzbatchRuntime) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(AzbatchRuntime);
      }
      if (runtimeCase_ == RuntimeOneofCase.MesosRuntime) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(MesosRuntime);
      }
      if (DriverClientLaunchCommand.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(DriverClientLaunchCommand);
      }
      size += handler_.CalculateSize(_repeated_handler_codec);
      if (TcpPortRangeBegin != 0) {
        size += 1 + pb::CodedOutputStream.ComputeUInt32Size(TcpPortRangeBegin);
      }
      if (TcpPortRangeCount != 0) {
        size += 2 + pb::CodedOutputStream.ComputeUInt32Size(TcpPortRangeCount);
      }
      if (TcpPortRangeTryCount != 0) {
        size += 2 + pb::CodedOutputStream.ComputeUInt32Size(TcpPortRangeTryCount);
      }
      size += globalFiles_.CalculateSize(_repeated_globalFiles_codec);
      size += localFiles_.CalculateSize(_repeated_localFiles_codec);
      size += globalLibraries_.CalculateSize(_repeated_globalLibraries_codec);
      size += localLibraries_.CalculateSize(_repeated_localLibraries_codec);
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(DriverClientConfiguration other) {
      if (other == null) {
        return;
      }
      if (other.Jobid.Length != 0) {
        Jobid = other.Jobid;
      }
      if (other.CpuCores != 0) {
        CpuCores = other.CpuCores;
      }
      if (other.MemoryMb != 0) {
        MemoryMb = other.MemoryMb;
      }
      if (other.DriverClientLaunchCommand.Length != 0) {
        DriverClientLaunchCommand = other.DriverClientLaunchCommand;
      }
      handler_.Add(other.handler_);
      if (other.TcpPortRangeBegin != 0) {
        TcpPortRangeBegin = other.TcpPortRangeBegin;
      }
      if (other.TcpPortRangeCount != 0) {
        TcpPortRangeCount = other.TcpPortRangeCount;
      }
      if (other.TcpPortRangeTryCount != 0) {
        TcpPortRangeTryCount = other.TcpPortRangeTryCount;
      }
      globalFiles_.Add(other.globalFiles_);
      localFiles_.Add(other.localFiles_);
      globalLibraries_.Add(other.globalLibraries_);
      localLibraries_.Add(other.localLibraries_);
      switch (other.RuntimeCase) {
        case RuntimeOneofCase.LocalRuntime:
          if (LocalRuntime == null) {
            LocalRuntime = new global::Org.Apache.REEF.Bridge.Proto.LocalRuntimeParameters();
          }
          LocalRuntime.MergeFrom(other.LocalRuntime);
          break;
        case RuntimeOneofCase.YarnRuntime:
          if (YarnRuntime == null) {
            YarnRuntime = new global::Org.Apache.REEF.Bridge.Proto.YarnRuntimeParameters();
          }
          YarnRuntime.MergeFrom(other.YarnRuntime);
          break;
        case RuntimeOneofCase.AzbatchRuntime:
          if (AzbatchRuntime == null) {
            AzbatchRuntime = new global::Org.Apache.REEF.Bridge.Proto.AzureBatchRuntimeParameters();
          }
          AzbatchRuntime.MergeFrom(other.AzbatchRuntime);
          break;
        case RuntimeOneofCase.MesosRuntime:
          if (MesosRuntime == null) {
            MesosRuntime = new global::Org.Apache.REEF.Bridge.Proto.MesosRuntimeParameters();
          }
          MesosRuntime.MergeFrom(other.MesosRuntime);
          break;
      }

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            Jobid = input.ReadString();
            break;
          }
          case 16: {
            CpuCores = input.ReadUInt32();
            break;
          }
          case 24: {
            MemoryMb = input.ReadUInt32();
            break;
          }
          case 34: {
            global::Org.Apache.REEF.Bridge.Proto.LocalRuntimeParameters subBuilder = new global::Org.Apache.REEF.Bridge.Proto.LocalRuntimeParameters();
            if (runtimeCase_ == RuntimeOneofCase.LocalRuntime) {
              subBuilder.MergeFrom(LocalRuntime);
            }
            input.ReadMessage(subBuilder);
            LocalRuntime = subBuilder;
            break;
          }
          case 42: {
            global::Org.Apache.REEF.Bridge.Proto.YarnRuntimeParameters subBuilder = new global::Org.Apache.REEF.Bridge.Proto.YarnRuntimeParameters();
            if (runtimeCase_ == RuntimeOneofCase.YarnRuntime) {
              subBuilder.MergeFrom(YarnRuntime);
            }
            input.ReadMessage(subBuilder);
            YarnRuntime = subBuilder;
            break;
          }
          case 50: {
            global::Org.Apache.REEF.Bridge.Proto.AzureBatchRuntimeParameters subBuilder = new global::Org.Apache.REEF.Bridge.Proto.AzureBatchRuntimeParameters();
            if (runtimeCase_ == RuntimeOneofCase.AzbatchRuntime) {
              subBuilder.MergeFrom(AzbatchRuntime);
            }
            input.ReadMessage(subBuilder);
            AzbatchRuntime = subBuilder;
            break;
          }
          case 58: {
            global::Org.Apache.REEF.Bridge.Proto.MesosRuntimeParameters subBuilder = new global::Org.Apache.REEF.Bridge.Proto.MesosRuntimeParameters();
            if (runtimeCase_ == RuntimeOneofCase.MesosRuntime) {
              subBuilder.MergeFrom(MesosRuntime);
            }
            input.ReadMessage(subBuilder);
            MesosRuntime = subBuilder;
            break;
          }
          case 82: {
            DriverClientLaunchCommand = input.ReadString();
            break;
          }
          case 90:
          case 88: {
            handler_.AddEntriesFrom(input, _repeated_handler_codec);
            break;
          }
          case 120: {
            TcpPortRangeBegin = input.ReadUInt32();
            break;
          }
          case 128: {
            TcpPortRangeCount = input.ReadUInt32();
            break;
          }
          case 136: {
            TcpPortRangeTryCount = input.ReadUInt32();
            break;
          }
          case 162: {
            globalFiles_.AddEntriesFrom(input, _repeated_globalFiles_codec);
            break;
          }
          case 170: {
            localFiles_.AddEntriesFrom(input, _repeated_localFiles_codec);
            break;
          }
          case 178: {
            globalLibraries_.AddEntriesFrom(input, _repeated_globalLibraries_codec);
            break;
          }
          case 186: {
            localLibraries_.AddEntriesFrom(input, _repeated_localLibraries_codec);
            break;
          }
        }
      }
    }

    #region Nested types
    /// <summary>Container for nested types declared in the DriverClientConfiguration message type.</summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static partial class Types {
      public enum Handlers {
        /// <summary>
        /// control events
        /// </summary>
        [pbr::OriginalName("START")] Start = 0,
        [pbr::OriginalName("STOP")] Stop = 1,
        /// <summary>
        /// evaluator events
        /// </summary>
        [pbr::OriginalName("EVALUATOR_ALLOCATED")] EvaluatorAllocated = 5,
        [pbr::OriginalName("EVALUATOR_COMPLETED")] EvaluatorCompleted = 6,
        [pbr::OriginalName("EVALUATOR_FAILED")] EvaluatorFailed = 7,
        /// <summary>
        /// context events
        /// </summary>
        [pbr::OriginalName("CONTEXT_ACTIVE")] ContextActive = 10,
        [pbr::OriginalName("CONTEXT_CLOSED")] ContextClosed = 11,
        [pbr::OriginalName("CONTEXT_FAILED")] ContextFailed = 12,
        [pbr::OriginalName("CONTEXT_MESSAGE")] ContextMessage = 13,
        /// <summary>
        /// task events
        /// </summary>
        [pbr::OriginalName("TASK_RUNNING")] TaskRunning = 15,
        [pbr::OriginalName("TASK_FAILED")] TaskFailed = 16,
        [pbr::OriginalName("TASK_COMPLETED")] TaskCompleted = 17,
        [pbr::OriginalName("TASK_MESSAGE")] TaskMessage = 18,
        /// <summary>
        /// client events
        /// </summary>
        [pbr::OriginalName("CLIENT_MESSAGE")] ClientMessage = 20,
        [pbr::OriginalName("CLIENT_CLOSE")] ClientClose = 21,
        [pbr::OriginalName("CLIENT_CLOSE_WITH_MESSAGE")] ClientCloseWithMessage = 22,
      }

    }
    #endregion

  }

  #endregion

}

#endregion Designer generated code
