提交 a18e7177 authored 作者: Thomas Mueller's avatar Thomas Mueller

STORAGE=TEXT is no longer supported.

上级 4764791c
......@@ -18,7 +18,8 @@ Change Log
<h1>Change Log</h1>
<h2>Next Version (unreleased)</h2>
<ul><li>Deleting a database using the tool DeleteDbFiles deleted LOB files
<ul><li>The setting STORAGE=TEXT is no longer supported.
</li><li>Deleting a database using the tool DeleteDbFiles deleted LOB files
of other databases in the same directory.
</li><li>When used in a subquery, LIKE and IN(..) did not work correctly sometimes.
</li><li>The fulltext search documentation has been improved.
......
......@@ -69,8 +69,6 @@ Features
Read Only Databases</a><br />
<a href="#database_in_zip">
Read Only Databases in Zip or Jar File</a><br />
<a href="#storage_formats">
Binary and Text Storage Formats</a><br />
<a href="#low_disk_space">
Graceful Handling of Low Disk Space Situations</a><br />
<a href="#computed_columns">
......@@ -151,7 +149,7 @@ Features
</li><li>Contains a recovery tool that can dump the contents of the data file
</li><li>Support for variables (for example to calculate running totals)
</li><li>Automatic re-compilation of prepared statements
</li><li>Uses a small number of database files, binary and text storage formats, graceful handling of low disk space situations
</li><li>Uses a small number of database files
</li><li>Uses a checksum for each record and log entry for data integrity
</li><li>Well tested (high code coverage, randomized stress tests)
</li></ul>
......@@ -1321,18 +1319,6 @@ is not read in memory; so large databases are supported as well. The same indexe
a regular database.
</p>
<br /><a name="storage_formats"></a>
<h2>Binary and Text Storage Formats</h2>
<p>
This database engine supports both binary and text storage formats.
The binary format is faster, but the text storage format can be useful as well,
for example to debug the database engine.
If a database already exists, the storage format is recognized automatically.
New databases are created in the binary storage format by default.
To create a new database in the text storage format, the database URL must contain
the parameter STORAGE=TEXT. Example URL: jdbc:h2:~/test;STORAGE=TEXT
</p>
<br /><a name="low_disk_space"></a>
<h2>Graceful Handling of Low Disk Space Situations</h2>
<p>
......
......@@ -4056,10 +4056,6 @@ public class Parser {
readIfEqualOrTo();
read();
return new NoOperation(session);
} else if (readIf("STORAGE")) {
readIfEqualOrTo();
read();
return new NoOperation(session);
} else if (readIf("DB_CLOSE_ON_EXIT")) {
readIfEqualOrTo();
read();
......
......@@ -107,11 +107,10 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
}
private void initStore() throws SQLException {
byte[] magic = Database.getMagic(true);
Database db = session.getDatabase();
// script files are always in text format
String fileName = getFileName();
store = FileStore.open(db, fileName, "rw", magic, cipher, key);
store = FileStore.open(db, fileName, "rw", cipher, key);
store.setCheckedWriting(false);
store.init();
}
......@@ -180,11 +179,6 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
return false;
}
public boolean getTextStorage() {
// script files are always in text format
return true;
}
public String getDatabasePath() {
return null;
}
......
......@@ -52,7 +52,7 @@ public class ConnectionInfo implements Cloneable {
// TODO document these settings
String[] connectionTime = new String[] { "ACCESS_MODE_LOG", "ACCESS_MODE_DATA", "AUTOCOMMIT", "CIPHER",
"CREATE", "CACHE_TYPE", "DB_CLOSE_ON_EXIT", "FILE_LOCK", "IGNORE_UNKNOWN_SETTINGS", "IFEXISTS",
"PASSWORD", "RECOVER", "STORAGE", "USER", "DATABASE_EVENT_LISTENER_OBJECT", "AUTO_SERVER",
"PASSWORD", "RECOVER", "USER", "DATABASE_EVENT_LISTENER_OBJECT", "AUTO_SERVER",
"AUTO_RECONNECT", "OPEN_NEW" };
for (int i = 0; i < connectionTime.length; i++) {
String key = connectionTime[i];
......@@ -492,22 +492,6 @@ public class ConnectionInfo implements Cloneable {
originalURL = url;
}
/**
* Check if this database URL references a text based database explicitly.
*
* @return true if the storage has been set to text
*/
boolean getTextStorage() throws SQLException {
String storage = removeProperty("STORAGE", "BINARY");
if ("BINARY".equalsIgnoreCase(storage)) {
return false;
} else if ("TEXT".equalsIgnoreCase(storage)) {
return true;
} else {
throw Message.getInvalidValueException(storage, "storage");
}
}
/**
* Generate an URL format exception.
*
......
......@@ -370,11 +370,6 @@ public class Constants {
*/
public static final String MAGIC_FILE_HEADER = "-- H2 0.5/B -- ".substring(0, FILE_BLOCK_SIZE - 1) + "\n";
/**
* The file header used for text files.
*/
public static final String MAGIC_FILE_HEADER_TEXT = "-- H2 0.5/T -- ".substring(0, FILE_BLOCK_SIZE - 1) + "\n";
/**
* The name of the in-memory management database used by the TCP server
* to keep the active sessions.
......
......@@ -7,7 +7,6 @@
package org.h2.engine;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
......@@ -59,7 +58,6 @@ import org.h2.util.ByteUtils;
import org.h2.util.CacheLRU;
import org.h2.util.ClassUtils;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils;
import org.h2.util.IntHashMap;
import org.h2.util.MemoryUtils;
import org.h2.util.NetUtils;
......@@ -105,7 +103,6 @@ public class Database implements DataHandler {
private final BitField objectIds = new BitField();
private final Object lobSyncObject = new Object();
private boolean textStorage;
private Schema mainSchema;
private Schema infoSchema;
private int nextSessionId;
......@@ -182,7 +179,6 @@ public class Database implements DataHandler {
accessModeLog = "r";
}
this.fileLockMethod = FileLock.getFileLockMethod(lockMethodName);
this.textStorage = ci.getTextStorage();
this.databaseURL = ci.getURL();
this.eventListener = ci.getDatabaseEventListenerObject();
ci.removeDatabaseEventListenerObject();
......@@ -248,56 +244,6 @@ public class Database implements DataHandler {
powerOffCount = count;
}
public boolean getTextStorage() {
return textStorage;
}
/**
* Check if the storage mode of the given database file is 'text'.
*
* @param fileName the file name of the database file
* @param defaultValue the value to use if the file doesn't exist or is too
* small
* @return true if the storage mode is 'text'
* @throws SQLException if the database file version does not match
*/
public static boolean isTextStorage(String fileName, boolean defaultValue) throws SQLException {
byte[] magicText = Constants.MAGIC_FILE_HEADER_TEXT.getBytes();
byte[] magicBinary = Constants.MAGIC_FILE_HEADER.getBytes();
try {
InputStream fin = FileUtils.openFileInputStream(fileName);
byte[] magic = IOUtils.readBytesAndClose(fin, magicBinary.length);
if (ByteUtils.compareNotNull(magic, magicText) == 0) {
return true;
} else if (ByteUtils.compareNotNull(magic, magicBinary) == 0) {
return false;
} else if (magic.length < magicText.length) {
// file size is 0 or too small
return defaultValue;
}
throw Message.getSQLException(ErrorCode.FILE_VERSION_ERROR_1, fileName);
} catch (IOException e) {
throw Message.convertIOException(e, fileName);
}
}
/**
* Get the file header (the 'magic bytes').
*
* @param textStorage if the header of a text storage should be returned
* @return the magic bytes
*/
public static byte[] getMagic(boolean textStorage) {
if (textStorage) {
return Constants.MAGIC_FILE_HEADER_TEXT.getBytes();
}
return Constants.MAGIC_FILE_HEADER.getBytes();
}
public byte[] getMagic() {
return getMagic(textStorage);
}
/**
* Check if two values are equal with the current comparison mode.
*
......@@ -447,7 +393,7 @@ public class Database implements DataHandler {
if (mustExist && !FileUtils.exists(name)) {
throw Message.getSQLException(ErrorCode.FILE_NOT_FOUND_1, name);
}
FileStore store = FileStore.open(this, name, mode, getMagic(), cipher, filePasswordHash);
FileStore store = FileStore.open(this, name, mode, cipher, filePasswordHash);
try {
store.init();
} catch (SQLException e) {
......@@ -534,7 +480,6 @@ public class Database implements DataHandler {
}
}
if (FileUtils.exists(dataFileName)) {
textStorage = isTextStorage(dataFileName, textStorage);
lobFilesInDirectories &= !ValueLob.existsLobFile(getDatabasePath());
lobFilesInDirectories |= FileUtils.exists(databaseName + Constants.SUFFIX_LOBS_DIRECTORY);
}
......
......@@ -613,10 +613,6 @@ public class SessionRemote implements SessionInterface, SessionFactory, DataHand
return Constants.DEFAULT_MAX_LENGTH_CLIENTSIDE_LOB;
}
public boolean getTextStorage() {
return false;
}
public void handleInvalidChecksum() throws SQLException {
throw Message.getSQLException(ErrorCode.FILE_CORRUPTED_1, "wrong checksum");
}
......@@ -626,11 +622,10 @@ public class SessionRemote implements SessionInterface, SessionFactory, DataHand
throw Message.getSQLException(ErrorCode.FILE_CORRUPTED_1, name);
}
FileStore store;
byte[] magic = Constants.MAGIC_FILE_HEADER.getBytes();
if (cipher == null) {
store = FileStore.open(this, name, mode, magic);
store = FileStore.open(this, name, mode);
} else {
store = FileStore.open(this, name, mode, magic, cipher, fileEncryptionKey, 0);
store = FileStore.open(this, name, mode, cipher, fileEncryptionKey, 0);
}
store.setCheckedWriting(false);
try {
......
......@@ -38,7 +38,7 @@ public class BtreeHead extends Record {
}
public int getByteCount(DataPage dummy) {
return 1 + dummy.getIntLen();
return 1 + DataPage.LENGTH_INT;
}
public void write(DataPage buff) {
......
......@@ -276,7 +276,7 @@ public class BtreeLeaf extends BtreePage {
return;
}
DataPage dummy = index.getDatabase().getDataPage();
int diff = getRowSize(dummy, row) + dummy.getIntLen();
int diff = getRowSize(dummy, row) + DataPage.LENGTH_INT;
cachedRealByteCount += add ? diff : -diff;
if (cachedRealByteCount + index.getRecordOverhead() >= DiskFile.BLOCK_SIZE * BLOCKS_PER_PAGE) {
cachedRealByteCount = 0;
......@@ -286,7 +286,7 @@ public class BtreeLeaf extends BtreePage {
int getRealByteCount() throws SQLException {
DataPage dummy = index.getDatabase().getDataPage();
int len = pageData.size();
int size = 2 + dummy.getIntLen() * (len + 1);
int size = 2 + DataPage.LENGTH_INT * (len + 1);
for (int i = 0; i < len; i++) {
SearchRow row = (SearchRow) pageData.get(i);
size += getRowSize(dummy, row);
......
......@@ -356,10 +356,10 @@ public class BtreeNode extends BtreePage {
int getRealByteCount() throws SQLException {
DataPage dummy = index.getDatabase().getDataPage();
int len = pageChildren.size();
int size = 2 + dummy.getIntLen() + dummy.getIntLen() * len;
int size = 2 + DataPage.LENGTH_INT + DataPage.LENGTH_INT * len;
len = pageData.size();
size += dummy.getIntLen();
size += len * dummy.getIntLen();
size += DataPage.LENGTH_INT;
size += len * DataPage.LENGTH_INT;
for (int i = 0; i < len; i++) {
SearchRow row = getData(i);
size += getRowSize(dummy, row);
......
......@@ -170,7 +170,7 @@ public abstract class BtreePage extends Record {
* @return the number of bytes
*/
int getRowSize(DataPage dummy, SearchRow row) throws SQLException {
int rowsize = dummy.getIntLen();
int rowsize = DataPage.LENGTH_INT;
Column[] columns = index.getColumns();
for (int j = 0; j < columns.length; j++) {
Value v = row.getValue(columns[j].getColumnId());
......
......@@ -12,11 +12,6 @@ package org.h2.index;
*/
public class Page {
/**
* A log page.
*/
public static final int TYPE_LOG = 8;
/**
* This is the last page of a chain.
*/
......@@ -25,22 +20,32 @@ public class Page {
/**
* An empty page.
*/
static final int TYPE_EMPTY = 0;
public static final int TYPE_EMPTY = 0;
/**
* A data leaf page (without overflow: or FLAG_LAST).
* A data leaf page (without overflow: + FLAG_LAST).
*/
static final int TYPE_DATA_LEAF = 1;
public static final int TYPE_DATA_LEAF = 1;
/**
* A data node page (does never have overflow).
* A data node page (never has overflow pages).
*/
static final int TYPE_DATA_NODE = 2;
public static final int TYPE_DATA_NODE = 2;
/**
* An overflow pages (the last page: or FLAG_LAST).
* An overflow page (the last page: + FLAG_LAST).
*/
public static final int TYPE_DATA_OVERFLOW = 3;
/**
* A page containing a list of free pages (the last page: + FLAG_LAST).
*/
public static final int TYPE_FREE_LIST = 4;
/**
* A log page.
*/
static final int TYPE_DATA_OVERFLOW = 3;
public static final int TYPE_LOG = 5;
/**
* This is a root page.
......
......@@ -10,7 +10,7 @@ import java.sql.SQLException;
import org.h2.engine.Session;
import org.h2.result.Row;
import org.h2.store.DataPageBinary;
import org.h2.store.DataPage;
import org.h2.store.Record;
/**
......@@ -36,7 +36,7 @@ abstract class PageData extends Record {
/**
* The data page.
*/
protected final DataPageBinary data;
protected final DataPage data;
/**
* The number of entries.
......@@ -48,7 +48,7 @@ abstract class PageData extends Record {
*/
protected int[] keys;
PageData(PageScanIndex index, int pageId, int parentPageId, DataPageBinary data) {
PageData(PageScanIndex index, int pageId, int parentPageId, DataPage data) {
this.index = index;
this.parentPageId = parentPageId;
this.data = data;
......
......@@ -12,7 +12,7 @@ import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.result.Row;
import org.h2.store.DataPage;
import org.h2.store.DataPageBinary;
import org.h2.store.DataPage;
import org.h2.store.PageStore;
import org.h2.util.IntArray;
......@@ -60,7 +60,7 @@ class PageDataLeaf extends PageData {
*/
int start;
PageDataLeaf(PageScanIndex index, int pageId, int parentPageId, DataPageBinary data) {
PageDataLeaf(PageScanIndex index, int pageId, int parentPageId, DataPage data) {
super(index, pageId, parentPageId, data);
start = 7;
}
......@@ -188,7 +188,7 @@ class PageDataLeaf extends PageData {
data.setPos(pageSize);
int next = firstOverflowPageId;
while (true) {
DataPageBinary page = store.readPage(next);
DataPage page = store.readPage(next);
page.setPos(4);
int type = page.readByte();
if (type == (Page.TYPE_DATA_OVERFLOW | Page.FLAG_LAST)) {
......@@ -251,7 +251,7 @@ class PageDataLeaf extends PageData {
int testIfReallyNotRequired;
// PageStore store = index.getPageStore();
// store.updateRecord(firstOverflowPageId);
// DataPageBinary overflow = store.readPage(firstOverflowPageId);
// DataPage overflow = store.readPage(firstOverflowPageId);
// overflow.reset();
// overflow.writeInt(getPos());
// store.writePage(firstOverflowPageId, overflow);
......@@ -321,7 +321,7 @@ class PageDataLeaf extends PageData {
if (firstOverflowPageId == 0) {
throw Message.getInternalError();
}
DataPageBinary overflow = store.createDataPage();
DataPage overflow = store.createDataPage();
int parent = getPos();
int pos = pageSize;
int remaining = data.length() - pageSize;
......
......@@ -12,7 +12,7 @@ import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.result.Row;
import org.h2.store.DataPage;
import org.h2.store.DataPageBinary;
import org.h2.store.DataPage;
/**
* A leaf page that contains data of one or multiple rows.
......@@ -36,7 +36,7 @@ class PageDataNode extends PageData {
private int rowCount = UNKNOWN_ROWCOUNT;
PageDataNode(PageScanIndex index, int pageId, int parentPageId, DataPageBinary data) {
PageDataNode(PageScanIndex index, int pageId, int parentPageId, DataPage data) {
super(index, pageId, parentPageId, data);
}
......
......@@ -14,7 +14,7 @@ import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.store.DataPageBinary;
import org.h2.store.DataPage;
import org.h2.store.PageStore;
import org.h2.store.Record;
import org.h2.table.Column;
......@@ -113,7 +113,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
if (rec != null) {
return (PageData) rec;
}
DataPageBinary data = store.readPage(id);
DataPage data = store.readPage(id);
data.reset();
int parentPageId = data.readInt();
int type = data.readByte() & 255;
......@@ -211,7 +211,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
* @param data the data page
* @return the row
*/
Row readRow(DataPageBinary data) throws SQLException {
Row readRow(DataPage data) throws SQLException {
return tableData.readRow(data);
}
......
......@@ -150,7 +150,7 @@ public class LogFile {
if (file == null) {
throw Message.getSQLException(ErrorCode.SIMULATED_POWER_OFF);
}
int size = MathUtils.roundUp(buff.length() + buff.getFillerLength(), BLOCK_SIZE);
int size = MathUtils.roundUp(buff.length() + DataPage.LENGTH_FILLER, BLOCK_SIZE);
int blockCount = size / BLOCK_SIZE;
buff.fill(size);
buff.setInt(0, blockCount);
......
......@@ -54,7 +54,7 @@ public class Row extends Record implements SearchRow {
public int getByteCount(DataPage dummy) throws SQLException {
int len = data.length;
int size = dummy.getIntLen();
int size = DataPage.LENGTH_INT;
for (int i = 0; i < len; i++) {
Value v = data[i];
size += dummy.getValueLen(v);
......
......@@ -51,7 +51,7 @@ public class RowList {
}
private void writeRow(DataPage buff, Row r) throws SQLException {
buff.checkCapacity(1 + buff.getIntLen() * 7);
buff.checkCapacity(1 + DataPage.LENGTH_INT * 7);
buff.writeByte((byte) 1);
buff.writeInt(r.getMemorySize());
buff.writeInt(r.getColumnCount());
......
......@@ -29,8 +29,8 @@ public class SecureFileStore extends FileStore {
private byte[] bufferForInitVector;
private int keyIterations;
public SecureFileStore(DataHandler handler, String name, String mode, byte[] magic, String cipher, byte[] key, int keyIterations) throws SQLException {
super(handler, name, mode, magic);
public SecureFileStore(DataHandler handler, String name, String mode, String cipher, byte[] key, int keyIterations) throws SQLException {
super(handler, name, mode);
this.key = key;
if ("XTEA".equalsIgnoreCase(cipher)) {
this.cipher = new XTEA();
......
......@@ -19,13 +19,6 @@ import org.h2.value.Value;
*/
public interface DataHandler {
/**
* Check if text storage is used.
*
* @return if text storage is used.
*/
boolean getTextStorage();
/**
* Get the database path.
*
......
/*
* Copyright 2004-2008 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store;
import java.sql.SQLException;
/**
* This class represents a byte buffer optimized for performance.
* It is the standard mechanism to convert data to a byte array and vice versa.
*/
public class DataPageBinary extends DataPage {
// private final static boolean UTF8 = true;
public DataPageBinary(DataHandler handler, byte[] data) {
super(handler, data);
}
public void updateChecksum() {
if (CHECKSUM) {
int x = handler.getChecksum(data, 0, pos - 2);
data[pos - 2] = (byte) x;
}
}
public void check(int len) throws SQLException {
if (CHECKSUM) {
int x = handler.getChecksum(data, 0, len - 2);
if (data[len - 2] == (byte) x) {
return;
}
handler.handleInvalidChecksum();
}
}
public int getFillerLength() {
return 2;
}
public void writeByte(byte x) {
data[pos++] = x;
}
public int readByte() {
return data[pos++];
}
public void writeInt(int x) {
byte[] buff = data;
buff[pos++] = (byte) (x >> 24);
buff[pos++] = (byte) (x >> 16);
buff[pos++] = (byte) (x >> 8);
buff[pos++] = (byte) x;
}
public void setInt(int pos, int x) {
byte[] buff = data;
buff[pos] = (byte) (x >> 24);
buff[pos + 1] = (byte) (x >> 16);
buff[pos + 2] = (byte) (x >> 8);
buff[pos + 3] = (byte) x;
}
public int readInt() {
byte[] buff = data;
return (buff[pos++] << 24) + ((buff[pos++] & 0xff) << 16) + ((buff[pos++] & 0xff) << 8) + (buff[pos++] & 0xff);
}
/**
* Write a short integer at the current position.
* The current position is incremented.
*
* @param x the value
*/
public void writeShortInt(int x) {
byte[] buff = data;
buff[pos++] = (byte) (x >> 8);
buff[pos++] = (byte) x;
}
/**
* Read an short integer at the current position.
* The current position is incremented.
*
* @return the value
*/
public int readShortInt() {
byte[] buff = data;
return ((buff[pos++] & 0xff) << 8) + (buff[pos++] & 0xff);
}
// private static int getStringLenChar(String s) {
// return 4 + s.length() * 2;
// }
// private String readStringChar() {
// int len = ((data[pos++] & 0xff) << 24) +
// ((data[pos++] & 0xff) << 16) +
// ((data[pos++] & 0xff) << 8) + (data[pos++] & 0xff);
// char[] chars = new char[len];
// for(int i=0; i<len; i++) {
// chars[i] = (char)(((data[pos++] & 0xff) << 8) +
// (data[pos++] & 0xff));
// }
// return new String(chars);
// }
// private void writeStringChar(String s) {
// checkCapacity(s.length()*2+4);
// int len = s.length();
// data[pos++] = (byte) ((len >> 24) & 0xff);
// data[pos++] = (byte) ((len >> 16) & 0xff);
// data[pos++] = (byte) ((len >> 8) & 0xff);
// data[pos++] = (byte) (len & 0xff);
// for(int i=0; i<s.length(); i++) {
// int c = s.charAt(i);
// data[pos++] = (byte)(c >> 8);
// data[pos++] = (byte)c;
// }
// }
private static int getStringLenUTF8(String s) {
int plus = 4, len = s.length();
for (int i = 0; i < len; i++) {
char c = s.charAt(i);
if (c >= 0x800) {
plus += 2;
} else if (c == 0 || c >= 0x80) {
plus++;
}
}
return len + plus;
}
private void writeStringUTF8(String s) {
int len = s.length();
checkCapacity(len * 3 + 4);
int p = pos;
byte[] buff = data;
buff[p++] = (byte) (len >> 24);
buff[p++] = (byte) (len >> 16);
buff[p++] = (byte) (len >> 8);
buff[p++] = (byte) len;
for (int i = 0; i < len; i++) {
int c = s.charAt(i);
if (c > 0 && c < 0x80) {
buff[p++] = (byte) c;
} else if (c >= 0x800) {
buff[p++] = (byte) (0xe0 | (c >> 12));
buff[p++] = (byte) (0x80 | ((c >> 6) & 0x3f));
buff[p++] = (byte) (0x80 | (c & 0x3f));
} else {
buff[p++] = (byte) (0xc0 | (c >> 6));
buff[p++] = (byte) (0x80 | (c & 0x3f));
}
}
pos = p;
}
private String readStringUTF8() {
byte[] buff = data;
int p = pos;
int len = ((buff[p++] & 0xff) << 24) + ((buff[p++] & 0xff) << 16) + ((buff[p++] & 0xff) << 8)
+ (buff[p++] & 0xff);
char[] chars = new char[len];
for (int i = 0; i < len; i++) {
int x = buff[p++] & 0xff;
if (x < 0x80) {
chars[i] = (char) x;
} else if (x >= 0xe0) {
chars[i] = (char) (((x & 0xf) << 12) + ((buff[p++] & 0x3f) << 6) + (buff[p++] & 0x3f));
} else {
chars[i] = (char) (((x & 0x1f) << 6) + (buff[p++] & 0x3f));
}
}
pos = p;
return new String(chars);
}
public void writeString(String s) {
// if(UTF8) {
writeStringUTF8(s);
// } else {
// writeStringChar(s);
// }
}
public String readString() {
// if(UTF8) {
return readStringUTF8();
// }
// return readStringChar();
}
public int getIntLen() {
return 4;
}
public int getLongLen(long x) {
return 8;
}
public int getStringLen(String s) {
// if(UTF8) {
return getStringLenUTF8(s);
// }
// return getStringLenChar(s);
}
public void fill(int len) {
if (pos > len) {
pos = len;
}
checkCapacity(len - pos);
pos = len;
}
}
/*
* Copyright 2004-2008 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store;
import java.sql.SQLException;
import org.h2.constant.SysProperties;
import org.h2.message.Message;
/**
* This class represents a byte buffer that is human readable up to some point.
* Number are stored in hex format.
* It is mainly used to debug storage problems.
*/
public class DataPageText extends DataPage {
public DataPageText(DataHandler handler, byte[] data) {
super(handler, data);
}
public void setInt(int pos, int x) {
for (int i = 7; i >= 0; i--, x >>>= 4) {
data[i] = (byte) Character.forDigit(x & 0xf, 16);
}
}
public void updateChecksum() {
if (CHECKSUM) {
int x = handler.getChecksum(data, 0, pos - 2);
data[pos - 2] = (byte) ('a' + (((x ^ (x >> 4)) & 0xf)));
}
}
public void check(int len) throws SQLException {
if (CHECKSUM) {
int x = handler.getChecksum(data, 0, len - 2);
if (data[len - 2] == (byte) ('a' + (((x ^ (x >> 4)) & 0xf)))) {
return;
}
handler.handleInvalidChecksum();
}
}
public int getFillerLength() {
return 2;
}
public void writeInt(int x) {
if (SysProperties.CHECK) {
checkCapacity(8);
}
for (int i = 7; i >= 0; i--, x >>>= 4) {
data[pos + i] = (byte) Character.forDigit(x & 0xf, 16);
}
pos += 8;
}
public int readInt() {
int x = 0;
if (data[pos] == ' ') {
pos += 8;
return 0;
}
for (int i = 8, c; i > 0; i--) {
x <<= 4;
x |= (c = data[pos++]) >= 'a' ? (c - 'a' + 10) : (c - '0');
}
return x;
}
public int getIntLen() {
return 8;
}
public int getLongLen(long x) {
return 16;
}
public int getStringLen(String s) {
int len = 2 + s.length() + 1;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '\b':
case '\n':
case '\r':
case '\t':
case '\f':
case '"':
case '\\':
len++;
break;
default:
int ch = c & 0xffff;
if ((ch >= ' ') && (ch <= 0xff)) {
// 0
} else {
len += 5;
}
}
}
return len;
}
public String readString() {
StringBuffer buff = new StringBuffer(32);
if (SysProperties.CHECK && data[pos] != '"') {
throw Message.getInternalError("\" expected");
}
pos++;
while (true) {
char x = (char) (data[pos++] & 0xff);
if (x == '"') {
break;
} else if (x == '\\') {
x = (char) data[pos++];
switch (x) {
case 't':
buff.append('\t');
break;
case 'r':
buff.append('\r');
break;
case 'n':
buff.append('\n');
break;
case 'b':
buff.append('\b');
break;
case 'f':
buff.append('\f');
break;
case '"':
buff.append('"');
break;
case '\\':
buff.append('\\');
break;
case 'u': {
x = 0;
for (int i = 3, c; i >= 0; i--) {
x <<= 4;
x |= (c = data[pos++]) >= 'a' ? (c - 'a' + 10) : (c - '0');
}
buff.append(x);
break;
}
default:
throw Message.getInternalError("unexpected " + x);
}
} else {
buff.append(x);
}
}
pos++;
return buff.toString();
}
public void writeString(String s) {
checkCapacity(s.length() * 6 + 2);
data[pos++] = '\"';
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '\t':
data[pos++] = '\\';
data[pos++] = 't';
break;
case '\r':
data[pos++] = '\\';
data[pos++] = 'r';
break;
case '\n':
data[pos++] = '\\';
data[pos++] = 'n';
break;
case '\b':
data[pos++] = '\\';
data[pos++] = 'b';
break;
case '\f':
data[pos++] = '\\';
data[pos++] = 'f';
break;
case '"':
data[pos++] = '\\';
data[pos++] = '\"';
break;
case '\\':
data[pos++] = '\\';
data[pos++] = '\\';
break;
default:
int ch = c & 0xffff;
if ((ch >= ' ') && (ch <= 0xff)) {
data[pos++] = (byte) ch;
} else {
data[pos++] = '\\';
data[pos++] = 'u';
for (int j = 3; j >= 0; j--, ch >>>= 4) {
data[pos + j] = (byte) Character.forDigit(ch & 0xf, 16);
}
pos += 4;
}
}
}
data[pos++] = '\"';
data[pos++] = ' ';
}
public void fill(int len) {
if (pos > len) {
pos = len;
}
checkCapacity(len - pos);
while (pos < len) {
data[pos++] = ' ';
}
data[pos - 1] = '\n';
}
}
......@@ -142,7 +142,7 @@ public class DiskFile implements CacheWriter {
}
rowBuff = DataPage.create(database, BLOCK_SIZE);
// TODO: the overhead is larger in the log file, so this value is too high :-(
recordOverhead = 4 * rowBuff.getIntLen() + 1 + rowBuff.getFillerLength();
recordOverhead = 4 * DataPage.LENGTH_INT + 1 + DataPage.LENGTH_FILLER;
freeBlock = DataPage.create(database, BLOCK_SIZE);
freeBlock.fill(BLOCK_SIZE);
freeBlock.updateChecksum();
......@@ -399,7 +399,7 @@ public class DiskFile implements CacheWriter {
s.setRecordCount(0);
}
}
int blockHeaderLen = Math.max(Constants.FILE_BLOCK_SIZE, 2 * rowBuff.getIntLen());
int blockHeaderLen = Math.max(Constants.FILE_BLOCK_SIZE, 2 * DataPage.LENGTH_INT);
byte[] buff = new byte[blockHeaderLen];
DataPage s = DataPage.create(database, buff);
long time = 0;
......@@ -655,12 +655,6 @@ public class DiskFile implements CacheWriter {
if (!found) {
int max = fileBlockCount;
pos = MathUtils.roundUp(max, BLOCKS_PER_PAGE);
if (rowBuff instanceof DataPageText) {
if (pos > max) {
writeDirectDeleted(max, pos - max);
}
writeDirectDeleted(pos, blockCount);
} else {
long min = ((long) pos + blockCount) * BLOCK_SIZE;
min = MathUtils.scaleUp50Percent(Constants.FILE_MIN_SIZE, min, Constants.FILE_PAGE_SIZE, Constants.FILE_MAX_INCREMENT) + OFFSET;
if (min > file.length()) {
......@@ -668,7 +662,6 @@ public class DiskFile implements CacheWriter {
database.notifyFileSize(min);
}
}
}
setBlockOwner(null, storage, pos, blockCount, false);
for (i = 0; i < blockCount; i++) {
storage.free(i + pos, 1);
......
......@@ -50,7 +50,6 @@ public class FileStore {
*/
protected DataHandler handler;
private byte[] magic;
private FileObject file;
private long filePos;
private long fileLength;
......@@ -68,11 +67,10 @@ public class FileStore {
* @param mode the access mode ("r", "rw", "rws", "rwd")
* @param magic the magic file header
*/
protected FileStore(DataHandler handler, String name, String mode, byte[] magic) throws SQLException {
protected FileStore(DataHandler handler, String name, String mode) throws SQLException {
FileSystem fs = FileSystem.getInstance(name);
this.handler = handler;
this.name = name;
this.magic = magic;
this.mode = mode;
if (handler != null) {
tempFileDeleter = handler.getTempFileDeleter();
......@@ -102,8 +100,8 @@ public class FileStore {
* @param magic the file header magic bytes
* @return the created object
*/
public static FileStore open(DataHandler handler, String name, String mode, byte[] magic) throws SQLException {
return open(handler, name, mode, magic, null, null, 0);
public static FileStore open(DataHandler handler, String name, String mode) throws SQLException {
return open(handler, name, mode, null, null, 0);
}
/**
......@@ -117,8 +115,8 @@ public class FileStore {
* @param key the encryption key
* @return the created object
*/
public static FileStore open(DataHandler handler, String name, String mode, byte[] magic, String cipher, byte[] key) throws SQLException {
return open(handler, name, mode, magic, cipher, key, Constants.ENCRYPTION_KEY_HASH_ITERATIONS);
public static FileStore open(DataHandler handler, String name, String mode, String cipher, byte[] key) throws SQLException {
return open(handler, name, mode, cipher, key, Constants.ENCRYPTION_KEY_HASH_ITERATIONS);
}
/**
......@@ -133,13 +131,13 @@ public class FileStore {
* @param keyIterations the number of iterations the key should be hashed
* @return the created object
*/
public static FileStore open(DataHandler handler, String name, String mode, byte[] magic, String cipher,
public static FileStore open(DataHandler handler, String name, String mode, String cipher,
byte[] key, int keyIterations) throws SQLException {
FileStore store;
if (cipher == null) {
store = new FileStore(handler, name, mode, magic);
store = new FileStore(handler, name, mode);
} else {
store = new SecureFileStore(handler, name, mode, magic, cipher, key, keyIterations);
store = new SecureFileStore(handler, name, mode, cipher, key, keyIterations);
}
return store;
}
......@@ -150,7 +148,7 @@ public class FileStore {
* @return the random salt or the magic
*/
protected byte[] generateSalt() {
return magic;
return Constants.MAGIC_FILE_HEADER.getBytes();
}
/**
......@@ -185,6 +183,7 @@ public class FileStore {
public void init() throws SQLException {
int len = Constants.FILE_BLOCK_SIZE;
byte[] salt;
byte[] magic = Constants.MAGIC_FILE_HEADER.getBytes();
if (length() < HEADER_LENGTH) {
// write unencrypted
checkedWriting = false;
......
......@@ -106,7 +106,7 @@ public class FileStoreInputStream extends InputStream {
page.checkCapacity(remainingInBuffer);
// get the length to read
if (compress != null) {
page.checkCapacity(page.getIntLen());
page.checkCapacity(DataPage.LENGTH_INT);
page.readInt();
}
page.setPos(page.length() + remainingInBuffer);
......
/*
* Copyright 2004-2008 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store;
import java.sql.SQLException;
import org.h2.constant.ErrorCode;
import org.h2.index.Page;
import org.h2.message.Message;
import org.h2.util.IntArray;
/**
* The list of free pages of a page store.
* The format of a free list trunk page is:
* <ul><li>0-3: parent page id (0 for head)
* </li><li>4-4: page type
* </li><li>5-8: the next page (if there are more) or number of entries
* </li><li>9-remainder: data (4 bytes each entry)
* </li></ul>
*/
public class PageFreeList {
private final PageStore store;
private DataPage page;
private int pageId;
private int nextPage;
private IntArray array = new IntArray();
PageFreeList(PageStore store, int pageId) throws SQLException {
this.store = store;
readTrunk(pageId);
int maybeWorkLikeAStack;
int alsoReturnTrunkPagesOnceTheyAreEmpty;
}
int allocate() throws SQLException {
while (true) {
int size = array.size();
if (size > 0) {
int x = array.get(size - 1);
array.remove(size - 1);
return x;
}
if (nextPage == 0) {
return -1;
}
readTrunk(nextPage);
}
}
private void readTrunk(int pageId) throws SQLException {
if (nextPage == 0) {
return;
}
int parentPage = pageId;
pageId = nextPage;
store.readPage(pageId, page);
int p = page.readInt();
int t = page.readByte();
boolean last = (t & Page.FLAG_LAST) != 0;
t &= ~Page.FLAG_LAST;
if (t != Page.TYPE_FREE_LIST || p != parentPage) {
throw Message.getSQLException(
ErrorCode.FILE_CORRUPTED_1,
"type:" + t + " parent:" + p +
" expected type:" + Page.TYPE_FREE_LIST + " expected parent:" + parentPage);
}
int size;
if (last) {
nextPage = 0;
size = page.readInt();
} else {
nextPage = page.readInt();
size = (store.getPageSize() - page.length()) / DataPage.LENGTH_INT;
}
for (int i = 0; i < size; i++) {
array.add(page.readInt());
}
}
void free(int pageId) {
}
}
......@@ -21,11 +21,6 @@ import org.h2.message.Message;
* </li><li>5-8: the next page (if there are more) or length
* </li><li>9-remainder: data
* </li></ul>
* The data format is:
* <ul><li>0-0: type (0: end, 1: undo)
* </li><li>1-4: page id
* </li><li>5-: data
* </li></ul>
*/
public class PageInputStream extends InputStream {
......@@ -33,7 +28,7 @@ public class PageInputStream extends InputStream {
private int parentPage;
private int type;
private int nextPage;
private DataPageBinary page;
private DataPage page;
private boolean endOfFile;
private int remaining;
......
......@@ -31,8 +31,8 @@ public class PageLog {
private int bufferPos;
private int firstPage;
private int nextPage;
private DataPageBinary data;
private DataPageBinary output;
private DataPage data;
private DataPage output;
PageLog(PageStore store, int firstPage) {
this.store = store;
......@@ -72,7 +72,7 @@ public class PageLog {
// data.reset();
// data.writeByte((byte) 1);
// data.writeInt(pageId);
// DataPageBinary p = store.readPage(pageId);
// DataPage p = store.readPage(pageId);
// data.write(p.getBytes(), 0, store.getPageSize());
// write(data.getBytes(), 0, data.length());
// }
......
......@@ -22,7 +22,7 @@ public class PageOutputStream extends OutputStream {
private int type;
private int pageId;
private int nextPage;
private DataPageBinary page;
private DataPage page;
private int remaining;
/**
......
......@@ -52,14 +52,13 @@ public class PageStore implements CacheWriter {
private String accessMode;
private int cacheSize;
private Cache cache;
private DataPageBinary fileHeader;
private DataPage fileHeader;
private int systemRootPageId;
private int freeListRootPageId;
private int freePageCount;
private int pageCount;
private int writeCount;
private long fileLength;
private long currentPos;
/**
* Create a new page store object.
......@@ -87,7 +86,7 @@ public class PageStore implements CacheWriter {
*/
public void open() throws SQLException {
try {
fileHeader = new DataPageBinary(database, new byte[FILE_HEADER_SIZE - FileStore.HEADER_LENGTH]);
fileHeader = DataPage.create(database, new byte[FILE_HEADER_SIZE - FileStore.HEADER_LENGTH]);
if (FileUtils.exists(fileName)) {
file = database.openFile(fileName, accessMode, true);
readHeader();
......@@ -259,8 +258,8 @@ public class PageStore implements CacheWriter {
*
* @return the data page.
*/
public DataPageBinary createDataPage() {
return new DataPageBinary(database, new byte[pageSize]);
public DataPage createDataPage() {
return DataPage.create(database, new byte[pageSize]);
}
/**
......@@ -280,8 +279,8 @@ public class PageStore implements CacheWriter {
* @param pos the page id
* @return the page
*/
public DataPageBinary readPage(int pos) throws SQLException {
DataPageBinary page = createDataPage();
public DataPage readPage(int pos) throws SQLException {
DataPage page = createDataPage();
readPage(pos, page);
return page;
}
......@@ -290,9 +289,9 @@ public class PageStore implements CacheWriter {
* Read a page.
*
* @param pos the page id
* @return the page
* @param page the page
*/
public void readPage(int pos, DataPageBinary page) throws SQLException {
public void readPage(int pos, DataPage page) throws SQLException {
file.seek(pos << pageSizeShift);
file.readFully(page.getBytes(), 0, pageSize);
}
......@@ -321,7 +320,7 @@ public class PageStore implements CacheWriter {
* @param pageId the page id
* @param data the data
*/
public void writePage(int pageId, DataPageBinary data) throws SQLException {
public void writePage(int pageId, DataPage data) throws SQLException {
file.seek(pageId << pageSizeShift);
file.write(data.getBytes(), 0, pageSize);
}
......
......@@ -9,8 +9,6 @@ package org.h2.tools;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import org.h2.engine.Database;
import org.h2.message.Message;
import org.h2.security.SHA256;
import org.h2.store.FileLister;
......@@ -169,27 +167,24 @@ public class ChangeFileEncryption extends Tool {
}
private void process(String fileName) throws SQLException {
boolean textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage);
FileStore in;
if (decrypt == null) {
in = FileStore.open(null, fileName, "r", magic);
in = FileStore.open(null, fileName, "r");
} else {
in = FileStore.open(null, fileName, "r", magic, cipher, decrypt);
in = FileStore.open(null, fileName, "r", cipher, decrypt);
}
in.init();
copy(fileName, textStorage, in, encrypt);
copy(fileName, in, encrypt);
}
private void copy(String fileName, boolean textStorage, FileStore in, byte[] key) throws SQLException {
private void copy(String fileName, FileStore in, byte[] key) throws SQLException {
String temp = dir + "/temp.db";
FileUtils.delete(temp);
byte[] magic = Database.getMagic(textStorage);
FileStore fileOut;
if (key == null) {
fileOut = FileStore.open(null, temp, "rw", magic);
fileOut = FileStore.open(null, temp, "rw");
} else {
fileOut = FileStore.open(null, temp, "rw", magic, cipher, key);
fileOut = FileStore.open(null, temp, "rw", cipher, key);
}
fileOut.init();
byte[] buffer = new byte[4 * 1024];
......
......@@ -24,10 +24,8 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.h2.command.Parser;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.DbObject;
import org.h2.engine.MetaRecord;
import org.h2.log.LogFile;
......@@ -65,7 +63,6 @@ import org.h2.value.ValueLob;
public class Recover extends Tool implements DataHandler {
private String databaseName;
private boolean textStorage;
private int block;
private int blockCount;
private int storageId;
......@@ -173,9 +170,7 @@ public class Recover extends Tool implements DataHandler {
private void removePassword(String fileName) throws SQLException {
setDatabaseName(fileName.substring(fileName.length() - Constants.SUFFIX_DATA_FILE.length()));
textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage);
FileStore store = FileStore.open(null, fileName, "rw", magic);
FileStore store = FileStore.open(null, fileName, "rw");
long length = store.length();
int offset = FileStore.HEADER_LENGTH;
int blockSize = DiskFile.BLOCK_SIZE;
......@@ -356,9 +351,7 @@ public class Recover extends Tool implements DataHandler {
InputStream in = null;
try {
fileOut = FileUtils.openFileOutputStream(n, false);
textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage);
store = FileStore.open(null, fileName, "r", magic);
store = FileStore.open(null, fileName, "r");
store.init();
in = new BufferedInputStream(new FileStoreInputStream(store, this, lobCompression, false));
byte[] buffer = new byte[Constants.IO_BUFFER_SIZE];
......@@ -455,9 +448,7 @@ public class Recover extends Tool implements DataHandler {
try {
setDatabaseName(fileName.substring(fileName.length() - Constants.SUFFIX_LOG_FILE.length()));
writer = getWriter(fileName, ".txt");
textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage);
store = FileStore.open(null, fileName, "r", magic);
store = FileStore.open(null, fileName, "r");
long length = store.length();
writer.println("// length: " + length);
int offset = FileStore.HEADER_LENGTH;
......@@ -617,9 +608,7 @@ public class Recover extends Tool implements DataHandler {
try {
setDatabaseName(fileName.substring(fileName.length() - Constants.SUFFIX_INDEX_FILE.length()));
writer = getWriter(fileName, ".txt");
textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage);
store = FileStore.open(null, fileName, "r", magic);
store = FileStore.open(null, fileName, "r");
long length = store.length();
int offset = FileStore.HEADER_LENGTH;
int blockSize = DiskFile.BLOCK_SIZE;
......@@ -691,21 +680,10 @@ public class Recover extends Tool implements DataHandler {
private void dumpData(String fileName) {
setDatabaseName(fileName.substring(0, fileName.length() - Constants.SUFFIX_DATA_FILE.length()));
try {
textStorage = Database.isTextStorage(fileName, false);
dumpData(fileName, textStorage, fileName, FileStore.HEADER_LENGTH);
} catch (SQLException e) {
traceError("Can not parse file header", e);
for (int i = 0; i < 256; i += 16) {
textStorage = (i % 2) == 0;
int offset = i / 2;
String out = fileName + (textStorage ? ".txt." : ".") + offset + Constants.SUFFIX_DATA_FILE;
dumpData(fileName, textStorage, out, offset);
}
}
dumpData(fileName, fileName, FileStore.HEADER_LENGTH);
}
private void dumpData(String fileName, boolean textStorage, String outputName, int offset) {
private void dumpData(String fileName, String outputName, int offset) {
PrintWriter writer = null;
FileStore store = null;
try {
......@@ -715,8 +693,7 @@ public class Recover extends Tool implements DataHandler {
ObjectArray schema = new ObjectArray();
HashSet objectIdSet = new HashSet();
HashMap tableMap = new HashMap();
byte[] magic = Database.getMagic(textStorage);
store = FileStore.open(null, fileName, "r", magic);
store = FileStore.open(null, fileName, "r");
long length = store.length();
int blockSize = DiskFile.BLOCK_SIZE;
int blocks = (int) (length / blockSize);
......@@ -763,7 +740,7 @@ public class Recover extends Tool implements DataHandler {
} catch (Throwable e) {
writeDataError(writer, "eof", s.getBytes(), 1);
blockCount = 1;
store = FileStore.open(null, fileName, "r", magic);
store = FileStore.open(null, fileName, "r");
continue;
}
}
......@@ -922,13 +899,6 @@ public class Recover extends Tool implements DataHandler {
traceError("Error", e);
}
/**
* INTERNAL
*/
public boolean getTextStorage() {
return textStorage;
}
/**
* INTERNAL
*/
......@@ -940,7 +910,7 @@ public class Recover extends Tool implements DataHandler {
* INTERNAL
*/
public FileStore openFile(String name, String mode, boolean mustExist) throws SQLException {
return FileStore.open(this, name, "rw", Constants.MAGIC_FILE_HEADER.getBytes());
return FileStore.open(this, name, "rw");
}
/**
......
......@@ -477,7 +477,7 @@ public class ValueLob extends Value {
}
deleteFile(handler, temp);
renameFile(handler, fileName, temp);
tempFile = FileStore.open(handler, temp, "rw", null);
tempFile = FileStore.open(handler, temp, "rw");
tempFile.autoDelete();
tempFile.closeSilently();
fileName = temp;
......
......@@ -232,11 +232,6 @@ java org.h2.test.TestAll timer
*/
boolean diskUndo;
/**
* If the text storage mechanism should be used.
*/
boolean textStorage;
/**
* If a small cache and a low number for MAX_MEMORY_ROWS should be used.
*/
......@@ -291,7 +286,6 @@ http://blog.flexive.org/2008/12/05/porting-flexive-to-the-h2-database/
postgresql generate_series?
is in-memory scan index re-using ids?
don't store default values (store a special value)
build.sh from mac (test in Ubuntu)
btree: maybe split at the insertion point
split files (1 GB max size)
add a setting (that can be changed at runtime) to call fsync
......@@ -417,15 +411,14 @@ http://www.w3schools.com/sql/
} else {
cipher = "AES";
}
for (int a = 0; a < 256; a++) {
for (int a = 0; a < 128; a++) {
smallLog = (a & 1) != 0;
big = (a & 2) != 0;
networked = (a & 4) != 0;
memory = (a & 8) != 0;
ssl = (a & 16) != 0;
textStorage = (a & 32) != 0;
diskResult = (a & 64) != 0;
deleteIndex = (a & 128) != 0;
diskResult = (a & 32) != 0;
deleteIndex = (a & 64) != 0;
for (logMode = 0; logMode < 3; logMode++) {
traceLevelFile = logMode;
test();
......@@ -439,7 +432,7 @@ http://www.w3schools.com/sql/
*/
private void runTests() throws SQLException {
jdk14 = true;
smallLog = big = networked = memory = ssl = textStorage = false;
smallLog = big = networked = memory = ssl = false;
diskResult = deleteIndex = traceSystemOut = diskUndo = false;
mvcc = traceTest = stopOnError = cache2Q = false;
traceLevelFile = throttle = 0;
......@@ -449,18 +442,15 @@ http://www.w3schools.com/sql/
networked = true;
memory = true;
textStorage = true;
test();
networked = false;
memory = false;
textStorage = false;
logMode = 2;
test();
logMode = 1;
diskUndo = true;
textStorage = true;
diskResult = true;
deleteIndex = true;
traceLevelFile = 3;
......@@ -469,7 +459,6 @@ http://www.w3schools.com/sql/
test();
diskUndo = false;
textStorage = false;
diskResult = false;
deleteIndex = false;
traceLevelFile = 1;
......@@ -718,7 +707,6 @@ http://www.w3schools.com/sql/
appendIf(buff, smallLog, "smallLog");
appendIf(buff, ssl, "ssl");
appendIf(buff, diskUndo, "diskUndo");
appendIf(buff, textStorage, "textStorage");
appendIf(buff, diskResult, "diskResult");
appendIf(buff, traceSystemOut, "traceSystemOut");
appendIf(buff, endless, "endless");
......
......@@ -51,6 +51,7 @@ public abstract class TestBase {
* Get the test directory for this test.
*
* @param name the directory name suffix
* @return the test directory
*/
public static String getTestDir(String name) {
return BASE_TEST_DIR + "/test" + name;
......@@ -211,9 +212,6 @@ public abstract class TestBase {
url = name;
}
if (!config.memory) {
if (config.textStorage) {
url += ";STORAGE=TEXT";
}
if (admin) {
url += ";LOG=" + config.logMode;
}
......
......@@ -28,12 +28,8 @@ import org.h2.value.ValueString;
*/
public class TestDataPage extends TestBase implements DataHandler {
boolean text;
public void test() throws SQLException {
testAll();
text = true;
testAll();
}
private void testAll() throws SQLException {
......@@ -90,10 +86,6 @@ public class TestDataPage extends TestBase implements DataHandler {
page = null;
}
public boolean getTextStorage() {
return text;
}
public String getDatabasePath() {
return null;
}
......
......@@ -29,7 +29,6 @@ public class TestFile extends TestBase implements DataHandler {
}
private void doTest(boolean compress) throws Exception {
byte[] magic = new byte[0];
int len = getSize(1000, 10000);
Random random = new Random();
FileStore mem = null, file = null;
......@@ -48,8 +47,8 @@ public class TestFile extends TestBase implements DataHandler {
buffFile = new byte[l];
}
if (file == null) {
mem = FileStore.open(this, prefix + "test", "rw", magic);
file = FileStore.open(this, "~/testFile", "rw", magic);
mem = FileStore.open(this, prefix + "test", "rw");
file = FileStore.open(this, "~/testFile", "rw");
}
assertEquals(file.getFilePointer(), mem.getFilePointer());
assertEquals(file.length(), mem.length());
......@@ -169,10 +168,6 @@ public class TestFile extends TestBase implements DataHandler {
return 0;
}
public boolean getTextStorage() {
return false;
}
public void handleInvalidChecksum() {
// nothing to do
}
......
......@@ -38,13 +38,12 @@ public class TestPageStoreStreams extends TestBase {
public void test() throws Exception {
testFuzz();
// for (int i = 0; i < 4; i++) {
// testPerformance(true);
// testPerformance(false);
// }
testPerformance(false, 1000);
// testPerformance(true, 1000000);
// testPerformance(false, 1000000);
}
private void testPerformance(boolean file) throws Exception {
private void testPerformance(boolean file, int count) throws Exception {
String name = "mem:pageStoreStreams";
ConnectionInfo ci = new ConnectionInfo(name);
Database db = new Database(name, ci, null);
......@@ -65,7 +64,7 @@ public class TestPageStoreStreams extends TestBase {
} else {
out = new PageOutputStream(store, 0, head, Page.TYPE_LOG);
}
for (int i = 0; i < 1000000; i++) {
for (int i = 0; i < count; i++) {
out.write(buff);
}
out.close();
......@@ -81,7 +80,7 @@ public class TestPageStoreStreams extends TestBase {
}
}
in.close();
System.out.println((file ? "file" : "pageStore") +
println((file ? "file" : "pageStore") +
" " + (System.currentTimeMillis() - start));
store.close();
db.shutdownImmediately();
......
......@@ -421,7 +421,7 @@ public class TestTools extends TestBase {
private void testChangeFileEncryption() throws SQLException {
org.h2.Driver.load();
Connection conn = DriverManager.getConnection("jdbc:h2:" + baseDir + "/utils;CIPHER=XTEA;STORAGE=TEXT", "sa",
Connection conn = DriverManager.getConnection("jdbc:h2:" + baseDir + "/utils;CIPHER=XTEA", "sa",
"abc 123");
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
......
......@@ -90,10 +90,6 @@ public class TestValueHashMap extends TestBase implements DataHandler {
}
}
public boolean getTextStorage() {
return false;
}
public String getDatabasePath() {
return null;
}
......
......@@ -225,16 +225,12 @@ public class TestValueMemory extends TestBase implements DataHandler {
return 100;
}
public boolean getTextStorage() {
return false;
}
public void handleInvalidChecksum() {
// nothing to do
}
public FileStore openFile(String name, String mode, boolean mustExist) throws SQLException {
return FileStore.open(this, name, mode, null);
return FileStore.open(this, name, mode);
}
public boolean getLobFilesInDirectories() {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论