提交 4a67b82c authored 作者: Thomas Mueller's avatar Thomas Mueller

New experimental page store

上级 b896df02
......@@ -70,25 +70,29 @@ public class BackupCommand extends Prepared {
try {
log.flush();
log.updateKeepFiles(1);
String fn = db.getName() + Constants.SUFFIX_DATA_FILE;
backupDiskFile(out, fn, db.getDataFile());
fn = db.getName() + Constants.SUFFIX_INDEX_FILE;
backupDiskFile(out, fn, db.getIndexFile());
String fn;
if (SysProperties.PAGE_STORE) {
fn = db.getName() + Constants.SUFFIX_PAGE_FILE;
backupPageStore(out, fn, db.getPageStore());
} else {
fn = db.getName() + Constants.SUFFIX_DATA_FILE;
backupDiskFile(out, fn, db.getDataFile());
fn = db.getName() + Constants.SUFFIX_INDEX_FILE;
backupDiskFile(out, fn, db.getIndexFile());
}
ObjectArray list = log.getActiveLogFiles();
int max = list.size();
// synchronize on the database, to avoid concurrent temp file
// creation / deletion / backup
String base = FileUtils.getParent(fn);
synchronized (db.getLobSyncObject()) {
for (int i = 0; i < list.size(); i++) {
LogFile lf = (LogFile) list.get(i);
fn = lf.getFileName();
backupFile(out, base, fn);
db.setProgress(DatabaseEventListener.STATE_BACKUP_FILE, name, i, max);
if (!SysProperties.PAGE_STORE) {
ObjectArray list = log.getActiveLogFiles();
int max = list.size();
for (int i = 0; i < list.size(); i++) {
LogFile lf = (LogFile) list.get(i);
fn = lf.getFileName();
backupFile(out, base, fn);
db.setProgress(DatabaseEventListener.STATE_BACKUP_FILE, name, i, max);
}
}
String prefix = db.getDatabasePath();
String dir = FileUtils.getParent(prefix);
......
......@@ -530,27 +530,29 @@ public class Database implements DataHandler {
dummy = DataPage.create(this, 0);
deleteOldTempFiles();
log = new LogSystem(this, databaseName, readOnly, accessModeLog, pageStore);
openFileData();
log.open();
openFileIndex();
log.recover();
fileData.init();
try {
fileIndex.init();
} catch (Exception e) {
if (recovery) {
traceSystem.getTrace(Trace.DATABASE).error("opening index", e);
ArrayList list = new ArrayList(storageMap.values());
for (int i = 0; i < list.size(); i++) {
Storage s = (Storage) list.get(i);
if (s.getDiskFile() == fileIndex) {
removeStorage(s.getId(), fileIndex);
if (pageStore == null) {
openFileData();
log.open();
openFileIndex();
log.recover();
fileData.init();
try {
fileIndex.init();
} catch (Exception e) {
if (recovery) {
traceSystem.getTrace(Trace.DATABASE).error("opening index", e);
ArrayList list = new ArrayList(storageMap.values());
for (int i = 0; i < list.size(); i++) {
Storage s = (Storage) list.get(i);
if (s.getDiskFile() == fileIndex) {
removeStorage(s.getId(), fileIndex);
}
}
fileIndex.delete();
openFileIndex();
} else {
throw Message.convert(e);
}
fileIndex.delete();
openFileIndex();
} else {
throw Message.convert(e);
}
}
reserveLobFileObjectIds();
......
......@@ -85,6 +85,9 @@ abstract class PageBtree extends Record {
* @return the index of the found row
*/
int find(SearchRow compare, boolean bigger) throws SQLException {
if (compare == null) {
return 0;
}
int l = 0, r = entryCount;
while (l < r) {
int i = (l + r) >>> 1;
......
......@@ -57,6 +57,9 @@ public class PageBtreeCursor implements Cursor {
}
public boolean next() throws SQLException {
if (current == null) {
return false;
}
if (i >= current.getEntryCount()) {
current.nextPage(this);
i = 0;
......@@ -65,7 +68,7 @@ public class PageBtreeCursor implements Cursor {
}
}
currentSearchRow = current.getRow(i);
if (index.compareRows(currentSearchRow, last) > 0) {
if (last != null && index.compareRows(currentSearchRow, last) > 0) {
currentSearchRow = null;
currentRow = null;
return false;
......
......@@ -9,7 +9,6 @@ package org.h2.index;
import java.sql.SQLException;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.result.Row;
......@@ -46,9 +45,6 @@ public class PageBtreeIndex extends BaseIndex {
return;
}
this.store = database.getPageStore();
if (store == null) {
System.out.println("stop");
}
if (headPos == Index.EMPTY_HEAD) {
// new table
headPos = store.allocatePage();
......@@ -113,7 +109,6 @@ if (store == null) {
root = newRoot;
}
rowCount++;
store.logAddOrRemoveRow(session, tableData.getId(), row, true);
}
/**
......@@ -175,9 +170,8 @@ if (store == null) {
throw Message.getUnsupportedException();
}
public double getCost(Session session, int[] masks) throws SQLException {
long cost = 10 * (tableData.getRowCountApproximation() + Constants.COST_ROW_OFFSET);
return cost;
public double getCost(Session session, int[] masks) {
return 10 * getCostRangeIndex(masks, tableData.getRowCount(session));
}
public boolean needRebuild() {
......@@ -207,7 +201,6 @@ if (store == null) {
rowCount--;
int todoReuseKeys;
}
store.logAddOrRemoveRow(session, tableData.getId(), row, false);
}
public void remove(Session session) throws SQLException {
......@@ -237,8 +230,8 @@ if (store == null) {
rowCount = 0;
}
public void checkRename() throws SQLException {
throw Message.getUnsupportedException();
public void checkRename() {
// ok
}
/**
......
......@@ -8,7 +8,6 @@ package org.h2.index;
import java.sql.SQLException;
import org.h2.constant.ErrorCode;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.result.Row;
import org.h2.result.SearchRow;
......@@ -206,7 +205,7 @@ class PageBtreeLeaf extends PageBtree {
}
void find(PageBtreeCursor cursor, SearchRow first, boolean bigger) throws SQLException {
int i = find(first, bigger) + 1;
int i = find(first, bigger);
if (i > entryCount) {
if (parentPageId == Page.ROOT) {
return;
......
......@@ -7,7 +7,6 @@
package org.h2.index;
import java.sql.SQLException;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.result.SearchRow;
import org.h2.store.DataPage;
......@@ -91,6 +90,7 @@ class PageBtreeNode extends PageBtree {
newRows[x] = row;
newChildPageIds[x + 1] = childPageId;
offsets = newOffsets;
rows = newRows;
childPageIds = newChildPageIds;
entryCount++;
return 0;
......@@ -163,15 +163,15 @@ class PageBtreeNode extends PageBtree {
*/
void init(PageBtree page1, SearchRow pivot, PageBtree page2) throws SQLException {
entryCount = 0;
childPageIds = new int[] { page2.getPageId() };
childPageIds = new int[] { page1.getPageId() };
rows = new SearchRow[0];
offsets = new int[0];
addChild(0, page1.getPageId(), pivot);
addChild(0, page2.getPageId(), pivot);
check();
}
void find(PageBtreeCursor cursor, SearchRow first, boolean bigger) throws SQLException {
int i = find(first, bigger) + 1;
int i = find(first, bigger);
if (i > entryCount) {
if (parentPageId == Page.ROOT) {
return;
......
......@@ -8,12 +8,14 @@ package org.h2.result;
import java.sql.SQLException;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
import org.h2.engine.Session;
import org.h2.index.BtreeIndex;
import org.h2.index.Cursor;
import org.h2.index.Index;
import org.h2.index.IndexType;
import org.h2.index.PageBtreeIndex;
import org.h2.message.Message;
import org.h2.schema.Schema;
import org.h2.table.Column;
......@@ -52,7 +54,11 @@ public class ResultTempTable implements ResultExternal {
IndexType indexType;
indexType = IndexType.createPrimaryKey(true, false);
IndexColumn[] indexCols = new IndexColumn[]{indexColumn};
index = new BtreeIndex(session, table, indexId, tableName, indexCols, indexType, Index.EMPTY_HEAD);
if (SysProperties.PAGE_STORE) {
index = new PageBtreeIndex(table, indexId, tableName, indexCols, indexType, Index.EMPTY_HEAD);
} else {
index = new BtreeIndex(session, table, indexId, tableName, indexCols, indexType, Index.EMPTY_HEAD);
}
table.getIndexes().add(index);
}
......
......@@ -81,7 +81,9 @@ public class RowList {
private void writeAllRows() throws SQLException {
if (file == null) {
Database db = session.getDatabase();
this.cache = db.getDataFile().getCache();
if (!SysProperties.PAGE_STORE) {
cache = db.getDataFile().getCache();
}
String fileName = db.createTempFile();
file = db.openFile(fileName, "rw", false);
file.seek(FileStore.HEADER_LENGTH);
......@@ -184,7 +186,7 @@ public class RowList {
}
values[i] = v;
}
if (pos != 0) {
if (pos != 0 && cache != null) {
CacheObject found = cache.find(pos);
if (found != null) {
return (Row) found;
......
......@@ -70,6 +70,7 @@ public class PageStore implements CacheWriter {
// TODO two phase commit: append (not patch) commit & rollback
// TODO remove trace or use isDebugEnabled
// TODO recover tool: don't re-do uncommitted operations
// TODO no need to log old page if it was always empty
/**
* The smallest possible page size.
......@@ -86,10 +87,14 @@ public class PageStore implements CacheWriter {
*/
public static final int PAGE_SIZE_DEFAULT = 1024;
/**
* The number of log streams.
*/
public static final int LOG_COUNT = 2;
private static final int INCREMENT_PAGES = 128;
private static final int READ_VERSION = 0;
private static final int WRITE_VERSION = 0;
private static final int LOG_COUNT = 2;
private Database database;
private final Trace trace;
......@@ -155,7 +160,7 @@ public class PageStore implements CacheWriter {
this.database = database;
trace = database.getTrace(Trace.PAGE_STORE);
int test;
trace.setLevel(TraceSystem.DEBUG);
//trace.setLevel(TraceSystem.DEBUG);
this.cacheSize = cacheSizeDefault;
String cacheType = database.getCacheType();
if (Cache2Q.TYPE_NAME.equals(cacheType)) {
......
......@@ -68,7 +68,7 @@ public class TableData extends Table implements RecordReader {
setColumns(cols);
this.clustered = clustered;
if (!clustered) {
if (SysProperties.PAGE_STORE && persistent) {
if (SysProperties.PAGE_STORE && database.isPersistent()) {
scanIndex = new PageScanIndex(this, id, IndexColumn.wrap(cols), IndexType.createScan(persistent), headPos);
} else {
scanIndex = new ScanIndex(this, id, IndexColumn.wrap(cols), IndexType.createScan(persistent));
......
......@@ -762,6 +762,12 @@ public class Recover extends Tool implements DataHandler {
writer.println("-- page " + page + ": data leaf " + (last ? "(last)" : ""));
dumpPageDataLeaf(store, pageSize, writer, s, last, page);
break;
case Page.TYPE_BTREE_NODE:
writer.println("-- page " + page + ": btree node" + (last ? "(last)" : ""));
break;
case Page.TYPE_BTREE_LEAF:
writer.println("-- page " + page + ": btree leaf " + (last ? "(last)" : ""));
break;
case Page.TYPE_FREE_LIST:
writer.println("-- page " + page + ": free list " + (last ? "(last)" : ""));
break;
......@@ -775,32 +781,8 @@ public class Recover extends Tool implements DataHandler {
}
}
writeSchema(writer);
DataInputStream in = new DataInputStream(
new PageInputStream(writer, this, store, logHead, pageSize, 0, Page.TYPE_LOG)
);
writer.println("-- log");
while (true) {
int x = in.read();
if (x < 0) {
break;
}
if (x == PageLog.NO_OP) {
// nothing to do
} else if (x == PageLog.UNDO) {
int pageId = in.readInt();
in.readFully(new byte[pageSize]);
writer.println("-- undo page " + pageId);
} else if (x == PageLog.ADD || x == PageLog.REMOVE) {
int sessionId = in.readInt();
storageId = in.readInt();
Row row = PageLog.readRow(in, s);
writer.println("-- session " + sessionId +
" table " + storageId +
" " + (x == PageLog.ADD ? "add" : "remove") + " " + row.toString());
} else if (x == PageLog.COMMIT) {
int sessionId = in.readInt();
writer.println("-- commit " + sessionId);
}
for (int i = 0; i < PageStore.LOG_COUNT; i++) {
dumpPageLogStream(writer, store, logHead + i, pageSize);
}
writer.close();
} catch (Throwable e) {
......@@ -811,6 +793,39 @@ public class Recover extends Tool implements DataHandler {
}
}
private void dumpPageLogStream(PrintWriter writer, FileStore store, int logHead, int pageSize) throws IOException, SQLException {
DataPage s = DataPage.create(this, pageSize);
DataInputStream in = new DataInputStream(
new PageInputStream(writer, this, store, logHead, pageSize, 0, Page.TYPE_LOG)
);
int logId = in.readInt();
writer.println("-- log " + logId);
while (true) {
int x = in.read();
if (x < 0) {
break;
}
if (x == PageLog.NO_OP) {
// nothing to do
} else if (x == PageLog.UNDO) {
int pageId = in.readInt();
in.readFully(new byte[pageSize]);
writer.println("-- undo page " + pageId);
} else if (x == PageLog.ADD || x == PageLog.REMOVE) {
int sessionId = in.readInt();
storageId = in.readInt();
Row row = PageLog.readRow(in, s);
writer.println("-- session " + sessionId +
" table " + storageId +
" " + (x == PageLog.ADD ? "add" : "remove") + " " + row.toString());
} else if (x == PageLog.COMMIT) {
int sessionId = in.readInt();
writer.println("-- commit " + sessionId);
}
}
}
/**
* An input stream that reads the data from a page store.
*/
......
......@@ -283,6 +283,8 @@ java org.h2.test.TestAll timer
/*
arc
select 1 from dual a where 1 in(select 1 from dual b
where 1 in(select 1 from dual c where a.x=1));
......
......@@ -581,4 +581,4 @@ titles headers grew orchestration social razor finder ranging friend intervals
bot jot delicious rife appenders circles spelling cash sky ecm nuxeo poland
opengeospatial sfs symmetric obsolete failing parenthesis unloading refreshed
grails reloading slightly accepting deploying conflicting recovered counters
versus extracts squirrel misdirected rle looking
versus extracts squirrel misdirected rle looking arc
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论