You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by rh...@apache.org on 2012/05/08 17:10:19 UTC

svn commit: r1335570 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/store/raw/data/ testing/org/apache/derbyTesting/functionTests/tests/store/

Author: rhillegas
Date: Tue May  8 15:10:18 2012
New Revision: 1335570

URL: http://svn.apache.org/viewvc?rev=1335570&view=rev
Log:
DERBY-5234: Fix database corruption during table compression.

Added:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby5234Test.java   (with props)
Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/AllocExtent.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/AllocPage.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/AllocExtent.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/AllocExtent.java?rev=1335570&r1=1335569&r2=1335570&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/AllocExtent.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/AllocExtent.java Tue May  8 15:10:18 2012
@@ -207,7 +207,6 @@ public class AllocExtent implements Exte
 							"length " + length + " > maxlength " + maxlength);
 		}
 
-
 		this.extentOffset = offset;
 		this.extentStart = start;
 		this.extentEnd = start+maxlength-1;
@@ -575,7 +574,7 @@ public class AllocExtent implements Exte
             }
         }
 
-        if (new_highest_page >= 0)
+        if (new_highest_page + 1 >= 0)
         {
             freePages.shrink(new_highest_page + 1);
             unFilledPages.shrink(new_highest_page + 1);

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/AllocPage.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/AllocPage.java?rev=1335570&r1=1335569&r2=1335570&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/AllocPage.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/AllocPage.java Tue May  8 15:10:18 2012
@@ -1069,15 +1069,15 @@ public class AllocPage extends StoredPag
 			SanityManager.ASSERT(isLatched(), "page is not latched");
         }
 
-        int last_valid_page = extent.compress(owner, ntt, this);
+        int last_valid_page_bit = extent.compress(owner, ntt, this);
 
-        if (last_valid_page >= 0)
+        if (last_valid_page_bit >= 0)
         {
             // a non-negative return means that pages can be returned to
             // the operating system.
-            myContainer.truncatePages(extent.getPagenum(last_valid_page));
+            myContainer.truncatePages(extent.getPagenum(last_valid_page_bit));
 
-            if (last_valid_page == this.getPageNumber())
+            if (last_valid_page_bit == 0)
             {
                 // all pages of the extent have been returned to OS.
                 all_pages_compressed = true;

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby5234Test.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby5234Test.java?rev=1335570&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby5234Test.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby5234Test.java Tue May  8 15:10:18 2012
@@ -0,0 +1,202 @@
+/*
+  Class org.apache.derbyTesting.functionTests.tests.store.Derby5234Test
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to you under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+*/
+
+package org.apache.derbyTesting.functionTests.tests.store;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+import junit.framework.Test;
+
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.TestConfiguration;
+
+/**
+ * Regression test for DERBY-5234.
+ */
+public class Derby5234Test extends BaseJDBCTestCase
+{
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // CONSTANTS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    // this number of rows will force Derby to grab a second allocation page for the table
+    private static  final   long    ITERATIONS = 12500;
+
+    private static  final   int     VARCHAR_LENGTH = 2000;
+    private static  final   String  SEED = "0123456789";
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // STATE
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // CONSTRUCTOR
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    public Derby5234Test(String name)
+    {
+        super(name);
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // JUnit BEHAVIOR
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    /** Create a suite of tests. */
+    public static Test suite()
+    {
+        return TestConfiguration.defaultSuite( Derby5234Test.class );
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // TESTS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * <p>
+     * Basic test case for DERBY-5234. Test that the last allocation page
+     * remembers which pages have been released to the operating system.
+     * </p>
+     */
+    public void test_01_basic() throws Exception
+    {
+        Connection  conn = getConnection();
+
+        goodStatement
+            (
+             conn,
+             "create table t5234( a bigint, b varchar( " + VARCHAR_LENGTH + " ) )"
+             );
+
+        // this makes the test run faster
+        boolean oldAutoCommit = conn.getAutoCommit();
+        conn.setAutoCommit( false );
+
+        insertRows( conn );
+        deleteRows( conn );
+        compressTable( conn );
+
+        // the bug would cause the second round of insertions to write
+        // beyond the end of the file
+        insertRows( conn );
+        
+        conn.setAutoCommit( oldAutoCommit );
+    }
+    /** Fill the table with enough rows to force Derby to grab a second allocation page */
+    private void    insertRows( Connection conn )
+        throws Exception
+    {
+        PreparedStatement insert = chattyPrepare
+            (
+             conn,
+             "insert into t5234( a, b ) values ( ?, ? )"
+             );
+        String          varcharValue = makeVarcharValue();
+
+        long    percent = 0L;
+        for ( long i = 0; i < ITERATIONS; i++)
+        {
+            if ( (i * 10) / ITERATIONS  > percent)
+            {
+                conn.commit();
+                percent++;
+            }
+
+            insert.setLong( 1, i );
+            insert.setString( 2, varcharValue );
+            insert.executeUpdate();
+        }
+        
+        conn.commit();
+    }
+    private String    makeVarcharValue()
+    {
+        StringBuffer    buffer = new StringBuffer();
+        int                 count = VARCHAR_LENGTH / SEED.length();
+
+        for ( int i = 0; i < count; i++ ) { buffer.append( SEED ); }
+
+        return buffer.toString();
+    }
+    private void deleteRows( Connection conn )
+        throws Exception
+    {
+        goodStatement
+            (
+             conn,
+             "delete from t5234"
+             );
+        
+        conn.commit();
+    }
+    private void compressTable( Connection conn )
+        throws Exception
+    {
+        goodStatement
+            (
+             conn,
+             "call syscs_util.syscs_inplace_compress_table( 'APP', 'T5234', 0, 0, 1 )"
+             );
+
+        conn.commit();
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    //
+    // HELPER METHODS
+    //
+    ///////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Run a successful statement.
+     * @throws SQLException 
+     */
+    private void    goodStatement( Connection conn, String command ) throws SQLException
+    {
+        PreparedStatement    ps = chattyPrepare( conn, command );
+
+        ps.execute();
+        ps.close();
+    }
+    
+    /**
+     * Prepare a statement and report its sql text.
+     */
+    private PreparedStatement   chattyPrepare( Connection conn, String text )
+        throws SQLException
+    {
+        println( "Preparing statement:\n\t" + text );
+        
+        return conn.prepareStatement( text );
+    }
+
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby5234Test.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java?rev=1335570&r1=1335569&r2=1335570&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java Tue May  8 15:10:18 2012
@@ -81,6 +81,7 @@ public class _Suite extends BaseTestCase
         suite.addTest(OCRecoveryTest.suite());
         suite.addTest(TableLockBasicTest.suite());
         suite.addTest(ServicePropertiesFileTest.suite());
+        suite.addTest(Derby5234Test.suite());
 
         /* Tests that only run in sane builds */
         if (SanityManager.DEBUG) {