📄 btreescan.java
字号:
* * * @param pos position to set the scan to. * * @param missing_row_for_key_ok if true and exact key is not found then * scan is just set to key just left of * the key (thus a next will move to the * key just after "pos") * * @return returns true if scan has been repositioned successfully, else * returns false if the position key could not be found and * missing_row_for_key_ok was false indicating that scan could * only be positioned on the exact key match. * * @exception StandardException Standard exception policy. **/ protected boolean reposition( BTreeRowPosition pos, boolean missing_row_for_key_ok) throws StandardException { // RESOLVE (mikem) - performance - we need to do a buffer manager // get for every row returned from the scan. It may be better to // allow a reference to the page with no latch (ie. a fixed bit). if (this.scan_state != SCAN_INPROGRESS) { throw StandardException.newException( SQLState.BTREE_SCAN_NOT_POSITIONED, new Integer(this.scan_state)); } // Either current_rh or positionKey is valid - the other is null. if (SanityManager.DEBUG) { if ((pos.current_rh == null) != (pos.current_positionKey != null)) SanityManager.THROWASSERT( "pos.current_rh = (" + pos.current_rh + "), " + "pos.current_positionKey = (" + pos.current_positionKey + ")."); } if (!((pos.current_rh == null) == (pos.current_positionKey != null))) { throw StandardException.newException( SQLState.BTREE_SCAN_INTERNAL_ERROR, new Boolean(pos.current_rh == null), new Boolean(pos.current_positionKey == null)); } if (pos.current_positionKey == null) { // Reposition to remembered spot on page. if (SanityManager.DEBUG) SanityManager.ASSERT(pos.current_scan_pageno != 0); pos.current_leaf = (LeafControlRow) ControlRow.Get(this, pos.current_rh.getPageNumber()); pos.current_slot = pos.current_leaf.page.getSlotNumber(pos.current_rh); } else { // RESOLVE (mikem) - not sure but someday in the future this // assert may not be true, but for now we always release the // scan lock when we save the row away as the current position. if (SanityManager.DEBUG) SanityManager.ASSERT(pos.current_scan_pageno == 0); SearchParameters sp = new SearchParameters( pos.current_positionKey, // this is a full key search, so this arg is not used. SearchParameters.POSITION_LEFT_OF_PARTIAL_KEY_MATCH, init_template, this, false); // latch/lock loop, continue until you can get scan lock on page // while holding page latched without waiting. boolean latch_released; do { pos.current_leaf = (LeafControlRow) ControlRow.Get(this, BTree.ROOTPAGEID).search(sp); if (sp.resultExact || missing_row_for_key_ok) { // RESOLVE (mikem) - we could have a scan which always // maintained it's position by key value, or we could // optimize and delay this lock until we were about to // give up the latch. But it is VERY likely we will get // the lock since we have the latch on the page. // // In order to be successfully positioned we must get the // scan lock again. latch_released = !this.getLockingPolicy().lockScan( pos.current_leaf, (LeafControlRow) null, // no other latch currently false /* not for update */, ConglomerateController.LOCK_READ); // read lock on scan position // TESTING CODE: if (SanityManager.DEBUG) { latch_released = test_errors( this, "BTreeScan_reposition", true, this.getLockingPolicy(), pos.current_leaf, latch_released); } } else { // Did not find key to exactly position on. pos.current_leaf.release(); pos.current_leaf = null; return(false); } } while (latch_released); pos.current_scan_pageno = pos.current_leaf.page.getPageNumber(); pos.current_slot = sp.resultSlot; pos.current_positionKey = null; } return(true); } /* ** Public Methods of BTreeScan */ /** Initialize the scan for use. <p> Any changes to this method may have to be reflected in close as well. <p> The btree init opens the container (super.init), and stores away the state of the qualifiers. The actual searching for the first position is delayed until the first next() call. @exception StandardException Standard exception policy. **/ public void init( TransactionManager xact_manager, Transaction rawtran, boolean hold, int open_mode, int lock_level, BTreeLockingPolicy btree_locking_policy, FormatableBitSet scanColumnList, DataValueDescriptor[] startKeyValue, int startSearchOperator, Qualifier qualifier[][], DataValueDescriptor[] stopKeyValue, int stopSearchOperator, BTree conglomerate, LogicalUndo undo, StaticCompiledOpenConglomInfo static_info, DynamicCompiledOpenConglomInfo dynamic_info) throws StandardException { super.init( xact_manager, xact_manager, (ContainerHandle) null, rawtran, hold, open_mode, lock_level, btree_locking_policy, conglomerate, undo, dynamic_info); this.init_rawtran = rawtran; this.init_forUpdate = ((open_mode & ContainerHandle.MODE_FORUPDATE) == ContainerHandle.MODE_FORUPDATE); // Keep track of whether this scan should use update locks. this.init_useUpdateLocks = ((open_mode & ContainerHandle.MODE_USE_UPDATE_LOCKS) != 0); this.init_hold = hold; this.init_template = runtime_mem.get_template(); this.init_scanColumnList = scanColumnList; this.init_lock_fetch_desc = RowUtil.getFetchDescriptorConstant(init_template.length - 1); if (SanityManager.DEBUG) { SanityManager.ASSERT( init_lock_fetch_desc.getMaxFetchColumnId() == (init_template.length - 1)); SanityManager.ASSERT( (init_lock_fetch_desc.getValidColumnsArray())[init_template.length - 1] == 1); } // note that we don't process qualifiers in btree fetch's this.init_fetchDesc = new FetchDescriptor( init_template.length, init_scanColumnList,(Qualifier[][]) null); initScanParams( startKeyValue, startSearchOperator, qualifier, stopKeyValue, stopSearchOperator); if (SanityManager.DEBUG) { // RESOLVE - (mikem) we should we require a template, need to // clean up some of the old tests which did not provide one? if (init_template != null) { SanityManager.ASSERT( TemplateRow.checkColumnTypes( this.getConglomerate().format_ids, init_template)); } } // System.out.println("initializing scan:" + this); // initialize default locking operation for the scan. this.lock_operation = (init_forUpdate ? ConglomerateController.LOCK_UPD : ConglomerateController.LOCK_READ); if (init_useUpdateLocks) this.lock_operation |= ConglomerateController.LOCK_UPDATE_LOCKS; // System.out.println("Btree scan: " + this); } /* ** Methods of ScanController */ /** Close the scan. **/ public void close() throws StandardException { // Scan is closed, make sure no access to any state variables positionAtDoneScanFromClose(scan_position); super.close(); // null out so that these object's can get GC'd earlier. this.init_rawtran = null; this.init_template = null; this.init_startKeyValue = null; this.init_qualifier = null; this.init_stopKeyValue = null; this.getXactMgr().closeMe(this); } /** Delete the row at the current position of the scan. @see ScanController#delete @exception StandardException Standard exception policy. **/ public boolean delete() throws StandardException { boolean ret_val = false; if (scan_state != SCAN_INPROGRESS) throw StandardException.newException( SQLState.AM_SCAN_NOT_POSITIONED); if (SanityManager.DEBUG) { SanityManager.ASSERT(this.container != null, "BTreeScan.delete() called on a closed scan."); SanityManager.ASSERT(init_forUpdate); } try { // Get current page of scan, with latch. if (!reposition(scan_position, false)) { throw StandardException.newException( SQLState.AM_RECORD_NOT_FOUND, new Long(err_containerid), new Long(scan_position.current_rh.getId())); } if (init_useUpdateLocks) { // RESOLVE (mikem) - I don't think lockScanRow() is the right // thing to call. // if we are doing update locking, then we got an U lock on // this row when the scan positioned on it, but now that we // are doing a delete on the current position we need to upgrade // the lock to X. boolean latch_released = !this.getLockingPolicy().lockScanRow( this, this.getConglomerate(), scan_position, false, init_lock_fetch_desc, scan_position.current_lock_template, scan_position.current_lock_row_loc, false, init_forUpdate, lock_operation); if (latch_released) { // lost latch on page in order to wait for row lock. // Because we have scan lock on page, we need only // call reposition() which will use the saved record // handle to reposition to the same spot on the page. // We don't have to search the // tree again, as we have the a scan lock on the page // which means the current_rh is valid to reposition on. if (reposition(scan_position, false)) { throw StandardException.newException( SQLState.AM_RECORD_NOT_FOUND, new Long(err_containerid), new Long(scan_position.current_rh.getId())); } } } // Do a fetch just to get the RecordHandle for the delete call, // don't fetch any columns. RecordHandle delete_rh = scan_position.current_leaf.page.fetchFromSlot( (RecordHandle) null, scan_position.current_slot, RowUtil.EMPTY_ROW, (FetchDescriptor) null, true);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -