提交 1944438b authored 作者: Thomas Mueller's avatar Thomas Mueller

Page store: automatically compact the database (work in progress)

上级 d220c5d3
......@@ -1238,6 +1238,8 @@ public class Database implements DataHandler {
pageStore.checkpoint();
pageStore.trim();
} catch (Throwable e) {
int test;
// e.printStackTrace(System.out);
traceSystem.getTrace(Trace.DATABASE).error("close", e);
}
}
......
......@@ -27,11 +27,10 @@ import org.h2.value.ValueNull;
* This is the most common type of index, a b tree index.
* Only the data of the indexed columns are stored in the index.
*/
public class PageBtreeIndex extends BaseIndex {
public class PageBtreeIndex extends PageIndex {
private PageStore store;
private TableData tableData;
private final int headPos;
private boolean needRebuild;
private long rowCount;
......@@ -41,25 +40,24 @@ public class PageBtreeIndex extends BaseIndex {
// trace.setLevel(TraceSystem.DEBUG);
tableData = table;
if (!database.isPersistent() || id < 0) {
this.headPos = 0;
throw Message.throwInternalError("" + indexName);
}
this.store = database.getPageStore();
store.addIndex(this);
if (headPos == Index.EMPTY_HEAD) {
// new index
rootPageId = store.allocatePage();
needRebuild = true;
this.headPos = headPos = store.allocatePage();
// TODO currently the head position is stored in the log
// it should not for new tables, otherwise redo of other operations
// must ensure this page is not used for other things
store.addMeta(this, session, headPos);
PageBtreeLeaf root = new PageBtreeLeaf(this, headPos, store.createData());
store.addMeta(this, session);
PageBtreeLeaf root = new PageBtreeLeaf(this, rootPageId, store.createData());
root.parentPageId = PageBtree.ROOT;
store.updateRecord(root, true, root.data);
} else {
this.headPos = headPos;
PageBtree root = getPage(headPos);
rootPageId = store.getRootPageId(this);
PageBtree root = getPage(rootPageId);
rowCount = root.getRowCount();
if (rowCount == 0 && store.isRecoveryRunning()) {
needRebuild = true;
......@@ -75,10 +73,6 @@ public class PageBtreeIndex extends BaseIndex {
}
}
public int getHeadPos() {
return headPos;
}
public void add(Session session, Row row) throws SQLException {
if (trace.isDebugEnabled()) {
trace.debug("add " + row.getPos());
......@@ -86,7 +80,7 @@ public class PageBtreeIndex extends BaseIndex {
// safe memory
SearchRow newRow = getSearchRow(row);
while (true) {
PageBtree root = getPage(headPos);
PageBtree root = getPage(rootPageId);
int splitPoint = root.addRowTry(newRow);
if (splitPoint == -1) {
break;
......@@ -100,8 +94,8 @@ public class PageBtreeIndex extends BaseIndex {
int rootPageId = root.getPos();
int id = store.allocatePage();
page1.setPageId(id);
page1.setParentPageId(headPos);
page2.setParentPageId(headPos);
page1.setParentPageId(rootPageId);
page2.setParentPageId(rootPageId);
PageBtreeNode newRoot = new PageBtreeNode(this, rootPageId, store.createData());
newRoot.parentPageId = PageBtree.ROOT;
newRoot.init(page1, pivot, page2);
......@@ -161,7 +155,7 @@ public class PageBtreeIndex extends BaseIndex {
if (SysProperties.CHECK && store == null) {
throw Message.getSQLException(ErrorCode.OBJECT_CLOSED);
}
PageBtree root = getPage(headPos);
PageBtree root = getPage(rootPageId);
PageBtreeCursor cursor = new PageBtreeCursor(session, this, last);
root.find(cursor, first, bigger);
return cursor;
......@@ -180,7 +174,7 @@ public class PageBtreeIndex extends BaseIndex {
}
return cursor;
}
PageBtree root = getPage(headPos);
PageBtree root = getPage(rootPageId);
PageBtreeCursor cursor = new PageBtreeCursor(session, this, null);
root.last(cursor);
cursor.previous();
......@@ -223,7 +217,7 @@ public class PageBtreeIndex extends BaseIndex {
if (rowCount == 1) {
removeAllRows();
} else {
PageBtree root = getPage(headPos);
PageBtree root = getPage(rootPageId);
root.remove(row);
rowCount--;
}
......@@ -234,7 +228,7 @@ public class PageBtreeIndex extends BaseIndex {
trace.debug("remove");
}
removeAllRows();
store.freePage(headPos, false, null);
store.freePage(rootPageId, false, null);
store.removeMeta(this, session);
}
......@@ -250,11 +244,11 @@ public class PageBtreeIndex extends BaseIndex {
}
private void removeAllRows() throws SQLException {
PageBtree root = getPage(headPos);
PageBtree root = getPage(rootPageId);
root.freeChildren();
root = new PageBtreeLeaf(this, headPos, store.createData());
root = new PageBtreeLeaf(this, rootPageId, store.createData());
root.parentPageId = PageBtree.ROOT;
store.removeRecord(headPos);
store.removeRecord(rootPageId);
store.updateRecord(root, true, null);
rowCount = 0;
}
......@@ -358,4 +352,11 @@ public class PageBtreeIndex extends BaseIndex {
return true;
}
public void setRootPageId(Session session, int newPos) throws SQLException {
store.removeMeta(this, session);
this.rootPageId = newPos;
store.addMeta(this, session);
store.addIndex(this);
}
}
......@@ -9,11 +9,13 @@ package org.h2.index;
import java.sql.SQLException;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.result.SearchRow;
import org.h2.store.Data;
import org.h2.store.DataPage;
import org.h2.store.Page;
import org.h2.store.PageStore;
/**
* A b-tree leaf page that contains index data.
......@@ -283,4 +285,24 @@ public class PageBtreeLeaf extends PageBtree {
return "page[" + getPos() + "] b-tree leaf table:" + index.getId() + " entries:" + entryCount;
}
public void moveTo(Session session, int newPos) throws SQLException {
PageStore store = index.getPageStore();
PageBtreeLeaf p2 = new PageBtreeLeaf(index, newPos, store.createData());
readAllRows();
p2.rows = rows;
p2.entryCount = entryCount;
p2.offsets = offsets;
p2.onlyPosition = onlyPosition;
p2.parentPageId = parentPageId;
p2.start = start;
store.updateRecord(p2, false, null);
if (parentPageId == ROOT) {
index.setRootPageId(session, newPos);
} else {
PageBtreeNode p = (PageBtreeNode) store.getPage(parentPageId);
p.moveChild(getPos(), newPos);
}
store.freePage(getPos(), true, data);
}
}
......@@ -9,6 +9,7 @@ package org.h2.index;
import java.sql.SQLException;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.result.SearchRow;
import org.h2.store.Data;
......@@ -477,4 +478,42 @@ public class PageBtreeNode extends PageBtree {
return "page[" + getPos() + "] b-tree node table:" + index.getId() + " entries:" + entryCount;
}
public void moveTo(Session session, int newPos) throws SQLException {
PageStore store = index.getPageStore();
PageBtreeNode p2 = new PageBtreeNode(index, newPos, store.createData());
readAllRows();
p2.childPageIds = childPageIds;
p2.rows = rows;
p2.entryCount = entryCount;
p2.offsets = offsets;
p2.onlyPosition = onlyPosition;
p2.parentPageId = parentPageId;
p2.start = start;
store.updateRecord(p2, false, null);
if (parentPageId == ROOT) {
index.setRootPageId(session, newPos);
} else {
PageBtreeNode p = (PageBtreeNode) store.getPage(parentPageId);
p.moveChild(getPos(), newPos);
}
for (int i = 0; i < childPageIds.length; i++) {
PageBtree p = (PageBtree) store.getPage(childPageIds[i]);
p.setParentPageId(newPos);
store.updateRecord(p, true, p.data);
}
store.freePage(getPos(), true, data);
}
public void moveChild(int oldPos, int newPos) throws SQLException {
for (int i = 0; i < childPageIds.length; i++) {
if (childPageIds[i] == oldPos) {
written = false;
childPageIds[i] = newPos;
index.getPageStore().updateRecord(this, true, data);
return;
}
}
throw Message.throwInternalError();
}
}
\ No newline at end of file
......@@ -399,4 +399,24 @@ public class PageDataLeaf extends PageData {
return "page[" + getPos() + "] data leaf table:" + index.getId() + " entries:" + entryCount;
}
public void moveTo(Session session, int newPos) throws SQLException {
// PageStore store = index.getPageStore();
// PageBtreeLeaf p2 = new PageBtreeLeaf(index, newPos, store.createData());
// readAllRows();
// p2.rows = rows;
// p2.entryCount = entryCount;
// p2.offsets = offsets;
// p2.onlyPosition = onlyPosition;
// p2.parentPageId = parentPageId;
// p2.start = start;
// store.updateRecord(p2, false, null);
// if (firstOverflowPageId != 0) {
// }
// if (parentPageId == ROOT) {
// } else {
// PageBtreeNode p = (PageBtreeNode) store.getPage(parentPageId);
// p.moveChild(getPos(), newPos);
// }
}
}
......@@ -329,4 +329,9 @@ public class PageDataNode extends PageData {
return "page[" + getPos() + "] data node table:" + index.getId() + " entries:" + entryCount;
}
public void moveTo(Session session, int newPos) throws SQLException {
// TODO Auto-generated method stub
}
}
......@@ -8,6 +8,7 @@ package org.h2.index;
import java.sql.SQLException;
import org.h2.constant.ErrorCode;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.store.Data;
import org.h2.store.DataPage;
......@@ -180,4 +181,9 @@ public class PageDataOverflow extends Page {
this.parentPage = parent;
}
public void moveTo(Session session, int newPos) throws SQLException {
// TODO Auto-generated method stub
}
}
/*
* Copyright 2004-2009 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.index;
/**
* A page store index.
*/
public abstract class PageIndex extends BaseIndex {
protected int rootPageId;
public int getRootPageId() {
return rootPageId;
}
public int getHeadPos() {
return 0;
}
}
......@@ -33,11 +33,10 @@ import org.h2.value.ValueLob;
* all rows of a table. Each regular table has one such object, even if no
* primary key or indexes are defined.
*/
public class PageScanIndex extends BaseIndex implements RowIndex {
public class PageScanIndex extends PageIndex implements RowIndex {
private PageStore store;
private TableData tableData;
private final int headPos;
private int lastKey;
private long rowCount;
private HashSet<Row> delta;
......@@ -55,22 +54,21 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
this.store = database.getPageStore();
store.addIndex(this);
if (!database.isPersistent()) {
this.headPos = 0;
throw Message.throwInternalError(table.getName());
}
if (headPos == Index.EMPTY_HEAD) {
// new table
this.headPos = headPos = store.allocatePage();
rootPageId = store.allocatePage();
// TODO currently the head position is stored in the log
// it should not for new tables, otherwise redo of other operations
// must ensure this page is not used for other things
store.addMeta(this, session, headPos);
PageDataLeaf root = new PageDataLeaf(this, headPos, store.createData());
store.addMeta(this, session);
PageDataLeaf root = new PageDataLeaf(this, rootPageId, store.createData());
root.parentPageId = PageData.ROOT;
store.updateRecord(root, true, root.data);
} else {
this.headPos = headPos;
PageData root = getPage(headPos, 0);
rootPageId = store.getRootPageId(this);
PageData root = getPage(rootPageId, 0);
lastKey = root.getLastKey();
rowCount = root.getRowCount();
// could have been created before, but never committed
......@@ -86,10 +84,6 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
table.setRowCount(rowCount);
}
public int getHeadPos() {
return headPos;
}
public void add(Session session, Row row) throws SQLException {
if (row.getPos() == 0) {
row.setPos(++lastKey);
......@@ -112,7 +106,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
}
}
while (true) {
PageData root = getPage(headPos, 0);
PageData root = getPage(rootPageId, 0);
int splitPoint = root.addRowTry(row);
if (splitPoint == -1) {
break;
......@@ -126,8 +120,8 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
int rootPageId = root.getPos();
int id = store.allocatePage();
page1.setPageId(id);
page1.setParentPageId(headPos);
page2.setParentPageId(headPos);
page1.setParentPageId(rootPageId);
page2.setParentPageId(rootPageId);
PageDataNode newRoot = new PageDataNode(this, rootPageId, store.createData());
newRoot.parentPageId = PageData.ROOT;
newRoot.init(page1, pivot, page2);
......@@ -177,8 +171,8 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
empty.parentPageId = parent;
return empty;
}
if (p.index.headPos != headPos) {
throw Message.throwInternalError("Wrong index: " + p.index.getName() + ":" + p.index.headPos + " " + getName() + ":" + headPos);
if (p.index.rootPageId != rootPageId) {
throw Message.throwInternalError("Wrong index: " + p.index.getName() + ":" + p.index.rootPageId + " " + getName() + ":" + rootPageId);
}
if (parent != -1) {
if (p.getParentPageId() != parent) {
......@@ -193,7 +187,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
}
public Cursor find(Session session, SearchRow first, SearchRow last) throws SQLException {
PageData root = getPage(headPos, 0);
PageData root = getPage(rootPageId, 0);
return root.find(session);
}
......@@ -226,7 +220,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
removeAllRows();
} else {
int key = row.getPos();
PageData root = getPage(headPos, 0);
PageData root = getPage(rootPageId, 0);
root.remove(key);
invalidateRowCount();
rowCount--;
......@@ -248,7 +242,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
}
private void invalidateRowCount() throws SQLException {
PageData root = getPage(headPos, 0);
PageData root = getPage(rootPageId, 0);
root.setRowCountStored(PageData.UNKNOWN_ROWCOUNT);
}
......@@ -257,7 +251,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
trace.debug("remove");
}
removeAllRows();
store.freePage(headPos, false, null);
store.freePage(rootPageId, false, null);
store.removeMeta(this, session);
}
......@@ -277,11 +271,11 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
}
private void removeAllRows() throws SQLException {
PageData root = getPage(headPos, 0);
PageData root = getPage(rootPageId, 0);
root.freeChildren();
root = new PageDataLeaf(this, headPos, store.createData());
root = new PageDataLeaf(this, rootPageId, store.createData());
root.parentPageId = PageData.ROOT;
store.removeRecord(headPos);
store.removeRecord(rootPageId);
store.updateRecord(root, true, null);
rowCount = 0;
lastKey = 0;
......@@ -292,7 +286,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
}
public Row getRow(Session session, int key) throws SQLException {
PageData root = getPage(headPos, 0);
PageData root = getPage(rootPageId, 0);
return root.getRow(key);
}
......@@ -348,7 +342,7 @@ public class PageScanIndex extends BaseIndex implements RowIndex {
}
// can not close the index because it might get used afterwards,
// for example after running recovery
PageData root = getPage(headPos, 0);
PageData root = getPage(rootPageId, 0);
root.setRowCountStored(MathUtils.convertLongToInt(rowCount));
}
......
......@@ -6,6 +6,9 @@
*/
package org.h2.store;
import java.sql.SQLException;
import org.h2.engine.Session;
/**
* A page. Format:
......@@ -66,4 +69,13 @@ public abstract class Page extends Record {
*/
public static final int TYPE_STREAM_DATA = 8;
/**
* Copy the data to a new location, change the parent to point to the new
* location, and free up the current page.
*
* @param session the session
* @param newPos the new position
*/
public abstract void moveTo(Session session, int newPos) throws SQLException;
}
......@@ -7,6 +7,7 @@ package org.h2.store;
import java.sql.SQLException;
import org.h2.constant.ErrorCode;
import org.h2.engine.Session;
import org.h2.message.Message;
import org.h2.util.BitField;
......@@ -102,7 +103,7 @@ public class PageFreeList extends Page {
if (free >= pageCount) {
return -1;
}
return free;
return free + getPos();
}
int getLastUsed() {
......@@ -197,4 +198,10 @@ public class PageFreeList extends Page {
return used.get(pageId - getPos());
}
public void moveTo(Session session, int newPos) throws SQLException {
// the old data does not need to be copied, as free-list pages
// at the end of the file are not required
store.freePage(getPos(), true, data);
}
}
......@@ -258,7 +258,7 @@ public class PageLog {
int tableId = in.readInt();
Row row = readRow(in, data);
if (stage == RECOVERY_STAGE_UNDO && x == ADD) {
store.allocateIfHead(pos, tableId, row);
store.allocateIfIndexRoot(pos, tableId, row);
} else if (stage == RECOVERY_STAGE_REDO) {
if (isSessionCommitted(sessionId, logId, pos)) {
if (trace.isDebugEnabled()) {
......@@ -517,6 +517,7 @@ public class PageLog {
}
session.addLogPos(logSectionId, logPos);
row.setLastLog(logSectionId, logPos);
logPos++;
data.reset();
data.checkCapacity(row.getByteCount(data));
......@@ -545,6 +546,8 @@ public class PageLog {
trace.debug("log truncate s:" + session.getId() + " table:" + tableId);
}
session.addLogPos(logSectionId, logPos);
logPos++;
data.reset();
out.write(TRUNCATE);
out.writeInt(session.getId());
......@@ -579,6 +582,7 @@ public class PageLog {
}
undo = new BitField();
logSectionId++;
logPos = 0;
pageOut.fillPage();
int currentDataPage = pageOut.getCurrentDataPageId();
logSectionPageMap.put(logSectionId, currentDataPage);
......@@ -588,6 +592,10 @@ public class PageLog {
return logSectionId;
}
long getLogPos() {
return logPos;
}
/**
* Remove all pages until the given log (excluding).
*
......
......@@ -24,11 +24,13 @@ import org.h2.index.PageBtreeNode;
import org.h2.index.PageDataLeaf;
import org.h2.index.PageDataNode;
import org.h2.index.PageDataOverflow;
import org.h2.index.PageIndex;
import org.h2.index.PageScanIndex;
import org.h2.log.InDoubtTransaction;
import org.h2.log.LogSystem;
import org.h2.message.Message;
import org.h2.message.Trace;
import org.h2.message.TraceSystem;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.schema.Schema;
......@@ -43,6 +45,7 @@ import org.h2.util.CacheObject;
import org.h2.util.CacheWriter;
import org.h2.util.FileUtils;
import org.h2.util.IntArray;
import org.h2.util.IntIntHashMap;
import org.h2.util.New;
import org.h2.util.ObjectArray;
import org.h2.util.StatementBuilder;
......@@ -66,16 +69,17 @@ import org.h2.value.ValueString;
* The format of page 1 and 2 is:
* <ul>
* <li>0-7: write counter (incremented each time the header changes)</li>
* <li>8-11: log trunk page (initially 4)</li>
* <li>12-15: log data page (initially 5)</li>
* <li>8-11: log trunk page (0 for none)</li>
* <li>12-15: log data page (0 for none)</li>
* <li>16-23: checksum of bytes 0-15 (CRC32)</li>
* </ul>
* Page 3 contains the first free list page.
* Page 4 contains the meta table root page.
* For a new database, page 5 contains the first log trunk page.
*/
public class PageStore implements CacheWriter {
// TODO database head pos = id? head pos > root pos?
// TODO a correctly closed database should not contain log pages
// TODO shrinking: a way to load pages centrally
// TODO shrinking: Page.moveTo(int pageId).
......@@ -196,7 +200,8 @@ public class PageStore implements CacheWriter {
private Schema metaSchema;
private TableData metaTable;
private PageScanIndex metaIndex;
private HashMap<Integer, Index> metaObjects = New.hashMap();
private IntIntHashMap metaRootPageId = new IntIntHashMap();
private HashMap<Integer, PageIndex> metaObjects = New.hashMap();
/**
* The map of reserved pages, to ensure index head pages
......@@ -259,6 +264,7 @@ public class PageStore implements CacheWriter {
*/
public void open() throws SQLException {
try {
metaRootPageId.put(META_TABLE_ID, PAGE_ID_META_ROOT);
if (FileUtils.exists(fileName)) {
if (FileUtils.length(fileName) < MIN_PAGE_COUNT * PAGE_SIZE_MIN) {
// the database was not fully created
......@@ -354,17 +360,50 @@ public class PageStore implements CacheWriter {
}
}
private void compact() throws SQLException {
trim();
int full = pageCount - 1;
/**
* Shrink the file so there are no empty pages at the end.
*/
public void trim() throws SQLException {
int test;
int maxMove = 100000;
for (int x = pageCount - 1, j = 0; x > MIN_PAGE_COUNT && j < maxMove; x--, j++) {
compact(x);
}
for (int i = getFreeListId(pageCount); i >= 0; i--) {
int last = getFreeList(i).getLastUsed();
if (last != -1) {
pageCount = last + 1;
break;
}
}
trace.debug("pageCount:" + pageCount);
file.setLength((long) pageCount << pageSizeShift);
}
private void compact(int full) throws SQLException {
int free = -1;
for (int i = 0; i < pageCount && free != -1; i++) {
for (int i = 0; i < pageCount; i++) {
free = getFreeList(i).getFirstFree();
if (free != -1) {
break;
}
}
if (free == -1 || free < 10) {
if (free == -1 || free >= full) {
return;
}
Page f = (Page) cache.get(free);
if (f != null) {
Message.throwInternalError("not free: " + f);
}
Page p = getPage(full);
if (p != null) {
trace.debug("move " + p.getPos() + " to " + free);
long logSection = log.getLogSectionId(), logPos = log.getLogPos();
p.moveTo(systemSession, free);
if (log.getLogSectionId() == logSection || log.getLogPos() != logPos) {
commit(systemSession);
}
}
}
/**
......@@ -447,21 +486,6 @@ public class PageStore implements CacheWriter {
return p;
}
/**
* Shrink the file so there are no empty pages at the end.
*/
public void trim() throws SQLException {
for (int i = getFreeListId(pageCount); i >= 0; i--) {
int last = getFreeList(i).getLastUsed();
if (last != -1) {
pageCount = last + 1;
break;
}
}
trace.debug("pageCount:" + pageCount);
file.setLength((long) pageCount << pageSizeShift);
}
private void switchLog() throws SQLException {
trace.debug("switchLog");
Session[] sessions = database.getSessions(true);
......@@ -977,19 +1001,19 @@ public class PageStore implements CacheWriter {
}
/**
* Reserve the page if this is a index head entry.
* Reserve the page if this is a index root page entry.
*
* @param logPos the redo log position
* @param tableId the table id
* @param row the row
*/
void allocateIfHead(int logPos, int tableId, Row row) throws SQLException {
void allocateIfIndexRoot(int logPos, int tableId, Row row) throws SQLException {
if (tableId == META_TABLE_ID) {
int headPos = row.getValue(3).getInt();
int rootPageId = row.getValue(3).getInt();
if (reservedPages == null) {
reservedPages = New.hashMap();
}
reservedPages.put(headPos, logPos);
reservedPages.put(rootPageId, logPos);
}
}
......@@ -1041,9 +1065,8 @@ public class PageStore implements CacheWriter {
cols.add(new Column("OPTIONS", Value.STRING));
cols.add(new Column("COLUMNS", Value.STRING));
metaSchema = new Schema(database, 0, "", null, true);
int headPos = PAGE_ID_META_ROOT;
metaTable = new TableData(metaSchema, "PAGE_INDEX",
META_TABLE_ID, cols, false, true, true, false, headPos, systemSession);
META_TABLE_ID, cols, false, true, true, false, 0, systemSession);
metaIndex = (PageScanIndex) metaTable.getScanIndex(
systemSession);
metaObjects.clear();
......@@ -1084,7 +1107,7 @@ public class PageStore implements CacheWriter {
int id = row.getValue(0).getInt();
int type = row.getValue(1).getInt();
int parent = row.getValue(2).getInt();
int headPos = row.getValue(3).getInt();
int rootPageId = row.getValue(3).getInt();
String options = row.getValue(4).getString();
String columnList = row.getValue(5).getString();
String[] columns = StringUtils.arraySplit(columnList, ',', false);
......@@ -1094,9 +1117,10 @@ public class PageStore implements CacheWriter {
trace.debug("addMeta id=" + id + " type=" + type + " parent=" + parent + " columns=" + columnList);
}
if (redo) {
writePage(headPos, createData());
allocatePage(headPos);
writePage(rootPageId, createData());
allocatePage(rootPageId);
}
metaRootPageId.put(id, rootPageId);
if (type == META_TYPE_SCAN_INDEX) {
ObjectArray<Column> columnArray = ObjectArray.newInstance();
for (int i = 0; i < columns.length; i++) {
......@@ -1105,7 +1129,7 @@ public class PageStore implements CacheWriter {
}
String[] ops = StringUtils.arraySplit(options, ',', true);
boolean temp = ops.length == 3 && ops[2].equals("temp");
TableData table = new TableData(metaSchema, "T" + id, id, columnArray, temp, true, true, false, headPos, session);
TableData table = new TableData(metaSchema, "T" + id, id, columnArray, temp, true, true, false, 0, session);
CompareMode mode = CompareMode.getInstance(ops[0], Integer.parseInt(ops[1]));
table.setCompareMode(mode);
meta = table.getScanIndex(session);
......@@ -1130,9 +1154,9 @@ public class PageStore implements CacheWriter {
ic.column = column;
cols[i] = ic;
}
meta = table.addIndex(session, "I" + id, id, cols, indexType, headPos, null);
meta = table.addIndex(session, "I" + id, id, cols, indexType, id, null);
}
metaObjects.put(id, meta);
metaObjects.put(id, (PageIndex) meta);
}
/**
......@@ -1140,7 +1164,7 @@ public class PageStore implements CacheWriter {
*
* @param index the index
*/
public void addIndex(Index index) {
public void addIndex(PageIndex index) {
metaObjects.put(index.getId(), index);
}
......@@ -1149,9 +1173,8 @@ public class PageStore implements CacheWriter {
*
* @param index the index to add
* @param session the session
* @param headPos the head position
*/
public void addMeta(Index index, Session session, int headPos) throws SQLException {
public void addMeta(PageIndex index, Session session) throws SQLException {
int type = index instanceof PageScanIndex ? META_TYPE_SCAN_INDEX : META_TYPE_BTREE_INDEX;
IndexColumn[] columns = index.getIndexColumns();
StatementBuilder buff = new StatementBuilder();
......@@ -1176,7 +1199,7 @@ public class PageStore implements CacheWriter {
row.setValue(0, ValueInt.get(index.getId()));
row.setValue(1, ValueInt.get(type));
row.setValue(2, ValueInt.get(table.getId()));
row.setValue(3, ValueInt.get(headPos));
row.setValue(3, ValueInt.get(index.getRootPageId()));
row.setValue(4, ValueString.get(options));
row.setValue(5, ValueString.get(columnList));
row.setPos(index.getId() + 1);
......@@ -1288,6 +1311,18 @@ public class PageStore implements CacheWriter {
}
}
int getLogFirstTrunkPage() {
return this.logFirstTrunkPage;
}
int getLogFirstDataPage() {
return this.logFirstDataPage;
}
public int getRootPageId(PageIndex index) {
return metaRootPageId.get(index.getId());
}
// TODO implement checksum
// private void updateChecksum(byte[] d, int pos) {
// int ps = pageSize;
......
......@@ -7,6 +7,7 @@
package org.h2.store;
import java.sql.SQLException;
import org.h2.engine.Session;
/**
* A data page of a stream. The format is:
......@@ -160,4 +161,23 @@ public class PageStreamData extends Page {
remaining = length;
}
public void moveTo(Session session, int newPos) throws SQLException {
// PageStreamData d2 = new PageStreamData(store, newPos, trunk);
// d2.initWrite();
// initRead();
// byte[] buff = new byte[remaining];
// read(buff, 0, remaining);
// d2.write(buff, 0, remaining);
// store.updateRecord(d2, false, null);
// PageStreamTrunk t = (PageStreamTrunk) store.getPage(trunk);
// t.moveChild(getPos(), newPos);
// store.freePage(getPos(), true, data);
}
void setTrunkPage(int newTrunk) throws SQLException {
this.trunk = newTrunk;
data.setInt(0, trunk);
store.updateRecord(this, true, data);
}
}
\ No newline at end of file
......@@ -7,6 +7,7 @@
package org.h2.store;
import java.sql.SQLException;
import org.h2.engine.Session;
/**
* A trunk page of a stream. It contains the page numbers of the stream, and
......@@ -180,4 +181,37 @@ public class PageStreamTrunk extends Page {
return store.getPageSize() >> 2;
}
/**
* One of the children has moved to another place.
*
* @param oldPos the old position
* @param newPos the new position
*/
void moveChild(int oldPos, int newPos) throws SQLException {
for (int i = 0; i < pageIds.length; i++) {
if (pageIds[i] == oldPos) {
pageIds[i] = newPos;
break;
}
}
store.updateRecord(this, true, data);
}
public void moveTo(Session session, int newPos) throws SQLException {
// PageStreamTrunk p2 = new PageStreamTrunk(store, parent, newPos, nextTrunk, pageIds);
// store.updateRecord(p2, false, null);
// for (int i = 0; i < pageCount; i++) {
// int p = pageIds[i];
// PageStreamData d = (PageStreamData) store.getPage(p);
// if (d != null) {
// d.setTrunkPage(newPos);
// }
// }
// if (store.getLogFirstTrunkPage() == getPos()) {
// int dataPageId = store.getLogFirstDataPage();
// store.setLogFirstPage(newPos, dataPageId);
// }
// store.freePage(getPos(), true, data);
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论