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

New experimental page store.

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