Update of /cvsroot/monetdb/clients/src/java/src/nl/cwi/monetdb/mcl/net
In directory 
sc8-pr-cvs16.sourceforge.net:/tmp/cvs-serv20440/src/nl/cwi/monetdb/mcl/net

Modified Files:
      Tag: Clients_1-20
        MapiSocket.java 
Log Message:
Fixing the bug rapported to happen on Windows and by jsolderitsch.

When the connection is slow enough for blocks not to arrive in time,
such that Java cannot fetch them at once, the BufferedInputStream will
return the sofar received part, instead of blocking until the entire
requested number of bytes are read.  This little detail I had missed,
and instead I assumed the behaviour was the same as the InputStream's
read() method, which /does/ block.  As a result, JBDC would sometimes
get partial blocks, and the code would assume this was because the
server sent an EOF.  The latter, however, was not true.  To work around
this, I now read as long as necessary to get the required bytes
(actually spinlocking) to make sure I deal with entire blocks.  Maybe we
should invest in dealing with incomplete blocks in the future, but for
now this should solve the issue at hand.

I consider this a quite critical bug-fix for JDBC.



Index: MapiSocket.java
===================================================================
RCS file: 
/cvsroot/monetdb/clients/src/java/src/nl/cwi/monetdb/mcl/net/MapiSocket.java,v
retrieving revision 1.9.2.1
retrieving revision 1.9.2.2
diff -u -d -r1.9.2.1 -r1.9.2.2
--- MapiSocket.java     12 Nov 2007 21:42:10 -0000      1.9.2.1
+++ MapiSocket.java     13 Nov 2007 14:52:39 -0000      1.9.2.2
@@ -632,6 +632,41 @@
                }
 
                /**
+                * Small wrapper to get a blocking variant of the read() method
+                * on the BufferedInputStream.  We want to benefit from the
+                * Buffered pre-fetching, but not dealing with half blocks.
+                * Changing this class to be able to use the partially received
+                * data will greatly complicate matters, while an performance
+                * improvement is debatable given the relatively small size of
+                * our blocks.  Maybe it does speed up on slower links, then
+                * consider this method a quick bug fix/workaround.
+                */
+               private boolean _read(byte[] b, int len) throws IOException {
+                       int s;
+                       int off = 0;
+
+                       while (len > 0) {
+                               s = in.read(b, off, len);
+                               if (s == -1) {
+                                       // if we have read something before, we 
should have been
+                                       // able to read the whole, so make this 
fatal
+                                       if (off > 0) {
+                                               if (debug) {
+                                                       logRd("the following 
incomplete block was received:");
+                                                       logRx(new String(b, 0, 
off, "UTF-8"));
+                                               }
+                                               throw new 
IOException("Incomplete block read from stream");
+                                       }
+                                       return(false);
+                               }
+                               len -= s;
+                               off += s;
+                       }
+
+                       return(true);
+               }
+
+               /**
                 * Reads the next block on the stream into the internal buffer,
                 * or writes the prompt in the buffer.
                 *
@@ -656,11 +691,8 @@
                 */
                private void readBlock() throws IOException {
                        // read next two bytes (short)
-                       int size = in.read(blklen);
-                       if (size == -1) throw
+                       if (!_read(blklen, 2)) throw
                                new IOException("End of stream reached");
-                       if (size < 2) throw
-                               new AssertionError("Illegal start of block");
 
                        // Get the short-value and store its value in blockLen.
                        blockLen = (short)(
@@ -683,19 +715,11 @@
                                throw new AssertionError("Server sent a block " 
+
                                                "larger than BLOCKsize: " +
                                                blockLen + " > " + 
block.length);
-                       size = in.read(block, 0, blockLen);
-                       if (size == -1)
+                       if (!_read(block, blockLen))
                                throw new IOException("End of stream reached");
-                       if (size != blockLen) {
-                               if (debug) {
-                                       logRd("the following incomplete block 
was received:");
-                                       logRx(new String(block, 0, size, 
"UTF-8"));
-                               }
-                               throw new IOException("Incomplete block read 
from stream");
-                       }
 
                        if (debug) {
-                               logRx(new String(block, 0, size, "UTF-8"));
+                               logRx(new String(block, 0, blockLen, "UTF-8"));
                        }
 
                        // if this is the last block, make it end with a 
newline and


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Monetdb-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/monetdb-checkins

Reply via email to