public override BaseLightStream CloneStream(int bodySize)
 {
     return(new MemoryStream2(BufferUtil.Copy(this, bodySize)));
 }
Beispiel #2
0
        internal async Task DispatchDeliveredMessage(string consumerTag, ulong deliveryTag, bool redelivered,
                                                     string exchange, string routingKey, int bodySize, BasicProperties properties, Stream stream)
        {
            BasicConsumerSubscriptionInfo consumer;

            if (_consumerSubscriptions.TryGetValue(consumerTag, out consumer))
            {
                var delivery = new MessageDelivery()
                {
                    bodySize    = bodySize,
                    properties  = properties,
                    routingKey  = routingKey,
                    deliveryTag = deliveryTag,
                    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 = stream;

                    // upon return it's assumed the user has consumed from the stream and is done with it
                    try
                    {
                        if (cb != null)
                        {
                            await cb(delivery);
                        }
                        else
                        {
                            await consumerInstance.Consume(delivery);
                        }
                    }
                    finally
                    {
                        // fingers crossed the user cloned the buffer if she needs it later
                        this.Return(properties);
                    }
                }
                else
                {
                    // parallel mode. it cannot hold the frame handler, so we copy the buffer (yuck) and more forward

                    // since we dont have any control on how the user
                    // will deal with the buffer we cant even re-use/use a pool, etc :-(

                    // Idea: split Ringbuffer consumers, create reader barrier. once they are all done,
                    // move the read pos forward. Shouldnt be too hard to implement and
                    // avoids the new buffer + GC and keeps the api Stream based consistently

                    if (mode == ConsumeMode.ParallelWithBufferCopy)
                    {
                        var bufferCopy = BufferUtil.Copy(stream as RingBufferStreamAdapter, (int)bodySize);
                        var memStream  = new MemoryStream(bufferCopy, writable: false);
                        delivery.stream = memStream;
                    }
//					else if (mode == ConsumeMode.ParallelWithReadBarrier)
//					{
//						var readBarrier = new RingBufferStreamReadBarrier(stream as RingBufferStreamAdapter, delivery.bodySize);
//						delivery.stream = readBarrier;
//					}

#pragma warning disable 4014
                    Task.Factory.StartNew(async() =>
                                          // ThreadPool.UnsafeQueueUserWorkItem((param) =>
#pragma warning restore 4014
                    {
                        try
                        {
                            using (delivery.stream)
                            {
                                if (cb != null)
                                {
                                    await cb(delivery);
                                }
                                else
                                {
                                    await consumerInstance.Consume(delivery);
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("From threadpool " + e);
                        }
                        finally
                        {
                            this.Return(properties);
                        }
                    }, TaskCreationOptions.PreferFairness);
                }
            }
            else
            {
                // received msg but nobody was subscribed to get it (?) TODO: log it at least
            }
        }