Modified:
branches/branch_5_1/CHANGES
branches/branch_5_1/src/com/mysql/jdbc/ConnectionImpl.java
branches/branch_5_1/src/com/mysql/jdbc/ConnectionProperties.java
branches/branch_5_1/src/com/mysql/jdbc/ConnectionPropertiesImpl.java
branches/branch_5_1/src/com/mysql/jdbc/LocalizedErrorMessages.properties
branches/branch_5_1/src/com/mysql/jdbc/MysqlIO.java
branches/branch_5_1/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java
branches/branch_5_1/src/testsuite/simple/ConnectionTest.java
Log:
Added two new connection properties, "selfDestructOnPingSecondsLifetime" and
"selfDestructOnPingMaxOperations" designed to control overall connection lifetime
(useful to reclaim resources on the server side) for connection pools that don't have such a
facility.
The driver will consult the values of these properties when a ping is sent, either through
calling Connection.ping(), issuing the "ping marker" query (any query that starts with
"/* ping */"), or when using JDBC-4.0, calling Connection.isValid().
If the connection has issued too many operations, or is too old, the driver will
throw a SQLException with the SQLState of "08S01" at the time of the ping, which
will cause the connection to be invalidated with most pools in use today.
Modified: branches/branch_5_1/CHANGES
===================================================================
--- branches/branch_5_1/CHANGES 2007-12-13 17:20:34 UTC (rev 6698)
+++ branches/branch_5_1/CHANGES 2007-12-18 15:39:28 UTC (rev 6699)
@@ -72,6 +72,19 @@
- Fixed BUG#30508 - ResultSet returned by Statement.getGeneratedKeys() is not closed
automatically when statement that created it is closed.
+ - Added two new connection properties, "selfDestructOnPingSecondsLifetime" and
+ "selfDestructOnPingMaxOperations" designed to control overall connection lifetime
+ (useful to reclaim resources on the server side) for connection pools that don't have such a
+ facility.
+
+ The driver will consult the values of these properties when a ping is sent, either through
+ calling Connection.ping(), issuing the "ping marker" query (any query that starts with
+ "/* ping */"), or when using JDBC-4.0, calling Connection.isValid().
+
+ If the connection has issued too many operations, or is too old, the driver will
+ throw a SQLException with the SQLState of "08S01" at the time of the ping, which
+ will cause the connection to be invalidated with most pools in use today.
+
10-09-07 - Version 5.1.5
- Released instead of 5.1.4 to pickup patch for BUG#31053
Modified: branches/branch_5_1/src/com/mysql/jdbc/ConnectionImpl.java
===================================================================
--- branches/branch_5_1/src/com/mysql/jdbc/ConnectionImpl.java 2007-12-13 17:20:34 UTC (rev 6698)
+++ branches/branch_5_1/src/com/mysql/jdbc/ConnectionImpl.java 2007-12-18 15:39:28 UTC (rev 6699)
@@ -1971,7 +1971,7 @@
long queriesIssuedFailedOverCopy = this.queriesIssuedFailedOver;
this.queriesIssuedFailedOver = 0;
-
+
try {
if (!getHighAvailability() && !this.failedOver) {
boolean connectionGood = false;
@@ -3689,7 +3689,7 @@
}
private boolean usingCachedConfig = false;
-
+
/**
* Loads the result of 'SHOW VARIABLES' into the serverVariables field so
* that the driver can configure itself.
@@ -3899,6 +3899,19 @@
checkClosed();
}
+ long pingMillisLifetime = getSelfDestructOnPingSecondsLifetime();
+ int pingMaxOperations = getSelfDestructOnPingMaxOperations();
+
+ if ((pingMillisLifetime > 0 && (System.currentTimeMillis() - this.connectionCreationTimeMillis) > pingMillisLifetime)
+ || (pingMaxOperations > 0 && pingMaxOperations <= this.io
+ .getCommandCount())) {
+
+ close();
+
+ throw SQLError.createSQLException(Messages
+ .getString("Connection.exceededConnectionLifetime"),
+ SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE);
+ }
// Need MySQL-3.22.1, but who uses anything older!?
this.io.sendCommand(MysqlDefs.PING, null, null, false, null);
}
Modified: branches/branch_5_1/src/com/mysql/jdbc/ConnectionProperties.java
===================================================================
--- branches/branch_5_1/src/com/mysql/jdbc/ConnectionProperties.java 2007-12-13 17:20:34 UTC (rev 6698)
+++ branches/branch_5_1/src/com/mysql/jdbc/ConnectionProperties.java 2007-12-18 15:39:28 UTC (rev 6699)
@@ -1586,4 +1586,12 @@
public abstract boolean getUseLegacyDatetimeCode();
public abstract void setUseLegacyDatetimeCode(boolean flag);
+
+ public int getSelfDestructOnPingSecondsLifetime();
+
+ public void setSelfDestructOnPingSecondsLifetime(int seconds);
+
+ public int getSelfDestructOnPingMaxOperations();
+
+ public void setSelfDestructOnPingMaxOperations(int maxOperations);
}
Modified: branches/branch_5_1/src/com/mysql/jdbc/ConnectionPropertiesImpl.java
===================================================================
--- branches/branch_5_1/src/com/mysql/jdbc/ConnectionPropertiesImpl.java 2007-12-13 17:20:34 UTC (rev 6698)
+++ branches/branch_5_1/src/com/mysql/jdbc/ConnectionPropertiesImpl.java 2007-12-18 15:39:28 UTC (rev 6699)
@@ -1277,6 +1277,22 @@
Messages.getString("ConnectionProperties.secondsBeforeRetryMaster"), //$NON-NLS-1$
"3.0.2", HA_CATEGORY, 8); //$NON-NLS-1$
+ private IntegerConnectionProperty selfDestructOnPingSecondsLifetime = new IntegerConnectionProperty(
+ "selfDestructOnPingSecondsLifetime",
+ 0,
+ 0,
+ Integer.MAX_VALUE,
+ Messages.getString("ConnectionProperties.selfDestructOnPingSecondsLifetime"),
+ "5.1.6", HA_CATEGORY, Integer.MAX_VALUE);
+
+ private IntegerConnectionProperty selfDestructOnPingMaxOperations = new IntegerConnectionProperty(
+ "selfDestructOnPingMaxOperations",
+ 0,
+ 0,
+ Integer.MAX_VALUE,
+ Messages.getString("ConnectionProperties.selfDestructOnPingMaxOperations"),
+ "5.1.6", HA_CATEGORY, Integer.MAX_VALUE);
+
private StringConnectionProperty serverTimezone = new StringConnectionProperty(
"serverTimezone", //$NON-NLS-1$
null,
@@ -4325,4 +4341,20 @@
public void setUseLegacyDatetimeCode(boolean flag) {
this.useLegacyDatetimeCode.setValue(flag);
}
+
+ public int getSelfDestructOnPingSecondsLifetime() {
+ return this.selfDestructOnPingSecondsLifetime.getValueAsInt();
+ }
+
+ public void setSelfDestructOnPingSecondsLifetime(int seconds) {
+ this.selfDestructOnPingSecondsLifetime.setValue(seconds);
+ }
+
+ public int getSelfDestructOnPingMaxOperations() {
+ return this.selfDestructOnPingMaxOperations.getValueAsInt();
+ }
+
+ public void setSelfDestructOnPingMaxOperations(int maxOperations) {
+ this.selfDestructOnPingMaxOperations.setValue(maxOperations);
+ }
}
Modified: branches/branch_5_1/src/com/mysql/jdbc/LocalizedErrorMessages.properties
===================================================================
--- branches/branch_5_1/src/com/mysql/jdbc/LocalizedErrorMessages.properties 2007-12-13 17:20:34 UTC (rev 6698)
+++ branches/branch_5_1/src/com/mysql/jdbc/LocalizedErrorMessages.properties 2007-12-18 15:39:28 UTC (rev 6699)
@@ -542,6 +542,8 @@
ConnectionProperties.secondsBeforeRetryMaster.1=to reconnect to the master server? Whichever condition is met first,
ConnectionProperties.secondsBeforeRetryMaster.2='queriesBeforeRetryMaster' or 'secondsBeforeRetryMaster' will cause an
ConnectionProperties.secondsBeforeRetryMaster.3=attempt to be made to reconnect to the master. Time in seconds, defaults to 30
+ConnectionProperties.selfDestructOnPingSecondsLifetime=If set to a non-zero value, the driver will report close the connection and report failure when Connection.ping() or Connection.isValid(int) is called if the connnection's lifetime exceeds this value.
+ConnectionProperties.selfDestructOnPingMaxOperations==If set to a non-zero value, the driver will report close the connection and report failure when Connection.ping() or Connection.isValid(int) is called if the connnection's count of commands sent to the server exceeds this value.
ConnectionProperties.serverTimezone=Override detection/mapping of timezone. Used when timezone from server doesn't map to Java timezone
ConnectionProperties.sessionVariables=A comma-separated list of name/value pairs to be sent as SET SESSION ... to the server when the driver connects.
ConnectionProperties.slowQueryThresholdMillis=If 'logSlowQueries' is enabled, how long should a query (in ms) before it is logged as 'slow'?
@@ -615,4 +617,6 @@
TimeUtil.TooGenericTimezoneId=The server timezone value ''${0}'' represents more than one timezone. You must \
configure either the server or JDBC driver (via the 'serverTimezone' configuration property) to use a \
-more specifc timezone value if you want to utilize timezone support. The timezones that ''${0}'' maps to are: ${1}.
\ No newline at end of file
+more specifc timezone value if you want to utilize timezone support. The timezones that ''${0}'' maps to are: ${1}.
+
+Connection.exceededConnectionLifetime=Ping or validation failed because configured connection lifetime exceeded.
\ No newline at end of file
Modified: branches/branch_5_1/src/com/mysql/jdbc/MysqlIO.java
===================================================================
--- branches/branch_5_1/src/com/mysql/jdbc/MysqlIO.java 2007-12-13 17:20:34 UTC (rev 6698)
+++ branches/branch_5_1/src/com/mysql/jdbc/MysqlIO.java 2007-12-18 15:39:28 UTC (rev 6699)
@@ -234,6 +234,7 @@
private List statementInterceptors;
private boolean useDirectRowUnpack = true;
private int useBufferRowSizeThreshold;
+ private int commandCount = 0;
/**
* Constructor: Connect to the MySQL server and setup a stream connection.
@@ -591,6 +592,10 @@
int packetLength = (this.packetHeaderBuf[0] & 0xff) +
((this.packetHeaderBuf[1] & 0xff) << 8) +
((this.packetHeaderBuf[2] & 0xff) << 16);
+
+ if (packetLength > this.maxAllowedPacket) {
+ throw new PacketTooBigException(packetLength, this.maxAllowedPacket);
+ }
if (this.traceProtocol) {
StringBuffer traceMessageBuf = new StringBuffer();
@@ -1754,6 +1759,8 @@
final Buffer sendCommand(int command, String extraData, Buffer queryPacket,
boolean skipCheck, String extraDataCharEncoding)
throws SQLException {
+ this.commandCount++;
+
//
// We cache these locally, per-command, as the checks
// for them are in very 'hot' sections of the I/O code
@@ -4458,4 +4465,8 @@
protected String getQueryTimingUnits() {
return this.queryTimingUnits;
}
-}
+
+ protected int getCommandCount() {
+ return this.commandCount;
+ }
+}
\ No newline at end of file
Modified: branches/branch_5_1/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java
===================================================================
--- branches/branch_5_1/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java 2007-12-13 17:20:34 UTC (rev 6698)
+++ branches/branch_5_1/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java 2007-12-18 15:39:28 UTC (rev 6699)
@@ -2524,4 +2524,20 @@
public void setUseLegacyDatetimeCode(boolean flag) {
this.mc.setUseLegacyDatetimeCode(flag);
}
+
+ public int getSelfDestructOnPingMaxOperations() {
+ return this.mc.getSelfDestructOnPingMaxOperations();
+ }
+
+ public int getSelfDestructOnPingSecondsLifetime() {
+ return this.mc.getSelfDestructOnPingSecondsLifetime();
+ }
+
+ public void setSelfDestructOnPingMaxOperations(int maxOperations) {
+ this.mc.setSelfDestructOnPingMaxOperations(maxOperations);
+ }
+
+ public void setSelfDestructOnPingSecondsLifetime(int seconds) {
+ this.mc.setSelfDestructOnPingSecondsLifetime(seconds);
+ }
}
Modified: branches/branch_5_1/src/testsuite/simple/ConnectionTest.java
===================================================================
--- branches/branch_5_1/src/testsuite/simple/ConnectionTest.java 2007-12-13 17:20:34 UTC (rev 6698)
+++ branches/branch_5_1/src/testsuite/simple/ConnectionTest.java 2007-12-18 15:39:28 UTC (rev 6699)
@@ -1602,4 +1602,57 @@
public void testNonVerifyServerCert() throws Exception {
getConnectionWithProps("useSSL=true,verifyServerCertificate=false,requireSSL=true");
}
-}
+
+ public void testSelfDestruct() throws Exception {
+ Connection selfDestructingConn = getConnectionWithProps("selfDestructOnPingMaxOperations=2");
+
+ boolean failed = false;
+
+ for (int i = 0; i < 20; i++) {
+ selfDestructingConn.createStatement().executeQuery("SELECT 1");
+
+ try {
+ selfDestructingConn.createStatement().executeQuery("/* ping */ SELECT 1");
+ } catch (SQLException sqlEx) {
+ String sqlState = sqlEx.getSQLState();
+
+ assertEquals("08S01", sqlState);
+
+ failed = true;
+
+ break;
+ }
+ }
+
+ if (!failed) {
+ fail("Connection should've self-destructed");
+ }
+
+ failed = false;
+
+ selfDestructingConn = getConnectionWithProps("selfDestructOnPingSecondsLifetime=1");
+
+ long begin = System.currentTimeMillis();
+
+ for (int i = 0; i < 20; i++) {
+ selfDestructingConn.createStatement().executeQuery("SELECT SLEEP(1)");
+
+ try {
+ selfDestructingConn.createStatement().executeQuery("/* ping */ SELECT 1");
+ } catch (SQLException sqlEx) {
+ String sqlState = sqlEx.getSQLState();
+
+ assertEquals("08S01", sqlState);
+
+ failed = true;
+
+ break;
+ }
+ }
+
+ if (!failed) {
+ fail("Connection should've self-destructed");
+ }
+
+ }
+}
\ No newline at end of file
| Thread |
|---|
| • Connector/J commit: r6699 - in branches/branch_5_1: . src/com/mysql/jdbc src/com/mysql/jdbc/jdbc2/optional src/testsuite/simple | mmatthews | 18 Dec |