use of org.apache.derby.iapi.store.raw.Page in project derby by apache.
the class BTreeScan method savePositionAndReleasePage.
/**
* Save the current scan position by key and release the latch on the leaf
* that's being scanned. This method should be called if the latch on a
* leaf needs to be released in the middle of the scan. The scan can
* later reposition to the saved position by calling {@code reposition()}.
*
* @param partialKey known parts of the key that should be saved, or
* {@code null} if the entire key is unknown and will have to be fetched
* from the page
* @param vcols an array which tells which columns of the partial key are
* valid (key columns that have 0 in this array are not valid, and their
* values must be fetched from the page), or {@code null} if all the
* columns are valid
* @throws StandardException if an error occurs while saving the position
* @see #reposition(BTreeRowPosition, boolean)
*/
void savePositionAndReleasePage(DataValueDescriptor[] partialKey, int[] vcols) throws StandardException {
final Page page = scan_position.current_leaf.getPage();
if (SanityManager.DEBUG) {
SanityManager.ASSERT(page.isLatched(), "Page is not latched");
SanityManager.ASSERT(scan_position.current_positionKey == null, "Scan position already saved");
if (partialKey == null) {
SanityManager.ASSERT(vcols == null);
}
if (vcols != null) {
SanityManager.ASSERT(partialKey != null);
SanityManager.ASSERT(vcols.length <= partialKey.length);
}
}
try {
DataValueDescriptor[] fullKey = scan_position.getKeyTemplate();
FetchDescriptor fetchDescriptor = null;
boolean haveAllColumns = false;
if (partialKey != null) {
int copiedCols = 0;
final int partialKeyLength = (vcols == null) ? partialKey.length : vcols.length;
for (int i = 0; i < partialKeyLength; i++) {
if (vcols == null || vcols[i] != 0) {
fullKey[i].setValue(partialKey[i]);
copiedCols++;
}
}
if (copiedCols < fullKey.length) {
fetchDescriptor = scan_position.getFetchDescriptorForSaveKey(vcols, fullKey.length);
} else {
haveAllColumns = true;
}
}
if (!haveAllColumns) {
RecordHandle rh = page.fetchFromSlot((RecordHandle) null, scan_position.current_slot, fullKey, fetchDescriptor, true);
if (SanityManager.DEBUG) {
SanityManager.ASSERT(rh != null, "Row not found");
}
}
scan_position.current_positionKey = fullKey;
// Don't null out current_rh, we might be able to use it later if
// no rows are moved off the page.
// scan_position.current_rh = null;
scan_position.versionWhenSaved = page.getPageVersion();
scan_position.current_slot = Page.INVALID_SLOT_NUMBER;
} finally {
scan_position.current_leaf.release();
scan_position.current_leaf = null;
}
}
use of org.apache.derby.iapi.store.raw.Page in project derby by apache.
the class BTreeScan method reposition.
/**
* 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.
*
* 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, 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.
*
* @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 {
if (this.scan_state != SCAN_INPROGRESS) {
throw StandardException.newException(SQLState.BTREE_SCAN_NOT_POSITIONED, this.scan_state);
}
// positionKey is always valid
if (SanityManager.DEBUG) {
if (pos.current_positionKey == null)
SanityManager.THROWASSERT("pos.current_rh = (" + pos.current_rh + "), " + "pos.current_positionKey = (" + pos.current_positionKey + ").");
}
if (pos.current_positionKey == null) {
throw StandardException.newException(SQLState.BTREE_SCAN_INTERNAL_ERROR, (pos.current_rh == null), (pos.current_positionKey == null));
}
// from the root of the B-tree in the common case.
if (pos.current_rh != null) {
// Reposition to remembered spot on page.
// Get the page object. If getPage() returns null, the page is
// not valid (could for instance have been removed by compress
// table) so we need to reposition by key instead.
Page page = container.getPage(pos.current_rh.getPageNumber());
if (page != null) {
ControlRow row = ControlRow.getControlRowForPage(container, page);
if (row instanceof LeafControlRow && !row.page.isRepositionNeeded(pos.versionWhenSaved)) {
// No rows have been moved off the page after we released
// the latch, and the page is still a leaf page. No need
// to reposition by key.
pos.current_leaf = (LeafControlRow) row;
pos.current_slot = row.page.getSlotNumber(pos.current_rh);
pos.current_positionKey = null;
return true;
}
// We couldn't use the position specified by current_rh, so we
// need to reposition by key and may find the row on another
// page. Therefore, give up the latch on this page.
row.release();
}
}
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);
pos.current_leaf = (LeafControlRow) ControlRow.get(this, BTree.ROOTPAGEID).search(sp);
if (!sp.resultExact && !missing_row_for_key_ok) {
// Did not find key to exactly position on.
pos.current_leaf.release();
pos.current_leaf = null;
return (false);
}
pos.current_slot = sp.resultSlot;
// so we don't set it here if its old value is null.
if (pos.current_rh != null) {
pos.current_rh = pos.current_leaf.page.getRecordHandleAtSlot(pos.current_slot);
}
pos.current_positionKey = null;
return (true);
}
use of org.apache.derby.iapi.store.raw.Page in project derby by apache.
the class BranchControlRow method allocate.
/**
* Allocate a new leaf page to the conglomerate.
*
* @exception StandardException Standard exception policy.
*/
private static BranchControlRow allocate(OpenBTree open_btree, ControlRow leftchild, int level, ControlRow parent) throws StandardException {
Page page = open_btree.container.addPage();
// Create a control row for the new page.
BranchControlRow control_row = new BranchControlRow(open_btree, page, level, parent, false, leftchild.page.getPageNumber());
// Insert the control row on the page.
byte insertFlag = Page.INSERT_INITIAL;
insertFlag |= Page.INSERT_DEFAULT;
page.insertAtSlot(Page.FIRST_SLOT_NUMBER, control_row.getRow(), (FormatableBitSet) null, (LogicalUndo) null, insertFlag, AccessFactoryGlobals.BTREE_OVERFLOW_THRESHOLD);
// Page is returned latched.
return (control_row);
}
use of org.apache.derby.iapi.store.raw.Page in project derby by apache.
the class D_BTreeController method diag_page.
/* Private/Protected methods of This class: */
private static void diag_page(OpenBTree open_btree, ControlRow control_row, Properties prop, LevelInfo[] level_info) throws StandardException {
LevelInfo li = level_info[control_row.getLevel()];
Page page = control_row.page;
li.num_pages++;
li.num_entries += (page.recordCount() - 1);
li.num_deleted += (page.recordCount() - page.nonDeletedRecordCount());
li.max_pageno = Math.max(li.max_pageno, page.getPageNumber());
DiagnosticUtil.findDiagnostic(page).diag_detail(prop);
DiagnosticUtil.findDiagnostic(page).diag_detail(prop);
// number of free bytes on page.
int free_bytes = Integer.parseInt(prop.getProperty(Page.DIAG_BYTES_FREE));
li.num_free_bytes += free_bytes;
// number of bytes reserved on page.
int res_bytes = Integer.parseInt(prop.getProperty(Page.DIAG_BYTES_RESERVED));
li.num_res_bytes += res_bytes;
// overflow rows.
int overflow = Integer.parseInt(prop.getProperty(Page.DIAG_NUMOVERFLOWED));
li.num_overflow_rows += overflow;
// size of rows.
int rowsize = Integer.parseInt(prop.getProperty(Page.DIAG_ROWSIZE));
li.num_rowsize_bytes += rowsize;
// size of slot table.
int slottable_size = Integer.parseInt(prop.getProperty(Page.DIAG_SLOTTABLE_SIZE));
li.num_slottab_bytes += slottable_size;
// minimum row size.
int min_rowsize = Integer.parseInt(prop.getProperty(Page.DIAG_MINROWSIZE));
li.min_rowsize_bytes = Math.min(li.min_rowsize_bytes, min_rowsize);
// maximum row size.
int max_rowsize = Integer.parseInt(prop.getProperty(Page.DIAG_MAXROWSIZE));
li.max_rowsize_bytes = Math.max(li.max_rowsize_bytes, max_rowsize);
}
use of org.apache.derby.iapi.store.raw.Page in project derby by apache.
the class LeafControlRow method allocate.
/* Private/Protected methods of This class: */
/**
* Allocate a new leaf page to the conglomerate.
*
* @param btree The open conglomerate from which to get the leaf from
* @param parent The parent page of the newly allocated page, null if
* allocating root page.
*
* @exception StandardException Standard exception policy.
*/
private static LeafControlRow allocate(OpenBTree btree, ControlRow parent) throws StandardException {
Page page = btree.container.addPage();
// Create a control row for the new page.
LeafControlRow control_row = new LeafControlRow(btree, page, parent, false);
// Insert the control row on the page, in the first slot on the page.
// This operation is only done as part of a new tree or split, which
// which both will be undone physically so no logical undo record is
// needed.
byte insertFlag = Page.INSERT_INITIAL;
insertFlag |= Page.INSERT_DEFAULT;
RecordHandle rh = page.insertAtSlot(Page.FIRST_SLOT_NUMBER, control_row.getRow(), (FormatableBitSet) null, (LogicalUndo) null, insertFlag, AccessFactoryGlobals.BTREE_OVERFLOW_THRESHOLD);
if (SanityManager.DEBUG) {
RecordHandle rh2 = null;
rh2 = page.fetchFromSlot((RecordHandle) null, page.FIRST_SLOT_NUMBER, new DataValueDescriptor[0], (FetchDescriptor) null, true);
SanityManager.ASSERT(rh.getId() == rh2.getId() && rh.getPageNumber() == rh2.getPageNumber());
}
// Page is returned latched.
return (control_row);
}
Aggregations