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

📄 btreescan.java

📁 derby database source code.good for you.
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
            }            boolean latch_released =                 !this.getLockingPolicy().lockScan(                    pos.next_leaf,                    (LeafControlRow) null, // no other latch currently                    false /* not for update */,                    ConglomerateController.LOCK_READ); // get read scan lock.            // TESTING CODE:            if (SanityManager.DEBUG)            {                latch_released =                     test_errors(                        this,                        "BTreeScan_positionAtNextPage", true,                        this.getLockingPolicy(), pos.next_leaf, latch_released);            }            if (!latch_released)            {                break;            }        }        // Now that we either have both latch and scan lock on next leaf, or         // there is no next leaf we can release scan and latch on current page.        if (SanityManager.DEBUG)        {			if (pos.current_scan_pageno != pos.current_leaf.page.getPageNumber())				SanityManager.THROWASSERT(                "pos.current_scan_pageno = " + pos.current_scan_pageno +                "pos.current_leaf = " + pos.current_leaf);        }        // unlock the previous row if doing read.        if (pos.current_rh != null)        {            this.getLockingPolicy().unlockScanRecordAfterRead(                pos, init_forUpdate);        }        this.getLockingPolicy().unlockScan(            pos.current_leaf.page.getPageNumber());        pos.current_leaf.release();        pos.current_leaf        = pos.next_leaf;        pos.current_scan_pageno =             (pos.next_leaf == null) ? 0 : pos.next_leaf.page.getPageNumber();        // set up for scan to continue at beginning of next page.        pos.current_slot        = Page.FIRST_SLOT_NUMBER;        pos.current_rh          = null;    }	/**	Position scan at "start" position.	<p>    Positions the scan to the slot just before the first record to be returned    from the scan.  Returns the start page latched, and sets "current_slot" to    the slot number.	@exception  StandardException  Standard exception policy.	**/    abstract void positionAtStartPosition(    BTreeRowPosition    pos)        throws StandardException;    /**     * Do any necessary work to complete the scan.     *     * @param pos           current row position of the scan.     *	 * @exception  StandardException  Standard exception policy.     **/    protected void positionAtDoneScanFromClose(    BTreeRowPosition    pos)        throws StandardException    {        // call unlockScanRecordAfterRead() before closing, currently        // this is only important for releasing RR locks on non-qualified        // rows.           //        // Otherwise the correct behavior happens as part of the close, ie.:        //        //     for READ_UNCOMMITTED there is no lock to release,         //     for READ_COMMITTED   all read locks will be released,         //     for REPEATABLE_READ or SERIALIZABLE no locks are released.        if ((pos.current_rh != null) && !pos.current_rh_qualified)        {            if (pos.current_leaf == null || pos.current_leaf.page == null)            {                // If we are being called from a "normal" close then there                // will be no latch on current_leaf, get it and do the the                // unlock.  We may be called sometimes, after an error where                // we may have the latch, in this case the transaction is about                // to be backed out anyway so don't worry about doing this                 // unlock (thus why we only do the following code if we                // "don't" have lock, ie. pos.current_leaf== null).                if (!reposition(pos, false))                {                    if (SanityManager.DEBUG)                    {                        SanityManager.THROWASSERT(                            "can not fail while holding update row lock.");                    }                }                this.getLockingPolicy().unlockScanRecordAfterRead(                    pos, init_forUpdate);                pos.current_rh   = null;                pos.current_leaf.release();                pos.current_leaf = null;            }        }        // Need to do this unlock in any case, until lock manager provides        // a way to release locks associated with a compatibility space.  This        // scan lock is special, as it is a lock on the btree container rather        // than the heap container.  The open container on the btree actually        // has a null locking policy so the close of that container does not        // release this lock, need to explicitly unlock it here or when the        // scan is closed as part of the abort the lock will not be released.        if (pos.current_scan_pageno != 0)        {            this.getLockingPolicy().unlockScan(pos.current_scan_pageno);            pos.current_scan_pageno = 0;        }        pos.current_slot = Page.INVALID_SLOT_NUMBER;        pos.current_rh   = null;        pos.current_positionKey  = null;        this.scan_state   = SCAN_DONE;        return;    }    /**     * Do work necessary to close a scan.     * <p>     * This routine can only be called "inline" from other btree routines,     * as it counts on the state of the pos to be correct.     * <p>     * Closing a scan from close() must handle long jumps from exceptions     * where the state of pos may not be correct.  The easiest case is     * a lock timeout which has caused us not to have a latch on a page,     * but pos still thinks there is a latch.  This is the easiest but     * other exceptions can also caused the same state at close() time.     **/    protected void positionAtDoneScan(    BTreeRowPosition    pos)        throws StandardException    {        // Need to do this unlock in any case, until lock manager provides        // a way to release locks associated with a compatibility space.  This        // scan lock is special, as it is a lock on the btree container rather        // than the heap container.  The open container on the btree actually        // has a null locking policy so the close of that container does not        // release this lock, need to explicitly unlock it here or when the        // scan is closed as part of the abort the lock will not be released.        if (pos.current_scan_pageno != 0)        {            this.getLockingPolicy().unlockScan(pos.current_scan_pageno);            pos.current_scan_pageno = 0;        }        pos.current_slot        = Page.INVALID_SLOT_NUMBER;        pos.current_rh          = null;        pos.current_positionKey = null;        this.scan_state         = SCAN_DONE;        return;    }    /**     * process_qualifier - Determine if a row meets all qualifier conditions.     * <p>     * Check all qualifiers in the qualifier array against row.  Return true     * if all compares specified by the qualifier array return true, else     * return false.     * <p>     * It is up to caller to make sure qualifier list is non-null.     *     * @param row      The row with the same partial column list as the     *                 row returned by the current scan.     *	 * @exception  StandardException  Standard exception policy.     */    protected boolean process_qualifier(    DataValueDescriptor[]     row)         throws StandardException    {        boolean     row_qualifies = true;        Qualifier   q;        // Process the 2-d qualifier which is structured as follows:        //        // A two dimensional array is to be used to pass around a AND's and OR's        // in conjunctive normal form (CNF).  The top slot of the 2 dimensional        // array is optimized for the more frequent where no OR's are present.          // The first array slot is always a list of AND's to be treated as         // described above for single dimensional AND qualifier arrays.  The         // subsequent slots are to be treated as AND'd arrays or OR's.  Thus         // the 2 dimensional array qual[][] argument is to be treated as the         // following, note if qual.length = 1 then only the first array is         // valid and // it is and an array of and clauses:        //        // (qual[0][0] and qual[0][0] ... and qual[0][qual[0].length - 1])        // and        // (qual[1][0] or  qual[1][1] ... or  qual[1][qual[1].length - 1])        // and        // (qual[2][0] or  qual[2][1] ... or  qual[2][qual[2].length - 1])        // ...        // and        // (qual[qual.length - 1][0] or  qual[1][1] ... or  qual[1][2])        // First do the qual[0] which is an array of qualifer terms.        if (SanityManager.DEBUG)        {            // routine should not be called if there is no qualifier            SanityManager.ASSERT(this.init_qualifier != null);            SanityManager.ASSERT(this.init_qualifier.length > 0);        }        for (int i = 0; i < this.init_qualifier[0].length; i++)        {            // process each AND clause             row_qualifies = false;            // process each OR clause.            q = this.init_qualifier[0][i];            // Get the column from the possibly partial row, of the             // q.getColumnId()'th column in the full row.            DataValueDescriptor columnValue = row[q.getColumnId()];            row_qualifies =                columnValue.compare(                    q.getOperator(),                    q.getOrderable(),                    q.getOrderedNulls(),                    q.getUnknownRV());            if (q.negateCompareResult())                row_qualifies = !row_qualifies;            // Once an AND fails the whole Qualification fails - do a return!            if (!row_qualifies)                return(false);        }        // all the qual[0] and terms passed, now process the OR clauses        for (int and_idx = 1; and_idx < this.init_qualifier.length; and_idx++)        {            // process each AND clause             row_qualifies = false;            if (SanityManager.DEBUG)            {                // Each OR clause must be non-empty.                SanityManager.ASSERT(this.init_qualifier[and_idx].length > 0);            }            for (int or_idx = 0;                  or_idx < this.init_qualifier[and_idx].length; or_idx++)            {                // process each OR clause.                q = this.init_qualifier[and_idx][or_idx];                // Get the column from the possibly partial row, of the                 // q.getColumnId()'th column in the full row.                DataValueDescriptor columnValue = row[q.getColumnId()];                row_qualifies =                    columnValue.compare(                        q.getOperator(),                        q.getOrderable(),                        q.getOrderedNulls(),                        q.getUnknownRV());                if (q.negateCompareResult())                    row_qualifies = !row_qualifies;                // once one OR qualifies the entire clause is TRUE                if (row_qualifies)                    break;            }            if (!row_qualifies)                break;        }        return(row_qualifies);    }    /**     * Reposition the scan leaving and reentering the access layer.     * <p>     * When a scan leaves access it saves the RecordHandle of the record     * on the page.  There are 2 cases to consider when trying to reposition     * the scan when re-entering access:     *     o ROW has not moved off the page.     *       If the row has not moved then the RecordHandle we have saved     *       away is valid, and we just call RawStore to reposition on that     *       RecordHandle (RawStore takes care of the row moving within     *       the page).     *     o ROW has moved off the page.     *       This can only happen in the case of a btree split.  In that     *       case the splitter will have caused all scans positioned on      *       this page within the same transaction to save a copy of the     *       row that the scan was positioned on.  Then to reposition the     *       scan it is necessary to research the tree from the top using     *       the copy of the row.     *     * If the scan has saved it's position by key (and thus has given up the     * scan lock on the page), there are a few cases where it is possible that     * the key no longer exists in the table.  In the case of a scan held      * open across commit it is easy to imagine that the row the scan was      * positioned on could be deleted and subsequently purged from the table      * all before the scan resumes.  Also in the case of read uncommitted      * the scan holds no lock on the current row, so it could be purged -     * in the following scenario for instance:  read uncommitted transaction 1     * opens scan and positions on row (1,2), transaction 2 deletes (1,2) and     * commits, transaction 1 inserts (1,3) which goes to same page as (1,2)     * and is going to cause a split, transaction 1 saves scan position as     * key, gives up scan lock and then purges row (1, 2), when transaction      * 1 resumes scan (1, 2) no longer exists.  missing_row_for_key_ok      * parameter is added as a sanity check to make sure it ok that      * repositioning does not go to same row that we were repositioned on.     *

⌨️ 快捷键说明

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