Ruby client causing java.net.SocketException on server

Saturday, 22 October 2011 · 5 messages · last reply 23 Oct 2011
DK
Daniël Knippers22 Oct 2011 22:04 #
Good evening, I am using Ruby on Rails and BaseX for some hobby projects, and I have noticed the new Ruby client API + BaseX 7.0 causes java.net.SocketExceptions (see bottom of this message for complete error + stack trace) on the server. After inspecting the new client code, this seemed to have been caused by the new query iteration method which uses a cache. Reproducing this is easy; execute the QueryExample.rb script from the repository (make sure to first remove 'query.init', which is still in the example but has been removed from the API). It raises the Exception every single time for me. Note the query does seem to return the expected result so I could just ignore the Exception but that does not seem like the right thing to do :) On a side note, the 'if more()' in the 'next' method seems superfluous as query.next should only be called inside a 'while query.more' loop anyway. Effectively 'query.more' is now called twice in that loop before the cache is read. Kind regards, Daniël Knippers ps. I'm using Java 1.6.0_27, and the error occurs on the stable BaseX 7.0 as well as on snapshot 170343 (7.0.1 RC1). The error below is from the 7.0.1 RC1 version. Server and client were ran from the same machine. ================= <error> ================= java.net.SocketException: Connection reset by peer: socket write error java.net.SocketOutputStream.socketWrite0(Native Method) java.net.SocketOutputStream.socketWrite(Unknown Source) java.net.SocketOutputStream.write(Unknown Source) org.basex.io.out.BufferOutput.flush(BufferOutput.java:52) org.basex.io.out.PrintOutput.flush(PrintOutput.java:149) org.basex.server.ClientListener.send(ClientListener.java:504) org.basex.server.ClientListener.info(ClientListener.java:326) org.basex.server.ClientListener.run(ClientListener.java:212) ================= </error> ================= =============== <caused_by> =============== def more() if @cache.length == 0 @session.write(4.chr) @session.send(@id) while(@session.read == 1.chr) @cache << @session.receive end end return @pos < @cache.length end def next if more() @pos += 1 return @cache[@pos - 1] end end =============== </caused_by> ===============
CG
Christian Grün22 Oct 2011 23:25 #
Dear Daniël, thanks for the observation and the detailed feedback. I neither have Ruby installed, nor do I much about coding Ruby, but I think I found some bugs in the current implementation (e.g., the more() function had no exception handling yet). I hope I didn't introduce any typos.. Your feedback is welcome. Btw, if you know a little about Ruby encoding, it would be great if you could have a closer look at our client implementation. I'm sure it could be optimized, both in terms of execution time and coding style. Thanks, Christian PS: in all of our client implementations, the next() method can be used without calling more(). Indeed, the more() method only checks if there are more elements left, while the next() method increases the internal pointer.
Quoted text · Daniël Knippers · 65 lines
On Sat, Oct 22, 2011 at 10:04 PM, Daniël Knippers <dknippers at gmail.com> wrote: > Good evening, > > I am using Ruby on Rails and BaseX for some hobby projects, and I have > noticed the new Ruby client API + BaseX 7.0 causes java.net.SocketExceptions > (see bottom of this message for complete error + stack trace) on the server. > After inspecting the new client code, this seemed to have been caused by the > new query iteration method which uses a cache. Reproducing this is easy; > execute the QueryExample.rb script from the repository (make sure to first > remove 'query.init', which is still in the example but has been removed from > the API). It raises the Exception every single time for me. > > Note the query does seem to return the expected result so I could just > ignore the Exception but that does not seem like the right thing to do :) > > On a side note, the 'if more()' in the 'next' method seems superfluous as > query.next should only be called inside a 'while query.more' loop anyway. > Effectively 'query.more' is now called twice in that loop before the cache > is read. > > Kind regards, > Daniël Knippers > > ps. I'm using Java 1.6.0_27, and the error occurs on the stable BaseX 7.0 as > well as on snapshot 170343 (7.0.1 RC1). The error below is from the 7.0.1 > RC1 version. Server and client were ran from the same machine. > > ================= <error> ================= > java.net.SocketException: Connection reset by peer: socket write error > java.net.SocketOutputStream.socketWrite0(Native Method) > java.net.SocketOutputStream.socketWrite(Unknown Source) > java.net.SocketOutputStream.write(Unknown Source) > org.basex.io.out.BufferOutput.flush(BufferOutput.java:52) > org.basex.io.out.PrintOutput.flush(PrintOutput.java:149) > org.basex.server.ClientListener.send(ClientListener.java:504) > org.basex.server.ClientListener.info(ClientListener.java:326) > org.basex.server.ClientListener.run(ClientListener.java:212) > ================= </error> ================= > > =============== <caused_by> =============== > def more() > if @cache.length == 0 > @session.write(4.chr) > @session.send(@id) > while(@session.read == 1.chr) > @cache << @session.receive > end > end > return @pos < @cache.length > end > > def next > if more() > @pos += 1 > return @cache[@pos - 1] > end > end > =============== </caused_by> =============== > > _______________________________________________ > BaseX-Talk mailing list > BaseX-Talk at mailman.uni-konstanz.de > https://mailman.uni-konstanz.de/mailman/listinfo/basex-talk > >
DK
Daniël Knippers23 Oct 2011 00:01 #
Hi Christian, Thank you for your quick response. With your fix it seems to work fine now. Regarding the closer look at the Ruby code; I cannot quickly spot any optimizations (seems like a very lightweight protocol anyway). If you are interested in writing more 'Ruby-like' code then I can give some recommendations about the syntax. Ruby syntax aims at improving readability of code in general. The changes below will change nothing in execution, so this is 100% optional and even personal preference so perhaps you want to skip all of this. -- Boolean functions typically end with a '?', as if you are asking a question (well, you are). The ones I spot are 'def ok()' => def ok?, and 'def more()' => def more? - Constructs like if !sesson.ok raise receive end can be rewritten to read more naturally when written on 1 line and using the '?' for boolean functions. Note the 'unless' keyword simply means if not. raise receive unless session.ok? while loops can also be written like this on 1 line (@cache << @session.receive while @session.read == 1.chr) but personally I'm not a fan. I like my loops starting on top and going down and looping back up :) - Parentheses can be omitted when functions do not take any arguments. Most calls already do this (except send(hash.hexdigest*()*) and more()), but the method definitions still have them (def close(), def info(), etc). Can be removed there. - Camel case is generally not used. Instead, use method names with underscores (so sendCmd => send_cmd). Thanks again for the quick fix and have a nice weekend ! -- Daniël On Sat, Oct 22, 2011 at 23:25, Christian Grün <christian.gruen at gmail.com>wrote:
Quoted text · Christian Grün · 95 lines
> Dear Daniël, > > thanks for the observation and the detailed feedback. I neither have > Ruby installed, nor do I much about coding Ruby, but I think I found > some bugs in the current implementation (e.g., the more() function had > no exception handling yet). I hope I didn't introduce any typos.. > Your feedback is welcome. > > Btw, if you know a little about Ruby encoding, it would be great if > you could have a closer look at our client implementation. I'm sure it > could be optimized, both in terms of execution time and coding style. > > Thanks, > Christian > > PS: in all of our client implementations, the next() method can be > used without calling more(). Indeed, the more() method only checks if > there are more elements left, while the next() method increases the > internal pointer. > ___________________________ > > On Sat, Oct 22, 2011 at 10:04 PM, Daniël Knippers <dknippers at gmail.com> > wrote: > > Good evening, > > > > I am using Ruby on Rails and BaseX for some hobby projects, and I have > > noticed the new Ruby client API + BaseX 7.0 causes > java.net.SocketExceptions > > (see bottom of this message for complete error + stack trace) on the > server. > > After inspecting the new client code, this seemed to have been caused by > the > > new query iteration method which uses a cache. Reproducing this is easy; > > execute the QueryExample.rb script from the repository (make sure to > first > > remove 'query.init', which is still in the example but has been removed > from > > the API). It raises the Exception every single time for me. > > > > Note the query does seem to return the expected result so I could just > > ignore the Exception but that does not seem like the right thing to do :) > > > > On a side note, the 'if more()' in the 'next' method seems superfluous as > > query.next should only be called inside a 'while query.more' loop anyway. > > Effectively 'query.more' is now called twice in that loop before the > cache > > is read. > > > > Kind regards, > > Daniël Knippers > > > > ps. I'm using Java 1.6.0_27, and the error occurs on the stable BaseX 7.0 > as > > well as on snapshot 170343 (7.0.1 RC1). The error below is from the 7.0.1 > > RC1 version. Server and client were ran from the same machine. > > > > ================= <error> ================= > > java.net.SocketException: Connection reset by peer: socket write error > > java.net.SocketOutputStream.socketWrite0(Native Method) > > java.net.SocketOutputStream.socketWrite(Unknown Source) > > java.net.SocketOutputStream.write(Unknown Source) > > org.basex.io.out.BufferOutput.flush(BufferOutput.java:52) > > org.basex.io.out.PrintOutput.flush(PrintOutput.java:149) > > org.basex.server.ClientListener.send(ClientListener.java:504) > > org.basex.server.ClientListener.info(ClientListener.java:326) > > org.basex.server.ClientListener.run(ClientListener.java:212) > > ================= </error> ================= > > > > =============== <caused_by> =============== > > def more() > > if @cache.length == 0 > > @session.write(4.chr) > > @session.send(@id) > > while(@session.read == 1.chr) > > @cache << @session.receive > > end > > end > > return @pos < @cache.length > > end > > > > def next > > if more() > > @pos += 1 > > return @cache[@pos - 1] > > end > > end > > =============== </caused_by> =============== > > > > _______________________________________________ > > BaseX-Talk mailing list > > BaseX-Talk at mailman.uni-konstanz.de > > https://mailman.uni-konstanz.de/mailman/listinfo/basex-talk > > > > >
CG
Christian Grün23 Oct 2011 00:14 #
Quoted text · Daniël Knippers · 1 line
> Thank you for your quick response. With your fix it seems to work fine now.
good to know..
Quoted text · Daniël Knippers · 2 lines
> Regarding the closer look at the Ruby code; I cannot quickly spot any > optimizations (seems like a very lightweight protocol anyway).
I was wondering if there's any optimization for the << operator? Some clients (such as the one for Python) directly write to a temporary buffer to speed up the result generation. This doesn't look very Python-like, but indeed it's faster than doing it the ordinary way. I didn't find a similar optimization for Perl, though.
Quoted text · Daniël Knippers · 7 lines
> If you are > interested in writing more 'Ruby-like' code then I can give some > recommendations about the syntax. Ruby syntax aims at improving readability > of code in general. The changes below will change nothing in execution, so > this is 100% optional and even personal preference so perhaps you want to > skip all of this. > [...]
That's good to know, and it all sounds reasonable. If you are interested in rewriting the BaseXClient file by yourself, I'll be glad to update in our repository.. ;) All the best, thanks again, Christian
Quoted text · Christian Grün · 103 lines
> On Sat, Oct 22, 2011 at 23:25, Christian Grün <christian.gruen at gmail.com> > wrote: >> >> Dear Daniël, >> >> thanks for the observation and the detailed feedback. I neither have >> Ruby installed, nor do I much about coding Ruby, but I think I found >> some bugs in the current implementation (e.g., the more() function had >> no exception handling yet). I hope I didn't introduce any typos.. >> Your feedback is welcome. >> >> Btw, if you know a little about Ruby encoding, it would be great if >> you could have a closer look at our client implementation. I'm sure it >> could be optimized, both in terms of execution time and coding style. >> >> Thanks, >> Christian >> >> PS: in all of our client implementations, the next() method can be >> used without calling more(). Indeed, the more() method only checks if >> there are more elements left, while the next() method increases the >> internal pointer. >> ___________________________ >> >> On Sat, Oct 22, 2011 at 10:04 PM, Daniël Knippers <dknippers at gmail.com> >> wrote: >> > Good evening, >> > >> > I am using Ruby on Rails and BaseX for some hobby projects, and I have >> > noticed the new Ruby client API + BaseX 7.0 causes >> > java.net.SocketExceptions >> > (see bottom of this message for complete error + stack trace) on the >> > server. >> > After inspecting the new client code, this seemed to have been caused by >> > the >> > new query iteration method which uses a cache. Reproducing this is easy; >> > execute the QueryExample.rb script from the repository (make sure to >> > first >> > remove 'query.init', which is still in the example but has been removed >> > from >> > the API). It raises the Exception every single time for me. >> > >> > Note the query does seem to return the expected result so I could just >> > ignore the Exception but that does not seem like the right thing to do >> > :) >> > >> > On a side note, the 'if more()' in the 'next' method seems superfluous >> > as >> > query.next should only be called inside a 'while query.more' loop >> > anyway. >> > Effectively 'query.more' is now called twice in that loop before the >> > cache >> > is read. >> > >> > Kind regards, >> > Daniël Knippers >> > >> > ps. I'm using Java 1.6.0_27, and the error occurs on the stable BaseX >> > 7.0 as >> > well as on snapshot 170343 (7.0.1 RC1). The error below is from the >> > 7.0.1 >> > RC1 version. Server and client were ran from the same machine. >> > >> > ================= <error> ================= >> > java.net.SocketException: Connection reset by peer: socket write error >> > java.net.SocketOutputStream.socketWrite0(Native Method) >> > java.net.SocketOutputStream.socketWrite(Unknown Source) >> > java.net.SocketOutputStream.write(Unknown Source) >> > org.basex.io.out.BufferOutput.flush(BufferOutput.java:52) >> > org.basex.io.out.PrintOutput.flush(PrintOutput.java:149) >> > org.basex.server.ClientListener.send(ClientListener.java:504) >> > org.basex.server.ClientListener.info(ClientListener.java:326) >> > org.basex.server.ClientListener.run(ClientListener.java:212) >> > ================= </error> ================= >> > >> > =============== <caused_by> =============== >> > def more() >> > if @cache.length == 0 >> > @session.write(4.chr) >> > @session.send(@id) >> > while(@session.read == 1.chr) >> > @cache << @session.receive >> > end >> > end >> > return @pos < @cache.length >> > end >> > >> > def next >> > if more() >> > @pos += 1 >> > return @cache[@pos - 1] >> > end >> > end >> > =============== </caused_by> =============== >> > >> > _______________________________________________ >> > BaseX-Talk mailing list >> > BaseX-Talk at mailman.uni-konstanz.de >> > https://mailman.uni-konstanz.de/mailman/listinfo/basex-talk >> > >> > > >
DK
Daniël Knippers23 Oct 2011 00:30 #
Quoted text · Christian Grün · 1 line
> I was wondering if there's any optimization for the << operator?
No idea :(
Quoted text · Christian Grün · 3 lines
> That's good to know, and it all sounds reasonable. If you are > interested in rewriting the BaseXClient file by yourself, I'll be glad > to update in our repository.. ;)
Yeah sure, I guess I can do that in the near future. Shouldn't take too long, but unfortunately cannot do it right now so it has to wait a bit. You'll see it pass by, and if not please forgive me for forgetting it ;) -- Daniël On Sun, Oct 23, 2011 at 00:14, Christian Grün <christian.gruen at gmail.com>wrote:
Quoted text · Christian Grün · 140 lines
> > Thank you for your quick response. With your fix it seems to work fine > now. > > good to know.. > > > Regarding the closer look at the Ruby code; I cannot quickly spot any > > optimizations (seems like a very lightweight protocol anyway). > > I was wondering if there's any optimization for the << operator? Some > clients (such as the one for Python) directly write to a temporary > buffer to speed up the result generation. This doesn't look very > Python-like, but indeed it's faster than doing it the ordinary way. I > didn't find a similar optimization for Perl, though. > > > If you are > > interested in writing more 'Ruby-like' code then I can give some > > recommendations about the syntax. Ruby syntax aims at improving > readability > > of code in general. The changes below will change nothing in execution, > so > > this is 100% optional and even personal preference so perhaps you want to > > skip all of this. > > [...] > > That's good to know, and it all sounds reasonable. If you are > interested in rewriting the BaseXClient file by yourself, I'll be glad > to update in our repository.. ;) > > All the best, thanks again, > Christian > __________________________________ > > > On Sat, Oct 22, 2011 at 23:25, Christian Grün <christian.gruen at gmail.com > > > > wrote: > >> > >> Dear Daniël, > >> > >> thanks for the observation and the detailed feedback. I neither have > >> Ruby installed, nor do I much about coding Ruby, but I think I found > >> some bugs in the current implementation (e.g., the more() function had > >> no exception handling yet). I hope I didn't introduce any typos.. > >> Your feedback is welcome. > >> > >> Btw, if you know a little about Ruby encoding, it would be great if > >> you could have a closer look at our client implementation. I'm sure it > >> could be optimized, both in terms of execution time and coding style. > >> > >> Thanks, > >> Christian > >> > >> PS: in all of our client implementations, the next() method can be > >> used without calling more(). Indeed, the more() method only checks if > >> there are more elements left, while the next() method increases the > >> internal pointer. > >> ___________________________ > >> > >> On Sat, Oct 22, 2011 at 10:04 PM, Daniël Knippers <dknippers at gmail.com> > >> wrote: > >> > Good evening, > >> > > >> > I am using Ruby on Rails and BaseX for some hobby projects, and I have > >> > noticed the new Ruby client API + BaseX 7.0 causes > >> > java.net.SocketExceptions > >> > (see bottom of this message for complete error + stack trace) on the > >> > server. > >> > After inspecting the new client code, this seemed to have been caused > by > >> > the > >> > new query iteration method which uses a cache. Reproducing this is > easy; > >> > execute the QueryExample.rb script from the repository (make sure to > >> > first > >> > remove 'query.init', which is still in the example but has been > removed > >> > from > >> > the API). It raises the Exception every single time for me. > >> > > >> > Note the query does seem to return the expected result so I could just > >> > ignore the Exception but that does not seem like the right thing to do > >> > :) > >> > > >> > On a side note, the 'if more()' in the 'next' method seems superfluous > >> > as > >> > query.next should only be called inside a 'while query.more' loop > >> > anyway. > >> > Effectively 'query.more' is now called twice in that loop before the > >> > cache > >> > is read. > >> > > >> > Kind regards, > >> > Daniël Knippers > >> > > >> > ps. I'm using Java 1.6.0_27, and the error occurs on the stable BaseX > >> > 7.0 as > >> > well as on snapshot 170343 (7.0.1 RC1). The error below is from the > >> > 7.0.1 > >> > RC1 version. Server and client were ran from the same machine. > >> > > >> > ================= <error> ================= > >> > java.net.SocketException: Connection reset by peer: socket write error > >> > java.net.SocketOutputStream.socketWrite0(Native Method) > >> > java.net.SocketOutputStream.socketWrite(Unknown Source) > >> > java.net.SocketOutputStream.write(Unknown Source) > >> > org.basex.io.out.BufferOutput.flush(BufferOutput.java:52) > >> > org.basex.io.out.PrintOutput.flush(PrintOutput.java:149) > >> > org.basex.server.ClientListener.send(ClientListener.java:504) > >> > org.basex.server.ClientListener.info(ClientListener.java:326) > >> > org.basex.server.ClientListener.run(ClientListener.java:212) > >> > ================= </error> ================= > >> > > >> > =============== <caused_by> =============== > >> > def more() > >> > if @cache.length == 0 > >> > @session.write(4.chr) > >> > @session.send(@id) > >> > while(@session.read == 1.chr) > >> > @cache << @session.receive > >> > end > >> > end > >> > return @pos < @cache.length > >> > end > >> > > >> > def next > >> > if more() > >> > @pos += 1 > >> > return @cache[@pos - 1] > >> > end > >> > end > >> > =============== </caused_by> =============== > >> > > >> > _______________________________________________ > >> > BaseX-Talk mailing list > >> > BaseX-Talk at mailman.uni-konstanz.de > >> > https://mailman.uni-konstanz.de/mailman/listinfo/basex-talk > >> > > >> > > > > > >

⚡Generated with XQuery