Commit Graph

56 Commits

Author SHA1 Message Date
Trustin Lee
85a2ba3752 Remove dead code
- Fixed #1557
2013-07-12 20:10:39 +09:00
Jeff Pinner
224f05e626 Use correct permission mode for java files 2013-07-10 21:58:12 +02:00
Norman Maurer
b57d9f307f Allow per-write promises and disallow promises on flush()
- write() now accepts a ChannelPromise and returns ChannelFuture as most
  users expected.  It makes the user's life much easier because it is
  now much easier to get notified when a specific message has been
  written.
- flush() does not create a ChannelPromise nor returns ChannelFuture.
  It is now similar to what read() looks like.
2013-07-11 00:49:48 +09:00
Trustin Lee
cbd8817905 Remove MessageList from public API and change ChannelInbound/OutboundHandler accordingly
I must admit MesageList was pain in the ass.  Instead of forcing a
handler always loop over the list of messages, this commit splits
messageReceived(ctx, list) into two event handlers:

- messageReceived(ctx, msg)
- mmessageReceivedLast(ctx)

When Netty reads one or more messages, messageReceived(ctx, msg) event
is triggered for each message.  Once the current read operation is
finished, messageReceivedLast() is triggered to tell the handler that
the last messageReceived() was the last message in the current batch.

Similarly, for outbound, write(ctx, list) has been split into two:

- write(ctx, msg)
- flush(ctx, promise)

Instead of writing a list of message with a promise, a user is now
supposed to call write(msg) multiple times and then call flush() to
actually flush the buffered messages.

Please note that write() doesn't have a promise with it.  You must call
flush() to get notified on completion. (or you can use writeAndFlush())

Other changes:

- Because MessageList is completely hidden, codec framework uses
  List<Object> instead of MessageList as an output parameter.
2013-07-09 23:51:48 +09:00
Norman Maurer
9c1b31d20a [#1535] Remove Channel.id() and so fix the possible leakage of the previous used Channel id map
The user can still use Channel.hashCode() for logging. It's just not 100% unique but should be good enough for most cases
2013-07-08 14:07:18 +02:00
Trustin Lee
14158070bf Revamp the core API to reduce memory footprint and consumption
The API changes made so far turned out to increase the memory footprint
and consumption while our intention was actually decreasing them.

Memory consumption issue:

When there are many connections which does not exchange data frequently,
the old Netty 4 API spent a lot more memory than 3 because it always
allocates per-handler buffer for each connection unless otherwise
explicitly stated by a user.  In a usual real world load, a client
doesn't always send requests without pausing, so the idea of having a
buffer whose life cycle if bound to the life cycle of a connection
didn't work as expected.

Memory footprint issue:

The old Netty 4 API decreased overall memory footprint by a great deal
in many cases.  It was mainly because the old Netty 4 API did not
allocate a new buffer and event object for each read.  Instead, it
created a new buffer for each handler in a pipeline.  This works pretty
well as long as the number of handlers in a pipeline is only a few.
However, for a highly modular application with many handlers which
handles connections which lasts for relatively short period, it actually
makes the memory footprint issue much worse.

Changes:

All in all, this is about retaining all the good changes we made in 4 so
far such as better thread model and going back to the way how we dealt
with message events in 3.

To fix the memory consumption/footprint issue mentioned above, we made a
hard decision to break the backward compatibility again with the
following changes:

- Remove MessageBuf
- Merge Buf into ByteBuf
- Merge ChannelInboundByte/MessageHandler and ChannelStateHandler into ChannelInboundHandler
  - Similar changes were made to the adapter classes
- Merge ChannelOutboundByte/MessageHandler and ChannelOperationHandler into ChannelOutboundHandler
  - Similar changes were made to the adapter classes
- Introduce MessageList which is similar to `MessageEvent` in Netty 3
- Replace inboundBufferUpdated(ctx) with messageReceived(ctx, MessageList)
- Replace flush(ctx, promise) with write(ctx, MessageList, promise)
- Remove ByteToByteEncoder/Decoder/Codec
  - Replaced by MessageToByteEncoder<ByteBuf>, ByteToMessageDecoder<ByteBuf>, and ByteMessageCodec<ByteBuf>
- Merge EmbeddedByteChannel and EmbeddedMessageChannel into EmbeddedChannel
- Add SimpleChannelInboundHandler which is sometimes more useful than
  ChannelInboundHandlerAdapter
- Bring back Channel.isWritable() from Netty 3
- Add ChannelInboundHandler.channelWritabilityChanges() event
- Add RecvByteBufAllocator configuration property
  - Similar to ReceiveBufferSizePredictor in Netty 3
  - Some existing configuration properties such as
    DatagramChannelConfig.receivePacketSize is gone now.
- Remove suspend/resumeIntermediaryDeallocation() in ByteBuf

This change would have been impossible without @normanmaurer's help. He
fixed, ported, and improved many parts of the changes.
2013-06-10 16:10:39 +09:00
Norman Maurer
f7931af704 Re-add Unsafe.voidPromise() which can be used for Unsafe operations for which no notification should be done [#1375] 2013-05-25 14:35:22 +02:00
Norman Maurer
699ef0784e [#1317] Allow to use VoidPromise for flush(...), write(...) and sendFile(...)
* This also move rename Channel.Unsafe.voidFuture() to ChannelPropertyAccess.voidPromise()
2013-05-17 15:50:14 +02:00
Trustin Lee
fd1d31e7d8 Remove unnecessary inEventLoop() checks in Channel.Unsafe
.. because HeadHandler in the pipeline always ensures those methods are always invoked from the correct I/O thread
2013-05-17 19:20:46 +09:00
Trustin Lee
8bb6d5b303 Rename Unsafe.directOutboundContext to headContext 2013-04-26 10:23:01 +09:00
Norman Maurer
12b392b4cc Revert "[#1058] Add Channel/ChannelHandlerContext/ChannelPipeline.isWritable()"
This reverts commit 4e36fbca58.
2013-02-22 14:42:32 +01:00
Norman Maurer
4e36fbca58 [#1058] Add Channel/ChannelHandlerContext/ChannelPipeline.isWritable() 2013-02-17 21:13:03 +01:00
Trustin Lee
1011227b88 Remove apiviz tags - we are focusing on user guide instead and putting diagrams there 2013-02-14 12:09:16 -08:00
Norman Maurer
547d4c20b0 Fix javadocs 2013-02-10 14:40:17 +01:00
Norman Maurer
4e77bacdf7 [#873] [#868] Split ChannelFuture into ChannelFuture and ChannelPromise 2012-12-31 23:27:16 +09:00
Trustin Lee
0909878581 Read only when requested (read-on-demand)
This pull request introduces a new operation called read() that replaces the existing inbound traffic control method. EventLoop now performs socket reads only when the read() operation has been issued. Once the requested read() operation is actually performed, EventLoop triggers an inboundBufferSuspended event that tells the handlers that the requested read() operation has been performed and the inbound traffic has been suspended again. A handler can decide to continue reading or not.

Unlike other outbound operations, read() does not use ChannelFuture at all to avoid GC cost. If there's a good reason to create a new future per read at the GC cost, I'll change this.

This pull request consequently removes the readable property in ChannelHandlerContext, which means how the traffic control works changed significantly.

This pull request also adds a new configuration property ChannelOption.AUTO_READ whose default value is true. If true, Netty will call ctx.read() for you. If you need a close control over when read() is called, you can set it to false.

Another interesting fact is that non-terminal handlers do not really need to call read() at all. Only the last inbound handler will have to call it, and that's just enough. Actually, you don't even need to call it at the last handler in most cases because of the ChannelOption.AUTO_READ mentioned above.

There's no serious backward compatibility issue. If the compiler complains your handler does not implement the read() method, add the following:

public void read(ChannelHandlerContext ctx) throws Exception {
    ctx.read();
}

Note that this pull request certainly makes bounded inbound buffer support very easy, but itself does not add the bounded inbound buffer support.
2012-12-31 23:26:00 +09:00
Norman Maurer
71b089cb3b Add javadocs and cleanup 2012-12-23 19:24:20 +01:00
Norman Maurer
ef555d268c Add more javadocs and replace some abstract methods with noops as we often implemented them as noops 2012-12-21 17:06:24 +01:00
Norman Maurer
62bf98af8c More javadoc fixes 2012-12-21 07:13:31 +01:00
Norman Maurer
39250873ae Add some javadocs 2012-12-17 16:01:58 +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
f9225df0a9 Add back support for FileRegion. See #668 2012-12-03 12:08:17 +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
Trustin Lee
ea4a0e3535 Prefer {@code ...} to <code>...</code> / Fix deprecation warnings 2012-11-12 11:51:23 +09:00
Trustin Lee
0b71afb81c Improve the stability of ServerSocketSuspendTest 2012-09-22 12:05:00 +09:00
Trustin Lee
5c347c5683 Remove unused import 2012-09-01 16:56:44 +09:00
Norman Maurer
ea3d304206 Some javadocs love 2012-08-28 01:14:05 +02:00
Norman Maurer
57e7255566 Add support to suspend reads. See #71 2012-07-27 20:02:47 +02:00
Trustin Lee
42380b54b3 Revert file mode 2012-07-07 14:39:35 +09:00
Trustin Lee
a5bb2c7f77 Add ChannelMetadata and remove unnecessary disconnect() impls
- Add Channel.metadata() and remove Channel.bufferType()
- DefaultPipeline automatically redirects disconnect() request to
  close() if the channel has no disconnect operation
- Remove unnecessary disconnect() implementations
2012-07-07 14:30:24 +09:00
Norman Maurer
f8ef5d5d78 Next round for async channel api support a.k.a nio2. See See #396 2012-06-14 21:02:47 +02:00
Trustin Lee
3b562c917d Move ChannelBufferType to netty-buffers and rename it to ChannelBufType
- Also add ChannelBuf.type()
2012-06-12 17:05:28 +09:00
Trustin Lee
6211e53e86 Code clean-up based on IntelliJ code analysis 2012-06-11 22:54:28 +09:00
Trustin Lee
9dce123938 Use MessageBuf instead of Queue wherever possible in channel API 2012-06-11 10:43:47 +09:00
Trustin Lee
5164d91255 Rename ChannelBuffer to ByteBuf as discussed before
- ChannelBuffer gives a perception that it's a buffer of a
  channel, but channel's buffer is now a byte buffer or a message
  buffer.  Therefore letting it be as is is going to be confusing.
2012-06-10 11:08:43 +09:00
Trustin Lee
24e1f936a8 ChannelType -> ChannelBufferType / Optimize DefaultChannelPipeline
- Channel.type() -> bufferType()
- Use simpler bit mask operation for pipeline traversal
2012-06-09 09:44:30 +09:00
Trustin Lee
5e93d206ff Overhaul - Split ChannelHandler & Merge ChannelHandlerContext
- Extracted some handler methods from ChannelInboundHandler into
  ChannelStateHandler
- Extracted some handler methods from ChannelOutboundHandler into
  ChannelOperationHandler
- Moved exceptionCaught and userEventTriggered are now in
  ChannelHandler
  
- Channel(Inbound|Outbound)HandlerContext is merged into
  ChannelHandlerContext
- ChannelHandlerContext adds direct access methods for inboud and
  outbound buffers
  - The use of ChannelBufferHolder is minimal now.
    - Before: inbound().byteBuffer()
    - After: inboundByteBuffer()
    - Simpler and better performance
    
- Bypass buffer types were removed because it just does not work at all
  with the thread model.
  - All handlers that uses a bypass buffer are broken.  Will fix soon.

- CombinedHandlerAdapter does not make sense anymore either because
  there are four handler interfaces to consider and often the two
  handlers will implement the same handler interface such as
  ChannelStateHandler.  Thinking of better ways to provide this feature
2012-06-07 14:52:33 +09:00
Trustin Lee
1eced1e9e3 Update license headers 2012-06-04 13:31:44 -07:00
Trustin Lee
01a5bd41f0 Add Channel.type() which tells if stream-oriented or message-oriented
- DefaultChannelPipeline uses this information to reject invalid buffer
  access in inbound(Message|Byte)Buffer.  Otherwise, a user can access
  a message buffer when the channel is stream-oriented.
- Because ChannelType cannot be both STREAM and MESSAGE, catch-all
  buffer has been removed to avoid confusion and unexpected behavior
  (it's already causing headache.)
- As a result, codec embedder needs rework.
2012-06-02 01:58:15 -07:00
Trustin Lee
141a05c831 Strict thread model / Allow assign an executor to a handler
- Add EventExecutor and make EventLoop extend it
- Add SingleThreadEventExecutor and MultithreadEventExecutor
- Add EventExecutor's default implementation
- Fixed an API design problem where there is no way to get non-bypass
  buffer of desired type
2012-06-01 17:51:19 -07:00
Trustin Lee
78974e85c5 AbstractUnsafe.out() -> directOutbound()
- to avoid confusion between Channel.outbound()
2012-05-30 00:38:23 -07:00
Trustin Lee
026715e818 Refactor the pipeline API to support stacked codecs
- Previous API did not support the pipeline which contains multiple
  MessageToStreamEncoders because there was no way to find the closest
  outbound byte buffer.  Now you always get the correct buffer even if
  the handler that provides the buffer is placed distantly.
  For example:
  
    Channel -> MsgAEncoder -> MsgBEncoder -> MsgCEncoder
  
  Msg(A|B|C)Encoder will all have access to the channel's outbound
  byte buffer.  Previously, it was simply impossible.

- Improved ChannelBufferHolder.toString()
2012-05-29 12:09:29 -07:00
Trustin Lee
6206d82b2c Split AbstractChannel into AbstractOioChannel and AbstractNioChannel
- Simpler OIO transport
- Suits better for other transports such as AIO, RXTX, IOStream
- Add ChannelBufferHolders.discardBuffer()
2012-05-26 22:48:48 -07:00
Trustin Lee
3642879d98 Move up write spinning from SelectorEventLoop to AbstractChannel 2012-05-13 05:09:05 +09:00
Trustin Lee
6d14fac99c Revive Channel.closeFuture
- ChannelPipeline now rejects an unsafe ChannelFuture, so there's no
  need to hide/remove closeFuture.
2012-05-13 01:37:16 +09:00
Trustin Lee
08137e2c49 Implement flush-future properly / Make channel options type-safe
- AbstractChannel keeps the expected number of written bytes so that
  the ChannelFuture of a flush() operation is notified on right timing.
  - Added ChannelBufferHolder.size() to make this possible
- Added AbstractChannel.isCompatible() so that only compatible EventLoop
  is accepted by a channel on registration
- Added ChannelOption to make channel options type-safe
- Moved writeSpinCount property to ChannelConfig and removed Nio*Config
- Miscellaneous cleanup

introducing
ChannelOption
2012-05-13 00:40:28 +09:00
Trustin Lee
cb718a07c8 Move ChannelFutureFactory.newVoidFuture() to Channel.Unsafe() / Cleanup 2012-05-11 00:57:42 +09:00
Trustin Lee
129a2af86a Initial working version of the echo server example
- Optimized AbstractChannelBuffer.discardReadBytes()
- Split ChannelHandlerInvoker into ChannelInboundInvoker and
  ChannelOutboundInvoker
  - Channel implements ChannelOutboundInvoker
  - ChannelOutboundInvoker.nextOut() is now out()
  - ChannelOutboundHandlerContext.out() is now prevOut()
  - Added the outbound operations without future
    parameter to ChannelOutboundInvoker for user convenience
- All async operations which requires a ChannelFuture as a parameter
  now returns ChannelFuture for user convenience
- Added ChannelFutureFactory.newVoidFuture() to allow a user specify
  a dummy future that is of no use
  - I'm unsure if it is actually a good idea to introduce it. It might
    go away later.
- Made the contract of AbstractChannel.doXXX() much simpler and moved
  all common code up to AbstractChannel.DefaultUnsafe
- Added Channel.isOpen()
- Fixed a bug where MultithreadEventLoop always shut down its child
  event loops on construction
- Maybe more changes I don't remember :-)
2012-05-09 22:09:06 +09:00
Trustin Lee
607d784e5e Retrofit/overhaul the NIO transport with the new API
- Remove large portion of code thanks to the new API
- SocketChannel implementations are instantiated without factories
- Retrofit the existing code with the new API
2012-05-02 21:05:53 +09:00
Trustin Lee
9e6f8b46df Retrofit the NIO transport with the new API / improve the new API
- Remove the classes and properties that are not necessary anymore
- Remove SingleThreadEventLoop.newRegistrationTask() and let
  Channel.Unsafe handle registration by itself
- Channel.Unsafe.localAddress() and remoteAddress()
  - JdkChannel is replaced by Channel.Unsafe.
2012-05-02 15:01:58 +09:00