Пример #1
0
        internal void DispatchBasicReturn(ushort replyCode, string replyText,
                                          string exchange, string routingKey, int bodySize,
                                          BasicProperties properties, BaseLightStream ringBufferStream)
        {
            var ev     = this.MessageUndeliveredHandler;
            var marker = new RingBufferPositionMarker(ringBufferStream);

            try
            {
                if (ev != null)
                {
                    var inst = new UndeliveredMessage
                    {
                        bodySize   = bodySize,
                        stream     = bodySize == 0 ? EmptyStream : ringBufferStream,
                        properties = properties,
                        routingKey = routingKey,
                        replyCode  = replyCode,
                        replyText  = replyText,
                        exchange   = exchange
                    };

                    ev(inst);
                }
            }
            finally
            {
                marker.EnsureConsumed(bodySize);
            }
        }
        public RingBufferPositionMarker(BaseLightStream untypedStream)
        {
            _ringBuffer      = null;
            _mbStreamWrapper = untypedStream as MultiBodyStreamWrapper;
            _start           = 0;
            var adapter = untypedStream as RingBufferStreamAdapter;

            if (adapter != null)
            {
                _ringBuffer = adapter._ringBuffer;
                _start      = _ringBuffer.GlobalReadPos;
            }
        }
Пример #3
0
        internal void DispatchDeliveredMessage(
            string consumerTag, ulong deliveryTag, bool redelivered,
            string exchange, string routingKey, int bodySize,
            BasicProperties properties, BaseLightStream lightStream)
        {
            BasicConsumerSubscriptionInfo consumer;

            if (!_consumerSubscriptions.TryGetValue(consumerTag, out consumer))
            {
                // received msg but nobody was subscribed to get it (?)
                LogAdapter.LogWarn(LogSource, "Received message without a matching subscription. Discarding. " +
                                   "Exchange: " + exchange + " routing: " + routingKey +
                                   " consumer tag: " + consumerTag + " and channel " + this.ChannelNumber);

                // Ensure moved cursor ahead
                var marker = new RingBufferPositionMarker(lightStream);
                marker.EnsureConsumed(bodySize);
                return;
            }

            var delivery = new MessageDelivery
            {
                bodySize    = bodySize,
                properties  = properties,
                routingKey  = routingKey,
                deliveryTag = deliveryTag + this._deliveryTagOffset,                 // adds tag offset
                redelivered = redelivered,
            };

            var mode             = consumer.Mode;
            var cb               = consumer.Callback;
            var consumerInstance = consumer._consumer;

            if (mode == ConsumeMode.SingleThreaded)
            {
                // run with scissors, we're letting
                // the user code mess with the ring buffer in the name of performance
                delivery.stream = bodySize == 0 ? EmptyStream : lightStream;

                // upon return it's assumed the user has consumed from the stream and is done with it
                var marker = new RingBufferPositionMarker(lightStream);

                try
                {
                    if (cb != null)
                    {
                        cb(delivery).GetAwaiter().GetResult();
                    }
                    else
                    {
                        consumerInstance.Consume(delivery).GetAwaiter().GetResult();
                    }
                }
                finally
                {
                    if (!delivery.TakenOver)
                    {
                        delivery.Dispose();
                    }

                    // fingers crossed the user cloned the buffer if she needs it later
                    marker.EnsureConsumed(bodySize);
                }
            }
            else
            {
                // parallel mode. it cannot hold the frame handler, so we copy the buffer (yuck) and move forward

                if (mode == ConsumeMode.ParallelWithBufferCopy ||
                    mode == ConsumeMode.SerializedWithBufferCopy)
                {
                    delivery.stream = delivery.bodySize == 0
                                                ? EmptyStream
                                                : lightStream.CloneStream(bodySize);
                }

                if (mode == ConsumeMode.SerializedWithBufferCopy)                 // Posts to a thread
                {
                    if (consumer._consumerThread == null)
                    {
                        // Initialization. safe since this delivery call always happen from the same thread
                        consumer._receivedMessages   = new ConcurrentQueue <MessageDelivery>();
                        consumer._messageAvailableEv = new AutoResetEvent(false);
                        consumer._consumerThread     = ThreadFactory.BackgroundThread(SerializedDelivery, "Delivery_" + consumer.ConsumerTag,
                                                                                      consumer);
                    }

                    consumer._receivedMessages.Enqueue(delivery);
                    consumer._messageAvailableEv.Set();
                }
                else if (mode == ConsumeMode.ParallelWithBufferCopy)                 // Posts to TaskScheduler
                {
                    new Task(async state =>
                    {
                        var tuple       = (Tuple <MessageDelivery, Func <MessageDelivery, Task>, IQueueConsumer, Channel>)state;
                        var delivery1   = tuple.Item1;
                        var cb1         = tuple.Item2;
                        var conInstance = tuple.Item3;

                        try
                        {
                            if (cb1 != null)
                            {
                                await cb1(delivery1).ConfigureAwait(false);
                            }
                            else
                            {
                                await conInstance.Consume(delivery1).ConfigureAwait(false);
                            }
                        }
                        catch (Exception e)
                        {
                            if (LogAdapter.IsErrorEnabled)
                            {
                                LogAdapter.LogError(LogSource, "Error processing message (user code)", e);
                            }
                        }
                        finally
                        {
                            if (!delivery1.TakenOver)
                            {
                                delivery1.Dispose();
                            }
                        }
                    }, Tuple.Create(delivery, cb, consumerInstance, this))                     // tuple avoids the closure capture
                    // Start task in the given scheduler
                    .Start(_schedulerToDeliverMessages);
                }
            }
        }