use of org.apache.derby.iapi.store.raw.Page in project derby by apache.
the class HeapController method doInsert.
/**
* Insert a new row into the heap.
* <p>
* Overflow policy:
* The current heap access method implements an algorithm that optimizes
* for fetch efficiency vs. space efficiency. A row will not be over
* flowed unless it is bigger than a page. If it is bigger than a page
* then it's initial part will be placed on a page and then subsequent
* parts will be overflowed to other pages.
* <p>
*
* @return The record handle of the inserted row.
*
* @param row The row to insert.
*
* @exception StandardException Standard exception policy.
*/
private RecordHandle doInsert(DataValueDescriptor[] row) throws StandardException {
Page page = null;
byte insert_mode;
RecordHandle rh;
if (SanityManager.DEBUG) {
Heap heap = (Heap) open_conglom.getConglomerate();
// Make sure valid columns are in the list. The RowUtil
// call is too expensive to make in a released system for
// every insert.
int invalidColumn = RowUtil.columnOutOfRange(row, null, heap.format_ids.length);
if (invalidColumn >= 0) {
throw (StandardException.newException(SQLState.HEAP_TEMPLATE_MISMATCH, invalidColumn, heap.format_ids.length));
}
}
// Get the last page that was returned for insert or the last page
// that was allocated.
page = open_conglom.getContainer().getPageForInsert(0);
if (page != null) {
// if there are 0 rows on the page allow the insert to overflow.
insert_mode = (page.recordCount() == 0) ? Page.INSERT_OVERFLOW : Page.INSERT_DEFAULT;
// Check to see if there is enough space on the page
// for the row.
rh = page.insert(row, null, insert_mode, AccessFactoryGlobals.HEAP_OVERFLOW_THRESHOLD);
page.unlatch();
page = null;
// insert it and release exclusive access to the page.
if (rh != null) {
return rh;
}
}
// If the last inserted page is now full, or RawStore have
// forgotten what it was, or the row cannot fit on the last
// inserted page, try to have rawStore get a relatively unfilled
// page.
page = open_conglom.getContainer().getPageForInsert(ContainerHandle.GET_PAGE_UNFILLED);
if (page != null) {
// Do the insert all over again hoping that it will fit into
// this page, and if not, allocate a new page.
// if there are 0 rows on the page allow the insert to overflow.
insert_mode = (page.recordCount() == 0) ? Page.INSERT_OVERFLOW : Page.INSERT_DEFAULT;
rh = page.insert(row, null, insert_mode, AccessFactoryGlobals.HEAP_OVERFLOW_THRESHOLD);
page.unlatch();
page = null;
// insert it and release exclusive access to the page.
if (rh != null) {
return rh;
}
}
page = open_conglom.getContainer().addPage();
// At this point with long rows the raw store will guarantee
// that any size row will fit on an empty page.
rh = page.insert(row, null, Page.INSERT_OVERFLOW, AccessFactoryGlobals.HEAP_OVERFLOW_THRESHOLD);
page.unlatch();
page = null;
if (SanityManager.DEBUG) {
// a null will only be returned if this page is not empty
SanityManager.ASSERT(rh != null);
}
return rh;
}
use of org.apache.derby.iapi.store.raw.Page in project derby by apache.
the class BTreePostCommit method purgeCommittedDeletes.
/**
* Reclaim space taken up by committed deleted rows.
* <p>
* This routine assumes it has been called by an internal transaction which
* has performed no work so far, and that it has an exclusive table lock.
* These assumptions mean that any deleted rows encountered must be from
* committed transactions (otherwise we could not have gotten the exclusive
* table lock).
* <p>
* This routine handles purging committed deletes while holding a table
* level exclusive lock. See purgeRowLevelCommittedDeletes() for row level
* purging.
*
* @param open_btree The btree already opened.
* @param pageno The page number of the page to look for committed deletes.
*
* @exception StandardException Standard exception policy.
*/
private final DataValueDescriptor[] purgeCommittedDeletes(OpenBTree open_btree, long pageno) throws StandardException {
ControlRow control_row = null;
DataValueDescriptor[] shrink_key = null;
try {
// The following can fail either if it can't get the latch or
// somehow the page requested no longer exists. In either case
// the post commit work will just skip it.
control_row = ControlRow.getNoWait(open_btree, pageno);
if (control_row != null) {
Page page = control_row.page;
// The number records that can be reclaimed is:
// total recs - control row - recs_not_deleted
int num_possible_commit_delete = page.recordCount() - 1 - page.nonDeletedRecordCount();
if (num_possible_commit_delete > 0) {
// have already looked at).
for (int slot_no = page.recordCount() - 1; slot_no > 0; slot_no--) {
if (page.isDeletedAtSlot(slot_no)) {
if (page.recordCount() == 2) {
// About to purge last row from page so
// remember the key so we can shrink the
// tree.
shrink_key = this.getShrinkKey(open_btree, control_row, slot_no);
}
page.purgeAtSlot(slot_no, 1, true);
// Tell scans positioned on this page to reposition
// because the row they are positioned on may have
// disappeared.
page.setRepositionNeeded();
if (SanityManager.DEBUG) {
if (SanityManager.DEBUG_ON("verbose_btree_post_commit")) {
System.out.println("Purging row[" + slot_no + "]" + "on page:" + pageno + ".\n");
}
}
}
}
}
if (page.recordCount() == 1) {
if (SanityManager.DEBUG) {
if (SanityManager.DEBUG_ON("verbose_btree_post_commit")) {
System.out.println("Chance to shrink.\n");
}
}
}
} else {
if (SanityManager.DEBUG) {
if (SanityManager.DEBUG_ON("verbose_btree_post_commit")) {
System.out.println("Get No Wait returned null. page num = " + pageno + "\n");
}
}
}
} finally {
if (control_row != null)
control_row.release();
}
return (shrink_key);
}
use of org.apache.derby.iapi.store.raw.Page in project derby by apache.
the class B2IUndo method findUndo.
/**
* Find the page and record to undo. If no logical undo is necessary,
* i.e., row has not moved, then just return the latched page where undo
* should go. If the record has moved, it has a new recordId on the new
* page, this routine needs to call pageOp.resetRecord with the new
* RecordHandle so that the logging system can update the compensation
* Operation with the new location.
*
* @param rawtran the transaction doing the rollback
* @param pageOp the page operation that supports logical undo. This
* LogicalUndo function pointer is a field of that
* pageOperation
* @param in data stored in the log stream that contains the record
* data necessary to restore the row.
*
* @exception StandardException Standard Derby error policy
* @exception IOException Method may read from InputStream
*/
public Page findUndo(Transaction rawtran, LogicalUndoable pageOp, LimitObjectInput in) throws StandardException, IOException {
ControlRow root = null;
ControlRow control_row = null;
DataValueDescriptor[] logged_index_row_template = null;
DataValueDescriptor[] template = null;
Page ret_page = null;
ContainerHandle container = pageOp.getContainer();
RecordHandle rechandle = pageOp.getRecordHandle();
boolean ok_exit = false;
int compare_result = 1;
B2I btree = null;
try {
// Need Conglomerate to create templates - get from the root page.
root = ControlRow.get(container, BTree.ROOTPAGEID);
if (SanityManager.DEBUG)
SanityManager.ASSERT(root.getPage().isLatched());
btree = (B2I) root.getConglom(B2I.FORMAT_NUMBER);
if (SanityManager.DEBUG)
SanityManager.ASSERT(btree instanceof B2I);
// create a template for the logged index row from the conglomerate.
logged_index_row_template = btree.createTemplate(rawtran);
// create a template for the page index row from the conglomerate.
template = btree.createTemplate(rawtran);
} finally {
if (root != null)
root.release();
}
// Get logged row from record.
pageOp.restoreLoggedRow(logged_index_row_template, in);
// RESOLVE (mikem) - currently restoreLoggedRow() may latch and unlatch
// a page in the container (see ST059).
// Now get the page where the record used to be.
ok_exit = false;
try {
// "open" the btree, using recovery's already opened container
OpenBTree open_btree = new OpenBTree();
open_btree.init(// current user xact - not needed
(TransactionManager) null, // current xact - not needed
(TransactionManager) null, // recovery already opened container
pageOp.getContainer(), rawtran, false, ContainerHandle.MODE_FORUPDATE, // already opened.
TransactionManager.MODE_NONE, // don't get locks during undo
(BTreeLockingPolicy) null, btree, // no logical undo necessary, as
(LogicalUndo) null, // this code only does read.
(DynamicCompiledOpenConglomInfo) null);
// System.out.println(
// "calling logical undo, recordhandle = " + rechandle);
// System.out.println("calling logical undo, record= " +
// logged_index_row_template);
// Get the page where the record was originally, before splits
// could have possibly moved it.
control_row = ControlRow.get(open_btree, rechandle.getPageNumber());
// init compare_result, if record doesn't exist do the search
compare_result = 1;
if (control_row.getPage().recordExists(rechandle, true)) {
if (SanityManager.DEBUG) {
SanityManager.ASSERT(control_row.getPage().fetchNumFields(rechandle) == logged_index_row_template.length);
}
// create template for the page index row from the conglomerate.
RecordHandle ret_rechandle = control_row.getPage().fetchFromSlot((RecordHandle) null, control_row.getPage().getSlotNumber(rechandle), template, (FetchDescriptor) null, true);
// compare the 2 rows, and if they are the same then the raw
// store has the right page and record and there is no work to
// be done (this is usual case).
compare_result = ControlRow.compareIndexRowToKey(template, logged_index_row_template, logged_index_row_template.length, 1, open_btree.getColumnSortOrderInfo());
}
if (compare_result == 0) {
ret_page = control_row.getPage();
} else {
// if the 2 don't compare equal, search the btree from the root
// for the logged row, find the leaf, reset the row for the raw
// store, and return the new page latched.
// Create the objects needed for the insert.
SearchParameters sp = new SearchParameters(logged_index_row_template, ScanController.GE, template, open_btree, false);
control_row.release();
control_row = null;
control_row = ControlRow.get(open_btree, BTree.ROOTPAGEID).search(sp);
if (!sp.resultExact) {
if (SanityManager.DEBUG) {
SanityManager.THROWASSERT("B2IUndo - could not find key being searched for:" + ";key = " + RowUtil.toString(logged_index_row_template) + ";sp = " + sp + "control_row = " + control_row + "control_row.debugPage() = " + control_row.debugPage(open_btree) + "control_row.getPage() = " + control_row.getPage());
}
throw StandardException.newException(SQLState.BTREE_ROW_NOT_FOUND_DURING_UNDO);
} else {
RecordHandle rh = control_row.getPage().fetchFromSlot((RecordHandle) null, sp.resultSlot, new DataValueDescriptor[0], (FetchDescriptor) null, true);
pageOp.resetRecordHandle(rh);
ret_page = control_row.getPage();
}
}
ok_exit = true;
} finally {
// pageOp.getRecordHandle());
if ((!ok_exit) && (control_row != null))
control_row.release();
}
return (ret_page);
}
use of org.apache.derby.iapi.store.raw.Page in project derby by apache.
the class HeapPostCommit method purgeCommittedDeletes.
/**
************************************************************************
* Private/Protected methods of This class:
**************************************************************************
*/
/**
* Reclaim space taken of committed deleted rows or aborted inserted rows.
* <p>
* This routine assumes it has been called by an internal transaction which
* has performed no work so far, and that it has an exclusive intent table
* lock. It will attempt obtain exclusive row locks on rows marked
* deleted, where successful those rows can be reclaimed as they must be
* "committed deleted" or "aborted inserted" rows.
* <p>
* This routine will latch the page and hold the latch due to interface
* requirement from Page.purgeAtSlot.
*
* @param heap_control The heap, already opened.
* @param pageno number of page to look for committed deletes.
*
* @see Page#purgeAtSlot
* @exception StandardException Standard exception policy.
*/
private final void purgeCommittedDeletes(HeapController heap_control, long pageno) throws StandardException {
// The following can fail either if it can't get the latch or
// somehow the page requested no longer exists.
// resolve - what will happen if the user page doesnt exist
// wait to get the latch on the page
Page page = heap_control.getUserPageWait(pageno);
boolean purgingDone = false;
if (page != null) {
try {
// The number records that can be reclaimed is:
// total recs - recs_not_deleted
int num_possible_commit_delete = page.recordCount() - page.nonDeletedRecordCount();
if (num_possible_commit_delete > 0) {
// have already looked at).
for (int slot_no = page.recordCount() - 1; slot_no >= 0; slot_no--) {
boolean row_is_committed_delete = page.isDeletedAtSlot(slot_no);
if (row_is_committed_delete) {
// At this point we only know that the row is
// deleted, not whether it is committed.
// see if we can purge the row, by getting an
// exclusive lock on the row. If it is marked
// deleted and we can get this lock, then it
// must be a committed delete and we can purge
// it.
RecordHandle rh = page.fetchFromSlot((RecordHandle) null, slot_no, RowUtil.EMPTY_ROW, RowUtil.EMPTY_ROW_FETCH_DESCRIPTOR, true);
row_is_committed_delete = heap_control.lockRowAtSlotNoWaitExclusive(rh);
if (row_is_committed_delete) {
purgingDone = true;
page.purgeAtSlot(slot_no, 1, false);
if (SanityManager.DEBUG) {
if (SanityManager.DEBUG_ON("verbose_heap_post_commit")) {
SanityManager.DEBUG_PRINT("HeapPostCommit", "Purging row[" + slot_no + "]" + "on page:" + pageno + ".\n");
}
}
}
}
}
}
if (page.recordCount() == 0) {
purgingDone = true;
// Deallocate the current page with 0 rows on it.
heap_control.removePage(page);
if (SanityManager.DEBUG) {
if (SanityManager.DEBUG_ON("verbose_heap_post_commit")) {
SanityManager.DEBUG_PRINT("HeapPostCommit", "Calling Heap removePage().; pagenumber=" + pageno + "\n");
}
}
}
} finally {
// would cause a subquent undo of the purge to fail.
if (!purgingDone) {
page.unlatch();
page = null;
}
}
} else {
if (SanityManager.DEBUG) {
if (SanityManager.DEBUG_ON("verbose_heap_post_commit")) {
SanityManager.DEBUG_PRINT("HeapPostCommit", "Get No Wait returned null. page num = " + pageno + "\n");
SanityManager.showTrace(new Throwable());
}
}
}
return;
}
use of org.apache.derby.iapi.store.raw.Page in project derby by apache.
the class GenericScanController method replace.
/**
* @see org.apache.derby.iapi.store.access.ScanController#replace
*/
public boolean replace(DataValueDescriptor[] row, FormatableBitSet validColumns) throws StandardException {
repositionScanForUpateOper();
Page page = scan_position.current_page;
int slot = scan_position.current_slot;
if (SanityManager.DEBUG) {
// DERBY-2197: Previously, we would try to get an exclusive row
// lock here when the container was opened in row locking mode. In
// most cases, the container is not opened in row locking mode. If
// it is, and the open conglomerate uses update locks,
// repositionScanForUpateOper() has already obtained an exclusive
// row lock. We don't expect this method to be called unless these
// conditions are satisfied, so now we just assert that no row
// locking is required at this point.
SanityManager.ASSERT(((open_conglom.getContainer().getLockingPolicy().getMode() != LockingPolicy.MODE_RECORD) || (open_conglom.isUseUpdateLocks())), "Current mode of container requires row locking.");
// make sure current_rh and current_slot are in sync
SanityManager.ASSERT(slot == page.getSlotNumber(scan_position.current_rh));
}
boolean ret_val;
if (page.isDeletedAtSlot(slot)) {
ret_val = false;
} else {
page.updateAtSlot(slot, row, validColumns);
ret_val = true;
}
scan_position.unlatch();
return (ret_val);
}
Aggregations