Merge pull request #2815 from jtattermusch/introduce_call_options

Introduce client-side CallOptions
pull/2376/head
Jan Tattermusch 9 years ago
commit 2ba9e5df81
  1. 82
      src/compiler/csharp_generator.cc
  2. 74
      src/csharp/Grpc.Core.Tests/ClientServerTest.cs
  3. 30
      src/csharp/Grpc.Core.Tests/TimeoutsTest.cs
  4. 56
      src/csharp/Grpc.Core/CallInvocationDetails.cs
  5. 89
      src/csharp/Grpc.Core/CallOptions.cs
  6. 48
      src/csharp/Grpc.Core/Calls.cs
  7. 16
      src/csharp/Grpc.Core/Channel.cs
  8. 10
      src/csharp/Grpc.Core/ClientBase.cs
  9. 3
      src/csharp/Grpc.Core/Grpc.Core.csproj
  10. 84
      src/csharp/Grpc.Core/Internal/AsyncCall.cs
  11. 28
      src/csharp/Grpc.Core/Method.cs
  12. 15
      src/csharp/Grpc.Core/ServerCallContext.cs
  13. 54
      src/csharp/Grpc.Examples/MathGrpc.cs
  14. 21
      src/csharp/Grpc.HealthCheck/HealthGrpc.cs
  15. 86
      src/csharp/Grpc.IntegrationTesting/TestGrpc.cs

@ -246,6 +246,8 @@ void GenerateStaticMethodField(Printer* out, const MethodDescriptor *method) {
out->Indent(); out->Indent();
out->Print("$methodtype$,\n", "methodtype", out->Print("$methodtype$,\n", "methodtype",
GetCSharpMethodType(GetMethodType(method))); GetCSharpMethodType(GetMethodType(method)));
out->Print("$servicenamefield$,\n", "servicenamefield",
GetServiceNameFieldName());
out->Print("\"$methodname$\",\n", "methodname", method->name()); out->Print("\"$methodname$\",\n", "methodname", method->name());
out->Print("$requestmarshaller$,\n", "requestmarshaller", out->Print("$requestmarshaller$,\n", "requestmarshaller",
GetMarshallerFieldName(method->input_type())); GetMarshallerFieldName(method->input_type()));
@ -273,6 +275,13 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
"methodname", method->name(), "request", "methodname", method->name(), "request",
GetClassName(method->input_type()), "response", GetClassName(method->input_type()), "response",
GetClassName(method->output_type())); GetClassName(method->output_type()));
// overload taking CallOptions as a param
out->Print(
"$response$ $methodname$($request$ request, CallOptions options);\n",
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
} }
std::string method_name = method->name(); std::string method_name = method->name();
@ -284,6 +293,13 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
"methodname", method_name, "request_maybe", "methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype", GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method)); GetMethodReturnTypeClient(method));
// overload taking CallOptions as a param
out->Print(
"$returntype$ $methodname$($request_maybe$CallOptions options);\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
} }
out->Outdent(); out->Outdent();
out->Print("}\n"); out->Print("}\n");
@ -340,10 +356,23 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
GetClassName(method->output_type())); GetClassName(method->output_type()));
out->Print("{\n"); out->Print("{\n");
out->Indent(); out->Indent();
out->Print("var call = CreateCall($servicenamefield$, $methodfield$, headers, deadline);\n", out->Print("var call = CreateCall($methodfield$, new CallOptions(headers, deadline, cancellationToken));\n",
"servicenamefield", GetServiceNameFieldName(), "methodfield", "methodfield", GetMethodFieldName(method));
GetMethodFieldName(method)); out->Print("return Calls.BlockingUnaryCall(call, request);\n");
out->Print("return Calls.BlockingUnaryCall(call, request, cancellationToken);\n"); out->Outdent();
out->Print("}\n");
// overload taking CallOptions as a param
out->Print(
"public $response$ $methodname$($request$ request, CallOptions options)\n",
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($methodfield$, options);\n",
"methodfield", GetMethodFieldName(method));
out->Print("return Calls.BlockingUnaryCall(call, request);\n");
out->Outdent(); out->Outdent();
out->Print("}\n"); out->Print("}\n");
} }
@ -359,26 +388,55 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
GetMethodReturnTypeClient(method)); GetMethodReturnTypeClient(method));
out->Print("{\n"); out->Print("{\n");
out->Indent(); out->Indent();
out->Print("var call = CreateCall($servicenamefield$, $methodfield$, headers, deadline);\n", out->Print("var call = CreateCall($methodfield$, new CallOptions(headers, deadline, cancellationToken));\n",
"servicenamefield", GetServiceNameFieldName(), "methodfield", "methodfield", GetMethodFieldName(method));
GetMethodFieldName(method));
switch (GetMethodType(method)) { switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING: case METHODTYPE_NO_STREAMING:
out->Print("return Calls.AsyncUnaryCall(call, request, cancellationToken);\n"); out->Print("return Calls.AsyncUnaryCall(call, request);\n");
break; break;
case METHODTYPE_CLIENT_STREAMING: case METHODTYPE_CLIENT_STREAMING:
out->Print("return Calls.AsyncClientStreamingCall(call, cancellationToken);\n"); out->Print("return Calls.AsyncClientStreamingCall(call);\n");
break; break;
case METHODTYPE_SERVER_STREAMING: case METHODTYPE_SERVER_STREAMING:
out->Print( out->Print(
"return Calls.AsyncServerStreamingCall(call, request, cancellationToken);\n"); "return Calls.AsyncServerStreamingCall(call, request);\n");
break; break;
case METHODTYPE_BIDI_STREAMING: case METHODTYPE_BIDI_STREAMING:
out->Print("return Calls.AsyncDuplexStreamingCall(call, cancellationToken);\n"); out->Print("return Calls.AsyncDuplexStreamingCall(call);\n");
break; break;
default: default:
GOOGLE_LOG(FATAL)<< "Can't get here."; GOOGLE_LOG(FATAL)<< "Can't get here.";
} }
out->Outdent();
out->Print("}\n");
// overload taking CallOptions as a param
out->Print(
"public $returntype$ $methodname$($request_maybe$CallOptions options)\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($methodfield$, options);\n",
"methodfield", GetMethodFieldName(method));
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
out->Print("return Calls.AsyncUnaryCall(call, request);\n");
break;
case METHODTYPE_CLIENT_STREAMING:
out->Print("return Calls.AsyncClientStreamingCall(call);\n");
break;
case METHODTYPE_SERVER_STREAMING:
out->Print(
"return Calls.AsyncServerStreamingCall(call, request);\n");
break;
case METHODTYPE_BIDI_STREAMING:
out->Print("return Calls.AsyncDuplexStreamingCall(call);\n");
break;
default:
GOOGLE_LOG(FATAL)<< "Can't get here.";
}
out->Outdent(); out->Outdent();
out->Print("}\n"); out->Print("}\n");
} }

@ -46,23 +46,26 @@ namespace Grpc.Core.Tests
public class ClientServerTest public class ClientServerTest
{ {
const string Host = "127.0.0.1"; const string Host = "127.0.0.1";
const string ServiceName = "/tests.Test"; const string ServiceName = "tests.Test";
static readonly Method<string, string> EchoMethod = new Method<string, string>( static readonly Method<string, string> EchoMethod = new Method<string, string>(
MethodType.Unary, MethodType.Unary,
"/tests.Test/Echo", ServiceName,
"Echo",
Marshallers.StringMarshaller, Marshallers.StringMarshaller,
Marshallers.StringMarshaller); Marshallers.StringMarshaller);
static readonly Method<string, string> ConcatAndEchoMethod = new Method<string, string>( static readonly Method<string, string> ConcatAndEchoMethod = new Method<string, string>(
MethodType.ClientStreaming, MethodType.ClientStreaming,
"/tests.Test/ConcatAndEcho", ServiceName,
"ConcatAndEcho",
Marshallers.StringMarshaller, Marshallers.StringMarshaller,
Marshallers.StringMarshaller); Marshallers.StringMarshaller);
static readonly Method<string, string> NonexistentMethod = new Method<string, string>( static readonly Method<string, string> NonexistentMethod = new Method<string, string>(
MethodType.Unary, MethodType.Unary,
"/tests.Test/NonexistentMethod", ServiceName,
"NonexistentMethod",
Marshallers.StringMarshaller, Marshallers.StringMarshaller,
Marshallers.StringMarshaller); Marshallers.StringMarshaller);
@ -102,17 +105,17 @@ namespace Grpc.Core.Tests
[Test] [Test]
public void UnaryCall() public void UnaryCall()
{ {
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty); var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
Assert.AreEqual("ABC", Calls.BlockingUnaryCall(internalCall, "ABC", CancellationToken.None)); Assert.AreEqual("ABC", Calls.BlockingUnaryCall(callDetails, "ABC"));
} }
[Test] [Test]
public void UnaryCall_ServerHandlerThrows() public void UnaryCall_ServerHandlerThrows()
{ {
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty); var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
try try
{ {
Calls.BlockingUnaryCall(internalCall, "THROW", CancellationToken.None); Calls.BlockingUnaryCall(callDetails, "THROW");
Assert.Fail(); Assert.Fail();
} }
catch (RpcException e) catch (RpcException e)
@ -124,10 +127,10 @@ namespace Grpc.Core.Tests
[Test] [Test]
public void UnaryCall_ServerHandlerThrowsRpcException() public void UnaryCall_ServerHandlerThrowsRpcException()
{ {
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty); var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
try try
{ {
Calls.BlockingUnaryCall(internalCall, "THROW_UNAUTHENTICATED", CancellationToken.None); Calls.BlockingUnaryCall(callDetails, "THROW_UNAUTHENTICATED");
Assert.Fail(); Assert.Fail();
} }
catch (RpcException e) catch (RpcException e)
@ -139,10 +142,10 @@ namespace Grpc.Core.Tests
[Test] [Test]
public void UnaryCall_ServerHandlerSetsStatus() public void UnaryCall_ServerHandlerSetsStatus()
{ {
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty); var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
try try
{ {
Calls.BlockingUnaryCall(internalCall, "SET_UNAUTHENTICATED", CancellationToken.None); Calls.BlockingUnaryCall(callDetails, "SET_UNAUTHENTICATED");
Assert.Fail(); Assert.Fail();
} }
catch (RpcException e) catch (RpcException e)
@ -152,20 +155,20 @@ namespace Grpc.Core.Tests
} }
[Test] [Test]
public void AsyncUnaryCall() public async Task AsyncUnaryCall()
{ {
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty); var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
var result = Calls.AsyncUnaryCall(internalCall, "ABC", CancellationToken.None).ResponseAsync.Result; var result = await Calls.AsyncUnaryCall(callDetails, "ABC");
Assert.AreEqual("ABC", result); Assert.AreEqual("ABC", result);
} }
[Test] [Test]
public async Task AsyncUnaryCall_ServerHandlerThrows() public async Task AsyncUnaryCall_ServerHandlerThrows()
{ {
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty); var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
try try
{ {
await Calls.AsyncUnaryCall(internalCall, "THROW", CancellationToken.None); await Calls.AsyncUnaryCall(callDetails, "THROW");
Assert.Fail(); Assert.Fail();
} }
catch (RpcException e) catch (RpcException e)
@ -177,8 +180,8 @@ namespace Grpc.Core.Tests
[Test] [Test]
public async Task ClientStreamingCall() public async Task ClientStreamingCall()
{ {
var internalCall = new Call<string, string>(ServiceName, ConcatAndEchoMethod, channel, Metadata.Empty); var callDetails = new CallInvocationDetails<string, string>(channel, ConcatAndEchoMethod, new CallOptions());
var call = Calls.AsyncClientStreamingCall(internalCall, CancellationToken.None); var call = Calls.AsyncClientStreamingCall(callDetails);
await call.RequestStream.WriteAll(new string[] { "A", "B", "C" }); await call.RequestStream.WriteAll(new string[] { "A", "B", "C" });
Assert.AreEqual("ABC", await call.ResponseAsync); Assert.AreEqual("ABC", await call.ResponseAsync);
@ -187,10 +190,9 @@ namespace Grpc.Core.Tests
[Test] [Test]
public async Task ClientStreamingCall_CancelAfterBegin() public async Task ClientStreamingCall_CancelAfterBegin()
{ {
var internalCall = new Call<string, string>(ServiceName, ConcatAndEchoMethod, channel, Metadata.Empty);
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
var call = Calls.AsyncClientStreamingCall(internalCall, cts.Token); var callDetails = new CallInvocationDetails<string, string>(channel, ConcatAndEchoMethod, new CallOptions(cancellationToken: cts.Token));
var call = Calls.AsyncClientStreamingCall(callDetails);
// TODO(jtattermusch): we need this to ensure call has been initiated once we cancel it. // TODO(jtattermusch): we need this to ensure call has been initiated once we cancel it.
await Task.Delay(1000); await Task.Delay(1000);
@ -214,8 +216,8 @@ namespace Grpc.Core.Tests
new Metadata.Entry("ascii-header", "abcdefg"), new Metadata.Entry("ascii-header", "abcdefg"),
new Metadata.Entry("binary-header-bin", new byte[] { 1, 2, 3, 0, 0xff }), new Metadata.Entry("binary-header-bin", new byte[] { 1, 2, 3, 0, 0xff }),
}; };
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, headers); var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions(headers: headers));
var call = Calls.AsyncUnaryCall(internalCall, "ABC", CancellationToken.None); var call = Calls.AsyncUnaryCall(callDetails, "ABC");
Assert.AreEqual("ABC", call.ResponseAsync.Result); Assert.AreEqual("ABC", call.ResponseAsync.Result);
@ -235,25 +237,25 @@ namespace Grpc.Core.Tests
{ {
channel.Dispose(); channel.Dispose();
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty); var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
Assert.Throws(typeof(ObjectDisposedException), () => Calls.BlockingUnaryCall(internalCall, "ABC", CancellationToken.None)); Assert.Throws(typeof(ObjectDisposedException), () => Calls.BlockingUnaryCall(callDetails, "ABC"));
} }
[Test] [Test]
public void UnaryCallPerformance() public void UnaryCallPerformance()
{ {
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty); var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
BenchmarkUtil.RunBenchmark(100, 100, BenchmarkUtil.RunBenchmark(100, 100,
() => { Calls.BlockingUnaryCall(internalCall, "ABC", default(CancellationToken)); }); () => { Calls.BlockingUnaryCall(callDetails, "ABC"); });
} }
[Test] [Test]
public void UnknownMethodHandler() public void UnknownMethodHandler()
{ {
var internalCall = new Call<string, string>(ServiceName, NonexistentMethod, channel, Metadata.Empty); var callDetails = new CallInvocationDetails<string, string>(channel, NonexistentMethod, new CallOptions());
try try
{ {
Calls.BlockingUnaryCall(internalCall, "ABC", default(CancellationToken)); Calls.BlockingUnaryCall(callDetails, "ABC");
Assert.Fail(); Assert.Fail();
} }
catch (RpcException e) catch (RpcException e)
@ -265,16 +267,16 @@ namespace Grpc.Core.Tests
[Test] [Test]
public void UserAgentStringPresent() public void UserAgentStringPresent()
{ {
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty); var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
string userAgent = Calls.BlockingUnaryCall(internalCall, "RETURN-USER-AGENT", CancellationToken.None); string userAgent = Calls.BlockingUnaryCall(callDetails, "RETURN-USER-AGENT");
Assert.IsTrue(userAgent.StartsWith("grpc-csharp/")); Assert.IsTrue(userAgent.StartsWith("grpc-csharp/"));
} }
[Test] [Test]
public void PeerInfoPresent() public void PeerInfoPresent()
{ {
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty); var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
string peer = Calls.BlockingUnaryCall(internalCall, "RETURN-PEER", CancellationToken.None); string peer = Calls.BlockingUnaryCall(callDetails, "RETURN-PEER");
Assert.IsTrue(peer.Contains(Host)); Assert.IsTrue(peer.Contains(Host));
} }
@ -286,8 +288,8 @@ namespace Grpc.Core.Tests
var stateChangedTask = channel.WaitForStateChangedAsync(channel.State); var stateChangedTask = channel.WaitForStateChangedAsync(channel.State);
var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty); var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
await Calls.AsyncUnaryCall(internalCall, "abc", CancellationToken.None); await Calls.AsyncUnaryCall(callDetails, "abc");
await stateChangedTask; await stateChangedTask;
Assert.AreEqual(ChannelState.Ready, channel.State); Assert.AreEqual(ChannelState.Ready, channel.State);

@ -49,11 +49,12 @@ namespace Grpc.Core.Tests
public class TimeoutsTest public class TimeoutsTest
{ {
const string Host = "localhost"; const string Host = "localhost";
const string ServiceName = "/tests.Test"; const string ServiceName = "tests.Test";
static readonly Method<string, string> TestMethod = new Method<string, string>( static readonly Method<string, string> TestMethod = new Method<string, string>(
MethodType.Unary, MethodType.Unary,
"/tests.Test/Test", ServiceName,
"Test",
Marshallers.StringMarshaller, Marshallers.StringMarshaller,
Marshallers.StringMarshaller); Marshallers.StringMarshaller);
@ -98,12 +99,12 @@ namespace Grpc.Core.Tests
public void InfiniteDeadline() public void InfiniteDeadline()
{ {
// no deadline specified, check server sees infinite deadline // no deadline specified, check server sees infinite deadline
var internalCall = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty); var callDetails = new CallInvocationDetails<string, string>(channel, TestMethod, new CallOptions());
Assert.AreEqual("DATETIME_MAXVALUE", Calls.BlockingUnaryCall(internalCall, "RETURN_DEADLINE", CancellationToken.None)); Assert.AreEqual("DATETIME_MAXVALUE", Calls.BlockingUnaryCall(callDetails, "RETURN_DEADLINE"));
// DateTime.MaxValue deadline specified, check server sees infinite deadline // DateTime.MaxValue deadline specified, check server sees infinite deadline
var internalCall2 = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty, DateTime.MaxValue); var callDetails2 = new CallInvocationDetails<string, string>(channel, TestMethod, new CallOptions());
Assert.AreEqual("DATETIME_MAXVALUE", Calls.BlockingUnaryCall(internalCall2, "RETURN_DEADLINE", CancellationToken.None)); Assert.AreEqual("DATETIME_MAXVALUE", Calls.BlockingUnaryCall(callDetails2, "RETURN_DEADLINE"));
} }
[Test] [Test]
@ -112,9 +113,9 @@ namespace Grpc.Core.Tests
var remainingTimeClient = TimeSpan.FromDays(7); var remainingTimeClient = TimeSpan.FromDays(7);
var deadline = DateTime.UtcNow + remainingTimeClient; var deadline = DateTime.UtcNow + remainingTimeClient;
Thread.Sleep(1000); Thread.Sleep(1000);
var internalCall = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty, deadline); var callDetails = new CallInvocationDetails<string, string>(channel, TestMethod, new CallOptions(deadline: deadline));
var serverDeadlineTicksString = Calls.BlockingUnaryCall(internalCall, "RETURN_DEADLINE", CancellationToken.None); var serverDeadlineTicksString = Calls.BlockingUnaryCall(callDetails, "RETURN_DEADLINE");
var serverDeadline = new DateTime(long.Parse(serverDeadlineTicksString), DateTimeKind.Utc); var serverDeadline = new DateTime(long.Parse(serverDeadlineTicksString), DateTimeKind.Utc);
// A fairly relaxed check that the deadline set by client and deadline seen by server // A fairly relaxed check that the deadline set by client and deadline seen by server
@ -126,12 +127,11 @@ namespace Grpc.Core.Tests
[Test] [Test]
public void DeadlineInThePast() public void DeadlineInThePast()
{ {
var deadline = DateTime.MinValue; var callDetails = new CallInvocationDetails<string, string>(channel, TestMethod, new CallOptions(deadline: DateTime.MinValue));
var internalCall = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty, deadline);
try try
{ {
Calls.BlockingUnaryCall(internalCall, "TIMEOUT", CancellationToken.None); Calls.BlockingUnaryCall(callDetails, "TIMEOUT");
Assert.Fail(); Assert.Fail();
} }
catch (RpcException e) catch (RpcException e)
@ -145,11 +145,11 @@ namespace Grpc.Core.Tests
public void DeadlineExceededStatusOnTimeout() public void DeadlineExceededStatusOnTimeout()
{ {
var deadline = DateTime.UtcNow.Add(TimeSpan.FromSeconds(5)); var deadline = DateTime.UtcNow.Add(TimeSpan.FromSeconds(5));
var internalCall = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty, deadline); var callDetails = new CallInvocationDetails<string, string>(channel, TestMethod, new CallOptions(deadline: deadline));
try try
{ {
Calls.BlockingUnaryCall(internalCall, "TIMEOUT", CancellationToken.None); Calls.BlockingUnaryCall(callDetails, "TIMEOUT");
Assert.Fail(); Assert.Fail();
} }
catch (RpcException e) catch (RpcException e)
@ -163,11 +163,11 @@ namespace Grpc.Core.Tests
public void ServerReceivesCancellationOnTimeout() public void ServerReceivesCancellationOnTimeout()
{ {
var deadline = DateTime.UtcNow.Add(TimeSpan.FromSeconds(5)); var deadline = DateTime.UtcNow.Add(TimeSpan.FromSeconds(5));
var internalCall = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty, deadline); var callDetails = new CallInvocationDetails<string, string>(channel, TestMethod, new CallOptions(deadline: deadline));
try try
{ {
Calls.BlockingUnaryCall(internalCall, "CHECK_CANCELLATION_RECEIVED", CancellationToken.None); Calls.BlockingUnaryCall(callDetails, "CHECK_CANCELLATION_RECEIVED");
Assert.Fail(); Assert.Fail();
} }
catch (RpcException e) catch (RpcException e)

@ -38,30 +38,30 @@ using Grpc.Core.Utils;
namespace Grpc.Core namespace Grpc.Core
{ {
/// <summary> /// <summary>
/// Abstraction of a call to be invoked on a client. /// Details about a client-side call to be invoked.
/// </summary> /// </summary>
public class Call<TRequest, TResponse> public class CallInvocationDetails<TRequest, TResponse>
{ {
readonly string name; readonly Channel channel;
readonly string method;
readonly string host;
readonly Marshaller<TRequest> requestMarshaller; readonly Marshaller<TRequest> requestMarshaller;
readonly Marshaller<TResponse> responseMarshaller; readonly Marshaller<TResponse> responseMarshaller;
readonly Channel channel; readonly CallOptions options;
readonly Metadata headers;
readonly DateTime deadline;
public Call(string serviceName, Method<TRequest, TResponse> method, Channel channel, Metadata headers) public CallInvocationDetails(Channel channel, Method<TRequest, TResponse> method, CallOptions options) :
: this(serviceName, method, channel, headers, DateTime.MaxValue) this(channel, method.FullName, null, method.RequestMarshaller, method.ResponseMarshaller, options)
{ {
} }
public Call(string serviceName, Method<TRequest, TResponse> method, Channel channel, Metadata headers, DateTime deadline) public CallInvocationDetails(Channel channel, string method, string host, Marshaller<TRequest> requestMarshaller, Marshaller<TResponse> responseMarshaller, CallOptions options)
{ {
this.name = method.GetFullName(serviceName);
this.requestMarshaller = method.RequestMarshaller;
this.responseMarshaller = method.ResponseMarshaller;
this.channel = Preconditions.CheckNotNull(channel); this.channel = Preconditions.CheckNotNull(channel);
this.headers = Preconditions.CheckNotNull(headers); this.method = Preconditions.CheckNotNull(method);
this.deadline = deadline; this.host = host;
this.requestMarshaller = Preconditions.CheckNotNull(requestMarshaller);
this.responseMarshaller = Preconditions.CheckNotNull(responseMarshaller);
this.options = Preconditions.CheckNotNull(options);
} }
public Channel Channel public Channel Channel
@ -72,49 +72,43 @@ namespace Grpc.Core
} }
} }
/// <summary> public string Method
/// Full methods name including the service name.
/// </summary>
public string Name
{ {
get get
{ {
return name; return this.method;
} }
} }
/// <summary> public string Host
/// Headers to send at the beginning of the call.
/// </summary>
public Metadata Headers
{ {
get get
{ {
return headers; return this.host;
} }
} }
public DateTime Deadline public Marshaller<TRequest> RequestMarshaller
{ {
get get
{ {
return this.deadline; return this.requestMarshaller;
} }
} }
public Marshaller<TRequest> RequestMarshaller public Marshaller<TResponse> ResponseMarshaller
{ {
get get
{ {
return requestMarshaller; return this.responseMarshaller;
} }
} }
public Marshaller<TResponse> ResponseMarshaller public CallOptions Options
{ {
get get
{ {
return responseMarshaller; return options;
} }
} }
} }

@ -0,0 +1,89 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Threading;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
namespace Grpc.Core
{
/// <summary>
/// Options for calls made by client.
/// </summary>
public class CallOptions
{
readonly Metadata headers;
readonly DateTime deadline;
readonly CancellationToken cancellationToken;
/// <summary>
/// Creates a new instance of <c>CallOptions</c>.
/// </summary>
/// <param name="headers">Headers to be sent with the call.</param>
/// <param name="deadline">Deadline for the call to finish. null means no deadline.</param>
/// <param name="cancellationToken">Can be used to request cancellation of the call.</param>
public CallOptions(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
// TODO(jtattermusch): consider only creating metadata object once it's really needed.
this.headers = headers != null ? headers : new Metadata();
this.deadline = deadline.HasValue ? deadline.Value : DateTime.MaxValue;
this.cancellationToken = cancellationToken;
}
/// <summary>
/// Headers to send at the beginning of the call.
/// </summary>
public Metadata Headers
{
get { return headers; }
}
/// <summary>
/// Call deadline.
/// </summary>
public DateTime Deadline
{
get { return deadline; }
}
/// <summary>
/// Token that can be used for cancelling the call.
/// </summary>
public CancellationToken CancellationToken
{
get { return cancellationToken; }
}
}
}

@ -43,70 +43,52 @@ namespace Grpc.Core
/// </summary> /// </summary>
public static class Calls public static class Calls
{ {
public static TResponse BlockingUnaryCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token) public static TResponse BlockingUnaryCall<TRequest, TResponse>(CallInvocationDetails<TRequest, TResponse> call, TRequest req)
where TRequest : class where TRequest : class
where TResponse : class where TResponse : class
{ {
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer); var asyncCall = new AsyncCall<TRequest, TResponse>(call);
// TODO(jtattermusch): this gives a race that cancellation can be requested before the call even starts. return asyncCall.UnaryCall(req);
RegisterCancellationCallback(asyncCall, token);
return asyncCall.UnaryCall(call.Channel, call.Name, req, call.Headers, call.Deadline);
} }
public static AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token) public static AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(CallInvocationDetails<TRequest, TResponse> call, TRequest req)
where TRequest : class where TRequest : class
where TResponse : class where TResponse : class
{ {
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer); var asyncCall = new AsyncCall<TRequest, TResponse>(call);
asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name, Timespec.FromDateTime(call.Deadline)); var asyncResult = asyncCall.UnaryCallAsync(req);
var asyncResult = asyncCall.UnaryCallAsync(req, call.Headers, call.Deadline);
RegisterCancellationCallback(asyncCall, token);
return new AsyncUnaryCall<TResponse>(asyncResult, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel); return new AsyncUnaryCall<TResponse>(asyncResult, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel);
} }
public static AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token) public static AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(CallInvocationDetails<TRequest, TResponse> call, TRequest req)
where TRequest : class where TRequest : class
where TResponse : class where TResponse : class
{ {
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer); var asyncCall = new AsyncCall<TRequest, TResponse>(call);
asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name, Timespec.FromDateTime(call.Deadline)); asyncCall.StartServerStreamingCall(req);
asyncCall.StartServerStreamingCall(req, call.Headers, call.Deadline);
RegisterCancellationCallback(asyncCall, token);
var responseStream = new ClientResponseStream<TRequest, TResponse>(asyncCall); var responseStream = new ClientResponseStream<TRequest, TResponse>(asyncCall);
return new AsyncServerStreamingCall<TResponse>(responseStream, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel); return new AsyncServerStreamingCall<TResponse>(responseStream, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel);
} }
public static AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Call<TRequest, TResponse> call, CancellationToken token) public static AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(CallInvocationDetails<TRequest, TResponse> call)
where TRequest : class where TRequest : class
where TResponse : class where TResponse : class
{ {
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer); var asyncCall = new AsyncCall<TRequest, TResponse>(call);
asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name, Timespec.FromDateTime(call.Deadline)); var resultTask = asyncCall.ClientStreamingCallAsync();
var resultTask = asyncCall.ClientStreamingCallAsync(call.Headers, call.Deadline);
RegisterCancellationCallback(asyncCall, token);
var requestStream = new ClientRequestStream<TRequest, TResponse>(asyncCall); var requestStream = new ClientRequestStream<TRequest, TResponse>(asyncCall);
return new AsyncClientStreamingCall<TRequest, TResponse>(requestStream, resultTask, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel); return new AsyncClientStreamingCall<TRequest, TResponse>(requestStream, resultTask, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel);
} }
public static AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Call<TRequest, TResponse> call, CancellationToken token) public static AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(CallInvocationDetails<TRequest, TResponse> call)
where TRequest : class where TRequest : class
where TResponse : class where TResponse : class
{ {
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer); var asyncCall = new AsyncCall<TRequest, TResponse>(call);
asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name, Timespec.FromDateTime(call.Deadline)); asyncCall.StartDuplexStreamingCall();
asyncCall.StartDuplexStreamingCall(call.Headers, call.Deadline);
RegisterCancellationCallback(asyncCall, token);
var requestStream = new ClientRequestStream<TRequest, TResponse>(asyncCall); var requestStream = new ClientRequestStream<TRequest, TResponse>(asyncCall);
var responseStream = new ClientResponseStream<TRequest, TResponse>(asyncCall); var responseStream = new ClientResponseStream<TRequest, TResponse>(asyncCall);
return new AsyncDuplexStreamingCall<TRequest, TResponse>(requestStream, responseStream, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel); return new AsyncDuplexStreamingCall<TRequest, TResponse>(requestStream, responseStream, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel);
} }
private static void RegisterCancellationCallback<TRequest, TResponse>(AsyncCall<TRequest, TResponse> asyncCall, CancellationToken token)
{
if (token.CanBeCanceled)
{
token.Register(() => asyncCall.Cancel());
}
}
} }
} }

@ -178,22 +178,6 @@ namespace Grpc.Core
} }
} }
internal CompletionQueueSafeHandle CompletionQueue
{
get
{
return this.environment.CompletionQueue;
}
}
internal CompletionRegistry CompletionRegistry
{
get
{
return this.environment.CompletionRegistry;
}
}
internal GrpcEnvironment Environment internal GrpcEnvironment Environment
{ {
get get

@ -76,19 +76,17 @@ namespace Grpc.Core
/// <summary> /// <summary>
/// Creates a new call to given method. /// Creates a new call to given method.
/// </summary> /// </summary>
protected Call<TRequest, TResponse> CreateCall<TRequest, TResponse>(string serviceName, Method<TRequest, TResponse> method, Metadata metadata, DateTime? deadline) protected CallInvocationDetails<TRequest, TResponse> CreateCall<TRequest, TResponse>(Method<TRequest, TResponse> method, CallOptions options)
where TRequest : class where TRequest : class
where TResponse : class where TResponse : class
{ {
var interceptor = HeaderInterceptor; var interceptor = HeaderInterceptor;
if (interceptor != null) if (interceptor != null)
{ {
metadata = metadata ?? new Metadata(); interceptor(options.Headers);
interceptor(metadata); options.Headers.Freeze();
metadata.Freeze();
} }
return new Call<TRequest, TResponse>(serviceName, method, channel, return new CallInvocationDetails<TRequest, TResponse>(channel, method, options);
metadata ?? Metadata.Empty, deadline ?? DateTime.MaxValue);
} }
} }
} }

@ -57,7 +57,6 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RpcException.cs" /> <Compile Include="RpcException.cs" />
<Compile Include="Calls.cs" /> <Compile Include="Calls.cs" />
<Compile Include="Call.cs" />
<Compile Include="AsyncClientStreamingCall.cs" /> <Compile Include="AsyncClientStreamingCall.cs" />
<Compile Include="GrpcEnvironment.cs" /> <Compile Include="GrpcEnvironment.cs" />
<Compile Include="Status.cs" /> <Compile Include="Status.cs" />
@ -114,6 +113,8 @@
<Compile Include="Logging\ConsoleLogger.cs" /> <Compile Include="Logging\ConsoleLogger.cs" />
<Compile Include="Internal\NativeLogRedirector.cs" /> <Compile Include="Internal\NativeLogRedirector.cs" />
<Compile Include="ChannelState.cs" /> <Compile Include="ChannelState.cs" />
<Compile Include="CallInvocationDetails.cs" />
<Compile Include="CallOptions.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="Grpc.Core.nuspec" /> <None Include="Grpc.Core.nuspec" />

@ -50,7 +50,7 @@ namespace Grpc.Core.Internal
{ {
static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<AsyncCall<TRequest, TResponse>>(); static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<AsyncCall<TRequest, TResponse>>();
Channel channel; readonly CallInvocationDetails<TRequest, TResponse> callDetails;
// Completion of a pending unary response if not null. // Completion of a pending unary response if not null.
TaskCompletionSource<TResponse> unaryResponseTcs; TaskCompletionSource<TResponse> unaryResponseTcs;
@ -60,26 +60,18 @@ namespace Grpc.Core.Internal
bool readObserverCompleted; // True if readObserver has already been completed. bool readObserverCompleted; // True if readObserver has already been completed.
public AsyncCall(Func<TRequest, byte[]> serializer, Func<byte[], TResponse> deserializer) : base(serializer, deserializer) public AsyncCall(CallInvocationDetails<TRequest, TResponse> callDetails)
: base(callDetails.RequestMarshaller.Serializer, callDetails.ResponseMarshaller.Deserializer)
{ {
} this.callDetails = callDetails;
public void Initialize(Channel channel, CompletionQueueSafeHandle cq, string methodName, Timespec deadline)
{
this.channel = channel;
var call = channel.Handle.CreateCall(channel.CompletionRegistry, cq, methodName, null, deadline);
channel.Environment.DebugStats.ActiveClientCalls.Increment();
InitializeInternal(call);
} }
// TODO: this method is not Async, so it shouldn't be in AsyncCall class, but // TODO: this method is not Async, so it shouldn't be in AsyncCall class, but
// it is reusing fair amount of code in this class, so we are leaving it here. // it is reusing fair amount of code in this class, so we are leaving it here.
// TODO: for other calls, you need to call Initialize, this methods calls initialize
// on its own, so there's a usage inconsistency.
/// <summary> /// <summary>
/// Blocking unary request - unary response call. /// Blocking unary request - unary response call.
/// </summary> /// </summary>
public TResponse UnaryCall(Channel channel, string methodName, TRequest msg, Metadata headers, DateTime deadline) public TResponse UnaryCall(TRequest msg)
{ {
using (CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create()) using (CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create())
{ {
@ -89,13 +81,15 @@ namespace Grpc.Core.Internal
lock (myLock) lock (myLock)
{ {
Initialize(channel, cq, methodName, Timespec.FromDateTime(deadline)); Preconditions.CheckState(!started);
started = true; started = true;
Initialize(cq);
halfcloseRequested = true; halfcloseRequested = true;
readingDone = true; readingDone = true;
} }
using (var metadataArray = MetadataArraySafeHandle.Create(headers)) using (var metadataArray = MetadataArraySafeHandle.Create(callDetails.Options.Headers))
{ {
using (var ctx = BatchContextSafeHandle.Create()) using (var ctx = BatchContextSafeHandle.Create())
{ {
@ -129,20 +123,22 @@ namespace Grpc.Core.Internal
/// <summary> /// <summary>
/// Starts a unary request - unary response call. /// Starts a unary request - unary response call.
/// </summary> /// </summary>
public Task<TResponse> UnaryCallAsync(TRequest msg, Metadata headers, DateTime deadline) public Task<TResponse> UnaryCallAsync(TRequest msg)
{ {
lock (myLock) lock (myLock)
{ {
Preconditions.CheckNotNull(call); Preconditions.CheckState(!started);
started = true; started = true;
Initialize(callDetails.Channel.Environment.CompletionQueue);
halfcloseRequested = true; halfcloseRequested = true;
readingDone = true; readingDone = true;
byte[] payload = UnsafeSerialize(msg); byte[] payload = UnsafeSerialize(msg);
unaryResponseTcs = new TaskCompletionSource<TResponse>(); unaryResponseTcs = new TaskCompletionSource<TResponse>();
using (var metadataArray = MetadataArraySafeHandle.Create(headers)) using (var metadataArray = MetadataArraySafeHandle.Create(callDetails.Options.Headers))
{ {
call.StartUnary(payload, HandleUnaryResponse, metadataArray); call.StartUnary(payload, HandleUnaryResponse, metadataArray);
} }
@ -154,17 +150,19 @@ namespace Grpc.Core.Internal
/// Starts a streamed request - unary response call. /// Starts a streamed request - unary response call.
/// Use StartSendMessage and StartSendCloseFromClient to stream requests. /// Use StartSendMessage and StartSendCloseFromClient to stream requests.
/// </summary> /// </summary>
public Task<TResponse> ClientStreamingCallAsync(Metadata headers, DateTime deadline) public Task<TResponse> ClientStreamingCallAsync()
{ {
lock (myLock) lock (myLock)
{ {
Preconditions.CheckNotNull(call); Preconditions.CheckState(!started);
started = true; started = true;
Initialize(callDetails.Channel.Environment.CompletionQueue);
readingDone = true; readingDone = true;
unaryResponseTcs = new TaskCompletionSource<TResponse>(); unaryResponseTcs = new TaskCompletionSource<TResponse>();
using (var metadataArray = MetadataArraySafeHandle.Create(headers)) using (var metadataArray = MetadataArraySafeHandle.Create(callDetails.Options.Headers))
{ {
call.StartClientStreaming(HandleUnaryResponse, metadataArray); call.StartClientStreaming(HandleUnaryResponse, metadataArray);
} }
@ -176,19 +174,21 @@ namespace Grpc.Core.Internal
/// <summary> /// <summary>
/// Starts a unary request - streamed response call. /// Starts a unary request - streamed response call.
/// </summary> /// </summary>
public void StartServerStreamingCall(TRequest msg, Metadata headers, DateTime deadline) public void StartServerStreamingCall(TRequest msg)
{ {
lock (myLock) lock (myLock)
{ {
Preconditions.CheckNotNull(call); Preconditions.CheckState(!started);
started = true; started = true;
Initialize(callDetails.Channel.Environment.CompletionQueue);
halfcloseRequested = true; halfcloseRequested = true;
halfclosed = true; // halfclose not confirmed yet, but it will be once finishedHandler is called. halfclosed = true; // halfclose not confirmed yet, but it will be once finishedHandler is called.
byte[] payload = UnsafeSerialize(msg); byte[] payload = UnsafeSerialize(msg);
using (var metadataArray = MetadataArraySafeHandle.Create(headers)) using (var metadataArray = MetadataArraySafeHandle.Create(callDetails.Options.Headers))
{ {
call.StartServerStreaming(payload, HandleFinished, metadataArray); call.StartServerStreaming(payload, HandleFinished, metadataArray);
} }
@ -199,15 +199,16 @@ namespace Grpc.Core.Internal
/// Starts a streaming request - streaming response call. /// Starts a streaming request - streaming response call.
/// Use StartSendMessage and StartSendCloseFromClient to stream requests. /// Use StartSendMessage and StartSendCloseFromClient to stream requests.
/// </summary> /// </summary>
public void StartDuplexStreamingCall(Metadata headers, DateTime deadline) public void StartDuplexStreamingCall()
{ {
lock (myLock) lock (myLock)
{ {
Preconditions.CheckNotNull(call); Preconditions.CheckState(!started);
started = true; started = true;
using (var metadataArray = MetadataArraySafeHandle.Create(headers)) Initialize(callDetails.Channel.Environment.CompletionQueue);
using (var metadataArray = MetadataArraySafeHandle.Create(callDetails.Options.Headers))
{ {
call.StartDuplexStreaming(HandleFinished, metadataArray); call.StartDuplexStreaming(HandleFinished, metadataArray);
} }
@ -309,7 +310,26 @@ namespace Grpc.Core.Internal
protected override void OnReleaseResources() protected override void OnReleaseResources()
{ {
channel.Environment.DebugStats.ActiveClientCalls.Decrement(); callDetails.Channel.Environment.DebugStats.ActiveClientCalls.Decrement();
}
private void Initialize(CompletionQueueSafeHandle cq)
{
var call = callDetails.Channel.Handle.CreateCall(callDetails.Channel.Environment.CompletionRegistry, cq,
callDetails.Method, callDetails.Host, Timespec.FromDateTime(callDetails.Options.Deadline));
callDetails.Channel.Environment.DebugStats.ActiveClientCalls.Increment();
InitializeInternal(call);
RegisterCancellationCallback();
}
// Make sure that once cancellationToken for this call is cancelled, Cancel() will be called.
private void RegisterCancellationCallback()
{
var token = callDetails.Options.CancellationToken;
if (token.CanBeCanceled)
{
token.Register(() => this.Cancel());
}
} }
/// <summary> /// <summary>

@ -53,16 +53,20 @@ namespace Grpc.Core
public class Method<TRequest, TResponse> public class Method<TRequest, TResponse>
{ {
readonly MethodType type; readonly MethodType type;
readonly string serviceName;
readonly string name; readonly string name;
readonly Marshaller<TRequest> requestMarshaller; readonly Marshaller<TRequest> requestMarshaller;
readonly Marshaller<TResponse> responseMarshaller; readonly Marshaller<TResponse> responseMarshaller;
readonly string fullName;
public Method(MethodType type, string name, Marshaller<TRequest> requestMarshaller, Marshaller<TResponse> responseMarshaller) public Method(MethodType type, string serviceName, string name, Marshaller<TRequest> requestMarshaller, Marshaller<TResponse> responseMarshaller)
{ {
this.type = type; this.type = type;
this.name = name; this.serviceName = Preconditions.CheckNotNull(serviceName);
this.requestMarshaller = requestMarshaller; this.name = Preconditions.CheckNotNull(name);
this.responseMarshaller = responseMarshaller; this.requestMarshaller = Preconditions.CheckNotNull(requestMarshaller);
this.responseMarshaller = Preconditions.CheckNotNull(responseMarshaller);
this.fullName = GetFullName(serviceName);
} }
public MethodType Type public MethodType Type
@ -72,6 +76,14 @@ namespace Grpc.Core
return this.type; return this.type;
} }
} }
public string ServiceName
{
get
{
return this.serviceName;
}
}
public string Name public string Name
{ {
@ -97,6 +109,14 @@ namespace Grpc.Core
} }
} }
public string FullName
{
get
{
return this.fullName;
}
}
/// <summary> /// <summary>
/// Gets full name of the method including the service name. /// Gets full name of the method including the service name.
/// </summary> /// </summary>

@ -65,7 +65,7 @@ namespace Grpc.Core
this.cancellationToken = cancellationToken; this.cancellationToken = cancellationToken;
} }
/// <summary> Name of method called in this RPC. </summary> /// <summary>Name of method called in this RPC.</summary>
public string Method public string Method
{ {
get get
@ -74,7 +74,7 @@ namespace Grpc.Core
} }
} }
/// <summary> Name of host called in this RPC. </summary> /// <summary>Name of host called in this RPC.</summary>
public string Host public string Host
{ {
get get
@ -83,7 +83,7 @@ namespace Grpc.Core
} }
} }
/// <summary> Address of the remote endpoint in URI format. </summary> /// <summary>Address of the remote endpoint in URI format.</summary>
public string Peer public string Peer
{ {
get get
@ -92,7 +92,7 @@ namespace Grpc.Core
} }
} }
/// <summary> Deadline for this RPC. </summary> /// <summary>Deadline for this RPC.</summary>
public DateTime Deadline public DateTime Deadline
{ {
get get
@ -101,7 +101,7 @@ namespace Grpc.Core
} }
} }
/// <summary> Initial metadata sent by client. </summary> /// <summary>Initial metadata sent by client.</summary>
public Metadata RequestHeaders public Metadata RequestHeaders
{ {
get get
@ -110,8 +110,7 @@ namespace Grpc.Core
} }
} }
// TODO(jtattermusch): support signalling cancellation. ///<summary>Cancellation token signals when call is cancelled.</summary>
/// <summary> Cancellation token signals when call is cancelled. </summary>
public CancellationToken CancellationToken public CancellationToken CancellationToken
{ {
get get
@ -120,7 +119,7 @@ namespace Grpc.Core
} }
} }
/// <summary> Trailers to send back to client after RPC finishes.</summary> /// <summary>Trailers to send back to client after RPC finishes.</summary>
public Metadata ResponseTrailers public Metadata ResponseTrailers
{ {
get get

@ -19,24 +19,28 @@ namespace math {
static readonly Method<global::math.DivArgs, global::math.DivReply> __Method_Div = new Method<global::math.DivArgs, global::math.DivReply>( static readonly Method<global::math.DivArgs, global::math.DivReply> __Method_Div = new Method<global::math.DivArgs, global::math.DivReply>(
MethodType.Unary, MethodType.Unary,
__ServiceName,
"Div", "Div",
__Marshaller_DivArgs, __Marshaller_DivArgs,
__Marshaller_DivReply); __Marshaller_DivReply);
static readonly Method<global::math.DivArgs, global::math.DivReply> __Method_DivMany = new Method<global::math.DivArgs, global::math.DivReply>( static readonly Method<global::math.DivArgs, global::math.DivReply> __Method_DivMany = new Method<global::math.DivArgs, global::math.DivReply>(
MethodType.DuplexStreaming, MethodType.DuplexStreaming,
__ServiceName,
"DivMany", "DivMany",
__Marshaller_DivArgs, __Marshaller_DivArgs,
__Marshaller_DivReply); __Marshaller_DivReply);
static readonly Method<global::math.FibArgs, global::math.Num> __Method_Fib = new Method<global::math.FibArgs, global::math.Num>( static readonly Method<global::math.FibArgs, global::math.Num> __Method_Fib = new Method<global::math.FibArgs, global::math.Num>(
MethodType.ServerStreaming, MethodType.ServerStreaming,
__ServiceName,
"Fib", "Fib",
__Marshaller_FibArgs, __Marshaller_FibArgs,
__Marshaller_Num); __Marshaller_Num);
static readonly Method<global::math.Num, global::math.Num> __Method_Sum = new Method<global::math.Num, global::math.Num>( static readonly Method<global::math.Num, global::math.Num> __Method_Sum = new Method<global::math.Num, global::math.Num>(
MethodType.ClientStreaming, MethodType.ClientStreaming,
__ServiceName,
"Sum", "Sum",
__Marshaller_Num, __Marshaller_Num,
__Marshaller_Num); __Marshaller_Num);
@ -45,10 +49,15 @@ namespace math {
public interface IMathClient public interface IMathClient
{ {
global::math.DivReply Div(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); global::math.DivReply Div(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
global::math.DivReply Div(global::math.DivArgs request, CallOptions options);
AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, CallOptions options);
AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(CallOptions options);
AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, CallOptions options);
AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(CallOptions options);
} }
// server-side interface // server-side interface
@ -68,28 +77,53 @@ namespace math {
} }
public global::math.DivReply Div(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) public global::math.DivReply Div(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{ {
var call = CreateCall(__ServiceName, __Method_Div, headers, deadline); var call = CreateCall(__Method_Div, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request, cancellationToken); return Calls.BlockingUnaryCall(call, request);
}
public global::math.DivReply Div(global::math.DivArgs request, CallOptions options)
{
var call = CreateCall(__Method_Div, options);
return Calls.BlockingUnaryCall(call, request);
} }
public AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) public AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{ {
var call = CreateCall(__ServiceName, __Method_Div, headers, deadline); var call = CreateCall(__Method_Div, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request, cancellationToken); return Calls.AsyncUnaryCall(call, request);
}
public AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, CallOptions options)
{
var call = CreateCall(__Method_Div, options);
return Calls.AsyncUnaryCall(call, request);
} }
public AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) public AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{ {
var call = CreateCall(__ServiceName, __Method_DivMany, headers, deadline); var call = CreateCall(__Method_DivMany, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call, cancellationToken); return Calls.AsyncDuplexStreamingCall(call);
}
public AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(CallOptions options)
{
var call = CreateCall(__Method_DivMany, options);
return Calls.AsyncDuplexStreamingCall(call);
} }
public AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) public AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{ {
var call = CreateCall(__ServiceName, __Method_Fib, headers, deadline); var call = CreateCall(__Method_Fib, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncServerStreamingCall(call, request, cancellationToken); return Calls.AsyncServerStreamingCall(call, request);
}
public AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, CallOptions options)
{
var call = CreateCall(__Method_Fib, options);
return Calls.AsyncServerStreamingCall(call, request);
} }
public AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) public AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{ {
var call = CreateCall(__ServiceName, __Method_Sum, headers, deadline); var call = CreateCall(__Method_Sum, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncClientStreamingCall(call, cancellationToken); return Calls.AsyncClientStreamingCall(call);
}
public AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(CallOptions options)
{
var call = CreateCall(__Method_Sum, options);
return Calls.AsyncClientStreamingCall(call);
} }
} }

@ -17,6 +17,7 @@ namespace Grpc.Health.V1Alpha {
static readonly Method<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckResponse> __Method_Check = new Method<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckResponse>( static readonly Method<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckResponse> __Method_Check = new Method<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckResponse>(
MethodType.Unary, MethodType.Unary,
__ServiceName,
"Check", "Check",
__Marshaller_HealthCheckRequest, __Marshaller_HealthCheckRequest,
__Marshaller_HealthCheckResponse); __Marshaller_HealthCheckResponse);
@ -25,7 +26,9 @@ namespace Grpc.Health.V1Alpha {
public interface IHealthClient public interface IHealthClient
{ {
global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, CallOptions options);
AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, CallOptions options);
} }
// server-side interface // server-side interface
@ -42,13 +45,23 @@ namespace Grpc.Health.V1Alpha {
} }
public global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) public global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{ {
var call = CreateCall(__ServiceName, __Method_Check, headers, deadline); var call = CreateCall(__Method_Check, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request, cancellationToken); return Calls.BlockingUnaryCall(call, request);
}
public global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, CallOptions options)
{
var call = CreateCall(__Method_Check, options);
return Calls.BlockingUnaryCall(call, request);
} }
public AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) public AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{ {
var call = CreateCall(__ServiceName, __Method_Check, headers, deadline); var call = CreateCall(__Method_Check, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request, cancellationToken); return Calls.AsyncUnaryCall(call, request);
}
public AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, CallOptions options)
{
var call = CreateCall(__Method_Check, options);
return Calls.AsyncUnaryCall(call, request);
} }
} }

@ -22,36 +22,42 @@ namespace grpc.testing {
static readonly Method<global::grpc.testing.Empty, global::grpc.testing.Empty> __Method_EmptyCall = new Method<global::grpc.testing.Empty, global::grpc.testing.Empty>( static readonly Method<global::grpc.testing.Empty, global::grpc.testing.Empty> __Method_EmptyCall = new Method<global::grpc.testing.Empty, global::grpc.testing.Empty>(
MethodType.Unary, MethodType.Unary,
__ServiceName,
"EmptyCall", "EmptyCall",
__Marshaller_Empty, __Marshaller_Empty,
__Marshaller_Empty); __Marshaller_Empty);
static readonly Method<global::grpc.testing.SimpleRequest, global::grpc.testing.SimpleResponse> __Method_UnaryCall = new Method<global::grpc.testing.SimpleRequest, global::grpc.testing.SimpleResponse>( static readonly Method<global::grpc.testing.SimpleRequest, global::grpc.testing.SimpleResponse> __Method_UnaryCall = new Method<global::grpc.testing.SimpleRequest, global::grpc.testing.SimpleResponse>(
MethodType.Unary, MethodType.Unary,
__ServiceName,
"UnaryCall", "UnaryCall",
__Marshaller_SimpleRequest, __Marshaller_SimpleRequest,
__Marshaller_SimpleResponse); __Marshaller_SimpleResponse);
static readonly Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> __Method_StreamingOutputCall = new Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse>( static readonly Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> __Method_StreamingOutputCall = new Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse>(
MethodType.ServerStreaming, MethodType.ServerStreaming,
__ServiceName,
"StreamingOutputCall", "StreamingOutputCall",
__Marshaller_StreamingOutputCallRequest, __Marshaller_StreamingOutputCallRequest,
__Marshaller_StreamingOutputCallResponse); __Marshaller_StreamingOutputCallResponse);
static readonly Method<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> __Method_StreamingInputCall = new Method<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse>( static readonly Method<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> __Method_StreamingInputCall = new Method<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse>(
MethodType.ClientStreaming, MethodType.ClientStreaming,
__ServiceName,
"StreamingInputCall", "StreamingInputCall",
__Marshaller_StreamingInputCallRequest, __Marshaller_StreamingInputCallRequest,
__Marshaller_StreamingInputCallResponse); __Marshaller_StreamingInputCallResponse);
static readonly Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> __Method_FullDuplexCall = new Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse>( static readonly Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> __Method_FullDuplexCall = new Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse>(
MethodType.DuplexStreaming, MethodType.DuplexStreaming,
__ServiceName,
"FullDuplexCall", "FullDuplexCall",
__Marshaller_StreamingOutputCallRequest, __Marshaller_StreamingOutputCallRequest,
__Marshaller_StreamingOutputCallResponse); __Marshaller_StreamingOutputCallResponse);
static readonly Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> __Method_HalfDuplexCall = new Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse>( static readonly Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> __Method_HalfDuplexCall = new Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse>(
MethodType.DuplexStreaming, MethodType.DuplexStreaming,
__ServiceName,
"HalfDuplexCall", "HalfDuplexCall",
__Marshaller_StreamingOutputCallRequest, __Marshaller_StreamingOutputCallRequest,
__Marshaller_StreamingOutputCallResponse); __Marshaller_StreamingOutputCallResponse);
@ -60,13 +66,21 @@ namespace grpc.testing {
public interface ITestServiceClient public interface ITestServiceClient
{ {
global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, CallOptions options);
AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, CallOptions options);
global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, CallOptions options);
AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, CallOptions options);
AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, CallOptions options);
AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options);
AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options);
AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options);
} }
// server-side interface // server-side interface
@ -88,43 +102,83 @@ namespace grpc.testing {
} }
public global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) public global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{ {
var call = CreateCall(__ServiceName, __Method_EmptyCall, headers, deadline); var call = CreateCall(__Method_EmptyCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request, cancellationToken); return Calls.BlockingUnaryCall(call, request);
}
public global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, CallOptions options)
{
var call = CreateCall(__Method_EmptyCall, options);
return Calls.BlockingUnaryCall(call, request);
} }
public AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) public AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{ {
var call = CreateCall(__ServiceName, __Method_EmptyCall, headers, deadline); var call = CreateCall(__Method_EmptyCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request, cancellationToken); return Calls.AsyncUnaryCall(call, request);
}
public AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, CallOptions options)
{
var call = CreateCall(__Method_EmptyCall, options);
return Calls.AsyncUnaryCall(call, request);
} }
public global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) public global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{ {
var call = CreateCall(__ServiceName, __Method_UnaryCall, headers, deadline); var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request, cancellationToken); return Calls.BlockingUnaryCall(call, request);
}
public global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, CallOptions options)
{
var call = CreateCall(__Method_UnaryCall, options);
return Calls.BlockingUnaryCall(call, request);
} }
public AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) public AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{ {
var call = CreateCall(__ServiceName, __Method_UnaryCall, headers, deadline); var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request, cancellationToken); return Calls.AsyncUnaryCall(call, request);
}
public AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, CallOptions options)
{
var call = CreateCall(__Method_UnaryCall, options);
return Calls.AsyncUnaryCall(call, request);
} }
public AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) public AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{ {
var call = CreateCall(__ServiceName, __Method_StreamingOutputCall, headers, deadline); var call = CreateCall(__Method_StreamingOutputCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncServerStreamingCall(call, request, cancellationToken); return Calls.AsyncServerStreamingCall(call, request);
}
public AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, CallOptions options)
{
var call = CreateCall(__Method_StreamingOutputCall, options);
return Calls.AsyncServerStreamingCall(call, request);
} }
public AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) public AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{ {
var call = CreateCall(__ServiceName, __Method_StreamingInputCall, headers, deadline); var call = CreateCall(__Method_StreamingInputCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncClientStreamingCall(call, cancellationToken); return Calls.AsyncClientStreamingCall(call);
}
public AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options)
{
var call = CreateCall(__Method_StreamingInputCall, options);
return Calls.AsyncClientStreamingCall(call);
} }
public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{ {
var call = CreateCall(__ServiceName, __Method_FullDuplexCall, headers, deadline); var call = CreateCall(__Method_FullDuplexCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call, cancellationToken); return Calls.AsyncDuplexStreamingCall(call);
}
public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options)
{
var call = CreateCall(__Method_FullDuplexCall, options);
return Calls.AsyncDuplexStreamingCall(call);
} }
public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{ {
var call = CreateCall(__ServiceName, __Method_HalfDuplexCall, headers, deadline); var call = CreateCall(__Method_HalfDuplexCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call, cancellationToken); return Calls.AsyncDuplexStreamingCall(call);
}
public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options)
{
var call = CreateCall(__Method_HalfDuplexCall, options);
return Calls.AsyncDuplexStreamingCall(call);
} }
} }

Loading…
Cancel
Save