예제 #1
0
        public static string ToDebugInfo(this CommandToSend source)
        {
            if (source == null)
            {
                return(string.Empty);
            }

            return("[Channel_" + source.Channel + "] Class " + source.ClassId + " Method " + source.MethodId + " Opt: " + source.OptionalArg + "");
        }
예제 #2
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();
            }
        }
예제 #3
0
//		[MethodImpl(MethodImplOptions.AggressiveInlining)]
        private void FlushCommand(CommandToSend cmdToSend)
        {
            if (_threadCancelToken.IsCancellationRequested)
            {
                if (cmdToSend.Tcs != null)
                {
                    cmdToSend.Tcs.TrySetCanceled();
                }
                return;
            }

            var token = _threadCancelToken;

            if (!cmdToSend.Immediately)
            {
                _waitingServerReply.Wait(token);                 // Contention sadly required by the server/amqp
            }

            // The command will signal that we can send more commands...
            cmdToSend.Prepare(cmdToSend.ExpectsReply ? _waitingServerReply : null);

            if (cmdToSend.ExpectsReply)             // enqueues as awaiting a reply from the server
            {
                _waitingServerReply.Reset();        // cannot send anything else

                var queue = cmdToSend.Channel == 0
                                        ? _awaitingReplyQueue
                                        : _conn.ResolveChannel(cmdToSend.Channel)._awaitingReplyQueue;

                queue.Enqueue(cmdToSend);
            }

            // writes to socket
            var frameWriter = cmdToSend.OptionalArg as IFrameContentWriter;

            if (frameWriter != null)
            {
                frameWriter.Write(_amqpWriter, cmdToSend.Channel, cmdToSend.ClassId, cmdToSend.MethodId, cmdToSend.OptionalArg);
            }
            else
            {
                cmdToSend.commandGenerator(_amqpWriter, cmdToSend.Channel, cmdToSend.ClassId, cmdToSend.MethodId, cmdToSend.OptionalArg);
            }

            // if writing to socket is enough, set as complete
            if (!cmdToSend.ExpectsReply)
            {
                cmdToSend.RunReplyAction(0, 0, null);
            }
        }
예제 #4
0
        internal void SendCommand(ushort channel, ushort classId, ushort methodId,
                                  Action <AmqpPrimitivesWriter, ushort, ushort, ushort, object> commandWriter,
                                  Action <ushort, int, AmqpError> reply, bool expectsReply, TaskCompletionSource <bool> tcs = null,
                                  object optArg = null, Action prepare = null, bool immediately = false)
        {
            if (_lastError != null)
            {
                // ConnClose and Channel close el al, are allowed to move fwd.
                var cmdId = (classId << 16) | methodId;
                if (cmdId != AmqpClassMethodConnectionLevelConstants.ConnectionClose &&
                    cmdId != AmqpClassMethodConnectionLevelConstants.ConnectionCloseOk &&
                    cmdId != AmqpClassMethodChannelLevelConstants.ChannelClose &&
                    cmdId != AmqpClassMethodChannelLevelConstants.ChannelCloseOk)
                {
                    SetErrorResultIfErrorPending(expectsReply, reply, tcs /*, tcsL*/);
                    return;
                }
            }

            // var cmd = _cmdToSendObjPool.GetObject();
            var cmd = new CommandToSend(null);

            cmd.BeginInit();

            cmd.Channel          = channel;
            cmd.ClassId          = classId;
            cmd.MethodId         = methodId;
            cmd.ReplyAction      = reply;
            cmd.commandGenerator = commandWriter;
            cmd.ExpectsReply     = expectsReply;
            cmd.Tcs           = tcs;
            cmd.OptionalArg   = optArg;
            cmd.PrepareAction = prepare;
            cmd.Immediately   = immediately;

            _commandOutbox.Enqueue(cmd);
            _commandOutboxEvent.Set();
        }
예제 #5
0
        // Run on its own thread, and invokes user code from it (task continuations)
        private void WriteFramesLoop()
        {
            if (LogAdapter.ExtendedLogEnabled)
            {
                LogAdapter.LogDebug("ConnectionIO", "WriteFramesLoop starting");
            }

            CommandToSend cmdToSend = null;

            try
            {
                var token = _threadCancelToken;

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

                    while (_commandOutbox.TryDequeue(out cmdToSend))
                    {
                        _waitingServerReply.Wait(token);                         // Contention sadly required by the server/amqp

                        // The command will signal that we can send more commands...
                        cmdToSend.Prepare(cmdToSend.ExpectsReply ? _waitingServerReply : null);

                        if (cmdToSend.ExpectsReply)                         // enqueues as awaiting a reply from the server
                        {
                            _waitingServerReply.Reset();                    // cannot send anything else

                            var queue = cmdToSend.Channel == 0
                                                                ? _awaitingReplyQueue :
                                        _conn.ResolveChannel(cmdToSend.Channel)._awaitingReplyQueue;

                            queue.Enqueue(cmdToSend);
                        }

                        // writes to socket
                        var frameWriter = cmdToSend.OptionalArg as IFrameContentWriter;
                        if (frameWriter != null)
                        {
                            frameWriter.Write(_amqpWriter, cmdToSend.Channel, cmdToSend.ClassId, cmdToSend.MethodId, cmdToSend.OptionalArg);
                        }
                        else
                        {
                            cmdToSend.commandGenerator(_amqpWriter, cmdToSend.Channel, cmdToSend.ClassId, cmdToSend.MethodId, cmdToSend.OptionalArg);
                        }

                        // if writing to socket is enough, set as complete
                        if (!cmdToSend.ExpectsReply)
                        {
                            cmdToSend.RunReplyAction(0, 0, null).IntentionallyNotAwaited();
                        }
                    }
                }

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

                this.InitiateAbruptClose(ex);
            }
        }