⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 btreecontroller.java

📁 derby database source code.good for you.
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
            split_open_btree.close();        }        split_xact.commit();        split_xact.destroy();        return(new_leaf_pageno);    }	/**    Insert a row into the conglomerate.    @param rowToInsert 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.    **/	private int doIns(DataValueDescriptor[] rowToInsert)        throws StandardException	{		LeafControlRow  targetleaf                      = null;		LeafControlRow  save_targetleaf                 = null;        int             insert_slot                     = 0;        int             result_slot                     = 0;        int             ret_val                         = 0;        boolean         reclaim_deleted_rows_attempted  = false;        if (scratch_template == null)            scratch_template = runtime_mem.get_template();        if (SanityManager.DEBUG)            this.isIndexableRowConsistent(rowToInsert);        // Create the objects needed for the insert.        // RESOLVE (mikem) - should we cache this in the controller?        SearchParameters sp =             new SearchParameters(                rowToInsert,                SearchParameters.POSITION_LEFT_OF_PARTIAL_KEY_MATCH,                scratch_template, this, false);        // RowLocation column is in last column of template.        FetchDescriptor lock_fetch_desc =             RowUtil.getFetchDescriptorConstant(                scratch_template.length - 1);        RowLocation lock_row_loc =             (RowLocation) scratch_template[scratch_template.length - 1];        // Row locking - lock the row being inserted.        if (get_insert_row_lock)        {            // I don't hold any latch yet so I can wait on this lock, so I            // don't care about return value from this call.  This            // lock can only wait if the base table row was inserted in a            // separate transaction which never happens in sql tables, but            // does happen in the sparse indexes that synchronization builds.                    this.getLockingPolicy().lockNonScanRow(                this.getConglomerate(),                (LeafControlRow) null,                (LeafControlRow) null,                rowToInsert,                 (ConglomerateController.LOCK_INS |                  ConglomerateController.LOCK_UPD));        }        while (true)        {            // Search the location at which the new row should be inserted.            if (SanityManager.DEBUG)                SanityManager.ASSERT(this.container != null);            targetleaf = (LeafControlRow)                ControlRow.Get(this, BTree.ROOTPAGEID).search(sp);            // Row locking - first lock row previous to row being inserted:            //     o if (sp.resultExact) then the row must be deleted and            //           we will be replacing it with the new row, lock            //           the row before the slot as the previous key.            //     o else             //           we will be inserting after the current slot so            //           lock the current slot as the previous key.            //            int slot_after_previous =                 (sp.resultExact ? sp.resultSlot : sp.resultSlot + 1);            boolean latch_released = false;            latch_released =                 !this.getLockingPolicy().lockNonScanPreviousRow(                    this.getConglomerate(),                    targetleaf,                     slot_after_previous,                     lock_fetch_desc,                    scratch_template,                    lock_row_loc,                    this,                     (ConglomerateController.LOCK_INS_PREVKEY |                     ConglomerateController.LOCK_UPD),                    TransactionManager.LOCK_INSTANT_DURATION);            // special test to see if latch release code works            if (SanityManager.DEBUG)            {                latch_released =                     test_errors(                        this,                        "BTreeController_doIns", false,                        this.getLockingPolicy(),                         targetleaf, latch_released);            }            if (latch_released)            {                // Had to release latch in order to get the lock, probably                 // because of a forward scanner, research tree, and try again.                targetleaf = null;                continue;            }            // If the row is there already, simply undelete it.            // The rationale for this is, since the index does            // not support duplicates, the only way we could            // find a duplicate is if we found a deleted row.            // If we could lock it, then no other transaction            // is deleting it; either this transaction deleted            // it earlier, or it's simply a row that the space            // reclaimer hasn't reclaimed yet.            // Since inserts are done directly (i.e., not to a            // location provided by a scan, we will see the             // deleted row).            if (sp.resultExact)            {                result_slot = insert_slot = sp.resultSlot;                if (this.getConglomerate().nKeyFields !=                         this.getConglomerate().nUniqueColumns)                {                    // The key fields match, but not the row location.  We                    // must wait on the lock on the other row location before                    // preceding, so as to serialize behind any work being done                    // to the row as part of another transaction.                    latch_released =                         !this.getLockingPolicy().lockNonScanRowOnPage(                            this.getConglomerate(), targetleaf, insert_slot,                             lock_fetch_desc, scratch_template, lock_row_loc,                            ConglomerateController.LOCK_UPD);                    if (latch_released)                    {                        // Had to release latch in order to get the lock,                         // probably to wait for deleting xact to commit or                         // abort.  Research tree, and try again.                        targetleaf = null;                        continue;                    }                }                // The row better be deleted, or something is very wrong.                if (!(targetleaf.page.isDeletedAtSlot(insert_slot)))                {                    // attempt to insert a duplicate into the index.                    ret_val = ConglomerateController.ROWISDUPLICATE;                    break;                }                else                {                    if (this.getConglomerate().nKeyFields ==                         this.getConglomerate().nUniqueColumns)                    {                        // The row that we found deleted is exactly the new row.                        targetleaf.page.deleteAtSlot(                            insert_slot, false, this.btree_undo);                        break;                    }                    else if (this.getConglomerate().nUniqueColumns ==                              (this.getConglomerate().nKeyFields - 1))                    {                        // The row that we found deleted has matching keys                        // which form the unique key fields,                        // but the nonkey fields may differ (for now the                        // heap rowlocation is the only nonkey field                         // allowed).                                                // RESOLVE BT39 (mikem) - when/if heap row location                        // is not fixed we must handle update failing for                        // out of space and split if it does.  For now                        // if the update fails because of lack of space                        // an exception is thrown and the statement is                         // backed out.  Should not happen very often.                        targetleaf.page.deleteAtSlot(                            insert_slot, false, this.btree_undo);                        boolean update_succeeded = true;                        try                         {                            int rowloc_index =                                 this.getConglomerate().nKeyFields - 1;                            targetleaf.page.updateFieldAtSlot(                                insert_slot, rowloc_index,                                 (DataValueDescriptor) RowUtil.getColumn(                                    rowToInsert,                                     (FormatableBitSet) null, rowloc_index),                                this.btree_undo);                        }                        catch (StandardException se)                        {                            // check if the exception is for out of space                            if (!se.getMessageId().equals(SQLState.DATA_NO_SPACE_FOR_RECORD))                            {                                throw se;                            }                            // The statement exception is                            // because the update failed for out of                            // space (ie. the field got longer and there                            // is no room on the page for the expanded                            // field).  Address this error by falling                            // through the code and doing a split.                            update_succeeded = false;                          // update failed.                            targetleaf.page.deleteAtSlot(                                insert_slot, true, this.btree_undo);                        }                        if (update_succeeded)                            break;                    }                    else                    {                        // Can only happen with non key fields in the btree.                        throw(                            StandardException.newException(                                SQLState.BTREE_UNIMPLEMENTED_FEATURE));                    }                }            }            else if (targetleaf.page.recordCount() - 1 <                     this.getConglomerate().maxRowsPerPage)            {                // The row wasn't there, so try to insert it                // on the page returned by the search.                insert_slot = sp.resultSlot + 1;                result_slot = insert_slot + 1;                // By default maxRowsPerPage is set to MAXINT, some tests                // set it small to cause splitting to happen quicker with                // less data.                if (targetleaf.page.insertAtSlot(                        insert_slot,                         rowToInsert, (FormatableBitSet) null,                        this.btree_undo,                        Page.INSERT_DEFAULT,						AccessFactoryGlobals.BTREE_OVERFLOW_THRESHOLD) != null)                {                    // Insert succeeded, so we're done.                    break;                }                // 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 (targetleaf.page.recordCount() <= 2)                {                    throw StandardException.newException(                            SQLState.BTREE_NO_SPACE_FOR_KEY);                }                // start splitting ...            }                        // Create some space by splitting pages.            // determine where in page/table row causing split would go            int flag = 0;            if (insert_slot == 1)            {                flag |= ControlRow.SPLIT_FLAG_FIRST_ON_PAGE;                if (targetleaf.isLeftmostLeaf())                    flag |= ControlRow.SPLIT_FLAG_FIRST_IN_TABLE;            }            else if (insert_slot == targetleaf.page.recordCount())            {                flag |= ControlRow.SPLIT_FLAG_LAST_ON_PAGE;                if (targetleaf.isRightmostLeaf())                    flag |= ControlRow.SPLIT_FLAG_LAST_IN_TABLE;            }            long targetleaf_pageno = targetleaf.page.getPageNumber();            if ((targetleaf.page.recordCount() -                  targetleaf.page.nonDeletedRecordCount()) <= 0)            {                // Don't do reclaim work if there are no deleted records.                reclaim_deleted_rows_attempted = true;            }            BranchRow branchrow =                 BranchRow.createBranchRowFromOldLeafRow(                    rowToInsert, targetleaf_pageno);            // 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.            targetleaf.release();            targetleaf = null;            start_xact_and_dosplit(                !reclaim_deleted_rows_attempted, targetleaf_pageno,                 scratch_template, branchrow.getRow(), flag);            // only attempt to reclaim deleted rows once, otherwise the            // split loop could loop forever, trying to reclaim a deleted            // row that was not committed.            reclaim_deleted_rows_attempted = true;            // RESOLVE (mikem) possible optimization could be to save            // split location and look there first, if this has             // already caused a split.  Or even return a latched page            // from splitFor().  For now just execute the loop again            // searching the tree for somewhere to put the row.        }        // set in-memory hint of where last row on page was inserted.        targetleaf.last_search_result = result_slot;        // Check that page just updated is consistent.        if (SanityManager.DEBUG)        {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -