/** * Change the parent page id. * * @param id the new parent page id */ void setParentPageId(int id) { index.getPageStore().logUndo(this, data); changeCount = index.getPageStore().getChangeCount(); written = false; parentPageId = id; }
@Override public boolean canRemove() { return changeCount < index.getPageStore().getChangeCount(); }
@Override void freeRecursive() { index.getPageStore().logUndo(this, data); index.getPageStore().free(getPos()); }
private void updateRowCount(int offset) { if (rowCount != UNKNOWN_ROWCOUNT) { rowCount += offset; } if (rowCountStored != UNKNOWN_ROWCOUNT) { rowCountStored = UNKNOWN_ROWCOUNT; index.getPageStore().logUndo(this, data); if (written) { writeHead(); } index.getPageStore().update(this); } }
@Override void setRowCountStored(int rowCount) { if (rowCount < 0 && pageStoreInternalCount) { return; } this.rowCount = rowCount; if (rowCountStored != rowCount) { rowCountStored = rowCount; index.getPageStore().logUndo(this, data); if (written) { changeCount = index.getPageStore().getChangeCount(); writeHead(); } index.getPageStore().update(this); } }
/** * One of the children has moved to a new page. * * @param oldPos the old position * @param newPos the new position */ void moveChild(int oldPos, int newPos) { for (int i = 0; i < entryCount + 1; i++) { if (childPageIds[i] == oldPos) { index.getPageStore().logUndo(this, data); written = false; changeCount = index.getPageStore().getChangeCount(); childPageIds[i] = newPos; index.getPageStore().update(this); return; } } throw DbException.throwInternalError(oldPos + " " + newPos); }
/** * Change the page id. * * @param id the new page id */ void setPageId(int id) { changeCount = index.getPageStore().getChangeCount(); written = false; index.getPageStore().removeFromCache(getPos()); setPos(id); index.getPageStore().logUndo(this, null); remapChildren(); }
@Override void freeRecursive() { index.getPageStore().logUndo(this, data); index.getPageStore().free(getPos()); for (int i = 0; i < entryCount + 1; i++) { int child = childPageIds[i]; index.getPage(child).freeRecursive(); } }
@Override public void write() { writeData(); index.getPageStore().writePage(getPos(), data); }
/** * Create a new page. * * @param index the index * @param pageId the page id * @param parentPageId the parent * @return the page */ static PageBtreeLeaf create(PageBtreeIndex index, int pageId, int parentPageId) { PageBtreeLeaf p = new PageBtreeLeaf(index, pageId, index.getPageStore() .createData()); index.getPageStore().logUndo(p, null); p.rows = SearchRow.EMPTY_ARRAY; p.parentPageId = parentPageId; p.writeHead(); p.start = p.data.length(); return p; }
/** * Create a new b-tree node page. * * @param index the index * @param pageId the page id * @param parentPageId the parent page id * @return the page */ static PageBtreeNode create(PageBtreeIndex index, int pageId, int parentPageId) { PageBtreeNode p = new PageBtreeNode(index, pageId, index.getPageStore() .createData()); index.getPageStore().logUndo(p, null); p.parentPageId = parentPageId; p.writeHead(); // 4 bytes for the rightmost child page id p.start = p.data.length() + 4; p.rows = SearchRow.EMPTY_ARRAY; if (p.pageStoreInternalCount) { p.rowCount = 0; } return p; }
@Override public void write() { check(); writeData(); index.getPageStore().writePage(getPos(), data); }
@Override protected void remapChildren() { for (int i = 0; i < entryCount + 1; i++) { int child = childPageIds[i]; PageBtree p = index.getPage(child); p.setParentPageId(getPos()); index.getPageStore().update(p); } }
@Override int addRowTry(SearchRow row) { while (true) { int x = find(row, false, true, true); PageBtree page = index.getPage(childPageIds[x]); int splitPoint = page.addRowTry(row); if (splitPoint == -1) { break; } SearchRow pivot = page.getRow(splitPoint - 1); index.getPageStore().logUndo(this, data); int splitPoint2 = addChildTry(pivot); if (splitPoint2 != -1) { return splitPoint2; } PageBtree page2 = page.split(splitPoint); readAllRows(); addChild(x, page2.getPos(), pivot); index.getPageStore().update(page); index.getPageStore().update(page2); index.getPageStore().update(this); } updateRowCount(1); written = false; changeCount = index.getPageStore().getChangeCount(); return -1; }
@Override protected void memoryChange() { if (!PageBtreeIndex.isMemoryChangeRequired()) { return; } int memory = Constants.MEMORY_PAGE_BTREE + index.getPageStore().getPageSize(); if (rows != null) { memory += getEntryCount() * (4 + Constants.MEMORY_POINTER); for (int i = 0; i < entryCount; i++) { SearchRow r = rows[i]; if (r != null) { memory += r.getMemory(); } } } index.memoryChange(memory >> 2); }
@Override PageBtree split(int splitPoint) { int newPageId = index.getPageStore().allocatePage(); PageBtreeNode p2 = PageBtreeNode.create(index, newPageId, parentPageId); index.getPageStore().logUndo(this, data); if (onlyPosition) { // TODO optimize: maybe not required p2.onlyPosition = true; } int firstChild = childPageIds[splitPoint]; readAllRows(); while (splitPoint < entryCount) { p2.addChild(p2.entryCount, childPageIds[splitPoint + 1], getRow(splitPoint)); removeChild(splitPoint); } int lastChild = childPageIds[splitPoint - 1]; removeChild(splitPoint - 1); childPageIds[splitPoint - 1] = lastChild; if (p2.childPageIds == null) { p2.childPageIds = new int[1]; } p2.childPageIds[0] = firstChild; p2.remapChildren(); return p2; }
@Override PageBtree split(int splitPoint) { int newPageId = index.getPageStore().allocatePage(); PageBtreeLeaf p2 = PageBtreeLeaf.create(index, newPageId, parentPageId); while (splitPoint < entryCount) { p2.addRow(getRow(splitPoint), false); removeRow(splitPoint); } memoryChange(); p2.memoryChange(); return p2; }
private void removeChild(int i) { readAllRows(); entryCount--; if (pageStoreInternalCount) { updateRowCount(-index.getPage(childPageIds[i]).getRowCount()); } written = false; changeCount = index.getPageStore().getChangeCount(); if (entryCount < 0) { DbException.throwInternalError("" + entryCount); } if (entryCount > i) { int startNext = i > 0 ? offsets[i - 1] : index.getPageStore().getPageSize(); int rowLength = startNext - offsets[i]; add(offsets, i, entryCount + 1, rowLength); } rows = remove(rows, entryCount + 1, i); offsets = remove(offsets, entryCount + 1, i); childPageIds = remove(childPageIds, entryCount + 2, i); start -= CHILD_OFFSET_PAIR_LENGTH; }
@Override SearchRow remove(SearchRow row) { int at = find(row, false, false, true); SearchRow delete = getRow(at); if (index.compareRows(row, delete) != 0 || delete.getKey() != row.getKey()) { throw DbException.get(ErrorCode.ROW_NOT_FOUND_WHEN_DELETING_1, index.getSQL() + ": " + row); } index.getPageStore().logUndo(this, data); if (entryCount == 1) { // the page is now empty return row; } removeRow(at); memoryChange(); index.getPageStore().update(this); if (at == entryCount) { // the last row changed return getRow(at - 1); } // the last row didn't change return null; }
@Override public void moveTo(Session session, int newPos) { PageStore store = index.getPageStore(); readAllRows(); PageBtreeLeaf p2 = PageBtreeLeaf.create(index, newPos, parentPageId); store.logUndo(this, data); store.logUndo(p2, null); p2.rows = rows; p2.entryCount = entryCount; p2.offsets = offsets; p2.onlyPosition = onlyPosition; p2.parentPageId = parentPageId; p2.start = start; store.update(p2); if (parentPageId == ROOT) { index.setRootPageId(session, newPos); } else { PageBtreeNode p = (PageBtreeNode) store.getPage(parentPageId); p.moveChild(getPos(), newPos); } store.free(getPos()); }