Commit Graph

1496 Commits

Author SHA1 Message Date
Norman Maurer
c08c965117 Use OneTimeTask where possible to reduce object creation
Motivation:

We should use OneTimeTask where possible to reduce object creation.

Modifications:

Replace Runnable with OneTimeTask

Result:

Less object creation
2015-11-20 14:28:28 -08:00
Norman Maurer
01da38d21a Reduce memory footprint of DefaultChannelPipeline
Motivation:

If you need to handle a lot of concurrent connections (1M+) the memory footprint can be problem.

Modifications:

- Lazy create the IdentityHashMap that holds the EventExecutor mappings as this is not needed by most users anyway
- Use a sane initial capacity when creating the IdentityHashMap

Result:

Smaller memory footprint of DefaultChannelPipeline
2015-11-20 06:53:51 -08:00
Norman Maurer
19950f89e4 Remove unnecessary reference to AbstractChannel from AbstractChannelHandlerContext
Motivation:

We not need to store another reference to AbstractChannel as we can access it through DefaultChannelHandlerContext.

Modifications:

Remove reference.

Result:

Cleaner code.
2015-11-20 06:35:31 -08:00
Norman Maurer
d6c23d0af9 Remove HashMap for lookup name / ctx from DefaultChannelPipeline to reduce memory footprint
Motivation:

If you start to have 1M+ concurrent connections memory footprint can be come a big issue. We should try to reduce it as much as possible in the core of netty.

Modifications:

- Remove HashMap that was used to store name to ctx mapping. This was only used for validation and access a handler by name. As a pipeline is not expected to be very long (like 100+ handlers) we can just walk the linked list structure to find the ctx with a given name.

Result:

Less memory footprint of the DefaultChannelPipeline.
2015-11-20 06:10:39 -08:00
pieteradejong
f571f7279b fixed word - issue #4469 2015-11-19 07:32:47 -08:00
Sergio Bossa
60a240316a Improved DefaultChannelPipeline#destroy() to avoid spinning continuously in case of custom executors.
Motivation:

The previous DefaultChannelPipeline#destroy() implementation, introduced in #3156, is suboptimal as it can cause the for loop to continuously spin if the executor used by a given handler is unable to "recognize" the event loop.
It could be objected that it's the custom executor responsibility to properly implement the inEventLoop() method, but some implementetaions might not be able to do that for performance reasons, and even so, it's always better to be safe against API misuse, in particular when it is not possible to fail fast and the alternative is rather some sutle behaviour.

Modifications:

The patch simply avoids the recursive spin by explicitly passing the "in event loop" condition as a boolean parameter, preserving the same guarantees offered by #3156. A unit test has also been added.

Result:

All channel events are correctly called and no high CPU usage is seen anymore.
2015-11-06 19:37:41 +01:00
Norman Maurer
8ecfd58714 Remove synchronization overhead on generateName.
Motivation:

Changing the chache of generated names to use a cache per thread. This will remove the bottleneck when many eventloops are used and names need to generate.

Modifications:

Use a FastThreadLocal to store the cached names.

Result:

Less locking between threads.
2015-11-04 20:41:06 +01:00
Norman Maurer
69b5aefd09 [maven-release-plugin] prepare release netty-4.0.33.Final 2015-11-03 14:18:17 +01:00
Norman Maurer
c42d710c6e [#4363] Improve size calculation of messages when written from outside the EventLoop
Motiviation:

If a user writes from outside the EventLoop we increase the pending bytes of the outbound buffer before submitting the write request. This is done so the user can stop writing asap once the channel turns unwritable. Unfortunally this doesn't take the overhead of adding the task into the account and so it is very easy for an user to full up the task queue. Beside this we use a value of 0 for an unown message by default which is not ideal.

Modifications:

- port the message calculation we used in netty 3.x into AbstractChannelHandlerContext and so better calculate the overhead of a message that is submitted from outside the EventLoop
- change the default estimated size for an unknown message to 8.

Result:

Better behaviour when submiting writes from outside the EventLoop.
2015-10-28 21:34:26 +01:00
Norman Maurer
082e9cc722 [#4373] Fix assert error when trying to release Channel to closed FixedChannelPool
Motivation:

Once a FixedChannelPool was closed we must not allow to acquire or release Channels to prevent assert errors.

Modifications:

Fail release and acquire calls when FixedChannelPool is closed.

Result:

No more assert errors.1
2015-10-24 11:56:36 +02:00
Sky Ao
b79714ab5a change type definition of pipeline from DefaultChannelPipeline to ChannelPipeline 2015-10-10 20:16:07 +02:00
Norman Maurer
bd61b96efa Cleanup PendingWriteQueueTest
Motivation:

PendingWriteQueueTest needs some cleanup.

Modifications:

- Cleanup code to remove deprecation warnings
- use static imports

Result:

No more warnings
2015-10-10 20:01:48 +02:00
Norman Maurer
845a1a526a [#4316] Ensure pending tasks are run when EmbeddedChannel.close(...) or disconnect(...) is called.
Motivation:

We missed to run all pending tasks when EmbeddedChannel.close(...) or disconnect(...) was called. Because of this channelInactive(...) / channelUnregistered(...) of the handlers were never called.

Modifications:

Correctly run all pending tasks and cancel all not ready scheduled tasks when close or disconnect was called.

Result:

Correctly run tasks on close / disconnect and have channelInactive(...) / channelUnregistered(...) called.
2015-10-07 09:32:14 +02:00
Norman Maurer
696a287736 [maven-release-plugin] prepare for next development iteration 2015-09-30 09:31:26 +02:00
Norman Maurer
fb2d562306 [maven-release-plugin] prepare release netty-4.0.32.Final 2015-09-30 09:28:40 +02:00
Norman Maurer
da39e601e0 Ensure close caused by write will happen before write promise is notified
Motiviation:

We need to ensure the actual close to the transport takes place before the promsie of the write is notified that triggered it. This is needed as otherwise Channel.isActive(), isOpen() and isWritable() may return true even if the Channel should be closed already.

Modifications:

- Ensure the close takes place first

Result:

ChannelFutureListener will see the correct state of the Channel.
2015-09-16 20:35:34 +02:00
Norman Maurer
7961138f52 [#4205] Correctly set EPOLLOUT flag whe writeBytes(...) was not able to write everything
Motivation:

writeBytes(...) missed to set EPOLLOUT flag when not all bytes were written. This could lead to have the EpollEventLoop not try to flush the remaining bytes once the socket becomes writable again.

Modifications:

- Move setting EPOLLOUT flag logic to one point so we are sure we always do it.
- Move OP_WRITE flag logic to one point as well.

Result:

Correctly try to write pending data if socket becomes writable again.
2015-09-16 07:28:28 +02:00
Norman Maurer
bd928eaa38 [maven-release-plugin] prepare for next development iteration 2015-09-02 08:58:54 +02:00
Norman Maurer
26bbcc38c2 [maven-release-plugin] prepare release netty-4.0.31.Final 2015-09-02 08:57:57 +02:00
Scott Mitchell
71308376ca LocalChannel write when peer closed leak
Motivation:
If LocalChannel doWrite executes while the peer's state changes from CONNECTED to CLOSED it is possible that some promise's won't be completed and buffers will be leaked.

Modifications:
- Check the peer's state in doWrite to avoid a race condition

Result:
All write operations should release, and the associated promise should be completed.
2015-09-01 13:17:05 -07:00
Scott Mitchell
e3f1416478 LocalChannelWrite event sequencing issue
Motivation:
https://github.com/netty/netty/pull/4143 addressed a few ordering issues but an ordering issue still remained if the Promise for a write completes, and a listener of that promise does a write on a peer channel. The ordering was subject to how potentially 2 different executors would run a task, but it should be coordinated such that the first write is read first.

Modifications:
- Keep track of the finishPeerRead task run on the executor if necessary and ensure it completes before current channel read occurs

Result:
Ordering of events for echo type situations is preserved.
2015-08-28 11:28:55 -07:00
Scott Mitchell
37eedb60fe LocalChannel Event Ordering Error
Motivation:
When a LocalChannel write operation occurs, the promise associated with the write operation is marked successful when it is added to the peer's queue, but before the peer has actually received the data. If the promise callback closes the channel then a race condition exists where the close event may occur before the data is delivered. We should preserve ordering of events.

Modifications:
- LocalChannel should track when a write is in progress, and if a close operation happens make sure the peer gets all pending read operations.

Result:
LocalChannel preserves order of operations.
Fixes https://github.com/netty/netty/issues/4118
2015-08-28 09:23:31 -07:00
Christopher Probst
93d2e86ed0 Fix race condition of DefaultChannelGroup by introducing a closed flag.
Motivation:

Doc of ChannelGroup says, that it can be used to manage server and child channels at once.
However, in DefaultChannelGroup, there is a race condition. When a server channel accepts a child, it schedules its
registration on an event loop, which takes some time. If the ChannelGroup, which is supposed
to close server and child channels at once, is closed after the child channel has been scheduled
for registration and before this registration actually happens, this child channel is not closed
and remains connected. This could lead to connection leaks.

Modifications:

To fix this, the DefaultChannelGroup is changed to has a closed flag.
This flag is set to true, just before the close() method is actually closing channels.
The add() method checks after adding a new channel, if this flag has been set to true.
If yes, the new channel is closed. If not, we have the guarantee, that this channel will be
closed by the ChannelGroup, because setting the closed flag to true happens-before closing any channels.

This behaviour can be activated by two new constructors. The old constructors are still there and behave like before.
Therefore, no existing code should be affected directly.

Result:

If activating this feature, the DefaultChannelGroup can be used, for managing server and child channels at once.
But this activating this feature means also, that a ChannelGroup cannot be reused after calling close().
2015-08-27 09:48:56 +02:00
Trustin Lee
5eea4d7ea2 Fix compilation errors 2015-08-18 12:42:01 +09:00
Ivan Bahdanau
b46e07089d Unhealthy channel is not offered back to the pool.
Motivation:
When releasing unhealthy channel back to a pool we don't have to offer it since on acquire it will be discarded anyways.
 Also checking healthiness at release is a good idea so we don't end up having tons of unhealthy channels in the pool(unless they became unhealthy after being offered)

Modifications:
private SimpleChannelPool.offerIfHealthy() method added that is called from SimpleChannelPool.doReleaseChannel(). SimpleChannelPool.offerIfHealthy() offers channel back to pool only if channel is healthy.
Otherwise it throws setFailure exception to the promise.

 Result:
The pool is now much cleaner and not spammed with unhealthy channels.

Added ability to choose if channel health has to be validated on release by passing boolean flag.

Motivation:
Depending on performance preferences and individual use cases sometimes we would like to be able force health check of a channel at release time and do not offer it back to the pool. Other times we would want to just release channel and offer it back to the pool and check health only when we try to acquire that channel from the pool. See more details here: https://github.com/netty/netty/issues/4077#issuecomment-130461684

Modifications:
Future<Void> release(Channel channel, Promise<Void> promise, boolean offerHealthyOnly);
The offerHealthyOnly boolean flag allows developers to choose whether to do channel validation before offering it back to pool or not.
Appropriate modifications made to hierarchy of implementations of ChannelPool. offerHealthyOnly=true will force channel health to be checked before offering back to pool. offerHealthyOnly=false  will ignore channel health check and will just try just offer it back to the pool
 offerHealthyOnly=true by default.

Result:
Channel health check before offer back to pool is controlled by a flag now.

Code changed to satisfy checkstyle requirements.

Motivation:
Code needs to satisfy checkstyle requirements.

Modifications:
 SimpleChannelPool.java:279 line split to be less then 120 characters.
 SimpleChannelPool.java:280:31 space added after '{'
 SimpleChannelPool.java:282:17 space added after '{'
 SimpleChannelPoolTest.java:198 - extra white space line removed.

Result:
Code satisfies checkstyle requirements.

 offerHealthyOnly is passed as a constructor parameter now.

Motivation:
Instead of passing offerHealthyOnly as a method parameter it is better to pass it in as SimpleChannelPool or FixedChannelPool constructor.

Modifications:
 Redundant release method that takes offerHealthyOnly removed from ChannelPool.
 offerHealthyOnly parameter added to constructor for FixedChannelPool and SimpleChannelPool.

Result:
SimpleChannelPool and FixedChannelPool are now take offerHealthyOnly as a constructor parameter. Default behavior is: offerHealthyOnly=true.

Code changed to satisfy checkstyle requirements.

Motivation:
Code needs to satisfy checkstyle requirements.

Modifications:
 SimpleChannelPool.java:84: line made to be no longer then 120 characters.
 SimpleChannelPool.java:237: extra white space line removed.

Result:
Code satisfies checkstyle requirements.

Tests do not need to be too  copled to the code. Exception message should not be validated

Motivation:
We don't need our tests to be too coupled to the code. Exception type validation in tests is just good enough.

Modifications:
Exception validation message removed from SimpleChannelPoolTest.testUnhealthyChannelIsNotOffered() test.

Result:
The SimpleChannelPoolTest test is less coupled to the code now.

Stack trace set to empty for UNHEALTHY_NON_OFFERED_TO_POOL.

Motivation:
We don't need stack trace for UNHEALTHY_NON_OFFERED_TO_POOL.

Modifications:
Added  UNHEALTHY_NON_OFFERED_TO_POOL.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE) to static init block.

Result:
UNHEALTHY_NON_OFFERED_TO_POOL's stack trace set to empty.

Minor code re-factorings.

Motivation:
For better code readability we need to apply several minor code re-factorings.

Modifications:
javadocs true -> {@code true}
offerHealthyOnly variable name changed to releaseHeathCheck
<p/> -> <p> in javadocs
offerHealthyOnly removed from doReleaseChannel as it not needed there.

Result:
Code quality is improved.

Code changed to satisfy checkstyle requirements.

Motivation:
Code needs to satisfy checkstyle requirements.

Modifications:
SimpleChannelPool.java:87: line made to be no longer then 120 characters.

Result:
Code satisfies checkstyle requirements.

Pull request needs to contain only necessary changes

Motivation:
The pull request should not contain unnecessary changes that are not needed as part of required functionality of pull request.

Modifications:
private void doReleaseChannel(final Channel channel, final Promise<Void> promise) - >  private void doReleaseChannel(Channel channel, Promise<Void> promise)

Result:
Pull request contains less unnecessary modifications.
2015-08-17 15:42:50 -07:00
Norman Maurer
6d86856e40 Fixing compile error, introduce by 4b41ae73f3 2015-08-12 14:16:24 +02:00
Ivan Bahdanau
4b41ae73f3 Improve the logic around acquire channel function is improved.
Motivation:
The acquire channel function resulted in calling itself several times in case when channel polled from the pool queue was unhealthy, which resulted FixedChannelPool to be called several times which in it's turn caused FixedChannelPool.acquire() to be called and resulted into acquireChannelCount to be unnecessary increased.
Example use case:
1) Create FixedChannelPool instance with one channel in the pool: new FixedChannelPool(cb, handler, 1)
2) Acquire channel A from the pool
3) close the channel A
4) Return it back to the pool
5) Acquire channel from the same pool again
Expected result:
new channel created and acquired, channel A that has been closed discarded and removed from the pool from being unhealthy
Actual result:
Channel A had been removed from the pool, how ever the new channel had never be acquired, instead the request to acquire had been added to the pending queue in FixedChannelPool and the acquireChannelCount is increased by one. The reason is that at the time when SimpleChannelPool figured out that the channel was unhealthy called FixedChannelPool.acquire to try to acquire new channel, how ever the request was added to the pendingTakQueue because by the time when FixedChannelPool.acquire was called, the acquireChannelCount was already "1" so new channel ould not be created cause of maxChannelsLimit=1.

Modifications:
The suggested approach modifies the SimpleChannelPool in a way so that when channel detected to be unhealthy it calls private method SimpleChannelPool.acquireHealthyFromPoolOrNew() which guarantees that SimpleChannelPool actually either finds a healthy channel in the pool and returns it or causes the promise.cause() in case when new channel was failed to be created.

 Result:
The  ```acquiredChannelCount``` is now calculated correctly as a result of SimpleChannelPool.acquire() of not being recursive on overridable acquire method.
2015-08-12 06:36:04 +02:00
fratboy
b6dc1a4cec Correctly count acquired channels when timeout occurs in FixedChannelPool
Motivation:

We don't decrease acquired channel count in FixedChannelPool when timeout occurs by AcquireTimeoutAction.NEW and eventually fails.

Modifications:

Set AcquireTask.acquired=true to call decrementAndRunTaskQueue when timeout action fails.

Result:

Acquired channel count decreases correctly.
2015-07-30 07:56:08 +02:00
Norman Maurer
148692705c [maven-release-plugin] prepare for next development iteration 2015-07-24 10:11:44 +02:00
Norman Maurer
11cc2d5197 [maven-release-plugin] prepare release netty-4.0.30.Final 2015-07-24 09:54:20 +02:00
Norman Maurer
467a07aa30 [#3988] Correctly count acquired channels in FixedChannelPool
Motivation:

We missed to correctly count acquired channels in FixedChannelPool which could produce an assert error.

Modifications:

Only try to decrement acquired count if the channel was really acuired.

Result:

No more assert error possible.
2015-07-21 21:05:17 +02:00
Minwoo Jung
3063b9cccf Update ChannelConfig.java
{@link ByteBufAllocator} -> {@link MessageSizeEstimator} on
https://github.com/netty/netty/blob/4.0/transport/src/main/java/io/netty/channel/ChannelConfig.java#L248
2015-07-19 18:10:38 +02:00
Norman Maurer
ae32fd4f0b [#3967] Guard against NPE in PendingWriteQueue
Motivation:

If the Channel is already closed when the PendingWriteQueue is created it will generate a NPE when add or remove is called later.

Modifications:

Add null checks to guard against NPE.

Result:

No more NPE possible.
2015-07-17 21:31:07 +02:00
Norman Maurer
9e8edb3093 Allow to construct EmbeddedChannel without a ChannelHandler
Motivation:

In 4.1 and master branch we allow to construct an EmbeddedChannel without ChannelHandlers, we should do the same in 4.0.

Modifications:

Backport behavoir.

Result:

It's now possible to construct an EmbeddedChannel without any ChannelHandler
2015-07-17 21:29:45 +02:00
Effective Light
88a2c6ef49 Fix DatagramChannel javadoc
there seems to be an extra arrow incorrectly placed there when trying to link "Channel."
2015-07-12 20:20:28 +02:00
Norman Maurer
d295321bb4 Reduce memory usage by EmbeddedChannel
Motivation:

When using an EmbeddedChannel often it either does inbound or outbound processing which means we only often need one queue.

Modifications:

Lazy init the inbound and outbound message queues.

Result:

Less memory usage.
2015-07-08 10:43:19 +02:00
Norman Maurer
c9e71aafbd [#3780] Handle ChannelInitializer exception in exceptionCaught()
Motivation:

At the moment we directly closed the Channel when an exception accoured durring initChannel(...) without giving the user any way to do extra or special handling.

Modifications:

Handle the exception in exceptionCaught(...) of the ChannelInitializer which will by default log and close the Channel. This way the user can override this.

Result:

More felixible handling of exceptions.
2015-07-07 09:12:46 +02:00
Norman Maurer
287ac6d328 [#3921] EmbeddedChannel should add ChannelHandlers once registered
Motivation:

Currently in EmbeddedChannel we add the ChannelHandlers before the Channel is registered which leads to have the handlerAdded(...) callback
be called from outside the EventLoop and also prevent the user to obtain a reference to the EventLoop in the callback itself.

Modifications:

Delay adding ChannelHandlers until EmbeddedChannel is registered.

Result:

Correctly call handlerAdded(...) after EmbeddedChannel is registered.
2015-07-07 08:47:18 +02:00
Norman Maurer
5804cb3e1c ServerBootstrap.handler(...) will add handler before Channel is registered.
Motivation:

If you set a ChannelHandler via ServerBootstrap.handler(...) it is added to the ChannelPipeline before the Channel is registered. This will lead to and IllegalStateException if a user tries to access the EventLoop in the ChannelHandler.handlerAdded(...) method.

Modifications:

Delay the adding of the ChannelHandler until the Channel was registered.

Result:

No more IllegalStateException.
2015-07-07 08:44:02 +02:00
Norman Maurer
1da998bc7c [maven-release-plugin] prepare for next development iteration 2015-06-23 11:08:27 +02:00
Norman Maurer
4c482c1215 [maven-release-plugin] prepare release netty-4.0.29.Final 2015-06-23 11:07:56 +02:00
a-mkarjalainen
1dfbab0642 Fix broken constructor chaining for FixedChannelPool class.
Motivation:

Only one of the three FixedChannelPool constructors checks for the constructor
arguments. Therfore it was possible to create a pool with zero maxConnections.

This change chains all constructors together, so that the last one
in the chain always checks the validity of the arguments, regardless of the
constructor used.

Result:

It is no longer possible to create a FixedChannelPool instance with invalid
maxConnections or maxPendingAcquires parameters.
2015-06-18 20:11:41 +02:00
Norman Maurer
bb17071ea0 [#3881] FixedChannelPool creates 1 more channel than maxConnections
Motivation:

FixedChannelPool should enforce a number of maximal used channels, but due a bug we fail to correctly enforce this.

Modifications:

Change check to correctly only acquire channel if we not hit the limit yet.

Result:

Correct limiting.
2015-06-16 20:10:08 +02:00
Scott Mitchell
f2796bae29 Rename method from bytesBeforeUnWritable to bytesBeforeUnwritable
Motiviation:
To be consistent with changes in 4.1 and master.  This is a new method and should not impact compatibility.

Modifications:
- ChannelOutboundBuffer method bytesBeforeUnWritable -> bytesBeforeUnwritable

Result:
Consistent interface for 4.0, 4.1, and master.
2015-06-12 12:42:44 -07:00
Norman Maurer
81d5c7c198 Allow to receive a ChannelGroupFuture that will be notified once all Channels are closed.
Motivation:

It's useful to be able to be notified once all Channels that are part of the ChannelGroup are notified. This can for example be useful if you want to do a graceful shutdown.

Modifications:

- Add ChannelGroup.newCloseFuture(...) which will be notified once all Channels are notified that are part of the ChannelGroup at the time of calling.

Result:

Easier to be notified once all Channels within a ChannelGroup are closed.
2015-06-12 14:03:31 +02:00
Scott Mitchell
14da966a41 ChannelOutboundBuffer bytes before writable accessor
Motiviation:
There are currently no accessors which provide visbility into how many bytes must be written in order for a writability change to occur. This feature would be useful for codecs which intent to control how many bytes are queued at any given time.

Modifications:
- add bytesBeforeUnWritable() which will give the number of bytes before the buffer (and associated channel) transitions to not writable
- add bytesBeforeWritable() which will give the number of bytes that must be drained from the queue until the channel becomes writable.

Result:
More visibility into writability for the ChannelOutboundBuffer.
2015-06-10 08:44:26 -07:00
Norman Maurer
5d4e34b021 [#3837] Null out ByteBuffer[] array once done
Motivation:

the ByteBuffer[] that we keep in the ThreadLocal are never nulled out which can lead to have ByteBuffer instances sit there forever.
This is even a bigger problem if nioBuffer() of ByteBuffer returns a new ByteBuffer that can not be destroyed by ByteBuffer.release().

Modifications:

Null out ByteBuffer array after processing.

Result:

No more dangling references after done.
2015-06-04 12:33:13 +02:00
Jean-Rémi Desjardins
1f3e6be32b Fix typo 2015-06-02 13:02:10 +02:00
Trustin Lee
add630c957 Fix sporadic assertion failure in SingleThreadEventLoopTest
Motivation:

SingleThreadEventLoopTest.testScheduleTaskAtFixedRate() fails often due to:

- too little tolerance
- incorrect assertion (it compares only with the previous timestamp)

Modifications:

- Increase the timestamp difference tolerance from 10ms to 20ms
- Improve the timestamp assertion so that the comparison is performed against the first recorded timestamp
- Misc: Fix broken Javadoc tag

Result:

More build stability
2015-06-01 14:44:49 +09:00
Norman Maurer
76d51b514a Mention correct order in SimplechannelPool javadocs 2015-05-29 20:56:40 +02:00