Exemple #1
0
        /// <summary>
        /// Starts a unary request - streamed response call.
        /// </summary>
        public void StartServerStreamingCall(TRequest msg)
        {
            lock (myLock)
            {
                bool callStartedOk = false;
                try
                {
                    GrpcPreconditions.CheckState(!started);
                    started = true;

                    Initialize(details.Channel.CompletionQueue);

                    halfcloseRequested = true;

                    using (var serializationScope = DefaultSerializationContext.GetInitializedThreadLocalScope())
                    {
                        var payload = UnsafeSerialize(msg, serializationScope.Context);
                        streamingResponseCallFinishedTcs = new TaskCompletionSource <object>();
                        using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers))
                        {
                            call.StartServerStreaming(ReceivedStatusOnClientCallback, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags);
                            callStartedOk = true;
                        }
                    }
                    call.StartReceiveInitialMetadata(ReceivedResponseHeadersCallback);
                }
                finally
                {
                    if (!callStartedOk)
                    {
                        OnFailedToStartCallLocked();
                    }
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Sends call result status, indicating we are done with writes.
        /// Sending a status different from StatusCode.OK will also implicitly cancel the call.
        /// </summary>
        public Task SendStatusFromServerAsync(Status status, Metadata trailers, ResponseWithFlags?optionalWrite)
        {
            using (var serializationScope = DefaultSerializationContext.GetInitializedThreadLocalScope())
            {
                var payload    = optionalWrite.HasValue ? UnsafeSerialize(optionalWrite.Value.Response, serializationScope.Context) : SliceBufferSafeHandle.NullInstance;
                var writeFlags = optionalWrite.HasValue ? optionalWrite.Value.WriteFlags : default(WriteFlags);

                lock (myLock)
                {
                    GrpcPreconditions.CheckState(started);
                    GrpcPreconditions.CheckState(!disposed);
                    GrpcPreconditions.CheckState(!halfcloseRequested, "Can only send status from server once.");

                    using (var metadataArray = MetadataArraySafeHandle.Create(trailers))
                    {
                        call.StartSendStatusFromServer(SendStatusFromServerCompletionCallback, status, metadataArray, !initialMetadataSent,
                                                       payload, writeFlags);
                    }
                    halfcloseRequested      = true;
                    initialMetadataSent     = true;
                    sendStatusFromServerTcs = new TaskCompletionSource <object>();
                    if (optionalWrite.HasValue)
                    {
                        streamingWritesCounter++;
                    }
                    return(sendStatusFromServerTcs.Task);
                }
            }
        }
Exemple #3
0
        protected byte[] UnsafeSerialize(TWrite msg)
        {
            DefaultSerializationContext context = null;

            try
            {
                context = DefaultSerializationContext.GetInitializedThreadLocal();
                serializer(msg, context);
                return(context.GetPayload());
            }
            finally
            {
                context?.Reset();
            }
        }
Exemple #4
0
        /// <summary>
        /// Initiates sending a message. Only one send operation can be active at a time.
        /// </summary>
        protected Task SendMessageInternalAsync(TWrite msg, WriteFlags writeFlags)
        {
            using (var serializationScope = DefaultSerializationContext.GetInitializedThreadLocalScope())
            {
                var payload = UnsafeSerialize(msg, serializationScope.Context);
                lock (myLock)
                {
                    GrpcPreconditions.CheckState(started);
                    var earlyResult = CheckSendAllowedOrEarlyResult();
                    if (earlyResult != null)
                    {
                        return(earlyResult);
                    }

                    call.StartSendMessage(SendCompletionCallback, payload, writeFlags, !initialMetadataSent);

                    initialMetadataSent = true;
                    streamingWritesCounter++;
                    streamingWriteTcs = new TaskCompletionSource <object>();
                    return(streamingWriteTcs.Task);
                }
            }
        }
Exemple #5
0
        /// <summary>
        /// Starts a unary request - unary response call.
        /// </summary>
        public Task <TResponse> UnaryCallAsync(TRequest msg)
        {
            lock (myLock)
            {
                bool callStartedOk = false;
                try
                {
                    GrpcPreconditions.CheckState(!started);
                    started = true;

                    Initialize(details.Channel.CompletionQueue);

                    halfcloseRequested = true;
                    readingDone        = true;

                    using (var serializationScope = DefaultSerializationContext.GetInitializedThreadLocalScope())
                    {
                        var payload = UnsafeSerialize(msg, serializationScope.Context);
                        unaryResponseTcs = new TaskCompletionSource <TResponse>();
                        using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers))
                        {
                            call.StartUnary(UnaryResponseClientCallback, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags);
                            callStartedOk = true;
                        }
                    }

                    return(unaryResponseTcs.Task);
                }
                finally
                {
                    if (!callStartedOk)
                    {
                        OnFailedToStartCallLocked();
                    }
                }
            }
        }
Exemple #6
0
 // runs the serializer, propagating any exceptions being thrown without modifying them
 protected SliceBufferSafeHandle UnsafeSerialize(TWrite msg, DefaultSerializationContext context)
 {
     serializer(msg, context);
     return(context.GetPayload());
 }
Exemple #7
0
        // 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.
        /// <summary>
        /// Blocking unary request - unary response call.
        /// </summary>
        public TResponse UnaryCall(TRequest msg)
        {
            var profiler = Profilers.ForCurrentThread();

            using (profiler.NewScope("AsyncCall.UnaryCall"))
                using (CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.CreateSync())
                {
                    bool callStartedOk = false;
                    try
                    {
                        unaryResponseTcs = new TaskCompletionSource <TResponse>();

                        lock (myLock)
                        {
                            GrpcPreconditions.CheckState(!started);
                            started = true;
                            Initialize(cq);

                            halfcloseRequested = true;
                            readingDone        = true;
                        }

                        using (var serializationScope = DefaultSerializationContext.GetInitializedThreadLocalScope())
                            using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers))
                            {
                                var payload = UnsafeSerialize(msg, serializationScope.Context); // do before metadata array?
                                var ctx     = details.Channel.Environment.BatchContextPool.Lease();
                                try
                                {
                                    call.StartUnary(ctx, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags);
                                    callStartedOk = true;

                                    var  ev      = cq.Pluck(ctx.Handle);
                                    bool success = (ev.success != 0);
                                    try
                                    {
                                        using (profiler.NewScope("AsyncCall.UnaryCall.HandleBatch"))
                                        {
                                            HandleUnaryResponse(success, ctx.GetReceivedStatusOnClient(), ctx.GetReceivedMessageReader(), ctx.GetReceivedInitialMetadata());
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        Logger.Error(e, "Exception occurred while invoking completion delegate.");
                                    }
                                }
                                finally
                                {
                                    ctx.Recycle();
                                }
                            }
                    }
                    finally
                    {
                        if (!callStartedOk)
                        {
                            lock (myLock)
                            {
                                OnFailedToStartCallLocked();
                            }
                        }
                    }

                    // Once the blocking call returns, the result should be available synchronously.
                    // Note that GetAwaiter().GetResult() doesn't wrap exceptions in AggregateException.
                    return(unaryResponseTcs.Task.GetAwaiter().GetResult());
                }
        }
Exemple #8
0
 public UsageScope(DefaultSerializationContext context)
 {
     this.context = context;
 }
Exemple #9
0
        // 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.
        /// <summary>
        /// Blocking unary request - unary response call.
        /// </summary>
        public TResponse UnaryCall(TRequest msg)
        {
            var profiler = Profilers.ForCurrentThread();

            using (profiler.NewScope("AsyncCall.UnaryCall"))

                // Create a pluckable completion queue for the call. Avoid creating a completion queue when we know the channel has already
                // been shutdown. In such case, the call will fail with ObjectDisposedException immediately anyway and creating / destroying
                // a completion queue would lead to crash if this was the last channel in the application (and thus GrpcEnvironment has been shutdown).
                // See https://github.com/grpc/grpc/issues/19090
                using (CompletionQueueSafeHandle cq = details.Channel.Handle.IsClosed ?  null : CompletionQueueSafeHandle.CreateSync())
                {
                    bool callStartedOk = false;
                    try
                    {
                        unaryResponseTcs = new TaskCompletionSource <TResponse>();

                        lock (myLock)
                        {
                            GrpcPreconditions.CheckState(!started);
                            started = true;
                            Initialize(cq);

                            halfcloseRequested = true;
                            readingDone        = true;
                        }

                        using (var serializationScope = DefaultSerializationContext.GetInitializedThreadLocalScope())
                            using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers))
                            {
                                var payload = UnsafeSerialize(msg, serializationScope.Context); // do before metadata array?
                                var ctx     = details.Channel.Environment.BatchContextPool.Lease();
                                try
                                {
                                    call.StartUnary(ctx, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags);
                                    callStartedOk = true;

                                    var  ev      = cq.Pluck(ctx.Handle);
                                    bool success = (ev.success != 0);
                                    try
                                    {
                                        using (profiler.NewScope("AsyncCall.UnaryCall.HandleBatch"))
                                        {
                                            HandleUnaryResponse(success, ctx.GetReceivedStatusOnClient(), ctx.GetReceivedMessageReader(), ctx.GetReceivedInitialMetadata());
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        Logger.Error(e, "Exception occurred while invoking completion delegate.");
                                    }
                                }
                                finally
                                {
                                    ctx.Recycle();
                                }
                            }
                    }
                    finally
                    {
                        if (!callStartedOk)
                        {
                            lock (myLock)
                            {
                                OnFailedToStartCallLocked();
                            }
                        }
                    }

                    // Once the blocking call returns, the result should be available synchronously.
                    // Note that GetAwaiter().GetResult() doesn't wrap exceptions in AggregateException.
                    return(unaryResponseTcs.Task.GetAwaiter().GetResult());
                }
        }