dev@grizzly.java.net

Re: [Brainstorming] Grizzly 2 I/O API :)

From: Jeanfrancois Arcand <Jeanfrancois.Arcand_at_Sun.COM>
Date: Wed, 28 Jan 2009 14:50:34 -0500

Salut,

Oleksiy Stashok wrote:
> Hi,
>
> wanted to share ideas John and myself came to, about changing current
> Grizzly 2 I/O API.
> The main idea is to make Grizzly 2.0 API to be based on
> StreamReader/StreamWriter API, proposed by Ken. What does it mean?
>
> Currently, to read something from Grizzly 2.0 Connection, we perform
> following steps:
>
> (1) Connect
> /Future<Connection> connectionFuture = transport.connect(...);/
> /connection = connectionFuture.get();/
>
> (2) Allocate buffer
> /Buffer buffer = transport.getMemoryManager().allocate(size);/
>
> (3) Read data to buffer
> /Future<ReadResult> readFuture = connection.read(buffer);/
> /ReadResult result = readFuture.get();/
>
> (4) Parse buffer
> /if (buffer.remaining() >= 4) {/
> / intValue = buffer.getInt();/
> /}/
>
> Similar steps we do for writing.
>
> Concerns?
> IMHO, there is one. We always have to care about allocating Buffers and
> then, if we use some smart buffer pool, don't forget to release it.

I like the don't forget to release it :-) But should we still allow
people to manipulate byte buffer, but also supports/recommend stream?



>
> What John proposed and I like his idea is to use Streams for read and
> write operations. This will let us hide Buffers complexity, developer
> will not need to care about them anymore... and this should let us make
> Buffers usage more optimal.
> How read may look like with Streams?
>
> (1) Connect
> /Future<Connection> connectionFuture = transport.connect(...);/
> /connection = connectionFuture.get();/
>
> (2) Get StreamReader
> /StreamReader reader = connection.getStreamReader();/
>
> (3) Wait until data will become available
> /Future future = reader.notifyAvailable(4);/
> /future.get();/

Should we have the CompletionHandler here as well so the Future.get()
can be avoided (because blocking).


>
> (4) Parse data from stream
> /intValue = reader.getInt();/
>
> As you see in Stream-like case we don't allocate any Buffer, so Grizzly
> has complete control over a Buffer inside StreamReader.

That seems OK but how will you implement a protocol like http using
this? Would you support something like:

read.readUntil('\r\n\r\n'); or the reader.read(byte[])?

I would like to see the complete API picture here :-)


>
> With write operation it's not so clear to me in terms of API, because
> currently write works following way:
>
> /Buffer buffer = transport.getMemoryManager().allocate(size);/
> /buffer.putInt(intValue);/
> /buffer.putLong(longValue);/
> /buffer.flip();/
> /
> /
> /Future writeFuture = connection.write(buffer);/
> /writeFuture.get();/
>
> here developer has full control over filling the buffer and flushing it
> to network.
> In Streams example:
>
> /StreamWriter writer = connection.getStreamWriter();/
> /writer.putInt(intValue);/
> /writer.putLong(longValue);/
> /

I suspect writter.write(bb) or bytes is planned as well?

> /
> /Future future = writer.flush();/
> /future.get();/

Same comment as above, e.g. CompletionHandler can probably be used here
as well to avoid blocking.


>
> we can not guarantee that flush operation will be called just once,
> because internal buffer could be overflowed before flush() will be
> explicitly called. Not sure this is a big deal, but just possible issue.
>
> I will appreciate feedback on API change proposal, and ideas, how it
> could be improved.

Looks promising!

A+

-- Jeanfrancois

>
> Thanks.
>
> WBR,
> Alexey.