|
|
|
Gili
|
Hi,
Just curious, what's the point of shutdownInput() and shutdownOutput() in AsynchronousSocketChannel? When would users want to shut them as opposed to closing the entire channel? Thanks, Gili |
||||||||||||||||||
|
Alexander Libman
|
Hi Gili,
shutdownOutput () signals the other side the end of stream So asynch read completed (not failed) with the value of read bytes equal to -1. Example, where shutdownOutput is useful is AsynchoronousSSLChanel (also a filter similar to AsynchronousCoder). Implementation initiates graceful final handshake. I looked at your version of AsynchronousCharByteChannel. BTW, it is another, example where shutdowOutput() can be used instead of method write(CharBuffer source, boolean endOfInput) I think shutdownOutput() provides more consistent interface. Terabit's AsynchronousCoder uses shutdownOutput() for graceful encoding final step. Also there are some cases (not very often) when the closure of external channel (filter itself) should not close the embedded(internal) channel. Assume we want to write AsynchronousSMTPClient. It can be implemented via the following stack of asynch. filters: AsynchronousByteChannel | AsynchronousCharChannel | AsynchronousSMTPChannel AsychronousSMTPChannel "rents" the underline channels to do a SMTP transaction: MailFrom, RcptTo,..., Body After transactions is completed successfully, SMTP channel can be closed, but AsynchronousCharChannel can be reused for the next SMTP transaction. Would you mind to join our effords to facilitate Asynchronous Filter Framework? What do you think about splitting functionality of "Asynchronous Char Line Reader" (i.e. your implementation ) into two filters AsynchronousCoder and AsynchronousScanner? The first one will do only read/write CharBuffers and the second can be generic AsynchronousScanner similar to Scanner? Alex > -----Original Message----- > From: [hidden email] > [mailto:[hidden email]]On Behalf Of Gili > Sent: Friday, July 31, 2009 8:44 PM > To: [hidden email] > Subject: AsynchronousSocketChannel.shutdownInput() > > > > Hi, > > Just curious, what's the point of shutdownInput() and shutdownOutput() in > AsynchronousSocketChannel? When would users want to shut them as > opposed to > closing the entire channel? > > Thanks, > Gili > -- > View this message in context: > http://n2.nabble.com/AsynchronousSocketChannel.shutdownInput%28%29 Sent from the nio-discuss mailing list archive at Nabble.com. No virus found in this incoming message. Checked by AVG - www.avg.com Version: 8.5.392 / Virus Database: 270.13.38/2274 - Release Date: 07/31/09 05:58:00 |
||||
|
Gili
|
The problem is that write() returns the number of bytes written. shutdownOutput() would only make sense if it returned an Integer (indicate the number of bytes written) instead of returning the channel. Interesting point. Perhaps there should be a configuration option that indicates whether close() is recursive? I like the idea of collaborating on this work and the idea of moving readLine() into AsynchronousScanner, but I'm afraid that the last time I took a look at your framework I was a little put off by the lack of source-code comments and Javadoc. If you take a look at http://projectkenai.com/projects/jperipheral/sources you will notice that I went out of my way to document heavily (in fact, I will probably add more in the future). If we can find a way to work together, great. Otherwise, you are always welcome to "borrow" some of my code as I am using the Apache license. Cheers, Gili |
||||||||||||||||||
|
Alan Bateman
|
In reply to this post
by Gili
Gili wrote:
> Hi, > > Just curious, what's the point of shutdownInput() and shutdownOutput() in > AsynchronousSocketChannel? When would users want to shut them as opposed to > closing the entire channel? > > Thanks, > Gili > The shutdown methods are required to support half-close semantics, important for TCP applications. As Alex said, you can use shutdownOutput to disable further write operations but the channel's socket can continue to receive data from the peer. -Alan. |
|||||||||||||||||||
|
Alexander Libman
|
In reply to this post
by Gili
> > > > The problem is that write() returns the number of bytes written. > shutdownOutput() would only make sense if it returned an Integer (indicate > the number of bytes written) instead of returning the channel. write() must return the number of elements (chars, not bytes!) processed from the buffer(CharBuffer), i.e. consumed by encoder. How many bytes encoder produces on output(i.e. on internal channel ) is not important for the caller. "write () "is a job and "completed()" callback means the job is done. If write() completed with less bytes processed than requested, it should be called again. write() in TCP means data accepted for the trasnmission, but it does not mean data is delivered. It is up to decoder to buffer encoded data or to push them into internal channel. So shutdownOutput() works like flush and prohibits any future write operations. If error occurs during shutdownOutput() , exception should be thrown. If you are still worried about all data are transmitted on internal channel, you can wait in external channel close() the completion of all operations on internal channel. > > > Alexander Libman wrote: > > > > Also there are some cases (not very often) when the closure > of external > > channel (filter itself) should not close > > the embedded(internal) channel. Assume we want to write > > AsynchronousSMTPClient. > > It can be implemented via the following stack of asynch. filters: > > AsynchronousByteChannel > > | > > AsynchronousCharChannel > > | > > AsynchronousSMTPChannel > > > > AsychronousSMTPChannel "rents" the underline channels to do a SMTP > > transaction: > > MailFrom, RcptTo,..., Body > > > > After transactions is completed successfully, SMTP channel can > be closed, > > but > > AsynchronousCharChannel can be reused for the next SMTP transaction. > > > > Interesting point. Perhaps there should be a configuration option that > indicates whether close() is recursive? May be some flag : close (boolean doNotCloseInternalChannel) and close () by default is implemented as { close (false);} or more generic closeWithOptions(...) to specify: a) close or nor the internal channel b) wait to all operations on internal channel to be completed() > > > > > I like the idea of collaborating on this work and the idea of moving > readLine() into AsynchronousScanner, but I'm afraid that the last time I > took a look at your framework I was a little put off by the lack of > source-code comments and Javadoc. Yes, I know - it is still a draft, but it is working draft and I hope the code is not hard to read. We will definetely try to find time to write better comments/doc. Alex |
|||||||||||||||||||
|
Gili
|
Hi Alex, To be honest I don't fully understand the implications of CharsetEncoder.encode(endOfInput=true) and CharsetEncoder.flush(). If I write() 5 characters with endOfInput = false, 1) What's the point of CharsetEncoder.flush() if write(endOfInput=true) already knows that you're flushing? Is it because flush() is overridable by subclasses whereas encode() is not? 2) Am I guaranteed that the total characters outputted by CharsetEncoder.write() and flush() will be equal to 5 characters? I ask because the specification for flush() makes it seem as if there is no limit to the number of bytes it could output. 3) If I want to implement a method similar to OutputStream.flush() on top of CharsetEncoder, how would I do it? write(endOfInput=true) and flush() cannot be invoked more than once, whereas OutputStream.flush() can. But if I don't invoke them am I really flushing? Okay. I will try to finalize my implementation in the coming weeks. Once that's done we'll discuss folding it into nio2 or your framework. I'd like to hand maintenance over to someone else once I finish the stabilizing the code. Gili |
||||||||||||||||||
|
Alexander Libman
|
Hi Gili, Alan I have read again JavaDoc about encoder and looked at the source code of ChasretEncoder. Basically, its state machine can be decribed as follows: State Signal New State --------- ------------------------- -------------- RESET encode(EOF=false) CODING encode(EOF=true) END reset RESET flush Exception Illegal CODING encode(EOF=false) CODING encode(EOF=true) END reset RESET flush Exception Illegal END encode(EOF=false) Exception Illegal encode(EOF=true) END reset RESET flush FLUSHED FLUSHED encode(EOF=false) Exception Illegal encode(EOF=true) Exception Illegal reset RESET flush FLUSHED This means we should have two kind of filters for AsynchronousCoders : 1) AsynchronousMessageEncoder: 2) AsynchonouseStreamEncoder For the 1) AsynchronousMessageEncoder: each asynchnous write (CharBuffer buffer) translates to the following sequence of operations on encoder: reset(); encode(EOF=true); flush(); shutdownOutput() simply prevents any future writes close() calls shutdownOutput() For the 2) AsynchronousStreamEncoder (Terabit version) reset() called from constructor each write() translates into encode(EOF=false) shutdowOutput() translates into encode(zeroByteBuffer, EOF=true); flush(); and prevents any future writes close() calls shutdownOutput() The type of AsynchronousEncoder (Message or Stream) can be specified at construction time. Another possible option to introduce "HybridEncoder" with additional method flush() that does not have analogy in AsynchronousByteChannel: 3) HybridEncoder works like: reset() called from constructor each write() translates into encode(EOF=false) flush() translates into encode(zeroByteBuffer, EOF=true); flush(); reset() shutdowOutput() translates into encode(zeroByteBuffer, EOF=true); flush(); and prevents any future writes close() calls shutdownOutput() another way to implement HybridEncoder (as Gili proposed): reset() called from constructor each write() translates into encode(EOF=false) each write(EOF=true) translates into encode( EOF=true); flush(); reset() shutdowOutput() translates into encode(zeroByteBuffer, EOF=true); flush(); and prevents any future writes close() calls shutdownOutput() Gili, you missed reset() in your implementation. write(EOF=true) does not mean we can not write anymore, it means end-of-transaction encoding and after flushing is done the encoder is ready for next operations. Any opinions? what interface is preferable? I am thinking that Gili's write(buffer) and write(buffer,EOFFlag) make sense. One more option: setMode(mode) method messageMode -means write() works as 1) and and streamMode - means write() works as 2) setMode () can be invoked at any time. Alex > -----Original Message----- > From: [hidden email] > [mailto:[hidden email]]On Behalf Of Gili > Sent: Tuesday, August 04, 2009 11:27 PM > To: [hidden email] > Subject: RE: AsynchronousSocketChannel.shutdownInput() > > > > > Alexander Libman wrote: > > > > write() must return the number of elements (chars, not bytes!) > processed > > from the buffer(CharBuffer), i.e. consumed by encoder. > > How many bytes encoder produces on output(i.e. on internal channel ) is > > not > > important for the caller. > > "write () "is a job and "completed()" callback means the job is done. > > If write() completed with less bytes processed than requested, it should > > be > > called again. > > write() in TCP means data accepted for the trasnmission, but it does not > > mean data is delivered. > > It is up to decoder to buffer encoded data or to push them into internal > > channel. > > So shutdownOutput() works like flush and prohibits any future write > > operations. > > If error occurs during shutdownOutput() , exception should be thrown. > > If you are still worried about all data are transmitted on internal > > channel, > > you can wait in external channel close() the completion of all > operations > > on internal channel. > > > > Hi Alex, > > To be honest I don't fully understand the implications of > CharsetEncoder.encode(endOfInput=true) and CharsetEncoder.flush(). If I > write() 5 characters with endOfInput = false, > > 1) What's the point of CharsetEncoder.flush() if write(endOfInput=true) > already knows that you're flushing? Is it because flush() is > overridable by > subclasses whereas encode() is not? > 2) Am I guaranteed that the total characters outputted by > CharsetEncoder.write() and flush() will be equal to 5 characters? I ask > because the specification for flush() makes it seem as if there > is no limit > to the number of bytes it could output. > 3) If I want to implement a method similar to > OutputStream.flush() on top of > CharsetEncoder, how would I do it? write(endOfInput=true) and > flush() cannot > be invoked more than once, whereas OutputStream.flush() can. But > if I don't > invoke them am I really flushing? > > > Alexander Libman wrote: > > > > Yes, I know - it is still a draft, but it is working draft and I hope > > the > > code is not hard to read. > > We will definetely try to find time to write better comments/doc. > > > > Okay. I will try to finalize my implementation in the coming weeks. Once > that's done we'll discuss folding it into nio2 or your framework. I'd like > to hand maintenance over to someone else once I finish the stabilizing the > code. > > Gili > -- > View this message in context: > http://n2.nabble.com/AsynchronousSocketChannel.shutdownInput%28%29 Sent from the nio-discuss mailing list archive at Nabble.com. No virus found in this incoming message. Checked by AVG - www.avg.com Version: 8.5.392 / Virus Database: 270.13.44/2282 - Release Date: 08/04/09 18:01:00 |
|||||||||||||||||||
|
Gili
|
Alex,
Please take a look at http://kenai.com/projects/jperipheral/sources/svn/content/trunk/java/source/jperipheral/AsynchronousByteCharChannel.java?raw=true I fixed numerous bugs since I posted the source-code on this mailing list. You bring up a good point regarding reset(). Perhaps the class should be refactored as follows: write() invokes endOfInput=false always flush() invokes encoder.write(endOfInput=true), flush(), reset() close() invokes flush() before closing the channel Anyone wishing to send messages versus streams would either use flush() at the end of a message or not. I believe this would result in a cleaner more consistent API with the respect to the core Java APIs. What do you think? Gili
|
||||||||||||||||||
|
Alexander Libman
|
Gili,
> > > Alex, > > Please take a look at > http://kenai.com/projects/jperipheral/sources/svn/content/trunk/ja > va/source/jperipheral/AsynchronousByteCharChannel.java?raw=true OK, will do > > I fixed numerous bugs since I posted the source-code on this mailing list. > You bring up a good point regarding reset(). Perhaps the class should be > refactored as follows: > > write() invokes endOfInput=false always > flush() invokes encoder.write(endOfInput=true), flush(), reset() > close() invokes flush() before closing the channel yes, later we can add one more method writeAndFlush () Basically its is composition of write and flush, but we can gain in performance a liitle bit > > What do you think? Agree. Alex > > Gili > > > Alexander Libman wrote: > > > > > > Hi Gili, Alan > > > > I have read again JavaDoc about encoder and looked at the source code of > > ChasretEncoder. Basically, its state machine can be decribed as follows: > > > > State Signal New State > > --------- ------------------------- -------------- > > RESET encode(EOF=false) CODING > > encode(EOF=true) END > > reset RESET > > flush Exception Illegal > > > > CODING encode(EOF=false) CODING > > encode(EOF=true) END > > reset RESET > > flush Exception Illegal > > > > END encode(EOF=false) Exception Illegal > > encode(EOF=true) END > > reset RESET > > flush FLUSHED > > > > FLUSHED encode(EOF=false) Exception Illegal > > encode(EOF=true) Exception Illegal > > reset RESET > > flush FLUSHED > > > > > > This means we should have two kind of filters for > AsynchronousCoders : > > > > 1) AsynchronousMessageEncoder: > > 2) AsynchonouseStreamEncoder > > > > For the 1) AsynchronousMessageEncoder: > > each asynchnous write (CharBuffer buffer) translates to the following > > sequence of operations on encoder: > > reset(); encode(EOF=true); flush(); > > shutdownOutput() simply prevents any future writes > > close() calls shutdownOutput() > > > > For the 2) AsynchronousStreamEncoder (Terabit version) > > reset() called from constructor > > each write() translates into encode(EOF=false) > > shutdowOutput() translates into encode(zeroByteBuffer, > EOF=true); flush(); > > and prevents any future writes > > close() calls shutdownOutput() > > > > The type of AsynchronousEncoder (Message or Stream) can be specified at > > construction time. > > Another possible option to introduce "HybridEncoder" with additional > > method > > flush() that does not have analogy in AsynchronousByteChannel: > > > > 3) HybridEncoder works like: > > reset() called from constructor > > each write() translates into encode(EOF=false) > > flush() translates into encode(zeroByteBuffer, EOF=true); flush(); > > reset() > > shutdowOutput() translates into encode(zeroByteBuffer, > EOF=true); flush(); > > and prevents any future writes > > close() calls shutdownOutput() > > > > another way to implement HybridEncoder (as Gili proposed): > > reset() called from constructor > > each write() translates into encode(EOF=false) > > each write(EOF=true) translates into encode( EOF=true); > flush(); reset() > > shutdowOutput() translates into encode(zeroByteBuffer, > EOF=true); flush(); > > and prevents any future writes > > close() calls shutdownOutput() > > > > Gili, you missed reset() in your implementation. > write(EOF=true) does not > > mean we can not write anymore, > > it means end-of-transaction encoding and after flushing is done the > > encoder > > is ready for next operations. > > > > Any opinions? what interface is preferable? > > I am thinking that Gili's write(buffer) and write(buffer,EOFFlag) make > > sense. > > One more option: > > setMode(mode) method > > messageMode -means write() works as 1) and > > and > > streamMode - means write() works as 2) > > setMode () can be invoked at any time. > > > > Alex > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >> -----Original Message----- > >> From: [hidden email] > >> [mailto:[hidden email]]On Behalf Of Gili > >> Sent: Tuesday, August 04, 2009 11:27 PM > >> To: [hidden email] > >> Subject: RE: AsynchronousSocketChannel.shutdownInput() > >> > >> > >> > >> > >> Alexander Libman wrote: > >> > > >> > write() must return the number of elements (chars, not bytes!) > >> processed > >> > from the buffer(CharBuffer), i.e. consumed by encoder. > >> > How many bytes encoder produces on output(i.e. on internal > channel ) is > >> > not > >> > important for the caller. > >> > "write () "is a job and "completed()" callback means the > job is done. > >> > If write() completed with less bytes processed than requested, it > >> should > >> > be > >> > called again. > >> > write() in TCP means data accepted for the trasnmission, but it does > >> not > >> > mean data is delivered. > >> > It is up to decoder to buffer encoded data or to push them into > >> internal > >> > channel. > >> > So shutdownOutput() works like flush and prohibits any future write > >> > operations. > >> > If error occurs during shutdownOutput() , exception should be thrown. > >> > If you are still worried about all data are transmitted on internal > >> > channel, > >> > you can wait in external channel close() the completion of all > >> operations > >> > on internal channel. > >> > > >> > >> Hi Alex, > >> > >> To be honest I don't fully understand the implications of > >> CharsetEncoder.encode(endOfInput=true) and CharsetEncoder.flush(). If I > >> write() 5 characters with endOfInput = false, > >> > >> 1) What's the point of CharsetEncoder.flush() if write(endOfInput=true) > >> already knows that you're flushing? Is it because flush() is > >> overridable by > >> subclasses whereas encode() is not? > >> 2) Am I guaranteed that the total characters outputted by > >> CharsetEncoder.write() and flush() will be equal to 5 characters? I ask > >> because the specification for flush() makes it seem as if there > >> is no limit > >> to the number of bytes it could output. > >> 3) If I want to implement a method similar to > >> OutputStream.flush() on top of > >> CharsetEncoder, how would I do it? write(endOfInput=true) and > >> flush() cannot > >> be invoked more than once, whereas OutputStream.flush() can. But > >> if I don't > >> invoke them am I really flushing? > >> > >> > >> Alexander Libman wrote: > >> > > >> > Yes, I know - it is still a draft, but it is working draft > and I hope > >> > the > >> > code is not hard to read. > >> > We will definetely try to find time to write better comments/doc. > >> > > >> > >> Okay. I will try to finalize my implementation in the coming > weeks. Once > >> that's done we'll discuss folding it into nio2 or your framework. I'd > >> like > >> to hand maintenance over to someone else once I finish the stabilizing > >> the > >> code. > >> > >> Gili > >> -- > >> View this message in context: > >> http://n2.nabble.com/AsynchronousSocketChannel.shutdownInput%28%29 > > -tp3365782p3388926.html > > Sent from the nio-discuss mailing list archive at Nabble.com. > > No virus found in this incoming message. > > Checked by AVG - www.avg.com > > Version: 8.5.392 / Virus Database: 270.13.44/2282 - Release > Date: 08/04/09 > > 18:01:00 > > > > > > > > -- > View this message in context: > http://n2.nabble.com/AsynchronousSocketChannel.shutdownInput%28%29 Sent from the nio-discuss mailing list archive at Nabble.com. No virus found in this incoming message. Checked by AVG - www.avg.com Version: 8.5.392 / Virus Database: 270.13.48/2291 - Release Date: 08/09/09 18:10:00 |
|||||||||||||||||||
| Free Embeddable Forum Powered by Nabble | Help |