public Task InvokeWriteAsync(IChannelHandlerContext ctx, object msg) { Contract.Requires(msg != null); // todo: check for cancellation //if (!validatePromise(ctx, promise, false)) { // // promise cancelled // return; //} if (this.executor.InEventLoop) { return(ChannelHandlerInvokerUtil.InvokeWriteAsyncNow(ctx, msg)); } else { var channel = (AbstractChannel)ctx.Channel; int size = channel.EstimatorHandle.Size(msg); if (size > 0) { ChannelOutboundBuffer buffer = channel.Unsafe.OutboundBuffer; // Check for null as it may be set to null if the channel is closed already if (buffer != null) { buffer.IncrementPendingOutboundBytes(size); } } return(this.SafeProcessOutboundMessageAsync(InvokeWriteAsyncFunc, ctx, msg)); } }
public static WriteTask NewInstance( IChannelHandlerContext ctx, object msg, TaskCompletionSource promise) { WriteTask task = Recycler.Take(); task.ctx = ctx; task.msg = msg; task.promise = promise; if (EstimateTaskSizeOnSubmit) { ChannelOutboundBuffer buffer = ctx.Channel.Unsafe.OutboundBuffer; // Check for null as it may be set to null if the channel is closed already if (buffer != null) { task.size = ((AbstractChannel)ctx.Channel).EstimatorHandle.Size(msg) + WriteTaskOverhead; buffer.IncrementPendingOutboundBytes(task.size); } else { task.size = 0; } } else { task.size = 0; } return(task); }
protected static void Init(AbstractWriteTask task, AbstractChannelHandlerContext ctx, object msg, TaskCompletionSource promise) { task.ctx = ctx; task.msg = msg; task.promise = promise; if (EstimateTaskSizeOnSubmit) { ChannelOutboundBuffer buffer = ctx.Channel.Unsafe.OutboundBuffer; // Check for null as it may be set to null if the channel is closed already if (buffer != null) { task.size = ctx.pipeline.EstimatorHandle.Size(msg) + WriteTaskOverhead; buffer.IncrementPendingOutboundBytes(task.size); } else { task.size = 0; } } else { task.size = 0; } }
public PendingWriteQueue(IChannelHandlerContext ctx) { Contract.Requires(ctx != null); this.ctx = ctx; this.buffer = ctx.Channel.Unsafe.OutboundBuffer; this.estimatorHandle = ctx.Channel.Configuration.MessageSizeEstimator.NewHandle(); }
public PendingWriteQueue(IChannelHandlerContext ctx) { Contract.Requires(ctx != null); this.ctx = ctx; this.buffer = ctx.Channel.Unsafe.OutboundBuffer; this.estimatorHandle = ctx.Channel.Configuration.MessageSizeEstimator.NewHandle(); }
public void Flush() { ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; if (outboundBuffer == null) { return; } outboundBuffer.AddFlush(); this.Flush0(); }
public BatchingPendingWriteQueue(IChannelHandlerContext ctx, int maxSize) { if (ctx is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.ctx); } _ctx = ctx; _maxSize = maxSize; _buffer = ctx.Channel.Unsafe.OutboundBuffer; _estimatorHandle = ctx.Channel.Configuration.MessageSizeEstimator.NewHandle(); }
protected virtual void Flush0() { if (this.inFlush0) { // Avoid re-entrance return; } ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; if (outboundBuffer == null || outboundBuffer.IsEmpty) { return; } this.inFlush0 = true; // Mark all pending write requests as failure if the channel is inactive. if (!this.CanWrite) { try { if (this.channel.Open) { outboundBuffer.FailFlushed(NotYetConnectedException, true); } else { // Do not trigger channelWritabilityChanged because the channel is closed already. outboundBuffer.FailFlushed(new ClosedChannelException(), false); } } finally { this.inFlush0 = false; } return; } try { this.channel.DoWrite(outboundBuffer); } catch (Exception ex) { Util.CompleteChannelCloseTaskSafely(this.channel, this.CloseAsync(new ClosedChannelException("Failed to write", ex), false)); } finally { this.inFlush0 = false; } }
protected virtual void Flush0() { if (this.inFlush0) { // Avoid re-entrance return; } ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; if (outboundBuffer == null || outboundBuffer.IsEmpty) { return; } this.inFlush0 = true; // Mark all pending write requests as failure if the channel is inactive. if (!this.channel.Active) { try { if (this.channel.Open) { outboundBuffer.FailFlushed(NotYetConnectedException, true); } else { // Do not trigger channelWritabilityChanged because the channel is closed already. outboundBuffer.FailFlushed(ClosedChannelException, false); } } finally { this.inFlush0 = false; } return; } try { this.channel.DoWrite(outboundBuffer); } catch (Exception t) { outboundBuffer.FailFlushed(t, true); } finally { this.inFlush0 = false; } }
public void Flush() { AssertEventLoop(); ChannelOutboundBuffer outboundBuffer = Volatile.Read(ref _outboundBuffer); if (outboundBuffer is null) { return; } outboundBuffer.AddFlush(); Flush0(); }
public void Flush() { this.AssertEventLoop(); ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; if (outboundBuffer == null) { return; } outboundBuffer.AddFlush(); this.Flush0(); }
public void Run() { try { ChannelOutboundBuffer buffer = this.ctx.Channel.Unsafe.OutboundBuffer; // Check for null as it may be set to null if the channel is closed already if (EstimateTaskSizeOnSubmit) { buffer?.DecrementPendingOutboundBytes(this.size); } ChannelHandlerInvokerUtil.InvokeWriteNowAsync(this.ctx, this.msg).LinkOutcome(this.promise); } finally { // Set to null so the GC can collect them directly this.ctx = null; this.msg = null; this.promise = null; } }
public Task InvokeWriteAsync(IChannelHandlerContext ctx, object msg) { Contract.Requires(msg != null); // todo: check for cancellation //if (!validatePromise(ctx, promise, false)) { // // promise cancelled // return; //} if (this.executor.InEventLoop) { return(ChannelHandlerInvokerUtil.InvokeWriteAsyncNow(ctx, msg)); } else { var channel = (AbstractChannel)ctx.Channel; var promise = new TaskCompletionSource(ctx); try { int size = channel.EstimatorHandle.Size(msg); if (size > 0) { ChannelOutboundBuffer buffer = channel.Unsafe.OutboundBuffer; // Check for null as it may be set to null if the channel is closed already if (buffer != null) { buffer.IncrementPendingOutboundBytes(size); } } this.executor.Execute(InvokeWriteAsyncAction, promise, msg); } catch (Exception cause) { ReferenceCountUtil.Release(msg); // todo: safe release? promise.TrySetException(cause); } return(promise.Task); } }
public Task WriteAsync(object msg) { this.AssertEventLoop(); ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; if (outboundBuffer == null) { // If the outboundBuffer is null we know the channel was closed and so // need to fail the future right away. If it is not null the handling of the rest // will be done input flush0() // See https://github.com/netty/netty/issues/2362 // release message now to prevent resource-leak ReferenceCountUtil.Release(msg); return(TaskEx.FromException(new ClosedChannelException())); } int size; try { msg = this.channel.FilterOutboundMessage(msg); size = this.channel.pipeline.EstimatorHandle.Size(msg); if (size < 0) { size = 0; } } catch (Exception t) { ReferenceCountUtil.Release(msg); return(TaskEx.FromException(t)); } var promise = new TaskCompletionSource(); outboundBuffer.AddMessage(msg, size, promise); return(promise.Task); }
public void Write(object msg, IPromise promise) { AssertEventLoop(); ChannelOutboundBuffer outboundBuffer = Volatile.Read(ref _outboundBuffer); if (outboundBuffer is null) { // If the outboundBuffer is null we know the channel was closed and so // need to fail the future right away. If it is not null the handling of the rest // will be done input flush0() // See https://github.com/netty/netty/issues/2362 Util.SafeSetFailure(promise, WriteClosedChannelException, Logger); // release message now to prevent resource-leak _ = ReferenceCountUtil.Release(msg); return; } int size; try { var ch = _channel; msg = ch.FilterOutboundMessage(msg); size = ch._pipeline.EstimatorHandle.Size(msg); if (size < 0) { size = 0; } } catch (Exception t) { Util.SafeSetFailure(promise, t, Logger); _ = ReferenceCountUtil.Release(msg); return; } outboundBuffer.AddMessage(msg, size, promise); }
/// <summary> /// Flush the content of the given buffer to the remote peer. /// </summary> protected abstract void DoWrite(ChannelOutboundBuffer input);
protected Task CloseAsync(Exception cause, bool notify) { var promise = new TaskCompletionSource(); if (!promise.SetUncancellable()) { return(promise.Task); } ChannelOutboundBuffer outboundBuffer = this.outboundBuffer; if (outboundBuffer == null) { // Only needed if no VoidChannelPromise. if (promise != TaskCompletionSource.Void) { // This means close() was called before so we just register a listener and return return(this.channel.closeFuture.Task); } return(promise.Task); } if (this.channel.closeFuture.Task.IsCompleted) { // Closed already. Util.SafeSetSuccess(promise, Logger); return(promise.Task); } bool wasActive = this.channel.Active; this.outboundBuffer = null; // Disallow adding any messages and flushes to outboundBuffer. IEventExecutor closeExecutor = null; // todo closeExecutor(); if (closeExecutor != null) { closeExecutor.Execute(() => { try { // Execute the close. this.DoClose0(promise); } finally { // Call invokeLater so closeAndDeregister is executed input the EventLoop again! this.InvokeLater(() => { // Fail all the queued messages outboundBuffer.FailFlushed(cause, notify); outboundBuffer.Close(new ClosedChannelException()); this.FireChannelInactiveAndDeregister(wasActive); }); } }); } else { try { // Close the channel and fail the queued messages input all cases. this.DoClose0(promise); } finally { // Fail all the queued messages. outboundBuffer.FailFlushed(cause, notify); outboundBuffer.Close(new ClosedChannelException()); } if (this.inFlush0) { this.InvokeLater(() => this.FireChannelInactiveAndDeregister(wasActive)); } else { this.FireChannelInactiveAndDeregister(wasActive); } } return(promise.Task); }
public Task CloseAsync() //CancellationToken cancellationToken) { var promise = new TaskCompletionSource(); if (!promise.setUncancellable()) { return promise.Task; } //if (cancellationToken.IsCancellationRequested) //{ // return TaskEx.Cancelled; //} if (this.outboundBuffer == null) { // Only needed if no VoidChannelPromise. if (promise != TaskCompletionSource.Void) { // This means close() was called before so we just register a listener and return return this.channel.closeFuture.Task; } return promise.Task; } if (this.channel.closeFuture.Task.IsCompleted) { // Closed already. Util.SafeSetSuccess(promise); return promise.Task; } bool wasActive = this.channel.Active; ChannelOutboundBuffer buffer = this.outboundBuffer; this.outboundBuffer = null; // Disallow adding any messages and flushes to outboundBuffer. IEventExecutor closeExecutor = null; // todo closeExecutor(); if (closeExecutor != null) { closeExecutor.Execute(() => { try { // Execute the close. this.DoClose0(promise); } finally { // Call invokeLater so closeAndDeregister is executed input the EventLoop again! this.InvokeLater(() => { // Fail all the queued messages buffer.FailFlushed(ClosedChannelException, false); buffer.Close(ClosedChannelException); this.FireChannelInactiveAndDeregister(wasActive); }); } }); } else { try { // Close the channel and fail the queued messages input all cases. this.DoClose0(promise); } finally { // Fail all the queued messages. buffer.FailFlushed(ClosedChannelException, false); buffer.Close(ClosedChannelException); } if (this.inFlush0) { this.InvokeLater(() => this.FireChannelInactiveAndDeregister(wasActive)); } else { this.FireChannelInactiveAndDeregister(wasActive); } } return promise.Task; }
//public ChannelHandlerInvoker invoker() { // // return the unwrapped invoker. // return ((PausableChannelEventExecutor) eventLoop().asInvoker()).unwrapInvoker(); //} protected AbstractUnsafe(AbstractChannel channel) { this.channel = channel; this.outboundBuffer = new ChannelOutboundBuffer(channel); }
public CloseChannelTask(ChannelOutboundBuffer buf, Exception cause, bool allowChannelOpen) { this.buf = buf; this.cause = cause; this.allowChannelOpen = allowChannelOpen; }
//public ChannelHandlerInvoker invoker() { // // return the unwrapped invoker. // return ((PausableChannelEventExecutor) eventLoop().asInvoker()).unwrapInvoker(); //} protected AbstractUnsafe(AbstractChannel channel) { this.channel = channel; this.outboundBuffer = new ChannelOutboundBuffer(channel); }
protected virtual void Flush0() { if (_inFlush0) { // Avoid re-entrance return; } ChannelOutboundBuffer outboundBuffer = Volatile.Read(ref _outboundBuffer); if (outboundBuffer is null || outboundBuffer.IsEmpty) { return; } _inFlush0 = true; var ch = _channel; // Mark all pending write requests as failure if the channel is inactive. if (!CanWrite) { try { if (ch.Open) { outboundBuffer.FailFlushed(Flush0NotYetConnectedException, true); } else { // Do not trigger channelWritabilityChanged because the channel is closed already. outboundBuffer.FailFlushed(Flush0ClosedChannelException, false); } } finally { _inFlush0 = false; } return; } try { ch.DoWrite(outboundBuffer); } catch (Exception ex) { //if (ch.Configuration.AutoClose) //{ /* * Just call {@link #close(ChannelPromise, Throwable, boolean)} here which will take care of * failing all flushed messages and also ensure the actual close of the underlying transport * will happen before the promises are notified. * * This is needed as otherwise {@link #isActive()} , {@link #isOpen()} and {@link #isWritable()} * may still return <c>true</c> even if the channel should be closed as result of the exception. */ Close(VoidPromise(), ex, Flush0ClosedChannelException, false); //} //else //{ // try // { // shutdownOutput(voidPromise(), t); // } // catch(Exception ex2) // { // close(voidPromise(), t2, FLUSH0_CLOSED_CHANNEL_EXCEPTION, false); // } //} } finally { _inFlush0 = false; } }
private void CloseOutboundBufferForShutdown(IChannelPipeline pipeline, ChannelOutboundBuffer buffer, Exception cause) { buffer.FailFlushed(cause, false); buffer.Close(cause, true); _ = pipeline.FireUserEventTriggered(ChannelOutputShutdownEvent.Instance); }
/// <summary> /// Flush the content of the given buffer to the remote peer. /// </summary> protected abstract void DoWrite(ChannelOutboundBuffer input);
//protected override IChannelUnsafe NewUnsafe() => new DefaultServerUnsafe(this); protected override void DoWrite(ChannelOutboundBuffer buf) => throw new NotSupportedException();