提交 73ce982b authored 作者: Thomas Mueller's avatar Thomas Mueller

New experimental page store.

上级 71603295
...@@ -85,6 +85,7 @@ abstract class PageBtree extends Record { ...@@ -85,6 +85,7 @@ abstract class PageBtree extends Record {
* *
* @param rowCount the stored row count * @param rowCount the stored row count
*/ */
// TODO remove
abstract void setRowCountStored(int rowCount) throws SQLException; abstract void setRowCountStored(int rowCount) throws SQLException;
/** /**
......
...@@ -32,8 +32,8 @@ public class PageBtreeIndex extends BaseIndex { ...@@ -32,8 +32,8 @@ public class PageBtreeIndex extends BaseIndex {
private PageStore store; private PageStore store;
private TableData tableData; private TableData tableData;
private final int headPos; private final int headPos;
private long rowCount;
private boolean needRebuild; private boolean needRebuild;
private long rowCount;
public PageBtreeIndex(TableData table, int id, String indexName, IndexColumn[] columns, public PageBtreeIndex(TableData table, int id, String indexName, IndexColumn[] columns,
IndexType indexType, int headPos, Session session) throws SQLException { IndexType indexType, int headPos, Session session) throws SQLException {
...@@ -310,11 +310,11 @@ public class PageBtreeIndex extends BaseIndex { ...@@ -310,11 +310,11 @@ public class PageBtreeIndex extends BaseIndex {
} }
public long getRowCountApproximation() { public long getRowCountApproximation() {
return rowCount; return tableData.getRowCountApproximation();
} }
public long getRowCount(Session session) { public long getRowCount(Session session) {
return rowCount; return tableData.getRowCount(session);
} }
public void close(Session session) { public void close(Session session) {
......
...@@ -37,7 +37,7 @@ class PageBtreeNode extends PageBtree { ...@@ -37,7 +37,7 @@ class PageBtreeNode extends PageBtree {
*/ */
private int[] childPageIds; private int[] childPageIds;
private int rowCountStored = UNKNOWN_ROWCOUNT; // private int rowCountStored = UNKNOWN_ROWCOUNT;
private int rowCount = UNKNOWN_ROWCOUNT; private int rowCount = UNKNOWN_ROWCOUNT;
...@@ -51,7 +51,10 @@ class PageBtreeNode extends PageBtree { ...@@ -51,7 +51,10 @@ class PageBtreeNode extends PageBtree {
int type = data.readByte(); int type = data.readByte();
onlyPosition = (type & Page.FLAG_LAST) == 0; onlyPosition = (type & Page.FLAG_LAST) == 0;
entryCount = data.readShortInt(); entryCount = data.readShortInt();
rowCount = rowCountStored = data.readInt(); rowCount = data.readInt();
if (!PageStore.STORE_BTREE_ROWCOUNT) {
rowCount = UNKNOWN_ROWCOUNT;
}
childPageIds = new int[entryCount + 1]; childPageIds = new int[entryCount + 1];
childPageIds[entryCount] = data.readInt(); childPageIds[entryCount] = data.readInt();
rows = PageStore.newSearchRows(entryCount); rows = PageStore.newSearchRows(entryCount);
...@@ -155,14 +158,10 @@ class PageBtreeNode extends PageBtree { ...@@ -155,14 +158,10 @@ class PageBtreeNode extends PageBtree {
return 0; return 0;
} }
private void updateRowCount(int offset) throws SQLException { private void updateRowCount(int offset) {
if (rowCount != UNKNOWN_ROWCOUNT) { if (PageStore.STORE_BTREE_ROWCOUNT) {
rowCount += offset; rowCount += offset;
} }
if (rowCountStored != UNKNOWN_ROWCOUNT) {
rowCountStored = UNKNOWN_ROWCOUNT;
index.getPageStore().updateRecord(this, true, data);
}
} }
PageBtree split(int splitPoint) throws SQLException { PageBtree split(int splitPoint) throws SQLException {
...@@ -209,6 +208,7 @@ class PageBtreeNode extends PageBtree { ...@@ -209,6 +208,7 @@ class PageBtreeNode extends PageBtree {
rows = new SearchRow[0]; rows = new SearchRow[0];
offsets = MemoryUtils.EMPTY_INTS; offsets = MemoryUtils.EMPTY_INTS;
addChild(0, page2.getPos(), pivot); addChild(0, page2.getPos(), pivot);
rowCount = page1.getRowCount() + page2.getRowCount();
check(); check();
} }
...@@ -276,12 +276,8 @@ class PageBtreeNode extends PageBtree { ...@@ -276,12 +276,8 @@ class PageBtreeNode extends PageBtree {
return rowCount; return rowCount;
} }
void setRowCountStored(int rowCount) throws SQLException { void setRowCountStored(int rowCount) {
this.rowCount = rowCount; this.rowCount = rowCount;
if (rowCountStored != rowCount) {
rowCountStored = rowCount;
index.getPageStore().updateRecord(this, true, data);
}
} }
private void check() { private void check() {
...@@ -311,7 +307,7 @@ class PageBtreeNode extends PageBtree { ...@@ -311,7 +307,7 @@ class PageBtreeNode extends PageBtree {
data.writeInt(parentPageId); data.writeInt(parentPageId);
data.writeByte((byte) (Page.TYPE_BTREE_NODE | (onlyPosition ? 0 : Page.FLAG_LAST))); data.writeByte((byte) (Page.TYPE_BTREE_NODE | (onlyPosition ? 0 : Page.FLAG_LAST)));
data.writeShortInt(entryCount); data.writeShortInt(entryCount);
data.writeInt(rowCountStored); data.writeInt(rowCount);
data.writeInt(childPageIds[entryCount]); data.writeInt(childPageIds[entryCount]);
for (int i = 0; i < entryCount; i++) { for (int i = 0; i < entryCount; i++) {
data.writeInt(childPageIds[i]); data.writeInt(childPageIds[i]);
......
...@@ -26,6 +26,7 @@ import org.h2.store.Record; ...@@ -26,6 +26,7 @@ import org.h2.store.Record;
import org.h2.table.Column; import org.h2.table.Column;
import org.h2.table.IndexColumn; import org.h2.table.IndexColumn;
import org.h2.table.TableData; import org.h2.table.TableData;
import org.h2.util.MathUtils;
import org.h2.util.New; import org.h2.util.New;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueLob; import org.h2.value.ValueLob;
...@@ -146,6 +147,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex { ...@@ -146,6 +147,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
} }
incrementRowCount(session.getId(), 1); incrementRowCount(session.getId(), 1);
} }
invalidateRowCount();
rowCount++; rowCount++;
store.logAddOrRemoveRow(session, tableData.getId(), row, true); store.logAddOrRemoveRow(session, tableData.getId(), row, true);
} }
...@@ -249,14 +251,13 @@ public class PageScanIndex extends BaseIndex implements RowIndex { ...@@ -249,14 +251,13 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
} }
} }
} }
// TODO invalidate the row count
// setChanged(session);
if (rowCount == 1) { if (rowCount == 1) {
removeAllRows(); removeAllRows();
} else { } else {
int key = row.getPos(); int key = row.getPos();
PageData root = getPage(headPos, 0); PageData root = getPage(headPos, 0);
root.remove(key); root.remove(key);
invalidateRowCount();
rowCount--; rowCount--;
// TODO re-use keys // TODO re-use keys
} }
...@@ -275,6 +276,11 @@ public class PageScanIndex extends BaseIndex implements RowIndex { ...@@ -275,6 +276,11 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
store.logAddOrRemoveRow(session, tableData.getId(), row, false); store.logAddOrRemoveRow(session, tableData.getId(), row, false);
} }
private void invalidateRowCount() throws SQLException {
PageData root = getPage(headPos, 0);
root.setRowCountStored(PageData.UNKNOWN_ROWCOUNT);
}
public void remove(Session session) throws SQLException { public void remove(Session session) throws SQLException {
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
trace.debug("remove"); trace.debug("remove");
...@@ -356,7 +362,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex { ...@@ -356,7 +362,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
return -1; return -1;
} }
public void close(Session session) { public void close(Session session) throws SQLException {
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
trace.debug("close"); trace.debug("close");
} }
...@@ -369,7 +375,8 @@ public class PageScanIndex extends BaseIndex implements RowIndex { ...@@ -369,7 +375,8 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
} }
// can not close the index because it might get used afterwards, // can not close the index because it might get used afterwards,
// for example after running recovery // for example after running recovery
// TODO write the row count PageData root = getPage(headPos, 0);
root.setRowCountStored(MathUtils.convertLongToInt(rowCount));
} }
Iterator<Row> getDelta() { Iterator<Row> getDelta() {
......
...@@ -69,15 +69,15 @@ import org.h2.value.ValueString; ...@@ -69,15 +69,15 @@ import org.h2.value.ValueString;
*/ */
public class PageStore implements CacheWriter { public class PageStore implements CacheWriter {
// TODO btree index with fixed size values doesn't need offset and so on // TODO var int: see google protocol buffers
// TODO somehow remember rowcount // TODO don't save parent (only root); remove setPageId
// TODO implement checksum - 0 for empty // TODO implement checksum - 0 for empty
// TODO btree index with fixed size values doesn't need offset and so on
// TODO remove parent, use tableId if required // TODO remove parent, use tableId if required
// TODO replace CRC32 // TODO replace CRC32
// TODO PageBtreeNode: 4 bytes offset - others use only 2 // TODO PageBtreeNode: 4 bytes offset - others use only 2
// 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.
// TODO don't save parent (only root); remove setPageId
// TODO order pages so that searching for a key only seeks forward // TODO order pages so that searching for a key only seeks forward
// TODO completely re-use keys of deleted rows; maybe // TODO completely re-use keys of deleted rows; maybe
// remember last page with deleted keys (in the root page?), // remember last page with deleted keys (in the root page?),
...@@ -95,10 +95,10 @@ public class PageStore implements CacheWriter { ...@@ -95,10 +95,10 @@ public class PageStore implements CacheWriter {
// TODO split files (1 GB max size) // TODO split files (1 GB max size)
// TODO add a setting (that can be changed at runtime) to call fsync // TODO add a setting (that can be changed at runtime) to call fsync
// and delay on each commit // and delay on each commit
// TODO var int: see google protocol buffers
// TODO PageData and PageBtree addRowTry: try to simplify // TODO PageData and PageBtree addRowTry: try to simplify
// TODO test running out of disk space (using a special file system) // TODO test running out of disk space (using a special file system)
// TODO check for file size (exception if not exact size expected) // TODO check for file size (exception if not exact size expected)
// TODO implement missing code for STORE_BTREE_ROWCOUNT (maybe enable, maybe not)
// TODO when removing DiskFile: // TODO when removing DiskFile:
// remove CacheObject.blockCount // remove CacheObject.blockCount
...@@ -107,6 +107,7 @@ public class PageStore implements CacheWriter { ...@@ -107,6 +107,7 @@ public class PageStore implements CacheWriter {
// remove parameter in Record.write(DataPage buff) // remove parameter in Record.write(DataPage buff)
// remove Record.getByteCount // remove Record.getByteCount
// remove Database.objectIds // remove Database.objectIds
// remove TableData.checkRowCount
/** /**
* The smallest possible page size. * The smallest possible page size.
...@@ -123,6 +124,11 @@ public class PageStore implements CacheWriter { ...@@ -123,6 +124,11 @@ public class PageStore implements CacheWriter {
*/ */
public static final int PAGE_SIZE_DEFAULT = 1024; public static final int PAGE_SIZE_DEFAULT = 1024;
/**
* Store the rowcount in b-tree indexes.
*/
public static final boolean STORE_BTREE_ROWCOUNT = false;
private static final int PAGE_ID_FREE_LIST_ROOT = 3; private static final int PAGE_ID_FREE_LIST_ROOT = 3;
private static final int PAGE_ID_META_ROOT = 4; private static final int PAGE_ID_META_ROOT = 4;
...@@ -734,7 +740,6 @@ public class PageStore implements CacheWriter { ...@@ -734,7 +740,6 @@ public class PageStore implements CacheWriter {
database.setReadOnly(true); database.setReadOnly(true);
} }
} }
recoveryRunning = false;
PageScanIndex index = (PageScanIndex) metaObjects.get(0); PageScanIndex index = (PageScanIndex) metaObjects.get(0);
if (index == null) { if (index == null) {
systemTableHeadPos = Index.EMPTY_HEAD; systemTableHeadPos = Index.EMPTY_HEAD;
...@@ -744,6 +749,7 @@ public class PageStore implements CacheWriter { ...@@ -744,6 +749,7 @@ public class PageStore implements CacheWriter {
for (Index openIndex : metaObjects.values()) { for (Index openIndex : metaObjects.values()) {
openIndex.close(systemSession); openIndex.close(systemSession);
} }
recoveryRunning = false;
trace.debug("log recover done"); trace.debug("log recover done");
} }
......
...@@ -36,6 +36,7 @@ import org.h2.result.Row; ...@@ -36,6 +36,7 @@ import org.h2.result.Row;
import org.h2.schema.Schema; import org.h2.schema.Schema;
import org.h2.schema.SchemaObject; import org.h2.schema.SchemaObject;
import org.h2.store.DataPage; import org.h2.store.DataPage;
import org.h2.store.PageStore;
import org.h2.store.Record; import org.h2.store.Record;
import org.h2.store.RecordReader; import org.h2.store.RecordReader;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
...@@ -142,6 +143,9 @@ public class TableData extends Table implements RecordReader { ...@@ -142,6 +143,9 @@ public class TableData extends Table implements RecordReader {
private void checkRowCount(Session session, Index index, int offset) { private void checkRowCount(Session session, Index index, int offset) {
if (SysProperties.CHECK && !database.isMultiVersion()) { if (SysProperties.CHECK && !database.isMultiVersion()) {
if (database.isPageStoreEnabled() && !PageStore.STORE_BTREE_ROWCOUNT) {
return;
}
long rc = index.getRowCount(session); long rc = index.getRowCount(session);
if (rc != rowCount + offset) { if (rc != rowCount + offset) {
Message.throwInternalError("rowCount expected " + (rowCount + offset) + " got " + rc + " " + getName() + "." + index.getName()); Message.throwInternalError("rowCount expected " + (rowCount + offset) + " got " + rc + " " + getName() + "." + index.getName());
......
...@@ -109,6 +109,7 @@ import org.h2.test.unit.TestDateIso8601; ...@@ -109,6 +109,7 @@ import org.h2.test.unit.TestDateIso8601;
import org.h2.test.unit.TestExit; import org.h2.test.unit.TestExit;
import org.h2.test.unit.TestFile; import org.h2.test.unit.TestFile;
import org.h2.test.unit.TestFileLock; import org.h2.test.unit.TestFileLock;
import org.h2.test.unit.TestFileLockSerialized;
import org.h2.test.unit.TestFileSystem; import org.h2.test.unit.TestFileSystem;
import org.h2.test.unit.TestFtp; import org.h2.test.unit.TestFtp;
import org.h2.test.unit.TestIntArray; import org.h2.test.unit.TestIntArray;
...@@ -332,7 +333,6 @@ kill -9 `jps -l | grep "org.h2.test.TestAll" | cut -d " " -f 1` ...@@ -332,7 +333,6 @@ kill -9 `jps -l | grep "org.h2.test.TestAll" | cut -d " " -f 1`
new TestTimer().runTest(test); new TestTimer().runTest(test);
} }
} else { } else {
int todo;
System.setProperty(SysProperties.H2_PAGE_STORE, "true"); System.setProperty(SysProperties.H2_PAGE_STORE, "true");
test.pageStore = true; test.pageStore = true;
test.runTests(); test.runTests();
...@@ -555,6 +555,7 @@ kill -9 `jps -l | grep "org.h2.test.TestAll" | cut -d " " -f 1` ...@@ -555,6 +555,7 @@ kill -9 `jps -l | grep "org.h2.test.TestAll" | cut -d " " -f 1`
new TestExit().runTest(this); new TestExit().runTest(this);
new TestFile().runTest(this); new TestFile().runTest(this);
new TestFileLock().runTest(this); new TestFileLock().runTest(this);
new TestFileLockSerialized().runTest(this);
new TestFtp().runTest(this); new TestFtp().runTest(this);
new TestFileSystem().runTest(this); new TestFileSystem().runTest(this);
new TestIntArray().runTest(this); new TestIntArray().runTest(this);
......
...@@ -93,16 +93,20 @@ public class TestIndex extends TestBase { ...@@ -93,16 +93,20 @@ public class TestIndex extends TestBase {
switch (random.nextInt(4)) { switch (random.nextInt(4)) {
case 0: case 0:
if (reopen) { if (reopen) {
trace("reconnect");
reconnect(); reconnect();
} }
break; break;
case 1: case 1:
trace("insert");
stat.execute("insert into test(id) values(null)"); stat.execute("insert into test(id) values(null)");
break; break;
case 2: case 2:
trace("delete");
stat.execute("delete from test"); stat.execute("delete from test");
break; break;
case 3: case 3:
trace("insert 1-100");
stat.execute("insert into test select null from system_range(1, 100)"); stat.execute("insert into test select null from system_range(1, 100)");
break; break;
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论