📄 btreecontroller.java
字号:
if (SanityManager.DEBUG_ON("enableBtreeConsistencyCheck")) { targetleaf.checkConsistency(this, null, true); } } // Done with the target page. targetleaf.release(); targetleaf = null; // return the status about insert - 0 is ok, or duplicate status. return(ret_val); } /** * Just insert the row on the current page/slot if it fits. * <p> * @exception StandardException Standard exception policy. **/ private boolean do_load_insert( DataValueDescriptor[] rowToInsert, LeafControlRow leaf, int insert_slot) throws StandardException { LeafControlRow old_leaf = null; boolean row_inserted = false; int num_rows_on_page = leaf.page.recordCount() - 1; if (SanityManager.DEBUG) { SanityManager.ASSERT(insert_slot == leaf.page.recordCount()); SanityManager.ASSERT( leaf.getrightSiblingPageNumber() == ContainerHandle.INVALID_PAGE_NUMBER); this.isIndexableRowConsistent(rowToInsert); } if (num_rows_on_page < this.getConglomerate().maxRowsPerPage) { // By default maxRowsPerPage is set to MAXINT, some tests // set it small to cause splitting to happen quicker with // less data. if (SanityManager.DEBUG) { // Caller should have sorted and done duplicate checking. if (insert_slot > 1) { // verify that the row inserted is >= than previous row. int compare_result = ControlRow.CompareIndexRowFromPageToKey( leaf, insert_slot - 1, scratch_template, rowToInsert, this.getConglomerate().nUniqueColumns, 0, this.getConglomerate().ascDescInfo); if (compare_result >= 0) { // Rows must be presented in order, so the row we are // inserting must always be greater than the previous // row on the page. SanityManager.THROWASSERT("result = " + compare_result); } } } if (leaf.page.insertAtSlot( insert_slot, rowToInsert, (FormatableBitSet) null, this.btree_undo, Page.INSERT_DEFAULT, AccessFactoryGlobals.BTREE_OVERFLOW_THRESHOLD) != null) { // Insert succeeded, so we're done. row_inserted = true; } else { // RESOLVE (mikem) - another long row issue. // For now if a row does not fit on a page and there // is only the control row on the page and at most one // other row on the page, throw an exception if (leaf.page.recordCount() <= 2) { throw StandardException.newException( SQLState.BTREE_NO_SPACE_FOR_KEY); } } } // Check that page just updated is consistent. if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("enableBtreeConsistencyCheck")) { leaf.checkConsistency(this, null, true); } } return(row_inserted); } /** * Create room to insert a row to the right of the largest key in table. * <p> * Perform a split pass on the tree which will move the largest key in * leaf right to a new leaf, splitting parent branch pages as necessary. * * @exception StandardException Standard exception policy. **/ private LeafControlRow do_load_split( DataValueDescriptor[] rowToInsert, LeafControlRow leaf) throws StandardException { LeafControlRow new_leaf = null; BranchRow branchrow = BranchRow.createBranchRowFromOldLeafRow( rowToInsert, leaf.page.getPageNumber()); // Release the target page because (a) it may change as a // result of the split, (b) the latch ordering requires us // to acquire latches from top to bottom, and (c) this // loop should be done in a system transaction. long old_leafpage = leaf.page.getPageNumber(); leaf.release(); leaf = null; long new_leaf_pageno = start_xact_and_dosplit( false /* don't try to reclaim deleted rows */, old_leafpage, scratch_template, branchrow.getRow(), (ControlRow.SPLIT_FLAG_LAST_ON_PAGE | ControlRow.SPLIT_FLAG_LAST_IN_TABLE)); new_leaf = (LeafControlRow) ControlRow.Get(this, new_leaf_pageno); // The leaf must be the rightmost leaf in the table, the first time // the root grows from leaf to branch it will be a leaf with many // rows which will probably have to be split soon, after that it will // be a leaf with only one row. The current algorithm requires that // there be at least one row for duplicate checking (the duplicate // checking code does not handle going left to the previous leaf) - // this is the way the split at rightmost leaf row works currently. if (SanityManager.DEBUG) { if (new_leaf.getrightSiblingPageNumber() != ContainerHandle.INVALID_PAGE_NUMBER) { SanityManager.THROWASSERT( "new_leaf.getrightSiblingPageNumber() = " + new_leaf.getrightSiblingPageNumber()); } if (new_leaf.page.recordCount() <= 1) { SanityManager.THROWASSERT( "new_leaf.page.recordCount() = " + new_leaf.page.recordCount()); } } return(new_leaf); } /* ** public Methods of BTreeController */ /** Initialize the controller for use. <p> Any changes to this method will probably have to be reflected in close as well. <p> Currently delegates to OpenBTree. If the btree controller ends up not having any state of its own, we can remove this method (the VM will dispatch to OpenBTree), gaining some small efficiency. For now, this method remains for clarity. @exception StandardException Standard exception policy. **/ public void init( TransactionManager xact_manager, boolean hold, ContainerHandle container, Transaction rawtran, int open_mode, int lock_level, BTreeLockingPolicy btree_locking_policy, BTree conglomerate, LogicalUndo undo, StaticCompiledOpenConglomInfo static_info, DynamicCompiledOpenConglomInfo dynamic_info) throws StandardException { get_insert_row_lock = ((open_mode & TransactionController.OPENMODE_BASEROW_INSERT_LOCKED) == 0); super.init( xact_manager, xact_manager, container, rawtran, hold, open_mode, lock_level, btree_locking_policy, conglomerate, undo, dynamic_info); } /* ** Methods of ConglomerateController */ /** Close the conglomerate controller. <p> Any changes to this method will probably have to be reflected in close as well. <p> Currently delegates to OpenBTree. If the btree controller ends up not having any state of its own, we can remove this method (the VM will dispatch to OpenBTree), gaining some small efficiency. For now, this method remains for clarity. @see ConglomerateController#close **/ public void close() throws StandardException { super.close(); // If we are closed due to catching an error in the middle of init, // xact_manager may not be set yet. if (getXactMgr() != null) getXactMgr().closeMe(this); } /** * Close conglomerate controller as part of terminating a transaction. * <p> * Use this call to close the conglomerate controller resources as part of * committing or aborting a transaction. The normal close() routine may * do some cleanup that is either unnecessary, or not correct due to the * unknown condition of the controller following a transaction ending error. * Use this call when closing all controllers as part of an abort of a * transaction. * <p) * This call is meant to only be used internally by the Storage system, * clients of the storage system should use the simple close() interface. * <p> * RESOLVE (mikem) - move this call to ConglomerateManager so it is * obvious that non-access clients should not call this. * * @param closeHeldScan If true, means to close controller even if * it has been opened to be kept opened * across commit. This is * used to close these controllers on abort. * * @return boolean indicating that the close has resulted in a real close * of the controller. A held scan will return false if * called by closeForEndTransaction(false), otherwise it * will return true. A non-held scan will always return * true. * * @exception StandardException Standard exception policy. **/ public boolean closeForEndTransaction(boolean closeHeldScan) throws StandardException { super.close(); if ((!getHold()) || closeHeldScan) { // If we are closed due to catching an error in the middle of init, // xact_manager may not be set yet. if (getXactMgr() != null) getXactMgr().closeMe(this); return(true); } else { return(false); } } /** Insert a row into the conglomerate. @see ConglomerateController#insert @param row The row to insert into the conglomerate. The stored representations of the row's columns are copied into a new row somewhere in the conglomerate. @return Returns 0 if insert succeeded. Returns ConglomerateController.ROWISDUPLICATE if conglomerate supports uniqueness checks and has been created to disallow duplicates, and the row inserted had key columns which were duplicate of a row already in the table. Other insert failures will raise StandardException's. @exception StandardException Standard exception policy. **/ public int insert(DataValueDescriptor[] row) throws StandardException { if (isClosed()) { if (getHold()) { reopen(); } else { throw StandardException.newException( SQLState.BTREE_IS_CLOSED, new Long(err_containerid)); } } if (SanityManager.DEBUG) { SanityManager.ASSERT(this.container != null); TemplateRow.checkPartialColumnTypes( this.getConglomerate().format_ids, (FormatableBitSet) null, (int []) null, row); } return doIns(row); } /** Return whether this is a keyed conglomerate. <p> All b-trees are keyed. @see ConglomerateController#isKeyed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -