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 ka...@apache.org on 2013/02/19 14:56:55 UTC
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
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());
+ }
+ }
}