Beispiel #1
0
        public void MultipleAcquiresSemaphoreTest()
        {
            const int ACQUIRES = 10;

            bool[]        acquires = new bool[ACQUIRES];
            Thread[]      threads  = new Thread[ACQUIRES];
            SafeSemaphore sem      = new SafeSemaphore(10, 10);

            for (int i = 0; i < ACQUIRES; ++i)
            {
                threads[i] = new Thread((idx) => {
                    bool res;
                    do
                    {
                        res = sem.TryAcquire(1);
                    }while (!res);
                    acquires[(int)idx] = true;
                });
                threads[i].Start(i);
            }

            // check if all threads terminate
            bool result = true;

            for (int i = 0; i < ACQUIRES; ++i)
            {
                bool partial = threads[i].Join(2000);
                if (!partial)
                {
                    TerminateThread(threads[i]);
                }
                result = result && partial;
            }
            if (!result)
            {
                Assert.Fail("One or more threads not terminated!");
            }

            // check if all results are true
            for (int i = 0; i < ACQUIRES; ++i)
            {
                if (!acquires[i])
                {
                    Assert.Fail("Unsuccessful acquire!");
                }
            }

            Assert.AreEqual(false, sem.TryAcquire(1));
        }
        public void Ready()
        {
            if (_subscription == null)
            {
                throw new Exception("Subscription not initialized, call Init first");
            }
            if (PriorityQueue == null)
            {
                throw new Exception("PriorityQueue not initialized, call Init first");
            }

            lock (SyncRoot)
            {
                _pool = new SafeSemaphore(_watcher, BatchSize, BatchSize, _sharedSemaphore);
            }

            StartConsumerThread(string.Format("Consumer thread: {0}, Priority queue: {1}", ConsumerTag, _queuePriorirty));
        }
Beispiel #3
0
        /// <summary>
        /// Initialize an object of <see cref="BurrowConsumer"/>
        /// </summary>
        /// <param name="channel">RabbitMQ.Client channel</param>
        /// <param name="messageHandler">An instance of message handler to handle the message from queue</param>
        /// <param name="watcher"></param>
        /// <param name="autoAck">If set to true, the msg will be acked after processed</param>
        /// <param name="batchSize"></param>
        /// <param name="startThread">Whether should start the consuming thread straight away</param>
        protected BurrowConsumer(IModel channel,
                                 IMessageHandler messageHandler,
                                 IRabbitWatcher watcher,
                                 bool autoAck,
                                 int batchSize, bool startThread)
            : base(channel, new SharedQueue <BasicDeliverEventArgs>())
        {
            if (channel == null)
            {
                throw new ArgumentNullException(nameof(channel));
            }
            if (messageHandler == null)
            {
                throw new ArgumentNullException(nameof(messageHandler));
            }
            if (watcher == null)
            {
                throw new ArgumentNullException(nameof(watcher));
            }

            if (batchSize < 1)
            {
                throw new ArgumentException("batchSize must be greater than or equal 1", nameof(batchSize));
            }

            Model.ModelShutdown += WhenChannelShutdown;;
            Model.BasicRecoverAsync(true);
            BatchSize = batchSize;

            _pool    = new SafeSemaphore(watcher, BatchSize, BatchSize);
            _watcher = watcher;
            _autoAck = autoAck;

            _messageHandler = messageHandler;
            _messageHandler.HandlingComplete     += MessageHandlerHandlingComplete;
            _messageHandler.MessageWasNotHandled += MessageWasNotHandled;

            if (startThread)
            {
                StartConsumerThread($"Consumer thread: {ConsumerTag}");
            }
        }
Beispiel #4
0
        public void TwoAcquiresOnOnePermitsSemaphoreTest()
        {
            int    acquire1 = -1, acquire2 = -1;
            Thread t = new Thread(() => {
                SafeSemaphore sem = new SafeSemaphore(1, 1);

                acquire1 = sem.TryAcquire(1) ? 1 : 0;
                acquire2 = sem.TryAcquire(1) ? 1 : 0;
            });

            t.Start();

            bool done = t.Join(2000);

            if (!done)
            {
                TerminateThread(t);
                Assert.Fail();
            }
            Assert.AreEqual(1, acquire1);
            Assert.AreEqual(0, acquire2);
        }
Beispiel #5
0
        public BurrowConsumer(IModel channel,
                              IMessageHandler messageHandler,
                              IRabbitWatcher watcher,

                              bool autoAck,
                              int batchSize)
            : base(channel, new SharedQueue())
        {
            if (channel == null)
            {
                throw new ArgumentNullException("channel");
            }
            if (messageHandler == null)
            {
                throw new ArgumentNullException("messageHandler");
            }
            if (watcher == null)
            {
                throw new ArgumentNullException("watcher");
            }

            if (batchSize < 1)
            {
                throw new ArgumentNullException("batchSize", "batchSize must be greater than or equal 1");
            }

            Model.ModelShutdown += WhenChannelShutdown;
            Model.BasicRecoverAsync(true);
            BatchSize = batchSize;

            _pool    = new SafeSemaphore(watcher, BatchSize, BatchSize);
            _watcher = watcher;
            _autoAck = autoAck;


            _messageHandler = messageHandler;
            _messageHandler.HandlingComplete     += MessageHandlerHandlingComplete;
            _messageHandler.MessageWasNotHandled += MessageWasNotHandled;

            Task.Factory.StartNew(() =>
            {
                try
                {
                    Thread.CurrentThread.Name = string.Format("Consumer thread: {0}", ConsumerTag);
                    while (!_disposed && !_channelShutdown)
                    {
                        WaitAndHandleMessageDelivery();
                    }
                }
                catch (ThreadStateException tse)
                {
                    _watcher.WarnFormat("The consumer thread {0} got a ThreadStateException: {1}, {2}", ConsumerTag, tse.Message, tse.StackTrace);
                }
                catch (ThreadInterruptedException)
                {
                    _watcher.WarnFormat("The consumer thread {0} is interrupted", ConsumerTag);
                }
                catch (ThreadAbortException)
                {
                    _watcher.WarnFormat("The consumer thread {0} is aborted", ConsumerTag);
                }
            }, TaskCreationOptions.LongRunning);
        }
        public void Ready()
        {
            if (_subscription == null)
            {
                throw new Exception("Subscription not initialized, call Init first");
            }
            if (PriorityQueue == null)
            {
                throw new Exception("PriorityQueue not initialized, call Init first");
            }

            lock (SyncRoot)
            {
                _pool = new SafeSemaphore(_watcher, _batchSize, _batchSize, _sharedSemaphore);
            }

            Task.Factory.StartNew(() =>
            {
                try
                {
                    Thread.CurrentThread.Name = string.Format("Consumer thread: {0}, Priority queue: {1}", ConsumerTag, _queuePriorirty);
                    while (!_disposed && !_channelShutdown)
                    {
                        try
                        {
#if DEBUG
                            _watcher.DebugFormat("1. Wait the semaphore to release");
                            _pool.WaitOne();
                            _watcher.DebugFormat("2. Semaphore released, wait a msg from RabbitMQ. Probably a wait-for-ack message is blocking this");
#else
                            _pool.WaitOne();
#endif
                            var msg = PriorityQueue.Dequeue();

                            if (msg != null && msg.Message != null)
                            {
#if DEBUG
                                _watcher.DebugFormat("3. Msg from RabbitMQ arrived (probably the previous msg has been acknownledged), prepare to handle it");
#endif
                                HandleMessageDelivery(msg.Message);
                            }
                            else
                            {
                                _watcher.ErrorFormat("Msg from RabbitMQ arrived but it's NULL for some reason, properly a serious BUG :D, contact author asap, release the semaphore for other messages");
                                _pool.Release();
                            }
                        }
                        catch (EndOfStreamException) // NOTE: Must keep the consumer thread alive
                        {
                            // This happen when the internal Queue is closed. The root reason could be connection problem
                            Thread.Sleep(100);
#if DEBUG
                            _watcher.DebugFormat("EndOfStreamException occurs, release the semaphore for another message");
#endif
                            _pool.Release();
                        }
                        catch (BadMessageHandlerException ex)
                        {
                            _watcher.Error(ex);
                            Dispose();
                        }
                    }
                }
                catch (ThreadStateException tse)
                {
                    _watcher.WarnFormat("The consumer thread {0} on queue {1} got a ThreadStateException: {2}, {3}", ConsumerTag, _queuePriorirty, tse.Message, tse.StackTrace);
                }
                catch (ThreadInterruptedException)
                {
                    _watcher.WarnFormat("The consumer thread {0} on queue {1} is interrupted", ConsumerTag, _queuePriorirty);
                }
                catch (ThreadAbortException)
                {
                    _watcher.WarnFormat("The consumer thread {0} on queue {1} is aborted", ConsumerTag, _queuePriorirty);
                }
            }, TaskCreationOptions.LongRunning);
        }