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

new experimental page store

上级 90db2694
......@@ -5,7 +5,6 @@
* Initial Developer: H2 Group
*/
package org.h2.index;
import java.sql.SQLException;
import org.h2.constant.ErrorCode;
......@@ -13,6 +12,8 @@ import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.result.Row;
import org.h2.store.DataPageBinary;
import org.h2.store.PageStore;
import org.h2.util.IntArray;
/**
* A leaf page that contains data of one or multiple rows.
......@@ -26,7 +27,8 @@ import org.h2.store.DataPageBinary;
* The format of an overflow page is:
* <ul><li>0-3: parent page id (0 for root)
* </li><li>4-4: page type
* </li><li>only if there is overflow: 5-8: next overflow page id
* </li><li>if there is more data: 5-8: next overflow page id
* </li><li>otherwise: 5-6: remaining size
* </li><li>data
* </li></ul>
*/
......@@ -43,9 +45,14 @@ class PageDataLeaf extends PageData {
Row[] rows;
/**
* The page id of the first overflow page (0 for no overflow).
* The page id of the first overflow page (0 if no overflow).
*/
int firstOverflowPageId;
/**
* The page ids of all overflow pages (null if no overflow).
*/
int overflowPageId;
int[] overflowPageIds;
/**
* The start of the data area.
......@@ -54,6 +61,7 @@ class PageDataLeaf extends PageData {
PageDataLeaf(PageScanIndex index, int pageId, int parentPageId, DataPageBinary data) {
super(index, pageId, parentPageId, data);
start = 7;
}
void read() throws SQLException {
......@@ -64,7 +72,7 @@ class PageDataLeaf extends PageData {
keys = new int[entryCount];
rows = new Row[entryCount];
if (type == Page.TYPE_DATA_LEAF_WITH_OVERFLOW) {
overflowPageId = data.readInt();
firstOverflowPageId = data.readInt();
}
for (int i = 0; i < entryCount; i++) {
keys[i] = data.readInt();
......@@ -81,15 +89,15 @@ class PageDataLeaf extends PageData {
data.reset();
data.writeInt(parentPageId);
int type;
if (overflowPageId == 0) {
if (firstOverflowPageId == 0) {
type = Page.TYPE_DATA_LEAF;
} else {
type = Page.TYPE_DATA_LEAF_WITH_OVERFLOW;
}
data.writeByte((byte) type);
data.writeShortInt(entryCount);
if (overflowPageId != 0) {
data.writeInt(overflowPageId);
if (firstOverflowPageId != 0) {
data.writeInt(firstOverflowPageId);
}
for (int i = 0; i < entryCount; i++) {
data.writeInt(keys[i]);
......@@ -99,18 +107,39 @@ class PageDataLeaf extends PageData {
data.setPos(offsets[i]);
rows[i].write(data);
}
int pageSize = index.getPageStore().getPageSize();
if (data.length() > pageSize) {
if (overflowPageId == 0) {
PageStore store = index.getPageStore();
int pageSize = store.getPageSize();
store.writePage(pageId, data);
// don't need to write overflow if we just update the parent page id
if (data.length() > pageSize && overflowPageIds != null) {
if (firstOverflowPageId == 0) {
throw Message.getInternalError();
}
int todoWriteOverflow;
} else {
if (overflowPageId != 0) {
throw Message.getInternalError();
DataPageBinary overflow = store.createDataPage();
int parent = pageId;
int pos = pageSize;
int remaining = data.length() - pageSize;
for (int i = 0; i < overflowPageIds.length; i++) {
overflow.reset();
overflow.writeInt(parent);
int size;
if (remaining > pageSize - 7) {
overflow.writeByte((byte) Page.TYPE_DATA_OVERFLOW_WITH_MORE);
overflow.writeInt(overflowPageIds[i + 1]);
size = pageSize - overflow.length();
} else {
overflow.writeByte((byte) Page.TYPE_DATA_OVERFLOW_LAST);
size = remaining;
overflow.writeShortInt(remaining);
}
overflow.write(data.getBytes(), pos, size);
remaining -= size;
pos += size;
int id = overflowPageIds[i];
store.writePage(id, overflow);
parent = id;
}
}
index.getPageStore().writePage(pageId, data);
}
/**
......@@ -121,7 +150,12 @@ class PageDataLeaf extends PageData {
*/
int addRow(Row row) throws SQLException {
int rowLength = row.getByteCount(data);
int last = entryCount == 0 ? index.getPageStore().getPageSize() : offsets[entryCount - 1];
int pageSize = index.getPageStore().getPageSize();
int last = entryCount == 0 ? pageSize : offsets[entryCount - 1];
if (entryCount > 0 && last - rowLength < start + 6) {
int todoSplitAtLastInsertionPoint;
return (entryCount / 2) + 1;
}
int offset = last - rowLength;
int[] newOffsets = new int[entryCount + 1];
int[] newKeys = new int[entryCount + 1];
......@@ -149,13 +183,27 @@ class PageDataLeaf extends PageData {
keys = newKeys;
rows = newRows;
if (offset < start) {
if (entryCount > 0) {
int todoSplitAtLastInsertionPoint;
return entryCount / 2;
if (entryCount > 1) {
throw Message.getInternalError();
}
offset = start + 6;
overflowPageId = index.getPageStore().allocatePage();
int todoWriteOverflow;
// need to write the overflow page id
start += 4;
int remaining = rowLength - (pageSize - start);
// fix offset
offset = start;
offsets[x] = offset;
IntArray array = new IntArray();
do {
int next = index.getPageStore().allocatePage();
array.add(next);
remaining -= pageSize - 7;
if (remaining > 0) {
remaining += 2;
}
} while (remaining > 0);
overflowPageIds = new int[array.size()];
array.toArray(overflowPageIds);
firstOverflowPageId = overflowPageIds[0];
}
write();
return 0;
......@@ -188,16 +236,40 @@ class PageDataLeaf extends PageData {
/**
* Get the row at the given index.
*
* @param index the index
* @param at the index
* @return the row
*/
Row getRowAt(int index) throws SQLException {
Row r = rows[index];
Row getRowAt(int at) throws SQLException {
if (at >= rows.length) {
int test;
System.out.println("test");
}
Row r = rows[at];
if (r == null) {
data.setPos(offsets[index]);
r = this.index.readRow(data);
r.setPos(keys[index]);
rows[index] = r;
if (firstOverflowPageId != 0) {
PageStore store = index.getPageStore();
int pageSize = store.getPageSize();
data.setPos(pageSize);
int next = firstOverflowPageId;
while (true) {
DataPageBinary page = store.readPage(next);
page.setPos(4);
int type = page.readByte();
if (type == Page.TYPE_DATA_OVERFLOW_LAST) {
int size = page.readShortInt();
data.write(page.getBytes(), 7, size);
break;
} else {
next = page.readInt();
int size = pageSize - 9;
data.write(page.getBytes(), 9, size);
}
}
}
data.setPos(offsets[at]);
r = index.readRow(data);
r.setPos(keys[at]);
rows[at] = r;
}
return r;
}
......@@ -252,9 +324,6 @@ class PageDataLeaf extends PageData {
Row getRow(Session session, int key) throws SQLException {
int index = find(key);
if(index >= keys.length) {
System.out.println("stop");
}
return getRowAt(index);
}
......
......@@ -79,23 +79,25 @@ class PageDataNode extends PageData {
}
int addRow(Row row) throws SQLException {
int x = find(row.getPos());
PageData page = index.getPage(childPageIds[x]);
int splitPoint = page.addRow(row);
if (splitPoint == 0) {
return 0;
}
int pivot = page.getKey(splitPoint);
PageData page2 = page.split(splitPoint);
page.write();
page2.write();
addChild(x, page2.getPageId(), pivot);
int maxEntries = (index.getPageStore().getPageSize() - 11) / 8;
if (entryCount >= maxEntries) {
int todoSplitAtLastInsertionPoint;
return entryCount / 2;
while (true) {
int x = find(row.getPos());
PageData page = index.getPage(childPageIds[x]);
int splitPoint = page.addRow(row);
if (splitPoint == 0) {
break;
}
int pivot = page.getKey(splitPoint - 1);
PageData page2 = page.split(splitPoint);
page.write();
page2.write();
addChild(x, page2.getPageId(), pivot);
int maxEntries = (index.getPageStore().getPageSize() - 11) / 8;
if (entryCount >= maxEntries) {
int todoSplitAtLastInsertionPoint;
return entryCount / 2;
}
write();
}
write();
return 0;
}
......@@ -107,7 +109,6 @@ class PageDataNode extends PageData {
PageData split(int splitPoint) throws SQLException {
int newPageId = index.getPageStore().allocatePage();
PageDataNode p2 = new PageDataNode(index, newPageId, parentPageId, index.getPageStore().createDataPage());
splitPoint++;
int firstChild = childPageIds[splitPoint];
for (int i = splitPoint; i < entryCount;) {
p2.addChild(p2.entryCount, childPageIds[splitPoint + 1], keys[splitPoint]);
......@@ -175,7 +176,7 @@ class PageDataNode extends PageData {
return null;
}
PageDataNode next = (PageDataNode) index.getPage(parentPageId);
return next.getNextPage(keys[entryCount - 1]);
return next.getNextPage(key);
}
PageData page = index.getPage(childPageIds[i]);
return page.getFirstLeaf();
......@@ -202,7 +203,6 @@ class PageDataNode extends PageData {
}
boolean remove(int key) throws SQLException {
int todo;
int at = find(key);
// merge is not implemented to allow concurrent usage of btrees
// TODO maybe implement merge
......
......@@ -30,14 +30,15 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
private TableData tableData;
private int headPos;
// TODO cache the row count of all children (row count, group count)
// TODO remember last page with deleted keys (in the root page?),
// and chain such pages
// TODO order pages so that searching for a key
// doesn't seek backwards in the file
// TODO use an undo log and maybe redo log (for performance)
// TODO file position, content checksums
private int nextKey;
// TODO remember the row count (in the root page?)
public PageScanIndex(TableData table, int id, IndexColumn[] columns, IndexType indexType, int headPos) throws SQLException {
initBaseIndex(table, id, table.getName() + "_TABLE_SCAN", columns, indexType);
if (database.isMultiVersion()) {
......@@ -64,10 +65,13 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
public void add(Session session, Row row) throws SQLException {
row.setPos((int) rowCount);
PageData root = getPage(headPos);
int splitPoint = root.addRow(row);
if (splitPoint != 0) {
int pivot = root.getKey(splitPoint);
while (true) {
PageData root = getPage(headPos);
int splitPoint = root.addRow(row);
if (splitPoint == 0) {
break;
}
int pivot = root.getKey(splitPoint - 1);
PageData page1 = root;
PageData page2 = root.split(splitPoint);
int rootPageId = root.getPageId();
......@@ -159,6 +163,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
public void truncate(Session session) throws SQLException {
int invalidateRowCount;
int freePages;
PageDataLeaf root = new PageDataLeaf(this, headPos, Page.ROOT, store.createDataPage());
root.write();
rowCount = 0;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论