예제 #1
0
        private void WriteResponseInOrder(IChannelHandlerContext ctx,
                                          ThriftMessage response,
                                          long responseSequenceId)
        {
            // Ensure responses to requests are written in the same order the requests
            // were received.
            lock (_responseMap) {
                long currentResponseId = Interlocked.Read(ref _lastResponseWrittenId) + 1;
                if (responseSequenceId != currentResponseId)
                {
                    // This response is NOT next in line of ordered responses, save it to
                    // be sent later, after responses to all earlier requests have been
                    // sent.
                    _responseMap[responseSequenceId] = response;
                }
                else
                {
                    // This response was next in line, write this response now, and see if
                    // there are others next in line that should be sent now as well.
                    do
                    {
                        ctx.Channel.WriteAndFlushAsync(response).GetAwaiter().GetResult();
                        Interlocked.Increment(ref _lastResponseWrittenId);
                        ++currentResponseId;
                        response = _responseMap.RemoveAndGet(currentResponseId);
                    } while (null != response);

                    // Now that we've written some responses, check if reads should be unblocked
                    if (DispatcherContext.IsChannelReadBlocked(ctx))
                    {
                        long lastRequestSequenceId = Interlocked.Read(ref _dispatcherSequenceId);
                        if (lastRequestSequenceId <= Interlocked.Read(ref _lastResponseWrittenId) + _queuedResponseLimit)
                        {
                            DispatcherContext.UnblockChannelReads(ctx);
                        }
                    }
                }
            }
        }
예제 #2
0
        private long BlockReadingForOrderReponse(IChannelHandlerContext ctx)
        {
            long requestSequenceId = Interlocked.Increment(ref _dispatcherSequenceId);

            if (DispatcherContext.IsResponseOrderingRequired(ctx))
            {
                lock (_responseMap)
                {
                    // Limit the number of pending responses (responses which finished out of order, and are
                    // waiting for previous requests to be finished so they can be written in order), by
                    // blocking further channel reads. Due to the way Netty frame decoders work, this is more
                    // of an estimate than a hard limit. Netty may continue to decode and process several
                    // more requests that were in the latest read, even while further reads on the channel
                    // have been blocked.
                    if (requestSequenceId > Interlocked.Read(ref _lastResponseWrittenId) + _queuedResponseLimit &&
                        !DispatcherContext.IsChannelReadBlocked(ctx))
                    {
                        DispatcherContext.BlockChannelReads(ctx);
                    }
                }
            }

            return(requestSequenceId);
        }