"이희승 (Trustin Lee) <[EMAIL PROTECTED]>" wrote:
I thought about the current MINA API these days while I am idle, and got
some idea of improvements:
1) Split IoBuffer into two parts - array and buffer
IoBuffer is basically an improvement to ByteBuffer. Improvement here
means it inherited some bad asset from ByteBuffer - all the stateful
properties such as position, limit and mark. I think they should be
provided as a separate class, and there should be classes dedicated for
storing bytes only (something like ByteArray?)
I was also thinking about this class. ByteBuffers are allocated once,
with a specific size, and the JVM will optimize the way they are
handled. When dealing with IO, I don't see a lot of reasons to have
expandable BB.
I think that using a byte[] (for instance in the encoder), transform it
to a ByteBuffer, is another way to deal with the problem.
One important point is that ByteBuffers are just mean to contains a
fixed amount of data. It's a buffer, not a data structure. Transforming
ByteBuffer to make them able to expand twist their intrinsic semantic.
So I would say that BB should be used on the very low level (reading
data and sending data), but then, the other layers should use byte[] or
a stream of bytes.
This will lead to very intersting performances questions :
- how to handle large stream of data ?
- should we serialize the stream at some point ?
- how to write an efficient decoder, when you may receive fractions of
what you are waiting for ?
- how to write an efficient encoder when you have no idea about the size
of the data you are going to send ?
For all these reasons, the mail I sent a few days ago express my
personnal opinion that IoBuffer may be a little bit overkilling
(remember that this class -and the associated tests- represent around
13% of all mina common code ! )
BTW, why is mixing them a bad idea? It's because it makes the
implementation too complicated. For example, it is almost impossible to
implement a composite buffer to support close-to-zero-copy I/O. What
about all the weird rules related with auto-expansion and buffer
derivation? It's increasing the learning curve.
Very true.
2) Get rid of IoHandler and let IoFilter replace it.
IoHandler is just a special IoFilter at the end of the filter chain. I
don't see any reason to keep it special considering that we are often
building multi-layered protocols.
I didn't went deep into this class, but if it's just the last part of a
filter, then it's just a filter like any other, a catch-all filter. So I
agree with the idea to define it as a IoFilter too.
3) Split IoFilter into multiple interfaces.
If IoHandler is removed, IoFilter should be renamed to represent itself
better. Moreover, IoFilter should be split into more than one interface
(e.g. UpstreamHandler for receiving events and DownstreamHandler for
sending events from/to an IoProcessor) so they can choose what to
override more conveniently.
I'm a little bit reluctant... Filters are two-ways, so I'm not sure this
is a good idea to define at least two separate kind of filters (up and
down stream). let me explain :
You have something similar to what Eiffel (the language) has : pre and
post processing. Calling the next filter is just an action. The flow is
much more like :
filter N-1 -> [Filter N] pre processing... call Filter N+1... post
processing -> return to filter N-1
If you separate up stream and downstream filters, this will become
slightly more complicated to write, because post-processing won't be
executed, but moved to the up-stream Filter. This will split the logic
of a filter into two classes.
I have some other suggestion which is not related : The CoR we are using
is really a PITA to handle when debugging. If you don't know which
filter will be called next, either you step through a container object
before jumping into the next filter, or you set a breakpoint in every
filter (but then, if you have many filters this is a burden).
I would rather see something really more simple, like if the call for
the next filter directly point to the next filter. Filter instanciation
will differ, but not that much.
Atm, the logic is :
filter N-1
call next filter
compute next filter
call next filter
Filter N
etc...
It would be really more simpler to have something like :
Filter N-1
next filter.call()
Filter N
Or at least :
Filter N-1
next Filter = compute next filter
next filter.call()
Filter N
4) UDP as the first citizen transport.
I don't know nothing about UDP ...
Any feed back is welcome.
Hope that i'm not totally off rails with my feedback !
--
--
cordialement, regards,
Emmanuel Lécharny
www.iktek.com
directory.apache.org