aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/csharp/Grpc.Core
diff options
context:
space:
mode:
Diffstat (limited to 'src/csharp/Grpc.Core')
-rw-r--r--src/csharp/Grpc.Core/CallOptions.cs46
-rw-r--r--src/csharp/Grpc.Core/Grpc.Core.csproj6
-rw-r--r--src/csharp/Grpc.Core/Grpc.Core.nuspec35
-rw-r--r--src/csharp/Grpc.Core/Internal/AsyncCall.cs107
-rw-r--r--src/csharp/Grpc.Core/Internal/AsyncCallBase.cs41
-rw-r--r--src/csharp/Grpc.Core/Internal/CallFlags.cs60
-rw-r--r--src/csharp/Grpc.Core/Internal/CallSafeHandle.cs25
-rw-r--r--src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs13
-rw-r--r--src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs5
-rw-r--r--src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs22
-rw-r--r--src/csharp/Grpc.Core/Internal/INativeCall.cs17
-rw-r--r--src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs23
-rw-r--r--src/csharp/Grpc.Core/Internal/NativeMethods.cs10
-rw-r--r--src/csharp/Grpc.Core/Profiling/Profilers.cs2
-rw-r--r--src/csharp/Grpc.Core/packages.config2
-rw-r--r--src/csharp/Grpc.Core/project.json3
16 files changed, 235 insertions, 182 deletions
diff --git a/src/csharp/Grpc.Core/CallOptions.cs b/src/csharp/Grpc.Core/CallOptions.cs
index 35548cfc96..ce43dae171 100644
--- a/src/csharp/Grpc.Core/CallOptions.cs
+++ b/src/csharp/Grpc.Core/CallOptions.cs
@@ -50,6 +50,7 @@ namespace Grpc.Core
WriteOptions writeOptions;
ContextPropagationToken propagationToken;
CallCredentials credentials;
+ CallFlags flags;
/// <summary>
/// Creates a new instance of <c>CallOptions</c> struct.
@@ -69,6 +70,7 @@ namespace Grpc.Core
this.writeOptions = writeOptions;
this.propagationToken = propagationToken;
this.credentials = credentials;
+ this.flags = default(CallFlags);
}
/// <summary>
@@ -126,6 +128,24 @@ namespace Grpc.Core
}
/// <summary>
+ /// If <c>true</c> and and channel is in <c>ChannelState.TransientFailure</c>, the call will attempt waiting for the channel to recover
+ /// instead of failing immediately (which is the default "FailFast" semantics).
+ /// Note: experimental API that can change or be removed without any prior notice.
+ /// </summary>
+ public bool IsWaitForReady
+ {
+ get { return (this.flags & CallFlags.WaitForReady) == CallFlags.WaitForReady; }
+ }
+
+ /// <summary>
+ /// Flags to use for this call.
+ /// </summary>
+ internal CallFlags Flags
+ {
+ get { return this.flags; }
+ }
+
+ /// <summary>
/// Returns new instance of <see cref="CallOptions"/> with
/// <c>Headers</c> set to the value provided. Values of all other fields are preserved.
/// </summary>
@@ -198,6 +218,32 @@ namespace Grpc.Core
}
/// <summary>
+ /// Returns new instance of <see cref="CallOptions"/> with "WaitForReady" semantics enabled/disabled.
+ /// <see cref="IsWaitForReady"/>.
+ /// Note: experimental API that can change or be removed without any prior notice.
+ /// </summary>
+ public CallOptions WithWaitForReady(bool waitForReady = true)
+ {
+ if (waitForReady)
+ {
+ return WithFlags(this.flags | CallFlags.WaitForReady);
+ }
+ return WithFlags(this.flags & ~CallFlags.WaitForReady);
+ }
+
+ /// <summary>
+ /// Returns new instance of <see cref="CallOptions"/> with
+ /// <c>Flags</c> set to the value provided. Values of all other fields are preserved.
+ /// </summary>
+ /// <param name="flags">The call flags.</param>
+ internal CallOptions WithFlags(CallFlags flags)
+ {
+ var newOptions = this;
+ newOptions.flags = flags;
+ return newOptions;
+ }
+
+ /// <summary>
/// Returns a new instance of <see cref="CallOptions"/> with
/// all previously unset values set to their defaults and deadline and cancellation
/// token propagated when appropriate.
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index d315e6d667..5bfb978ca6 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -40,7 +40,7 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Interactive.Async">
- <HintPath>..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll</HintPath>
+ <HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -140,9 +140,9 @@
<Compile Include="Logging\LogLevelFilterLogger.cs" />
<Compile Include="Internal\RequestCallContextSafeHandle.cs" />
<Compile Include="Utils\TaskUtils.cs" />
+ <Compile Include="Internal\CallFlags.cs" />
</ItemGroup>
<ItemGroup>
- <None Include="Grpc.Core.nuspec" />
<None Include="Grpc.Core.project.json" />
<None Include="packages.config" />
</ItemGroup>
@@ -154,4 +154,4 @@
<Link>roots.pem</Link>
</EmbeddedResource>
</ItemGroup>
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.Core/Grpc.Core.nuspec b/src/csharp/Grpc.Core/Grpc.Core.nuspec
deleted file mode 100644
index a8459c4d9c..0000000000
--- a/src/csharp/Grpc.Core/Grpc.Core.nuspec
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<package>
- <metadata>
- <id>Grpc.Core</id>
- <title>gRPC C# Core</title>
- <summary>Core C# implementation of gRPC - an RPC library and framework</summary>
- <description>Core C# implementation of gRPC - an RPC library and framework. See project site for more info.</description>
- <version>$version$</version>
- <authors>Google Inc.</authors>
- <owners>grpc-packages</owners>
- <licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
- <projectUrl>https://github.com/grpc/grpc</projectUrl>
- <requireLicenseAcceptance>false</requireLicenseAcceptance>
- <releaseNotes>Release $version$ of gRPC C#</releaseNotes>
- <copyright>Copyright 2015, Google Inc.</copyright>
- <tags>gRPC RPC Protocol HTTP/2</tags>
- <dependencies>
- <dependency id="System.Interactive.Async" version="3.0.0" />
- </dependencies>
- </metadata>
- <files>
- <file src="bin/ReleaseSigned/Grpc.Core.dll" target="lib/net45" />
- <file src="bin/ReleaseSigned/Grpc.Core.pdb" target="lib/net45" />
- <file src="bin/ReleaseSigned/Grpc.Core.xml" target="lib/net45" />
- <file src="**\*.cs" target="src" />
- <file src="Grpc.Core.targets" target="\build\net45\Grpc.Core.targets" />
- <!-- without backslashes in the the source path, nuget won't copy the files -->
- <file src="..\nativelibs\windows_x86\grpc_csharp_ext.dll" target="/runtimes/win/native/grpc_csharp_ext.x86.dll" />
- <file src="..\nativelibs\windows_x64\grpc_csharp_ext.dll" target="/runtimes/win/native/grpc_csharp_ext.x64.dll" />
- <file src="..\nativelibs\linux_x86\libgrpc_csharp_ext.so" target="/runtimes/linux/native/libgrpc_csharp_ext.x86.so" />
- <file src="..\nativelibs\linux_x64\libgrpc_csharp_ext.so" target="/runtimes/linux/native/libgrpc_csharp_ext.x64.so" />
- <file src="..\nativelibs\macosx_x86\libgrpc_csharp_ext.dylib" target="/runtimes/osx/native/libgrpc_csharp_ext.x86.dylib" />
- <file src="..\nativelibs\macosx_x64\libgrpc_csharp_ext.dylib" target="/runtimes/osx/native/libgrpc_csharp_ext.x64.dylib" />
- </files>
-</package>
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
index 5e61e9ec12..1f738a3b6f 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
@@ -106,7 +106,7 @@ namespace Grpc.Core.Internal
using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers))
using (var ctx = BatchContextSafeHandle.Create())
{
- call.StartUnary(ctx, payload, metadataArray, GetWriteFlagsForCall());
+ call.StartUnary(ctx, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags);
var ev = cq.Pluck(ctx.Handle);
@@ -150,7 +150,7 @@ namespace Grpc.Core.Internal
unaryResponseTcs = new TaskCompletionSource<TResponse>();
using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers))
{
- call.StartUnary(HandleUnaryResponse, payload, metadataArray, GetWriteFlagsForCall());
+ call.StartUnary(HandleUnaryResponse, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags);
}
return unaryResponseTcs.Task;
}
@@ -174,7 +174,7 @@ namespace Grpc.Core.Internal
unaryResponseTcs = new TaskCompletionSource<TResponse>();
using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers))
{
- call.StartClientStreaming(HandleUnaryResponse, metadataArray);
+ call.StartClientStreaming(HandleUnaryResponse, metadataArray, details.Options.Flags);
}
return unaryResponseTcs.Task;
@@ -200,7 +200,7 @@ namespace Grpc.Core.Internal
streamingResponseCallFinishedTcs = new TaskCompletionSource<object>();
using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers))
{
- call.StartServerStreaming(HandleFinished, payload, metadataArray, GetWriteFlagsForCall());
+ call.StartServerStreaming(HandleFinished, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags);
}
call.StartReceiveInitialMetadata(HandleReceivedResponseHeaders);
}
@@ -222,7 +222,7 @@ namespace Grpc.Core.Internal
streamingResponseCallFinishedTcs = new TaskCompletionSource<object>();
using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers))
{
- call.StartDuplexStreaming(HandleFinished, metadataArray);
+ call.StartDuplexStreaming(HandleFinished, metadataArray, details.Options.Flags);
}
call.StartReceiveInitialMetadata(HandleReceivedResponseHeaders);
}
@@ -388,35 +388,29 @@ namespace Grpc.Core.Internal
private void Initialize(CompletionQueueSafeHandle cq)
{
- using (Profilers.ForCurrentThread().NewScope("AsyncCall.Initialize"))
- {
- var call = CreateNativeCall(cq);
+ var call = CreateNativeCall(cq);
- details.Channel.AddCallReference(this);
- InitializeInternal(call);
- RegisterCancellationCallback();
- }
+ details.Channel.AddCallReference(this);
+ InitializeInternal(call);
+ RegisterCancellationCallback();
}
private INativeCall CreateNativeCall(CompletionQueueSafeHandle cq)
{
- using (Profilers.ForCurrentThread().NewScope("AsyncCall.CreateNativeCall"))
- {
- if (injectedNativeCall != null)
- {
- return injectedNativeCall; // allows injecting a mock INativeCall in tests.
- }
+ if (injectedNativeCall != null)
+ {
+ return injectedNativeCall; // allows injecting a mock INativeCall in tests.
+ }
- var parentCall = details.Options.PropagationToken != null ? details.Options.PropagationToken.ParentCall : CallSafeHandle.NullInstance;
+ var parentCall = details.Options.PropagationToken != null ? details.Options.PropagationToken.ParentCall : CallSafeHandle.NullInstance;
- var credentials = details.Options.Credentials;
- using (var nativeCredentials = credentials != null ? credentials.ToNativeCredentials() : null)
- {
- var result = details.Channel.Handle.CreateCall(
- parentCall, ContextPropagationToken.DefaultMask, cq,
- details.Method, details.Host, Timespec.FromDateTime(details.Options.Deadline.Value), nativeCredentials);
- return result;
- }
+ var credentials = details.Options.Credentials;
+ using (var nativeCredentials = credentials != null ? credentials.ToNativeCredentials() : null)
+ {
+ var result = details.Channel.Handle.CreateCall(
+ parentCall, ContextPropagationToken.DefaultMask, cq,
+ details.Method, details.Host, Timespec.FromDateTime(details.Options.Deadline.Value), nativeCredentials);
+ return result;
}
}
@@ -456,47 +450,44 @@ namespace Grpc.Core.Internal
// NOTE: because this event is a result of batch containing GRPC_OP_RECV_STATUS_ON_CLIENT,
// success will be always set to true.
- using (Profilers.ForCurrentThread().NewScope("AsyncCall.HandleUnaryResponse"))
+ TaskCompletionSource<object> delayedStreamingWriteTcs = null;
+ TResponse msg = default(TResponse);
+ var deserializeException = TryDeserialize(receivedMessage, out msg);
+
+ lock (myLock)
{
- TaskCompletionSource<object> delayedStreamingWriteTcs = null;
- TResponse msg = default(TResponse);
- var deserializeException = TryDeserialize(receivedMessage, out msg);
+ finished = true;
- lock (myLock)
+ if (deserializeException != null && receivedStatus.Status.StatusCode == StatusCode.OK)
{
- finished = true;
-
- if (deserializeException != null && receivedStatus.Status.StatusCode == StatusCode.OK)
- {
- receivedStatus = new ClientSideStatus(DeserializeResponseFailureStatus, receivedStatus.Trailers);
- }
- finishedStatus = receivedStatus;
-
- if (isStreamingWriteCompletionDelayed)
- {
- delayedStreamingWriteTcs = streamingWriteTcs;
- streamingWriteTcs = null;
- }
-
- ReleaseResourcesIfPossible();
+ receivedStatus = new ClientSideStatus(DeserializeResponseFailureStatus, receivedStatus.Trailers);
}
+ finishedStatus = receivedStatus;
- responseHeadersTcs.SetResult(responseHeaders);
-
- if (delayedStreamingWriteTcs != null)
+ if (isStreamingWriteCompletionDelayed)
{
- delayedStreamingWriteTcs.SetException(GetRpcExceptionClientOnly());
+ delayedStreamingWriteTcs = streamingWriteTcs;
+ streamingWriteTcs = null;
}
- var status = receivedStatus.Status;
- if (status.StatusCode != StatusCode.OK)
- {
- unaryResponseTcs.SetException(new RpcException(status));
- return;
- }
+ ReleaseResourcesIfPossible();
+ }
+
+ responseHeadersTcs.SetResult(responseHeaders);
- unaryResponseTcs.SetResult(msg);
+ if (delayedStreamingWriteTcs != null)
+ {
+ delayedStreamingWriteTcs.SetException(GetRpcExceptionClientOnly());
+ }
+
+ var status = receivedStatus.Status;
+ if (status.StatusCode != StatusCode.OK)
+ {
+ unaryResponseTcs.SetException(new RpcException(status));
+ return;
}
+
+ unaryResponseTcs.SetResult(msg);
}
/// <summary>
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
index 9f9d260e7e..8668903f6e 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
@@ -181,19 +181,16 @@ namespace Grpc.Core.Internal
/// </summary>
protected bool ReleaseResourcesIfPossible()
{
- using (Profilers.ForCurrentThread().NewScope("AsyncCallBase.ReleaseResourcesIfPossible"))
+ if (!disposed && call != null)
{
- if (!disposed && call != null)
+ bool noMoreSendCompletions = streamingWriteTcs == null && (halfcloseRequested || cancelRequested || finished);
+ if (noMoreSendCompletions && readingDone && finished)
{
- bool noMoreSendCompletions = streamingWriteTcs == null && (halfcloseRequested || cancelRequested || finished);
- if (noMoreSendCompletions && readingDone && finished)
- {
- ReleaseResources();
- return true;
- }
+ ReleaseResources();
+ return true;
}
- return false;
}
+ return false;
}
protected abstract bool IsClient
@@ -229,28 +226,20 @@ namespace Grpc.Core.Internal
protected byte[] UnsafeSerialize(TWrite msg)
{
- using (Profilers.ForCurrentThread().NewScope("AsyncCallBase.UnsafeSerialize"))
- {
- return serializer(msg);
- }
+ return serializer(msg);
}
protected Exception TryDeserialize(byte[] payload, out TRead msg)
{
- using (Profilers.ForCurrentThread().NewScope("AsyncCallBase.TryDeserialize"))
+ try
{
- try
- {
-
- msg = deserializer(payload);
- return null;
-
- }
- catch (Exception e)
- {
- msg = default(TRead);
- return e;
- }
+ msg = deserializer(payload);
+ return null;
+ }
+ catch (Exception e)
+ {
+ msg = default(TRead);
+ return e;
}
}
diff --git a/src/csharp/Grpc.Core/Internal/CallFlags.cs b/src/csharp/Grpc.Core/Internal/CallFlags.cs
new file mode 100644
index 0000000000..454fa9b1f4
--- /dev/null
+++ b/src/csharp/Grpc.Core/Internal/CallFlags.cs
@@ -0,0 +1,60 @@
+#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;
+
+namespace Grpc.Core.Internal
+{
+ /// <summary>
+ /// Flags to enable special call behaviors (client-side only).
+ /// </summary>
+ [Flags]
+ internal enum CallFlags
+ {
+ /// <summary>
+ /// The call is idempotent (retrying the call doesn't change the outcome of the operation).
+ /// </summary>
+ IdempotentRequest = 0x10,
+
+ /// <summary>
+ /// If channel is in <c>ChannelState.TransientFailure</c>, attempt waiting for the channel to recover
+ /// instead of failing the call immediately.
+ /// </summary>
+ WaitForReady = 0x20,
+
+ /// <summary>
+ /// The call is cacheable. gRPC is free to use GET verb */
+ /// </summary>
+ CacheableRequest = 0x40
+ }
+}
diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
index 82361f5797..6bfcc7fa74 100644
--- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
@@ -63,53 +63,50 @@ namespace Grpc.Core.Internal
Native.grpcsharp_call_set_credentials(this, credentials).CheckOk();
}
- public void StartUnary(UnaryResponseClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags)
+ public void StartUnary(UnaryResponseClientHandler callback, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags)
{
using (completionQueue.NewScope())
{
var ctx = BatchContextSafeHandle.Create();
completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient(), context.GetReceivedMessage(), context.GetReceivedInitialMetadata()));
- Native.grpcsharp_call_start_unary(this, ctx, payload, new UIntPtr((ulong)payload.Length), metadataArray, writeFlags)
+ Native.grpcsharp_call_start_unary(this, ctx, payload, new UIntPtr((ulong)payload.Length), writeFlags, metadataArray, callFlags)
.CheckOk();
}
}
- public void StartUnary(BatchContextSafeHandle ctx, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags)
+ public void StartUnary(BatchContextSafeHandle ctx, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags)
{
- using (Profilers.ForCurrentThread().NewScope("CallSafeHandle.StartUnary"))
- {
- Native.grpcsharp_call_start_unary(this, ctx, payload, new UIntPtr((ulong)payload.Length), metadataArray, writeFlags)
- .CheckOk();
- }
+ Native.grpcsharp_call_start_unary(this, ctx, payload, new UIntPtr((ulong)payload.Length), writeFlags, metadataArray, callFlags)
+ .CheckOk();
}
- public void StartClientStreaming(UnaryResponseClientHandler callback, MetadataArraySafeHandle metadataArray)
+ public void StartClientStreaming(UnaryResponseClientHandler callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags)
{
using (completionQueue.NewScope())
{
var ctx = BatchContextSafeHandle.Create();
completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient(), context.GetReceivedMessage(), context.GetReceivedInitialMetadata()));
- Native.grpcsharp_call_start_client_streaming(this, ctx, metadataArray).CheckOk();
+ Native.grpcsharp_call_start_client_streaming(this, ctx, metadataArray, callFlags).CheckOk();
}
}
- public void StartServerStreaming(ReceivedStatusOnClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags)
+ public void StartServerStreaming(ReceivedStatusOnClientHandler callback, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags)
{
using (completionQueue.NewScope())
{
var ctx = BatchContextSafeHandle.Create();
completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient()));
- Native.grpcsharp_call_start_server_streaming(this, ctx, payload, new UIntPtr((ulong)payload.Length), metadataArray, writeFlags).CheckOk();
+ Native.grpcsharp_call_start_server_streaming(this, ctx, payload, new UIntPtr((ulong)payload.Length), writeFlags, metadataArray, callFlags).CheckOk();
}
}
- public void StartDuplexStreaming(ReceivedStatusOnClientHandler callback, MetadataArraySafeHandle metadataArray)
+ public void StartDuplexStreaming(ReceivedStatusOnClientHandler callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags)
{
using (completionQueue.NewScope())
{
var ctx = BatchContextSafeHandle.Create();
completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient()));
- Native.grpcsharp_call_start_duplex_streaming(this, ctx, metadataArray).CheckOk();
+ Native.grpcsharp_call_start_duplex_streaming(this, ctx, metadataArray, callFlags).CheckOk();
}
}
diff --git a/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
index 62864dff0c..0fb6360a23 100644
--- a/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
@@ -65,16 +65,13 @@ namespace Grpc.Core.Internal
public CallSafeHandle CreateCall(CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline, CallCredentialsSafeHandle credentials)
{
- using (Profilers.ForCurrentThread().NewScope("ChannelSafeHandle.CreateCall"))
+ var result = Native.grpcsharp_channel_create_call(this, parentCall, propagationMask, cq, method, host, deadline);
+ if (credentials != null)
{
- var result = Native.grpcsharp_channel_create_call(this, parentCall, propagationMask, cq, method, host, deadline);
- if (credentials != null)
- {
- result.SetCredentials(credentials);
- }
- result.Initialize(cq);
- return result;
+ result.SetCredentials(credentials);
}
+ result.Initialize(cq);
+ return result;
}
public ChannelState CheckConnectivityState(bool tryToConnect)
diff --git a/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs
index 46f5624223..6c9a31921e 100644
--- a/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs
@@ -70,10 +70,7 @@ namespace Grpc.Core.Internal
public CompletionQueueEvent Pluck(IntPtr tag)
{
- using (Profilers.ForCurrentThread().NewScope("CompletionQueueSafeHandle.Pluck"))
- {
- return Native.grpcsharp_completion_queue_pluck(this, tag);
- }
+ return Native.grpcsharp_completion_queue_pluck(this, tag);
}
/// <summary>
diff --git a/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
index a446c1f99f..25a6589f11 100644
--- a/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
+++ b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
@@ -37,6 +37,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core.Logging;
+using Grpc.Core.Profiling;
using Grpc.Core.Utils;
namespace Grpc.Core.Internal
@@ -54,6 +55,8 @@ namespace Grpc.Core.Internal
readonly int poolSize;
readonly int completionQueueCount;
+ readonly List<BasicProfiler> threadProfilers = new List<BasicProfiler>(); // profilers assigned to threadpool threads
+
bool stopRequested;
IReadOnlyCollection<CompletionQueueSafeHandle> completionQueues;
@@ -82,7 +85,8 @@ namespace Grpc.Core.Internal
for (int i = 0; i < poolSize; i++)
{
- threads.Add(CreateAndStartThread(i));
+ var optionalProfiler = i < threadProfilers.Count ? threadProfilers[i] : null;
+ threads.Add(CreateAndStartThread(i, optionalProfiler));
}
}
}
@@ -111,6 +115,11 @@ namespace Grpc.Core.Internal
{
cq.Dispose();
}
+
+ for (int i = 0; i < threadProfilers.Count; i++)
+ {
+ threadProfilers[i].Dump(string.Format("grpc_trace_thread_{0}.txt", i));
+ }
});
}
@@ -137,12 +146,12 @@ namespace Grpc.Core.Internal
}
}
- private Thread CreateAndStartThread(int threadIndex)
+ private Thread CreateAndStartThread(int threadIndex, IProfiler optionalProfiler)
{
var cqIndex = threadIndex % completionQueues.Count;
var cq = completionQueues.ElementAt(cqIndex);
- var thread = new Thread(new ThreadStart(() => RunHandlerLoop(cq)));
+ var thread = new Thread(new ThreadStart(() => RunHandlerLoop(cq, optionalProfiler)));
thread.IsBackground = true;
thread.Name = string.Format("grpc {0} (cq {1})", threadIndex, cqIndex);
thread.Start();
@@ -153,8 +162,13 @@ namespace Grpc.Core.Internal
/// <summary>
/// Body of the polling thread.
/// </summary>
- private void RunHandlerLoop(CompletionQueueSafeHandle cq)
+ private void RunHandlerLoop(CompletionQueueSafeHandle cq, IProfiler optionalProfiler)
{
+ if (optionalProfiler != null)
+ {
+ Profilers.SetForCurrentThread(optionalProfiler);
+ }
+
CompletionQueueEvent ev;
do
{
diff --git a/src/csharp/Grpc.Core/Internal/INativeCall.cs b/src/csharp/Grpc.Core/Internal/INativeCall.cs
index cd3719cb50..94fbb08feb 100644
--- a/src/csharp/Grpc.Core/Internal/INativeCall.cs
+++ b/src/csharp/Grpc.Core/Internal/INativeCall.cs
@@ -31,6 +31,7 @@
#endregion
using System;
+using Grpc.Core;
namespace Grpc.Core.Internal
{
@@ -54,19 +55,19 @@ namespace Grpc.Core.Internal
{
void Cancel();
- void CancelWithStatus(Grpc.Core.Status status);
+ void CancelWithStatus(Status status);
string GetPeer();
- void StartUnary(UnaryResponseClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, Grpc.Core.WriteFlags writeFlags);
+ void StartUnary(UnaryResponseClientHandler callback, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags);
- void StartUnary(BatchContextSafeHandle ctx, byte[] payload, MetadataArraySafeHandle metadataArray, Grpc.Core.WriteFlags writeFlags);
+ void StartUnary(BatchContextSafeHandle ctx, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags);
- void StartClientStreaming(UnaryResponseClientHandler callback, MetadataArraySafeHandle metadataArray);
+ void StartClientStreaming(UnaryResponseClientHandler callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags);
- void StartServerStreaming(ReceivedStatusOnClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, Grpc.Core.WriteFlags writeFlags);
+ void StartServerStreaming(ReceivedStatusOnClientHandler callback, byte[] payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags);
- void StartDuplexStreaming(ReceivedStatusOnClientHandler callback, MetadataArraySafeHandle metadataArray);
+ void StartDuplexStreaming(ReceivedStatusOnClientHandler callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags);
void StartReceiveMessage(ReceivedMessageHandler callback);
@@ -74,11 +75,11 @@ namespace Grpc.Core.Internal
void StartSendInitialMetadata(SendCompletionHandler callback, MetadataArraySafeHandle metadataArray);
- void StartSendMessage(SendCompletionHandler callback, byte[] payload, Grpc.Core.WriteFlags writeFlags, bool sendEmptyInitialMetadata);
+ void StartSendMessage(SendCompletionHandler callback, byte[] payload, WriteFlags writeFlags, bool sendEmptyInitialMetadata);
void StartSendCloseFromClient(SendCompletionHandler callback);
- void StartSendStatusFromServer(SendCompletionHandler callback, Grpc.Core.Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, byte[] optionalPayload, Grpc.Core.WriteFlags writeFlags);
+ void StartSendStatusFromServer(SendCompletionHandler callback, Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, byte[] optionalPayload, WriteFlags writeFlags);
void StartServerSide(ReceivedCloseOnServerHandler callback);
}
diff --git a/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
index dc9f62fdab..05dda5b148 100644
--- a/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
@@ -48,22 +48,19 @@ namespace Grpc.Core.Internal
public static MetadataArraySafeHandle Create(Metadata metadata)
{
- using (Profilers.ForCurrentThread().NewScope("MetadataArraySafeHandle.Create"))
+ if (metadata.Count == 0)
{
- if (metadata.Count == 0)
- {
- return new MetadataArraySafeHandle();
- }
+ return new MetadataArraySafeHandle();
+ }
- // TODO(jtattermusch): we might wanna check that the metadata is readonly
- var metadataArray = Native.grpcsharp_metadata_array_create(new UIntPtr((ulong)metadata.Count));
- for (int i = 0; i < metadata.Count; i++)
- {
- var valueBytes = metadata[i].GetSerializedValueUnsafe();
- Native.grpcsharp_metadata_array_add(metadataArray, metadata[i].Key, valueBytes, new UIntPtr((ulong)valueBytes.Length));
- }
- return metadataArray;
+ // TODO(jtattermusch): we might wanna check that the metadata is readonly
+ var metadataArray = Native.grpcsharp_metadata_array_create(new UIntPtr((ulong)metadata.Count));
+ for (int i = 0; i < metadata.Count; i++)
+ {
+ var valueBytes = metadata[i].GetSerializedValueUnsafe();
+ Native.grpcsharp_metadata_array_add(metadataArray, metadata[i].Key, valueBytes, new UIntPtr((ulong)valueBytes.Length));
}
+ return metadataArray;
}
/// <summary>
diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs
index 40ba7e30cb..ce38e37093 100644
--- a/src/csharp/Grpc.Core/Internal/NativeMethods.cs
+++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs
@@ -325,14 +325,14 @@ namespace Grpc.Core.Internal
public delegate CallError grpcsharp_call_cancel_delegate(CallSafeHandle call);
public delegate CallError grpcsharp_call_cancel_with_status_delegate(CallSafeHandle call, StatusCode status, string description);
public delegate CallError grpcsharp_call_start_unary_delegate(CallSafeHandle call,
- BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags);
+ BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags);
public delegate CallError grpcsharp_call_start_client_streaming_delegate(CallSafeHandle call,
- BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray);
+ BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags);
public delegate CallError grpcsharp_call_start_server_streaming_delegate(CallSafeHandle call,
- BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen,
- MetadataArraySafeHandle metadataArray, WriteFlags writeFlags);
+ BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags,
+ MetadataArraySafeHandle metadataArray, CallFlags metadataFlags);
public delegate CallError grpcsharp_call_start_duplex_streaming_delegate(CallSafeHandle call,
- BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray);
+ BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags);
public delegate CallError grpcsharp_call_send_message_delegate(CallSafeHandle call,
BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, bool sendEmptyInitialMetadata);
public delegate CallError grpcsharp_call_send_close_from_client_delegate(CallSafeHandle call,
diff --git a/src/csharp/Grpc.Core/Profiling/Profilers.cs b/src/csharp/Grpc.Core/Profiling/Profilers.cs
index aa0d96c0e0..6afabff6a7 100644
--- a/src/csharp/Grpc.Core/Profiling/Profilers.cs
+++ b/src/csharp/Grpc.Core/Profiling/Profilers.cs
@@ -80,7 +80,7 @@ namespace Grpc.Core.Profiling
ProfilerEntry[] entries;
int count;
- public BasicProfiler() : this(1024*1024)
+ public BasicProfiler() : this(20*1024*1024)
{
}
diff --git a/src/csharp/Grpc.Core/packages.config b/src/csharp/Grpc.Core/packages.config
index 6514774021..53cfad52f0 100644
--- a/src/csharp/Grpc.Core/packages.config
+++ b/src/csharp/Grpc.Core/packages.config
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" />
+ <package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Core/project.json b/src/csharp/Grpc.Core/project.json
index aa1e4cc7fb..4405ecc5a2 100644
--- a/src/csharp/Grpc.Core/project.json
+++ b/src/csharp/Grpc.Core/project.json
@@ -27,11 +27,10 @@
"embed": [ "../../../etc/roots.pem" ],
"define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk",
- "publicSign": true,
"xmlDoc": true
},
"dependencies": {
- "System.Interactive.Async": "3.0.0"
+ "System.Interactive.Async": "3.1.1"
},
"frameworks": {
"net45": { },