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 kr...@apache.org on 2010/06/04 13:04:02 UTC

svn commit: r951362 - in /db/derby/code/branches/10.6: ./ java/engine/org/apache/derby/iapi/types/

Author: kristwaa
Date: Fri Jun  4 11:04:02 2010
New Revision: 951362

URL: http://svn.apache.org/viewvc?rev=951362&view=rev
Log:
DERBY-4661: Reduce size of encoding buffer for short character values

Merged fix from trunk (revision 948069).

Modified:
    db/derby/code/branches/10.6/   (props changed)
    db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/CharStreamHeaderGenerator.java
    db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/ClobStreamHeaderGenerator.java
    db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/ReaderToUTF8Stream.java
    db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/SQLClob.java
    db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/StreamHeaderGenerator.java

Propchange: db/derby/code/branches/10.6/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Jun  4 11:04:02 2010
@@ -1 +1 @@
-/db/derby/code/trunk:938547,938796,938959,939231,940462,940469,941627,942031,944152,946794,948045
+/db/derby/code/trunk:938547,938796,938959,939231,940462,940469,941627,942031,944152,946794,948045,948069

Modified: db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/CharStreamHeaderGenerator.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/CharStreamHeaderGenerator.java?rev=951362&r1=951361&r2=951362&view=diff
==============================================================================
--- db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/CharStreamHeaderGenerator.java (original)
+++ db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/CharStreamHeaderGenerator.java Fri Jun  4 11:04:02 2010
@@ -134,4 +134,13 @@ public final class CharStreamHeaderGener
             return 0;
         }
     }
+
+    /**
+     * Returns the maximum header length.
+     *
+     * @return Maximum header length in bytes.
+     */
+    public int getMaxHeaderLength() {
+        return 2;
+    }
 }

Modified: db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/ClobStreamHeaderGenerator.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/ClobStreamHeaderGenerator.java?rev=951362&r1=951361&r2=951362&view=diff
==============================================================================
--- db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/ClobStreamHeaderGenerator.java (original)
+++ db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/ClobStreamHeaderGenerator.java Fri Jun  4 11:04:02 2010
@@ -239,6 +239,15 @@ public final class ClobStreamHeaderGener
     }
 
     /**
+     * Returns the maximum header length.
+     *
+     * @return Maximum header length in bytes.
+     */
+    public int getMaxHeaderLength() {
+        return 5;
+    }
+
+    /**
      * Determines which header format to use.
      * <p>
      * <em>Implementation note:</em> The header format is determined by

Modified: db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/ReaderToUTF8Stream.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/ReaderToUTF8Stream.java?rev=951362&r1=951361&r2=951362&view=diff
==============================================================================
--- db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/ReaderToUTF8Stream.java (original)
+++ db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/ReaderToUTF8Stream.java Fri Jun  4 11:04:02 2010
@@ -51,6 +51,8 @@ public final class ReaderToUTF8Stream
 
     /** Constant indicating the first iteration of {@code fillBuffer}. */
     private final static int FIRST_READ = Integer.MIN_VALUE;
+    /** Buffer space reserved for one 3 byte encoded char and the EOF marker. */
+    private final static int READ_BUFFER_RESERVATION = 6;
     /**
      * Constant indicating that no mark is set in the stream, or that the read
      * ahead limit of the mark has been exceeded.
@@ -58,10 +60,11 @@ public final class ReaderToUTF8Stream
     private final static int MARK_UNSET_OR_EXCEEDED = -1;
     /**
      * Buffer to hold the data read from stream and converted to the modified
-     * UTF-8 format. The initial size is 32 KB, but it may grow if the
+     * UTF-8 format. The initial size is dependent on whether the data value
+     * length is known (limited upwards to 32 KB), but it may grow if
      * {@linkplain #mark(int)} is invoked.
      */
-    private byte[] buffer = new byte[32*1024];
+    private byte[] buffer;
 	private int boff;
     private int blen = -1;
     /** Stream mark, set through {@linkplain #mark(int)}. */
@@ -83,7 +86,7 @@ public final class ReaderToUTF8Stream
      * Number of characters to truncate from this stream.
      * The SQL standard allows for truncation of trailing spaces for CLOB,
      * VARCHAR and CHAR. If zero, no characters are truncated, unless the
-     * stream length execeeds the maximum length of the column we are inserting
+     * stream length exceeds the maximum length of the column we are inserting
      * into.
      */
     private final int charsToTruncate;
@@ -124,11 +127,13 @@ public final class ReaderToUTF8Stream
                               String typeName,
                               StreamHeaderGenerator headerGenerator) {
         this.reader = new LimitReader(appReader);
-        reader.setLimit(valueLength);
         this.charsToTruncate = numCharsToTruncate;
         this.valueLength = valueLength;
         this.typeName = typeName;
         this.hdrGen = headerGenerator;
+
+        int absValueLength = Math.abs(valueLength);
+        reader.setLimit(absValueLength);
         if (SanityManager.DEBUG) {
             // Check the type name
             // The national types (i.e. NVARCHAR) are not used/supported.
@@ -138,6 +143,17 @@ public final class ReaderToUTF8Stream
                     typeName.equals(TypeId.CLOB_NAME)) ||
                     typeName.equals(TypeId.LONGVARCHAR_NAME));
         }
+        // Optimization for small values, where we reduce the memory
+        // requirement during encoding/insertion.
+        // Be conservative, assume three bytes per char.
+        int bz = 32*1024; // 32 KB default
+        if (absValueLength < bz / 3) {
+            // Enforce a minimum size of the buffer, otherwise read may loop
+            // indefinitely (must enter for loop in fillBuffer to detect EOF).
+            bz = hdrGen.getMaxHeaderLength() +
+                    Math.max(READ_BUFFER_RESERVATION, absValueLength * 3 +3);
+        }
+        buffer = new byte[bz];
     }
 
     /**
@@ -167,7 +183,6 @@ public final class ReaderToUTF8Stream
             throw new IllegalArgumentException("Maximum length for a capped " +
                     "stream cannot be negative: " + maximumLength);
         }
-        reader.setLimit(maximumLength);
     }
 
     /**
@@ -325,7 +340,7 @@ public final class ReaderToUTF8Stream
         if (mark >= 0) {
             // Add 6 bytes reserved for one 3 byte character encoding and the
             // 3 byte Derby EOF marker (see encoding loop further down).
-            int spaceRequired = readAheadLimit + 6;
+            int spaceRequired = readAheadLimit + READ_BUFFER_RESERVATION;
             if (mark + spaceRequired > buffer.length) {
                 if (blen != -1) {
                     // Calculate the new offset, as we may have to shift bytes
@@ -347,7 +362,7 @@ public final class ReaderToUTF8Stream
 
 		// 6! need to leave room for a three byte UTF8 encoding
 		// and 3 bytes for our special end of file marker.
-		for (; off <= buffer.length - 6; )
+        for (; off <= buffer.length - READ_BUFFER_RESERVATION; )
 		{
 			int c = reader.read();
 			if (c < 0) {
@@ -558,7 +573,7 @@ public final class ReaderToUTF8Stream
      */
     public void reset()
             throws IOException {
-        // Throw execption if the stream has been closed implicitly or
+        // Throw exception if the stream has been closed implicitly or
         // explicitly.
         if (buffer == null) {
             throw new EOFException(MessageService.getTextMessage

Modified: db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/SQLClob.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/SQLClob.java?rev=951362&r1=951361&r2=951362&view=diff
==============================================================================
--- db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/SQLClob.java (original)
+++ db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/SQLClob.java Fri Jun  4 11:04:02 2010
@@ -57,10 +57,6 @@ import java.util.Calendar;
 public class SQLClob
 	extends SQLVarchar
 {
-
-    /** The maximum number of bytes used by the stream header. */
-    private static final int MAX_STREAM_HEADER_LENGTH = 5;
-
     /** The header generator used for 10.4 (or older) databases. */
     private static final StreamHeaderGenerator TEN_FOUR_CLOB_HEADER_GENERATOR =
             new ClobStreamHeaderGenerator(true);
@@ -70,6 +66,14 @@ public class SQLClob
             new ClobStreamHeaderGenerator(false);
 
     /**
+     * The maximum number of bytes used by the stream header.
+     * <p>
+     * Use the length specified by the ten five header generator.
+     */
+    private static final int MAX_STREAM_HEADER_LENGTH =
+            TEN_FIVE_CLOB_HEADER_GENERATOR.getMaxHeaderLength();
+
+    /**
      * The descriptor for the stream. If there is no stream this should be
      * {@code null}, which is also true if the descriptor hasen't been
      * constructed yet.

Modified: db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/StreamHeaderGenerator.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/StreamHeaderGenerator.java?rev=951362&r1=951361&r2=951362&view=diff
==============================================================================
--- db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/StreamHeaderGenerator.java (original)
+++ db/derby/code/branches/10.6/java/engine/org/apache/derby/iapi/types/StreamHeaderGenerator.java Fri Jun  4 11:04:02 2010
@@ -86,4 +86,11 @@ public interface StreamHeaderGenerator {
      * @throws IOException if writing to the destination stream fails
      */
     int writeEOF(ObjectOutput out, long valueLength) throws IOException;
+
+    /**
+     * Returns the maximum length of the header.
+     *
+     * @return Max header length in bytes.
+     */
+    int getMaxHeaderLength();
 }