protected void HandleCloseMethod(ushort replyCode, string replyText, ushort classId, ushort methodId) { var error = new AmqpError() { ClassId = classId, MethodId = methodId, ReplyCode = replyCode, ReplyText = replyText }; Volatile.Write(ref _lastError, error); InitiateCleanClose(startedByServer: true, offendingClassId: classId, offendingMethodId: methodId); // DrainMethodsWithErrorAndClose(error, classId, methodId, sendCloseOk: true); // return Task.CompletedTask; }
public void DrainDueToFailure(AmqpError error) { for (int i = 0; i < _tasks.Length; i++) { var tcs = Interlocked.Exchange(ref _tasks[i], null); if (tcs == null) continue; tcs.SetException(new Exception("Cancelled due to error " + error.ToErrorString()), runContinuationAsync: true); } }
internal void CloseAllChannels(bool initiatedByServer, AmqpError error) { foreach (var channel in _channels) { if (channel == null) continue; #pragma warning disable 4014 channel._io.InitiateCleanClose(initiatedByServer, error); #pragma warning restore 4014 } }
public async Task RunReplyAction(ushort channel, int classMethodId, AmqpError error) { #if DEBUG if (classMethodId != 0) { // Confirm reply var classId = classMethodId >> 16; var methodId = classMethodId & 0x0000FFFF; var matchesClass = (ClassId == classId); var matchesMethod = MethodId == (methodId - 1); if (!matchesClass || !matchesMethod) { Console.WriteLine("[channel " + channel + "] Command for " + ClassId + "|" + MethodId + " did not match reply " + classId + "|" + methodId); } } #endif if (this.ReplyAction != null) { await this.ReplyAction(channel, classMethodId, error); } else { if (error != null) { AmqpIOBase.SetException(Tcs, error, classMethodId); AmqpIOBase.SetException(TcsSlim, error, classMethodId); } else { if (Tcs != null) { Tcs.SetResult(true); } if (TcsSlim != null) { TcsSlim.SetCompleted(); } } } if (_recycler != null) { _recycler(this); } }
public async Task RunReplyAction(ushort channel, int classMethodId, AmqpError error) { #if DEBUG if (classMethodId != 0) { // Confirm reply var classId = classMethodId >> 16; var methodId = classMethodId & 0x0000FFFF; var matchesClass = (ClassId == classId); var matchesMethod = MethodId == (methodId - 1); if (!matchesClass || !matchesMethod) { Console.WriteLine("[channel " + channel + "] Command for " + ClassId + "|" + MethodId + " did not match reply " + classId + "|" + methodId); } } #endif if (this.ReplyAction != null) { await this.ReplyAction(channel, classMethodId, error); } else { if (error != null) { AmqpIOBase.SetException(Tcs, error, classMethodId); AmqpIOBase.SetException(TcsSlim, error, classMethodId); } else { if (Tcs != null) Tcs.SetResult(true); if (TcsSlim != null) TcsSlim.SetCompleted(); } } if (_recycler != null) _recycler(this); }
public void DrainDueToFailure(AmqpError error) { Exception exception = null; for (int i = 0; i < _tasks.Length; i++) { var tcs = Interlocked.Exchange(ref _tasks[i], null); if (tcs == null) { continue; } if (exception == null) { exception = new Exception("Cancelled due to error " + error.ToErrorString()); } tcs.TrySetException(exception); } }
public async Task RunReplyAction(ushort channel, int classMethodId, AmqpError error) { AssertCanBeUsed(); #if DEBUG if (classMethodId != 0) { // Confirm reply var classId = classMethodId >> 16; var methodId = classMethodId & 0x0000FFFF; var matchesClass = (ClassId == classId); var matchesMethod = MethodId == (methodId - 1); if (!matchesClass || !matchesMethod) { if (LogAdapter.ExtendedLogEnabled) { LogAdapter.LogDebug("CommandToSend", "[channel " + channel + "] Command for " + ClassId + "|" + MethodId + " did not match reply " + classId + "|" + methodId); } } } #endif // Allows more commands to be sent. This contention is sadly required by the amqp/rabbitmq if (_whenReplyReceived != null) { _whenReplyReceived.Set(); } // --- if (this.ReplyAction != null) { try { await this.ReplyAction(channel, classMethodId, error).ConfigureAwait(false); } catch (Exception ex) { error = new AmqpError { ReplyText = ex.Message }; AmqpIOBase.SetException(Tcs, error, classMethodId); AmqpIOBase.SetException(TcsSlim, error, classMethodId); throw; } } else { if (error != null) { AmqpIOBase.SetException(Tcs, error, classMethodId); AmqpIOBase.SetException(TcsSlim, error, classMethodId); } else { if (Tcs != null) { Tcs.SetResult(true); } if (TcsSlim != null) { TcsSlim.SetCompleted(); } } } if (_recycler != null) { _recycler(this); } }
internal override async Task<bool> InitiateCleanClose(bool initiatedByServer, AmqpError error) { if (!initiatedByServer) { while (true) { if (_socketHolder.StillSending) { Thread.Sleep(1000); // give it some time to finish writing to the socket (if it's open) } break; } } _conn.CloseAllChannels(initiatedByServer, error); await base.InitiateCleanClose(initiatedByServer, error); CancelPendingCommands(error); _socketHolder.Close(); return true; }
private void CancelPendingCommands(AmqpError error) { CommandToSend cmdToSend; while (_commandOutbox.TryDequeue(out cmdToSend)) { #pragma warning disable 4014 cmdToSend.RunReplyAction(0, 0, error); #pragma warning restore 4014 } }