📄 branchcontrolrow.java
字号:
// newbranchrow only valid while contents of split_branch_row // remain unchanged. newbranchrow = null; // Copy the rows from the split point, but not including it (since // the split point is turning into the left child of the new // branch), onto the new page. Purge the rows including the split // point from the current page. int num_rows_to_move = this.page.recordCount() - (splitpoint + 1); if (num_rows_to_move > 0) { this.page.copyAndPurge( newbranch.page, splitpoint + 1, num_rows_to_move, 1); } // remove the splitpoint row, we didn't copy it because it became // the "left child", but we do need to get rid of it. this.page.purgeAtSlot(splitpoint, 1, true); // Test fail after of copy of rows to new page. if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("branch_split_abort3")) { throw StandardException.newException( SQLState.BTREE_ABORT_THROUGH_TRACE); } } // Test fail after purge of rows on old page. if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("branch_split_abort4")) { throw StandardException.newException( SQLState.BTREE_ABORT_THROUGH_TRACE); } } // Check pages that have been altered by above split if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("enableBtreeConsistencyCheck")) { parent.checkConsistency(open_btree, null, false); newbranch.checkConsistency(open_btree, parent, false); this.checkConsistency(open_btree, parent, false); } } // Fix up the parent links on the pages for the rows that moved to // the new branch. newbranch.fixChildrensParents(open_btree, null); // At this point a unit of work in the split down the tree has // been performed in an internal transaction (ie. writes have been // done to latched pages), and the resulting // tree is logically consistent, thus the work can be committed. // This work must be committed before any latches are released. open_btree.getXactMgr().commit(); // Decide whether we're following the current page or the new page. BranchControlRow pagetofollow; if (CompareIndexRowToKey( splitrow, split_branch_row.getRow(), split_branch_row.getRow().length - 1, 0, open_btree.getConglomerate().ascDescInfo) >= 0) { // Follow the new branch pagetofollow = newbranch; this.release(); } else { // Follow the current branch pagetofollow = this; newbranch.release(); } // At this point we hold latches on the parent, and the current // child of the page that we are following. Note that committing // the internal transaction did not release the latches. if (SanityManager.DEBUG) { SanityManager.ASSERT(parent != null); SanityManager.ASSERT(parent.page.isLatched()); SanityManager.ASSERT( pagetofollow.page.isLatched()); } // Recurse down the tree splitting if necessary. return( pagetofollow.splitFor( open_btree, template, parent, splitrow, flag)); } if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("enableBtreeConsistencyCheck")) { this.checkConsistency(open_btree, parent, false); } } // Don't need the parent any more. if (parent != null) parent.release(); // RESOLVE (mikem) - should this be passed in? BranchRow branch_template = BranchRow.createEmptyTemplate(open_btree.getConglomerate()); SearchParameters sp = new SearchParameters( splitrow, SearchParameters.POSITION_LEFT_OF_PARTIAL_KEY_MATCH, branch_template.getRow(), open_btree, false); searchForEntry(sp); childpage = this.getChildPageAtSlot(open_btree, sp.resultSlot); return(childpage.splitFor(open_btree, template, this, splitrow, flag)); } /* ** Debug/consistency check Methods of ControlRow: */ /** ** Perform consistency checks for a branch page. The checks ** specific to a branch page are: ** <menu> ** <li> The rows on the page are indeed branch rows, and ** they all have the correct number of fields (which ** is the b-tree's key fields plus one for the child ** page number. ** <li> The child pages pointed to by the left child pointer ** and the index rows are linked together in the same ** order that they appear on the page. ** <li> The child pages themselves are all consistent. ** </menu> ** This method also performs the consistency checks that ** are common to both leaf and branch pages (see ** ControlRow.checkGeneric). ** ** @exception StandardException Standard exception policy. **/ public int checkConsistency( OpenBTree btree, ControlRow parent, boolean check_other_pages) throws StandardException { // Do the consistency checks that are common to all // types of pages. checkGeneric(btree, parent, check_other_pages); // Branch specific Control Row checks. if (SanityManager.DEBUG) { SanityManager.ASSERT( this.getLevel() > 0, "branch not above level 0"); // RESOLVE (mikem) - how to check right version? /* if (this.getVersion() != CURRENT_BRANCH_VERSION) SanityManager.THROWASSERT( "Expected branch version:(" + CURRENT_BRANCH_VERSION + ") but got (" + this.getVersion()); */ SanityManager.ASSERT( this.page.fetchNumFieldsAtSlot(CR_SLOT) == BranchControlRow.CR_NCOLUMNS); SanityManager.ASSERT(getLeftChildPageno() != ContainerHandle.INVALID_PAGE_NUMBER); // RESOLVE (mikem) - this makes an assumption about page numbering, // that may not be always valid in all implementations but has // been useful in finding bugs with uninitialized fields. SanityManager.ASSERT(getLeftChildPageno() >= BTree.ROOTPAGEID); } // The remaining checks are specific to branch pages. if (SanityManager.DEBUG) { // Check that all the branch rows are branch rows // (we'll get a case error otherwise), and have the right // number of columns. Every branch row should have the // btree's key columns plus one for the child link. int numslots = this.page.recordCount(); for (int slot = 1; slot < numslots; slot++) { if ((this.page.fetchNumFieldsAtSlot(slot) != (btree.getConglomerate().nKeyFields + 1))) SanityManager.THROWASSERT( "row[" + slot + "]" + " has " + this.page.fetchNumFieldsAtSlot(slot) + " columns, should have at least " + (btree.getConglomerate().nKeyFields + 1)); SanityManager.ASSERT(this.getChildPageIdAtSlot(btree, slot) != ContainerHandle.INVALID_PAGE_NUMBER); // Rows on branch pages are never deleted, they are only purged. SanityManager.ASSERT(!this.page.isDeletedAtSlot(slot)); // RESOLVE (mikem) - this makes an assumption about page // numbering, that may not be always valid in all // implementations but has been useful in finding bugs with // uninitialized fields. SanityManager.ASSERT(getLeftChildPageno() >= BTree.ROOTPAGEID); } } // Check that the linkage of the children is in the // same order as the branch rows. // RESOLVE (mikem) enable when multiple latches work. if (check_other_pages) checkChildOrderAgainstRowOrder(btree); // Check the children. int nchildren = 0; // RESOLVE (mikem) enable when multiple latches work. if (check_other_pages) nchildren = checkChildren(btree); // Return the number of children visited plus one for this page. return nchildren + 1; } private int checkChildren(OpenBTree btree) throws StandardException { int nchildren = 0; ControlRow childpage = null; try { // Check the left child. childpage = this.getLeftChild(btree); nchildren += childpage.checkConsistency(btree, this, true); childpage.release(); childpage = null; // Check children from each index row. int numslots = this.page.recordCount(); for (int slot = 1; slot < numslots; slot++) { childpage = this.getChildPageAtSlot(btree, slot); nchildren += childpage.checkConsistency(btree, this, true); childpage.release(); childpage = null; } return(nchildren); } finally { if (childpage != null) childpage.release(); } } private void checkChildOrderAgainstRowOrder(OpenBTree btree) throws StandardException { ControlRow cur = null; ControlRow prev = null; try { prev = this.getLeftChild(btree); int numslots = this.page.recordCount(); for (int slot = 1; slot < numslots; slot++) { cur = this.getChildPageAtSlot(btree, slot); long shouldbecur_pageno = prev.getrightSiblingPageNumber(); if (SanityManager.DEBUG) { if (shouldbecur_pageno != cur.page.getPageNumber()) SanityManager.THROWASSERT( "child linkage error going right.\n" + "cur page control row = " + cur + "\n" + "prev page control row = " + prev + "\n"); } long shouldbeprev_pageno = cur.getleftSiblingPageNumber(); if (SanityManager.DEBUG) { SanityManager.ASSERT( shouldbeprev_pageno == prev.page.getPageNumber(), "child linkeage error going left"); } prev.release(); prev = cur; cur = null; } prev.release(); prev = null; } finally { if (prev != null) prev.release(); if (cur != null) cur.release(); } return; } /** * Recursively print the tree starting at current node in tree. * * @param btree the open btree to print. * * @exception StandardException Standard exception policy. **/ public void printTree( OpenBTree btree) throws StandardException { if (SanityManager.DEBUG) { SanityManager.DEBUG_PRINT("p_tree", this.debugPage(btree)); ControlRow child = null; try { child = this.getLeftChild(btree); child.printTree(btree); child.release(); child = null; int numslots = this.page.recordCount(); for (int slot = 1; slot < numslots; slot++) { child = this.getChildPageAtSlot(btree, slot); child.printTree(btree); child.release(); child = null; } } finally { if (child != null) child.release(); } return; } } /* * Private methods of BranchControlRow */ /** ** Add a level to the tree by moving the current branch-root page up ** one level and adding a new page as it's left child. On exit the ** current root page remains the root of the tree. ** <P> ** On entry, the current branch root page is expected to be latched. ** On exit, all latches will have been released. ** <P> ** Latch order: ** o ROOT: on entry current root is latched. ** No other latches should be held. ** o ROOT_OLDCHILD: Get and Latch root's left child page. ** o ROOT_NEWCHILD: Allocate a new branch page with latch. ** o Conditionally fix up the parent links on the pages pointed at ** by the newly allocated page. Loop through slots on ROOT_NEWCHILD, ** from left to right getting and releasing latches. Note that ** fixChildrensParents() must not latch the leftchild as ROOT_OLDCHILD ** is already latched.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -