提交 9658fe81 authored 作者: Thomas Mueller's avatar Thomas Mueller

New experimental page store.

上级 455c15cb
...@@ -18,7 +18,12 @@ Change Log ...@@ -18,7 +18,12 @@ Change Log
<h1>Change Log</h1> <h1>Change Log</h1>
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul><li>Bugfixes in the new storage mechanism (page store). <ul><li>The Recover tool did not work with .data.db files of the wrong size.
</li><li>Triggers: if there was an exception when initializing a trigger, this exception could be hidden,
and in some cases (specially when using the Lucene fulltext index mechanism) a NullPointerException was
thrown later on. Now the exception that occurred on init is thrown when changing data.
</li><li>The soft-references cache (CACHE_TYPE=SOFT_LRU) could throw a NullPointerException.
</li><li>Bugfixes in the new storage mechanism (page store).
</li></ul> </li></ul>
<h2>Version 1.1.115 (2009-06-21)</h2> <h2>Version 1.1.115 (2009-06-21)</h2>
......
...@@ -226,6 +226,11 @@ abstract class PageBtree extends Record { ...@@ -226,6 +226,11 @@ abstract class PageBtree extends Record {
*/ */
abstract boolean remove(SearchRow row) throws SQLException; abstract boolean remove(SearchRow row) throws SQLException;
/**
* Free up all child pages.
*/
abstract void freeChildren() throws SQLException;
/** /**
* Ensure all rows are read in memory. * Ensure all rows are read in memory.
*/ */
......
...@@ -242,6 +242,8 @@ public class PageBtreeIndex extends BaseIndex { ...@@ -242,6 +242,8 @@ public class PageBtreeIndex extends BaseIndex {
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
trace.debug("remove"); trace.debug("remove");
} }
removeAllRows();
store.freePage(headPos, false, null);
store.removeMeta(this, session); store.removeMeta(this, session);
} }
...@@ -257,10 +259,10 @@ public class PageBtreeIndex extends BaseIndex { ...@@ -257,10 +259,10 @@ public class PageBtreeIndex extends BaseIndex {
} }
private void removeAllRows() throws SQLException { private void removeAllRows() throws SQLException {
PageBtree root = getPage(headPos);
root.freeChildren();
root = new PageBtreeLeaf(this, headPos, Page.ROOT, store.createDataPage());
store.removeRecord(headPos); store.removeRecord(headPos);
int todoLogOldData;
int freePages;
PageBtreeLeaf root = new PageBtreeLeaf(this, headPos, Page.ROOT, store.createDataPage());
store.updateRecord(root, true, null); store.updateRecord(root, true, null);
rowCount = 0; rowCount = 0;
} }
......
...@@ -159,6 +159,10 @@ class PageBtreeLeaf extends PageBtree { ...@@ -159,6 +159,10 @@ class PageBtreeLeaf extends PageBtree {
return false; return false;
} }
void freeChildren() {
// nothing to do
}
int getRowCount() { int getRowCount() {
return entryCount; return entryCount;
} }
......
...@@ -311,6 +311,15 @@ class PageBtreeNode extends PageBtree { ...@@ -311,6 +311,15 @@ class PageBtreeNode extends PageBtree {
written = true; written = true;
} }
void freeChildren() throws SQLException {
for (int i = 0; i <= entryCount; i++) {
int childPageId = childPageIds[i];
PageBtree child = index.getPage(childPageId);
index.getPageStore().freePage(childPageId, false, null);
child.freeChildren();
}
}
private void removeChild(int i) throws SQLException { private void removeChild(int i) throws SQLException {
readAllRows(); readAllRows();
entryCount--; entryCount--;
......
...@@ -182,6 +182,11 @@ abstract class PageData extends Record { ...@@ -182,6 +182,11 @@ abstract class PageData extends Record {
*/ */
abstract boolean remove(int key) throws SQLException; abstract boolean remove(int key) throws SQLException;
/**
* Free up all child pages.
*/
abstract void freeChildren() throws SQLException;
/** /**
* Get the row for the given key. * Get the row for the given key.
* *
......
...@@ -297,6 +297,28 @@ class PageDataLeaf extends PageData { ...@@ -297,6 +297,28 @@ class PageDataLeaf extends PageData {
return false; return false;
} }
void freeChildren() throws SQLException {
if (firstOverflowPageId != 0) {
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;
}
store.freePage(next, false, null);
next = page.getNextOverflow();
} while (next != 0);
}
}
Row getRow(int key) throws SQLException { Row getRow(int key) throws SQLException {
int index = find(key); int index = find(key);
return getRowAt(index); return getRowAt(index);
......
...@@ -109,6 +109,10 @@ public class PageDataLeafOverflow extends Record { ...@@ -109,6 +109,10 @@ public class PageDataLeafOverflow extends Record {
return nextPage; return nextPage;
} }
int getNextOverflow() {
return nextPage;
}
public int getByteCount(DataPage dummy) { public int getByteCount(DataPage dummy) {
return leaf.getByteCount(dummy); return leaf.getByteCount(dummy);
} }
......
...@@ -205,6 +205,15 @@ class PageDataNode extends PageData { ...@@ -205,6 +205,15 @@ class PageDataNode extends PageData {
return false; return false;
} }
void freeChildren() throws SQLException {
for (int i = 0; i <= entryCount; i++) {
int childPageId = childPageIds[i];
PageData child = index.getPage(childPageId);
index.getPageStore().freePage(childPageId, false, null);
child.freeChildren();
}
}
Row getRow(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]);
......
...@@ -256,6 +256,8 @@ public class PageScanIndex extends BaseIndex implements RowIndex { ...@@ -256,6 +256,8 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
trace.debug("remove"); trace.debug("remove");
} }
removeAllRows();
store.freePage(headPos, false, null);
store.removeMeta(this, session); store.removeMeta(this, session);
} }
...@@ -274,10 +276,10 @@ public class PageScanIndex extends BaseIndex implements RowIndex { ...@@ -274,10 +276,10 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
} }
private void removeAllRows() throws SQLException { private void removeAllRows() throws SQLException {
PageData root = getPage(headPos);
root.freeChildren();
root = new PageDataLeaf(this, headPos, Page.ROOT, store.createDataPage());
store.removeRecord(headPos); store.removeRecord(headPos);
int todoLogOldData;
int freePages;
PageDataLeaf root = new PageDataLeaf(this, headPos, Page.ROOT, store.createDataPage());
store.updateRecord(root, true, null); store.updateRecord(root, true, null);
rowCount = 0; rowCount = 0;
lastKey = 0; lastKey = 0;
......
...@@ -129,7 +129,7 @@ public class PageFreeList extends Record { ...@@ -129,7 +129,7 @@ public class PageFreeList extends Record {
* @param pageSize the page size * @param pageSize the page size
* @return the number of pages * @return the number of pages
*/ */
static int getPagesAddressed(int pageSize) { public static int getPagesAddressed(int pageSize) {
return (pageSize - DATA_START) * 8; return (pageSize - DATA_START) * 8;
} }
...@@ -142,4 +142,8 @@ public class PageFreeList extends Record { ...@@ -142,4 +142,8 @@ public class PageFreeList extends Record {
return store.getPageSize() >> 2; return store.getPageSize() >> 2;
} }
boolean isUsed(int pageId) {
return used.get(pageId - getPos());
}
} }
...@@ -93,6 +93,10 @@ public class PageOutputStream extends OutputStream { ...@@ -93,6 +93,10 @@ public class PageOutputStream extends OutputStream {
} }
int len = PageStreamTrunk.getPagesAddressed(store.getPageSize()); int len = PageStreamTrunk.getPagesAddressed(store.getPageSize());
int[] pageIds = new int[len]; int[] pageIds = new int[len];
if (reservedPages.size() < len) {
int test;
System.out.println("stop");
}
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
pageIds[i] = reservedPages.get(i); pageIds[i] = reservedPages.get(i);
} }
...@@ -172,6 +176,7 @@ public class PageOutputStream extends OutputStream { ...@@ -172,6 +176,7 @@ public class PageOutputStream extends OutputStream {
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
trace.debug("pageOut.storePage fill " + data.getPos()); trace.debug("pageOut.storePage fill " + data.getPos());
} }
reserve(data.getRemaining() + 1);
reserved -= data.getRemaining(); reserved -= data.getRemaining();
data.write(null); data.write(null);
initNextData(); initNextData();
......
...@@ -309,6 +309,14 @@ public class PageStore implements CacheWriter { ...@@ -309,6 +309,14 @@ public class PageStore implements CacheWriter {
} }
log.checkpoint(); log.checkpoint();
switchLog(); switchLog();
byte[] empty = new byte[pageSize];
// TODO avoid to write empty pages
for (int i = PAGE_ID_FREE_LIST_ROOT; i < pageCount; i++) {
if (!isUsed(i)) {
file.seek(i * pageSize);
file.write(empty, 0, pageSize);
}
}
// TODO shrink file if required here // TODO shrink file if required here
// int pageCount = getFreeList().getLastUsed() + 1; // int pageCount = getFreeList().getLastUsed() + 1;
// trace.debug("pageCount:" + pageCount); // trace.debug("pageCount:" + pageCount);
...@@ -505,6 +513,10 @@ public class PageStore implements CacheWriter { ...@@ -505,6 +513,10 @@ public class PageStore implements CacheWriter {
} }
} }
private PageFreeList getFreeListForPage(int pageId) throws SQLException {
return getFreeList((pageId - PAGE_ID_FREE_LIST_ROOT) / freeListPagesPerList);
}
private PageFreeList getFreeList(int i) throws SQLException { private PageFreeList getFreeList(int i) throws SQLException {
int p = PAGE_ID_FREE_LIST_ROOT + i * freeListPagesPerList; int p = PAGE_ID_FREE_LIST_ROOT + i * freeListPagesPerList;
while (p >= pageCount) { while (p >= pageCount) {
...@@ -522,8 +534,7 @@ public class PageStore implements CacheWriter { ...@@ -522,8 +534,7 @@ public class PageStore implements CacheWriter {
} }
private void freePage(int pageId) throws SQLException { private void freePage(int pageId) throws SQLException {
int i = (pageId - PAGE_ID_FREE_LIST_ROOT) / freeListPagesPerList; PageFreeList list = getFreeListForPage(pageId);
PageFreeList list = getFreeList(i);
list.free(pageId); list.free(pageId);
} }
...@@ -533,10 +544,14 @@ public class PageStore implements CacheWriter { ...@@ -533,10 +544,14 @@ public class PageStore implements CacheWriter {
* @param pageId the page to allocate * @param pageId the page to allocate
*/ */
void allocatePage(int pageId) throws SQLException { void allocatePage(int pageId) throws SQLException {
PageFreeList list = getFreeList(pageId / freeListPagesPerList); PageFreeList list = getFreeListForPage(pageId);
list.allocate(pageId); list.allocate(pageId);
} }
private boolean isUsed(int pageId) throws SQLException {
return getFreeListForPage(pageId).isUsed(pageId);
}
/** /**
* Allocate a page. * Allocate a page.
* *
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论