Return-Path: X-Original-To: apmail-db-derby-commits-archive@www.apache.org Delivered-To: apmail-db-derby-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id B9DB0912B for ; Tue, 7 Feb 2012 02:54:00 +0000 (UTC) Received: (qmail 14397 invoked by uid 500); 7 Feb 2012 02:54:00 -0000 Delivered-To: apmail-db-derby-commits-archive@db.apache.org Received: (qmail 14229 invoked by uid 500); 7 Feb 2012 02:53:54 -0000 Mailing-List: contact derby-commits-help@db.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: "Derby Development" List-Id: Delivered-To: mailing list derby-commits@db.apache.org Received: (qmail 14219 invoked by uid 99); 7 Feb 2012 02:53:52 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 07 Feb 2012 02:53:52 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 07 Feb 2012 02:53:50 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id A311F2388900; Tue, 7 Feb 2012 02:53:30 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1241335 - /db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BlobClob4BlobTest.java Date: Tue, 07 Feb 2012 02:53:30 -0000 To: derby-commits@db.apache.org From: mikem@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120207025330.A311F2388900@eris.apache.org> Author: mikem Date: Tue Feb 7 02:53:30 2012 New Revision: 1241335 URL: http://svn.apache.org/viewvc?rev=1241335&view=rev Log: DERBY-3740 BlobClob4BlobTest.testLockingWithLongRowBlob fails with .AssertionFailedError: FAIL - statement should timeout backported change #1240521 from trunk to 10.4 branch The 2 tests that were failing intermittently (testLockingWithLongRowBlob and testLockingBlob) would both select a target blob known to be returned as a stream, and assign it to a variable. The expectation was that until the end of the routine Derby would maintain a read lock on the blob. The problem was that it looks like some JVMs/JITs would recognize that the variable was never used and call finalize before the test executed the code to get an expected lock timeout on updating the blob in another connection. Fixed by adding references to the variable in code executed after the expected timeout. Before the fix test was failing about 1/2 time in my environment, after the fix the test ran 100 times without a failure. Modified: db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BlobClob4BlobTest.java Modified: db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BlobClob4BlobTest.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BlobClob4BlobTest.java?rev=1241335&r1=1241334&r2=1241335&view=diff ============================================================================== --- db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BlobClob4BlobTest.java (original) +++ db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/BlobClob4BlobTest.java Tue Feb 7 02:53:30 2012 @@ -69,10 +69,16 @@ public class BlobClob4BlobTest extends B stmt.executeUpdate("CREATE TABLE testClob (b INT, c INT)"); stmt.executeUpdate("ALTER TABLE testClob ADD COLUMN a CLOB(300K)"); + // multiple tests depend on small page size, make sure size is 4k + checkSmallPageSize(stmt, "TESTCLOB"); + stmt.executeUpdate("CREATE TABLE testBlob (b INT)"); stmt.executeUpdate("ALTER TABLE testBlob ADD COLUMN a blob(300k)"); stmt.executeUpdate("ALTER TABLE testBlob ADD COLUMN crc32 BIGINT"); + // multiple tests depend on small page size, make sure size is 4k + checkSmallPageSize(stmt, "TESTBLOB"); + stmt.close(); commit(); } @@ -1272,6 +1278,11 @@ public class BlobClob4BlobTest extends B } catch (SQLException se) { checkException(LOCK_TIMEOUT, se); } + + // DERBY-3740, the reference below to clob must remain after the above + // expected lock timeout, otherwise GC might run on the clob and + // cause intermittent problems if the GC causes lock to be released + // early. assertEquals("FAIL: clob length changed", 10000, clob.length()); // Test that update goes through after the transaction is committed @@ -2375,9 +2386,17 @@ public class BlobClob4BlobTest extends B * test locking */ public void testLockingBlob() throws Exception { - insertDefaultData(); Statement stmt = createStatement(); + + insertDefaultData(); + + // for blob lock to remain, autocommit must be false. + assertFalse(getConnection().getAutoCommit()); + + // test depends on small page size, make sure size is 4k + checkSmallPageSize(stmt, "TESTBLOB"); + ResultSet rs = stmt.executeQuery("select a,b from testBlob"); // fetch row back, get the column as a blob. Blob blob = null, shortBlob = null; @@ -2391,6 +2410,7 @@ public class BlobClob4BlobTest extends B } rs.close(); + Connection conn2 = openDefaultConnection(); // turn off autocommit, otherwise blobs/clobs cannot hang around // until end of transaction @@ -2414,6 +2434,21 @@ public class BlobClob4BlobTest extends B } catch (SQLException se) { checkException(LOCK_TIMEOUT, se); } + + // DERBY-3740, add a reference to the retrieved blobs that is used + // after the expected lock timeout in conn2. Before this change + // this test would intermittently fail. I believe that a smart + // JVM/JIT recognized that the blob reference was no longer used + // after the above while loop, and allowed gc on it before the routine + // could get to the expected conflicting lock. Upon GC the blob's + // finalize code closes the internal stream and releases the lock in + // read committed mode. + + // make sure we got the 10000 byte blob which should be a stream. + assertTrue(blob != null); + + // make sure we got the 26 byte blob which should be materialized. + assertTrue(shortBlob != null); // Test that update goes through after the transaction is committed commit(); @@ -2432,7 +2467,15 @@ public class BlobClob4BlobTest extends B { ResultSet rs; Statement stmt, stmt2; + + // for blob lock to remain, autocommit must be false. + assertFalse(getConnection().getAutoCommit()); + stmt = createStatement(); + + // test depends on small page size, make sure size is 4k + checkSmallPageSize(stmt, "TESTBLOB"); + stmt.execute("alter table testBlob add column al varchar(2000)"); stmt.execute("alter table testBlob add column bl varchar(3000)"); stmt.execute("alter table testBlob add column cl varchar(2000)"); @@ -2480,6 +2523,18 @@ public class BlobClob4BlobTest extends B } // Test that update goes through after the transaction is committed commit(); + + // DERBY-3740, add a reference to the retrieved blobs that is used + // after the expected lock timeout in conn2. Before this change + // this test would intermittently fail. I believe that a smart + // JVM/JIT recognized that the blob reference was no longer used + // after the above while loop, and allowed gc on it before the routine + // could get to the expected conflicting lock. Upon GC the blob's + // finalize code closes the internal stream and releases the lock in + // read committed mode. + assertTrue( + "FAIL - blob is null after expected lock timeout", blob != null); + stmt2.executeUpdate("update testBlob set el = null where b = 1"); stmt2.close(); @@ -3507,6 +3562,22 @@ public class BlobClob4BlobTest extends B + + private void checkSmallPageSize(Statement st, String tblName) + throws SQLException + { + ResultSet rs = st.executeQuery( + "select * from TABLE(SYSCS_DIAG.SPACE_TABLE('"+tblName+"')) T"); + + int found_rows = 0; + while (rs.next()) + { + found_rows++; + assertEquals(4096, rs.getInt("pagesize")); + } + assertTrue(found_rows == 1); + rs.close(); + } private static final String BLOB_BAD_POSITION = "XJ070";