List:Commits« Previous MessageNext Message »
From:mmatthews Date:December 18 2007 3:39pm
Subject:Connector/J commit: r6699 - in branches/branch_5_1: . src/com/mysql/jdbc src/com/mysql/jdbc/jdbc2/optional src/testsuite/simple
View as plain text  
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/simplemmatthews18 Dec