Commit Graph

3907 Commits

Author SHA1 Message Date
Trustin Lee
b47fc77522 Add PooledByteBufAllocator + microbenchmark module
This pull request introduces the new default ByteBufAllocator implementation based on jemalloc, with a some differences:

* Minimum possible buffer capacity is 16 (jemalloc: 2)
* Uses binary heap with random branching (jemalloc: red-black tree)
* No thread-local cache yet (jemalloc has thread-local cache)
* Default page size is 8 KiB (jemalloc: 4 KiB)
* Default chunk size is 16 MiB (jemalloc: 2 MiB)
* Cannot allocate a buffer bigger than the chunk size (jemalloc: possible) because we don't have control over memory layout in Java. A user can work around this issue by creating a composite buffer, but it's not always a feasible option. Although 16 MiB is a pretty big default, a user's handler might need to deal with the bounded buffers when the user wants to deal with a large message.

Also, to ensure the new allocator performs good enough, I wrote a microbenchmark for it and made it a dedicated Maven module. It uses Google's Caliper framework to run and publish the test result (example)

Miscellaneous changes:

* Made some ByteBuf implementations public so that those who implements a new allocator can make use of them.
* Added ByteBufAllocator.compositeBuffer() and its variants.
* ByteBufAllocator.ioBuffer() creates a buffer with 0 capacity.
2012-12-13 22:35:06 +09:00
Norman Maurer
9d42acbc2a [#803] Make sure the right EventExecutor is used after re-register a Channel to another EventLoop 2012-12-13 10:38:44 +01:00
Veebs
0c5fd38eb6 #722 - Make WebSocketClientHandshakerFactory a static utility class 2012-12-13 07:34:05 +01:00
Veebs
2704efc056 Added documentation to websocket classes. 2012-12-13 07:13:46 +01:00
Norman Maurer
2903b91e66 [#798] Not call fireExceptionCaught(..) for outbound operations as the future will get notified anyway and so it is redundant.
Outbound operations are those which are part of the ChannelOutboundInvoker interface.
2012-12-10 20:12:59 +01:00
Norman Maurer
3e783e1b5e Fix bug in DefaultChannelHandlerContext where ByteBridge does not handle bounded buffers well 2012-12-10 16:47:24 +01:00
Trustin Lee
321b18d4d1 Fix test failures n LocalTransportThreadModelTest
testConcurrentMessageBufferAccess() assumes the outbound/inbound byte buffers are unbounded.  Because PooledByteBuf is bounded, the test did not pass.

The fix makes an assumption that ctx.flush() or fireInboundBufferUpdated() will make the next buffer consumed immediately, which is not the case in the real world.  Under network congestion, a user will see IndexOutOfBoundsException if the user's handler implementation writes boundlessly into inbound/outbound buffers.
2012-12-10 16:38:20 +01:00
Norman Maurer
bf8345999c Fix release of buffers in ByteToMessageCodec and MessageToMessageCodec 2012-12-08 12:59:32 +01:00
Norman Maurer
312810d415 [#795] Fix WebSocketClientHandshaker13 and WebSocketClientHandshaker08 finishHandshake() method. 2012-12-07 20:14:11 +01:00
Shawn Silverman
e5a8958ed6 Fixed some 120-character line checkstyle problems. 2012-12-07 06:31:21 +01:00
Shawn Silverman
8be43903e1 Added more Javadocs to the 'replace' methods, see Netty issue 756. 2012-12-07 06:31:21 +01:00
Norman Maurer
038bcfc4ff [#792] Implement freeInboundBuffer(...) and freeOutboundBuffer(...) methods in ByteToByteCodec 2012-12-06 20:57:08 +01:00
Norman Maurer
16b05def59 Fix possible NPE which accour if the inbound/outbound buffer was not lazy allocated yet 2012-12-06 19:36:53 +01:00
Trustin Lee
51e6519b67 Replace UnsafeByteBuf with ByteBuf.unsafe() again
* UnsafeByteBuf is gone. I added ByteBuf.unsafe() back.
* To avoid extra instantiation, all ByteBuf implementations implement the ByteBuf.Unsafe interface.
* To hide this implementation detail, all ByteBuf implementations are package-private.
* AbstractByteBuf and SwappedByteBuf are public and they do not implement ByteBuf.Unsafe because they don't need to.
* unwrap() is not an unsafe operation anymore.
* ChannelBuf also has unsafe() and Unsafe. ByteBuf.Unsafe extends ChannelBuf.unsafe(). ChannelBuf.unsafe() provides free() operation so that a user does not need to down-cast the buffer in freeInbound/OutboundBuffer().
2012-12-05 19:28:56 +09:00
Norman Maurer
a9af028077 [#787] Move the socks package to the right place 2012-12-04 09:14:05 +01:00
Trustin Lee
9c0b2ad75c Update netty-build to the latest version
From this commit, checkstyle considers an unnecessary empty line as a
violation.
2012-12-04 16:46:46 +09:00
Norman Maurer
85c570505b [maven-release-plugin] prepare for next development iteration 2012-12-03 20:34:05 +01:00
Norman Maurer
17d77ed160 [maven-release-plugin] prepare release netty-4.0.0.Alpha8 2012-12-03 20:33:49 +01:00
Norman Maurer
760cc95115 Cleanup 2012-12-03 19:58:03 +01:00
Norman Maurer
f9225df0a9 Add back support for FileRegion. See #668 2012-12-03 12:08:17 +01:00
Trustin Lee
33c0c89fef Remove unnecessary empty lines 2012-12-03 19:58:13 +09:00
alexey
32f2122e64 fix socks5-auth subnegotiation version handling
Conflicts:

	codec-socks/src/main/java/io/netty/codec/socks/SocksAuthRequestDecoder.java
2012-12-03 10:47:07 +01:00
Norman Maurer
717bde05e2 [786] Fix possible corruption of first WebSocketFrame caused by WebSocketServerHandshaker* 2012-12-02 19:55:45 +01:00
Trustin Lee
e45ab1d182 Fix a checkstyle error 2012-12-02 22:03:11 +09:00
Trustin Lee
5f9090a7f0 Fix invalid memory access in AIO writes
To perform writes in AioSocketChannel, we get a ByteBuffer view of the
outbound buffer and specify it as a parameter when we call
AsynchronousSocketChannel.write().

In most cases, the write() operation is finished immediately.  However,
sometimes, it is scheduled for later execution.  In such a case, there's
a chance for a user's handler to append more data to the outbound
buffer.

When more data is appended to the outbound buffer, the outbound buffer
can expand its capacity by itself.  Changing the capacity of a buffer is
basically made of the following steps:

1. Allocate a larger new internal memory region.
2. Copy the current content of the buffer to the new memory region.
3. Rewire the buffer so that it refers to the new region.
4. Deallocate the old memory region.

Because the old memory region is deallocated at the step 4, the write
operation scheduled later will access the deallocated region, leading
all sort of data corruption or even segfaults.

To prevent this situation, I added suspendIntermediaryDeallocations()
and resumeIntermediaryDeallocations() to UnsafeByteBuf.

AioSocketChannel.doFlushByteBuf() now calls suspendIntermediaryDealloc()
to defer the deallocation of the old memory regions until the completion
handler is notified.
2012-12-02 21:50:33 +09:00
Trustin Lee
72e0acbe84 Use correct timeout in AioSocketChannel.beginRead() 2012-12-02 20:38:59 +09:00
Trustin Lee
bfe2a96505 Fix AssertionError from AsyncSocketChannel.beginRead()
An AssertionError is triggered by a ByteBuf when beginRead() attempts to
access the buffer which has been freed already.  This commit ensures the
buffer is not freed before performing an I/O operation.

To determine if the buffer has been freed, UnsafeByteBuf.isFreed() has
been added.
2012-12-02 20:17:53 +09:00
Trustin Lee
95e8ec1db9 Handle the case where JDK notifies aync I/O handler immediately
After some debugging, I found that JDK AIO implementation often performs
I/O immediately from the caller thread if the caller thread is the I/O
thread, and notifies the completion handler also immediately.  This
commit handles such a case correctly during reads and writes.

Additionally, this commit also changes SingleThreadEventExecutor to let
it handle unexpected exceptions such as AssertionError in a robus
manner.
2012-12-02 20:03:35 +09:00
Trustin Lee
00c4b944e4 Fix more inspector warnings introduced by recent mergences 2012-12-01 00:10:42 +09:00
Trustin Lee
6208c62888 Fix inspector warnings introduced by recent mergences 2012-11-30 23:01:57 +09:00
Trustin Lee
818a7b42a3 Fix all Xlint:unchecked warnings 2012-11-30 22:49:51 +09:00
Matthias Wessendorf
b33df8399e fixing type on event/send argument 2012-11-27 19:29:29 +01:00
Trustin Lee
c661c344ed Add proper toString() implementation for internal ChannelFactory impls 2012-11-26 17:15:14 +09:00
Trustin Lee
918666481e Ensure lazily instantiated outbound buffers are instantiated from the event loop 2012-11-26 17:14:21 +09:00
Trustin Lee
74749ec15d Implement Bootstrap.toString() and use it in the testsuite
By implementing Bootstrap.toString() and printing it for each test case helps us figure out which transport is causing a trouble.
2012-11-26 16:14:24 +09:00
Trustin Lee
089d022e03 Remove redundant exception message 2012-11-26 15:34:09 +09:00
Trustin Lee
9018f8e5ca Enable assertions only for Netty classes 2012-11-26 15:01:13 +09:00
Trustin Lee
d7f0351a85 Add JVM options for faster test runs 2012-11-26 14:53:15 +09:00
Trustin Lee
40373526ce Remove unexpected bad text
Doh!
2012-11-26 14:41:12 +09:00
Trustin Lee
5b68f00382 Make CompatibleMarshallingDecoder discard the inbound buffer once TooLongFrameException is raised
(See #768)

Once too long object is received, CompatibleMarshallingDecoder has to
discard all input from now on, just like MarshallingDecoder does.
Otherwise, the decoder will raise more exceptions because the decoder
has no idea anymore where the object starts.

Before this fix, SerialThreadLocalCompatibleMarshallingDecoderTest
logged many additional exceptions raised by the decoder after test is
finished.
2012-11-26 14:40:18 +09:00
Norman Maurer
d7d8503f5c Add a line-based frame decoder with good performance.
Using DelimiterBasedFrameDecoder with Delimiters.lineDelimiter() has
quadratic performance in the size of the input buffer.  Needless to
say, the performance degrades pretty quickly as the size of the buffer
increases.  Larger MTUs or loopback connections can make it so bad that
it appears that the code is "busy waiting", when in fact it's spending
almost 100% of the CPU time in DelimiterBasedFrameDecoder.indexOf().

Add a new LineBasedFrameDecoder that decodes line-delimited frames
in O(n) instead of DelimiterBasedFrameDecoder's O(n^2) implementation.
In OpenTSDB's telnet-style protocol decoder this resulted in throughput
increases of an order of magnitude.

Change DelimiterBasedFrameDecoder to automatically detect when the
frames are delimited by line endings, and automatically switch to
using LineBasedFrameDecoder under the hood.  This means that all Netty
applications out there that using the combo DelimiterBasedFrameDecoder
with Delimiters.lineDelimiter() will automatically benefit from the
better performance of LineBasedFrameDecoder, without requiring a code
change.
2012-11-25 13:36:55 +01:00
Daniel Bevenius
b1cd953d02 Adding WebSocket Example using WebSocketServerProtocolHandler. 2012-11-25 11:44:19 +01:00
Trustin Lee
dbbc6ad73f Reduce the chance of RejectedExecutionException
When a Netty application shuts down, a user often sees a REE
(RejectedExecutionException).

A REE is raised due to various reasons we don't have control over, such
as:

- A client connects to a server while the server is shutting down.

- An event is triggered for a closed Channel while its event loop is
  also shutting down.  Some of them are:
  - channelDeregistered (triggered after a channel is closed)
  - freeIn/OutboundBuffer (triggered after channelDeregistered)
  - userEventTriggered (triggered anytime)

To address this issue, a new method called confirmShutdown() has been
added to SingleThreadEventExecutor.  After a user calls shutdown(),
confirmShutdown() runs any remaining tasks in the task queue and ensures
no events are triggered for last 2 seconds.  If any task are added to
the task queue before 2 seconds passes, confirmShutdown() prevents the
event loop from terminating by returning false.

Now that SingleThreadEventExecutor needs to accept tasks even after
shutdown(), its execute() method only rejects the task after the event
loop is terminated (i.e. isTerminated() returns true.)  Except that,
there's no change in semantics.

SingleThreadEventExecutor also checks if its subclass called
confirmShutdown() in its run() implementation, so that Netty developers
can make sure they shut down their event loop impementation correctly.

It also fixes a bug in AioSocketChannel, revealed by delayed shutdown,
where an inboundBufferUpdated() event is triggered on a closed Channel
with deallocated buffers.

Caveats:

Because SingleThreadEventExecutor.takeTask() does not have a notion of
timeout, confirmShutdown() adds a dummy task (WAKEUP_TASK) to wake up
takeTask() immediately and instead sleeps hard-coded 100ms.  I'll
address this issue later by modifying takeTask() times out dynamically.

Miscellaneous changes:

SingleThreadEventExecutor.wakeup() now has the default implementation.
Instead of interrupting the current thread, it simply adds a dummy task
(WAKEUP_TASK) to the task queue, which is more elegant and efficient.
NioEventLoop is the only implementation that overrides it. All other
implementations' wakeup()s were removed thanks to this change.
2012-11-22 20:36:13 +01:00
Trustin Lee
81e2db10fa ByteBufAllocator API w/ ByteBuf perf improvements
This commit introduces a new API for ByteBuf allocation which fixes
issue #643 along with refactoring of ByteBuf for simplicity and better
performance. (see #62)

A user can configure the ByteBufAllocator of a Channel via
ChannelOption.ALLOCATOR or ChannelConfig.get/setAllocator().  The
default allocator is currently UnpooledByteBufAllocator.HEAP_BY_DEFAULT.

To allocate a buffer, do not use Unpooled anymore. do the following:

  ctx.alloc().buffer(...); // allocator chooses the buffer type.
  ctx.alloc().heapBuffer(...);
  ctx.alloc().directBuffer(...);

To deallocate a buffer, use the unsafe free() operation:

  ((UnsafeByteBuf) buf).free();

The following is the list of the relevant changes:

- Add ChannelInboundHandler.freeInboundBuffer() and
  ChannelOutboundHandler.freeOutboundBuffer() to let a user free the
  buffer he or she allocated. ChannelHandler adapter classes implement
  is already, so most users won't need to call free() by themselves.
  freeIn/OutboundBuffer() methods are invoked when a Channel is closed
  and deregistered.

- All ByteBuf by contract must implement UnsafeByteBuf. To access an
  unsafe operation: ((UnsafeByteBuf) buf).internalNioBuffer()

- Replace WrappedByteBuf and ByteBuf.Unsafe with UnsafeByteBuf to
  simplify overall class hierarchy and to avoid unnecesary instantiation
  of Unsafe instances on an unsafe operation.

- Remove buffer reference counting which is confusing

- Instantiate SwappedByteBuf lazily to avoid instantiation cost

- Rename ChannelFutureFactory to ChannelPropertyAccess and move common
  methods between Channel and ChannelHandlerContext there. Also made it
  package-private to hide it from a user.

- Remove unused unsafe operations such as newBuffer()

- Add DetectionUtil.canFreeDirectBuffer() so that an allocator decides
  which buffer type to use safely
2012-11-22 15:10:59 +09:00
Norman Maurer
2adebc4c54 [#755] SPDY: fix header block values truncation in decompression 2012-11-20 20:09:59 +01:00
Mike Heath
ff14feeb54 The handshake handler should not handle the exception and simply close the socket. The exception should be propagated to the WebSocketServerProtocolHandler to send the appropriate response and then close the socket. 2012-11-20 10:00:28 +01:00
Mike Heath
40e53b9b68 Fixed exception handling to call the exceptionCaught method in the current handler. By default the handler will call ctx.fireExceptionCaught which is what was happening before. 2012-11-20 10:00:27 +01:00
dantran
4107b08f29 Only generate OSGi manifest only at all-in-on sub module to reduce the complexity to the build 2012-11-19 06:27:18 +01:00
dantran
434c19da33 Clean maven-bundle-plugin warnings 2012-11-18 21:12:34 +01:00
Norman Maurer
524fac5184 [#748] Upgrade to yammer metrics 2.1.4 2012-11-18 12:23:44 +01:00