Changeset: d9f7d6285c63 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=d9f7d6285c63
Modified Files:
        java/ChangeLog
        java/src/nl/cwi/monetdb/jdbc/MonetConnection.java
        java/src/nl/cwi/monetdb/jdbc/MonetDriver.java.in
        java/src/nl/cwi/monetdb/mcl/net/MapiSocket.java
Branch: default
Log Message:

JDBC: add so_timeout Driver property

On case the server locks up, the JDBC remains "hanging" too, waiting for
the server to send something.  When the so_timeout property is set, a
timeout for this can be set, such that the read eventually breaks, and
the caller (application) can continue.

Based on original patch by Philippe Hanrigou in bug #2828


diffs (134 lines):

diff --git a/java/ChangeLog b/java/ChangeLog
--- a/java/ChangeLog
+++ b/java/ChangeLog
@@ -1,6 +1,12 @@
 # ChangeLog file for java
 # This file is updated with Maddlog
 
+* Thu Jun 30 2011 Fabian Groffen <fab...@cwi.nl>
+- Add so_timeout Driver property to specify a SO_TIMEOUT value for the
+  socket in use to the database.  Setting this property to a value in
+  milliseconds defines the timeout for read calls, which may 'unlock'
+  the driver if the server hangs, bug #2828
+
 * Wed May 25 2011 Fabian Groffen <fab...@cwi.nl>
 - Added a naive implementation for PreparedStatement.setCharacterStream
 
diff --git a/java/src/nl/cwi/monetdb/jdbc/MonetConnection.java 
b/java/src/nl/cwi/monetdb/jdbc/MonetConnection.java
--- a/java/src/nl/cwi/monetdb/jdbc/MonetConnection.java
+++ b/java/src/nl/cwi/monetdb/jdbc/MonetConnection.java
@@ -149,7 +149,12 @@
                boolean debug = 
Boolean.valueOf(props.getProperty("debug")).booleanValue();
                String hash = props.getProperty("hash");
                blobIsBinary = 
Boolean.valueOf(props.getProperty("treat_blob_as_binary")).booleanValue();
-
+               int sockTimeout = 0;
+               try {
+                       sockTimeout = 
Integer.parseInt(props.getProperty("so_timeout"));
+               } catch (NumberFormatException e) {
+                       sockTimeout = 0;
+               }
                // check input arguments
                if (hostname == null || hostname.trim().equals(""))
                        throw new IllegalArgumentException("hostname should not 
be null or empty");
@@ -173,6 +178,7 @@
                if (hash != null) server.setHash(hash);
                if (database != null) server.setDatabase(database);
                server.setLanguage(language);
+               server.setSoTimeout(sockTimeout);
 
                // we're debugging here... uhm, should be off in real life
                if (debug) {
diff --git a/java/src/nl/cwi/monetdb/jdbc/MonetDriver.java.in 
b/java/src/nl/cwi/monetdb/jdbc/MonetDriver.java.in
--- a/java/src/nl/cwi/monetdb/jdbc/MonetDriver.java.in
+++ b/java/src/nl/cwi/monetdb/jdbc/MonetDriver.java.in
@@ -117,6 +117,7 @@
                props.put("port", PORT);
                props.put("debug", "false");
                props.put("language", "sql");   // mal, sql, <future>
+               props.put("so_timeout", "0");
 
                props.putAll(info);
                info = props;
@@ -239,6 +240,11 @@
                prop.description = "Whether BLOBs on the server should be 
treated as BINARY types, thus mapped to byte[]";
                props.add(prop);
 
+               prop = new DriverPropertyInfo("so_timeout", "0");
+               prop.required = false;
+               prop.description = "Defines the maximum time to wait in 
milliseconds on a blocking read socket call";
+               props.add(prop);
+
                DriverPropertyInfo[] dpi = new DriverPropertyInfo[props.size()];
                return((DriverPropertyInfo[])props.toArray(dpi));
        }
diff --git a/java/src/nl/cwi/monetdb/mcl/net/MapiSocket.java 
b/java/src/nl/cwi/monetdb/mcl/net/MapiSocket.java
--- a/java/src/nl/cwi/monetdb/mcl/net/MapiSocket.java
+++ b/java/src/nl/cwi/monetdb/mcl/net/MapiSocket.java
@@ -119,6 +119,9 @@
        /** A short in two bytes for holding the block size in bytes */
        private byte[] blklen = new byte[2];
 
+       /** SO_TIMEOUT value for the underlying java.net.Socket */
+       private int sockTimeout = 0;
+
        /**
         * Constructs a new MapiSocket.
         */
@@ -188,6 +191,20 @@
        }
 
        /**
+        * Set the SO_TIMEOUT on the underlying Socket.  When for some
+        * reason the connection to the database hangs, this setting can be
+        * useful to break out of this indefinite wait.
+        * This option must be enabled prior to entering the blocking
+        * operation to have effect.
+        *
+        * @param timeout The specified timeout, in milliseconds.  A timeout
+        *        of zero is interpreted as an infinite timeout.
+        */
+       public void setSoTimeout(int s) {
+               this.sockTimeout = s;
+       }
+
+       /**
         * Connects to the given host and port, logging in as the given
         * user.  If followRedirect is false, a RedirectionException is
         * thrown when a redirect is encountered.
@@ -203,7 +220,7 @@
         * @throws MCLParseException if bogus data is received
         * @throws MCLException if an MCL related error occurs
         */
-       public List connect(String host, int port, String user, String pass) 
+       public List connect(String host, int port, String user, String pass)
                throws IOException, MCLParseException, MCLException
        {
                // Wrap around the internal connect that needs to know if it
@@ -212,7 +229,7 @@
        }
 
        private List connect(String host, int port, String user, String pass,
-                       boolean makeConnection) 
+                       boolean makeConnection)
                throws IOException, MCLParseException, MCLException
        {
                if (ttl-- <= 0)
@@ -223,6 +240,8 @@
                        // set nodelay, as it greatly speeds up small messages 
(like we
                        // often do)
                        con.setTcpNoDelay(true);
+                       // limit time to wait on blocking operations (0 = 
indefinite)
+                       con.setSoTimeout(sockTimeout);
 
                        fromMonet = new BlockInputStream(con.getInputStream());
                        toMonet = new BlockOutputStream(con.getOutputStream());
@@ -678,7 +697,7 @@
 
                        // write the actual block
                        out.write(block, 0, writePos);
-                               
+
                        if (debug) {
                                if (last) {
                                        logTd("write final block: " + writePos 
+ " bytes");
_______________________________________________
Checkin-list mailing list
Checkin-list@monetdb.org
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to