// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: src/proto/grpc/testing/control.proto
#pragma warning disable 1591, 0612, 3021
#region Designer generated code

using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace 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",
            "c19wZXJfY3EYESABKAUSGwoTbWVzc2FnZXNfcGVyX3N0cmVhbRgSIAEoBSI4",
            "CgxDbGllbnRTdGF0dXMSKAoFc3RhdHMYASABKAsyGS5ncnBjLnRlc3Rpbmcu",
            "Q2xpZW50U3RhdHMiFQoETWFyaxINCgVyZXNldBgBIAEoCCJoCgpDbGllbnRB",
            "cmdzEisKBXNldHVwGAEgASgLMhouZ3JwYy50ZXN0aW5nLkNsaWVudENvbmZp",
            "Z0gAEiIKBG1hcmsYAiABKAsyEi5ncnBjLnRlc3RpbmcuTWFya0gAQgkKB2Fy",
            "Z3R5cGUi/QIKDFNlcnZlckNvbmZpZxItCgtzZXJ2ZXJfdHlwZRgBIAEoDjIY",
            "LmdycGMudGVzdGluZy5TZXJ2ZXJUeXBlEjUKD3NlY3VyaXR5X3BhcmFtcxgC",
            "IAEoCzIcLmdycGMudGVzdGluZy5TZWN1cml0eVBhcmFtcxIMCgRwb3J0GAQg",
            "ASgFEhwKFGFzeW5jX3NlcnZlcl90aHJlYWRzGAcgASgFEhIKCmNvcmVfbGlt",
            "aXQYCCABKAUSMwoOcGF5bG9hZF9jb25maWcYCSABKAsyGy5ncnBjLnRlc3Rp",
            "bmcuUGF5bG9hZENvbmZpZxIRCgljb3JlX2xpc3QYCiADKAUSGAoQb3RoZXJf",
            "c2VydmVyX2FwaRgLIAEoCRIWCg50aHJlYWRzX3Blcl9jcRgMIAEoBRIcChNy",
            "ZXNvdXJjZV9xdW90YV9zaXplGOkHIAEoBRIvCgxjaGFubmVsX2FyZ3MY6gcg",
            "AygLMhguZ3JwYy50ZXN0aW5nLkNoYW5uZWxBcmciaAoKU2VydmVyQXJncxIr",
            "CgVzZXR1cBgBIAEoCzIaLmdycGMudGVzdGluZy5TZXJ2ZXJDb25maWdIABIi",
            "CgRtYXJrGAIgASgLMhIuZ3JwYy50ZXN0aW5nLk1hcmtIAEIJCgdhcmd0eXBl",
            "IlUKDFNlcnZlclN0YXR1cxIoCgVzdGF0cxgBIAEoCzIZLmdycGMudGVzdGlu",
            "Zy5TZXJ2ZXJTdGF0cxIMCgRwb3J0GAIgASgFEg0KBWNvcmVzGAMgASgFIg0K",
            "C0NvcmVSZXF1ZXN0Ih0KDENvcmVSZXNwb25zZRINCgVjb3JlcxgBIAEoBSIG",
            "CgRWb2lkIv0BCghTY2VuYXJpbxIMCgRuYW1lGAEgASgJEjEKDWNsaWVudF9j",
            "b25maWcYAiABKAsyGi5ncnBjLnRlc3RpbmcuQ2xpZW50Q29uZmlnEhMKC251",
            "bV9jbGllbnRzGAMgASgFEjEKDXNlcnZlcl9jb25maWcYBCABKAsyGi5ncnBj",
            "LnRlc3RpbmcuU2VydmVyQ29uZmlnEhMKC251bV9zZXJ2ZXJzGAUgASgFEhYK",
            "Dndhcm11cF9zZWNvbmRzGAYgASgFEhkKEWJlbmNobWFya19zZWNvbmRzGAcg",
            "ASgFEiAKGHNwYXduX2xvY2FsX3dvcmtlcl9jb3VudBgIIAEoBSI2CglTY2Vu",
            "YXJpb3MSKQoJc2NlbmFyaW9zGAEgAygLMhYuZ3JwYy50ZXN0aW5nLlNjZW5h",
            "cmlvIoQEChVTY2VuYXJpb1Jlc3VsdFN1bW1hcnkSCwoDcXBzGAEgASgBEhsK",
            "E3Fwc19wZXJfc2VydmVyX2NvcmUYAiABKAESGgoSc2VydmVyX3N5c3RlbV90",
            "aW1lGAMgASgBEhgKEHNlcnZlcl91c2VyX3RpbWUYBCABKAESGgoSY2xpZW50",
            "X3N5c3RlbV90aW1lGAUgASgBEhgKEGNsaWVudF91c2VyX3RpbWUYBiABKAES",
            "EgoKbGF0ZW5jeV81MBgHIAEoARISCgpsYXRlbmN5XzkwGAggASgBEhIKCmxh",
            "dGVuY3lfOTUYCSABKAESEgoKbGF0ZW5jeV85ORgKIAEoARITCgtsYXRlbmN5",
            "Xzk5ORgLIAEoARIYChBzZXJ2ZXJfY3B1X3VzYWdlGAwgASgBEiYKHnN1Y2Nl",
            "c3NmdWxfcmVxdWVzdHNfcGVyX3NlY29uZBgNIAEoARIiChpmYWlsZWRfcmVx",
            "dWVzdHNfcGVyX3NlY29uZBgOIAEoARIgChhjbGllbnRfcG9sbHNfcGVyX3Jl",
            "cXVlc3QYDyABKAESIAoYc2VydmVyX3BvbGxzX3Blcl9yZXF1ZXN0GBAgASgB",
            "EiIKGnNlcnZlcl9xdWVyaWVzX3Blcl9jcHVfc2VjGBEgASgBEiIKGmNsaWVu",
            "dF9xdWVyaWVzX3Blcl9jcHVfc2VjGBIgASgBIoMDCg5TY2VuYXJpb1Jlc3Vs",
            "dBIoCghzY2VuYXJpbxgBIAEoCzIWLmdycGMudGVzdGluZy5TY2VuYXJpbxIu",
            "CglsYXRlbmNpZXMYAiABKAsyGy5ncnBjLnRlc3RpbmcuSGlzdG9ncmFtRGF0",
            "YRIvCgxjbGllbnRfc3RhdHMYAyADKAsyGS5ncnBjLnRlc3RpbmcuQ2xpZW50",
            "U3RhdHMSLwoMc2VydmVyX3N0YXRzGAQgAygLMhkuZ3JwYy50ZXN0aW5nLlNl",
            "cnZlclN0YXRzEhQKDHNlcnZlcl9jb3JlcxgFIAMoBRI0CgdzdW1tYXJ5GAYg",
            "ASgLMiMuZ3JwYy50ZXN0aW5nLlNjZW5hcmlvUmVzdWx0U3VtbWFyeRIWCg5j",
            "bGllbnRfc3VjY2VzcxgHIAMoCBIWCg5zZXJ2ZXJfc3VjY2VzcxgIIAMoCBI5",
            "Cg9yZXF1ZXN0X3Jlc3VsdHMYCSADKAsyIC5ncnBjLnRlc3RpbmcuUmVxdWVz",
            "dFJlc3VsdENvdW50KkEKCkNsaWVudFR5cGUSDwoLU1lOQ19DTElFTlQQABIQ",
            "CgxBU1lOQ19DTElFTlQQARIQCgxPVEhFUl9DTElFTlQQAipbCgpTZXJ2ZXJU",
            "eXBlEg8KC1NZTkNfU0VSVkVSEAASEAoMQVNZTkNfU0VSVkVSEAESGAoUQVNZ",
            "TkNfR0VORVJJQ19TRVJWRVIQAhIQCgxPVEhFUl9TRVJWRVIQAypyCgdScGNU",
            "eXBlEgkKBVVOQVJZEAASDQoJU1RSRUFNSU5HEAESGQoVU1RSRUFNSU5HX0ZS",
            "T01fQ0xJRU5UEAISGQoVU1RSRUFNSU5HX0ZST01fU0VSVkVSEAMSFwoTU1RS",
            "RUFNSU5HX0JPVEhfV0FZUxAEYgZwcm90bzM="));
      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" }, 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());
    [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_;
    }

    [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 (OfferedLoad != other.OfferedLoad) return false;
      return true;
    }

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            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());
    [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() {
    }

    [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 true;
    }

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

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

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

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

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

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

  }

  public sealed partial class LoadParams : pb::IMessage<LoadParams> {
    private static readonly pb::MessageParser<LoadParams> _parser = new pb::MessageParser<LoadParams>(() => new LoadParams());
    [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;
      }

    }

    [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 true;
    }

    [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_;
      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);
      }
    }

    [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);
      }
      return size;
    }

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

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            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());
    [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_;
    }

    [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 true;
    }

    [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();
      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);
      }
    }

    [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);
      }
      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;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 8: {
            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());
    [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;
      }

    }

    [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 true;
    }

    [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_;
      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);
      }
    }

    [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);
      }
      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;
      }

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            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());
    [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_;
    }

    [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;
      }
    }

    [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;
      return true;
    }

    [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();
      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);
      }
    }

    [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);
      }
      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;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            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;
          }
        }
      }
    }

  }

  public sealed partial class ClientStatus : pb::IMessage<ClientStatus> {
    private static readonly pb::MessageParser<ClientStatus> _parser = new pb::MessageParser<ClientStatus>(() => new ClientStatus());
    [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;
    }

    [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 true;
    }

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (stats_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stats);
      }
      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);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            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());
    [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_;
    }

    [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 true;
    }

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 8: {
            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());
    [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;
      }

    }

    [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 true;
    }

    [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_;
      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);
      }
    }

    [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);
      }
      return size;
    }

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

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            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());
    [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();
    }

    [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 true;
    }

    [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();
      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);
    }

    [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);
      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_);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 8: {
            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());
    [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;
      }

    }

    [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 true;
    }

    [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_;
      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);
      }
    }

    [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);
      }
      return size;
    }

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

    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            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());
    [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_;
    }

    [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 true;
    }

    [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();
      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);
      }
    }

    [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);
      }
      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;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            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());
    [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() {
    }

    [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 true;
    }

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

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

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

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

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

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

  }

  public sealed partial class CoreResponse : pb::IMessage<CoreResponse> {
    private static readonly pb::MessageParser<CoreResponse> _parser = new pb::MessageParser<CoreResponse>(() => new CoreResponse());
    [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_;
    }

    [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 true;
    }

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 8: {
            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());
    [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() {
    }

    [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 true;
    }

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

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

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

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

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

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

  }

  /// <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());
    [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_;
    }

    [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 true;
    }

    [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();
      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);
      }
    }

    [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);
      }
      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;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            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());
    [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();
    }

    [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 true;
    }

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            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());
    [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_;
    }

    [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 (Qps != other.Qps) return false;
      if (QpsPerServerCore != other.QpsPerServerCore) return false;
      if (ServerSystemTime != other.ServerSystemTime) return false;
      if (ServerUserTime != other.ServerUserTime) return false;
      if (ClientSystemTime != other.ClientSystemTime) return false;
      if (ClientUserTime != other.ClientUserTime) return false;
      if (Latency50 != other.Latency50) return false;
      if (Latency90 != other.Latency90) return false;
      if (Latency95 != other.Latency95) return false;
      if (Latency99 != other.Latency99) return false;
      if (Latency999 != other.Latency999) return false;
      if (ServerCpuUsage != other.ServerCpuUsage) return false;
      if (SuccessfulRequestsPerSecond != other.SuccessfulRequestsPerSecond) return false;
      if (FailedRequestsPerSecond != other.FailedRequestsPerSecond) return false;
      if (ClientPollsPerRequest != other.ClientPollsPerRequest) return false;
      if (ServerPollsPerRequest != other.ServerPollsPerRequest) return false;
      if (ServerQueriesPerCpuSec != other.ServerQueriesPerCpuSec) return false;
      if (ClientQueriesPerCpuSec != other.ClientQueriesPerCpuSec) return false;
      return true;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (Qps != 0D) hash ^= Qps.GetHashCode();
      if (QpsPerServerCore != 0D) hash ^= QpsPerServerCore.GetHashCode();
      if (ServerSystemTime != 0D) hash ^= ServerSystemTime.GetHashCode();
      if (ServerUserTime != 0D) hash ^= ServerUserTime.GetHashCode();
      if (ClientSystemTime != 0D) hash ^= ClientSystemTime.GetHashCode();
      if (ClientUserTime != 0D) hash ^= ClientUserTime.GetHashCode();
      if (Latency50 != 0D) hash ^= Latency50.GetHashCode();
      if (Latency90 != 0D) hash ^= Latency90.GetHashCode();
      if (Latency95 != 0D) hash ^= Latency95.GetHashCode();
      if (Latency99 != 0D) hash ^= Latency99.GetHashCode();
      if (Latency999 != 0D) hash ^= Latency999.GetHashCode();
      if (ServerCpuUsage != 0D) hash ^= ServerCpuUsage.GetHashCode();
      if (SuccessfulRequestsPerSecond != 0D) hash ^= SuccessfulRequestsPerSecond.GetHashCode();
      if (FailedRequestsPerSecond != 0D) hash ^= FailedRequestsPerSecond.GetHashCode();
      if (ClientPollsPerRequest != 0D) hash ^= ClientPollsPerRequest.GetHashCode();
      if (ServerPollsPerRequest != 0D) hash ^= ServerPollsPerRequest.GetHashCode();
      if (ServerQueriesPerCpuSec != 0D) hash ^= ServerQueriesPerCpuSec.GetHashCode();
      if (ClientQueriesPerCpuSec != 0D) hash ^= ClientQueriesPerCpuSec.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);
      }
    }

    [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;
      }
      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;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            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());
    [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();
    }

    [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 true;
    }

    [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();
      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);
    }

    [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);
      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_);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            input.SkipLastField();
            break;
          case 10: {
            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
