提交 6be4766c authored 作者: Thomas Mueller's avatar Thomas Mueller

New experimental page store.

上级 36ed8325
......@@ -11,7 +11,6 @@ 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;
......@@ -39,16 +38,11 @@ public class PageBtreeIndex extends BaseIndex {
public PageBtreeIndex(TableData table, int id, String indexName, IndexColumn[] columns,
IndexType indexType, int headPos, Session session) throws SQLException {
initBaseIndex(table, id, indexName, columns, indexType);
int test;
// trace.setLevel(TraceSystem.DEBUG);
if (database.isMultiVersion()) {
int todoMvcc;
}
// trace.setLevel(TraceSystem.DEBUG);
tableData = table;
if (!database.isPersistent() || id < 0) {
int todo;
this.headPos = 0;
return;
throw Message.throwInternalError("" + indexName);
}
this.store = database.getPageStore();
if (headPos == Index.EMPTY_HEAD) {
......@@ -73,7 +67,6 @@ public class PageBtreeIndex extends BaseIndex {
// TODO test if really required
store.updateRecord(root, false, null);
}
int reuseKeysIfManyDeleted;
}
if (trace.isDebugEnabled()) {
trace.debug("opened " + getName() +" rows:"+ rowCount);
......@@ -239,16 +232,14 @@ public class PageBtreeIndex extends BaseIndex {
}
}
}
int invalidateRowCount;
// TODO invalidate row count
// setChanged(session);
if (rowCount == 1) {
int todoMaybeImprove;
removeAllRows();
} else {
PageBtree root = getPage(headPos);
root.remove(row);
rowCount--;
int todoReuseKeys;
}
}
......@@ -322,7 +313,7 @@ public class PageBtreeIndex extends BaseIndex {
if (trace.isDebugEnabled()) {
trace.debug("close");
}
int writeRowCount;
// TODO write the row count
}
/**
......
......@@ -67,7 +67,6 @@ class PageBtreeLeaf extends PageBtree {
int last = entryCount == 0 ? pageSize : offsets[entryCount - 1];
if (last - rowLength < start + OFFSET_LENGTH) {
if (entryCount > 1) {
int todoSplitAtLastInsertionPoint;
return (entryCount / 2) + 1;
}
onlyPosition = true;
......
......@@ -148,10 +148,6 @@ abstract class PageData extends Record {
remapChildren();
}
int getPageId() {
return getPos();
}
/**
* Get the last key of a page.
*
......
......@@ -13,7 +13,6 @@ import org.h2.message.Message;
import org.h2.result.Row;
import org.h2.store.DataPage;
import org.h2.store.PageStore;
import org.h2.store.Record;
/**
* A leaf page that contains data of one or multiple rows.
......@@ -63,7 +62,7 @@ class PageDataLeaf extends PageData {
int tableId = data.readInt();
if (tableId != index.getId()) {
throw Message.getSQLException(ErrorCode.FILE_CORRUPTED_1,
"page:" + getPageId() + " expected table:" + index.getId() +
"page:" + getPos() + " expected table:" + index.getId() +
" got:" + tableId + " type:" + type);
}
entryCount = data.readShortInt();
......@@ -212,17 +211,7 @@ class PageDataLeaf extends PageData {
int offset = pageSize;
data.setPos(pageSize);
do {
Record record = store.getRecord(next);
PageDataLeafOverflow page;
if (record == null) {
DataPage data = store.readPage(next);
page = new PageDataLeafOverflow(this, next, data, offset);
} else {
if (!(record instanceof PageDataLeafOverflow)) {
throw Message.getInternalError("page:"+ next + " " + record, null);
}
page = (PageDataLeafOverflow) record;
}
PageDataLeafOverflow page = index.getPageOverflow(next, this, offset);
next = page.readInto(data);
} while (next != 0);
}
......@@ -249,7 +238,7 @@ class PageDataLeaf extends PageData {
}
int getLastKey() throws SQLException {
int todoRemove;
// TODO re-use keys, but remove this mechanism
if (entryCount == 0) {
return 0;
}
......@@ -268,17 +257,13 @@ class PageDataLeaf extends PageData {
return this;
}
protected void remapChildren() {
protected void remapChildren() throws SQLException {
if (firstOverflowPageId == 0) {
return;
}
int testIfReallyNotRequired;
// PageStore store = index.getPageStore();
// store.updateRecord(firstOverflowPageId);
// DataPage overflow = store.readPage(firstOverflowPageId);
// overflow.reset();
// overflow.writeInt(getPos());
// store.writePage(firstOverflowPageId, overflow);
PageDataLeafOverflow overflow = index.getPageOverflow(firstOverflowPageId, this, 0);
overflow.setParent(getPos());
index.getPageStore().updateRecord(overflow, true, null);
}
boolean remove(int key) throws SQLException {
......@@ -299,17 +284,7 @@ class PageDataLeaf extends PageData {
PageStore store = index.getPageStore();
int next = firstOverflowPageId;
do {
Record record = store.getRecord(next);
PageDataLeafOverflow page;
if (record == null) {
DataPage data = store.readPage(next);
page = new PageDataLeafOverflow(this, next, data, 0);
} else {
if (!(record instanceof PageDataLeafOverflow)) {
throw Message.getInternalError("page:"+ next + " " + record, null);
}
page = (PageDataLeafOverflow) record;
}
PageDataLeafOverflow page = index.getPageOverflow(next, this, 0);
store.freePage(next, false, null);
next = page.getNextOverflow();
} while (next != 0);
......
......@@ -8,7 +8,6 @@ package org.h2.index;
import java.sql.SQLException;
import org.h2.constant.ErrorCode;
import org.h2.jdbc.JdbcSQLException;
import org.h2.message.Message;
import org.h2.store.DataPage;
import org.h2.store.PageStore;
......@@ -41,22 +40,22 @@ public class PageDataLeafOverflow extends Record {
/**
* The page type.
*/
private final int type;
private int type;
/**
* The previous page (overflow or leaf).
* The parent page (overflow or leaf).
*/
private final int previousPage;
private int parentPage;
/**
* The next overflow page, or 0.
*/
private final int nextPage;
private int nextPage;
/**
* The number of content bytes.
*/
private final int size;
private int size;
/**
* The first content byte starts at the given position
......@@ -70,18 +69,32 @@ public class PageDataLeafOverflow extends Record {
this.leaf = leaf;
setPos(pageId);
this.type = type;
this.previousPage = previous;
this.parentPage = previous;
this.nextPage = next;
this.offset = offset;
this.size = size;
}
public PageDataLeafOverflow(PageDataLeaf leaf, int pageId, DataPage data, int offset) throws JdbcSQLException {
/**
* Create an object from the given data page.
*
* @param leaf the leaf page
* @param pageId the page id
* @param data the data page
* @param offset the offset
*/
public PageDataLeafOverflow(PageDataLeaf leaf, int pageId, DataPage data, int offset) {
this.leaf = leaf;
setPos(pageId);
this.data = data;
this.offset = offset;
previousPage = data.readInt();
}
/**
* Read the page.
*/
void read() throws SQLException {
parentPage = data.readInt();
type = data.readByte();
if (type == (Page.TYPE_DATA_OVERFLOW | Page.FLAG_LAST)) {
size = data.readShortInt();
......@@ -121,7 +134,7 @@ public class PageDataLeafOverflow extends Record {
PageStore store = leaf.getPageStore();
DataPage overflow = store.createDataPage();
DataPage data = leaf.getDataPage();
overflow.writeInt(previousPage);
overflow.writeInt(parentPage);
overflow.writeByte((byte) type);
if (type == Page.TYPE_DATA_OVERFLOW) {
overflow.writeInt(nextPage);
......@@ -133,7 +146,7 @@ public class PageDataLeafOverflow extends Record {
}
public String toString() {
return "page[" + getPos() + "] data leaf overflow prev:" + previousPage + " next:" + nextPage;
return "page[" + getPos() + "] data leaf overflow parent:" + parentPage + " next:" + nextPage;
}
/**
......@@ -145,4 +158,12 @@ public class PageDataLeafOverflow extends Record {
return leaf.getMemorySize();
}
int getParent() {
return parentPage;
}
void setParent(int parent) {
this.parentPage = parent;
}
}
......@@ -93,7 +93,7 @@ class PageDataNode extends PageData {
PageData page2 = page.split(splitPoint);
index.getPageStore().updateRecord(page, true, page.data);
index.getPageStore().updateRecord(page2, true, page2.data);
addChild(x, page2.getPageId(), pivot);
addChild(x, page2.getPos(), pivot);
index.getPageStore().updateRecord(this, true, data);
}
updateRowCount(1);
......@@ -148,7 +148,7 @@ class PageDataNode extends PageData {
*/
void init(PageData page1, int pivot, PageData page2) {
entryCount = 1;
childPageIds = new int[] { page1.getPageId(), page2.getPageId() };
childPageIds = new int[] { page1.getPos(), page2.getPos() };
keys = new int[] { pivot };
check();
}
......@@ -193,7 +193,7 @@ class PageDataNode extends PageData {
return false;
}
// this child is now empty
index.getPageStore().freePage(page.getPageId(), true, page.data);
index.getPageStore().freePage(page.getPos(), true, page.data);
if (entryCount < 1) {
// no more children - this page is empty as well
return true;
......@@ -224,7 +224,7 @@ class PageDataNode extends PageData {
for (int child : childPageIds) {
PageData page = index.getPage(child, getPos());
if (getPos() == page.getPos()) {
throw Message.throwInternalError("Page it its own child: " + getPageId());
throw Message.throwInternalError("Page it its own child: " + getPos());
}
count += page.getRowCount();
}
......
......@@ -19,7 +19,6 @@ import org.h2.engine.Constants;
import org.h2.engine.Session;
import org.h2.log.UndoLogRecord;
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;
......@@ -50,8 +49,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
public PageScanIndex(TableData table, int id, IndexColumn[] columns, IndexType indexType, int headPos, Session session) throws SQLException {
initBaseIndex(table, id, table.getName() + "_TABLE_SCAN", columns, indexType);
int test;
// trace.setLevel(TraceSystem.DEBUG);
// trace.setLevel(TraceSystem.DEBUG);
if (database.isMultiVersion()) {
sessionRowCount = New.hashMap();
isMultiVersion = true;
......@@ -59,9 +57,8 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
tableData = table;
this.store = database.getPageStore();
if (!database.isPersistent()) {
int todo;
this.headPos = 0;
return;
throw Message.throwInternalError(table.getName());
}
if (headPos == Index.EMPTY_HEAD) {
// new table
......@@ -82,7 +79,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
// TODO check if really required
store.updateRecord(root, false, null);
}
int reuseKeysIfManyDeleted;
// TODO re-use keys after many rows are deleted
}
if (trace.isDebugEnabled()) {
trace.debug("opened " + getName() + " rows:" + rowCount);
......@@ -127,7 +124,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
int pivot = root.getKey(splitPoint - 1);
PageData page1 = root;
PageData page2 = root.split(splitPoint);
int rootPageId = root.getPageId();
int rootPageId = root.getPos();
int id = store.allocatePage();
page1.setPageId(id);
page1.setParentPageId(headPos);
......@@ -154,6 +151,25 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
store.logAddOrRemoveRow(session, tableData.getId(), row, true);
}
/**
* Read an overflow page page.
*
* @param id the page id
* @param leaf the leaf page
* @return the page
*/
PageDataLeafOverflow getPageOverflow(int id, PageDataLeaf leaf, int offset) throws SQLException {
Record rec = store.getRecord(id);
if (rec != null) {
return (PageDataLeafOverflow) rec;
}
DataPage data = store.readPage(id);
data.reset();
PageDataLeafOverflow result = new PageDataLeafOverflow(leaf, id, data, offset);
result.read();
return result;
}
/**
* Read the given page.
*
......@@ -233,20 +249,16 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
}
}
}
int invalidateRowCount;
// TODO invalidate the row count
// setChanged(session);
if (rowCount == 1) {
int todoMaybeImprove;
removeAllRows();
} else {
int key = row.getPos();
PageData root = getPage(headPos, 0);
root.remove(key);
rowCount--;
int todoReuseKeys;
// if (key == lastKey - 1) {
// lastKey--;
// }
// TODO re-use keys
}
if (database.isMultiVersion()) {
// if storage is null, the delete flag is not yet set
......@@ -355,9 +367,9 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
if (sessionRowCount != null) {
sessionRowCount.clear();
}
int todoWhyNotClose;
// store = null;
int writeRowCount;
// can not close the index because it might get used afterwards,
// for example after running recovery
// TODO write the row count
}
Iterator<Row> getDelta() {
......
......@@ -149,8 +149,8 @@ public class PageLog {
if (store.getRecord(firstTrunkPage) != null) {
// if the page is in use, don't free it
// TODO cleanup - this is a hack
int todoCleanup;
break;
// break;
throw Message.throwInternalError("" + store.getRecord(firstTrunkPage));
}
PageStreamTrunk t = new PageStreamTrunk(store, this.firstTrunkPage);
try {
......@@ -315,7 +315,7 @@ public class PageLog {
for (int i = 0; i < columnCount; i++) {
values[i] = data.readValue();
}
int todoTableDataReadRowWithMemory;
// TODO maybe calculate the memory usage
Row row = new Row(values, 0);
row.setPos(pos);
return row;
......
......@@ -24,7 +24,6 @@ import org.h2.log.InDoubtTransaction;
import org.h2.log.LogSystem;
import org.h2.message.Message;
import org.h2.message.Trace;
import org.h2.message.TraceSystem;
import org.h2.result.Row;
import org.h2.schema.Schema;
import org.h2.table.Column;
......@@ -201,8 +200,7 @@ public class PageStore implements CacheWriter {
this.accessMode = accessMode;
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();
this.cache = CacheLRU.getCache(this, cacheType, cacheSize);
......@@ -975,32 +973,6 @@ public class PageStore implements CacheWriter {
}
}
private void updateChecksum(byte[] d, int pos) {
int ps = pageSize;
int s1 = 255 + (d[0] & 255), s2 = 255 + s1;
s2 += s1 += d[1] & 255;
s2 += s1 += d[(ps >> 1) - 1] & 255;
s2 += s1 += d[ps >> 1] & 255;
s2 += s1 += d[ps - 2] & 255;
s2 += s1 += d[ps - 1] & 255;
d[5] = (byte) (((s1 & 255) + (s1 >> 8)) ^ pos);
d[6] = (byte) (((s2 & 255) + (s2 >> 8)) ^ (pos >> 8));
}
private void verifyChecksum(byte[] d, int pos) throws SQLException {
int ps = pageSize;
int s1 = 255 + (d[0] & 255), s2 = 255 + s1;
s2 += s1 += d[1] & 255;
s2 += s1 += d[(ps >> 1) - 1] & 255;
s2 += s1 += d[ps >> 1] & 255;
s2 += s1 += d[ps - 2] & 255;
s2 += s1 += d[ps - 1] & 255;
if (d[5] != (byte) (((s1 & 255) + (s1 >> 8)) ^ pos)
|| d[6] != (byte) (((s2 & 255) + (s2 >> 8)) ^ (pos >> 8))) {
throw Message.getSQLException(ErrorCode.FILE_CORRUPTED_1, "wrong checksum");
}
}
/**
* Set the maximum log file size in megabytes.
*
......@@ -1052,5 +1024,31 @@ public class PageStore implements CacheWriter {
}
}
// TODO implement checksum
// private void updateChecksum(byte[] d, int pos) {
// int ps = pageSize;
// int s1 = 255 + (d[0] & 255), s2 = 255 + s1;
// s2 += s1 += d[1] & 255;
// s2 += s1 += d[(ps >> 1) - 1] & 255;
// s2 += s1 += d[ps >> 1] & 255;
// s2 += s1 += d[ps - 2] & 255;
// s2 += s1 += d[ps - 1] & 255;
// d[5] = (byte) (((s1 & 255) + (s1 >> 8)) ^ pos);
// d[6] = (byte) (((s2 & 255) + (s2 >> 8)) ^ (pos >> 8));
// }
//
// private void verifyChecksum(byte[] d, int pos) throws SQLException {
// int ps = pageSize;
// int s1 = 255 + (d[0] & 255), s2 = 255 + s1;
// s2 += s1 += d[1] & 255;
// s2 += s1 += d[(ps >> 1) - 1] & 255;
// s2 += s1 += d[ps >> 1] & 255;
// s2 += s1 += d[ps - 2] & 255;
// s2 += s1 += d[ps - 1] & 255;
// if (d[5] != (byte) (((s1 & 255) + (s1 >> 8)) ^ pos)
// || d[6] != (byte) (((s2 & 255) + (s2 >> 8)) ^ (pos >> 8))) {
// throw Message.getSQLException(ErrorCode.FILE_CORRUPTED_1, "wrong checksum");
// }
// }
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论