提交 03e1c25a authored 作者: Thomas Mueller's avatar Thomas Mueller

new experimental page store

上级 d7e9f4a2
......@@ -524,7 +524,9 @@ public class Database implements DataHandler {
// wait until pending changes are written
isReconnectNeeded();
if (SysProperties.PAGE_STORE) {
starting = true;
getPageStore();
starting = false;
}
if (FileUtils.exists(dataFileName)) {
lobFilesInDirectories &= !ValueLob.existsLobFile(getDatabasePath());
......@@ -582,7 +584,7 @@ public class Database implements DataHandler {
cols.add(new Column("SQL", Value.STRING));
int headPos = 0;
if (pageStore != null) {
headPos = pageStore.getMetaTableHeadPos();
headPos = pageStore.getSystemTableHeadPos();
}
meta = mainSchema.createTable("SYS", 0, cols, persistent, false, headPos);
tableMap.put(0, meta);
......@@ -2143,31 +2145,6 @@ public class Database implements DataHandler {
return pageStore;
}
/**
* Redo a change in a table.
*
* @param tableId the object id of the table
* @param row the row
* @param add true if the record is added, false if deleted
*/
public void redo(int tableId, Row row, boolean add) throws SQLException {
TableData table = (TableData) tableMap.get(tableId);
if (add) {
table.addRow(systemSession, row);
} else {
table.removeRow(systemSession, row);
}
if (tableId == 0) {
MetaRecord m = new MetaRecord(row);
if (add) {
objectIds.set(m.getId());
m.execute(this, systemSession, eventListener);
} else {
m.undo(this, systemSession, eventListener);
}
}
}
/**
* Get the first user defined table.
*
......
......@@ -11,6 +11,7 @@ import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.message.TraceSystem;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.store.DataPage;
......@@ -36,6 +37,7 @@ public class PageBtreeIndex extends BaseIndex {
public PageBtreeIndex(TableData table, int id, String indexName, IndexColumn[] columns,
IndexType indexType, int headPos) throws SQLException {
initBaseIndex(table, id, indexName, columns, indexType);
int test;
// trace.setLevel(TraceSystem.DEBUG);
if (database.isMultiVersion()) {
int todoMvcc;
......@@ -49,22 +51,20 @@ public class PageBtreeIndex extends BaseIndex {
if (headPos == Index.EMPTY_HEAD) {
// new index
needRebuild = true;
headPos = store.allocatePage();
this.headPos = headPos = store.allocatePage();
PageBtreeLeaf root = new PageBtreeLeaf(this, headPos, Page.ROOT, store.createDataPage());
store.updateRecord(root, true, root.data);
int test;
// } else if (store.isNew()) {
// // the system table for a new database
// PageBtreeLeaf root = new PageBtreeLeaf(this,
// headPos, Page.ROOT, store.createDataPage());
// store.updateRecord(root, true, root.data);
store.addMeta(this);
} else {
rowCount = getPage(headPos).getRowCount();
this.headPos = headPos;
PageBtree root = getPage(headPos);
rowCount = root.getRowCount();
// could have been created before, but never committed
store.updateRecord(root, false, null);
int reuseKeysIfManyDeleted;
}
this.headPos = headPos;
if (trace.isDebugEnabled()) {
trace.debug("open " + rowCount);
trace.debug("opened " + getName() +" rows:"+ rowCount);
}
}
......@@ -211,7 +211,7 @@ public class PageBtreeIndex extends BaseIndex {
if (trace.isDebugEnabled()) {
trace.debug("remove");
}
int todo;
store.removeMeta(this);
}
public void truncate(Session session) throws SQLException {
......
......@@ -12,6 +12,7 @@ import org.h2.constant.ErrorCode;
import org.h2.engine.Constants;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.message.TraceSystem;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.store.DataPage;
......@@ -32,25 +33,27 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
private PageStore store;
private TableData tableData;
private int headPos;
private final int headPos;
private int lastKey;
private long rowCount;
public PageScanIndex(TableData table, int id, IndexColumn[] columns, IndexType indexType, int headPos) throws SQLException {
initBaseIndex(table, id, table.getName() + "_TABLE_SCAN", columns, indexType);
int test;
// trace.setLevel(TraceSystem.DEBUG);
if (database.isMultiVersion()) {
int todoMvcc;
}
tableData = table;
if (!database.isPersistent() || id < 0) {
this.store = database.getPageStore();
if (!database.isPersistent()) {
int todo;
this.headPos = 0;
return;
}
this.store = database.getPageStore();
if (headPos == Index.EMPTY_HEAD) {
// new table
headPos = store.allocatePage();
this.headPos = headPos = store.allocatePage();
store.addMeta(this);
PageDataLeaf root = new PageDataLeaf(this, headPos, Page.ROOT, store.createDataPage());
store.updateRecord(root, true, root.data);
......@@ -61,6 +64,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
// Page.ROOT, store.createDataPage());
// store.updateRecord(root, true, root.data);
} else {
this.headPos = headPos;
PageData root = getPage(headPos);
lastKey = root.getLastKey();
rowCount = root.getRowCount();
......@@ -68,9 +72,8 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
store.updateRecord(root, false, null);
int reuseKeysIfManyDeleted;
}
this.headPos = headPos;
if (trace.isDebugEnabled()) {
trace.debug("open " + rowCount);
trace.debug("opened " + getName() + " rows:" + rowCount);
}
table.setRowCount(rowCount);
}
......@@ -80,7 +83,9 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
}
public void add(Session session, Row row) throws SQLException {
row.setPos(++lastKey);
if (row.getPos() == 0) {
row.setPos(++lastKey);
}
if (trace.isDebugEnabled()) {
trace.debug("add " + row.getPos());
}
......@@ -217,7 +222,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
if (trace.isDebugEnabled()) {
trace.debug("remove");
}
int todo;
store.removeMeta(this);
}
public void truncate(Session session) throws SQLException {
......
......@@ -154,12 +154,11 @@ public class PageLog {
int tableId = in.readInt();
Row row = readRow(in, data);
if (!undo) {
Database db = store.getDatabase();
if (store.isSessionCommitted(sessionId, id, pos)) {
if (trace.isDebugEnabled()) {
trace.debug("log redo " + (x == ADD ? "+" : "-") + " " + row);
trace.debug("log redo " + (x == ADD ? "+" : "-") + " table:" + tableId + " " + row);
}
db.redo(tableId, row, x == ADD);
store.redo(tableId, row, x == ADD);
}
}
} else if (x == COMMIT) {
......
......@@ -10,6 +10,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import org.h2.constant.ErrorCode;
import org.h2.engine.Database;
import org.h2.engine.Session;
......@@ -23,9 +24,10 @@ import org.h2.message.Message;
import org.h2.message.Trace;
import org.h2.message.TraceSystem;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.schema.Schema;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.Table;
import org.h2.table.TableData;
import org.h2.util.Cache;
import org.h2.util.Cache2Q;
......@@ -50,7 +52,7 @@ import org.h2.value.ValueString;
* (512 - 32768, must be a power of 2)</li>
* <li>52: write version (0, otherwise the file is opened in read-only mode)</li>
* <li>53: read version (0, otherwise opening the file fails)</li>
* <li>54-57: system table root page number (usually 1)</li>
* <li>54-57: meta table root page number (usually 1)</li>
* <li>58-61: free list head page number (usually 2)</li>
* <li>62-65: log[0] head page number (usually 3)</li>
* <li>66-69: log[1] head page number (usually 4)</li>
......@@ -108,6 +110,10 @@ public class PageStore implements CacheWriter {
private static final int READ_VERSION = 0;
private static final int WRITE_VERSION = 0;
private static final int META_TYPE_SCAN_INDEX = 0;
private static final int META_TYPE_BTREE_INDEX = 1;
private static final int META_TABLE_ID = -1;
private Database database;
private final Trace trace;
private String fileName;
......@@ -118,7 +124,7 @@ public class PageStore implements CacheWriter {
private int pageSize;
private int pageSizeShift;
private int systemRootPageId;
private int metaTableRootPageId;
private int freeListRootPageId;
private int lastUsedPage;
......@@ -142,9 +148,11 @@ public class PageStore implements CacheWriter {
*/
private PageLog[] logs = new PageLog[LOG_COUNT];
private TableData pageTable;
private PageScanIndex pageIndex;
private HashMap metaObjects = new HashMap();
private Schema metaSchema;
private TableData metaTable;
private PageScanIndex metaIndex;
private HashMap metaObjects;
private int systemTableHeadPos;
/**
* Create a new page store object.
......@@ -160,7 +168,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)) {
......@@ -207,27 +215,27 @@ trace.setLevel(TraceSystem.DEBUG);
pageCount = (int) (fileLength / pageSize);
initLogs();
recover(true);
openPageIndex();
recover(false);
checkpoint();
} else {
// new
setPageSize(PAGE_SIZE_DEFAULT);
file = database.openFile(fileName, accessMode, false);
systemRootPageId = 1;
metaTableRootPageId = 1;
freeListRootPageId = 2;
pageCount = 3 + LOG_COUNT;
increaseFileSize(INCREMENT_PAGES - pageCount);
PageFreeList list = getFreeList();
getFreeList();
for (int i = 0; i < LOG_COUNT; i++) {
logRootPageIds[i] = 3 + i;
}
writeHeader();
initLogs();
openPageIndex();
openMetaIndex();
getLog().openForWriting(0);
switchLogIfPossible();
getLog().flush();
systemTableHeadPos = Index.EMPTY_HEAD;
}
lastUsedPage = getFreeList().getLastUsed() + 1;
} catch (SQLException e) {
......@@ -322,7 +330,7 @@ trace.setLevel(TraceSystem.DEBUG);
accessMode = "r";
file = database.openFile(fileName, accessMode, true);
}
systemRootPageId = page.readInt();
metaTableRootPageId = page.readInt();
freeListRootPageId = page.readInt();
for (int i = 0; i < LOG_COUNT; i++) {
logRootPageIds[i] = page.readInt();
......@@ -362,7 +370,7 @@ trace.setLevel(TraceSystem.DEBUG);
page.writeInt(pageSize);
page.writeByte((byte) WRITE_VERSION);
page.writeByte((byte) READ_VERSION);
page.writeInt(systemRootPageId);
page.writeInt(metaTableRootPageId);
page.writeInt(freeListRootPageId);
for (int i = 0; i < LOG_COUNT; i++) {
page.writeInt(logRootPageIds[i]);
......@@ -601,15 +609,6 @@ trace.setLevel(TraceSystem.DEBUG);
}
}
/**
* Get the system table root page number.
*
* @return the page number
*/
public int getSystemRootPageId() {
return systemRootPageId;
}
PageLog getLog() {
return logs[activeLog];
}
......@@ -627,7 +626,12 @@ trace.setLevel(TraceSystem.DEBUG);
* @param undo true if the undo step should be run
*/
private void recover(boolean undo) throws SQLException {
trace.debug("log recover");
if (undo) {
trace.debug("log recover");
} else {
openMetaIndex();
readMetaData();
}
try {
recoveryRunning = true;
int maxId = 0;
......@@ -665,7 +669,20 @@ trace.setLevel(TraceSystem.DEBUG);
} finally {
recoveryRunning = false;
}
trace.debug("log recover done");
if (!undo) {
PageScanIndex index = (PageScanIndex) metaObjects.get(ObjectUtils.getInteger(0));
if (index == null) {
systemTableHeadPos = Index.EMPTY_HEAD;
} else {
systemTableHeadPos = index.getHeadPos();
}
for (Iterator it = metaObjects.values().iterator(); it.hasNext();) {
Index openIndex = (Index) it.next();
openIndex.close(database.getSystemSession());
}
metaObjects = null;
trace.debug("log recover done");
}
}
/**
......@@ -740,83 +757,136 @@ trace.setLevel(TraceSystem.DEBUG);
return state.isCommitted(logId, pos);
}
public int getMetaTableHeadPos() throws SQLException {
int todo;
return 0;
/**
* Get the position of the system table head.
*
* @return the system table head
*/
public int getSystemTableHeadPos() throws SQLException {
return systemTableHeadPos;
}
/**
* Redo a change in a table.
*
* @param tableId the object id of the table
* @param row the row
* @param add true if the record is added, false if deleted
*/
void redo(int tableId, Row row, boolean add) throws SQLException {
if (tableId == META_TABLE_ID) {
if (add) {
addMeta(row);
} else {
removeMeta(row);
}
}
PageScanIndex index = (PageScanIndex) metaObjects.get(ObjectUtils.getInteger(tableId));
if (index == null) {
throw Message.throwInternalError("Table not found: " + tableId + " " + row + " " + add);
}
Table table = index.getTable();
if (add) {
table.addRow(database.getSystemSession(), row);
} else {
table.removeRow(database.getSystemSession(), row);
}
}
private void openPageIndex() throws SQLException {
private void openMetaIndex() throws SQLException {
ObjectArray cols = new ObjectArray();
cols.add(new Column("ID", Value.INT));
cols.add(new Column("TYPE", Value.INT));
cols.add(new Column("PARENT", Value.INT));
cols.add(new Column("HEAD", Value.INT));
cols.add(new Column("COLUMNS", Value.STRING));
int headPos = getSystemRootPageId();
pageTable = database.getMainSchema().createTable(
"PAGE_INDEX", 0, cols, true, false, headPos);
pageIndex = (PageScanIndex) pageTable.getScanIndex(
metaSchema = new Schema(database, 0, "", null, true);
int headPos = metaTableRootPageId;
metaTable = new TableData(metaSchema, "PAGE_INDEX",
META_TABLE_ID, cols, true, false, headPos);
metaIndex = (PageScanIndex) metaTable.getScanIndex(
database.getSystemSession());
metaObjects = new HashMap();
metaObjects.put(ObjectUtils.getInteger(-1), metaIndex);
}
private void readMetaData() throws SQLException {
Cursor cursor = pageIndex.find(database.getSystemSession(), null, null);
Cursor cursor = metaIndex.find(database.getSystemSession(), null, null);
while (cursor.next()) {
Row row = cursor.get();
int headPos = row.getValue(0).getInt();
int type = row.getValue(1).getInt();
int id = row.getValue(2).getInt();
int tableId = row.getValue(3).getInt();
String columnList = row.getValue(4).getString();
String[] columns = StringUtils.arraySplit(columnList, ',', false);
IndexType indexType = IndexType.createNonUnique(true);
Index meta;
TableData table;
if (type == 0) {
ObjectArray columnArray = new ObjectArray();
for (int i = 0; i < columns.length; i++) {
Column col = new Column("C" + i, Value.INT);
columnArray.add(col);
}
table = new TableData(database.getMainSchema(), "T" + id, id, columnArray, true, false, headPos);
} else {
PageScanIndex p = (PageScanIndex) metaObjects.get(ObjectUtils.getInteger(tableId));
table = (TableData) p.getTable();
addMeta(row);
}
}
private void removeMeta(Row row) throws SQLException {
int id = row.getValue(0).getInt();
Index index = (Index) metaObjects.remove(ObjectUtils.getInteger(id));
index.getTable().removeIndex(index);
if (index instanceof PageBtreeIndex) {
index.getSchema().remove(index);
}
}
private void addMeta(Row row) throws SQLException {
int id = row.getValue(0).getInt();
int type = row.getValue(1).getInt();
int parent = row.getValue(2).getInt();
int headPos = row.getValue(3).getInt();
String columnList = row.getValue(4).getString();
String[] columns = StringUtils.arraySplit(columnList, ',', false);
IndexType indexType = IndexType.createNonUnique(true);
Index meta;
if (trace.isDebugEnabled()) {
trace.debug("addMeta id=" + id + " type=" + type + " parent=" + parent + " columns=" + columnList);
}
if (type == META_TYPE_SCAN_INDEX) {
ObjectArray columnArray = new ObjectArray();
for (int i = 0; i < columns.length; i++) {
Column col = new Column("C" + i, Value.INT);
columnArray.add(col);
}
TableData table = new TableData(metaSchema, "T" + id, id, columnArray, true, false, headPos);
meta = table.getScanIndex(database.getSystemSession());
} else {
PageScanIndex p = (PageScanIndex) metaObjects.get(ObjectUtils.getInteger(parent));
TableData table = (TableData) p.getTable();
Column[] tableCols = table.getColumns();
Column[] cols = new Column[columns.length];
for (int i = 0; i < columns.length; i++) {
cols[i] = tableCols[Integer.parseInt(columns[i])];
}
IndexColumn[] indexColumns = IndexColumn.wrap(cols);
if (type == 0) {
meta = new PageScanIndex(table, id, indexColumns, indexType, headPos);
} else {
meta = new PageBtreeIndex(table, id, "I" + id, indexColumns, indexType, headPos);
}
metaObjects.put(ObjectUtils.getInteger(id), meta);
meta = table.addIndex(database.getSystemSession(), "I" + id, id, indexColumns, indexType, headPos, null);
}
metaObjects.put(ObjectUtils.getInteger(id), meta);
}
public void addMeta(Index index) throws SQLException {
int type = index instanceof PageScanIndex ? 0 : 1;
int type = index instanceof PageScanIndex ? META_TYPE_SCAN_INDEX : META_TYPE_BTREE_INDEX;
Column[] columns = index.getColumns();
String[] columnIndexes = new String[columns.length];
for (int i = 0; i < columns.length; i++) {
columnIndexes[i] = String.valueOf(columns[i].getColumnId());
}
String columnList = StringUtils.arrayCombine(columnIndexes, ',');
addMeta(index.getId(), type, index.getHeadPos(), index.getTable().getId(), columnList);
addMeta(index.getId(), type, index.getTable().getId(), index.getHeadPos(), columnList);
}
private void addMeta(int id, int type, int parent, int headPos, String columnList) throws SQLException {
Row row = pageTable.getTemplateRow();
Row row = metaTable.getTemplateRow();
row.setValue(0, ValueInt.get(id));
row.setValue(1, ValueInt.get(type));
row.setValue(2, ValueInt.get(parent));
row.setValue(3, ValueInt.get(headPos));
row.setValue(3, ValueString.get(columnList));
pageIndex.add(database.getSystemSession(), row);
row.setValue(4, ValueString.get(columnList));
row.setPos(id + 1);
metaIndex.add(database.getSystemSession(), row);
}
public void removeMeta(Index index) throws SQLException {
Session session = database.getSystemSession();
Row row = metaIndex.getRow(session, index.getId() + 1);
metaIndex.remove(session, row);
}
}
......@@ -239,15 +239,15 @@ public class TableData extends Table implements RecordReader {
} else {
database.addSchemaObject(session, index);
}
// Need to update, because maybe the index is rebuilt at startup,
// and so the head pos may have changed, which needs to be stored now.
// addSchemaObject doesn't update the sys table at startup
if (index.getIndexType().getPersistent() && !database.getReadOnly()
&& !database.getLog().containsInDoubtTransactions()) {
// can not save anything in the log file if it contains in-doubt transactions
if (!SysProperties.PAGE_STORE) {
// must not do this when using the page store
// because recovery is not done yet
// must not do this when using the page store
// because recovery is not done yet
if (!SysProperties.PAGE_STORE) {
// need to update, because maybe the index is rebuilt at startup,
// and so the head pos may have changed, which needs to be stored now.
// addSchemaObject doesn't update the sys table at startup
if (index.getIndexType().getPersistent() && !database.getReadOnly()
&& !database.getLog().containsInDoubtTransactions()) {
// can not save anything in the log file if it contains in-doubt transactions
database.update(session, index);
}
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论