Beispiel #1
0
        public Task __ExchangeUnbind(string source, string destination, string routingKey, IDictionary <string, object> arguments, bool waitConfirmation)
        {
            var tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);

            var writer = AmqpChannelLevelFrameWriter.ExchangeUnbind(source, destination, routingKey, arguments, waitConfirmation);

            _connectionIo.SendCommand(_channelNum,
                                      Amqp.Channel.Exchange.ClassId, Amqp.Channel.Exchange.Methods.ExchangeUnBind,
                                      writer,
                                      reply: (channel, classMethodId, error) =>
            {
                if (!waitConfirmation || classMethodId == AmqpClassMethodChannelLevelConstants.ExchangeUnbindOk)
                {
                    if (LogAdapter.ProtocolLevelLogEnabled)
                    {
                        LogAdapter.LogDebug(LogSource, "< ExchangeUnbindOk " + source);
                    }

                    tcs.SetResult(true);
                }
                else
                {
                    AmqpIOBase.SetException(tcs, error, classMethodId);
                }
            },
                                      expectsReply: waitConfirmation);

            return(tcs.Task);
        }
Beispiel #2
0
        internal Task __QueueUnbind(string queue, string exchange, string routingKey,
                                    IDictionary <string, object> arguments)
        {
            var tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);

            var writer = AmqpChannelLevelFrameWriter.QueueUnbind(queue, exchange, routingKey, arguments);

            _connectionIo.SendCommand(_channelNum,
                                      Amqp.Channel.Queue.ClassId, Amqp.Channel.Queue.Methods.QueueUnbind,
                                      writer,
                                      reply: (channel, classMethodId, error) =>
            {
                if (classMethodId == AmqpClassMethodChannelLevelConstants.QueueUnbindOk)
                {
                    if (LogAdapter.ProtocolLevelLogEnabled)
                    {
                        LogAdapter.LogDebug(LogSource, "< QueueUnbindOk " + queue);
                    }

                    tcs.SetResult(true);
                }
                else
                {
                    AmqpIOBase.SetException(tcs, error, classMethodId);
                }
            },
                                      expectsReply: true);

            return(tcs.Task);
        }
Beispiel #3
0
        private Task __SendConnectionClose(ushort replyCode, string message)
        {
            if (LogAdapter.ProtocolLevelLogEnabled)
            {
                LogAdapter.LogDebug(LogSource, "__SendConnectionClose >");
            }

            var tcs = new TaskCompletionSource <bool>();

            SendCommand(0, Amqp.Connection.ClassId, 50, AmqpConnectionFrameWriter.ConnectionClose,
                        reply: (channel, classMethodId, error) =>
            {
                if (classMethodId == AmqpClassMethodConnectionLevelConstants.ConnectionCloseOk)
                {
                    if (LogAdapter.ProtocolLevelLogEnabled)
                    {
                        LogAdapter.LogDebug(LogSource, "__SendConnectionClose enabled");
                    }

                    tcs.SetResult(true);
                }
                else
                {
                    AmqpIOBase.SetException(tcs, error, classMethodId);
                }
            },
                        expectsReply: true,
                        optArg: new FrameParameters.CloseParams()
            {
                replyCode = replyCode,
                replyText = message
            }, immediately: true);

            return(tcs.Task);
        }
Beispiel #4
0
        internal virtual async Task <bool> InitiateCleanClose(bool initiatedByServer, AmqpError error)
        {
            if (_isClosed)
            {
                return(false);
            }
            Thread.MemoryBarrier();
            _isClosed = true;

            if (LogAdapter.IsDebugEnabled)
            {
                LogAdapter.LogDebug(LogSource, "Clean close initiated. By server? " + initiatedByServer);
            }

            if (initiatedByServer)
            {
                await SendCloseConfirmation().ConfigureAwait(false);
            }
            else
            {
                await SendStartClose().ConfigureAwait(false);
            }

            DrainPending(error);

            if (error != null)
            {
                await FireErrorEvent(error);
            }

            return(true);
        }
Beispiel #5
0
        // Run on its own thread, and invokes user code from it
        private void ReadFramesLoop()
        {
            if (LogAdapter.ExtendedLogEnabled)
            {
                LogAdapter.LogDebug("ConnectionIO", "ReadFramesLoop starting");
            }

            try
            {
                var token = _threadCancelToken;

                while (!token.IsCancellationRequested)
                {
                    _frameReader.ReadAndDispatch();
                }

                LogAdapter.LogError("ConnectionIO", "ReadFramesLoop exiting");
            }
            catch (ThreadAbortException)
            {
                // no-op
            }
            catch (Exception ex)
            {
                LogAdapter.LogError("ConnectionIO", "ReadFramesLoop error", ex);

                this.InitiateAbruptClose(ex);
            }
        }
        public static WriterDelegate QueueBind(string queue, string exchange,
                                               string routingKey, IDictionary <string, object> arguments,
                                               bool waitConfirmation)
        {
            return((writer, channel, classId, methodId, args) =>
            {
                if (LogAdapter.ProtocolLevelLogEnabled)
                {
                    LogAdapter.LogDebug(LogSource, "> QueueBind : " + queue + "|" + exchange + "|" + routingKey);
                }

                writer.WriteFrameWithPayloadFirst(AmqpConstants.FrameMethod, channel, w =>
                {
                    w.WriteUShort(classId);
                    w.WriteUShort(methodId);

                    w.WriteUShort(0);
                    w.WriteShortstr(queue);
                    w.WriteShortstr(exchange);
                    w.WriteShortstr(routingKey);
                    w.WriteBits(!waitConfirmation);
                    w.WriteTable(arguments);
                });
            });
        }
Beispiel #7
0
        private Task <string> __SendConnectionOpen(string vhost)
        {
            if (LogAdapter.ProtocolLevelLogEnabled)
            {
                LogAdapter.LogDebug("ConnectionIO", "__SendConnectionOpen > vhost " + vhost);
            }

            var tcs    = new TaskCompletionSource <string>();
            var writer = AmqpConnectionFrameWriter.ConnectionOpen(vhost, string.Empty, false);

            SendCommand(0, 10, 40, writer,
                        reply: (channel, classMethodId, error) =>
            {
                if (classMethodId == AmqpClassMethodConnectionLevelConstants.ConnectionOpenOk)
                {
                    _frameReader.Read_ConnectionOpenOk((knowHosts) =>
                    {
                        if (LogAdapter.ProtocolLevelLogEnabled)
                        {
                            LogAdapter.LogDebug("ConnectionIO", "__SendConnectionOpen completed for vhost " + vhost);
                        }

                        tcs.SetResult(knowHosts);
                    });
                }
                else
                {
                    AmqpIOBase.SetException(tcs, error, classMethodId);
                }
                return(Task.CompletedTask);
            }, expectsReply: true);

            return(tcs.Task);
        }
Beispiel #8
0
        private void OnRecvWorker()
        {
            var polling = new Polling(PollingEvents.RecvReady, this._socket);

            polling.RecvReady += socket =>
            {
                var topic          = _socket.RecvString();
                var messageInBytes = _socket.Recv();
                var message        = _deserializer(messageInBytes);

                this.OnReceived(topic, message);
            };

            try
            {
                while (_started)
                {
                    polling.Poll(1000);
                }
            }
            catch (ZmqException e)
            {
                if (LogAdapter.LogEnabled)
                {
                    LogAdapter.LogDebug(this.GetType().FullName, "BaseSubscriber exception. Disposing. Details: " + e.ToString());
                }

                this.Dispose();
            }
        }
Beispiel #9
0
        private void InvalidatePoll(string name, string reason)
        {
            if (LogAdapter.LogEnabled)
            {
                LogAdapter.LogDebug("RequestPoll", "InvalidatePoll called. " + reason);
            }

            lock (_endpoint2Sockets)
            {
                EndpointPoll endpoint;
                if (!_endpoint2Sockets.TryRemove(name, out endpoint))
                {
                    return;
                }

//				if (endpoint.monitor != null)
//				{
//					endpoint.monitor.Dispose();
//					endpoint.monitored = false;
//					endpoint.monitor = null;
//				}
                foreach (var socket in endpoint.SocketsQueue.ToArray())
                {
                    socket.Dispose();
                }
            }
        }
Beispiel #10
0
        internal Task __ExchangeDelete(string exchange, bool waitConfirmation)
        {
            var tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);

            var writer = AmqpChannelLevelFrameWriter.ExchangeDelete(exchange, waitConfirmation);

            _connectionIo.SendCommand(_channelNum, Amqp.Channel.Exchange.ClassId, Amqp.Channel.Exchange.Methods.ExchangeDelete,
                                      writer,
                                      reply: (channel, classMethodId, error) =>
            {
                if (!waitConfirmation || classMethodId == AmqpClassMethodChannelLevelConstants.ExchangeDeleteOk)
                {
                    if (LogAdapter.ProtocolLevelLogEnabled)
                    {
                        LogAdapter.LogDebug(LogSource, "< ExchangeDeleteOk " + exchange);
                    }

                    tcs.SetResult(true);
                }
                else
                {
                    AmqpIOBase.SetException(tcs, error, classMethodId);
                }
            },
                                      expectsReply: waitConfirmation);

            return(tcs.Task);
        }
Beispiel #11
0
        public Task __ExchangeDeclare(string exchange, string type, bool durable, bool autoDelete,
                                      IDictionary <string, object> arguments, bool waitConfirmation)
        {
            var tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);

            var writer = AmqpChannelLevelFrameWriter.ExchangeDeclare(exchange, type, durable, autoDelete,
                                                                     arguments, false, false, waitConfirmation);

            _connectionIo.SendCommand(_channelNum, 40, 10,
                                      writer,
                                      reply: (channel, classMethodId, error) =>
            {
                if (!waitConfirmation || classMethodId == AmqpClassMethodChannelLevelConstants.ExchangeDeclareOk)
                {
                    if (LogAdapter.ProtocolLevelLogEnabled)
                    {
                        LogAdapter.LogDebug(LogSource, "< ExchangeDeclareOk " + exchange);
                    }

                    tcs.SetResult(true);
                }
                else
                {
                    AmqpIOBase.SetException(tcs, error, classMethodId);
                }
            },
                                      expectsReply: waitConfirmation);

            return(tcs.Task);
        }
        public Task Apply(Channel channel)
        {
            if (LogAdapter.ExtendedLogEnabled)
            {
                LogAdapter.LogDebug("Recovery", "Recovering queue " + _queue);
            }

            return(channel.QueueDeclare(_queue, _passive, _durable, _exclusive, _autoDelete, _arguments, waitConfirmation: !_passive));
        }
        public static void ConnectionCloseOk(AmqpPrimitivesWriter writer, ushort channel, ushort classId, ushort methodId, object args)
        {
            if (LogAdapter.ProtocolLevelLogEnabled)
            {
                LogAdapter.LogDebug(LogSource, "> ConnectionCloseOk");
            }

            WriteEmptyMethodFrame(writer, channel, classId, methodId);
        }
        public void NotifyConnected(string hostname)
        {
            _selectedHostname = hostname;

            if (LogAdapter.IsDebugEnabled)
            {
                LogAdapter.LogDebug(LogSource, "Connected to " + hostname);
            }
        }
Beispiel #15
0
        public Task Apply(Channel channel)
        {
            if (LogAdapter.ExtendedLogEnabled)
            {
                LogAdapter.LogDebug("Recovery", "Recovering binding queue: " + _queue + " ex: " + _exchange + " routing: " + _routingKey);
            }

            return(channel.QueueBind(_queue, _exchange, _routingKey, _arguments, waitConfirmation: true));
        }
        internal void NotifyCloseByUser()
        {
            _disableRecovery = true;

            if (LogAdapter.IsDebugEnabled)
            {
                LogAdapter.LogDebug(LogSource, "NotifyClosedByUser");
            }
        }
Beispiel #17
0
        public Task Apply(Channel channel)
        {
            if (LogAdapter.ExtendedLogEnabled)
            {
                LogAdapter.LogDebug(LogSource, "Recovering binding source: " + _source + " dest: " + _destination + " routing: " + _routingKey);
            }

            return(channel.ExchangeBind(_source, _destination, _routingKey, _arguments, waitConfirmation: true));
        }
Beispiel #18
0
        public Task Apply(Channel channel)
        {
            if (LogAdapter.ExtendedLogEnabled)
            {
                LogAdapter.LogDebug("Recovery", "Recovering exchange: " + _exchange);
            }

            return(channel.ExchangeDeclare(_exchange, _type, _durable, _autoDelete, _arguments, waitConfirmation: true));
        }
Beispiel #19
0
        internal RecoveryAction NotifyCloseByServer()
        {
            LogAdapter.LogDebug(LogSource, "NotifyClosedByServer ");

            // TODO: Block RecoveryChannels? So new operations are blocked. also should fire notifications to indicate recovery in progress

            TryInitiateRecovery();

            return(RecoveryAction.WillReconnect);
        }
Beispiel #20
0
        private Task __SendConnectionStartOk(string username, string password, string connectionName)
        {
            if (LogAdapter.ProtocolLevelLogEnabled)
            {
                LogAdapter.LogDebug(LogSource, "__SendConnectionStartOk >");
            }

            var tcs = new TaskCompletionSource <bool>();

            // Only supports PLAIN authentication for now

            var clientProperties = Protocol.ClientProperties;

            if (!string.IsNullOrEmpty(connectionName))
            {
                clientProperties = new Dictionary <string, object>(clientProperties);
                clientProperties["connection_name"] = connectionName;
            }

            var auth   = Encoding.UTF8.GetBytes("\0" + username + "\0" + password);
            var writer = AmqpConnectionFrameWriter.ConnectionStartOk(clientProperties, "PLAIN", auth, "en_US");

            SendCommand(0, Amqp.Connection.ClassId, 30,
                        writer,
                        reply: (channel, classMethodId, error) =>
            {
                if (classMethodId == AmqpClassMethodConnectionLevelConstants.ConnectionTune)
                {
                    _frameReader.Read_ConnectionTune((channelMax, frameMax, heartbeat) =>
                    {
                        this._channelMax = channelMax;
                        this._frameMax   = frameMax;
                        this.Heartbeat   = heartbeat;

                        if (LogAdapter.ProtocolLevelLogEnabled)
                        {
                            LogAdapter.LogDebug(LogSource, "__SendConnectionStartOk completed.");
                        }

                        if (LogAdapter.IsDebugEnabled)
                        {
                            LogAdapter.LogDebug(LogSource, "Tune results: Channel max: " + channel + " Frame max size: " + frameMax + " heartbeat: " + heartbeat);
                        }

                        tcs.SetResult(true);
                    });
                }
                else
                {
                    AmqpIOBase.SetException(tcs, error, classMethodId);
                }
            }, expectsReply: true, immediately: true);

            return(tcs.Task);
        }
        public void Read_ConnectionBlocked(Action <string> continuation)
        {
            string reason = _amqpReader.ReadShortStr();

            if (LogAdapter.ProtocolLevelLogEnabled)
            {
                LogAdapter.LogDebug(LogSource, "< ConnectionBlocked " + reason);
            }

            continuation(reason);
        }
        public void Read_ChannelOpenOk(Action <string> continuation)
        {
            string reserved = _amqpReader.ReadLongstr();

            if (LogAdapter.ProtocolLevelLogEnabled)
            {
                LogAdapter.LogDebug(LogSource, "< ChannelOpenOk " + reserved);
            }

            continuation(reserved);
        }
Beispiel #23
0
        // Run on its own thread, and invokes user code from it (task continuations)
        private void WriteFramesLoop()
        {
            if (LogAdapter.IsDebugEnabled)
            {
                LogAdapter.LogDebug(LogSource, "WriteFramesLoop starting");
            }

            CommandToSend cmdToSend = null;

            _writeThreadRunning = true;

            try
            {
                var token = _threadCancelToken;

                while (!token.IsCancellationRequested)
                {
                    _commandOutboxEvent.WaitOne(1000);                     // maybe it's better to _cancellationToken.Register(action) ?

                    if (token.IsCancellationRequested)
                    {
                        break;                                                    // perf hit?
                    }
                    while (_commandOutbox.TryDequeue(out cmdToSend))
                    {
                        FlushCommand(cmdToSend);
                    }
                }

                if (LogAdapter.IsErrorEnabled)
                {
                    LogAdapter.LogError(LogSource, "WriteFramesLoop exiting");
                }
            }
            catch (ThreadAbortException)
            {
                // no-op
            }
            catch (Exception ex)
            {
                if (LogAdapter.IsErrorEnabled)
                {
                    LogAdapter.LogError(LogSource, "WriteFramesLoop error. Last command " + cmdToSend.ToDebugInfo(), ex);
                }

                this.InitiateAbruptClose(ex).IntentionallyNotAwaited();
            }
            finally
            {
                _writeThreadRunning = false;

                TryTriggerClean();
            }
        }
Beispiel #24
0
        public void Read_GenericMessageCount(Action <uint> continuation)
        {
            uint messageCount = _amqpReader.ReadLong();

            if (LogAdapter.ProtocolLevelLogEnabled)
            {
                LogAdapter.LogDebug(LogSource, "< GenericMessageCount : " + messageCount);
            }

            continuation(messageCount);
        }
Beispiel #25
0
        public void Read_CancelOk(Action <string> continuation)
        {
            var consumerTag = _amqpReader.ReadShortStr();

            if (LogAdapter.ProtocolLevelLogEnabled)
            {
                LogAdapter.LogDebug(LogSource, "< CancelOk " + consumerTag);
            }

            continuation(consumerTag);
        }
Beispiel #26
0
        internal void SendHeartbeat()
        {
            if (LogAdapter.ExtendedLogEnabled)
            {
                LogAdapter.LogDebug(LogSource, "Sending Heartbeat");
            }

            SendCommand(0, 0, 0, AmqpConnectionFrameWriter.ConnectionClose,
                        reply: null,
                        expectsReply: false,
                        optArg: AmqpConnectionFrameWriter.HeartbeatFrameWriter, immediately: false);
        }
Beispiel #27
0
        public Task Apply(Channel channel, IDictionary <string, string> reservedNamesMapping)
        {
            var queueNameToUse =
                _queue.StartsWith(AmqpConstants.AmqpReservedPrefix, StringComparison.Ordinal) ? reservedNamesMapping[_queue] : _queue;

            if (LogAdapter.ExtendedLogEnabled)
            {
                LogAdapter.LogDebug("Recovery", "Recovering binding queue: " + queueNameToUse + " ex: " + _exchange + " routing: " + _routingKey);
            }

            return(channel.QueueBind(queueNameToUse, _exchange, _routingKey, _arguments, waitConfirmation: true));
        }
Beispiel #28
0
        public void Read_BasicAck(Channel channel)
        {
            ulong deliveryTags = _amqpReader.ReadULong();
            bool  multiple     = _amqpReader.ReadBits() != 0;

            if (LogAdapter.ProtocolLevelLogEnabled)
            {
                LogAdapter.LogDebug(LogSource, "< BasicAck : " + deliveryTags + " multiple " + multiple);
            }

            channel.ProcessAcks(deliveryTags, multiple);
        }
Beispiel #29
0
        internal async Task <bool> InternalDoConnectSocket(string hostname, int port, bool throwOnError)
        {
            var index = Interlocked.Increment(ref _counter);

            // read and write threads should not be running at this point
            if (_readThreadRunning)
            {
                throw new Exception("Read thread should not be running");
            }
            if (_writeThreadRunning)
            {
                throw new Exception("Write thread should not be running");
            }

            var result = await _socketHolder.Connect(hostname, port, index, throwOnError).ConfigureAwait(false);

            if (!result)
            {
                // Interlocked.Decrement(ref _counter);
                return(false);
            }

            if (LogAdapter.IsDebugEnabled)
            {
                LogAdapter.LogDebug(LogSource, "Connected socket to " + hostname + " port " + port);
            }

            DrainCommandsAndResetErrorState();

            if (_threadCancelSource != null)
            {
                if (LogAdapter.IsDebugEnabled)
                {
                    LogAdapter.LogDebug(LogSource, "Disposing existing cancellation token source");
                }

                _threadCancelSource.Dispose();
            }

            _threadCancelSource = new CancellationTokenSource();
            _threadCancelToken  = _threadCancelSource.Token;

            _socketHolder.WireStreams(_threadCancelToken, OnSocketClosed);

            _amqpWriter.Initialize(_socketHolder.Writer);
            _amqpReader.Initialize(_socketHolder.Reader);
            _frameReader.Initialize(_socketHolder.Reader, _amqpReader, this);

            ThreadFactory.BackgroundThread(WriteFramesLoop, WriteFrameThreadNamePrefix + index);
            ThreadFactory.BackgroundThread(ReadFramesLoop, ReadFrameThreadNamePrefix + index);

            return(true);
        }
Beispiel #30
0
        public void Read_BasicCancel(Action <string, byte> continuation)
        {
            string consumerTag = _amqpReader.ReadShortStr();
            var    noWait      = _amqpReader.ReadBits();

            if (LogAdapter.ProtocolLevelLogEnabled)
            {
                LogAdapter.LogDebug(LogSource, "< BasicCancel : " + consumerTag + " bits " + noWait);
            }

            continuation(consumerTag, noWait);
        }