提交 8bd62fd7 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 f5c69801
...@@ -215,4 +215,8 @@ public abstract class ScriptBase extends Prepared implements DataHandler { ...@@ -215,4 +215,8 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
return this; return this;
} }
public boolean getLobFilesInDirectories() {
return session.getDatabase().getLobFilesInDirectories();
}
} }
...@@ -162,7 +162,9 @@ public class SysProperties { ...@@ -162,7 +162,9 @@ public class SysProperties {
*/ */
// TODO change in version 1.1 // TODO change in version 1.1
// TODO: also remove DataHandler.allocateObjectId, createTempFile when setting this to true and removing it // TODO: also remove DataHandler.allocateObjectId, createTempFile when setting this to true and removing it
public static final boolean LOB_FILES_IN_DIRECTORIES = getBooleanSetting("h2.lobFilesInDirectories", false); public static final boolean LOB_FILES_IN_DIRECTORIES = getBooleanSetting("h2.lobFilesInDirectories", true);
private int test;
// public static final boolean LOB_FILES_IN_DIRECTORIES = getBooleanSetting("h2.lobFilesInDirectories", false);
/** /**
* System property <code>h2.lobFilesPerDirectory</code> (default: 256).<br /> * System property <code>h2.lobFilesPerDirectory</code> (default: 256).<br />
......
...@@ -149,6 +149,7 @@ public class Database implements DataHandler { ...@@ -149,6 +149,7 @@ public class Database implements DataHandler {
// TODO change in version 1.1 // TODO change in version 1.1
private boolean multiThreaded; private boolean multiThreaded;
private int maxOperationMemory = SysProperties.DEFAULT_MAX_OPERATION_MEMORY; private int maxOperationMemory = SysProperties.DEFAULT_MAX_OPERATION_MEMORY;
private boolean lobFilesInDirectories = SysProperties.LOB_FILES_IN_DIRECTORIES;
public Database(String name, ConnectionInfo ci, String cipher) throws SQLException { public Database(String name, ConnectionInfo ci, String cipher) throws SQLException {
this.compareMode = new CompareMode(null, null, 0); this.compareMode = new CompareMode(null, null, 0);
...@@ -431,6 +432,7 @@ public class Database implements DataHandler { ...@@ -431,6 +432,7 @@ public class Database implements DataHandler {
// if it is already read-only because ACCESS_MODE_DATA=r // if it is already read-only because ACCESS_MODE_DATA=r
readOnly = readOnly | FileUtils.isReadOnly(dataFileName); readOnly = readOnly | FileUtils.isReadOnly(dataFileName);
textStorage = isTextStorage(dataFileName, textStorage); textStorage = isTextStorage(dataFileName, textStorage);
lobFilesInDirectories |= FileUtils.exists(databaseName + Constants.SUFFIX_LOBS_DIRECTORY);
} }
} }
dummy = DataPage.create(this, 0); dummy = DataPage.create(this, 0);
...@@ -1709,4 +1711,8 @@ public class Database implements DataHandler { ...@@ -1709,4 +1711,8 @@ public class Database implements DataHandler {
this.exclusiveSession = session; this.exclusiveSession = session;
} }
public boolean getLobFilesInDirectories() {
return lobFilesInDirectories;
}
} }
...@@ -392,4 +392,8 @@ public class SessionRemote implements SessionInterface, DataHandler { ...@@ -392,4 +392,8 @@ public class SessionRemote implements SessionInterface, DataHandler {
// TODO open another remote connection and cancel this session using a unique id (like PostgreSQL) // TODO open another remote connection and cancel this session using a unique id (like PostgreSQL)
} }
public boolean getLobFilesInDirectories() {
return false;
}
} }
...@@ -162,6 +162,7 @@ public class FullText implements Trigger { ...@@ -162,6 +162,7 @@ public class FullText implements Trigger {
/** /**
* Drops all full text indexes from the database. * Drops all full text indexes from the database.
*
* @param conn the connection * @param conn the connection
*/ */
public static void dropAll(Connection conn) throws SQLException { public static void dropAll(Connection conn) throws SQLException {
...@@ -564,6 +565,7 @@ public class FullText implements Trigger { ...@@ -564,6 +565,7 @@ public class FullText implements Trigger {
addWords(setting, words, text); addWords(setting, words, text);
HashSet rIds = null, lastRowIds = null; HashSet rIds = null, lastRowIds = null;
HashMap allWords = setting.getWordList(); HashMap allWords = setting.getWordList();
PreparedStatement prepSelectMapByWordId = setting.getPrepSelectMapByWordId(); PreparedStatement prepSelectMapByWordId = setting.getPrepSelectMapByWordId();
for (Iterator it = words.iterator(); it.hasNext();) { for (Iterator it = words.iterator(); it.hasNext();) {
lastRowIds = rIds; lastRowIds = rIds;
......
...@@ -126,4 +126,11 @@ public interface DataHandler { ...@@ -126,4 +126,11 @@ public interface DataHandler {
*/ */
Object getLobSyncObject(); Object getLobSyncObject();
/**
* Checks if the lob files stored in directories.
*
* @return true if lob files are stored in directories.
*/
boolean getLobFilesInDirectories();
} }
...@@ -232,6 +232,7 @@ public class FileSystemZip extends FileSystem { ...@@ -232,6 +232,7 @@ public class FileSystemZip extends FileSystem {
} else { } else {
fileName = fileName.substring(idx + 1); fileName = fileName.substring(idx + 1);
} }
fileName = fileName.replace('\\', '/');
if (fileName.startsWith("/")) { if (fileName.startsWith("/")) {
fileName = fileName.substring(1); fileName = fileName.substring(1);
} }
......
...@@ -713,6 +713,8 @@ public class MetaTable extends Table { ...@@ -713,6 +713,8 @@ public class MetaTable extends Table {
add(rows, new String[] { "MULTI_THREADED", database.getMultiThreaded() ? "1" : "0"}); add(rows, new String[] { "MULTI_THREADED", database.getMultiThreaded() ? "1" : "0"});
add(rows, new String[] { "MVCC", database.isMultiVersion() ? "TRUE" : "FALSE" }); add(rows, new String[] { "MVCC", database.isMultiVersion() ? "TRUE" : "FALSE" });
add(rows, new String[] { "QUERY_TIMEOUT", "" + session.getQueryTimeout() }); add(rows, new String[] { "QUERY_TIMEOUT", "" + session.getQueryTimeout() });
int todoNotASettingYet;
add(rows, new String[] { "LOB_FILES_IN_DIRECTORIES", "" + database.getLobFilesInDirectories() });
add(rows, new String[]{"h2.allowBigDecimalExtensions", "" + SysProperties.ALLOW_BIG_DECIMAL_EXTENSIONS}); add(rows, new String[]{"h2.allowBigDecimalExtensions", "" + SysProperties.ALLOW_BIG_DECIMAL_EXTENSIONS});
add(rows, new String[]{"h2.baseDir", "" + SysProperties.getBaseDir()}); add(rows, new String[]{"h2.baseDir", "" + SysProperties.getBaseDir()});
add(rows, new String[]{"h2.check", "" + SysProperties.CHECK}); add(rows, new String[]{"h2.check", "" + SysProperties.CHECK});
......
...@@ -25,6 +25,7 @@ import java.util.Map; ...@@ -25,6 +25,7 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.h2.command.Parser; import org.h2.command.Parser;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.engine.DbObject; import org.h2.engine.DbObject;
...@@ -66,6 +67,7 @@ public class Recover implements DataHandler { ...@@ -66,6 +67,7 @@ public class Recover implements DataHandler {
private int recordLength; private int recordLength;
private int valueId; private int valueId;
private boolean log; private boolean log;
private boolean lobFilesInDirectories;
private void showUsage() { private void showUsage() {
System.out.println("java "+getClass().getName()+" [-dir <dir>] [-db <database>] [-log true]"); System.out.println("java "+getClass().getName()+" [-dir <dir>] [-db <database>] [-log true]");
...@@ -154,7 +156,7 @@ public class Recover implements DataHandler { ...@@ -154,7 +156,7 @@ public class Recover implements DataHandler {
} }
private void removePassword(String fileName) throws SQLException { private void removePassword(String fileName) throws SQLException {
databaseName = fileName.substring(fileName.length() - Constants.SUFFIX_DATA_FILE.length()); setDatabaseName(fileName.substring(fileName.length() - Constants.SUFFIX_DATA_FILE.length()));
textStorage = Database.isTextStorage(fileName, false); textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage); byte[] magic = Database.getMagic(textStorage);
FileStore store = FileStore.open(null, fileName, "rw", magic); FileStore store = FileStore.open(null, fileName, "rw", magic);
...@@ -282,8 +284,6 @@ public class Recover implements DataHandler { ...@@ -282,8 +284,6 @@ public class Recover implements DataHandler {
ArrayList list = FileLister.getDatabaseFiles(dir, db, true); ArrayList list = FileLister.getDatabaseFiles(dir, db, true);
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
String fileName = (String) list.get(i); String fileName = (String) list.get(i);
// TODO recover: should create a working SQL script if possible (2
// passes)
if (fileName.endsWith(Constants.SUFFIX_DATA_FILE)) { if (fileName.endsWith(Constants.SUFFIX_DATA_FILE)) {
dumpData(fileName); dumpData(fileName);
} else if (fileName.endsWith(Constants.SUFFIX_INDEX_FILE)) { } else if (fileName.endsWith(Constants.SUFFIX_INDEX_FILE)) {
...@@ -433,11 +433,16 @@ public class Recover implements DataHandler { ...@@ -433,11 +433,16 @@ public class Recover implements DataHandler {
return v.getSQL(); return v.getSQL();
} }
private void setDatabaseName(String name) {
databaseName = name;
lobFilesInDirectories = FileUtils.exists(databaseName + Constants.SUFFIX_LOBS_DIRECTORY);
}
private void dumpLog(String fileName) throws SQLException { private void dumpLog(String fileName) throws SQLException {
PrintWriter writer = null; PrintWriter writer = null;
FileStore store = null; FileStore store = null;
try { try {
databaseName = fileName.substring(fileName.length() - Constants.SUFFIX_LOG_FILE.length()); setDatabaseName(fileName.substring(fileName.length() - Constants.SUFFIX_LOG_FILE.length()));
writer = getWriter(fileName, ".txt"); writer = getWriter(fileName, ".txt");
textStorage = Database.isTextStorage(fileName, false); textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage); byte[] magic = Database.getMagic(textStorage);
...@@ -593,7 +598,7 @@ public class Recover implements DataHandler { ...@@ -593,7 +598,7 @@ public class Recover implements DataHandler {
PrintWriter writer = null; PrintWriter writer = null;
FileStore store = null; FileStore store = null;
try { try {
databaseName = fileName.substring(fileName.length() - Constants.SUFFIX_INDEX_FILE.length()); setDatabaseName(fileName.substring(fileName.length() - Constants.SUFFIX_INDEX_FILE.length()));
writer = getWriter(fileName, ".txt"); writer = getWriter(fileName, ".txt");
textStorage = Database.isTextStorage(fileName, false); textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage); byte[] magic = Database.getMagic(textStorage);
...@@ -669,7 +674,7 @@ public class Recover implements DataHandler { ...@@ -669,7 +674,7 @@ public class Recover implements DataHandler {
PrintWriter writer = null; PrintWriter writer = null;
FileStore store = null; FileStore store = null;
try { try {
databaseName = fileName.substring(0, fileName.length() - Constants.SUFFIX_DATA_FILE.length()); setDatabaseName(fileName.substring(0, fileName.length() - Constants.SUFFIX_DATA_FILE.length()));
writer = getWriter(fileName, ".sql"); writer = getWriter(fileName, ".sql");
writer.println("CREATE ALIAS IF NOT EXISTS READ_CLOB FOR \"" + this.getClass().getName() + ".readClob\";"); writer.println("CREATE ALIAS IF NOT EXISTS READ_CLOB FOR \"" + this.getClass().getName() + ".readClob\";");
writer.println("CREATE ALIAS IF NOT EXISTS READ_BLOB FOR \"" + this.getClass().getName() + ".readBlob\";"); writer.println("CREATE ALIAS IF NOT EXISTS READ_BLOB FOR \"" + this.getClass().getName() + ".readBlob\";");
...@@ -948,4 +953,11 @@ public class Recover implements DataHandler { ...@@ -948,4 +953,11 @@ public class Recover implements DataHandler {
return this; return this;
} }
/**
* INTERNAL
*/
public boolean getLobFilesInDirectories() {
return lobFilesInDirectories;
}
} }
...@@ -116,13 +116,17 @@ public abstract class Value { ...@@ -116,13 +116,17 @@ public abstract class Value {
*/ */
protected abstract int compareSecure(Value v, CompareMode mode) throws SQLException; protected abstract int compareSecure(Value v, CompareMode mode) throws SQLException;
public abstract int hashCode();
/** /**
* Check if the two values are equal. * Check if the two values are equal.
* No data conversion is made; this method returns false
* if the other object is not of the same class.
* *
* @param v the other value * @param other the other value
* @return true if they are equal * @return true if they are equal
*/ */
protected abstract boolean isEqual(Value v); public abstract boolean equals(Object other);
public static int getOrder(int type) { public static int getOrder(int type) {
switch(type) { switch(type) {
...@@ -200,7 +204,7 @@ public abstract class Value { ...@@ -200,7 +204,7 @@ public abstract class Value {
int index = hash & (SysProperties.OBJECT_CACHE_SIZE - 1); int index = hash & (SysProperties.OBJECT_CACHE_SIZE - 1);
Value cached = cache[index]; Value cached = cache[index];
if (cached != null) { if (cached != null) {
if (cached.getType() == v.getType() && v.isEqual(cached)) { if (cached.getType() == v.getType() && v.equals(cached)) {
// cacheHit++; // cacheHit++;
return cached; return cached;
} }
...@@ -625,10 +629,10 @@ public abstract class Value { ...@@ -625,10 +629,10 @@ public abstract class Value {
return false; return false;
} }
if (getType() == v.getType()) { if (getType() == v.getType()) {
return isEqual(v); return equals(v);
} }
int t2 = Value.getHigherOrder(getType(), v.getType()); int t2 = Value.getHigherOrder(getType(), v.getType());
return convertTo(t2).isEqual(v.convertTo(t2)); return convertTo(t2).equals(v.convertTo(t2));
} }
public final int compareTo(Value v, CompareMode mode) throws SQLException { public final int compareTo(Value v, CompareMode mode) throws SQLException {
......
...@@ -114,11 +114,11 @@ public class ValueArray extends Value { ...@@ -114,11 +114,11 @@ public class ValueArray extends Value {
return MathUtils.convertLongToInt(size); return MathUtils.convertLongToInt(size);
} }
protected boolean isEqual(Value o) { public boolean equals(Object other) {
if (!(o instanceof ValueArray)) { if (!(other instanceof ValueArray)) {
return false; return false;
} }
ValueArray v = (ValueArray) o; ValueArray v = (ValueArray) other;
if (values == v.values) { if (values == v.values) {
return true; return true;
} }
...@@ -126,7 +126,7 @@ public class ValueArray extends Value { ...@@ -126,7 +126,7 @@ public class ValueArray extends Value {
return false; return false;
} }
for (int i = 0; i < values.length; i++) { for (int i = 0; i < values.length; i++) {
if (!values[i].isEqual(v.values[i])) { if (!values[i].equals(v.values[i])) {
return false; return false;
} }
} }
......
...@@ -73,8 +73,9 @@ public class ValueBoolean extends Value { ...@@ -73,8 +73,9 @@ public class ValueBoolean extends Value {
return DISPLAY_SIZE; return DISPLAY_SIZE;
} }
protected boolean isEqual(Value v) { public boolean equals(Object other) {
return v instanceof ValueBoolean && value.booleanValue() == ((ValueBoolean) v).value.booleanValue(); // there are only ever two instances, so the instance must match
return this == other;
} }
} }
...@@ -124,8 +124,8 @@ public class ValueByte extends Value { ...@@ -124,8 +124,8 @@ public class ValueByte extends Value {
return DISPLAY_SIZE; return DISPLAY_SIZE;
} }
protected boolean isEqual(Value v) { public boolean equals(Object other) {
return v instanceof ValueByte && value == ((ValueByte) v).value; return other instanceof ValueByte && value == ((ValueByte) other).value;
} }
} }
...@@ -66,12 +66,12 @@ abstract class ValueBytesBase extends Value { ...@@ -66,12 +66,12 @@ abstract class ValueBytesBase extends Value {
return MathUtils.convertLongToInt(value.length * 2L); return MathUtils.convertLongToInt(value.length * 2L);
} }
protected boolean isEqual(Value v) {
return v instanceof ValueBytesBase && ByteUtils.compareNotNull(value, ((ValueBytesBase) v).value) == 0;
}
public int getMemory() { public int getMemory() {
return value.length + 4; return value.length + 4;
} }
public boolean equals(Object other) {
return other instanceof ValueBytesBase && ByteUtils.compareNotNull(value, ((ValueBytesBase) other).value) == 0;
}
} }
...@@ -85,8 +85,8 @@ public class ValueDate extends Value { ...@@ -85,8 +85,8 @@ public class ValueDate extends Value {
return DISPLAY_SIZE; return DISPLAY_SIZE;
} }
protected boolean isEqual(Value v) { public boolean equals(Object other) {
return v instanceof ValueDate && value.equals(((ValueDate) v).value); return other instanceof ValueDate && value.equals(((ValueDate) other).value);
} }
} }
...@@ -181,8 +181,8 @@ public class ValueDecimal extends Value { ...@@ -181,8 +181,8 @@ public class ValueDecimal extends Value {
return MathUtils.convertLongToInt(getPrecision() + 2); // - . return MathUtils.convertLongToInt(getPrecision() + 2); // - .
} }
protected boolean isEqual(Value v) { public boolean equals(Object other) {
return v instanceof ValueDecimal && value.equals(((ValueDecimal) v).value); return other instanceof ValueDecimal && value.equals(((ValueDecimal) other).value);
} }
public int getMemory() { public int getMemory() {
......
...@@ -118,8 +118,8 @@ public class ValueDouble extends Value { ...@@ -118,8 +118,8 @@ public class ValueDouble extends Value {
return DISPLAY_SIZE; return DISPLAY_SIZE;
} }
protected boolean isEqual(Value v) { public boolean equals(Object other) {
return v instanceof ValueDouble && value == ((ValueDouble) v).value; return other instanceof ValueDouble && value == ((ValueDouble) other).value;
} }
} }
...@@ -118,8 +118,8 @@ public class ValueFloat extends Value { ...@@ -118,8 +118,8 @@ public class ValueFloat extends Value {
return DISPLAY_SIZE; return DISPLAY_SIZE;
} }
protected boolean isEqual(Value v) { public boolean equals(Object other) {
return v instanceof ValueFloat && value == ((ValueFloat) v).value; return other instanceof ValueFloat && value == ((ValueFloat) other).value;
} }
} }
...@@ -145,8 +145,8 @@ public class ValueInt extends Value { ...@@ -145,8 +145,8 @@ public class ValueInt extends Value {
return DISPLAY_SIZE; return DISPLAY_SIZE;
} }
protected boolean isEqual(Value v) { public boolean equals(Object other) {
return v instanceof ValueInt && value == ((ValueInt) v).value; return other instanceof ValueInt && value == ((ValueInt) other).value;
} }
} }
...@@ -26,6 +26,7 @@ import org.h2.util.FileUtils; ...@@ -26,6 +26,7 @@ import org.h2.util.FileUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.RandomUtils; import org.h2.util.RandomUtils;
import org.h2.util.SmallLRUCache;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
/** /**
...@@ -88,7 +89,7 @@ public class ValueLob extends Value { ...@@ -88,7 +89,7 @@ public class ValueLob extends Value {
if (SysProperties.CHECK && tableId == 0 && objectId == 0) { if (SysProperties.CHECK && tableId == 0 && objectId == 0) {
throw Message.getInternalError("0 LOB"); throw Message.getInternalError("0 LOB");
} }
if (SysProperties.LOB_FILES_IN_DIRECTORIES) { if (handler.getLobFilesInDirectories()) {
String table = tableId < 0 ? ".temp" : ".t" + tableId; String table = tableId < 0 ? ".temp" : ".t" + tableId;
return getFileNamePrefix(handler.getDatabasePath(), objectId) + table + Constants.SUFFIX_LOB_FILE; return getFileNamePrefix(handler.getDatabasePath(), objectId) + table + Constants.SUFFIX_LOB_FILE;
} else { } else {
...@@ -197,7 +198,11 @@ public class ValueLob extends Value { ...@@ -197,7 +198,11 @@ public class ValueLob extends Value {
int objectId = 0; int objectId = 0;
while (true) { while (true) {
String dir = getFileNamePrefix(path, objectId); String dir = getFileNamePrefix(path, objectId);
String[] list = FileUtils.listFiles(dir);
int test;
String[] list = getFileList(handler, dir);
// String[] list = FileUtils.listFiles(dir);
int fileCount = 0; int fileCount = 0;
boolean[] used = new boolean[SysProperties.LOB_FILES_PER_DIRECTORY]; boolean[] used = new boolean[SysProperties.LOB_FILES_PER_DIRECTORY];
for (int i = 0; i < list.length; i++) { for (int i = 0; i < list.length; i++) {
...@@ -228,6 +233,7 @@ public class ValueLob extends Value { ...@@ -228,6 +233,7 @@ public class ValueLob extends Value {
} }
if (fileId > 0) { if (fileId > 0) {
objectId += fileId; objectId += fileId;
invalidateFileList(handler, dir);
break; break;
} else { } else {
if (objectId > Integer.MAX_VALUE / SysProperties.LOB_FILES_PER_DIRECTORY) { if (objectId > Integer.MAX_VALUE / SysProperties.LOB_FILES_PER_DIRECTORY) {
...@@ -236,7 +242,13 @@ public class ValueLob extends Value { ...@@ -236,7 +242,13 @@ public class ValueLob extends Value {
objectId = 0; objectId = 0;
} else { } else {
// start with 1 (otherwise we don't know the number of directories) // start with 1 (otherwise we don't know the number of directories)
int dirId = RandomUtils.nextInt(SysProperties.LOB_FILES_PER_DIRECTORY - 1) + 1;
int testHack;
// int dirId = RandomUtils.nextInt(SysProperties.LOB_FILES_PER_DIRECTORY - 1) + 1;
// int dirId = 1 + ((objectId / (SysProperties.LOB_FILES_PER_DIRECTORY-1)) % (SysProperties.LOB_FILES_PER_DIRECTORY - 1));
int dirId = 1 + (counter++ / (SysProperties.LOB_FILES_PER_DIRECTORY-1));
objectId = objectId * SysProperties.LOB_FILES_PER_DIRECTORY; objectId = objectId * SysProperties.LOB_FILES_PER_DIRECTORY;
objectId += dirId * SysProperties.LOB_FILES_PER_DIRECTORY; objectId += dirId * SysProperties.LOB_FILES_PER_DIRECTORY;
} }
...@@ -245,6 +257,29 @@ public class ValueLob extends Value { ...@@ -245,6 +257,29 @@ public class ValueLob extends Value {
return objectId; return objectId;
} }
private static int counter;
private static final SmallLRUCache FILE_LIST_CACHE = new SmallLRUCache(128);
private void invalidateFileList(DataHandler handler, String dir) {
int test;
synchronized (FILE_LIST_CACHE) {
FILE_LIST_CACHE.remove(dir);
}
}
private String[] getFileList(DataHandler handler, String dir) throws SQLException {
int test;
synchronized (FILE_LIST_CACHE) {
String[] list = (String[]) FILE_LIST_CACHE.get(dir);
if (list == null) {
list = FileUtils.listFiles(dir);
FILE_LIST_CACHE.put(dir, list);
}
return list;
}
}
public static ValueLob createBlob(InputStream in, long length, DataHandler handler) throws SQLException { public static ValueLob createBlob(InputStream in, long length, DataHandler handler) throws SQLException {
try { try {
long remaining = Long.MAX_VALUE; long remaining = Long.MAX_VALUE;
...@@ -278,7 +313,7 @@ public class ValueLob extends Value { ...@@ -278,7 +313,7 @@ public class ValueLob extends Value {
String compressionAlgorithm = handler.getLobCompressionAlgorithm(type); String compressionAlgorithm = handler.getLobCompressionAlgorithm(type);
this.compression = compressionAlgorithm != null; this.compression = compressionAlgorithm != null;
synchronized (handler) { synchronized (handler) {
if (SysProperties.LOB_FILES_IN_DIRECTORIES) { if (handler.getLobFilesInDirectories()) {
objectId = getNewObjectId(handler); objectId = getNewObjectId(handler);
fileName = getFileNamePrefix(handler.getDatabasePath(), objectId) + ".temp.db"; fileName = getFileNamePrefix(handler.getDatabasePath(), objectId) + ".temp.db";
} else { } else {
...@@ -355,7 +390,7 @@ public class ValueLob extends Value { ...@@ -355,7 +390,7 @@ public class ValueLob extends Value {
// synchronize on the database, to avoid concurrent temp file // synchronize on the database, to avoid concurrent temp file
// creation / deletion / backup // creation / deletion / backup
synchronized (handler) { synchronized (handler) {
if (SysProperties.LOB_FILES_IN_DIRECTORIES) { if (handler.getLobFilesInDirectories()) {
temp = getFileName(handler, -1, objectId); temp = getFileName(handler, -1, objectId);
} else { } else {
// just to get a filename - an empty file will be created // just to get a filename - an empty file will be created
...@@ -379,7 +414,7 @@ public class ValueLob extends Value { ...@@ -379,7 +414,7 @@ public class ValueLob extends Value {
} }
if (linked) { if (linked) {
ValueLob copy = ValueLob.copy(this); ValueLob copy = ValueLob.copy(this);
if (SysProperties.LOB_FILES_IN_DIRECTORIES) { if (handler.getLobFilesInDirectories()) {
copy.objectId = getNewObjectId(handler); copy.objectId = getNewObjectId(handler);
} else { } else {
copy.objectId = handler.allocateObjectId(false, true); copy.objectId = handler.allocateObjectId(false, true);
...@@ -551,9 +586,9 @@ public class ValueLob extends Value { ...@@ -551,9 +586,9 @@ public class ValueLob extends Value {
return MathUtils.convertLongToInt(getPrecision()); return MathUtils.convertLongToInt(getPrecision());
} }
protected boolean isEqual(Value v) { public boolean equals(Object other) {
try { try {
return compareSecure(v, null) == 0; return compareSecure((Value) other, null) == 0;
} catch (SQLException e) { } catch (SQLException e) {
// TODO exceptions: improve concept, maybe remove throws // TODO exceptions: improve concept, maybe remove throws
// SQLException almost everywhere // SQLException almost everywhere
...@@ -579,7 +614,7 @@ public class ValueLob extends Value { ...@@ -579,7 +614,7 @@ public class ValueLob extends Value {
} }
public static void removeAllForTable(DataHandler handler, int tableId) throws SQLException { public static void removeAllForTable(DataHandler handler, int tableId) throws SQLException {
if (SysProperties.LOB_FILES_IN_DIRECTORIES) { if (handler.getLobFilesInDirectories()) {
String dir = getFileNamePrefix(handler.getDatabasePath(), 0); String dir = getFileNamePrefix(handler.getDatabasePath(), 0);
removeAllForTable(handler, dir, tableId); removeAllForTable(handler, dir, tableId);
} else { } else {
......
...@@ -179,8 +179,8 @@ public class ValueLong extends Value { ...@@ -179,8 +179,8 @@ public class ValueLong extends Value {
return DISPLAY_SIZE; return DISPLAY_SIZE;
} }
protected boolean isEqual(Value v) { public boolean equals(Object other) {
return v instanceof ValueLong && value == ((ValueLong) v).value; return other instanceof ValueLong && value == ((ValueLong) other).value;
} }
} }
...@@ -125,8 +125,8 @@ public class ValueNull extends Value { ...@@ -125,8 +125,8 @@ public class ValueNull extends Value {
return DISPLAY_SIZE; return DISPLAY_SIZE;
} }
protected boolean isEqual(Value v) { public boolean equals(Object other) {
return v == ValueNull.INSTANCE; return other == this;
} }
} }
...@@ -93,8 +93,12 @@ public class ValueResultSet extends Value { ...@@ -93,8 +93,12 @@ public class ValueResultSet extends Value {
throw Message.getUnsupportedException(); throw Message.getUnsupportedException();
} }
protected boolean isEqual(Value v) { public boolean equals(Object other) {
return false; return other == this;
}
public int hashCode() {
return 0;
} }
public Object getObject() throws SQLException { public Object getObject() throws SQLException {
......
...@@ -124,8 +124,8 @@ public class ValueShort extends Value { ...@@ -124,8 +124,8 @@ public class ValueShort extends Value {
return DISPLAY_SIZE; return DISPLAY_SIZE;
} }
protected boolean isEqual(Value v) { public boolean equals(Object other) {
return v instanceof ValueShort && value == ((ValueShort) v).value; return other instanceof ValueShort && value == ((ValueShort) other).value;
} }
} }
...@@ -29,6 +29,10 @@ public class ValueString extends ValueStringBase { ...@@ -29,6 +29,10 @@ public class ValueString extends ValueStringBase {
return mode.compareString(value, v.value, false); return mode.compareString(value, v.value, false);
} }
public boolean equals(Object other) {
return other instanceof ValueStringBase && value.equals(((ValueStringBase) other).value);
}
public int hashCode() { public int hashCode() {
// TODO hash performance: could build a quicker hash by hashing the size and a few characters // TODO hash performance: could build a quicker hash by hashing the size and a few characters
return value.hashCode(); return value.hashCode();
......
...@@ -47,10 +47,6 @@ abstract class ValueStringBase extends Value { ...@@ -47,10 +47,6 @@ abstract class ValueStringBase extends Value {
return value.length(); return value.length();
} }
protected boolean isEqual(Value v) {
return v instanceof ValueStringBase && value.equals(((ValueStringBase) v).value);
}
public abstract Value convertPrecision(long precision); public abstract Value convertPrecision(long precision);
public int getMemory() { public int getMemory() {
......
...@@ -37,6 +37,10 @@ public class ValueStringFixed extends ValueStringBase { ...@@ -37,6 +37,10 @@ public class ValueStringFixed extends ValueStringBase {
return s; return s;
} }
public boolean equals(Object other) {
return other instanceof ValueStringBase && value.equals(((ValueStringBase) other).value);
}
public int hashCode() { public int hashCode() {
// TODO hash performance: could build a quicker hash by hashing the size and a few characters // TODO hash performance: could build a quicker hash by hashing the size and a few characters
return value.hashCode(); return value.hashCode();
......
...@@ -30,8 +30,8 @@ public class ValueStringIgnoreCase extends ValueStringBase { ...@@ -30,8 +30,8 @@ public class ValueStringIgnoreCase extends ValueStringBase {
return mode.compareString(value, v.value, true); return mode.compareString(value, v.value, true);
} }
protected boolean isEqual(Value v) { public boolean equals(Object other) {
return v instanceof ValueStringBase && value.equalsIgnoreCase(((ValueStringBase) v).value); return other instanceof ValueStringBase && value.equalsIgnoreCase(((ValueStringBase) other).value);
} }
public int hashCode() { public int hashCode() {
......
...@@ -83,8 +83,8 @@ public class ValueTime extends Value { ...@@ -83,8 +83,8 @@ public class ValueTime extends Value {
return DISPLAY_SIZE; return DISPLAY_SIZE;
} }
protected boolean isEqual(Value v) { public boolean equals(Object other) {
return v instanceof ValueTime && value.equals(((ValueTime) v).value); return other instanceof ValueTime && value.equals(((ValueTime) other).value);
} }
} }
...@@ -115,8 +115,8 @@ public class ValueTimestamp extends Value { ...@@ -115,8 +115,8 @@ public class ValueTimestamp extends Value {
return DISPLAY_SIZE; return DISPLAY_SIZE;
} }
protected boolean isEqual(Value v) { public boolean equals(Object other) {
return v instanceof ValueTimestamp && value.equals(((ValueTimestamp) v).value); return other instanceof ValueTimestamp && value.equals(((ValueTimestamp) other).value);
} }
} }
...@@ -103,6 +103,9 @@ public class ValueUuid extends Value { ...@@ -103,6 +103,9 @@ public class ValueUuid extends Value {
} }
protected int compareSecure(Value o, CompareMode mode) { protected int compareSecure(Value o, CompareMode mode) {
if (o == this) {
return 0;
}
ValueUuid v = (ValueUuid) o; ValueUuid v = (ValueUuid) o;
if (high == v.high) { if (high == v.high) {
return (low == v.low) ? 0 : (low > v.low ? 1 : -1); return (low == v.low) ? 0 : (low > v.low ? 1 : -1);
...@@ -111,8 +114,8 @@ public class ValueUuid extends Value { ...@@ -111,8 +114,8 @@ public class ValueUuid extends Value {
} }
} }
protected boolean isEqual(Value v) { public boolean equals(Object other) {
return v instanceof ValueUuid && compareSecure(v, null) == 0; return other instanceof ValueUuid && compareSecure((Value) other, null) == 0;
} }
public Object getObject() { public Object getObject() {
......
...@@ -157,7 +157,9 @@ java org.h2.test.TestAll timer ...@@ -157,7 +157,9 @@ java org.h2.test.TestAll timer
/* /*
test t recovery with System.setProperty("h2.lobFilesInDirectories", "true");
sparse files
remove old in use, links remove old in use, links
...@@ -181,6 +183,7 @@ happens, I get dot corrupt (.corrupt) files created. ...@@ -181,6 +183,7 @@ happens, I get dot corrupt (.corrupt) files created.
After several failed attempts (total After several failed attempts (total
across a database's lifespan), FILE_RENAME_FAILED_2 errors start occur across a database's lifespan), FILE_RENAME_FAILED_2 errors start occur
until I delete the .corrupt files. until I delete the .corrupt files.
Improved performance when using lob files in directories
Roadmap: Roadmap:
......
/*
* Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.db;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.HashMap;
/**
* A simple wrapper around the JDBC API.
* Currently used for testing.
* Features:
* <ul>
* <li>No checked exceptions
* </li><li>Easy to use, fluent API
* </li></ul>
*/
public class Db {
private static final String[] DRIVERS = {
"jdbc:h2:", "org.h2.Driver",
"jdbc:firebirdsql:", "org.firebirdsql.jdbc.FBDriver",
"jdbc:db2:", "COM.ibm.db2.jdbc.net.DB2Driver",
"jdbc:oracle:", "oracle.jdbc.driver.OracleDriver",
"jdbc:microsoft:", "com.microsoft.jdbc.sqlserver.SQLServerDriver",
"jdbc:sqlserver:", "com.microsoft.sqlserver.jdbc.SQLServerDriver",
"jdbc:postgresql:", "org.postgresql.Driver",
"jdbc:mysql:", "com.mysql.jdbc.Driver",
"jdbc:derby://", "org.apache.derby.jdbc.ClientDriver",
"jdbc:derby:", "org.apache.derby.jdbc.EmbeddedDriver",
"jdbc:hsqldb:", "org.hsqldb.jdbcDriver"
};
private Connection conn;
private Statement stat;
private HashMap prepared = new HashMap();
private long start;
public static Db open(String url, String user, String password) {
try {
for (int i = 0; i < DRIVERS.length; i += 2) {
String prefix = DRIVERS[i];
if (url.startsWith(prefix)) {
Class.forName(DRIVERS[i + 1]);
break;
}
}
return new Db(DriverManager.getConnection(url, user, password));
} catch (Exception e) {
throw convert(e);
}
}
public Prepared prepare(String sql) {
try {
PreparedStatement prep = (PreparedStatement) prepared.get(sql);
if (prep == null) {
prep = conn.prepareStatement(sql);
prepared.put(sql, prep);
}
return new Prepared(conn.prepareStatement(sql));
} catch (Exception e) {
throw convert(e);
}
}
public void execute(String sql) {
try {
stat.execute(sql);
} catch (Exception e) {
throw convert(e);
}
}
public void close() {
try {
conn.close();
} catch (Exception e) {
throw convert(e);
}
}
private Db(Connection conn) {
try {
this.conn = conn;
stat = conn.createStatement();
} catch (Exception e) {
throw convert(e);
}
}
public class Prepared {
private PreparedStatement prep;
private int index;
Prepared(PreparedStatement prep) {
this.prep = prep;
}
public Prepared set(int x) {
try {
prep.setInt(++index, x);
return this;
} catch (Exception e) {
throw convert(e);
}
}
public Prepared set(String x) {
try {
prep.setString(++index, x);
return this;
} catch (Exception e) {
throw convert(e);
}
}
public Prepared set(byte[] x) {
try {
prep.setBytes(++index, x);
return this;
} catch (Exception e) {
throw convert(e);
}
}
public Prepared set(InputStream x) {
try {
prep.setBinaryStream(++index, x, -1);
return this;
} catch (Exception e) {
throw convert(e);
}
}
public void execute() {
try {
prep.execute();
} catch (Exception e) {
throw convert(e);
}
}
}
private static Error convert(Exception e) {
return new Error("Error: " + e.toString(), e);
}
public void startTime() {
start = System.currentTimeMillis();
}
public void printTime(String s) {
System.out.println(s + ": " + (System.currentTimeMillis() - start));
}
}
...@@ -6,6 +6,7 @@ package org.h2.test.unit; ...@@ -6,6 +6,7 @@ package org.h2.test.unit;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.constant.SysProperties;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.DataPage; import org.h2.store.DataPage;
import org.h2.store.FileStore; import org.h2.store.FileStore;
...@@ -137,4 +138,8 @@ public class TestDataPage extends TestBase implements DataHandler { ...@@ -137,4 +138,8 @@ public class TestDataPage extends TestBase implements DataHandler {
return this; return this;
} }
public boolean getLobFilesInDirectories() {
return SysProperties.LOB_FILES_IN_DIRECTORIES;
}
} }
...@@ -6,6 +6,8 @@ package org.h2.test.unit; ...@@ -6,6 +6,8 @@ package org.h2.test.unit;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Random; import java.util.Random;
import org.h2.constant.SysProperties;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.test.TestBase; import org.h2.test.TestBase;
...@@ -171,4 +173,8 @@ public class TestFile extends TestBase implements DataHandler { ...@@ -171,4 +173,8 @@ public class TestFile extends TestBase implements DataHandler {
return null; return null;
} }
public boolean getLobFilesInDirectories() {
return SysProperties.LOB_FILES_IN_DIRECTORIES;
}
} }
...@@ -9,6 +9,7 @@ import java.util.Comparator; ...@@ -9,6 +9,7 @@ import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.Random; import java.util.Random;
import org.h2.constant.SysProperties;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.test.TestBase; import org.h2.test.TestBase;
...@@ -135,4 +136,8 @@ public class TestValueHashMap extends TestBase implements DataHandler { ...@@ -135,4 +136,8 @@ public class TestValueHashMap extends TestBase implements DataHandler {
return this; return this;
} }
public boolean getLobFilesInDirectories() {
return SysProperties.LOB_FILES_IN_DIRECTORIES;
}
} }
...@@ -12,6 +12,7 @@ import java.util.ArrayList; ...@@ -12,6 +12,7 @@ import java.util.ArrayList;
import java.util.IdentityHashMap; import java.util.IdentityHashMap;
import java.util.Random; import java.util.Random;
import org.h2.constant.SysProperties;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.test.TestBase; import org.h2.test.TestBase;
...@@ -221,4 +222,8 @@ public class TestValueMemory extends TestBase implements DataHandler { ...@@ -221,4 +222,8 @@ public class TestValueMemory extends TestBase implements DataHandler {
return FileStore.open(this, name, mode, null); return FileStore.open(this, name, mode, null);
} }
public boolean getLobFilesInDirectories() {
return SysProperties.LOB_FILES_IN_DIRECTORIES;
}
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论