Changeset: 4bb4e988164d for monetdb-java
URL: http://dev.monetdb.org/hg/monetdb-java?cmd=changeset;node=4bb4e988164d
Added Files:
src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTupleLineParserHelper.java
Modified Files:
src/main/java/nl/cwi/monetdb/jdbc/MonetClob.java
src/main/java/nl/cwi/monetdb/mcl/connection/helpers/BufferReallocator.java
src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiProtocol.java
src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiStartOfHeaderParser.java
src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTupleLineParser.java
Branch: embedded
Log Message:
Less memory usage while retrieving some native types on a JDBC MAPI connection.
diffs (truncated from 504 to 300 lines):
diff --git a/src/main/java/nl/cwi/monetdb/jdbc/MonetClob.java
b/src/main/java/nl/cwi/monetdb/jdbc/MonetClob.java
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetClob.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetClob.java
@@ -30,6 +30,10 @@ public class MonetClob implements Clob,
buffer = new StringBuilder(in);
}
+ public MonetClob(char[] toParse, int startPosition, int count) {
+ buffer = new StringBuilder(new String(toParse, startPosition,
count));
+ }
+
//== begin interface Clob
/**
diff --git
a/src/main/java/nl/cwi/monetdb/mcl/connection/helpers/BufferReallocator.java
b/src/main/java/nl/cwi/monetdb/mcl/connection/helpers/BufferReallocator.java
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/helpers/BufferReallocator.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/connection/helpers/BufferReallocator.java
@@ -33,9 +33,16 @@ public final class BufferReallocator {
public static CharBuffer ReallocateBuffer(CharBuffer oldBuffer) {
int newCapacity = GetNewCapacity(oldBuffer);
- CharBuffer newBuffer = CharBuffer.allocate(newCapacity);
+ CharBuffer newBuffer = CharBuffer.wrap(new char[newCapacity]);
oldBuffer.flip();
newBuffer.put(oldBuffer.array());
return newBuffer;
}
+
+ public static CharBuffer EnsureCapacity(CharBuffer oldBuffer, int
newCapacity) {
+ if(newCapacity > oldBuffer.capacity()) {
+ oldBuffer = CharBuffer.wrap(new char[newCapacity]);
+ }
+ return oldBuffer;
+ }
}
diff --git
a/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiProtocol.java
b/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiProtocol.java
--- a/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiProtocol.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiProtocol.java
@@ -32,12 +32,12 @@ public class OldMapiProtocol extends Abs
CharBuffer lineBuffer;
- private final StringBuilder tupleLineBuilder;
+ CharBuffer tupleLineBuffer;
public OldMapiProtocol(OldMapiSocket socket) {
this.socket = socket;
this.lineBuffer = CharBuffer.wrap(new char[OldMapiSocket.BLOCK]);
- this.tupleLineBuilder = new StringBuilder(OldMapiSocket.BLOCK);
+ this.tupleLineBuffer = CharBuffer.wrap(new char[1024]);
}
public OldMapiSocket getSocket() {
@@ -132,8 +132,7 @@ public class OldMapiProtocol extends Abs
@Override
public int parseTupleLines(int firstLineNumber, int[] typesMap, Object[]
data, boolean[][] nulls)
throws ProtocolException {
- OldMapiTupleLineParser.OldMapiParseTupleLine(firstLineNumber,
this.lineBuffer,
- this.tupleLineBuilder, typesMap, data, nulls);
+ OldMapiTupleLineParser.OldMapiParseTupleLine(this, firstLineNumber,
typesMap, data, nulls);
return firstLineNumber;
}
diff --git
a/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiStartOfHeaderParser.java
b/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiStartOfHeaderParser.java
---
a/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiStartOfHeaderParser.java
+++
b/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiStartOfHeaderParser.java
@@ -55,13 +55,14 @@ final class OldMapiStartOfHeaderParser {
if (currentPointer >= limit) {
throw new ProtocolException("unexpected end of string",
currentPointer - 1);
}
- int tmp = 0, negative = 1;;
+ int tmp = 0;
+ boolean positive = true;
char chr = array[currentPointer++];
// note: don't use Character.isDigit() here, because we only want
ISO-LATIN-1 digits
if (chr >= '0' && chr <= '9') {
tmp = (int)chr - (int)'0';
} else if(chr == '-') {
- negative = -1;
+ positive = false;
} else {
throw new ProtocolException("expected a digit", currentPointer -
1);
}
@@ -78,9 +79,8 @@ final class OldMapiStartOfHeaderParser {
throw new ProtocolException("expected a digit", currentPointer
- 1);
}
}
- tmp *= negative;
protocol.lineBuffer.position(currentPointer);
- return tmp;
+ return positive ? tmp : -tmp;
}
static String GetNextResponseDataAsString(OldMapiProtocol protocol) throws
ProtocolException {
diff --git
a/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTupleLineParser.java
b/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTupleLineParser.java
---
a/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTupleLineParser.java
+++
b/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTupleLineParser.java
@@ -10,6 +10,7 @@ package nl.cwi.monetdb.mcl.protocol.oldm
import nl.cwi.monetdb.jdbc.MonetBlob;
import nl.cwi.monetdb.jdbc.MonetClob;
+import nl.cwi.monetdb.mcl.connection.helpers.BufferReallocator;
import nl.cwi.monetdb.mcl.connection.helpers.GregorianCalendarParser;
import nl.cwi.monetdb.mcl.protocol.ProtocolException;
@@ -22,39 +23,13 @@ import java.util.Calendar;
final class OldMapiTupleLineParser {
- private static final char[] NULL_STRING = "NULL".toCharArray();
+ private static final char[] NULL_STRING = new char[]{'N','U','L','L'};
- private static int CharIndexOf(char[] source, int sourceCount, char[]
target, int targetCount) {
- if (targetCount == 0) {
- return 0;
- }
+ static int OldMapiParseTupleLine(OldMapiProtocol protocol, int lineNumber,
int[] typesMap, Object[] values,
+ boolean[][] nulls) throws
ProtocolException {
+ CharBuffer lineBuffer = protocol.lineBuffer;
+ CharBuffer tupleLineBuffer = protocol.tupleLineBuffer;
- char first = target[0];
- int max = sourceCount - targetCount;
-
- for (int i = 0; i <= max; i++) {
- /* Look for first character. */
- if (source[i] != first) {
- while (++i <= max && source[i] != first);
- }
-
- /* Found first character, now look at the rest of v2 */
- if (i <= max) {
- int j = i + 1;
- int end = j + targetCount - 1;
- for (int k = 1; j < end && source[j] == target[k]; j++, k++);
-
- if (j == end) {
- /* Found whole string. */
- return i;
- }
- }
- }
- return -1;
- }
-
- static int OldMapiParseTupleLine(int lineNumber, CharBuffer lineBuffer,
StringBuilder helper, int[] typesMap,
- Object[] values, boolean[][] nulls)
throws ProtocolException {
int len = lineBuffer.limit();
char[] array = lineBuffer.array();
@@ -64,7 +39,7 @@ final class OldMapiTupleLineParser {
throw new ProtocolException(typesMap.length + " columns
expected, but only single value found");
}
// return the whole string but the leading =
- OldMapiStringToJavaObjectConverter(new String(array, 1, len - 1),
lineNumber, values[0], typesMap[0]);
+ OldMapiStringToJavaDataConversion(array, 1, len - 1, lineNumber,
values[0], typesMap[0]);
return 1;
}
@@ -102,26 +77,26 @@ final class OldMapiTupleLineParser {
if (!inString && (i > 0 && array[i - 1] == ',') || (i + 1
== len - 1 && array[++i] == ']')) { // dirty
// split!
if (array[cursor] == '"' && array[i - 2] == '"') {
- // reuse the StringBuilder by cleaning it
- helper.setLength(0);
- // prevent capacity increases
- helper.ensureCapacity((i - 2) - (cursor + 1));
+ // reuse the CharBuffer by cleaning it and ensure
the capacity
+ tupleLineBuffer.clear();
+ tupleLineBuffer =
BufferReallocator.EnsureCapacity(tupleLineBuffer, (i - 2) - (cursor + 1));
+
for (int pos = cursor + 1; pos < i - 2; pos++) {
if (array[cursor] == '\\' && pos + 1 < i - 2) {
pos++;
// strToStr and strFromStr in gdk_atoms.mx
only support \t \n \\ \" and \377
switch (array[pos]) {
case '\\':
- helper.append('\\');
+ tupleLineBuffer.put('\\');
break;
case 'n':
- helper.append('\n');
+ tupleLineBuffer.put('\n');
break;
case 't':
- helper.append('\t');
+ tupleLineBuffer.put('\t');
break;
case '"':
- helper.append('"');
+ tupleLineBuffer.put('"');
break;
case '0': case '1': case '2': case '3':
// this could be an octal number,
let's check it out
@@ -129,7 +104,7 @@ final class OldMapiTupleLineParser {
array[pos + 2] >= '0' &&
array[pos + 2] <= '7') {
// we got the number!
try {
-
helper.append((char)(Integer.parseInt("" + array[pos] + array[pos + 1] +
array[pos + 2], 8)));
+
tupleLineBuffer.put((char)(Integer.parseInt("" + array[pos] + array[pos + 1] +
array[pos + 2], 8)));
pos += 2;
} catch (NumberFormatException
e) {
// hmmm, this point should
never be reached actually...
@@ -137,26 +112,27 @@ final class OldMapiTupleLineParser {
}
} else {
// do default action if number
seems not to be correct
- helper.append(array[pos]);
+
tupleLineBuffer.put(array[pos]);
}
break;
default:
// this is wrong, just ignore the
escape, and print the char
- helper.append(array[pos]);
+ tupleLineBuffer.put(array[pos]);
break;
}
} else {
- helper.append(array[pos]);
+ tupleLineBuffer.put(array[pos]);
}
}
// put the unescaped string in the right place
-
OldMapiStringToJavaObjectConverter(helper.toString(), lineNumber,
values[column], typesMap[column]);
+ tupleLineBuffer.flip();
+
OldMapiStringToJavaDataConversion(tupleLineBuffer.array(), 0,
tupleLineBuffer.limit(), lineNumber, values[column], typesMap[column]);
nulls[column][lineNumber] = false;
- } else if ((i - 1) - cursor == 4 && CharIndexOf(array,
array.length, NULL_STRING, NULL_STRING.length) == cursor) {
+ } else if ((i - 1) - cursor == 4 &&
OldMapiTupleLineParserHelper.CharIndexOf(array, array.length, NULL_STRING, 4)
== cursor) {
SetNullValue(lineNumber, values[column],
typesMap[column]);
nulls[column][lineNumber] = true;
} else {
- OldMapiStringToJavaObjectConverter(new
String(array, cursor, i - 1 - cursor), lineNumber, values[column],
typesMap[column]);
+ OldMapiStringToJavaDataConversion(array, cursor, i
- 1 - cursor, lineNumber, values[column], typesMap[column]);
nulls[column][lineNumber] = false;
}
column++;
@@ -167,82 +143,84 @@ final class OldMapiTupleLineParser {
break;
}
}
+
+ protocol.tupleLineBuffer = tupleLineBuffer;
// check if this result is of the size we expected it to be
if (column != typesMap.length)
throw new ProtocolException("illegal result length: " + column +
"\nlast read: " + (column > 0 ? values[column - 1] : "<none>"));
return column;
}
- private static byte[] BinaryBlobConverter(String toParse) {
- int len = toParse.length() / 2;
+ private static byte[] BinaryBlobConverter(char[] toParse, int
startPosition, int count) {
+ int len = (startPosition + count) / 2;
byte[] res = new byte[len];
for (int i = 0; i < len; i++) {
- res[i] = (byte) Integer.parseInt(toParse.substring(2 * i, (2 * i)
+ 2), 16);
+ res[i] = (byte) Integer.parseInt(new String(toParse, 2 * i, (2 *
i) + 2), 16);
}
return res;
}
private static final ParsePosition Ppos = new ParsePosition(0);
- private static void OldMapiStringToJavaObjectConverter(String toParse, int
lineNumber, Object columnArray,
- int jDBCMapping)
throws ProtocolException {
+ private static void OldMapiStringToJavaDataConversion(char[] toParse, int
startPosition, int count, int lineNumber,
+ Object columnArray,
int jDBCMapping) throws ProtocolException {
switch (jDBCMapping) {
case Types.BOOLEAN:
- ((boolean[]) columnArray)[lineNumber] =
Boolean.parseBoolean(toParse);
+ ((boolean[]) columnArray)[lineNumber] =
OldMapiTupleLineParserHelper.CharArrayToBoolean(toParse, startPosition, count);
break;
case Types.TINYINT:
- ((byte[]) columnArray)[lineNumber] = Byte.parseByte(toParse);
+ ((byte[]) columnArray)[lineNumber] =
OldMapiTupleLineParserHelper.CharArrayToByte(toParse, startPosition, count);
break;
case Types.SMALLINT:
- ((short[]) columnArray)[lineNumber] =
Short.parseShort(toParse);
+ ((short[]) columnArray)[lineNumber] =
OldMapiTupleLineParserHelper.CharArrayToShort(toParse, startPosition, count);
break;
case Types.INTEGER:
- ((int[]) columnArray)[lineNumber] =
Integer.parseInt(toParse.replace(".", "")); //intervals :(
+ ((int[]) columnArray)[lineNumber] =
OldMapiTupleLineParserHelper.CharArrayToInt(toParse, startPosition, count);
break;
case Types.BIGINT:
- ((long[]) columnArray)[lineNumber] =
Long.parseLong(toParse.replace(".", "")); //intervals :(
+ ((long[]) columnArray)[lineNumber] =
OldMapiTupleLineParserHelper.CharArrayToLong(toParse, startPosition, count);
break;
case Types.REAL:
- ((float[]) columnArray)[lineNumber] =
Float.parseFloat(toParse);
+ ((float[]) columnArray)[lineNumber] = Float.parseFloat(new
String(toParse, startPosition, count));
break;
case Types.DOUBLE:
- ((double[]) columnArray)[lineNumber] =
Double.parseDouble(toParse);
+ ((double[]) columnArray)[lineNumber] = Double.parseDouble(new
String(toParse, startPosition, count));
break;
case Types.DECIMAL:
- ((BigDecimal[]) columnArray)[lineNumber] = new
BigDecimal(toParse);
+ ((BigDecimal[]) columnArray)[lineNumber] = new
BigDecimal(toParse, startPosition, count);
break;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list