提交 796e386a authored 作者: Thomas Mueller's avatar Thomas Mueller

New experimental page store.

上级 69f5efd2
...@@ -56,6 +56,11 @@ abstract class PageBtree extends Record { ...@@ -56,6 +56,11 @@ abstract class PageBtree extends Record {
*/ */
protected int start; protected int start;
/**
* If only the position of the row is stored in the page
*/
protected boolean onlyPosition;
/** /**
* If the page was already written to the buffer. * If the page was already written to the buffer.
*/ */
...@@ -123,13 +128,13 @@ abstract class PageBtree extends Record { ...@@ -123,13 +128,13 @@ abstract class PageBtree extends Record {
abstract void read() throws SQLException; abstract void read() throws SQLException;
/** /**
* Add a row. * Try to add a row.
* *
* @param row the row * @param row the row
* @return 0 if successful, or the split position if the page needs to be * @return 0 if successful, or the split position if the page needs to be
* split * split
*/ */
abstract int addRow(SearchRow row) throws SQLException; abstract int addRowTry(SearchRow row) throws SQLException;
/** /**
* Find the first row. * Find the first row.
...@@ -147,13 +152,9 @@ abstract class PageBtree extends Record { ...@@ -147,13 +152,9 @@ abstract class PageBtree extends Record {
* @return the row * @return the row
*/ */
SearchRow getRow(int at) throws SQLException { SearchRow getRow(int at) throws SQLException {
int test;
if (at < 0) {
System.out.println("stop");
}
SearchRow row = rows[at]; SearchRow row = rows[at];
if (row == null) { if (row == null) {
row = index.readRow(data, offsets[at]); row = index.readRow(data, offsets[at], onlyPosition);
rows[at] = row; rows[at] = row;
} }
return row; return row;
......
...@@ -77,7 +77,7 @@ public class PageBtreeCursor implements Cursor { ...@@ -77,7 +77,7 @@ public class PageBtreeCursor implements Cursor {
return true; return true;
} }
public boolean previous() throws SQLException { public boolean previous() {
i--; i--;
int todo; int todo;
return true; return true;
......
...@@ -11,7 +11,6 @@ import org.h2.constant.ErrorCode; ...@@ -11,7 +11,6 @@ import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.message.TraceSystem;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.result.SearchRow; import org.h2.result.SearchRow;
import org.h2.store.DataPage; import org.h2.store.DataPage;
...@@ -94,7 +93,7 @@ public class PageBtreeIndex extends BaseIndex { ...@@ -94,7 +93,7 @@ public class PageBtreeIndex extends BaseIndex {
} }
while (true) { while (true) {
PageBtree root = getPage(headPos); PageBtree root = getPage(headPos);
int splitPoint = root.addRow(row); int splitPoint = root.addRowTry(row);
if (splitPoint == 0) { if (splitPoint == 0) {
break; break;
} }
...@@ -275,7 +274,7 @@ public class PageBtreeIndex extends BaseIndex { ...@@ -275,7 +274,7 @@ public class PageBtreeIndex extends BaseIndex {
return rowCount; return rowCount;
} }
public void close(Session session) throws SQLException { public void close(Session session) {
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
trace.debug("close"); trace.debug("close");
} }
...@@ -291,10 +290,14 @@ public class PageBtreeIndex extends BaseIndex { ...@@ -291,10 +290,14 @@ public class PageBtreeIndex extends BaseIndex {
* @param offset the offset * @param offset the offset
* @return the row * @return the row
*/ */
SearchRow readRow(DataPage data, int offset) throws SQLException { SearchRow readRow(DataPage data, int offset, boolean onlyPosition) throws SQLException {
data.setPos(offset); data.setPos(offset);
int pos = data.readInt();
if (onlyPosition) {
return tableData.getRow(null, pos);
}
SearchRow row = table.getTemplateSimpleRow(columns.length == 1); SearchRow row = table.getTemplateSimpleRow(columns.length == 1);
row.setPos(data.readInt()); row.setPos(pos);
for (Column col : columns) { for (Column col : columns) {
int idx = col.getColumnId(); int idx = col.getColumnId();
row.setValue(idx, data.readValue()); row.setValue(idx, data.readValue());
...@@ -307,18 +310,17 @@ public class PageBtreeIndex extends BaseIndex { ...@@ -307,18 +310,17 @@ public class PageBtreeIndex extends BaseIndex {
* *
* @param data the data * @param data the data
* @param offset the offset * @param offset the offset
* @param onlyPosition whether only the position of the row is stored
* @param row the row to write * @param row the row to write
*/ */
void writeRow(DataPage data, int offset, SearchRow row) throws SQLException { void writeRow(DataPage data, int offset, SearchRow row, boolean onlyPosition) throws SQLException {
if (offset < 0) {
int test;
System.out.println("stop");
}
data.setPos(offset); data.setPos(offset);
data.writeInt(row.getPos()); data.writeInt(row.getPos());
for (Column col : columns) { if (!onlyPosition) {
int idx = col.getColumnId(); for (Column col : columns) {
data.writeValue(row.getValue(idx)); int idx = col.getColumnId();
data.writeValue(row.getValue(idx));
}
} }
} }
...@@ -327,13 +329,16 @@ if (offset < 0) { ...@@ -327,13 +329,16 @@ if (offset < 0) {
* *
* @param dummy a dummy data page to calculate the size * @param dummy a dummy data page to calculate the size
* @param row the row * @param row the row
* @param onlyPosition whether only the position of the row is stored
* @return the number of bytes * @return the number of bytes
*/ */
int getRowSize(DataPage dummy, SearchRow row) throws SQLException { int getRowSize(DataPage dummy, SearchRow row, boolean onlyPosition) throws SQLException {
int rowsize = DataPage.LENGTH_INT; int rowsize = DataPage.LENGTH_INT;
for (Column col : columns) { if (!onlyPosition) {
Value v = row.getValue(col.getColumnId()); for (Column col : columns) {
rowsize += dummy.getValueLen(v); Value v = row.getValue(col.getColumnId());
rowsize += dummy.getValueLen(v);
}
} }
return rowsize; return rowsize;
} }
......
...@@ -14,30 +14,30 @@ import org.h2.store.DataPage; ...@@ -14,30 +14,30 @@ import org.h2.store.DataPage;
import org.h2.store.PageStore; import org.h2.store.PageStore;
/** /**
* A leaf page that contains index data. * A b-tree leaf page that contains index data.
* Format: * Format:
* <ul><li>0-3: parent page id (0 for root) * <ul><li>0-3: parent page id (0 for root)
* </li><li>4-4: page type * </li><li>4-4: page type
* </li><li>5-8: table id * </li><li>5-8: table id
* </li><li>9-10: entry count * </li><li>9-10: entry count
* </li><li>overflow: 11-14: the row key
* </li><li>11-: list of key / offset pairs (4 bytes key, 2 bytes offset) * </li><li>11-: list of key / offset pairs (4 bytes key, 2 bytes offset)
* </li><li>data * </li><li>data
* </li></ul> * </li></ul>
*/ */
class PageBtreeLeaf extends PageBtree { class PageBtreeLeaf extends PageBtree {
private static final int KEY_OFFSET_PAIR_LENGTH = 6; private static final int OFFSET_LENGTH = 2;
private static final int KEY_OFFSET_PAIR_START = 11; private static final int OFFSET_START = 11;
PageBtreeLeaf(PageBtreeIndex index, int pageId, int parentPageId, DataPage data) { PageBtreeLeaf(PageBtreeIndex index, int pageId, int parentPageId, DataPage data) {
super(index, pageId, parentPageId, data); super(index, pageId, parentPageId, data);
start = KEY_OFFSET_PAIR_START; start = OFFSET_START;
} }
void read() throws SQLException { void read() throws SQLException {
data.setPos(4); data.setPos(4);
data.readByte(); int type = data.readByte();
onlyPosition = (type & Page.FLAG_LAST) == 0;
int tableId = data.readInt(); int tableId = data.readInt();
if (tableId != index.getId()) { if (tableId != index.getId()) {
throw Message.getSQLException(ErrorCode.FILE_CORRUPTED_1, throw Message.getSQLException(ErrorCode.FILE_CORRUPTED_1,
...@@ -60,13 +60,17 @@ class PageBtreeLeaf extends PageBtree { ...@@ -60,13 +60,17 @@ class PageBtreeLeaf extends PageBtree {
* @param row the now to add * @param row the now to add
* @return the split point of this page, or 0 if no split is required * @return the split point of this page, or 0 if no split is required
*/ */
int addRow(SearchRow row) throws SQLException { int addRowTry(SearchRow row) throws SQLException {
int rowLength = index.getRowSize(data, row); int rowLength = index.getRowSize(data, row, onlyPosition);
int pageSize = index.getPageStore().getPageSize(); int pageSize = index.getPageStore().getPageSize();
int last = entryCount == 0 ? pageSize : offsets[entryCount - 1]; int last = entryCount == 0 ? pageSize : offsets[entryCount - 1];
if (entryCount > 0 && last - rowLength < start + KEY_OFFSET_PAIR_LENGTH) { if (last - rowLength < start + OFFSET_LENGTH) {
int todoSplitAtLastInsertionPoint; if (entryCount > 0) {
return (entryCount / 2) + 1; int todoSplitAtLastInsertionPoint;
return (entryCount / 2) + 1;
}
onlyPosition = true;
rowLength = index.getRowSize(data, row, onlyPosition);
} }
written = false; written = false;
int offset = last - rowLength; int offset = last - rowLength;
...@@ -89,23 +93,12 @@ class PageBtreeLeaf extends PageBtree { ...@@ -89,23 +93,12 @@ class PageBtreeLeaf extends PageBtree {
} }
} }
entryCount++; entryCount++;
start += KEY_OFFSET_PAIR_LENGTH; start += OFFSET_LENGTH;
newOffsets[x] = offset; newOffsets[x] = offset;
newRows[x] = row; newRows[x] = row;
offsets = newOffsets; offsets = newOffsets;
rows = newRows; rows = newRows;
index.getPageStore().updateRecord(this, true, data); index.getPageStore().updateRecord(this, true, data);
if (offset < start) {
if (entryCount > 1) {
Message.throwInternalError();
}
// need to write the overflow page id
start += 4;
int remaining = rowLength - (pageSize - start);
// fix offset
offset = start;
offsets[x] = offset;
}
return 0; return 0;
} }
...@@ -126,7 +119,7 @@ class PageBtreeLeaf extends PageBtree { ...@@ -126,7 +119,7 @@ class PageBtreeLeaf extends PageBtree {
newOffsets[j] = offsets[j + 1] + rowLength; newOffsets[j] = offsets[j + 1] + rowLength;
} }
System.arraycopy(rows, i + 1, newRows, i, entryCount - i); System.arraycopy(rows, i + 1, newRows, i, entryCount - i);
start -= KEY_OFFSET_PAIR_LENGTH; start -= OFFSET_LENGTH;
offsets = newOffsets; offsets = newOffsets;
rows = newRows; rows = newRows;
} }
...@@ -139,7 +132,7 @@ class PageBtreeLeaf extends PageBtree { ...@@ -139,7 +132,7 @@ class PageBtreeLeaf extends PageBtree {
int newPageId = index.getPageStore().allocatePage(); int newPageId = index.getPageStore().allocatePage();
PageBtreeLeaf p2 = new PageBtreeLeaf(index, newPageId, parentPageId, index.getPageStore().createDataPage()); PageBtreeLeaf p2 = new PageBtreeLeaf(index, newPageId, parentPageId, index.getPageStore().createDataPage());
for (int i = splitPoint; i < entryCount;) { for (int i = splitPoint; i < entryCount;) {
p2.addRow(getRow(splitPoint)); p2.addRowTry(getRow(splitPoint));
removeRow(splitPoint); removeRow(splitPoint);
} }
return p2; return p2;
...@@ -190,14 +183,14 @@ class PageBtreeLeaf extends PageBtree { ...@@ -190,14 +183,14 @@ class PageBtreeLeaf extends PageBtree {
readAllRows(); readAllRows();
data.reset(); data.reset();
data.writeInt(parentPageId); data.writeInt(parentPageId);
data.writeByte((byte) Page.TYPE_BTREE_LEAF); data.writeByte((byte) (Page.TYPE_BTREE_LEAF | (onlyPosition ? 0 : Page.FLAG_LAST)));
data.writeInt(index.getId()); data.writeInt(index.getId());
data.writeShortInt(entryCount); data.writeShortInt(entryCount);
for (int i = 0; i < entryCount; i++) { for (int i = 0; i < entryCount; i++) {
data.writeShortInt(offsets[i]); data.writeShortInt(offsets[i]);
} }
for (int i = 0; i < entryCount; i++) { for (int i = 0; i < entryCount; i++) {
index.writeRow(data, offsets[i], rows[i]); index.writeRow(data, offsets[i], rows[i], onlyPosition);
} }
written = true; written = true;
} }
...@@ -234,7 +227,7 @@ class PageBtreeLeaf extends PageBtree { ...@@ -234,7 +227,7 @@ class PageBtreeLeaf extends PageBtree {
return; return;
} }
PageBtreeNode next = (PageBtreeNode) index.getPage(parentPageId); PageBtreeNode next = (PageBtreeNode) index.getPage(parentPageId);
next.nextPage(cursor, getRow(0)); next.nextPage(cursor, getPos());
} }
public String toString() { public String toString() {
......
...@@ -7,13 +7,13 @@ ...@@ -7,13 +7,13 @@
package org.h2.index; package org.h2.index;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.constant.ErrorCode;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.result.SearchRow; import org.h2.result.SearchRow;
import org.h2.store.DataPage; import org.h2.store.DataPage;
/** /**
* A leaf page that contains index data. * A b-tree node page that contains index data.
* Data is organized as follows: [leaf 0] (largest value of leaf 0) [leaf 1]
* Format: * Format:
* <ul><li>0-3: parent page id * <ul><li>0-3: parent page id
* </li><li>4-4: page type * </li><li>4-4: page type
...@@ -43,7 +43,9 @@ class PageBtreeNode extends PageBtree { ...@@ -43,7 +43,9 @@ class PageBtreeNode extends PageBtree {
} }
void read() { void read() {
data.setPos(5); data.setPos(4);
int type = data.readByte();
onlyPosition = (type & Page.FLAG_LAST) == 0;
entryCount = data.readShortInt(); entryCount = data.readShortInt();
rowCount = rowCountStored = data.readInt(); rowCount = rowCountStored = data.readInt();
childPageIds = new int[entryCount + 1]; childPageIds = new int[entryCount + 1];
...@@ -58,25 +60,39 @@ class PageBtreeNode extends PageBtree { ...@@ -58,25 +60,39 @@ class PageBtreeNode extends PageBtree {
start = data.length(); start = data.length();
} }
private int addChildTry(SearchRow row) throws SQLException {
if (entryCount == 0) {
return 0;
}
int rowLength = index.getRowSize(data, row, onlyPosition);
int pageSize = index.getPageStore().getPageSize();
int last = entryCount == 0 ? pageSize : offsets[entryCount - 1];
if (last - rowLength < start + CHILD_OFFSET_PAIR_LENGTH) {
int todoSplitAtLastInsertionPoint;
return (entryCount / 2) + 1;
}
return 0;
}
/** /**
* Add a row if possible. If it is possible this method returns 0, otherwise * Add a row. If it is possible this method returns 0, otherwise
* the split point. It is always possible to add one row. * the split point. It is always possible to add one row.
* *
* @param row the now to add * @param row the now to add
* @return the split point of this page, or 0 if no split is required * @return the split point of this page, or 0 if no split is required
*/ */
private int addChild(int x, int childPageId, SearchRow row) throws SQLException { private void addChild(int x, int childPageId, SearchRow row) throws SQLException {
int rowLength = index.getRowSize(data, row); int rowLength = index.getRowSize(data, row, onlyPosition);
int pageSize = index.getPageStore().getPageSize(); int pageSize = index.getPageStore().getPageSize();
int last = entryCount == 0 ? pageSize : offsets[entryCount - 1]; int last = entryCount == 0 ? pageSize : offsets[entryCount - 1];
if (entryCount > 0 && last - rowLength < start + CHILD_OFFSET_PAIR_LENGTH) { if (last - rowLength < start + CHILD_OFFSET_PAIR_LENGTH) {
int todoSplitAtLastInsertionPoint; if (entryCount > 0) {
return (entryCount / 2) + 1; throw Message.throwInternalError();
}
onlyPosition = true;
rowLength = index.getRowSize(data, row, onlyPosition);
} }
int offset = last - rowLength; int offset = last - rowLength;
if(offset < 0) {
throw Message.getSQLException(ErrorCode.FEATURE_NOT_SUPPORTED_1, "Wide indexes");
}
int[] newOffsets = new int[entryCount + 1]; int[] newOffsets = new int[entryCount + 1];
SearchRow[] newRows = new SearchRow[entryCount + 1]; SearchRow[] newRows = new SearchRow[entryCount + 1];
int[] newChildPageIds = new int[entryCount + 2]; int[] newChildPageIds = new int[entryCount + 2];
...@@ -84,7 +100,6 @@ class PageBtreeNode extends PageBtree { ...@@ -84,7 +100,6 @@ class PageBtreeNode extends PageBtree {
System.arraycopy(childPageIds, 0, newChildPageIds, 0, x + 1); System.arraycopy(childPageIds, 0, newChildPageIds, 0, x + 1);
} }
if (entryCount > 0) { if (entryCount > 0) {
readAllRows();
System.arraycopy(offsets, 0, newOffsets, 0, x); System.arraycopy(offsets, 0, newOffsets, 0, x);
System.arraycopy(rows, 0, newRows, 0, x); System.arraycopy(rows, 0, newRows, 0, x);
if (x < entryCount) { if (x < entryCount) {
...@@ -104,26 +119,25 @@ class PageBtreeNode extends PageBtree { ...@@ -104,26 +119,25 @@ class PageBtreeNode extends PageBtree {
rows = newRows; rows = newRows;
childPageIds = newChildPageIds; childPageIds = newChildPageIds;
entryCount++; entryCount++;
return 0;
} }
int addRow(SearchRow row) throws SQLException { int addRowTry(SearchRow row) throws SQLException {
while (true) { while (true) {
int x = find(row, false, false); int x = find(row, false, false);
PageBtree page = index.getPage(childPageIds[x]); PageBtree page = index.getPage(childPageIds[x]);
int splitPoint = page.addRow(row); int splitPoint = page.addRowTry(row);
if (splitPoint == 0) { if (splitPoint == 0) {
break; break;
} }
SearchRow pivot = page.getRow(splitPoint - 1); SearchRow pivot = page.getRow(splitPoint - 1);
int splitPoint2 = addChildTry(pivot);
if (splitPoint2 != 0) {
return splitPoint;
}
PageBtree page2 = page.split(splitPoint); PageBtree page2 = page.split(splitPoint);
addChild(x, page2.getPageId(), pivot);
index.getPageStore().updateRecord(page, true, page.data); index.getPageStore().updateRecord(page, true, page.data);
index.getPageStore().updateRecord(page2, true, page2.data); index.getPageStore().updateRecord(page2, true, page2.data);
splitPoint = addChild(x, page2.getPageId(), pivot);
if (splitPoint != 0) {
int todoSplitAtLastInsertionPoint;
return splitPoint / 2;
}
index.getPageStore().updateRecord(this, true, data); index.getPageStore().updateRecord(this, true, data);
} }
updateRowCount(1); updateRowCount(1);
...@@ -202,7 +216,7 @@ class PageBtreeNode extends PageBtree { ...@@ -202,7 +216,7 @@ class PageBtreeNode extends PageBtree {
boolean remove(SearchRow row) throws SQLException { boolean remove(SearchRow row) throws SQLException {
int at = find(row, false, false); int at = find(row, false, false);
// merge is not implemented to allow concurrent usage of btrees // merge is not implemented to allow concurrent usage
// TODO maybe implement merge // TODO maybe implement merge
PageBtree page = index.getPage(childPageIds[at]); PageBtree page = index.getPage(childPageIds[at]);
boolean empty = page.remove(row); boolean empty = page.remove(row);
...@@ -265,13 +279,10 @@ class PageBtreeNode extends PageBtree { ...@@ -265,13 +279,10 @@ class PageBtreeNode extends PageBtree {
if (written) { if (written) {
return; return;
} }
// make sure rows are read readAllRows();
for (int i = 0; i < entryCount; i++) {
getRow(i);
}
data.reset(); data.reset();
data.writeInt(parentPageId); data.writeInt(parentPageId);
data.writeByte((byte) Page.TYPE_BTREE_NODE); data.writeByte((byte) (Page.TYPE_BTREE_NODE | (onlyPosition ? 0 : Page.FLAG_LAST)));
data.writeShortInt(entryCount); data.writeShortInt(entryCount);
data.writeInt(rowCountStored); data.writeInt(rowCountStored);
data.writeInt(childPageIds[entryCount]); data.writeInt(childPageIds[entryCount]);
...@@ -280,7 +291,7 @@ class PageBtreeNode extends PageBtree { ...@@ -280,7 +291,7 @@ class PageBtreeNode extends PageBtree {
data.writeInt(offsets[i]); data.writeInt(offsets[i]);
} }
for (int i = 0; i < entryCount; i++) { for (int i = 0; i < entryCount; i++) {
index.writeRow(data, offsets[i], rows[i]); index.writeRow(data, offsets[i], rows[i], onlyPosition);
} }
written = true; written = true;
} }
...@@ -319,16 +330,22 @@ class PageBtreeNode extends PageBtree { ...@@ -319,16 +330,22 @@ class PageBtreeNode extends PageBtree {
* @param cursor the cursor * @param cursor the cursor
* @param row the current row * @param row the current row
*/ */
void nextPage(PageBtreeCursor cursor, SearchRow row) throws SQLException { void nextPage(PageBtreeCursor cursor, int pageId) throws SQLException {
int i = find(row, false, false) + 1; int i;
// TODO maybe keep the index in the child page (transiently)
for (i = 0; i < childPageIds.length; i++) {
if (childPageIds[i] == pageId) {
i++;
break;
}
}
if (i > entryCount) { if (i > entryCount) {
if (parentPageId == Page.ROOT) { if (parentPageId == Page.ROOT) {
cursor.setCurrent(null, 0); cursor.setCurrent(null, 0);
return; return;
} }
PageBtreeNode next = (PageBtreeNode) index.getPage(parentPageId); PageBtreeNode next = (PageBtreeNode) index.getPage(parentPageId);
SearchRow r = entryCount == 0 ? row : getRow(entryCount - 1); next.nextPage(cursor, getPos());
next.nextPage(cursor, r);
return; return;
} }
PageBtree page = index.getPage(childPageIds[i]); PageBtree page = index.getPage(childPageIds[i]);
......
...@@ -8,7 +8,6 @@ package org.h2.index; ...@@ -8,7 +8,6 @@ package org.h2.index;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.engine.Session;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.store.DataPage; import org.h2.store.DataPage;
import org.h2.store.Record; import org.h2.store.Record;
...@@ -97,13 +96,13 @@ abstract class PageData extends Record { ...@@ -97,13 +96,13 @@ abstract class PageData extends Record {
abstract void read() throws SQLException; abstract void read() throws SQLException;
/** /**
* Add a row. * Try to add a row.
* *
* @param row the row * @param row the row
* @return 0 if successful, or the split position if the page needs to be * @return 0 if successful, or the split position if the page needs to be
* split * split
*/ */
abstract int addRow(Row row) throws SQLException; abstract int addRowTry(Row row) throws SQLException;
/** /**
* Get a cursor. * Get a cursor.
...@@ -188,6 +187,6 @@ abstract class PageData extends Record { ...@@ -188,6 +187,6 @@ abstract class PageData extends Record {
* @param key the key * @param key the key
* @return the row * @return the row
*/ */
abstract Row getRow(Session session, int key) throws SQLException; abstract Row getRow(int key) throws SQLException;
} }
...@@ -5,10 +5,9 @@ ...@@ -5,10 +5,9 @@
* Initial Developer: H2 Group * Initial Developer: H2 Group
*/ */
package org.h2.index; package org.h2.index;
import java.sql.SQLException;
import java.sql.SQLException;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.engine.Session;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.store.DataPage; import org.h2.store.DataPage;
...@@ -89,7 +88,7 @@ class PageDataLeaf extends PageData { ...@@ -89,7 +88,7 @@ class PageDataLeaf extends PageData {
* @param row the now to add * @param row the now to add
* @return the split point of this page, or 0 if no split is required * @return the split point of this page, or 0 if no split is required
*/ */
int addRow(Row row) throws SQLException { int addRowTry(Row row) throws SQLException {
int rowLength = row.getByteCount(data); int rowLength = row.getByteCount(data);
int pageSize = index.getPageStore().getPageSize(); int pageSize = index.getPageStore().getPageSize();
int last = entryCount == 0 ? pageSize : offsets[entryCount - 1]; int last = entryCount == 0 ? pageSize : offsets[entryCount - 1];
...@@ -245,7 +244,7 @@ class PageDataLeaf extends PageData { ...@@ -245,7 +244,7 @@ class PageDataLeaf extends PageData {
int newPageId = index.getPageStore().allocatePage(); int newPageId = index.getPageStore().allocatePage();
PageDataLeaf p2 = new PageDataLeaf(index, newPageId, parentPageId, index.getPageStore().createDataPage()); PageDataLeaf p2 = new PageDataLeaf(index, newPageId, parentPageId, index.getPageStore().createDataPage());
for (int i = splitPoint; i < entryCount;) { for (int i = splitPoint; i < entryCount;) {
p2.addRow(getRowAt(splitPoint)); p2.addRowTry(getRowAt(splitPoint));
removeRow(splitPoint); removeRow(splitPoint);
} }
return p2; return p2;
...@@ -297,7 +296,7 @@ class PageDataLeaf extends PageData { ...@@ -297,7 +296,7 @@ class PageDataLeaf extends PageData {
return false; return false;
} }
Row getRow(Session session, int key) throws SQLException { Row getRow(int key) throws SQLException {
int index = find(key); int index = find(key);
return getRowAt(index); return getRowAt(index);
} }
......
...@@ -77,24 +77,24 @@ class PageDataNode extends PageData { ...@@ -77,24 +77,24 @@ class PageDataNode extends PageData {
entryCount++; entryCount++;
} }
int addRow(Row row) throws SQLException { int addRowTry(Row row) throws SQLException {
while (true) { while (true) {
int x = find(row.getPos()); int x = find(row.getPos());
PageData page = index.getPage(childPageIds[x]); PageData page = index.getPage(childPageIds[x]);
int splitPoint = page.addRow(row); int splitPoint = page.addRowTry(row);
if (splitPoint == 0) { if (splitPoint == 0) {
break; break;
} }
int pivot = page.getKey(splitPoint - 1);
PageData page2 = page.split(splitPoint);
index.getPageStore().updateRecord(page, true, page.data);
index.getPageStore().updateRecord(page2, true, page2.data);
addChild(x, page2.getPageId(), pivot);
int maxEntries = (index.getPageStore().getPageSize() - ENTRY_START) / ENTRY_LENGTH; int maxEntries = (index.getPageStore().getPageSize() - ENTRY_START) / ENTRY_LENGTH;
if (entryCount >= maxEntries) { if (entryCount >= maxEntries) {
int todoSplitAtLastInsertionPoint; int todoSplitAtLastInsertionPoint;
return entryCount / 2; return entryCount / 2;
} }
int pivot = page.getKey(splitPoint - 1);
PageData page2 = page.split(splitPoint);
index.getPageStore().updateRecord(page, true, page.data);
index.getPageStore().updateRecord(page2, true, page2.data);
addChild(x, page2.getPageId(), pivot);
index.getPageStore().updateRecord(this, true, data); index.getPageStore().updateRecord(this, true, data);
} }
updateRowCount(1); updateRowCount(1);
...@@ -205,10 +205,10 @@ class PageDataNode extends PageData { ...@@ -205,10 +205,10 @@ class PageDataNode extends PageData {
return false; return false;
} }
Row getRow(Session session, int key) throws SQLException { Row getRow(int key) throws SQLException {
int at = find(key); int at = find(key);
PageData page = index.getPage(childPageIds[at]); PageData page = index.getPage(childPageIds[at]);
return page.getRow(session, key); return page.getRow(key);
} }
int getRowCount() throws SQLException { int getRowCount() throws SQLException {
......
...@@ -108,7 +108,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex { ...@@ -108,7 +108,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
} }
while (true) { while (true) {
PageData root = getPage(headPos); PageData root = getPage(headPos);
int splitPoint = root.addRow(row); int splitPoint = root.addRowTry(row);
if (splitPoint == 0) { if (splitPoint == 0) {
break; break;
} }
...@@ -260,7 +260,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex { ...@@ -260,7 +260,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
public Row getRow(Session session, int key) throws SQLException { public Row getRow(Session session, int key) throws SQLException {
PageData root = getPage(headPos); PageData root = getPage(headPos);
return root.getRow(session, key); return root.getRow(key);
} }
PageStore getPageStore() { PageStore getPageStore() {
......
...@@ -66,13 +66,14 @@ import org.h2.value.ValueString; ...@@ -66,13 +66,14 @@ import org.h2.value.ValueString;
*/ */
public class PageStore implements CacheWriter { public class PageStore implements CacheWriter {
// TODO currently working on PageBtreeNode Wide indexes // TODO TestPowerOff
// TODO implement redo log in Recover tool
// TODO PageStore.openMetaIndex (desc and nulls first / last) // TODO PageStore.openMetaIndex (desc and nulls first / last)
// TODO PageBtreeIndex.canGetFirstOrLast
// TODO btree index with fixed size values doesn't need offset and so on // TODO btree index with fixed size values doesn't need offset and so on
// TODO better checksums (for example, multiple fletcher) // TODO better checksums (for example, multiple fletcher)
// TODO replace CRC32 // TODO replace CRC32
// TODO PageBtreeNode: 4 bytes offset - others use only 2
// TODO PageBtreeLeaf: why table id
// TODO log block allocation // TODO log block allocation
// TODO block compression: maybe http://en.wikipedia.org/wiki/LZJB // TODO block compression: maybe http://en.wikipedia.org/wiki/LZJB
// with RLE, specially for 0s. // with RLE, specially for 0s.
...@@ -103,6 +104,7 @@ public class PageStore implements CacheWriter { ...@@ -103,6 +104,7 @@ public class PageStore implements CacheWriter {
// and delay on each commit // and delay on each commit
// TODO var int: see google protocol buffers // TODO var int: see google protocol buffers
// TODO SessionState.logId is no longer needed // TODO SessionState.logId is no longer needed
// TODO PageData and PageBtree addRowTry: try to simplify
/** /**
* The smallest possible page size. * The smallest possible page size.
......
...@@ -629,4 +629,8 @@ public class Column { ...@@ -629,4 +629,8 @@ public class Column {
return primaryKey; return primaryKey;
} }
public String toString() {
return name;
}
} }
...@@ -289,7 +289,7 @@ java org.h2.test.TestAll timer ...@@ -289,7 +289,7 @@ java org.h2.test.TestAll timer
// 2009-05-15: 25 tests fail with page store (first loop) // 2009-05-15: 25 tests fail with page store (first loop)
// 2009-05-18: 18 tests fail with page store (first loop) // 2009-05-18: 18 tests fail with page store (first loop)
// 2009-05-30: 15 tests fail with page store (first loop) // 2009-05-30: 15 tests fail with page store (first loop)
// 2009-06-16: 13 tests fail with page store (first loop) // 2009-06-19: 10 tests fail with page store (first loop)
// System.setProperty("h2.pageStore", "true"); // System.setProperty("h2.pageStore", "true");
/* /*
......
...@@ -178,14 +178,16 @@ public class TestPowerOff extends TestBase { ...@@ -178,14 +178,16 @@ public class TestPowerOff extends TestBase {
} catch (SQLException e) { } catch (SQLException e) {
assertKnownException(e); assertKnownException(e);
} }
boolean deleted = false; if (!SysProperties.PAGE_STORE) {
for (String fileName : FileLister.getDatabaseFiles(dir, dbName, false)) { boolean deleted = false;
if (fileName.endsWith(Constants.SUFFIX_INDEX_FILE)) { for (String fileName : FileLister.getDatabaseFiles(dir, dbName, false)) {
FileUtils.delete(fileName); if (fileName.endsWith(Constants.SUFFIX_INDEX_FILE)) {
deleted = true; FileUtils.delete(fileName);
deleted = true;
}
} }
assertTrue(deleted);
} }
assertTrue(deleted);
conn = getConnection(url); conn = getConnection(url);
conn.close(); conn.close();
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论