提交 36f3c9ef authored 作者: Thomas Mueller's avatar Thomas Mueller

Formatting, javadocs

上级 c4af37cd
...@@ -32,21 +32,24 @@ import org.h2.value.ValueLob; ...@@ -32,21 +32,24 @@ import org.h2.value.ValueLob;
import org.h2.value.ValueLobDb; import org.h2.value.ValueLobDb;
/** /**
* This class stores LOB objects in the database. * This class stores LOB objects in the database. This is the back-end i.e. the
* This is the back-end i.e. the server side of the LOB storage. * server side of the LOB storage.
* <p> * <p>
* Using the system session * Using the system session
* <p> * <p>
* Why do we use the system session to store the data? Some LOB operations can take a very long time. * Why do we use the system session to store the data? Some LOB operations can
* If we did them on a normal session, we would be locking the LOB tables for long periods of time, * take a very long time. If we did them on a normal session, we would be
* which is extremely detrimental to the rest of the system. * locking the LOB tables for long periods of time, which is extremely
* Perhaps when we shift to the MVStore engine, we can revisit this design decision. * detrimental to the rest of the system. Perhaps when we shift to the MVStore
* engine, we can revisit this design decision.
* <p> * <p>
* Locking Discussion * Locking Discussion
* <p> * <p>
* Normally, the locking order in H2 is: first lock the Session object, then lock the Database object. * Normally, the locking order in H2 is: first lock the Session object, then
* However, in the case of the LOB data, we are using the system session to store the data. * lock the Database object. However, in the case of the LOB data, we are using
* If we locked the normal way, we see deadlocks caused by the following pattern: * the system session to store the data. If we locked the normal way, we see
* deadlocks caused by the following pattern:
*
* <pre> * <pre>
* Thread 1: * Thread 1:
* locks normal session * locks normal session
...@@ -56,9 +59,11 @@ import org.h2.value.ValueLobDb; ...@@ -56,9 +59,11 @@ import org.h2.value.ValueLobDb;
* locks system session * locks system session
* waiting to lock database. * waiting to lock database.
* </pre> * </pre>
* So, in this class alone, we do two things: we have our very own dedicated session, the LOB session, *
* and we take the locks in this order: first the Database object, and then the LOB session. * So, in this class alone, we do two things: we have our very own dedicated
* Since we own the LOB session, no-one else can lock on it, and we are safe. * session, the LOB session, and we take the locks in this order: first the
* Database object, and then the LOB session. Since we own the LOB session,
* no-one else can lock on it, and we are safe.
*/ */
public class LobStorageBackend implements LobStorageInterface { public class LobStorageBackend implements LobStorageInterface {
...@@ -389,12 +394,14 @@ public class LobStorageBackend implements LobStorageInterface { ...@@ -389,12 +394,14 @@ public class LobStorageBackend implements LobStorageInterface {
small = new byte[0]; small = new byte[0];
} }
if (small != null) { if (small != null) {
// For a BLOB, precision is length in bytes. For a CLOB, precision is length in chars // For a BLOB, precision is length in bytes.
// For a CLOB, precision is length in chars
long precision = countingReaderForClob == null ? small.length : countingReaderForClob.getLength(); long precision = countingReaderForClob == null ? small.length : countingReaderForClob.getLength();
ValueLobDb v = ValueLobDb.createSmallLob(type, small, precision); ValueLobDb v = ValueLobDb.createSmallLob(type, small, precision);
return v; return v;
} }
// For a BLOB, precision is length in bytes. For a CLOB, precision is length in chars // For a BLOB, precision is length in bytes.
// For a CLOB, precision is length in chars
long precision = countingReaderForClob == null ? length : countingReaderForClob.getLength(); long precision = countingReaderForClob == null ? length : countingReaderForClob.getLength();
return registerLob(type, lobId, LobStorageFrontend.TABLE_TEMP, length, precision); return registerLob(type, lobId, LobStorageFrontend.TABLE_TEMP, length, precision);
} catch (IOException e) { } catch (IOException e) {
...@@ -585,19 +592,24 @@ public class LobStorageBackend implements LobStorageInterface { ...@@ -585,19 +592,24 @@ public class LobStorageBackend implements LobStorageInterface {
} }
} }
} }
private static void assertNotHolds(Object lock) { private static void assertNotHolds(Object lock) {
if (Thread.holdsLock(lock)) { if (Thread.holdsLock(lock)) {
throw DbException.throwInternalError(); throw DbException.throwInternalError();
} }
} }
/**
* Check whether this thread has synchronized on this object.
*
* @param lock the object
*/
static void assertHoldsLock(Object lock) { static void assertHoldsLock(Object lock) {
if (!Thread.holdsLock(lock)) { if (!Thread.holdsLock(lock)) {
throw DbException.throwInternalError(); throw DbException.throwInternalError();
} }
} }
/** /**
* An input stream that reads from a LOB. * An input stream that reads from a LOB.
*/ */
...@@ -636,7 +648,7 @@ public class LobStorageBackend implements LobStorageInterface { ...@@ -636,7 +648,7 @@ public class LobStorageBackend implements LobStorageInterface {
// before the lock on the database to prevent ABBA deadlocks // before the lock on the database to prevent ABBA deadlocks
assertHoldsLock(conn.getSession()); assertHoldsLock(conn.getSession());
assertHoldsLock(database); assertHoldsLock(database);
if (byteCount == -1) { if (byteCount == -1) {
String sql = "SELECT BYTE_COUNT FROM " + LOBS + " WHERE ID = ?"; String sql = "SELECT BYTE_COUNT FROM " + LOBS + " WHERE ID = ?";
PreparedStatement prep = prepare(sql); PreparedStatement prep = prepare(sql);
......
...@@ -104,7 +104,7 @@ public class FilePathCrypt extends FilePathWrapper { ...@@ -104,7 +104,7 @@ public class FilePathCrypt extends FilePathWrapper {
/** /**
* Convert a char array to a byte array, in UTF-16 format. The char array is * Convert a char array to a byte array, in UTF-16 format. The char array is
* not cleared after use (this must be done by the caller). * not cleared after use (this must be done by the caller).
* *
* @param passwordChars the password characters * @param passwordChars the password characters
* @return the byte array * @return the byte array
*/ */
......
...@@ -165,7 +165,7 @@ public abstract class Table extends SchemaObjectBase { ...@@ -165,7 +165,7 @@ public abstract class Table extends SchemaObjectBase {
*/ */
public abstract Index addIndex(Session session, String indexName, int indexId, IndexColumn[] cols, IndexType indexType, public abstract Index addIndex(Session session, String indexName, int indexId, IndexColumn[] cols, IndexType indexType,
boolean create, String indexComment); boolean create, String indexComment);
/** /**
* Get the given row. * Get the given row.
* *
......
...@@ -236,7 +236,7 @@ public class MultiDimension implements Comparator<long[]> { ...@@ -236,7 +236,7 @@ public class MultiDimension implements Comparator<long[]> {
/** /**
* Combine entries if the size of the list is too large. * Combine entries if the size of the list is too large.
* *
* @param list list of pairs(low, high) * @param list list of pairs(low, high)
* @param total product of the gap lengths * @param total product of the gap lengths
*/ */
private void combineEntries(ArrayList<long[]> list, int total) { private void combineEntries(ArrayList<long[]> list, int total) {
......
...@@ -44,12 +44,15 @@ import javax.tools.ToolProvider; ...@@ -44,12 +44,15 @@ import javax.tools.ToolProvider;
*/ */
public class SourceCompiler { public class SourceCompiler {
/**
* The "com.sun.tools.javac.Main" (if available).
*/
static final JavaCompiler JAVA_COMPILER; static final JavaCompiler JAVA_COMPILER;
private static final Class<?> JAVAC_SUN; private static final Class<?> JAVAC_SUN;
private static final String COMPILE_DIR = Utils.getProperty("java.io.tmpdir", "."); private static final String COMPILE_DIR = Utils.getProperty("java.io.tmpdir", ".");
/** /**
* The class name to source code map. * The class name to source code map.
*/ */
...@@ -59,7 +62,10 @@ public class SourceCompiler { ...@@ -59,7 +62,10 @@ public class SourceCompiler {
* The class name to byte code map. * The class name to byte code map.
*/ */
final HashMap<String, Class<?>> compiled = New.hashMap(); final HashMap<String, Class<?>> compiled = New.hashMap();
/**
* Whether to use the ToolProvider.getSystemJavaCompiler().
*/
boolean useJavaSystemCompiler = SysProperties.JAVA_SYSTEM_COMPILER; boolean useJavaSystemCompiler = SysProperties.JAVA_SYSTEM_COMPILER;
static { static {
...@@ -91,10 +97,10 @@ public class SourceCompiler { ...@@ -91,10 +97,10 @@ public class SourceCompiler {
sources.put(className, source); sources.put(className, source);
compiled.clear(); compiled.clear();
} }
/** /**
* Enable or disable the usage of the Java system compiler. * Enable or disable the usage of the Java system compiler.
* *
* @param enabled true to enable * @param enabled true to enable
*/ */
public void setJavaSystemCompiler(boolean enabled) { public void setJavaSystemCompiler(boolean enabled) {
...@@ -221,7 +227,16 @@ public class SourceCompiler { ...@@ -221,7 +227,16 @@ public class SourceCompiler {
classFile.delete(); classFile.delete();
} }
} }
/**
* Get the complete source code (including package name, imports, and so
* on).
*
* @param packageName the package name
* @param className the class name
* @param source the (possibly shortened) source code
* @return the full source code
*/
static String getCompleteSourceCode(String packageName, String className, String source) { static String getCompleteSourceCode(String packageName, String className, String source) {
if (source.startsWith("package ")) { if (source.startsWith("package ")) {
return source; return source;
...@@ -231,7 +246,7 @@ public class SourceCompiler { ...@@ -231,7 +246,7 @@ public class SourceCompiler {
buff.append("package ").append(packageName).append(";\n"); buff.append("package ").append(packageName).append(";\n");
} }
int endImport = source.indexOf("@CODE"); int endImport = source.indexOf("@CODE");
String importCode = String importCode =
"import java.util.*;\n" + "import java.util.*;\n" +
"import java.math.*;\n" + "import java.math.*;\n" +
"import java.sql.*;\n"; "import java.sql.*;\n";
...@@ -246,13 +261,21 @@ public class SourceCompiler { ...@@ -246,13 +261,21 @@ public class SourceCompiler {
"}\n"); "}\n");
return buff.toString(); return buff.toString();
} }
/**
* Compile using the standard java compiler.
*
* @param packageName the package name
* @param className the class name
* @param source the source code
* @return the class
*/
Class<?> javaxToolsJavac(String packageName, String className, String source) { Class<?> javaxToolsJavac(String packageName, String className, String source) {
String fullClassName = packageName + "." + className; String fullClassName = packageName + "." + className;
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
JavaFileManager fileManager = new JavaFileManager fileManager = new
ClassFileManager(JAVA_COMPILER ClassFileManager(JAVA_COMPILER
.getStandardFileManager(null, null, null)); .getStandardFileManager(null, null, null));
ArrayList<JavaFileObject> compilationUnits = new ArrayList<JavaFileObject>(); ArrayList<JavaFileObject> compilationUnits = new ArrayList<JavaFileObject>();
compilationUnits.add(new StringJavaFileObject(fullClassName, source)); compilationUnits.add(new StringJavaFileObject(fullClassName, source));
JAVA_COMPILER.getTask(writer, fileManager, null, null, JAVA_COMPILER.getTask(writer, fileManager, null, null,
...@@ -344,7 +367,7 @@ public class SourceCompiler { ...@@ -344,7 +367,7 @@ public class SourceCompiler {
* compile-time dependency unnecessarily. * compile-time dependency unnecessarily.
*/ */
private static final class GroovyCompiler { private static final class GroovyCompiler {
private static final Object LOADER; private static final Object LOADER;
private static final Throwable INIT_FAIL_EXCEPTION; private static final Throwable INIT_FAIL_EXCEPTION;
...@@ -358,12 +381,12 @@ public class SourceCompiler { ...@@ -358,12 +381,12 @@ public class SourceCompiler {
Object importCustomizer = Utils.newInstance( Object importCustomizer = Utils.newInstance(
"org.codehaus.groovy.control.customizers.ImportCustomizer"); "org.codehaus.groovy.control.customizers.ImportCustomizer");
// Call the method ImportCustomizer.addImports(String[]) // Call the method ImportCustomizer.addImports(String[])
String[] importsArray = new String[] { String[] importsArray = new String[] {
"java.sql.Connection", "java.sql.Connection",
"java.sql.Types", "java.sql.Types",
"java.sql.ResultSet", "java.sql.ResultSet",
"groovy.sql.Sql", "groovy.sql.Sql",
"org.h2.tools.SimpleResultSet" "org.h2.tools.SimpleResultSet"
}; };
Utils.callMethod(importCustomizer, "addImports", new Object[] { importsArray }); Utils.callMethod(importCustomizer, "addImports", new Object[] { importsArray });
...@@ -373,7 +396,7 @@ public class SourceCompiler { ...@@ -373,7 +396,7 @@ public class SourceCompiler {
Array.set(importCustomizerArray, 0, importCustomizer); Array.set(importCustomizerArray, 0, importCustomizer);
Object configuration = Utils.newInstance( Object configuration = Utils.newInstance(
"org.codehaus.groovy.control.CompilerConfiguration"); "org.codehaus.groovy.control.CompilerConfiguration");
Utils.callMethod(configuration, Utils.callMethod(configuration,
"addCompilationCustomizers", new Object[] { importCustomizerArray }); "addCompilationCustomizers", new Object[] { importCustomizerArray });
ClassLoader parent = GroovyCompiler.class.getClassLoader(); ClassLoader parent = GroovyCompiler.class.getClassLoader();
...@@ -391,7 +414,7 @@ public class SourceCompiler { ...@@ -391,7 +414,7 @@ public class SourceCompiler {
throw new RuntimeException("Compile fail: no Groovy jar in the classpath", INIT_FAIL_EXCEPTION); throw new RuntimeException("Compile fail: no Groovy jar in the classpath", INIT_FAIL_EXCEPTION);
} }
try { try {
Object codeSource = Utils.newInstance("groovy.lang.GroovyCodeSource", Object codeSource = Utils.newInstance("groovy.lang.GroovyCodeSource",
source, packageAndClassName + ".groovy", "UTF-8"); source, packageAndClassName + ".groovy", "UTF-8");
Utils.callMethod(codeSource, "setCachable", false); Utils.callMethod(codeSource, "setCachable", false);
Class<?> clazz = (Class<?>) Utils.callMethod(LOADER, "parseClass", codeSource); Class<?> clazz = (Class<?>) Utils.callMethod(LOADER, "parseClass", codeSource);
...@@ -401,7 +424,7 @@ public class SourceCompiler { ...@@ -401,7 +424,7 @@ public class SourceCompiler {
} }
} }
} }
/** /**
* An in-memory java source file object. * An in-memory java source file object.
*/ */
...@@ -419,15 +442,15 @@ public class SourceCompiler { ...@@ -419,15 +442,15 @@ public class SourceCompiler {
public CharSequence getCharContent(boolean ignoreEncodingErrors) { public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return sourceCode; return sourceCode;
} }
} }
/** /**
* An in-memory java class object. * An in-memory java class object.
*/ */
static class JavaClassObject extends SimpleJavaFileObject { static class JavaClassObject extends SimpleJavaFileObject {
protected final ByteArrayOutputStream out = new ByteArrayOutputStream(); private final ByteArrayOutputStream out = new ByteArrayOutputStream();
public JavaClassObject(String name, Kind kind) { public JavaClassObject(String name, Kind kind) {
super(URI.create("string:///" + name.replace('.', '/') super(URI.create("string:///" + name.replace('.', '/')
...@@ -443,12 +466,15 @@ public class SourceCompiler { ...@@ -443,12 +466,15 @@ public class SourceCompiler {
return out; return out;
} }
} }
/** /**
* An in-memory class file manager. * An in-memory class file manager.
*/ */
static class ClassFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> { static class ClassFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> {
/**
* The class (only one class is kept).
*/
JavaClassObject classObject; JavaClassObject classObject;
public ClassFileManager(StandardJavaFileManager standardManager) { public ClassFileManager(StandardJavaFileManager standardManager) {
......
...@@ -200,7 +200,7 @@ public class ValueLob extends Value { ...@@ -200,7 +200,7 @@ public class ValueLob extends Value {
long m = compress ? Constants.IO_BUFFER_SIZE_COMPRESS : Constants.IO_BUFFER_SIZE; long m = compress ? Constants.IO_BUFFER_SIZE_COMPRESS : Constants.IO_BUFFER_SIZE;
if (m < remaining && m <= inplace) { if (m < remaining && m <= inplace) {
// using "1L" to force long arithmetic // using "1L" to force long arithmetic
m = Math.min(remaining, inplace + 1L); m = Math.min(remaining, inplace + 1L);
// the buffer size must be bigger than the inplace lob, otherwise we can't // the buffer size must be bigger than the inplace lob, otherwise we can't
// know if it must be stored in-place or not // know if it must be stored in-place or not
m = MathUtils.roundUpLong(m, Constants.IO_BUFFER_SIZE); m = MathUtils.roundUpLong(m, Constants.IO_BUFFER_SIZE);
......
...@@ -41,13 +41,13 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo ...@@ -41,13 +41,13 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo
private final byte[] hmac; private final byte[] hmac;
private final byte[] small; private final byte[] small;
private final DataHandler handler; private final DataHandler handler;
/** /**
* For a BLOB, precision is length in bytes. * For a BLOB, precision is length in bytes.
* For a CLOB, precision is length in chars. * For a CLOB, precision is length in chars.
*/ */
private final long precision; private final long precision;
private final String fileName; private final String fileName;
private final FileStore tempFile; private final FileStore tempFile;
private int tableId; private int tableId;
...@@ -121,7 +121,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo ...@@ -121,7 +121,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo
} }
this.precision = tmpPrecision; this.precision = tmpPrecision;
} }
/** /**
* Create temporary BLOB from InputStream. * Create temporary BLOB from InputStream.
*/ */
...@@ -157,7 +157,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo ...@@ -157,7 +157,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo
} }
this.precision = tmpPrecision; this.precision = tmpPrecision;
} }
private static String createTempLobFileName(DataHandler handler) throws IOException { private static String createTempLobFileName(DataHandler handler) throws IOException {
String path = handler.getDatabasePath(); String path = handler.getDatabasePath();
if (path.length() == 0) { if (path.length() == 0) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论