db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kahat...@apache.org
Subject svn commit: r1447722 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/jdbc/LOBStreamControl.java testing/org/apache/derbyTesting/functionTests/tests/memory/BlobMemTest.java
Date Tue, 19 Feb 2013 13:56:55 GMT
Author: kahatlen
Date: Tue Feb 19 13:56:54 2013
New Revision: 1447722

URL: http://svn.apache.org/r1447722
Log:
DERBY-5752: LOBStreamControl should materialize less aggressively

Only materialize LOBs that are smaller than 32 KB in memory.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/memory/BlobMemTest.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java?rev=1447722&r1=1447721&r2=1447722&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/LOBStreamControl.java Tue Feb
19 13:56:54 2013
@@ -44,13 +44,12 @@ import org.apache.derby.shared.common.re
  * This class acts as a layer of blob/clob repository (in memory or file).
  * The max bytes of data stored in memory depends on the way this
  * class is created. If the class is created with initial data, the buffer
- * size is set to the size of the byte array supplied. If no initial data
- * is supplied or if the initial data size is less than DEFAULT_MAX_BUF_SIZE,
- * The buffer size is set to DEFAULT_MAX_BUF_SIZE.
+ * size is set to the size of the byte array supplied, but no larger than
+ * MAX_BUF_SIZE. If no initial data is supplied, or if the initial data size
+ * is less than DEFAULT_BUF_SIZE, the buffer size is set to DEFAULT_BUF_SIZE.
  * When write increases the data beyond this value a temporary file is created
  * and data is moved into that. If truncate reduces the size of the file below
- * initial buffer size (max of DEFAULT_MAX_BUF_SIZE and initial byte array size)
- * the data moved into memory.
+ * initial buffer size, the data is moved into memory.
  *
  * This class also creates InputStream and OutputStream which can be used to access
  * blob data irrespective of if its in memory or in file.
@@ -63,7 +62,8 @@ class LOBStreamControl {
     private final int bufferSize;
     private final EmbedConnection conn;
     private long updateCount;
-    private static final int DEFAULT_MAX_BUF_SIZE = 4096;
+    private static final int DEFAULT_BUF_SIZE = 4096;
+    private static final int MAX_BUF_SIZE = 32768;
 
     /**
      * Creates an empty LOBStreamControl.
@@ -73,7 +73,7 @@ class LOBStreamControl {
         this.conn = conn;
         updateCount = 0;
         //default buffer size
-        bufferSize = DEFAULT_MAX_BUF_SIZE;
+        bufferSize = DEFAULT_BUF_SIZE;
     }
 
     /**
@@ -85,7 +85,8 @@ class LOBStreamControl {
             throws IOException, StandardException {
         this.conn = conn;
         updateCount = 0;
-        bufferSize = Math.max (DEFAULT_MAX_BUF_SIZE, data.length);
+        bufferSize =
+            Math.min(Math.max(DEFAULT_BUF_SIZE, data.length), MAX_BUF_SIZE);
         write (data, 0, data.length, 0);
     }
 

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/memory/BlobMemTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/memory/BlobMemTest.java?rev=1447722&r1=1447721&r2=1447722&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/memory/BlobMemTest.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/memory/BlobMemTest.java
Tue Feb 19 13:56:54 2013
@@ -24,22 +24,16 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.sql.Blob;
+import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
-import java.sql.PreparedStatement;
 import java.util.Arrays;
 import java.util.Properties;
-
 import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import org.apache.derbyTesting.functionTests.harness.JavaVersionHolder;
-import org.apache.derbyTesting.functionTests.tests.lang.SimpleTest;
 import org.apache.derbyTesting.functionTests.util.streams.LoopingAlphabetStream;
-import org.apache.derbyTesting.functionTests.util.streams.LoopingAlphabetReader;
 import org.apache.derbyTesting.junit.BaseJDBCTestCase;
-import org.apache.derbyTesting.junit.DatabasePropertyTestSetup;
 import org.apache.derbyTesting.junit.JDBC;
 import org.apache.derbyTesting.junit.SystemPropertyTestSetup;
 import org.apache.derbyTesting.junit.TestConfiguration;
@@ -285,4 +279,44 @@ public class BlobMemTest extends BaseJDB
 
         rollback();
     }
+
+    /**
+     * Test that a BLOB that goes through the sorter does not get materialized
+     * twice in memory. It will still be materialized as part of the sorting,
+     * but the fix for DERBY-5752 prevents the creation of a second copy when
+     * accessing the BLOB after the sorting.
+     */
+    public void testDerby5752DoubleMaterialization() throws Exception {
+        setAutoCommit(false);
+
+        Statement s = createStatement();
+        s.execute("create table d5752(id int, b blob)");
+
+        int lobSize = 1000000;
+
+        // Insert a single BLOB in the table.
+        PreparedStatement insert =
+                prepareStatement("insert into d5752 values (1,?)");
+        insert.setBinaryStream(1, new LoopingAlphabetStream(lobSize), lobSize);
+        insert.execute();
+        closeStatement(insert);
+
+        Blob[] blobs = new Blob[15];
+
+        // Repeatedly sort the table and keep a reference to the BLOB.
+        for (int i = 0; i < blobs.length; i++) {
+            ResultSet rs = s.executeQuery("select * from d5752 order by id");
+            rs.next();
+            // Used to get an OutOfMemoryError here because a new copy of the
+            // BLOB was created in memory.
+            blobs[i] = rs.getBlob(2);
+            rs.close();
+        }
+
+        // Access the BLOBs here to make sure they are not garbage collected
+        // earlier (in which case we wouldn't see the OOME in the loop above).
+        for (int i = 0; i < blobs.length; i++) {
+            assertEquals(lobSize, blobs[i].length());
+        }
+    }
 }



Mime
View raw message