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

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

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

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

  #endregion

  #region Messages
  /// <summary>
  /// Parameters of poisson process distribution, which is a good representation
  /// of activity coming in from independent identical stationary sources.
  /// </summary>
  public sealed partial class PoissonParams : pb::IMessage<PoissonParams> {
    private static readonly pb::MessageParser<PoissonParams> _parser = new pb::MessageParser<PoissonParams>(() => new PoissonParams());
    [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:
          if (ClosedLoop == null) {
            ClosedLoop = new global::Grpc.Testing.ClosedLoopParams();
          }
          ClosedLoop.MergeFrom(other.ClosedLoop);
          break;
        case LoadOneofCase.Poisson:
          if (Poisson == null) {
            Poisson = new global::Grpc.Testing.PoissonParams();
          }
          Poisson.MergeFrom(other.Poisson);
          break;
      }

    }

    [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_;
      useCoalesceApi_ = other.useCoalesceApi_;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ClientConfig other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if(!serverTargets_.Equals(other.serverTargets_)) return false;
      if (ClientType != other.ClientType) return false;
      if (!object.Equals(SecurityParams, other.SecurityParams)) return false;
      if (OutstandingRpcsPerChannel != other.OutstandingRpcsPerChannel) return false;
      if (ClientChannels != other.ClientChannels) return false;
      if (AsyncClientThreads != other.AsyncClientThreads) return false;
      if (RpcType != other.RpcType) return false;
      if (!object.Equals(LoadParams, other.LoadParams)) return false;
      if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false;
      if (!object.Equals(HistogramParams, other.HistogramParams)) return false;
      if(!coreList_.Equals(other.coreList_)) return false;
      if (CoreLimit != other.CoreLimit) return false;
      if (OtherClientApi != other.OtherClientApi) return false;
      if(!channelArgs_.Equals(other.channelArgs_)) return false;
      if (ThreadsPerCq != other.ThreadsPerCq) return false;
      if (MessagesPerStream != other.MessagesPerStream) return false;
      if (UseCoalesceApi != other.UseCoalesceApi) return false;
      return 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();
      if (UseCoalesceApi != false) hash ^= UseCoalesceApi.GetHashCode();
      return hash;
    }

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

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

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

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

    [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;
          }
          case 152: {
            UseCoalesceApi = input.ReadBool();
            break;
          }
        }
      }
    }

  }

  public sealed partial class ClientStatus : pb::IMessage<ClientStatus> {
    private static readonly pb::MessageParser<ClientStatus> _parser = new pb::MessageParser<ClientStatus>(() => new ClientStatus());
    [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:
          if (Setup == null) {
            Setup = new global::Grpc.Testing.ClientConfig();
          }
          Setup.MergeFrom(other.Setup);
          break;
        case ArgtypeOneofCase.Mark:
          if (Mark == null) {
            Mark = new global::Grpc.Testing.Mark();
          }
          Mark.MergeFrom(other.Mark);
          break;
      }

    }

    [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:
          if (Setup == null) {
            Setup = new global::Grpc.Testing.ServerConfig();
          }
          Setup.MergeFrom(other.Setup);
          break;
        case ArgtypeOneofCase.Mark:
          if (Mark == null) {
            Mark = new global::Grpc.Testing.Mark();
          }
          Mark.MergeFrom(other.Mark);
          break;
      }

    }

    [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
