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