// <auto-generated>
//     Generated by the protocol buffer compiler.  DO NOT EDIT!
//     source: src/proto/grpc/testing/control.proto
// </auto-generated>
#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 Grpc.Testing {

  /// <summary>Holder for reflection information generated from src/proto/grpc/testing/control.proto</summary>
  public static partial class ControlReflection {

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

    static ControlReflection() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "CiRzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL2NvbnRyb2wucHJvdG8SDGdycGMu",
            "dGVzdGluZxolc3JjL3Byb3RvL2dycGMvdGVzdGluZy9wYXlsb2Fkcy5wcm90",
            "bxoic3JjL3Byb3RvL2dycGMvdGVzdGluZy9zdGF0cy5wcm90byIlCg1Qb2lz",
            "c29uUGFyYW1zEhQKDG9mZmVyZWRfbG9hZBgBIAEoASISChBDbG9zZWRMb29w",
            "UGFyYW1zInsKCkxvYWRQYXJhbXMSNQoLY2xvc2VkX2xvb3AYASABKAsyHi5n",
            "cnBjLnRlc3RpbmcuQ2xvc2VkTG9vcFBhcmFtc0gAEi4KB3BvaXNzb24YAiAB",
            "KAsyGy5ncnBjLnRlc3RpbmcuUG9pc3NvblBhcmFtc0gAQgYKBGxvYWQiVgoO",
            "U2VjdXJpdHlQYXJhbXMSEwoLdXNlX3Rlc3RfY2EYASABKAgSHAoUc2VydmVy",
            "X2hvc3Rfb3ZlcnJpZGUYAiABKAkSEQoJY3JlZF90eXBlGAMgASgJIk0KCkNo",
            "YW5uZWxBcmcSDAoEbmFtZRgBIAEoCRITCglzdHJfdmFsdWUYAiABKAlIABIT",
            "CglpbnRfdmFsdWUYAyABKAVIAEIHCgV2YWx1ZSLvBAoMQ2xpZW50Q29uZmln",
            "EhYKDnNlcnZlcl90YXJnZXRzGAEgAygJEi0KC2NsaWVudF90eXBlGAIgASgO",
            "MhguZ3JwYy50ZXN0aW5nLkNsaWVudFR5cGUSNQoPc2VjdXJpdHlfcGFyYW1z",
            "GAMgASgLMhwuZ3JwYy50ZXN0aW5nLlNlY3VyaXR5UGFyYW1zEiQKHG91dHN0",
            "YW5kaW5nX3JwY3NfcGVyX2NoYW5uZWwYBCABKAUSFwoPY2xpZW50X2NoYW5u",
            "ZWxzGAUgASgFEhwKFGFzeW5jX2NsaWVudF90aHJlYWRzGAcgASgFEicKCHJw",
            "Y190eXBlGAggASgOMhUuZ3JwYy50ZXN0aW5nLlJwY1R5cGUSLQoLbG9hZF9w",
            "YXJhbXMYCiABKAsyGC5ncnBjLnRlc3RpbmcuTG9hZFBhcmFtcxIzCg5wYXls",
            "b2FkX2NvbmZpZxgLIAEoCzIbLmdycGMudGVzdGluZy5QYXlsb2FkQ29uZmln",
            "EjcKEGhpc3RvZ3JhbV9wYXJhbXMYDCABKAsyHS5ncnBjLnRlc3RpbmcuSGlz",
            "dG9ncmFtUGFyYW1zEhEKCWNvcmVfbGlzdBgNIAMoBRISCgpjb3JlX2xpbWl0",
            "GA4gASgFEhgKEG90aGVyX2NsaWVudF9hcGkYDyABKAkSLgoMY2hhbm5lbF9h",
            "cmdzGBAgAygLMhguZ3JwYy50ZXN0aW5nLkNoYW5uZWxBcmcSFgoOdGhyZWFk",
            "c19wZXJfY3EYESABKAUSGwoTbWVzc2FnZXNfcGVyX3N0cmVhbRgSIAEoBRIY",
            "ChB1c2VfY29hbGVzY2VfYXBpGBMgASgIIjgKDENsaWVudFN0YXR1cxIoCgVz",
            "dGF0cxgBIAEoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0cyIVCgRNYXJr",
            "Eg0KBXJlc2V0GAEgASgIImgKCkNsaWVudEFyZ3MSKwoFc2V0dXAYASABKAsy",
            "Gi5ncnBjLnRlc3RpbmcuQ2xpZW50Q29uZmlnSAASIgoEbWFyaxgCIAEoCzIS",
            "LmdycGMudGVzdGluZy5NYXJrSABCCQoHYXJndHlwZSL9AgoMU2VydmVyQ29u",
            "ZmlnEi0KC3NlcnZlcl90eXBlGAEgASgOMhguZ3JwYy50ZXN0aW5nLlNlcnZl",
            "clR5cGUSNQoPc2VjdXJpdHlfcGFyYW1zGAIgASgLMhwuZ3JwYy50ZXN0aW5n",
            "LlNlY3VyaXR5UGFyYW1zEgwKBHBvcnQYBCABKAUSHAoUYXN5bmNfc2VydmVy",
            "X3RocmVhZHMYByABKAUSEgoKY29yZV9saW1pdBgIIAEoBRIzCg5wYXlsb2Fk",
            "X2NvbmZpZxgJIAEoCzIbLmdycGMudGVzdGluZy5QYXlsb2FkQ29uZmlnEhEK",
            "CWNvcmVfbGlzdBgKIAMoBRIYChBvdGhlcl9zZXJ2ZXJfYXBpGAsgASgJEhYK",
            "DnRocmVhZHNfcGVyX2NxGAwgASgFEhwKE3Jlc291cmNlX3F1b3RhX3NpemUY",
            "6QcgASgFEi8KDGNoYW5uZWxfYXJncxjqByADKAsyGC5ncnBjLnRlc3Rpbmcu",
            "Q2hhbm5lbEFyZyJoCgpTZXJ2ZXJBcmdzEisKBXNldHVwGAEgASgLMhouZ3Jw",
            "Yy50ZXN0aW5nLlNlcnZlckNvbmZpZ0gAEiIKBG1hcmsYAiABKAsyEi5ncnBj",
            "LnRlc3RpbmcuTWFya0gAQgkKB2FyZ3R5cGUiVQoMU2VydmVyU3RhdHVzEigK",
            "BXN0YXRzGAEgASgLMhkuZ3JwYy50ZXN0aW5nLlNlcnZlclN0YXRzEgwKBHBv",
            "cnQYAiABKAUSDQoFY29yZXMYAyABKAUiDQoLQ29yZVJlcXVlc3QiHQoMQ29y",
            "ZVJlc3BvbnNlEg0KBWNvcmVzGAEgASgFIgYKBFZvaWQi/QEKCFNjZW5hcmlv",
            "EgwKBG5hbWUYASABKAkSMQoNY2xpZW50X2NvbmZpZxgCIAEoCzIaLmdycGMu",
            "dGVzdGluZy5DbGllbnRDb25maWcSEwoLbnVtX2NsaWVudHMYAyABKAUSMQoN",
            "c2VydmVyX2NvbmZpZxgEIAEoCzIaLmdycGMudGVzdGluZy5TZXJ2ZXJDb25m",
            "aWcSEwoLbnVtX3NlcnZlcnMYBSABKAUSFgoOd2FybXVwX3NlY29uZHMYBiAB",
            "KAUSGQoRYmVuY2htYXJrX3NlY29uZHMYByABKAUSIAoYc3Bhd25fbG9jYWxf",
            "d29ya2VyX2NvdW50GAggASgFIjYKCVNjZW5hcmlvcxIpCglzY2VuYXJpb3MY",
            "ASADKAsyFi5ncnBjLnRlc3RpbmcuU2NlbmFyaW8ihAQKFVNjZW5hcmlvUmVz",
            "dWx0U3VtbWFyeRILCgNxcHMYASABKAESGwoTcXBzX3Blcl9zZXJ2ZXJfY29y",
            "ZRgCIAEoARIaChJzZXJ2ZXJfc3lzdGVtX3RpbWUYAyABKAESGAoQc2VydmVy",
            "X3VzZXJfdGltZRgEIAEoARIaChJjbGllbnRfc3lzdGVtX3RpbWUYBSABKAES",
            "GAoQY2xpZW50X3VzZXJfdGltZRgGIAEoARISCgpsYXRlbmN5XzUwGAcgASgB",
            "EhIKCmxhdGVuY3lfOTAYCCABKAESEgoKbGF0ZW5jeV85NRgJIAEoARISCgps",
            "YXRlbmN5Xzk5GAogASgBEhMKC2xhdGVuY3lfOTk5GAsgASgBEhgKEHNlcnZl",
            "cl9jcHVfdXNhZ2UYDCABKAESJgoec3VjY2Vzc2Z1bF9yZXF1ZXN0c19wZXJf",
            "c2Vjb25kGA0gASgBEiIKGmZhaWxlZF9yZXF1ZXN0c19wZXJfc2Vjb25kGA4g",
            "ASgBEiAKGGNsaWVudF9wb2xsc19wZXJfcmVxdWVzdBgPIAEoARIgChhzZXJ2",
            "ZXJfcG9sbHNfcGVyX3JlcXVlc3QYECABKAESIgoac2VydmVyX3F1ZXJpZXNf",
            "cGVyX2NwdV9zZWMYESABKAESIgoaY2xpZW50X3F1ZXJpZXNfcGVyX2NwdV9z",
            "ZWMYEiABKAEigwMKDlNjZW5hcmlvUmVzdWx0EigKCHNjZW5hcmlvGAEgASgL",
            "MhYuZ3JwYy50ZXN0aW5nLlNjZW5hcmlvEi4KCWxhdGVuY2llcxgCIAEoCzIb",
            "LmdycGMudGVzdGluZy5IaXN0b2dyYW1EYXRhEi8KDGNsaWVudF9zdGF0cxgD",
            "IAMoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0cxIvCgxzZXJ2ZXJfc3Rh",
            "dHMYBCADKAsyGS5ncnBjLnRlc3RpbmcuU2VydmVyU3RhdHMSFAoMc2VydmVy",
            "X2NvcmVzGAUgAygFEjQKB3N1bW1hcnkYBiABKAsyIy5ncnBjLnRlc3Rpbmcu",
            "U2NlbmFyaW9SZXN1bHRTdW1tYXJ5EhYKDmNsaWVudF9zdWNjZXNzGAcgAygI",
            "EhYKDnNlcnZlcl9zdWNjZXNzGAggAygIEjkKD3JlcXVlc3RfcmVzdWx0cxgJ",
            "IAMoCzIgLmdycGMudGVzdGluZy5SZXF1ZXN0UmVzdWx0Q291bnQqQQoKQ2xp",
            "ZW50VHlwZRIPCgtTWU5DX0NMSUVOVBAAEhAKDEFTWU5DX0NMSUVOVBABEhAK",
            "DE9USEVSX0NMSUVOVBACKlsKClNlcnZlclR5cGUSDwoLU1lOQ19TRVJWRVIQ",
            "ABIQCgxBU1lOQ19TRVJWRVIQARIYChRBU1lOQ19HRU5FUklDX1NFUlZFUhAC",
            "EhAKDE9USEVSX1NFUlZFUhADKnIKB1JwY1R5cGUSCQoFVU5BUlkQABINCglT",
            "VFJFQU1JTkcQARIZChVTVFJFQU1JTkdfRlJPTV9DTElFTlQQAhIZChVTVFJF",
            "QU1JTkdfRlJPTV9TRVJWRVIQAxIXChNTVFJFQU1JTkdfQk9USF9XQVlTEARi",
            "BnByb3RvMw=="));
      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
          new pbr::FileDescriptor[] { global::Grpc.Testing.PayloadsReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, },
          new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedClrTypeInfo[] {
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.PoissonParams), global::Grpc.Testing.PoissonParams.Parser, new[]{ "OfferedLoad" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClosedLoopParams), global::Grpc.Testing.ClosedLoopParams.Parser, null, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.LoadParams), global::Grpc.Testing.LoadParams.Parser, new[]{ "ClosedLoop", "Poisson" }, new[]{ "Load" }, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SecurityParams), global::Grpc.Testing.SecurityParams.Parser, new[]{ "UseTestCa", "ServerHostOverride", "CredType" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ChannelArg), global::Grpc.Testing.ChannelArg.Parser, new[]{ "Name", "StrValue", "IntValue" }, new[]{ "Value" }, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams", "CoreList", "CoreLimit", "OtherClientApi", "ChannelArgs", "ThreadsPerCq", "MessagesPerStream", "UseCoalesceApi" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStatus), global::Grpc.Testing.ClientStatus.Parser, new[]{ "Stats" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Mark), global::Grpc.Testing.Mark.Parser, new[]{ "Reset" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientArgs), global::Grpc.Testing.ClientArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerConfig), global::Grpc.Testing.ServerConfig.Parser, new[]{ "ServerType", "SecurityParams", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig", "CoreList", "OtherServerApi", "ThreadsPerCq", "ResourceQuotaSize", "ChannelArgs" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerArgs), global::Grpc.Testing.ServerArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerStatus), global::Grpc.Testing.ServerStatus.Parser, new[]{ "Stats", "Port", "Cores" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.CoreRequest), global::Grpc.Testing.CoreRequest.Parser, null, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.CoreResponse), global::Grpc.Testing.CoreResponse.Parser, new[]{ "Cores" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Void), global::Grpc.Testing.Void.Parser, null, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenario), global::Grpc.Testing.Scenario.Parser, new[]{ "Name", "ClientConfig", "NumClients", "ServerConfig", "NumServers", "WarmupSeconds", "BenchmarkSeconds", "SpawnLocalWorkerCount" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenarios), global::Grpc.Testing.Scenarios.Parser, new[]{ "Scenarios_" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResultSummary), global::Grpc.Testing.ScenarioResultSummary.Parser, new[]{ "Qps", "QpsPerServerCore", "ServerSystemTime", "ServerUserTime", "ClientSystemTime", "ClientUserTime", "Latency50", "Latency90", "Latency95", "Latency99", "Latency999", "ServerCpuUsage", "SuccessfulRequestsPerSecond", "FailedRequestsPerSecond", "ClientPollsPerRequest", "ServerPollsPerRequest", "ServerQueriesPerCpuSec", "ClientQueriesPerCpuSec" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResult), global::Grpc.Testing.ScenarioResult.Parser, new[]{ "Scenario", "Latencies", "ClientStats", "ServerStats", "ServerCores", "Summary", "ClientSuccess", "ServerSuccess", "RequestResults" }, null, null, null)
          }));
    }
    #endregion

  }
  #region Enums
  public enum ClientType {
    /// <summary>
    /// Many languages support a basic distinction between using
    /// sync or async client, and this allows the specification
    /// </summary>
    [pbr::OriginalName("SYNC_CLIENT")] SyncClient = 0,
    [pbr::OriginalName("ASYNC_CLIENT")] AsyncClient = 1,
    /// <summary>
    /// used for some language-specific variants
    /// </summary>
    [pbr::OriginalName("OTHER_CLIENT")] OtherClient = 2,
  }

  public enum ServerType {
    [pbr::OriginalName("SYNC_SERVER")] SyncServer = 0,
    [pbr::OriginalName("ASYNC_SERVER")] AsyncServer = 1,
    [pbr::OriginalName("ASYNC_GENERIC_SERVER")] AsyncGenericServer = 2,
    /// <summary>
    /// used for some language-specific variants
    /// </summary>
    [pbr::OriginalName("OTHER_SERVER")] OtherServer = 3,
  }

  public enum RpcType {
    [pbr::OriginalName("UNARY")] Unary = 0,
    [pbr::OriginalName("STREAMING")] Streaming = 1,
    [pbr::OriginalName("STREAMING_FROM_CLIENT")] StreamingFromClient = 2,
    [pbr::OriginalName("STREAMING_FROM_SERVER")] StreamingFromServer = 3,
    [pbr::OriginalName("STREAMING_BOTH_WAYS")] StreamingBothWays = 4,
  }

  #endregion

  #region Messages
  /// <summary>
  /// Parameters of poisson process distribution, which is a good representation
  /// of activity coming in from independent identical stationary sources.
  /// </summary>
  public sealed partial class PoissonParams : pb::IMessage<PoissonParams> {
    private static readonly pb::MessageParser<PoissonParams> _parser = new pb::MessageParser<PoissonParams>(() => new PoissonParams());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<PoissonParams> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[0]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public PoissonParams(PoissonParams other) : this() {
      offeredLoad_ = other.offeredLoad_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "offered_load" field.</summary>
    public const int OfferedLoadFieldNumber = 1;
    private double offeredLoad_;
    /// <summary>
    /// The rate of arrivals (a.k.a. lambda parameter of the exp distribution).
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double OfferedLoad {
      get { return offeredLoad_; }
      set {
        offeredLoad_ = value;
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(PoissonParams other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(OfferedLoad, other.OfferedLoad)) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (OfferedLoad != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(OfferedLoad);
      if (_unknownFields != null) {
        hash ^= _unknownFields.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 (OfferedLoad != 0D) {
        output.WriteRawTag(9);
        output.WriteDouble(OfferedLoad);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (OfferedLoad != 0D) {
        size += 1 + 8;
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(PoissonParams other) {
      if (other == null) {
        return;
      }
      if (other.OfferedLoad != 0D) {
        OfferedLoad = other.OfferedLoad;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 9: {
            OfferedLoad = input.ReadDouble();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Once an RPC finishes, immediately start a new one.
  /// No configuration parameters needed.
  /// </summary>
  public sealed partial class ClosedLoopParams : pb::IMessage<ClosedLoopParams> {
    private static readonly pb::MessageParser<ClosedLoopParams> _parser = new pb::MessageParser<ClosedLoopParams>(() => new ClosedLoopParams());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ClosedLoopParams> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[1]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ClosedLoopParams(ClosedLoopParams other) : this() {
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (_unknownFields != null) {
        hash ^= _unknownFields.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 (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ClosedLoopParams other) {
      if (other == null) {
        return;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

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

  }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[2]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public LoadParams(LoadParams other) : this() {
      switch (other.LoadCase) {
        case LoadOneofCase.ClosedLoop:
          ClosedLoop = other.ClosedLoop.Clone();
          break;
        case LoadOneofCase.Poisson:
          Poisson = other.Poisson.Clone();
          break;
      }

      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "closed_loop" field.</summary>
    public const int ClosedLoopFieldNumber = 1;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ClosedLoopParams ClosedLoop {
      get { return loadCase_ == LoadOneofCase.ClosedLoop ? (global::Grpc.Testing.ClosedLoopParams) load_ : null; }
      set {
        load_ = value;
        loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.ClosedLoop;
      }
    }

    /// <summary>Field number for the "poisson" field.</summary>
    public const int PoissonFieldNumber = 2;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.PoissonParams Poisson {
      get { return loadCase_ == LoadOneofCase.Poisson ? (global::Grpc.Testing.PoissonParams) load_ : null; }
      set {
        load_ = value;
        loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Poisson;
      }
    }

    private object load_;
    /// <summary>Enum of possible cases for the "load" oneof.</summary>
    public enum LoadOneofCase {
      None = 0,
      ClosedLoop = 1,
      Poisson = 2,
    }
    private LoadOneofCase loadCase_ = LoadOneofCase.None;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public LoadOneofCase LoadCase {
      get { return loadCase_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void ClearLoad() {
      loadCase_ = LoadOneofCase.None;
      load_ = null;
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(LoadParams other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!object.Equals(ClosedLoop, other.ClosedLoop)) return false;
      if (!object.Equals(Poisson, other.Poisson)) return false;
      if (LoadCase != other.LoadCase) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (loadCase_ == LoadOneofCase.ClosedLoop) hash ^= ClosedLoop.GetHashCode();
      if (loadCase_ == LoadOneofCase.Poisson) hash ^= Poisson.GetHashCode();
      hash ^= (int) loadCase_;
      if (_unknownFields != null) {
        hash ^= _unknownFields.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 (loadCase_ == LoadOneofCase.ClosedLoop) {
        output.WriteRawTag(10);
        output.WriteMessage(ClosedLoop);
      }
      if (loadCase_ == LoadOneofCase.Poisson) {
        output.WriteRawTag(18);
        output.WriteMessage(Poisson);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (loadCase_ == LoadOneofCase.ClosedLoop) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ClosedLoop);
      }
      if (loadCase_ == LoadOneofCase.Poisson) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Poisson);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(LoadParams other) {
      if (other == null) {
        return;
      }
      switch (other.LoadCase) {
        case LoadOneofCase.ClosedLoop:
          if (ClosedLoop == null) {
            ClosedLoop = new global::Grpc.Testing.ClosedLoopParams();
          }
          ClosedLoop.MergeFrom(other.ClosedLoop);
          break;
        case LoadOneofCase.Poisson:
          if (Poisson == null) {
            Poisson = new global::Grpc.Testing.PoissonParams();
          }
          Poisson.MergeFrom(other.Poisson);
          break;
      }

      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            global::Grpc.Testing.ClosedLoopParams subBuilder = new global::Grpc.Testing.ClosedLoopParams();
            if (loadCase_ == LoadOneofCase.ClosedLoop) {
              subBuilder.MergeFrom(ClosedLoop);
            }
            input.ReadMessage(subBuilder);
            ClosedLoop = subBuilder;
            break;
          }
          case 18: {
            global::Grpc.Testing.PoissonParams subBuilder = new global::Grpc.Testing.PoissonParams();
            if (loadCase_ == LoadOneofCase.Poisson) {
              subBuilder.MergeFrom(Poisson);
            }
            input.ReadMessage(subBuilder);
            Poisson = subBuilder;
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// presence of SecurityParams implies use of TLS
  /// </summary>
  public sealed partial class SecurityParams : pb::IMessage<SecurityParams> {
    private static readonly pb::MessageParser<SecurityParams> _parser = new pb::MessageParser<SecurityParams>(() => new SecurityParams());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<SecurityParams> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[3]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public SecurityParams(SecurityParams other) : this() {
      useTestCa_ = other.useTestCa_;
      serverHostOverride_ = other.serverHostOverride_;
      credType_ = other.credType_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

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

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(SecurityParams other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (UseTestCa != other.UseTestCa) return false;
      if (ServerHostOverride != other.ServerHostOverride) return false;
      if (CredType != other.CredType) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(SecurityParams other) {
      if (other == null) {
        return;
      }
      if (other.UseTestCa != false) {
        UseTestCa = other.UseTestCa;
      }
      if (other.ServerHostOverride.Length != 0) {
        ServerHostOverride = other.ServerHostOverride;
      }
      if (other.CredType.Length != 0) {
        CredType = other.CredType;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 8: {
            UseTestCa = input.ReadBool();
            break;
          }
          case 18: {
            ServerHostOverride = input.ReadString();
            break;
          }
          case 26: {
            CredType = input.ReadString();
            break;
          }
        }
      }
    }

  }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[4]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ChannelArg(ChannelArg other) : this() {
      name_ = other.name_;
      switch (other.ValueCase) {
        case ValueOneofCase.StrValue:
          StrValue = other.StrValue;
          break;
        case ValueOneofCase.IntValue:
          IntValue = other.IntValue;
          break;
      }

      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

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

    /// <summary>Field number for the "str_value" field.</summary>
    public const int StrValueFieldNumber = 2;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string StrValue {
      get { return valueCase_ == ValueOneofCase.StrValue ? (string) value_ : ""; }
      set {
        value_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        valueCase_ = ValueOneofCase.StrValue;
      }
    }

    /// <summary>Field number for the "int_value" field.</summary>
    public const int IntValueFieldNumber = 3;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int IntValue {
      get { return valueCase_ == ValueOneofCase.IntValue ? (int) value_ : 0; }
      set {
        value_ = value;
        valueCase_ = ValueOneofCase.IntValue;
      }
    }

    private object value_;
    /// <summary>Enum of possible cases for the "value" oneof.</summary>
    public enum ValueOneofCase {
      None = 0,
      StrValue = 2,
      IntValue = 3,
    }
    private ValueOneofCase valueCase_ = ValueOneofCase.None;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ValueOneofCase ValueCase {
      get { return valueCase_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void ClearValue() {
      valueCase_ = ValueOneofCase.None;
      value_ = null;
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ChannelArg other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Name != other.Name) return false;
      if (StrValue != other.StrValue) return false;
      if (IntValue != other.IntValue) return false;
      if (ValueCase != other.ValueCase) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Name.Length != 0) hash ^= Name.GetHashCode();
      if (valueCase_ == ValueOneofCase.StrValue) hash ^= StrValue.GetHashCode();
      if (valueCase_ == ValueOneofCase.IntValue) hash ^= IntValue.GetHashCode();
      hash ^= (int) valueCase_;
      if (_unknownFields != null) {
        hash ^= _unknownFields.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 (Name.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(Name);
      }
      if (valueCase_ == ValueOneofCase.StrValue) {
        output.WriteRawTag(18);
        output.WriteString(StrValue);
      }
      if (valueCase_ == ValueOneofCase.IntValue) {
        output.WriteRawTag(24);
        output.WriteInt32(IntValue);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Name.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
      }
      if (valueCase_ == ValueOneofCase.StrValue) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(StrValue);
      }
      if (valueCase_ == ValueOneofCase.IntValue) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntValue);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ChannelArg other) {
      if (other == null) {
        return;
      }
      if (other.Name.Length != 0) {
        Name = other.Name;
      }
      switch (other.ValueCase) {
        case ValueOneofCase.StrValue:
          StrValue = other.StrValue;
          break;
        case ValueOneofCase.IntValue:
          IntValue = other.IntValue;
          break;
      }

      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            Name = input.ReadString();
            break;
          }
          case 18: {
            StrValue = input.ReadString();
            break;
          }
          case 24: {
            IntValue = input.ReadInt32();
            break;
          }
        }
      }
    }

  }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[5]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ClientConfig(ClientConfig other) : this() {
      serverTargets_ = other.serverTargets_.Clone();
      clientType_ = other.clientType_;
      securityParams_ = other.securityParams_ != null ? other.securityParams_.Clone() : null;
      outstandingRpcsPerChannel_ = other.outstandingRpcsPerChannel_;
      clientChannels_ = other.clientChannels_;
      asyncClientThreads_ = other.asyncClientThreads_;
      rpcType_ = other.rpcType_;
      loadParams_ = other.loadParams_ != null ? other.loadParams_.Clone() : null;
      payloadConfig_ = other.payloadConfig_ != null ? other.payloadConfig_.Clone() : null;
      histogramParams_ = other.histogramParams_ != null ? other.histogramParams_.Clone() : null;
      coreList_ = other.coreList_.Clone();
      coreLimit_ = other.coreLimit_;
      otherClientApi_ = other.otherClientApi_;
      channelArgs_ = other.channelArgs_.Clone();
      threadsPerCq_ = other.threadsPerCq_;
      messagesPerStream_ = other.messagesPerStream_;
      useCoalesceApi_ = other.useCoalesceApi_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "server_targets" field.</summary>
    public const int ServerTargetsFieldNumber = 1;
    private static readonly pb::FieldCodec<string> _repeated_serverTargets_codec
        = pb::FieldCodec.ForString(10);
    private readonly pbc::RepeatedField<string> serverTargets_ = new pbc::RepeatedField<string>();
    /// <summary>
    /// List of targets to connect to. At least one target needs to be specified.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<string> ServerTargets {
      get { return serverTargets_; }
    }

    /// <summary>Field number for the "client_type" field.</summary>
    public const int ClientTypeFieldNumber = 2;
    private global::Grpc.Testing.ClientType clientType_ = 0;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ClientType ClientType {
      get { return clientType_; }
      set {
        clientType_ = value;
      }
    }

    /// <summary>Field number for the "security_params" field.</summary>
    public const int SecurityParamsFieldNumber = 3;
    private global::Grpc.Testing.SecurityParams securityParams_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.SecurityParams SecurityParams {
      get { return securityParams_; }
      set {
        securityParams_ = value;
      }
    }

    /// <summary>Field number for the "outstanding_rpcs_per_channel" field.</summary>
    public const int OutstandingRpcsPerChannelFieldNumber = 4;
    private int outstandingRpcsPerChannel_;
    /// <summary>
    /// How many concurrent RPCs to start for each channel.
    /// For synchronous client, use a separate thread for each outstanding RPC.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int OutstandingRpcsPerChannel {
      get { return outstandingRpcsPerChannel_; }
      set {
        outstandingRpcsPerChannel_ = value;
      }
    }

    /// <summary>Field number for the "client_channels" field.</summary>
    public const int ClientChannelsFieldNumber = 5;
    private int clientChannels_;
    /// <summary>
    /// Number of independent client channels to create.
    /// i-th channel will connect to server_target[i % server_targets.size()]
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int ClientChannels {
      get { return clientChannels_; }
      set {
        clientChannels_ = value;
      }
    }

    /// <summary>Field number for the "async_client_threads" field.</summary>
    public const int AsyncClientThreadsFieldNumber = 7;
    private int asyncClientThreads_;
    /// <summary>
    /// Only for async client. Number of threads to use to start/manage RPCs.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int AsyncClientThreads {
      get { return asyncClientThreads_; }
      set {
        asyncClientThreads_ = value;
      }
    }

    /// <summary>Field number for the "rpc_type" field.</summary>
    public const int RpcTypeFieldNumber = 8;
    private global::Grpc.Testing.RpcType rpcType_ = 0;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.RpcType RpcType {
      get { return rpcType_; }
      set {
        rpcType_ = value;
      }
    }

    /// <summary>Field number for the "load_params" field.</summary>
    public const int LoadParamsFieldNumber = 10;
    private global::Grpc.Testing.LoadParams loadParams_;
    /// <summary>
    /// The requested load for the entire client (aggregated over all the threads).
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.LoadParams LoadParams {
      get { return loadParams_; }
      set {
        loadParams_ = value;
      }
    }

    /// <summary>Field number for the "payload_config" field.</summary>
    public const int PayloadConfigFieldNumber = 11;
    private global::Grpc.Testing.PayloadConfig payloadConfig_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.PayloadConfig PayloadConfig {
      get { return payloadConfig_; }
      set {
        payloadConfig_ = value;
      }
    }

    /// <summary>Field number for the "histogram_params" field.</summary>
    public const int HistogramParamsFieldNumber = 12;
    private global::Grpc.Testing.HistogramParams histogramParams_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.HistogramParams HistogramParams {
      get { return histogramParams_; }
      set {
        histogramParams_ = value;
      }
    }

    /// <summary>Field number for the "core_list" field.</summary>
    public const int CoreListFieldNumber = 13;
    private static readonly pb::FieldCodec<int> _repeated_coreList_codec
        = pb::FieldCodec.ForInt32(106);
    private readonly pbc::RepeatedField<int> coreList_ = new pbc::RepeatedField<int>();
    /// <summary>
    /// Specify the cores we should run the client on, if desired
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<int> CoreList {
      get { return coreList_; }
    }

    /// <summary>Field number for the "core_limit" field.</summary>
    public const int CoreLimitFieldNumber = 14;
    private int coreLimit_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CoreLimit {
      get { return coreLimit_; }
      set {
        coreLimit_ = value;
      }
    }

    /// <summary>Field number for the "other_client_api" field.</summary>
    public const int OtherClientApiFieldNumber = 15;
    private string otherClientApi_ = "";
    /// <summary>
    /// If we use an OTHER_CLIENT client_type, this string gives more detail
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string OtherClientApi {
      get { return otherClientApi_; }
      set {
        otherClientApi_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "channel_args" field.</summary>
    public const int ChannelArgsFieldNumber = 16;
    private static readonly pb::FieldCodec<global::Grpc.Testing.ChannelArg> _repeated_channelArgs_codec
        = pb::FieldCodec.ForMessage(130, global::Grpc.Testing.ChannelArg.Parser);
    private readonly pbc::RepeatedField<global::Grpc.Testing.ChannelArg> channelArgs_ = new pbc::RepeatedField<global::Grpc.Testing.ChannelArg>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<global::Grpc.Testing.ChannelArg> ChannelArgs {
      get { return channelArgs_; }
    }

    /// <summary>Field number for the "threads_per_cq" field.</summary>
    public const int ThreadsPerCqFieldNumber = 17;
    private int threadsPerCq_;
    /// <summary>
    /// Number of threads that share each completion queue
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int ThreadsPerCq {
      get { return threadsPerCq_; }
      set {
        threadsPerCq_ = value;
      }
    }

    /// <summary>Field number for the "messages_per_stream" field.</summary>
    public const int MessagesPerStreamFieldNumber = 18;
    private int messagesPerStream_;
    /// <summary>
    /// Number of messages on a stream before it gets finished/restarted
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int MessagesPerStream {
      get { return messagesPerStream_; }
      set {
        messagesPerStream_ = value;
      }
    }

    /// <summary>Field number for the "use_coalesce_api" field.</summary>
    public const int UseCoalesceApiFieldNumber = 19;
    private bool useCoalesceApi_;
    /// <summary>
    /// Use coalescing API when possible.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool UseCoalesceApi {
      get { return useCoalesceApi_; }
      set {
        useCoalesceApi_ = value;
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ClientConfig other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if(!serverTargets_.Equals(other.serverTargets_)) return false;
      if (ClientType != other.ClientType) return false;
      if (!object.Equals(SecurityParams, other.SecurityParams)) return false;
      if (OutstandingRpcsPerChannel != other.OutstandingRpcsPerChannel) return false;
      if (ClientChannels != other.ClientChannels) return false;
      if (AsyncClientThreads != other.AsyncClientThreads) return false;
      if (RpcType != other.RpcType) return false;
      if (!object.Equals(LoadParams, other.LoadParams)) return false;
      if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false;
      if (!object.Equals(HistogramParams, other.HistogramParams)) return false;
      if(!coreList_.Equals(other.coreList_)) return false;
      if (CoreLimit != other.CoreLimit) return false;
      if (OtherClientApi != other.OtherClientApi) return false;
      if(!channelArgs_.Equals(other.channelArgs_)) return false;
      if (ThreadsPerCq != other.ThreadsPerCq) return false;
      if (MessagesPerStream != other.MessagesPerStream) return false;
      if (UseCoalesceApi != other.UseCoalesceApi) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      hash ^= serverTargets_.GetHashCode();
      if (ClientType != 0) hash ^= ClientType.GetHashCode();
      if (securityParams_ != null) hash ^= SecurityParams.GetHashCode();
      if (OutstandingRpcsPerChannel != 0) hash ^= OutstandingRpcsPerChannel.GetHashCode();
      if (ClientChannels != 0) hash ^= ClientChannels.GetHashCode();
      if (AsyncClientThreads != 0) hash ^= AsyncClientThreads.GetHashCode();
      if (RpcType != 0) hash ^= RpcType.GetHashCode();
      if (loadParams_ != null) hash ^= LoadParams.GetHashCode();
      if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode();
      if (histogramParams_ != null) hash ^= HistogramParams.GetHashCode();
      hash ^= coreList_.GetHashCode();
      if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode();
      if (OtherClientApi.Length != 0) hash ^= OtherClientApi.GetHashCode();
      hash ^= channelArgs_.GetHashCode();
      if (ThreadsPerCq != 0) hash ^= ThreadsPerCq.GetHashCode();
      if (MessagesPerStream != 0) hash ^= MessagesPerStream.GetHashCode();
      if (UseCoalesceApi != false) hash ^= UseCoalesceApi.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.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) {
      serverTargets_.WriteTo(output, _repeated_serverTargets_codec);
      if (ClientType != 0) {
        output.WriteRawTag(16);
        output.WriteEnum((int) ClientType);
      }
      if (securityParams_ != null) {
        output.WriteRawTag(26);
        output.WriteMessage(SecurityParams);
      }
      if (OutstandingRpcsPerChannel != 0) {
        output.WriteRawTag(32);
        output.WriteInt32(OutstandingRpcsPerChannel);
      }
      if (ClientChannels != 0) {
        output.WriteRawTag(40);
        output.WriteInt32(ClientChannels);
      }
      if (AsyncClientThreads != 0) {
        output.WriteRawTag(56);
        output.WriteInt32(AsyncClientThreads);
      }
      if (RpcType != 0) {
        output.WriteRawTag(64);
        output.WriteEnum((int) RpcType);
      }
      if (loadParams_ != null) {
        output.WriteRawTag(82);
        output.WriteMessage(LoadParams);
      }
      if (payloadConfig_ != null) {
        output.WriteRawTag(90);
        output.WriteMessage(PayloadConfig);
      }
      if (histogramParams_ != null) {
        output.WriteRawTag(98);
        output.WriteMessage(HistogramParams);
      }
      coreList_.WriteTo(output, _repeated_coreList_codec);
      if (CoreLimit != 0) {
        output.WriteRawTag(112);
        output.WriteInt32(CoreLimit);
      }
      if (OtherClientApi.Length != 0) {
        output.WriteRawTag(122);
        output.WriteString(OtherClientApi);
      }
      channelArgs_.WriteTo(output, _repeated_channelArgs_codec);
      if (ThreadsPerCq != 0) {
        output.WriteRawTag(136, 1);
        output.WriteInt32(ThreadsPerCq);
      }
      if (MessagesPerStream != 0) {
        output.WriteRawTag(144, 1);
        output.WriteInt32(MessagesPerStream);
      }
      if (UseCoalesceApi != false) {
        output.WriteRawTag(152, 1);
        output.WriteBool(UseCoalesceApi);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      size += serverTargets_.CalculateSize(_repeated_serverTargets_codec);
      if (ClientType != 0) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ClientType);
      }
      if (securityParams_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SecurityParams);
      }
      if (OutstandingRpcsPerChannel != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(OutstandingRpcsPerChannel);
      }
      if (ClientChannels != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ClientChannels);
      }
      if (AsyncClientThreads != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(AsyncClientThreads);
      }
      if (RpcType != 0) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) RpcType);
      }
      if (loadParams_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(LoadParams);
      }
      if (payloadConfig_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(PayloadConfig);
      }
      if (histogramParams_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(HistogramParams);
      }
      size += coreList_.CalculateSize(_repeated_coreList_codec);
      if (CoreLimit != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(CoreLimit);
      }
      if (OtherClientApi.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherClientApi);
      }
      size += channelArgs_.CalculateSize(_repeated_channelArgs_codec);
      if (ThreadsPerCq != 0) {
        size += 2 + pb::CodedOutputStream.ComputeInt32Size(ThreadsPerCq);
      }
      if (MessagesPerStream != 0) {
        size += 2 + pb::CodedOutputStream.ComputeInt32Size(MessagesPerStream);
      }
      if (UseCoalesceApi != false) {
        size += 2 + 1;
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ClientConfig other) {
      if (other == null) {
        return;
      }
      serverTargets_.Add(other.serverTargets_);
      if (other.ClientType != 0) {
        ClientType = other.ClientType;
      }
      if (other.securityParams_ != null) {
        if (securityParams_ == null) {
          securityParams_ = new global::Grpc.Testing.SecurityParams();
        }
        SecurityParams.MergeFrom(other.SecurityParams);
      }
      if (other.OutstandingRpcsPerChannel != 0) {
        OutstandingRpcsPerChannel = other.OutstandingRpcsPerChannel;
      }
      if (other.ClientChannels != 0) {
        ClientChannels = other.ClientChannels;
      }
      if (other.AsyncClientThreads != 0) {
        AsyncClientThreads = other.AsyncClientThreads;
      }
      if (other.RpcType != 0) {
        RpcType = other.RpcType;
      }
      if (other.loadParams_ != null) {
        if (loadParams_ == null) {
          loadParams_ = new global::Grpc.Testing.LoadParams();
        }
        LoadParams.MergeFrom(other.LoadParams);
      }
      if (other.payloadConfig_ != null) {
        if (payloadConfig_ == null) {
          payloadConfig_ = new global::Grpc.Testing.PayloadConfig();
        }
        PayloadConfig.MergeFrom(other.PayloadConfig);
      }
      if (other.histogramParams_ != null) {
        if (histogramParams_ == null) {
          histogramParams_ = new global::Grpc.Testing.HistogramParams();
        }
        HistogramParams.MergeFrom(other.HistogramParams);
      }
      coreList_.Add(other.coreList_);
      if (other.CoreLimit != 0) {
        CoreLimit = other.CoreLimit;
      }
      if (other.OtherClientApi.Length != 0) {
        OtherClientApi = other.OtherClientApi;
      }
      channelArgs_.Add(other.channelArgs_);
      if (other.ThreadsPerCq != 0) {
        ThreadsPerCq = other.ThreadsPerCq;
      }
      if (other.MessagesPerStream != 0) {
        MessagesPerStream = other.MessagesPerStream;
      }
      if (other.UseCoalesceApi != false) {
        UseCoalesceApi = other.UseCoalesceApi;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            serverTargets_.AddEntriesFrom(input, _repeated_serverTargets_codec);
            break;
          }
          case 16: {
            clientType_ = (global::Grpc.Testing.ClientType) input.ReadEnum();
            break;
          }
          case 26: {
            if (securityParams_ == null) {
              securityParams_ = new global::Grpc.Testing.SecurityParams();
            }
            input.ReadMessage(securityParams_);
            break;
          }
          case 32: {
            OutstandingRpcsPerChannel = input.ReadInt32();
            break;
          }
          case 40: {
            ClientChannels = input.ReadInt32();
            break;
          }
          case 56: {
            AsyncClientThreads = input.ReadInt32();
            break;
          }
          case 64: {
            rpcType_ = (global::Grpc.Testing.RpcType) input.ReadEnum();
            break;
          }
          case 82: {
            if (loadParams_ == null) {
              loadParams_ = new global::Grpc.Testing.LoadParams();
            }
            input.ReadMessage(loadParams_);
            break;
          }
          case 90: {
            if (payloadConfig_ == null) {
              payloadConfig_ = new global::Grpc.Testing.PayloadConfig();
            }
            input.ReadMessage(payloadConfig_);
            break;
          }
          case 98: {
            if (histogramParams_ == null) {
              histogramParams_ = new global::Grpc.Testing.HistogramParams();
            }
            input.ReadMessage(histogramParams_);
            break;
          }
          case 106:
          case 104: {
            coreList_.AddEntriesFrom(input, _repeated_coreList_codec);
            break;
          }
          case 112: {
            CoreLimit = input.ReadInt32();
            break;
          }
          case 122: {
            OtherClientApi = input.ReadString();
            break;
          }
          case 130: {
            channelArgs_.AddEntriesFrom(input, _repeated_channelArgs_codec);
            break;
          }
          case 136: {
            ThreadsPerCq = input.ReadInt32();
            break;
          }
          case 144: {
            MessagesPerStream = input.ReadInt32();
            break;
          }
          case 152: {
            UseCoalesceApi = input.ReadBool();
            break;
          }
        }
      }
    }

  }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[6]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ClientStatus(ClientStatus other) : this() {
      stats_ = other.stats_ != null ? other.stats_.Clone() : null;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "stats" field.</summary>
    public const int StatsFieldNumber = 1;
    private global::Grpc.Testing.ClientStats stats_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ClientStats Stats {
      get { return stats_; }
      set {
        stats_ = value;
      }
    }

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (stats_ != null) hash ^= Stats.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.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 (stats_ != null) {
        output.WriteRawTag(10);
        output.WriteMessage(Stats);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (stats_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stats);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ClientStatus other) {
      if (other == null) {
        return;
      }
      if (other.stats_ != null) {
        if (stats_ == null) {
          stats_ = new global::Grpc.Testing.ClientStats();
        }
        Stats.MergeFrom(other.Stats);
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            if (stats_ == null) {
              stats_ = new global::Grpc.Testing.ClientStats();
            }
            input.ReadMessage(stats_);
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Request current stats
  /// </summary>
  public sealed partial class Mark : pb::IMessage<Mark> {
    private static readonly pb::MessageParser<Mark> _parser = new pb::MessageParser<Mark>(() => new Mark());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<Mark> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[7]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public Mark(Mark other) : this() {
      reset_ = other.reset_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "reset" field.</summary>
    public const int ResetFieldNumber = 1;
    private bool reset_;
    /// <summary>
    /// if true, the stats will be reset after taking their snapshot.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Reset {
      get { return reset_; }
      set {
        reset_ = value;
      }
    }

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Reset != false) hash ^= Reset.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.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 (Reset != false) {
        output.WriteRawTag(8);
        output.WriteBool(Reset);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Reset != false) {
        size += 1 + 1;
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(Mark other) {
      if (other == null) {
        return;
      }
      if (other.Reset != false) {
        Reset = other.Reset;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 8: {
            Reset = input.ReadBool();
            break;
          }
        }
      }
    }

  }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[8]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ClientArgs(ClientArgs other) : this() {
      switch (other.ArgtypeCase) {
        case ArgtypeOneofCase.Setup:
          Setup = other.Setup.Clone();
          break;
        case ArgtypeOneofCase.Mark:
          Mark = other.Mark.Clone();
          break;
      }

      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "setup" field.</summary>
    public const int SetupFieldNumber = 1;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ClientConfig Setup {
      get { return argtypeCase_ == ArgtypeOneofCase.Setup ? (global::Grpc.Testing.ClientConfig) argtype_ : null; }
      set {
        argtype_ = value;
        argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Setup;
      }
    }

    /// <summary>Field number for the "mark" field.</summary>
    public const int MarkFieldNumber = 2;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.Mark Mark {
      get { return argtypeCase_ == ArgtypeOneofCase.Mark ? (global::Grpc.Testing.Mark) argtype_ : null; }
      set {
        argtype_ = value;
        argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Mark;
      }
    }

    private object argtype_;
    /// <summary>Enum of possible cases for the "argtype" oneof.</summary>
    public enum ArgtypeOneofCase {
      None = 0,
      Setup = 1,
      Mark = 2,
    }
    private ArgtypeOneofCase argtypeCase_ = ArgtypeOneofCase.None;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ArgtypeOneofCase ArgtypeCase {
      get { return argtypeCase_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void ClearArgtype() {
      argtypeCase_ = ArgtypeOneofCase.None;
      argtype_ = null;
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ClientArgs other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!object.Equals(Setup, other.Setup)) return false;
      if (!object.Equals(Mark, other.Mark)) return false;
      if (ArgtypeCase != other.ArgtypeCase) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode();
      if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode();
      hash ^= (int) argtypeCase_;
      if (_unknownFields != null) {
        hash ^= _unknownFields.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 (argtypeCase_ == ArgtypeOneofCase.Setup) {
        output.WriteRawTag(10);
        output.WriteMessage(Setup);
      }
      if (argtypeCase_ == ArgtypeOneofCase.Mark) {
        output.WriteRawTag(18);
        output.WriteMessage(Mark);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (argtypeCase_ == ArgtypeOneofCase.Setup) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Setup);
      }
      if (argtypeCase_ == ArgtypeOneofCase.Mark) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Mark);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ClientArgs other) {
      if (other == null) {
        return;
      }
      switch (other.ArgtypeCase) {
        case ArgtypeOneofCase.Setup:
          if (Setup == null) {
            Setup = new global::Grpc.Testing.ClientConfig();
          }
          Setup.MergeFrom(other.Setup);
          break;
        case ArgtypeOneofCase.Mark:
          if (Mark == null) {
            Mark = new global::Grpc.Testing.Mark();
          }
          Mark.MergeFrom(other.Mark);
          break;
      }

      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            global::Grpc.Testing.ClientConfig subBuilder = new global::Grpc.Testing.ClientConfig();
            if (argtypeCase_ == ArgtypeOneofCase.Setup) {
              subBuilder.MergeFrom(Setup);
            }
            input.ReadMessage(subBuilder);
            Setup = subBuilder;
            break;
          }
          case 18: {
            global::Grpc.Testing.Mark subBuilder = new global::Grpc.Testing.Mark();
            if (argtypeCase_ == ArgtypeOneofCase.Mark) {
              subBuilder.MergeFrom(Mark);
            }
            input.ReadMessage(subBuilder);
            Mark = subBuilder;
            break;
          }
        }
      }
    }

  }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[9]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerConfig(ServerConfig other) : this() {
      serverType_ = other.serverType_;
      securityParams_ = other.securityParams_ != null ? other.securityParams_.Clone() : null;
      port_ = other.port_;
      asyncServerThreads_ = other.asyncServerThreads_;
      coreLimit_ = other.coreLimit_;
      payloadConfig_ = other.payloadConfig_ != null ? other.payloadConfig_.Clone() : null;
      coreList_ = other.coreList_.Clone();
      otherServerApi_ = other.otherServerApi_;
      threadsPerCq_ = other.threadsPerCq_;
      resourceQuotaSize_ = other.resourceQuotaSize_;
      channelArgs_ = other.channelArgs_.Clone();
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "server_type" field.</summary>
    public const int ServerTypeFieldNumber = 1;
    private global::Grpc.Testing.ServerType serverType_ = 0;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ServerType ServerType {
      get { return serverType_; }
      set {
        serverType_ = value;
      }
    }

    /// <summary>Field number for the "security_params" field.</summary>
    public const int SecurityParamsFieldNumber = 2;
    private global::Grpc.Testing.SecurityParams securityParams_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.SecurityParams SecurityParams {
      get { return securityParams_; }
      set {
        securityParams_ = value;
      }
    }

    /// <summary>Field number for the "port" field.</summary>
    public const int PortFieldNumber = 4;
    private int port_;
    /// <summary>
    /// Port on which to listen. Zero means pick unused port.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int Port {
      get { return port_; }
      set {
        port_ = value;
      }
    }

    /// <summary>Field number for the "async_server_threads" field.</summary>
    public const int AsyncServerThreadsFieldNumber = 7;
    private int asyncServerThreads_;
    /// <summary>
    /// Only for async server. Number of threads used to serve the requests.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int AsyncServerThreads {
      get { return asyncServerThreads_; }
      set {
        asyncServerThreads_ = value;
      }
    }

    /// <summary>Field number for the "core_limit" field.</summary>
    public const int CoreLimitFieldNumber = 8;
    private int coreLimit_;
    /// <summary>
    /// Specify the number of cores to limit server to, if desired
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CoreLimit {
      get { return coreLimit_; }
      set {
        coreLimit_ = value;
      }
    }

    /// <summary>Field number for the "payload_config" field.</summary>
    public const int PayloadConfigFieldNumber = 9;
    private global::Grpc.Testing.PayloadConfig payloadConfig_;
    /// <summary>
    /// payload config, used in generic server.
    /// Note this must NOT be used in proto (non-generic) servers. For proto servers,
    /// 'response sizes' must be configured from the 'response_size' field of the
    /// 'SimpleRequest' objects in RPC requests.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.PayloadConfig PayloadConfig {
      get { return payloadConfig_; }
      set {
        payloadConfig_ = value;
      }
    }

    /// <summary>Field number for the "core_list" field.</summary>
    public const int CoreListFieldNumber = 10;
    private static readonly pb::FieldCodec<int> _repeated_coreList_codec
        = pb::FieldCodec.ForInt32(82);
    private readonly pbc::RepeatedField<int> coreList_ = new pbc::RepeatedField<int>();
    /// <summary>
    /// Specify the cores we should run the server on, if desired
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<int> CoreList {
      get { return coreList_; }
    }

    /// <summary>Field number for the "other_server_api" field.</summary>
    public const int OtherServerApiFieldNumber = 11;
    private string otherServerApi_ = "";
    /// <summary>
    /// If we use an OTHER_SERVER client_type, this string gives more detail
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string OtherServerApi {
      get { return otherServerApi_; }
      set {
        otherServerApi_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "threads_per_cq" field.</summary>
    public const int ThreadsPerCqFieldNumber = 12;
    private int threadsPerCq_;
    /// <summary>
    /// Number of threads that share each completion queue
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int ThreadsPerCq {
      get { return threadsPerCq_; }
      set {
        threadsPerCq_ = value;
      }
    }

    /// <summary>Field number for the "resource_quota_size" field.</summary>
    public const int ResourceQuotaSizeFieldNumber = 1001;
    private int resourceQuotaSize_;
    /// <summary>
    /// Buffer pool size (no buffer pool specified if unset)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int ResourceQuotaSize {
      get { return resourceQuotaSize_; }
      set {
        resourceQuotaSize_ = value;
      }
    }

    /// <summary>Field number for the "channel_args" field.</summary>
    public const int ChannelArgsFieldNumber = 1002;
    private static readonly pb::FieldCodec<global::Grpc.Testing.ChannelArg> _repeated_channelArgs_codec
        = pb::FieldCodec.ForMessage(8018, global::Grpc.Testing.ChannelArg.Parser);
    private readonly pbc::RepeatedField<global::Grpc.Testing.ChannelArg> channelArgs_ = new pbc::RepeatedField<global::Grpc.Testing.ChannelArg>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<global::Grpc.Testing.ChannelArg> ChannelArgs {
      get { return channelArgs_; }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ServerConfig other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (ServerType != other.ServerType) return false;
      if (!object.Equals(SecurityParams, other.SecurityParams)) return false;
      if (Port != other.Port) return false;
      if (AsyncServerThreads != other.AsyncServerThreads) return false;
      if (CoreLimit != other.CoreLimit) return false;
      if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false;
      if(!coreList_.Equals(other.coreList_)) return false;
      if (OtherServerApi != other.OtherServerApi) return false;
      if (ThreadsPerCq != other.ThreadsPerCq) return false;
      if (ResourceQuotaSize != other.ResourceQuotaSize) return false;
      if(!channelArgs_.Equals(other.channelArgs_)) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (ServerType != 0) hash ^= ServerType.GetHashCode();
      if (securityParams_ != null) hash ^= SecurityParams.GetHashCode();
      if (Port != 0) hash ^= Port.GetHashCode();
      if (AsyncServerThreads != 0) hash ^= AsyncServerThreads.GetHashCode();
      if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode();
      if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode();
      hash ^= coreList_.GetHashCode();
      if (OtherServerApi.Length != 0) hash ^= OtherServerApi.GetHashCode();
      if (ThreadsPerCq != 0) hash ^= ThreadsPerCq.GetHashCode();
      if (ResourceQuotaSize != 0) hash ^= ResourceQuotaSize.GetHashCode();
      hash ^= channelArgs_.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.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 (ServerType != 0) {
        output.WriteRawTag(8);
        output.WriteEnum((int) ServerType);
      }
      if (securityParams_ != null) {
        output.WriteRawTag(18);
        output.WriteMessage(SecurityParams);
      }
      if (Port != 0) {
        output.WriteRawTag(32);
        output.WriteInt32(Port);
      }
      if (AsyncServerThreads != 0) {
        output.WriteRawTag(56);
        output.WriteInt32(AsyncServerThreads);
      }
      if (CoreLimit != 0) {
        output.WriteRawTag(64);
        output.WriteInt32(CoreLimit);
      }
      if (payloadConfig_ != null) {
        output.WriteRawTag(74);
        output.WriteMessage(PayloadConfig);
      }
      coreList_.WriteTo(output, _repeated_coreList_codec);
      if (OtherServerApi.Length != 0) {
        output.WriteRawTag(90);
        output.WriteString(OtherServerApi);
      }
      if (ThreadsPerCq != 0) {
        output.WriteRawTag(96);
        output.WriteInt32(ThreadsPerCq);
      }
      if (ResourceQuotaSize != 0) {
        output.WriteRawTag(200, 62);
        output.WriteInt32(ResourceQuotaSize);
      }
      channelArgs_.WriteTo(output, _repeated_channelArgs_codec);
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (ServerType != 0) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ServerType);
      }
      if (securityParams_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SecurityParams);
      }
      if (Port != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Port);
      }
      if (AsyncServerThreads != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(AsyncServerThreads);
      }
      if (CoreLimit != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(CoreLimit);
      }
      if (payloadConfig_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(PayloadConfig);
      }
      size += coreList_.CalculateSize(_repeated_coreList_codec);
      if (OtherServerApi.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherServerApi);
      }
      if (ThreadsPerCq != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ThreadsPerCq);
      }
      if (ResourceQuotaSize != 0) {
        size += 2 + pb::CodedOutputStream.ComputeInt32Size(ResourceQuotaSize);
      }
      size += channelArgs_.CalculateSize(_repeated_channelArgs_codec);
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ServerConfig other) {
      if (other == null) {
        return;
      }
      if (other.ServerType != 0) {
        ServerType = other.ServerType;
      }
      if (other.securityParams_ != null) {
        if (securityParams_ == null) {
          securityParams_ = new global::Grpc.Testing.SecurityParams();
        }
        SecurityParams.MergeFrom(other.SecurityParams);
      }
      if (other.Port != 0) {
        Port = other.Port;
      }
      if (other.AsyncServerThreads != 0) {
        AsyncServerThreads = other.AsyncServerThreads;
      }
      if (other.CoreLimit != 0) {
        CoreLimit = other.CoreLimit;
      }
      if (other.payloadConfig_ != null) {
        if (payloadConfig_ == null) {
          payloadConfig_ = new global::Grpc.Testing.PayloadConfig();
        }
        PayloadConfig.MergeFrom(other.PayloadConfig);
      }
      coreList_.Add(other.coreList_);
      if (other.OtherServerApi.Length != 0) {
        OtherServerApi = other.OtherServerApi;
      }
      if (other.ThreadsPerCq != 0) {
        ThreadsPerCq = other.ThreadsPerCq;
      }
      if (other.ResourceQuotaSize != 0) {
        ResourceQuotaSize = other.ResourceQuotaSize;
      }
      channelArgs_.Add(other.channelArgs_);
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 8: {
            serverType_ = (global::Grpc.Testing.ServerType) input.ReadEnum();
            break;
          }
          case 18: {
            if (securityParams_ == null) {
              securityParams_ = new global::Grpc.Testing.SecurityParams();
            }
            input.ReadMessage(securityParams_);
            break;
          }
          case 32: {
            Port = input.ReadInt32();
            break;
          }
          case 56: {
            AsyncServerThreads = input.ReadInt32();
            break;
          }
          case 64: {
            CoreLimit = input.ReadInt32();
            break;
          }
          case 74: {
            if (payloadConfig_ == null) {
              payloadConfig_ = new global::Grpc.Testing.PayloadConfig();
            }
            input.ReadMessage(payloadConfig_);
            break;
          }
          case 82:
          case 80: {
            coreList_.AddEntriesFrom(input, _repeated_coreList_codec);
            break;
          }
          case 90: {
            OtherServerApi = input.ReadString();
            break;
          }
          case 96: {
            ThreadsPerCq = input.ReadInt32();
            break;
          }
          case 8008: {
            ResourceQuotaSize = input.ReadInt32();
            break;
          }
          case 8018: {
            channelArgs_.AddEntriesFrom(input, _repeated_channelArgs_codec);
            break;
          }
        }
      }
    }

  }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[10]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerArgs(ServerArgs other) : this() {
      switch (other.ArgtypeCase) {
        case ArgtypeOneofCase.Setup:
          Setup = other.Setup.Clone();
          break;
        case ArgtypeOneofCase.Mark:
          Mark = other.Mark.Clone();
          break;
      }

      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "setup" field.</summary>
    public const int SetupFieldNumber = 1;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ServerConfig Setup {
      get { return argtypeCase_ == ArgtypeOneofCase.Setup ? (global::Grpc.Testing.ServerConfig) argtype_ : null; }
      set {
        argtype_ = value;
        argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Setup;
      }
    }

    /// <summary>Field number for the "mark" field.</summary>
    public const int MarkFieldNumber = 2;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.Mark Mark {
      get { return argtypeCase_ == ArgtypeOneofCase.Mark ? (global::Grpc.Testing.Mark) argtype_ : null; }
      set {
        argtype_ = value;
        argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Mark;
      }
    }

    private object argtype_;
    /// <summary>Enum of possible cases for the "argtype" oneof.</summary>
    public enum ArgtypeOneofCase {
      None = 0,
      Setup = 1,
      Mark = 2,
    }
    private ArgtypeOneofCase argtypeCase_ = ArgtypeOneofCase.None;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ArgtypeOneofCase ArgtypeCase {
      get { return argtypeCase_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void ClearArgtype() {
      argtypeCase_ = ArgtypeOneofCase.None;
      argtype_ = null;
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ServerArgs other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!object.Equals(Setup, other.Setup)) return false;
      if (!object.Equals(Mark, other.Mark)) return false;
      if (ArgtypeCase != other.ArgtypeCase) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode();
      if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode();
      hash ^= (int) argtypeCase_;
      if (_unknownFields != null) {
        hash ^= _unknownFields.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 (argtypeCase_ == ArgtypeOneofCase.Setup) {
        output.WriteRawTag(10);
        output.WriteMessage(Setup);
      }
      if (argtypeCase_ == ArgtypeOneofCase.Mark) {
        output.WriteRawTag(18);
        output.WriteMessage(Mark);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (argtypeCase_ == ArgtypeOneofCase.Setup) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Setup);
      }
      if (argtypeCase_ == ArgtypeOneofCase.Mark) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Mark);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ServerArgs other) {
      if (other == null) {
        return;
      }
      switch (other.ArgtypeCase) {
        case ArgtypeOneofCase.Setup:
          if (Setup == null) {
            Setup = new global::Grpc.Testing.ServerConfig();
          }
          Setup.MergeFrom(other.Setup);
          break;
        case ArgtypeOneofCase.Mark:
          if (Mark == null) {
            Mark = new global::Grpc.Testing.Mark();
          }
          Mark.MergeFrom(other.Mark);
          break;
      }

      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            global::Grpc.Testing.ServerConfig subBuilder = new global::Grpc.Testing.ServerConfig();
            if (argtypeCase_ == ArgtypeOneofCase.Setup) {
              subBuilder.MergeFrom(Setup);
            }
            input.ReadMessage(subBuilder);
            Setup = subBuilder;
            break;
          }
          case 18: {
            global::Grpc.Testing.Mark subBuilder = new global::Grpc.Testing.Mark();
            if (argtypeCase_ == ArgtypeOneofCase.Mark) {
              subBuilder.MergeFrom(Mark);
            }
            input.ReadMessage(subBuilder);
            Mark = subBuilder;
            break;
          }
        }
      }
    }

  }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[11]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ServerStatus(ServerStatus other) : this() {
      stats_ = other.stats_ != null ? other.stats_.Clone() : null;
      port_ = other.port_;
      cores_ = other.cores_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "stats" field.</summary>
    public const int StatsFieldNumber = 1;
    private global::Grpc.Testing.ServerStats stats_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ServerStats Stats {
      get { return stats_; }
      set {
        stats_ = value;
      }
    }

    /// <summary>Field number for the "port" field.</summary>
    public const int PortFieldNumber = 2;
    private int port_;
    /// <summary>
    /// the port bound by the server
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int Port {
      get { return port_; }
      set {
        port_ = value;
      }
    }

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ServerStatus other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!object.Equals(Stats, other.Stats)) return false;
      if (Port != other.Port) return false;
      if (Cores != other.Cores) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (stats_ != null) hash ^= Stats.GetHashCode();
      if (Port != 0) hash ^= Port.GetHashCode();
      if (Cores != 0) hash ^= Cores.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.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 (stats_ != null) {
        output.WriteRawTag(10);
        output.WriteMessage(Stats);
      }
      if (Port != 0) {
        output.WriteRawTag(16);
        output.WriteInt32(Port);
      }
      if (Cores != 0) {
        output.WriteRawTag(24);
        output.WriteInt32(Cores);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (stats_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stats);
      }
      if (Port != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Port);
      }
      if (Cores != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Cores);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ServerStatus other) {
      if (other == null) {
        return;
      }
      if (other.stats_ != null) {
        if (stats_ == null) {
          stats_ = new global::Grpc.Testing.ServerStats();
        }
        Stats.MergeFrom(other.Stats);
      }
      if (other.Port != 0) {
        Port = other.Port;
      }
      if (other.Cores != 0) {
        Cores = other.Cores;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            if (stats_ == null) {
              stats_ = new global::Grpc.Testing.ServerStats();
            }
            input.ReadMessage(stats_);
            break;
          }
          case 16: {
            Port = input.ReadInt32();
            break;
          }
          case 24: {
            Cores = input.ReadInt32();
            break;
          }
        }
      }
    }

  }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[12]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public CoreRequest(CoreRequest other) : this() {
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (_unknownFields != null) {
        hash ^= _unknownFields.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 (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(CoreRequest other) {
      if (other == null) {
        return;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

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

  }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[13]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public CoreResponse(CoreResponse other) : this() {
      cores_ = other.cores_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

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

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

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(CoreResponse other) {
      if (other == null) {
        return;
      }
      if (other.Cores != 0) {
        Cores = other.Cores;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 8: {
            Cores = input.ReadInt32();
            break;
          }
        }
      }
    }

  }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[14]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public Void(Void other) : this() {
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (_unknownFields != null) {
        hash ^= _unknownFields.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 (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(Void other) {
      if (other == null) {
        return;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

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

  }

  /// <summary>
  /// A single performance scenario: input to qps_json_driver
  /// </summary>
  public sealed partial class Scenario : pb::IMessage<Scenario> {
    private static readonly pb::MessageParser<Scenario> _parser = new pb::MessageParser<Scenario>(() => new Scenario());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<Scenario> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[15]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public Scenario(Scenario other) : this() {
      name_ = other.name_;
      clientConfig_ = other.clientConfig_ != null ? other.clientConfig_.Clone() : null;
      numClients_ = other.numClients_;
      serverConfig_ = other.serverConfig_ != null ? other.serverConfig_.Clone() : null;
      numServers_ = other.numServers_;
      warmupSeconds_ = other.warmupSeconds_;
      benchmarkSeconds_ = other.benchmarkSeconds_;
      spawnLocalWorkerCount_ = other.spawnLocalWorkerCount_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "name" field.</summary>
    public const int NameFieldNumber = 1;
    private string name_ = "";
    /// <summary>
    /// Human readable name for this scenario
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string Name {
      get { return name_; }
      set {
        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "client_config" field.</summary>
    public const int ClientConfigFieldNumber = 2;
    private global::Grpc.Testing.ClientConfig clientConfig_;
    /// <summary>
    /// Client configuration
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ClientConfig ClientConfig {
      get { return clientConfig_; }
      set {
        clientConfig_ = value;
      }
    }

    /// <summary>Field number for the "num_clients" field.</summary>
    public const int NumClientsFieldNumber = 3;
    private int numClients_;
    /// <summary>
    /// Number of clients to start for the test
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int NumClients {
      get { return numClients_; }
      set {
        numClients_ = value;
      }
    }

    /// <summary>Field number for the "server_config" field.</summary>
    public const int ServerConfigFieldNumber = 4;
    private global::Grpc.Testing.ServerConfig serverConfig_;
    /// <summary>
    /// Server configuration
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ServerConfig ServerConfig {
      get { return serverConfig_; }
      set {
        serverConfig_ = value;
      }
    }

    /// <summary>Field number for the "num_servers" field.</summary>
    public const int NumServersFieldNumber = 5;
    private int numServers_;
    /// <summary>
    /// Number of servers to start for the test
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int NumServers {
      get { return numServers_; }
      set {
        numServers_ = value;
      }
    }

    /// <summary>Field number for the "warmup_seconds" field.</summary>
    public const int WarmupSecondsFieldNumber = 6;
    private int warmupSeconds_;
    /// <summary>
    /// Warmup period, in seconds
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int WarmupSeconds {
      get { return warmupSeconds_; }
      set {
        warmupSeconds_ = value;
      }
    }

    /// <summary>Field number for the "benchmark_seconds" field.</summary>
    public const int BenchmarkSecondsFieldNumber = 7;
    private int benchmarkSeconds_;
    /// <summary>
    /// Benchmark time, in seconds
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int BenchmarkSeconds {
      get { return benchmarkSeconds_; }
      set {
        benchmarkSeconds_ = value;
      }
    }

    /// <summary>Field number for the "spawn_local_worker_count" field.</summary>
    public const int SpawnLocalWorkerCountFieldNumber = 8;
    private int spawnLocalWorkerCount_;
    /// <summary>
    /// Number of workers to spawn locally (usually zero)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int SpawnLocalWorkerCount {
      get { return spawnLocalWorkerCount_; }
      set {
        spawnLocalWorkerCount_ = value;
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(Scenario other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (Name != other.Name) return false;
      if (!object.Equals(ClientConfig, other.ClientConfig)) return false;
      if (NumClients != other.NumClients) return false;
      if (!object.Equals(ServerConfig, other.ServerConfig)) return false;
      if (NumServers != other.NumServers) return false;
      if (WarmupSeconds != other.WarmupSeconds) return false;
      if (BenchmarkSeconds != other.BenchmarkSeconds) return false;
      if (SpawnLocalWorkerCount != other.SpawnLocalWorkerCount) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Name.Length != 0) hash ^= Name.GetHashCode();
      if (clientConfig_ != null) hash ^= ClientConfig.GetHashCode();
      if (NumClients != 0) hash ^= NumClients.GetHashCode();
      if (serverConfig_ != null) hash ^= ServerConfig.GetHashCode();
      if (NumServers != 0) hash ^= NumServers.GetHashCode();
      if (WarmupSeconds != 0) hash ^= WarmupSeconds.GetHashCode();
      if (BenchmarkSeconds != 0) hash ^= BenchmarkSeconds.GetHashCode();
      if (SpawnLocalWorkerCount != 0) hash ^= SpawnLocalWorkerCount.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.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 (Name.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(Name);
      }
      if (clientConfig_ != null) {
        output.WriteRawTag(18);
        output.WriteMessage(ClientConfig);
      }
      if (NumClients != 0) {
        output.WriteRawTag(24);
        output.WriteInt32(NumClients);
      }
      if (serverConfig_ != null) {
        output.WriteRawTag(34);
        output.WriteMessage(ServerConfig);
      }
      if (NumServers != 0) {
        output.WriteRawTag(40);
        output.WriteInt32(NumServers);
      }
      if (WarmupSeconds != 0) {
        output.WriteRawTag(48);
        output.WriteInt32(WarmupSeconds);
      }
      if (BenchmarkSeconds != 0) {
        output.WriteRawTag(56);
        output.WriteInt32(BenchmarkSeconds);
      }
      if (SpawnLocalWorkerCount != 0) {
        output.WriteRawTag(64);
        output.WriteInt32(SpawnLocalWorkerCount);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Name.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
      }
      if (clientConfig_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ClientConfig);
      }
      if (NumClients != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(NumClients);
      }
      if (serverConfig_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ServerConfig);
      }
      if (NumServers != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(NumServers);
      }
      if (WarmupSeconds != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(WarmupSeconds);
      }
      if (BenchmarkSeconds != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(BenchmarkSeconds);
      }
      if (SpawnLocalWorkerCount != 0) {
        size += 1 + pb::CodedOutputStream.ComputeInt32Size(SpawnLocalWorkerCount);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(Scenario other) {
      if (other == null) {
        return;
      }
      if (other.Name.Length != 0) {
        Name = other.Name;
      }
      if (other.clientConfig_ != null) {
        if (clientConfig_ == null) {
          clientConfig_ = new global::Grpc.Testing.ClientConfig();
        }
        ClientConfig.MergeFrom(other.ClientConfig);
      }
      if (other.NumClients != 0) {
        NumClients = other.NumClients;
      }
      if (other.serverConfig_ != null) {
        if (serverConfig_ == null) {
          serverConfig_ = new global::Grpc.Testing.ServerConfig();
        }
        ServerConfig.MergeFrom(other.ServerConfig);
      }
      if (other.NumServers != 0) {
        NumServers = other.NumServers;
      }
      if (other.WarmupSeconds != 0) {
        WarmupSeconds = other.WarmupSeconds;
      }
      if (other.BenchmarkSeconds != 0) {
        BenchmarkSeconds = other.BenchmarkSeconds;
      }
      if (other.SpawnLocalWorkerCount != 0) {
        SpawnLocalWorkerCount = other.SpawnLocalWorkerCount;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            Name = input.ReadString();
            break;
          }
          case 18: {
            if (clientConfig_ == null) {
              clientConfig_ = new global::Grpc.Testing.ClientConfig();
            }
            input.ReadMessage(clientConfig_);
            break;
          }
          case 24: {
            NumClients = input.ReadInt32();
            break;
          }
          case 34: {
            if (serverConfig_ == null) {
              serverConfig_ = new global::Grpc.Testing.ServerConfig();
            }
            input.ReadMessage(serverConfig_);
            break;
          }
          case 40: {
            NumServers = input.ReadInt32();
            break;
          }
          case 48: {
            WarmupSeconds = input.ReadInt32();
            break;
          }
          case 56: {
            BenchmarkSeconds = input.ReadInt32();
            break;
          }
          case 64: {
            SpawnLocalWorkerCount = input.ReadInt32();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// A set of scenarios to be run with qps_json_driver
  /// </summary>
  public sealed partial class Scenarios : pb::IMessage<Scenarios> {
    private static readonly pb::MessageParser<Scenarios> _parser = new pb::MessageParser<Scenarios>(() => new Scenarios());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<Scenarios> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[16]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public Scenarios(Scenarios other) : this() {
      scenarios_ = other.scenarios_.Clone();
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "scenarios" field.</summary>
    public const int Scenarios_FieldNumber = 1;
    private static readonly pb::FieldCodec<global::Grpc.Testing.Scenario> _repeated_scenarios_codec
        = pb::FieldCodec.ForMessage(10, global::Grpc.Testing.Scenario.Parser);
    private readonly pbc::RepeatedField<global::Grpc.Testing.Scenario> scenarios_ = new pbc::RepeatedField<global::Grpc.Testing.Scenario>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<global::Grpc.Testing.Scenario> Scenarios_ {
      get { return scenarios_; }
    }

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      hash ^= scenarios_.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.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) {
      scenarios_.WriteTo(output, _repeated_scenarios_codec);
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      size += scenarios_.CalculateSize(_repeated_scenarios_codec);
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(Scenarios other) {
      if (other == null) {
        return;
      }
      scenarios_.Add(other.scenarios_);
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            scenarios_.AddEntriesFrom(input, _repeated_scenarios_codec);
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Basic summary that can be computed from ClientStats and ServerStats
  /// once the scenario has finished.
  /// </summary>
  public sealed partial class ScenarioResultSummary : pb::IMessage<ScenarioResultSummary> {
    private static readonly pb::MessageParser<ScenarioResultSummary> _parser = new pb::MessageParser<ScenarioResultSummary>(() => new ScenarioResultSummary());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ScenarioResultSummary> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[17]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ScenarioResultSummary(ScenarioResultSummary other) : this() {
      qps_ = other.qps_;
      qpsPerServerCore_ = other.qpsPerServerCore_;
      serverSystemTime_ = other.serverSystemTime_;
      serverUserTime_ = other.serverUserTime_;
      clientSystemTime_ = other.clientSystemTime_;
      clientUserTime_ = other.clientUserTime_;
      latency50_ = other.latency50_;
      latency90_ = other.latency90_;
      latency95_ = other.latency95_;
      latency99_ = other.latency99_;
      latency999_ = other.latency999_;
      serverCpuUsage_ = other.serverCpuUsage_;
      successfulRequestsPerSecond_ = other.successfulRequestsPerSecond_;
      failedRequestsPerSecond_ = other.failedRequestsPerSecond_;
      clientPollsPerRequest_ = other.clientPollsPerRequest_;
      serverPollsPerRequest_ = other.serverPollsPerRequest_;
      serverQueriesPerCpuSec_ = other.serverQueriesPerCpuSec_;
      clientQueriesPerCpuSec_ = other.clientQueriesPerCpuSec_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "qps" field.</summary>
    public const int QpsFieldNumber = 1;
    private double qps_;
    /// <summary>
    /// Total number of operations per second over all clients.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double Qps {
      get { return qps_; }
      set {
        qps_ = value;
      }
    }

    /// <summary>Field number for the "qps_per_server_core" field.</summary>
    public const int QpsPerServerCoreFieldNumber = 2;
    private double qpsPerServerCore_;
    /// <summary>
    /// QPS per one server core.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double QpsPerServerCore {
      get { return qpsPerServerCore_; }
      set {
        qpsPerServerCore_ = value;
      }
    }

    /// <summary>Field number for the "server_system_time" field.</summary>
    public const int ServerSystemTimeFieldNumber = 3;
    private double serverSystemTime_;
    /// <summary>
    /// server load based on system_time (0.85 => 85%)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double ServerSystemTime {
      get { return serverSystemTime_; }
      set {
        serverSystemTime_ = value;
      }
    }

    /// <summary>Field number for the "server_user_time" field.</summary>
    public const int ServerUserTimeFieldNumber = 4;
    private double serverUserTime_;
    /// <summary>
    /// server load based on user_time (0.85 => 85%)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double ServerUserTime {
      get { return serverUserTime_; }
      set {
        serverUserTime_ = value;
      }
    }

    /// <summary>Field number for the "client_system_time" field.</summary>
    public const int ClientSystemTimeFieldNumber = 5;
    private double clientSystemTime_;
    /// <summary>
    /// client load based on system_time (0.85 => 85%)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double ClientSystemTime {
      get { return clientSystemTime_; }
      set {
        clientSystemTime_ = value;
      }
    }

    /// <summary>Field number for the "client_user_time" field.</summary>
    public const int ClientUserTimeFieldNumber = 6;
    private double clientUserTime_;
    /// <summary>
    /// client load based on user_time (0.85 => 85%)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double ClientUserTime {
      get { return clientUserTime_; }
      set {
        clientUserTime_ = value;
      }
    }

    /// <summary>Field number for the "latency_50" field.</summary>
    public const int Latency50FieldNumber = 7;
    private double latency50_;
    /// <summary>
    /// X% latency percentiles (in nanoseconds)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double Latency50 {
      get { return latency50_; }
      set {
        latency50_ = value;
      }
    }

    /// <summary>Field number for the "latency_90" field.</summary>
    public const int Latency90FieldNumber = 8;
    private double latency90_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double Latency90 {
      get { return latency90_; }
      set {
        latency90_ = value;
      }
    }

    /// <summary>Field number for the "latency_95" field.</summary>
    public const int Latency95FieldNumber = 9;
    private double latency95_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double Latency95 {
      get { return latency95_; }
      set {
        latency95_ = value;
      }
    }

    /// <summary>Field number for the "latency_99" field.</summary>
    public const int Latency99FieldNumber = 10;
    private double latency99_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double Latency99 {
      get { return latency99_; }
      set {
        latency99_ = value;
      }
    }

    /// <summary>Field number for the "latency_999" field.</summary>
    public const int Latency999FieldNumber = 11;
    private double latency999_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double Latency999 {
      get { return latency999_; }
      set {
        latency999_ = value;
      }
    }

    /// <summary>Field number for the "server_cpu_usage" field.</summary>
    public const int ServerCpuUsageFieldNumber = 12;
    private double serverCpuUsage_;
    /// <summary>
    /// server cpu usage percentage
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double ServerCpuUsage {
      get { return serverCpuUsage_; }
      set {
        serverCpuUsage_ = value;
      }
    }

    /// <summary>Field number for the "successful_requests_per_second" field.</summary>
    public const int SuccessfulRequestsPerSecondFieldNumber = 13;
    private double successfulRequestsPerSecond_;
    /// <summary>
    /// Number of requests that succeeded/failed
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double SuccessfulRequestsPerSecond {
      get { return successfulRequestsPerSecond_; }
      set {
        successfulRequestsPerSecond_ = value;
      }
    }

    /// <summary>Field number for the "failed_requests_per_second" field.</summary>
    public const int FailedRequestsPerSecondFieldNumber = 14;
    private double failedRequestsPerSecond_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double FailedRequestsPerSecond {
      get { return failedRequestsPerSecond_; }
      set {
        failedRequestsPerSecond_ = value;
      }
    }

    /// <summary>Field number for the "client_polls_per_request" field.</summary>
    public const int ClientPollsPerRequestFieldNumber = 15;
    private double clientPollsPerRequest_;
    /// <summary>
    /// Number of polls called inside completion queue per request
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double ClientPollsPerRequest {
      get { return clientPollsPerRequest_; }
      set {
        clientPollsPerRequest_ = value;
      }
    }

    /// <summary>Field number for the "server_polls_per_request" field.</summary>
    public const int ServerPollsPerRequestFieldNumber = 16;
    private double serverPollsPerRequest_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double ServerPollsPerRequest {
      get { return serverPollsPerRequest_; }
      set {
        serverPollsPerRequest_ = value;
      }
    }

    /// <summary>Field number for the "server_queries_per_cpu_sec" field.</summary>
    public const int ServerQueriesPerCpuSecFieldNumber = 17;
    private double serverQueriesPerCpuSec_;
    /// <summary>
    /// Queries per CPU-sec over all servers or clients
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double ServerQueriesPerCpuSec {
      get { return serverQueriesPerCpuSec_; }
      set {
        serverQueriesPerCpuSec_ = value;
      }
    }

    /// <summary>Field number for the "client_queries_per_cpu_sec" field.</summary>
    public const int ClientQueriesPerCpuSecFieldNumber = 18;
    private double clientQueriesPerCpuSec_;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public double ClientQueriesPerCpuSec {
      get { return clientQueriesPerCpuSec_; }
      set {
        clientQueriesPerCpuSec_ = value;
      }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ScenarioResultSummary other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Qps, other.Qps)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(QpsPerServerCore, other.QpsPerServerCore)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerSystemTime, other.ServerSystemTime)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerUserTime, other.ServerUserTime)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ClientSystemTime, other.ClientSystemTime)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ClientUserTime, other.ClientUserTime)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency50, other.Latency50)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency90, other.Latency90)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency95, other.Latency95)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency99, other.Latency99)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency999, other.Latency999)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerCpuUsage, other.ServerCpuUsage)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(SuccessfulRequestsPerSecond, other.SuccessfulRequestsPerSecond)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(FailedRequestsPerSecond, other.FailedRequestsPerSecond)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ClientPollsPerRequest, other.ClientPollsPerRequest)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerPollsPerRequest, other.ServerPollsPerRequest)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerQueriesPerCpuSec, other.ServerQueriesPerCpuSec)) return false;
      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ClientQueriesPerCpuSec, other.ClientQueriesPerCpuSec)) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Qps != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Qps);
      if (QpsPerServerCore != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(QpsPerServerCore);
      if (ServerSystemTime != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerSystemTime);
      if (ServerUserTime != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerUserTime);
      if (ClientSystemTime != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ClientSystemTime);
      if (ClientUserTime != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ClientUserTime);
      if (Latency50 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency50);
      if (Latency90 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency90);
      if (Latency95 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency95);
      if (Latency99 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency99);
      if (Latency999 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency999);
      if (ServerCpuUsage != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerCpuUsage);
      if (SuccessfulRequestsPerSecond != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(SuccessfulRequestsPerSecond);
      if (FailedRequestsPerSecond != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(FailedRequestsPerSecond);
      if (ClientPollsPerRequest != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ClientPollsPerRequest);
      if (ServerPollsPerRequest != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerPollsPerRequest);
      if (ServerQueriesPerCpuSec != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerQueriesPerCpuSec);
      if (ClientQueriesPerCpuSec != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ClientQueriesPerCpuSec);
      if (_unknownFields != null) {
        hash ^= _unknownFields.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 (Qps != 0D) {
        output.WriteRawTag(9);
        output.WriteDouble(Qps);
      }
      if (QpsPerServerCore != 0D) {
        output.WriteRawTag(17);
        output.WriteDouble(QpsPerServerCore);
      }
      if (ServerSystemTime != 0D) {
        output.WriteRawTag(25);
        output.WriteDouble(ServerSystemTime);
      }
      if (ServerUserTime != 0D) {
        output.WriteRawTag(33);
        output.WriteDouble(ServerUserTime);
      }
      if (ClientSystemTime != 0D) {
        output.WriteRawTag(41);
        output.WriteDouble(ClientSystemTime);
      }
      if (ClientUserTime != 0D) {
        output.WriteRawTag(49);
        output.WriteDouble(ClientUserTime);
      }
      if (Latency50 != 0D) {
        output.WriteRawTag(57);
        output.WriteDouble(Latency50);
      }
      if (Latency90 != 0D) {
        output.WriteRawTag(65);
        output.WriteDouble(Latency90);
      }
      if (Latency95 != 0D) {
        output.WriteRawTag(73);
        output.WriteDouble(Latency95);
      }
      if (Latency99 != 0D) {
        output.WriteRawTag(81);
        output.WriteDouble(Latency99);
      }
      if (Latency999 != 0D) {
        output.WriteRawTag(89);
        output.WriteDouble(Latency999);
      }
      if (ServerCpuUsage != 0D) {
        output.WriteRawTag(97);
        output.WriteDouble(ServerCpuUsage);
      }
      if (SuccessfulRequestsPerSecond != 0D) {
        output.WriteRawTag(105);
        output.WriteDouble(SuccessfulRequestsPerSecond);
      }
      if (FailedRequestsPerSecond != 0D) {
        output.WriteRawTag(113);
        output.WriteDouble(FailedRequestsPerSecond);
      }
      if (ClientPollsPerRequest != 0D) {
        output.WriteRawTag(121);
        output.WriteDouble(ClientPollsPerRequest);
      }
      if (ServerPollsPerRequest != 0D) {
        output.WriteRawTag(129, 1);
        output.WriteDouble(ServerPollsPerRequest);
      }
      if (ServerQueriesPerCpuSec != 0D) {
        output.WriteRawTag(137, 1);
        output.WriteDouble(ServerQueriesPerCpuSec);
      }
      if (ClientQueriesPerCpuSec != 0D) {
        output.WriteRawTag(145, 1);
        output.WriteDouble(ClientQueriesPerCpuSec);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (Qps != 0D) {
        size += 1 + 8;
      }
      if (QpsPerServerCore != 0D) {
        size += 1 + 8;
      }
      if (ServerSystemTime != 0D) {
        size += 1 + 8;
      }
      if (ServerUserTime != 0D) {
        size += 1 + 8;
      }
      if (ClientSystemTime != 0D) {
        size += 1 + 8;
      }
      if (ClientUserTime != 0D) {
        size += 1 + 8;
      }
      if (Latency50 != 0D) {
        size += 1 + 8;
      }
      if (Latency90 != 0D) {
        size += 1 + 8;
      }
      if (Latency95 != 0D) {
        size += 1 + 8;
      }
      if (Latency99 != 0D) {
        size += 1 + 8;
      }
      if (Latency999 != 0D) {
        size += 1 + 8;
      }
      if (ServerCpuUsage != 0D) {
        size += 1 + 8;
      }
      if (SuccessfulRequestsPerSecond != 0D) {
        size += 1 + 8;
      }
      if (FailedRequestsPerSecond != 0D) {
        size += 1 + 8;
      }
      if (ClientPollsPerRequest != 0D) {
        size += 1 + 8;
      }
      if (ServerPollsPerRequest != 0D) {
        size += 2 + 8;
      }
      if (ServerQueriesPerCpuSec != 0D) {
        size += 2 + 8;
      }
      if (ClientQueriesPerCpuSec != 0D) {
        size += 2 + 8;
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ScenarioResultSummary other) {
      if (other == null) {
        return;
      }
      if (other.Qps != 0D) {
        Qps = other.Qps;
      }
      if (other.QpsPerServerCore != 0D) {
        QpsPerServerCore = other.QpsPerServerCore;
      }
      if (other.ServerSystemTime != 0D) {
        ServerSystemTime = other.ServerSystemTime;
      }
      if (other.ServerUserTime != 0D) {
        ServerUserTime = other.ServerUserTime;
      }
      if (other.ClientSystemTime != 0D) {
        ClientSystemTime = other.ClientSystemTime;
      }
      if (other.ClientUserTime != 0D) {
        ClientUserTime = other.ClientUserTime;
      }
      if (other.Latency50 != 0D) {
        Latency50 = other.Latency50;
      }
      if (other.Latency90 != 0D) {
        Latency90 = other.Latency90;
      }
      if (other.Latency95 != 0D) {
        Latency95 = other.Latency95;
      }
      if (other.Latency99 != 0D) {
        Latency99 = other.Latency99;
      }
      if (other.Latency999 != 0D) {
        Latency999 = other.Latency999;
      }
      if (other.ServerCpuUsage != 0D) {
        ServerCpuUsage = other.ServerCpuUsage;
      }
      if (other.SuccessfulRequestsPerSecond != 0D) {
        SuccessfulRequestsPerSecond = other.SuccessfulRequestsPerSecond;
      }
      if (other.FailedRequestsPerSecond != 0D) {
        FailedRequestsPerSecond = other.FailedRequestsPerSecond;
      }
      if (other.ClientPollsPerRequest != 0D) {
        ClientPollsPerRequest = other.ClientPollsPerRequest;
      }
      if (other.ServerPollsPerRequest != 0D) {
        ServerPollsPerRequest = other.ServerPollsPerRequest;
      }
      if (other.ServerQueriesPerCpuSec != 0D) {
        ServerQueriesPerCpuSec = other.ServerQueriesPerCpuSec;
      }
      if (other.ClientQueriesPerCpuSec != 0D) {
        ClientQueriesPerCpuSec = other.ClientQueriesPerCpuSec;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 9: {
            Qps = input.ReadDouble();
            break;
          }
          case 17: {
            QpsPerServerCore = input.ReadDouble();
            break;
          }
          case 25: {
            ServerSystemTime = input.ReadDouble();
            break;
          }
          case 33: {
            ServerUserTime = input.ReadDouble();
            break;
          }
          case 41: {
            ClientSystemTime = input.ReadDouble();
            break;
          }
          case 49: {
            ClientUserTime = input.ReadDouble();
            break;
          }
          case 57: {
            Latency50 = input.ReadDouble();
            break;
          }
          case 65: {
            Latency90 = input.ReadDouble();
            break;
          }
          case 73: {
            Latency95 = input.ReadDouble();
            break;
          }
          case 81: {
            Latency99 = input.ReadDouble();
            break;
          }
          case 89: {
            Latency999 = input.ReadDouble();
            break;
          }
          case 97: {
            ServerCpuUsage = input.ReadDouble();
            break;
          }
          case 105: {
            SuccessfulRequestsPerSecond = input.ReadDouble();
            break;
          }
          case 113: {
            FailedRequestsPerSecond = input.ReadDouble();
            break;
          }
          case 121: {
            ClientPollsPerRequest = input.ReadDouble();
            break;
          }
          case 129: {
            ServerPollsPerRequest = input.ReadDouble();
            break;
          }
          case 137: {
            ServerQueriesPerCpuSec = input.ReadDouble();
            break;
          }
          case 145: {
            ClientQueriesPerCpuSec = input.ReadDouble();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Results of a single benchmark scenario.
  /// </summary>
  public sealed partial class ScenarioResult : pb::IMessage<ScenarioResult> {
    private static readonly pb::MessageParser<ScenarioResult> _parser = new pb::MessageParser<ScenarioResult>(() => new ScenarioResult());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ScenarioResult> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[18]; }
    }

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

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

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ScenarioResult(ScenarioResult other) : this() {
      scenario_ = other.scenario_ != null ? other.scenario_.Clone() : null;
      latencies_ = other.latencies_ != null ? other.latencies_.Clone() : null;
      clientStats_ = other.clientStats_.Clone();
      serverStats_ = other.serverStats_.Clone();
      serverCores_ = other.serverCores_.Clone();
      summary_ = other.summary_ != null ? other.summary_.Clone() : null;
      clientSuccess_ = other.clientSuccess_.Clone();
      serverSuccess_ = other.serverSuccess_.Clone();
      requestResults_ = other.requestResults_.Clone();
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

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

    /// <summary>Field number for the "scenario" field.</summary>
    public const int ScenarioFieldNumber = 1;
    private global::Grpc.Testing.Scenario scenario_;
    /// <summary>
    /// Inputs used to run the scenario.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.Scenario Scenario {
      get { return scenario_; }
      set {
        scenario_ = value;
      }
    }

    /// <summary>Field number for the "latencies" field.</summary>
    public const int LatenciesFieldNumber = 2;
    private global::Grpc.Testing.HistogramData latencies_;
    /// <summary>
    /// Histograms from all clients merged into one histogram.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.HistogramData Latencies {
      get { return latencies_; }
      set {
        latencies_ = value;
      }
    }

    /// <summary>Field number for the "client_stats" field.</summary>
    public const int ClientStatsFieldNumber = 3;
    private static readonly pb::FieldCodec<global::Grpc.Testing.ClientStats> _repeated_clientStats_codec
        = pb::FieldCodec.ForMessage(26, global::Grpc.Testing.ClientStats.Parser);
    private readonly pbc::RepeatedField<global::Grpc.Testing.ClientStats> clientStats_ = new pbc::RepeatedField<global::Grpc.Testing.ClientStats>();
    /// <summary>
    /// Client stats for each client
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<global::Grpc.Testing.ClientStats> ClientStats {
      get { return clientStats_; }
    }

    /// <summary>Field number for the "server_stats" field.</summary>
    public const int ServerStatsFieldNumber = 4;
    private static readonly pb::FieldCodec<global::Grpc.Testing.ServerStats> _repeated_serverStats_codec
        = pb::FieldCodec.ForMessage(34, global::Grpc.Testing.ServerStats.Parser);
    private readonly pbc::RepeatedField<global::Grpc.Testing.ServerStats> serverStats_ = new pbc::RepeatedField<global::Grpc.Testing.ServerStats>();
    /// <summary>
    /// Server stats for each server
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<global::Grpc.Testing.ServerStats> ServerStats {
      get { return serverStats_; }
    }

    /// <summary>Field number for the "server_cores" field.</summary>
    public const int ServerCoresFieldNumber = 5;
    private static readonly pb::FieldCodec<int> _repeated_serverCores_codec
        = pb::FieldCodec.ForInt32(42);
    private readonly pbc::RepeatedField<int> serverCores_ = new pbc::RepeatedField<int>();
    /// <summary>
    /// Number of cores available to each server
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<int> ServerCores {
      get { return serverCores_; }
    }

    /// <summary>Field number for the "summary" field.</summary>
    public const int SummaryFieldNumber = 6;
    private global::Grpc.Testing.ScenarioResultSummary summary_;
    /// <summary>
    /// An after-the-fact computed summary
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Grpc.Testing.ScenarioResultSummary Summary {
      get { return summary_; }
      set {
        summary_ = value;
      }
    }

    /// <summary>Field number for the "client_success" field.</summary>
    public const int ClientSuccessFieldNumber = 7;
    private static readonly pb::FieldCodec<bool> _repeated_clientSuccess_codec
        = pb::FieldCodec.ForBool(58);
    private readonly pbc::RepeatedField<bool> clientSuccess_ = new pbc::RepeatedField<bool>();
    /// <summary>
    /// Information on success or failure of each worker
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<bool> ClientSuccess {
      get { return clientSuccess_; }
    }

    /// <summary>Field number for the "server_success" field.</summary>
    public const int ServerSuccessFieldNumber = 8;
    private static readonly pb::FieldCodec<bool> _repeated_serverSuccess_codec
        = pb::FieldCodec.ForBool(66);
    private readonly pbc::RepeatedField<bool> serverSuccess_ = new pbc::RepeatedField<bool>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<bool> ServerSuccess {
      get { return serverSuccess_; }
    }

    /// <summary>Field number for the "request_results" field.</summary>
    public const int RequestResultsFieldNumber = 9;
    private static readonly pb::FieldCodec<global::Grpc.Testing.RequestResultCount> _repeated_requestResults_codec
        = pb::FieldCodec.ForMessage(74, global::Grpc.Testing.RequestResultCount.Parser);
    private readonly pbc::RepeatedField<global::Grpc.Testing.RequestResultCount> requestResults_ = new pbc::RepeatedField<global::Grpc.Testing.RequestResultCount>();
    /// <summary>
    /// Number of failed requests (one row per status code seen)
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<global::Grpc.Testing.RequestResultCount> RequestResults {
      get { return requestResults_; }
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ScenarioResult other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (!object.Equals(Scenario, other.Scenario)) return false;
      if (!object.Equals(Latencies, other.Latencies)) return false;
      if(!clientStats_.Equals(other.clientStats_)) return false;
      if(!serverStats_.Equals(other.serverStats_)) return false;
      if(!serverCores_.Equals(other.serverCores_)) return false;
      if (!object.Equals(Summary, other.Summary)) return false;
      if(!clientSuccess_.Equals(other.clientSuccess_)) return false;
      if(!serverSuccess_.Equals(other.serverSuccess_)) return false;
      if(!requestResults_.Equals(other.requestResults_)) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (scenario_ != null) hash ^= Scenario.GetHashCode();
      if (latencies_ != null) hash ^= Latencies.GetHashCode();
      hash ^= clientStats_.GetHashCode();
      hash ^= serverStats_.GetHashCode();
      hash ^= serverCores_.GetHashCode();
      if (summary_ != null) hash ^= Summary.GetHashCode();
      hash ^= clientSuccess_.GetHashCode();
      hash ^= serverSuccess_.GetHashCode();
      hash ^= requestResults_.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.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 (scenario_ != null) {
        output.WriteRawTag(10);
        output.WriteMessage(Scenario);
      }
      if (latencies_ != null) {
        output.WriteRawTag(18);
        output.WriteMessage(Latencies);
      }
      clientStats_.WriteTo(output, _repeated_clientStats_codec);
      serverStats_.WriteTo(output, _repeated_serverStats_codec);
      serverCores_.WriteTo(output, _repeated_serverCores_codec);
      if (summary_ != null) {
        output.WriteRawTag(50);
        output.WriteMessage(Summary);
      }
      clientSuccess_.WriteTo(output, _repeated_clientSuccess_codec);
      serverSuccess_.WriteTo(output, _repeated_serverSuccess_codec);
      requestResults_.WriteTo(output, _repeated_requestResults_codec);
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (scenario_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Scenario);
      }
      if (latencies_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Latencies);
      }
      size += clientStats_.CalculateSize(_repeated_clientStats_codec);
      size += serverStats_.CalculateSize(_repeated_serverStats_codec);
      size += serverCores_.CalculateSize(_repeated_serverCores_codec);
      if (summary_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Summary);
      }
      size += clientSuccess_.CalculateSize(_repeated_clientSuccess_codec);
      size += serverSuccess_.CalculateSize(_repeated_serverSuccess_codec);
      size += requestResults_.CalculateSize(_repeated_requestResults_codec);
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ScenarioResult other) {
      if (other == null) {
        return;
      }
      if (other.scenario_ != null) {
        if (scenario_ == null) {
          scenario_ = new global::Grpc.Testing.Scenario();
        }
        Scenario.MergeFrom(other.Scenario);
      }
      if (other.latencies_ != null) {
        if (latencies_ == null) {
          latencies_ = new global::Grpc.Testing.HistogramData();
        }
        Latencies.MergeFrom(other.Latencies);
      }
      clientStats_.Add(other.clientStats_);
      serverStats_.Add(other.serverStats_);
      serverCores_.Add(other.serverCores_);
      if (other.summary_ != null) {
        if (summary_ == null) {
          summary_ = new global::Grpc.Testing.ScenarioResultSummary();
        }
        Summary.MergeFrom(other.Summary);
      }
      clientSuccess_.Add(other.clientSuccess_);
      serverSuccess_.Add(other.serverSuccess_);
      requestResults_.Add(other.requestResults_);
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            if (scenario_ == null) {
              scenario_ = new global::Grpc.Testing.Scenario();
            }
            input.ReadMessage(scenario_);
            break;
          }
          case 18: {
            if (latencies_ == null) {
              latencies_ = new global::Grpc.Testing.HistogramData();
            }
            input.ReadMessage(latencies_);
            break;
          }
          case 26: {
            clientStats_.AddEntriesFrom(input, _repeated_clientStats_codec);
            break;
          }
          case 34: {
            serverStats_.AddEntriesFrom(input, _repeated_serverStats_codec);
            break;
          }
          case 42:
          case 40: {
            serverCores_.AddEntriesFrom(input, _repeated_serverCores_codec);
            break;
          }
          case 50: {
            if (summary_ == null) {
              summary_ = new global::Grpc.Testing.ScenarioResultSummary();
            }
            input.ReadMessage(summary_);
            break;
          }
          case 58:
          case 56: {
            clientSuccess_.AddEntriesFrom(input, _repeated_clientSuccess_codec);
            break;
          }
          case 66:
          case 64: {
            serverSuccess_.AddEntriesFrom(input, _repeated_serverSuccess_codec);
            break;
          }
          case 74: {
            requestResults_.AddEntriesFrom(input, _repeated_requestResults_codec);
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
