// 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: DriverClientProtocol.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 DriverClientProtocol.proto</summary>
  public static partial class DriverClientProtocolReflection {

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

    static DriverClientProtocolReflection() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "ChpEcml2ZXJDbGllbnRQcm90b2NvbC5wcm90bxIMZHJpdmVyYnJpZGdlGhpE",
            "cml2ZXJDb21tb25Qcm90b2NvbC5wcm90byItCgpJZGxlU3RhdHVzEg8KB2lz",
            "X2lkbGUYASABKAgSDgoGcmVhc29uGAIgASgJIiMKDVN0YXJ0VGltZUluZm8S",
            "EgoKc3RhcnRfdGltZRgBIAEoAyIhCgxTdG9wVGltZUluZm8SEQoJc3RvcF90",
            "aW1lGAEgASgDIiQKEEFsYXJtVHJpZ2dlckluZm8SEAoIYWxhcm1faWQYASAB",
            "KAkiTgoXRXZhbHVhdG9yRGVzY3JpcHRvckluZm8SDgoGbWVtb3J5GAEgASgF",
            "Eg0KBWNvcmVzGAIgASgFEhQKDHJ1bnRpbWVfbmFtZRgDIAEoCSLtAQoNRXZh",
            "bHVhdG9ySW5mbxIUCgxldmFsdWF0b3JfaWQYASABKAkSOAoHZmFpbHVyZRgC",
            "IAEoCzInLmRyaXZlcmJyaWRnZS5FdmFsdWF0b3JJbmZvLkZhaWx1cmVJbmZv",
            "Ej4KD2Rlc2NyaXB0b3JfaW5mbxgDIAEoCzIlLmRyaXZlcmJyaWRnZS5FdmFs",
            "dWF0b3JEZXNjcmlwdG9ySW5mbxpMCgtGYWlsdXJlSW5mbxIPCgdtZXNzYWdl",
            "GAEgASgJEhYKDmZhaWxlZENvbnRleHRzGAIgAygJEhQKDGZhaWxlZFRhc2tJ",
            "ZBgDIAEoCSJ6CgtDb250ZXh0SW5mbxISCgpjb250ZXh0X2lkGAEgASgJEhQK",
            "DGV2YWx1YXRvcl9pZBgCIAEoCRIRCglwYXJlbnRfaWQYAyABKAkSLgoJZXhj",
            "ZXB0aW9uGAUgASgLMhsuZHJpdmVyYnJpZGdlLkV4Y2VwdGlvbkluZm8ibQoS",
            "Q29udGV4dE1lc3NhZ2VJbmZvEhIKCmNvbnRleHRfaWQYASABKAkSDwoHcGF5",
            "bG9hZBgCIAEoDBIXCg9zZXF1ZW5jZV9udW1iZXIYAyABKAMSGQoRbWVzc2Fn",
            "ZV9zb3VyY2VfaWQYBCABKAkibwoIVGFza0luZm8SDwoHdGFza19pZBgBIAEo",
            "CRISCgpjb250ZXh0X2lkGAIgASgJEg4KBnJlc3VsdBgDIAEoDBIuCglleGNl",
            "cHRpb24YBSABKAsyGy5kcml2ZXJicmlkZ2UuRXhjZXB0aW9uSW5mbyJ7Cg9U",
            "YXNrTWVzc2FnZUluZm8SDwoHdGFza19pZBgBIAEoCRIPCgdwYXlsb2FkGAIg",
            "ASgMEhcKD3NlcXVlbmNlX251bWJlchgDIAEoAxISCgpjb250ZXh0X2lkGAQg",
            "ASgJEhkKEW1lc3NhZ2Vfc291cmNlX2lkGAUgASgJIiQKEUNsaWVudE1lc3Nh",
            "Z2VJbmZvEg8KB3BheWxvYWQYASABKAwy/goKDERyaXZlckNsaWVudBJGChRJ",
            "ZGxlbmVzc0NoZWNrSGFuZGxlchISLmRyaXZlcmJyaWRnZS5Wb2lkGhguZHJp",
            "dmVyYnJpZGdlLklkbGVTdGF0dXMiABJBCgxTdGFydEhhbmRsZXISGy5kcml2",
            "ZXJicmlkZ2UuU3RhcnRUaW1lSW5mbxoSLmRyaXZlcmJyaWRnZS5Wb2lkIgAS",
            "PwoLU3RvcEhhbmRsZXISGi5kcml2ZXJicmlkZ2UuU3RvcFRpbWVJbmZvGhIu",
            "ZHJpdmVyYnJpZGdlLlZvaWQiABJECgxBbGFybVRyaWdnZXISHi5kcml2ZXJi",
            "cmlkZ2UuQWxhcm1UcmlnZ2VySW5mbxoSLmRyaXZlcmJyaWRnZS5Wb2lkIgAS",
            "TgoZQWxsb2NhdGVkRXZhbHVhdG9ySGFuZGxlchIbLmRyaXZlcmJyaWRnZS5F",
            "dmFsdWF0b3JJbmZvGhIuZHJpdmVyYnJpZGdlLlZvaWQiABJOChlDb21wbGV0",
            "ZWRFdmFsdWF0b3JIYW5kbGVyEhsuZHJpdmVyYnJpZGdlLkV2YWx1YXRvcklu",
            "Zm8aEi5kcml2ZXJicmlkZ2UuVm9pZCIAEksKFkZhaWxlZEV2YWx1YXRvckhh",
            "bmRsZXISGy5kcml2ZXJicmlkZ2UuRXZhbHVhdG9ySW5mbxoSLmRyaXZlcmJy",
            "aWRnZS5Wb2lkIgASRwoUQWN0aXZlQ29udGV4dEhhbmRsZXISGS5kcml2ZXJi",
            "cmlkZ2UuQ29udGV4dEluZm8aEi5kcml2ZXJicmlkZ2UuVm9pZCIAEkcKFENs",
            "b3NlZENvbnRleHRIYW5kbGVyEhkuZHJpdmVyYnJpZGdlLkNvbnRleHRJbmZv",
            "GhIuZHJpdmVyYnJpZGdlLlZvaWQiABJHChRGYWlsZWRDb250ZXh0SGFuZGxl",
            "chIZLmRyaXZlcmJyaWRnZS5Db250ZXh0SW5mbxoSLmRyaXZlcmJyaWRnZS5W",
            "b2lkIgASTwoVQ29udGV4dE1lc3NhZ2VIYW5kbGVyEiAuZHJpdmVyYnJpZGdl",
            "LkNvbnRleHRNZXNzYWdlSW5mbxoSLmRyaXZlcmJyaWRnZS5Wb2lkIgASQgoS",
            "UnVubmluZ1Rhc2tIYW5kbGVyEhYuZHJpdmVyYnJpZGdlLlRhc2tJbmZvGhIu",
            "ZHJpdmVyYnJpZGdlLlZvaWQiABJBChFGYWlsZWRUYXNrSGFuZGxlchIWLmRy",
            "aXZlcmJyaWRnZS5UYXNrSW5mbxoSLmRyaXZlcmJyaWRnZS5Wb2lkIgASRAoU",
            "Q29tcGxldGVkVGFza0hhbmRsZXISFi5kcml2ZXJicmlkZ2UuVGFza0luZm8a",
            "Ei5kcml2ZXJicmlkZ2UuVm9pZCIAEkQKFFN1c3BlbmRlZFRhc2tIYW5kbGVy",
            "EhYuZHJpdmVyYnJpZGdlLlRhc2tJbmZvGhIuZHJpdmVyYnJpZGdlLlZvaWQi",
            "ABJJChJUYXNrTWVzc2FnZUhhbmRsZXISHS5kcml2ZXJicmlkZ2UuVGFza01l",
            "c3NhZ2VJbmZvGhIuZHJpdmVyYnJpZGdlLlZvaWQiABJNChRDbGllbnRNZXNz",
            "YWdlSGFuZGxlchIfLmRyaXZlcmJyaWRnZS5DbGllbnRNZXNzYWdlSW5mbxoS",
            "LmRyaXZlcmJyaWRnZS5Wb2lkIgASPgoSQ2xpZW50Q2xvc2VIYW5kbGVyEhIu",
            "ZHJpdmVyYnJpZGdlLlZvaWQaEi5kcml2ZXJicmlkZ2UuVm9pZCIAElYKHUNs",
            "aWVudENsb3NlV2l0aE1lc3NhZ2VIYW5kbGVyEh8uZHJpdmVyYnJpZGdlLkNs",
            "aWVudE1lc3NhZ2VJbmZvGhIuZHJpdmVyYnJpZGdlLlZvaWQiAEJVChxvcmcu",
            "YXBhY2hlLnJlZWYuYnJpZGdlLnByb3RvQhREcml2ZXJDbGllbnRQcm90b2Nv",
            "bFABqgIcT3JnLkFwYWNoZS5SRUVGLkJyaWRnZS5Qcm90b2IGcHJvdG8z"));
      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
          new pbr::FileDescriptor[] { global::Org.Apache.REEF.Bridge.Proto.DriverCommonProtocolReflection.Descriptor, },
          new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
            new pbr::GeneratedClrTypeInfo(typeof(global::Org.Apache.REEF.Bridge.Proto.IdleStatus), global::Org.Apache.REEF.Bridge.Proto.IdleStatus.Parser, new[]{ "IsIdle", "Reason" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Org.Apache.REEF.Bridge.Proto.StartTimeInfo), global::Org.Apache.REEF.Bridge.Proto.StartTimeInfo.Parser, new[]{ "StartTime" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Org.Apache.REEF.Bridge.Proto.StopTimeInfo), global::Org.Apache.REEF.Bridge.Proto.StopTimeInfo.Parser, new[]{ "StopTime" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Org.Apache.REEF.Bridge.Proto.AlarmTriggerInfo), global::Org.Apache.REEF.Bridge.Proto.AlarmTriggerInfo.Parser, new[]{ "AlarmId" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Org.Apache.REEF.Bridge.Proto.EvaluatorDescriptorInfo), global::Org.Apache.REEF.Bridge.Proto.EvaluatorDescriptorInfo.Parser, new[]{ "Memory", "Cores", "RuntimeName" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Org.Apache.REEF.Bridge.Proto.EvaluatorInfo), global::Org.Apache.REEF.Bridge.Proto.EvaluatorInfo.Parser, new[]{ "EvaluatorId", "Failure", "DescriptorInfo" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Org.Apache.REEF.Bridge.Proto.EvaluatorInfo.Types.FailureInfo), global::Org.Apache.REEF.Bridge.Proto.EvaluatorInfo.Types.FailureInfo.Parser, new[]{ "Message", "FailedContexts", "FailedTaskId" }, null, null, null)}),
            new pbr::GeneratedClrTypeInfo(typeof(global::Org.Apache.REEF.Bridge.Proto.ContextInfo), global::Org.Apache.REEF.Bridge.Proto.ContextInfo.Parser, new[]{ "ContextId", "EvaluatorId", "ParentId", "Exception" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Org.Apache.REEF.Bridge.Proto.ContextMessageInfo), global::Org.Apache.REEF.Bridge.Proto.ContextMessageInfo.Parser, new[]{ "ContextId", "Payload", "SequenceNumber", "MessageSourceId" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Org.Apache.REEF.Bridge.Proto.TaskInfo), global::Org.Apache.REEF.Bridge.Proto.TaskInfo.Parser, new[]{ "TaskId", "ContextId", "Result", "Exception" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Org.Apache.REEF.Bridge.Proto.TaskMessageInfo), global::Org.Apache.REEF.Bridge.Proto.TaskMessageInfo.Parser, new[]{ "TaskId", "Payload", "SequenceNumber", "ContextId", "MessageSourceId" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Org.Apache.REEF.Bridge.Proto.ClientMessageInfo), global::Org.Apache.REEF.Bridge.Proto.ClientMessageInfo.Parser, new[]{ "Payload" }, null, null, null)
          }));
    }
    #endregion

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

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public IdleStatus(IdleStatus other) : this() {
      isIdle_ = other.isIdle_;
      reason_ = other.reason_;
    }

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

    /// <summary>Field number for the "is_idle" field.</summary>
    public const int IsIdleFieldNumber = 1;
    private bool isIdle_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool IsIdle {
      get { return isIdle_; }
      set {
        isIdle_ = value;
      }
    }

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (IsIdle != false) hash ^= IsIdle.GetHashCode();
      if (Reason.Length != 0) hash ^= Reason.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 (IsIdle != false) {
        output.WriteRawTag(8);
        output.WriteBool(IsIdle);
      }
      if (Reason.Length != 0) {
        output.WriteRawTag(18);
        output.WriteString(Reason);
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(IdleStatus other) {
      if (other == null) {
        return;
      }
      if (other.IsIdle != false) {
        IsIdle = other.IsIdle;
      }
      if (other.Reason.Length != 0) {
        Reason = other.Reason;
      }
    }

    [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: {
            IsIdle = input.ReadBool();
            break;
          }
          case 18: {
            Reason = input.ReadString();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// The request message containing resource request.
  /// </summary>
  public sealed partial class StartTimeInfo : pb::IMessage<StartTimeInfo> {
    private static readonly pb::MessageParser<StartTimeInfo> _parser = new pb::MessageParser<StartTimeInfo>(() => new StartTimeInfo());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<StartTimeInfo> Parser { get { return _parser; } }

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public StartTimeInfo(StartTimeInfo other) : this() {
      startTime_ = other.startTime_;
    }

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

    /// <summary>Field number for the "start_time" field.</summary>
    public const int StartTimeFieldNumber = 1;
    private long startTime_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public long StartTime {
      get { return startTime_; }
      set {
        startTime_ = value;
      }
    }

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (StartTime != 0L) hash ^= StartTime.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 (StartTime != 0L) {
        output.WriteRawTag(8);
        output.WriteInt64(StartTime);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (StartTime != 0L) {
        size += 1 + pb::CodedOutputStream.ComputeInt64Size(StartTime);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(StartTimeInfo other) {
      if (other == null) {
        return;
      }
      if (other.StartTime != 0L) {
        StartTime = other.StartTime;
      }
    }

    [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: {
            StartTime = input.ReadInt64();
            break;
          }
        }
      }
    }

  }

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

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public StopTimeInfo(StopTimeInfo other) : this() {
      stopTime_ = other.stopTime_;
    }

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

    /// <summary>Field number for the "stop_time" field.</summary>
    public const int StopTimeFieldNumber = 1;
    private long stopTime_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public long StopTime {
      get { return stopTime_; }
      set {
        stopTime_ = value;
      }
    }

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (StopTime != 0L) hash ^= StopTime.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 (StopTime != 0L) {
        output.WriteRawTag(8);
        output.WriteInt64(StopTime);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (StopTime != 0L) {
        size += 1 + pb::CodedOutputStream.ComputeInt64Size(StopTime);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(StopTimeInfo other) {
      if (other == null) {
        return;
      }
      if (other.StopTime != 0L) {
        StopTime = other.StopTime;
      }
    }

    [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: {
            StopTime = input.ReadInt64();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Information associated with an alarm that was set.
  /// </summary>
  public sealed partial class AlarmTriggerInfo : pb::IMessage<AlarmTriggerInfo> {
    private static readonly pb::MessageParser<AlarmTriggerInfo> _parser = new pb::MessageParser<AlarmTriggerInfo>(() => new AlarmTriggerInfo());
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<AlarmTriggerInfo> Parser { get { return _parser; } }

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public AlarmTriggerInfo(AlarmTriggerInfo other) : this() {
      alarmId_ = other.alarmId_;
    }

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

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (AlarmId.Length != 0) hash ^= AlarmId.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 (AlarmId.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(AlarmId);
      }
    }

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

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

    [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: {
            AlarmId = input.ReadString();
            break;
          }
        }
      }
    }

  }

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

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public EvaluatorDescriptorInfo(EvaluatorDescriptorInfo other) : this() {
      memory_ = other.memory_;
      cores_ = other.cores_;
      runtimeName_ = other.runtimeName_;
    }

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

    /// <summary>Field number for the "memory" field.</summary>
    public const int MemoryFieldNumber = 1;
    private int memory_;
    /// <summary>
    /// the amount of memory allocated
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int Memory {
      get { return memory_; }
      set {
        memory_ = value;
      }
    }

    /// <summary>Field number for the "cores" field.</summary>
    public const int CoresFieldNumber = 2;
    private int cores_;
    /// <summary>
    /// the number of virtual cores allocated
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int Cores {
      get { return cores_; }
      set {
        cores_ = value;
      }
    }

    /// <summary>Field number for the "runtime_name" field.</summary>
    public const int RuntimeNameFieldNumber = 3;
    private string runtimeName_ = "";
    /// <summary>
    /// name of the runtime
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string RuntimeName {
      get { return runtimeName_; }
      set {
        runtimeName_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(EvaluatorDescriptorInfo other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Memory != other.Memory) return false;
      if (Cores != other.Cores) return false;
      if (RuntimeName != other.RuntimeName) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Memory != 0) hash ^= Memory.GetHashCode();
      if (Cores != 0) hash ^= Cores.GetHashCode();
      if (RuntimeName.Length != 0) hash ^= RuntimeName.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 (Memory != 0) {
        output.WriteRawTag(8);
        output.WriteInt32(Memory);
      }
      if (Cores != 0) {
        output.WriteRawTag(16);
        output.WriteInt32(Cores);
      }
      if (RuntimeName.Length != 0) {
        output.WriteRawTag(26);
        output.WriteString(RuntimeName);
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(EvaluatorDescriptorInfo other) {
      if (other == null) {
        return;
      }
      if (other.Memory != 0) {
        Memory = other.Memory;
      }
      if (other.Cores != 0) {
        Cores = other.Cores;
      }
      if (other.RuntimeName.Length != 0) {
        RuntimeName = other.RuntimeName;
      }
    }

    [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: {
            Memory = input.ReadInt32();
            break;
          }
          case 16: {
            Cores = input.ReadInt32();
            break;
          }
          case 26: {
            RuntimeName = input.ReadString();
            break;
          }
        }
      }
    }

  }

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

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public EvaluatorInfo(EvaluatorInfo other) : this() {
      evaluatorId_ = other.evaluatorId_;
      Failure = other.failure_ != null ? other.Failure.Clone() : null;
      DescriptorInfo = other.descriptorInfo_ != null ? other.DescriptorInfo.Clone() : null;
    }

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

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

    /// <summary>Field number for the "failure" field.</summary>
    public const int FailureFieldNumber = 2;
    private global::Org.Apache.REEF.Bridge.Proto.EvaluatorInfo.Types.FailureInfo failure_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Org.Apache.REEF.Bridge.Proto.EvaluatorInfo.Types.FailureInfo Failure {
      get { return failure_; }
      set {
        failure_ = value;
      }
    }

    /// <summary>Field number for the "descriptor_info" field.</summary>
    public const int DescriptorInfoFieldNumber = 3;
    private global::Org.Apache.REEF.Bridge.Proto.EvaluatorDescriptorInfo descriptorInfo_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Org.Apache.REEF.Bridge.Proto.EvaluatorDescriptorInfo DescriptorInfo {
      get { return descriptorInfo_; }
      set {
        descriptorInfo_ = value;
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(EvaluatorInfo other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (EvaluatorId != other.EvaluatorId) return false;
      if (!object.Equals(Failure, other.Failure)) return false;
      if (!object.Equals(DescriptorInfo, other.DescriptorInfo)) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (EvaluatorId.Length != 0) hash ^= EvaluatorId.GetHashCode();
      if (failure_ != null) hash ^= Failure.GetHashCode();
      if (descriptorInfo_ != null) hash ^= DescriptorInfo.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 (EvaluatorId.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(EvaluatorId);
      }
      if (failure_ != null) {
        output.WriteRawTag(18);
        output.WriteMessage(Failure);
      }
      if (descriptorInfo_ != null) {
        output.WriteRawTag(26);
        output.WriteMessage(DescriptorInfo);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (EvaluatorId.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(EvaluatorId);
      }
      if (failure_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Failure);
      }
      if (descriptorInfo_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(DescriptorInfo);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(EvaluatorInfo other) {
      if (other == null) {
        return;
      }
      if (other.EvaluatorId.Length != 0) {
        EvaluatorId = other.EvaluatorId;
      }
      if (other.failure_ != null) {
        if (failure_ == null) {
          failure_ = new global::Org.Apache.REEF.Bridge.Proto.EvaluatorInfo.Types.FailureInfo();
        }
        Failure.MergeFrom(other.Failure);
      }
      if (other.descriptorInfo_ != null) {
        if (descriptorInfo_ == null) {
          descriptorInfo_ = new global::Org.Apache.REEF.Bridge.Proto.EvaluatorDescriptorInfo();
        }
        DescriptorInfo.MergeFrom(other.DescriptorInfo);
      }
    }

    [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: {
            EvaluatorId = input.ReadString();
            break;
          }
          case 18: {
            if (failure_ == null) {
              failure_ = new global::Org.Apache.REEF.Bridge.Proto.EvaluatorInfo.Types.FailureInfo();
            }
            input.ReadMessage(failure_);
            break;
          }
          case 26: {
            if (descriptorInfo_ == null) {
              descriptorInfo_ = new global::Org.Apache.REEF.Bridge.Proto.EvaluatorDescriptorInfo();
            }
            input.ReadMessage(descriptorInfo_);
            break;
          }
        }
      }
    }

    #region Nested types
    /// <summary>Container for nested types declared in the EvaluatorInfo message type.</summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static partial class Types {
      public sealed partial class FailureInfo : pb::IMessage<FailureInfo> {
        private static readonly pb::MessageParser<FailureInfo> _parser = new pb::MessageParser<FailureInfo>(() => new FailureInfo());
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
        public static pb::MessageParser<FailureInfo> Parser { get { return _parser; } }

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

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

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

        partial void OnConstruction();

        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
        public FailureInfo(FailureInfo other) : this() {
          message_ = other.message_;
          failedContexts_ = other.failedContexts_.Clone();
          failedTaskId_ = other.failedTaskId_;
        }

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

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

        /// <summary>Field number for the "failedContexts" field.</summary>
        public const int FailedContextsFieldNumber = 2;
        private static readonly pb::FieldCodec<string> _repeated_failedContexts_codec
            = pb::FieldCodec.ForString(18);
        private readonly pbc::RepeatedField<string> failedContexts_ = new pbc::RepeatedField<string>();
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
        public pbc::RepeatedField<string> FailedContexts {
          get { return failedContexts_; }
        }

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

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

        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
        public bool Equals(FailureInfo other) {
          if (ReferenceEquals(other, null)) {
            return false;
          }
          if (ReferenceEquals(other, this)) {
            return true;
          }
          if (Message != other.Message) return false;
          if(!failedContexts_.Equals(other.failedContexts_)) return false;
          if (FailedTaskId != other.FailedTaskId) return false;
          return true;
        }

        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
        public override int GetHashCode() {
          int hash = 1;
          if (Message.Length != 0) hash ^= Message.GetHashCode();
          hash ^= failedContexts_.GetHashCode();
          if (FailedTaskId.Length != 0) hash ^= FailedTaskId.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 (Message.Length != 0) {
            output.WriteRawTag(10);
            output.WriteString(Message);
          }
          failedContexts_.WriteTo(output, _repeated_failedContexts_codec);
          if (FailedTaskId.Length != 0) {
            output.WriteRawTag(26);
            output.WriteString(FailedTaskId);
          }
        }

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

        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
        public void MergeFrom(FailureInfo other) {
          if (other == null) {
            return;
          }
          if (other.Message.Length != 0) {
            Message = other.Message;
          }
          failedContexts_.Add(other.failedContexts_);
          if (other.FailedTaskId.Length != 0) {
            FailedTaskId = other.FailedTaskId;
          }
        }

        [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: {
                Message = input.ReadString();
                break;
              }
              case 18: {
                failedContexts_.AddEntriesFrom(input, _repeated_failedContexts_codec);
                break;
              }
              case 26: {
                FailedTaskId = input.ReadString();
                break;
              }
            }
          }
        }

      }

    }
    #endregion

  }

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

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ContextInfo(ContextInfo other) : this() {
      contextId_ = other.contextId_;
      evaluatorId_ = other.evaluatorId_;
      parentId_ = other.parentId_;
      Exception = other.exception_ != null ? other.Exception.Clone() : null;
    }

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

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

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

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

    /// <summary>Field number for the "exception" field.</summary>
    public const int ExceptionFieldNumber = 5;
    private global::Org.Apache.REEF.Bridge.Proto.ExceptionInfo exception_;
    /// <summary>
    /// Optional exception information
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Org.Apache.REEF.Bridge.Proto.ExceptionInfo Exception {
      get { return exception_; }
      set {
        exception_ = value;
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ContextInfo other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (ContextId != other.ContextId) return false;
      if (EvaluatorId != other.EvaluatorId) return false;
      if (ParentId != other.ParentId) return false;
      if (!object.Equals(Exception, other.Exception)) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (ContextId.Length != 0) hash ^= ContextId.GetHashCode();
      if (EvaluatorId.Length != 0) hash ^= EvaluatorId.GetHashCode();
      if (ParentId.Length != 0) hash ^= ParentId.GetHashCode();
      if (exception_ != null) hash ^= Exception.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 (ContextId.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(ContextId);
      }
      if (EvaluatorId.Length != 0) {
        output.WriteRawTag(18);
        output.WriteString(EvaluatorId);
      }
      if (ParentId.Length != 0) {
        output.WriteRawTag(26);
        output.WriteString(ParentId);
      }
      if (exception_ != null) {
        output.WriteRawTag(42);
        output.WriteMessage(Exception);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (ContextId.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(ContextId);
      }
      if (EvaluatorId.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(EvaluatorId);
      }
      if (ParentId.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(ParentId);
      }
      if (exception_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Exception);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ContextInfo other) {
      if (other == null) {
        return;
      }
      if (other.ContextId.Length != 0) {
        ContextId = other.ContextId;
      }
      if (other.EvaluatorId.Length != 0) {
        EvaluatorId = other.EvaluatorId;
      }
      if (other.ParentId.Length != 0) {
        ParentId = other.ParentId;
      }
      if (other.exception_ != null) {
        if (exception_ == null) {
          exception_ = new global::Org.Apache.REEF.Bridge.Proto.ExceptionInfo();
        }
        Exception.MergeFrom(other.Exception);
      }
    }

    [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: {
            ContextId = input.ReadString();
            break;
          }
          case 18: {
            EvaluatorId = input.ReadString();
            break;
          }
          case 26: {
            ParentId = input.ReadString();
            break;
          }
          case 42: {
            if (exception_ == null) {
              exception_ = new global::Org.Apache.REEF.Bridge.Proto.ExceptionInfo();
            }
            input.ReadMessage(exception_);
            break;
          }
        }
      }
    }

  }

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

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ContextMessageInfo(ContextMessageInfo other) : this() {
      contextId_ = other.contextId_;
      payload_ = other.payload_;
      sequenceNumber_ = other.sequenceNumber_;
      messageSourceId_ = other.messageSourceId_;
    }

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

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

    /// <summary>Field number for the "payload" field.</summary>
    public const int PayloadFieldNumber = 2;
    private pb::ByteString payload_ = pb::ByteString.Empty;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pb::ByteString Payload {
      get { return payload_; }
      set {
        payload_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "sequence_number" field.</summary>
    public const int SequenceNumberFieldNumber = 3;
    private long sequenceNumber_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public long SequenceNumber {
      get { return sequenceNumber_; }
      set {
        sequenceNumber_ = value;
      }
    }

    /// <summary>Field number for the "message_source_id" field.</summary>
    public const int MessageSourceIdFieldNumber = 4;
    private string messageSourceId_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string MessageSourceId {
      get { return messageSourceId_; }
      set {
        messageSourceId_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ContextMessageInfo other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (ContextId != other.ContextId) return false;
      if (Payload != other.Payload) return false;
      if (SequenceNumber != other.SequenceNumber) return false;
      if (MessageSourceId != other.MessageSourceId) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (ContextId.Length != 0) hash ^= ContextId.GetHashCode();
      if (Payload.Length != 0) hash ^= Payload.GetHashCode();
      if (SequenceNumber != 0L) hash ^= SequenceNumber.GetHashCode();
      if (MessageSourceId.Length != 0) hash ^= MessageSourceId.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 (ContextId.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(ContextId);
      }
      if (Payload.Length != 0) {
        output.WriteRawTag(18);
        output.WriteBytes(Payload);
      }
      if (SequenceNumber != 0L) {
        output.WriteRawTag(24);
        output.WriteInt64(SequenceNumber);
      }
      if (MessageSourceId.Length != 0) {
        output.WriteRawTag(34);
        output.WriteString(MessageSourceId);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (ContextId.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(ContextId);
      }
      if (Payload.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeBytesSize(Payload);
      }
      if (SequenceNumber != 0L) {
        size += 1 + pb::CodedOutputStream.ComputeInt64Size(SequenceNumber);
      }
      if (MessageSourceId.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(MessageSourceId);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ContextMessageInfo other) {
      if (other == null) {
        return;
      }
      if (other.ContextId.Length != 0) {
        ContextId = other.ContextId;
      }
      if (other.Payload.Length != 0) {
        Payload = other.Payload;
      }
      if (other.SequenceNumber != 0L) {
        SequenceNumber = other.SequenceNumber;
      }
      if (other.MessageSourceId.Length != 0) {
        MessageSourceId = other.MessageSourceId;
      }
    }

    [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: {
            ContextId = input.ReadString();
            break;
          }
          case 18: {
            Payload = input.ReadBytes();
            break;
          }
          case 24: {
            SequenceNumber = input.ReadInt64();
            break;
          }
          case 34: {
            MessageSourceId = input.ReadString();
            break;
          }
        }
      }
    }

  }

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

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public TaskInfo(TaskInfo other) : this() {
      taskId_ = other.taskId_;
      contextId_ = other.contextId_;
      result_ = other.result_;
      Exception = other.exception_ != null ? other.Exception.Clone() : null;
    }

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

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

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

    /// <summary>Field number for the "result" field.</summary>
    public const int ResultFieldNumber = 3;
    private pb::ByteString result_ = pb::ByteString.Empty;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pb::ByteString Result {
      get { return result_; }
      set {
        result_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "exception" field.</summary>
    public const int ExceptionFieldNumber = 5;
    private global::Org.Apache.REEF.Bridge.Proto.ExceptionInfo exception_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Org.Apache.REEF.Bridge.Proto.ExceptionInfo Exception {
      get { return exception_; }
      set {
        exception_ = value;
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(TaskInfo other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (TaskId != other.TaskId) return false;
      if (ContextId != other.ContextId) return false;
      if (Result != other.Result) return false;
      if (!object.Equals(Exception, other.Exception)) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (TaskId.Length != 0) hash ^= TaskId.GetHashCode();
      if (ContextId.Length != 0) hash ^= ContextId.GetHashCode();
      if (Result.Length != 0) hash ^= Result.GetHashCode();
      if (exception_ != null) hash ^= Exception.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 (TaskId.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(TaskId);
      }
      if (ContextId.Length != 0) {
        output.WriteRawTag(18);
        output.WriteString(ContextId);
      }
      if (Result.Length != 0) {
        output.WriteRawTag(26);
        output.WriteBytes(Result);
      }
      if (exception_ != null) {
        output.WriteRawTag(42);
        output.WriteMessage(Exception);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (TaskId.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(TaskId);
      }
      if (ContextId.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(ContextId);
      }
      if (Result.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeBytesSize(Result);
      }
      if (exception_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Exception);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(TaskInfo other) {
      if (other == null) {
        return;
      }
      if (other.TaskId.Length != 0) {
        TaskId = other.TaskId;
      }
      if (other.ContextId.Length != 0) {
        ContextId = other.ContextId;
      }
      if (other.Result.Length != 0) {
        Result = other.Result;
      }
      if (other.exception_ != null) {
        if (exception_ == null) {
          exception_ = new global::Org.Apache.REEF.Bridge.Proto.ExceptionInfo();
        }
        Exception.MergeFrom(other.Exception);
      }
    }

    [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: {
            TaskId = input.ReadString();
            break;
          }
          case 18: {
            ContextId = input.ReadString();
            break;
          }
          case 26: {
            Result = input.ReadBytes();
            break;
          }
          case 42: {
            if (exception_ == null) {
              exception_ = new global::Org.Apache.REEF.Bridge.Proto.ExceptionInfo();
            }
            input.ReadMessage(exception_);
            break;
          }
        }
      }
    }

  }

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

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public TaskMessageInfo(TaskMessageInfo other) : this() {
      taskId_ = other.taskId_;
      payload_ = other.payload_;
      sequenceNumber_ = other.sequenceNumber_;
      contextId_ = other.contextId_;
      messageSourceId_ = other.messageSourceId_;
    }

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

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

    /// <summary>Field number for the "payload" field.</summary>
    public const int PayloadFieldNumber = 2;
    private pb::ByteString payload_ = pb::ByteString.Empty;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pb::ByteString Payload {
      get { return payload_; }
      set {
        payload_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "sequence_number" field.</summary>
    public const int SequenceNumberFieldNumber = 3;
    private long sequenceNumber_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public long SequenceNumber {
      get { return sequenceNumber_; }
      set {
        sequenceNumber_ = value;
      }
    }

    /// <summary>Field number for the "context_id" field.</summary>
    public const int ContextIdFieldNumber = 4;
    private string contextId_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string ContextId {
      get { return contextId_; }
      set {
        contextId_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "message_source_id" field.</summary>
    public const int MessageSourceIdFieldNumber = 5;
    private string messageSourceId_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string MessageSourceId {
      get { return messageSourceId_; }
      set {
        messageSourceId_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(TaskMessageInfo other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (TaskId != other.TaskId) return false;
      if (Payload != other.Payload) return false;
      if (SequenceNumber != other.SequenceNumber) return false;
      if (ContextId != other.ContextId) return false;
      if (MessageSourceId != other.MessageSourceId) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (TaskId.Length != 0) hash ^= TaskId.GetHashCode();
      if (Payload.Length != 0) hash ^= Payload.GetHashCode();
      if (SequenceNumber != 0L) hash ^= SequenceNumber.GetHashCode();
      if (ContextId.Length != 0) hash ^= ContextId.GetHashCode();
      if (MessageSourceId.Length != 0) hash ^= MessageSourceId.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 (TaskId.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(TaskId);
      }
      if (Payload.Length != 0) {
        output.WriteRawTag(18);
        output.WriteBytes(Payload);
      }
      if (SequenceNumber != 0L) {
        output.WriteRawTag(24);
        output.WriteInt64(SequenceNumber);
      }
      if (ContextId.Length != 0) {
        output.WriteRawTag(34);
        output.WriteString(ContextId);
      }
      if (MessageSourceId.Length != 0) {
        output.WriteRawTag(42);
        output.WriteString(MessageSourceId);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (TaskId.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(TaskId);
      }
      if (Payload.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeBytesSize(Payload);
      }
      if (SequenceNumber != 0L) {
        size += 1 + pb::CodedOutputStream.ComputeInt64Size(SequenceNumber);
      }
      if (ContextId.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(ContextId);
      }
      if (MessageSourceId.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(MessageSourceId);
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(TaskMessageInfo other) {
      if (other == null) {
        return;
      }
      if (other.TaskId.Length != 0) {
        TaskId = other.TaskId;
      }
      if (other.Payload.Length != 0) {
        Payload = other.Payload;
      }
      if (other.SequenceNumber != 0L) {
        SequenceNumber = other.SequenceNumber;
      }
      if (other.ContextId.Length != 0) {
        ContextId = other.ContextId;
      }
      if (other.MessageSourceId.Length != 0) {
        MessageSourceId = other.MessageSourceId;
      }
    }

    [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: {
            TaskId = input.ReadString();
            break;
          }
          case 18: {
            Payload = input.ReadBytes();
            break;
          }
          case 24: {
            SequenceNumber = input.ReadInt64();
            break;
          }
          case 34: {
            ContextId = input.ReadString();
            break;
          }
          case 42: {
            MessageSourceId = input.ReadString();
            break;
          }
        }
      }
    }

  }

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

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

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ClientMessageInfo(ClientMessageInfo other) : this() {
      payload_ = other.payload_;
    }

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

    /// <summary>Field number for the "payload" field.</summary>
    public const int PayloadFieldNumber = 1;
    private pb::ByteString payload_ = pb::ByteString.Empty;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pb::ByteString Payload {
      get { return payload_; }
      set {
        payload_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Payload.Length != 0) hash ^= Payload.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 (Payload.Length != 0) {
        output.WriteRawTag(10);
        output.WriteBytes(Payload);
      }
    }

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

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

    [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: {
            Payload = input.ReadBytes();
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
