public class BTreeController extends OpenBTree implements ConglomerateController
Concurrency Notes
The concurrency rules are derived from OpenBTree.
OpenBTree
Modifier and Type | Field and Description |
---|---|
(package private) boolean |
get_insert_row_lock
Whether to get lock on the row being inserted, usually this lock
has already been gotten when the row was inserted into the base table.
|
private static int |
MATCH_FOUND |
private static int |
NO_MATCH |
private static int |
RESCAN_REQUIRED |
(package private) DataValueDescriptor[] |
scratch_template |
btree_undo, container, err_containerid, init_lock_level, init_open_user_scans, runtime_mem
LOCK_INS, LOCK_INS_PREVKEY, LOCK_READ, LOCK_UPD, LOCK_UPDATE_LOCKS, ROWISDUPLICATE
Constructor and Description |
---|
BTreeController() |
Modifier and Type | Method and Description |
---|---|
void |
close()
Close the conglomerate controller.
|
boolean |
closeForEndTransaction(boolean closeHeldScan)
Close conglomerate controller as part of terminating a transaction.
|
private int |
compareLeftAndRightSiblings(DataValueDescriptor[] rowToInsert,
int insert_slot,
LeafControlRow targetleaf)
Compares immidiate left and right records to check for duplicates.
|
private int |
compareNextRecord(int slot,
LeafControlRow leaf,
DataValueDescriptor[] rows,
DataValueDescriptor[] oldRows)
Compares the new record with the one at slot or the one
right to it.
|
private int |
comparePreviousRecord(int slot,
LeafControlRow leaf,
DataValueDescriptor[] rows,
DataValueDescriptor[] oldRows)
Compares the oldrow with the one at 'slot' or the one left to it.
|
private int |
compareRowsForInsert(DataValueDescriptor[] originalRow,
DataValueDescriptor[] newRow,
LeafControlRow leaf,
int slot)
Compares two rows for insert.
|
boolean |
delete(RowLocation loc)
Delete a row from the conglomerate.
|
private boolean |
do_load_insert(DataValueDescriptor[] rowToInsert,
LeafControlRow leaf,
int insert_slot)
Just insert the row on the current page/slot if it fits.
|
private LeafControlRow |
do_load_split(DataValueDescriptor[] rowToInsert,
LeafControlRow leaf)
Create room to insert a row to the right of the largest key in table.
|
private int |
doIns(DataValueDescriptor[] rowToInsert)
Insert a row into the conglomerate.
|
boolean |
fetch(RowLocation loc,
DataValueDescriptor[] row,
FormatableBitSet validColumns)
Fetch the row at the given location.
|
boolean |
fetch(RowLocation loc,
DataValueDescriptor[] row,
FormatableBitSet validColumns,
boolean waitForLock)
Fetch the row at the given location.
|
java.util.Properties |
getInternalTablePropertySet(java.util.Properties prop)
Request set of properties associated with a table.
|
void |
getTableProperties(java.util.Properties prop)
Request the system properties associated with a table.
|
void |
init(TransactionManager xact_manager,
boolean hold,
ContainerHandle container,
Transaction rawtran,
int open_mode,
int lock_level,
BTreeLockingPolicy btree_locking_policy,
BTree conglomerate,
LogicalUndo undo,
StaticCompiledOpenConglomInfo static_info,
DynamicCompiledOpenConglomInfo dynamic_info)
Initialize the controller for use.
|
int |
insert(DataValueDescriptor[] row)
Insert a row into the conglomerate.
|
void |
insertAndFetchLocation(DataValueDescriptor[] row,
RowLocation templateRowLocation)
Insert a row into the conglomerate, and store its location in the
provided template row location.
|
boolean |
isKeyed()
Return whether this is a keyed conglomerate.
|
long |
load(TransactionManager xact_manager,
boolean createConglom,
RowLocationRetRowSource rowSource)
Load rows from rowSource into the opened btree.
|
boolean |
lockRow(long page_num,
int record_id,
int lock_operation,
boolean wait,
int lock_duration)
Lock the given record id/page num pair.
|
boolean |
lockRow(RowLocation loc,
int lock_operation,
boolean wait,
int lock_duration)
Lock the given row location.
|
RowLocation |
newRowLocationTemplate()
Return a row location object of the correct type to be
used in calls to insertAndFetchLocation.
|
private boolean |
reclaim_deleted_rows(OpenBTree open_btree,
long pageno)
Attempt to reclaim committed deleted rows from the page.
|
boolean |
replace(RowLocation loc,
DataValueDescriptor[] row,
FormatableBitSet validColumns)
Replace the entire row at the given location.
|
private long |
start_xact_and_dosplit(boolean attempt_to_reclaim_deleted_rows,
long leaf_pageno,
DataValueDescriptor[] scratch_template,
DataValueDescriptor[] rowToInsert,
int flag)
Start an internal transaction and do the split.
|
void |
unlockRowAfterRead(RowLocation loc,
boolean forUpdate,
boolean row_qualifies)
UnLock the given row location.
|
checkConsistency, debugConglomerate, getColumnSortOrderInfo, getConglomerate, getContainer, getContainerHandle, getEstimatedRowCount, getHeight, getHold, getLockingPolicy, getLockLevel, getOpenMode, getRawTran, getRuntimeMem, getSpaceInfo, getXactMgr, init, isClosed, isIndexableRowConsistent, isTableLocked, reopen, setEstimatedRowCount, setLockingPolicy, test_errors
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
checkConsistency, debugConglomerate, getSpaceInfo
transient DataValueDescriptor[] scratch_template
boolean get_insert_row_lock
private static final int NO_MATCH
private static final int MATCH_FOUND
private static final int RESCAN_REQUIRED
private boolean reclaim_deleted_rows(OpenBTree open_btree, long pageno) throws StandardException
Get exclusive latch on page, and then loop backward through page searching for deleted rows which are committed. The routine assumes that it is called from a transaction which cannot have deleted any rows on the page. For each deleted row on the page it attempts to get an exclusive lock on the deleted row, NOWAIT. If it succeeds, and since this row did not delete the row then the row must have been deleted by a transaction which has committed, so it is safe to purge the row. It then purges the row from the page.
Note that this routine may remove all rows from the page, it will not attempt a merge in this situation. This is because this routine is called from split which is attempting an insert on the given page, so it would be a waste to merge the page only to split it again to allow the insert of the row causing the split.
open_btree
- The already open btree to use to get latch on page.pageno
- The page number of the leaf to attempt the reclaim on.StandardException
- Standard exception policy.private long start_xact_and_dosplit(boolean attempt_to_reclaim_deleted_rows, long leaf_pageno, DataValueDescriptor[] scratch_template, DataValueDescriptor[] rowToInsert, int flag) throws StandardException
This routine starts a new transaction, and handles any errors that may come during the transaction. This transation must not obtain any locks as they are likely to conflict with the current user transaction.
If attempt_to_reclaim_deleted_rows is true this routine will attempt to reclaim space on the leaf page input, by purging committed deleted rows from the leaf. If it succeeds in purging at least one row, then it will commit the internal transaction and return without actually performing a split.
scratch_template
- A scratch template used to search a page.rowToInsert
- The row to insert, make sure during split to
make room for this row.StandardException
- Standard exception policy.private int comparePreviousRecord(int slot, LeafControlRow leaf, DataValueDescriptor[] rows, DataValueDescriptor[] oldRows) throws StandardException
slot
- slot number to start withleaf
- LeafControlRow of the current pagerows
- DataValueDescriptot array to fill it with fetched valuesStandardException
private int compareNextRecord(int slot, LeafControlRow leaf, DataValueDescriptor[] rows, DataValueDescriptor[] oldRows) throws StandardException
slot
- slot number to start withleaf
- LeafControlRow of the current pagerows
- DataValueDescriptot array to fill it with fetched valuesStandardException
private int compareRowsForInsert(DataValueDescriptor[] originalRow, DataValueDescriptor[] newRow, LeafControlRow leaf, int slot) throws StandardException
NO_MATCH
is returned. Otherwise, it tries to get a lock on
the row in the tree. If the lock is obtained without waiting,
MATCH_FOUND
is returned (even if the row has been deleted).
Otherwise, RESCAN_REQUIRED
is returned to indicate that the
latches have been released and the B-tree must be rescanned.
If MATCH_FOUND
is returned, the caller should check whether
the row has been deleted. If so, it may have to move to check the
adjacent rows to be sure that there is no non-deleted duplicate row.
If MATCH_FOUND
or RESCAN_REQUIRED
is returned, the
transaction will hold an update lock on the specified record when
the method returns.
Note! This method should only be called when the index is almost
unique (that is, a non-unique index backing a unique constraint).originalRow
- row from the treenewRow
- row to be insertedleaf
- leaf where originalRow residesslot
- slot where originalRowNO_MATCH
if no duplicate is found,
MATCH_FOUND
if a duplicate is found, or
RESCAN_REQUIRED
if the B-tree must be rescannedStandardException
private int compareLeftAndRightSiblings(DataValueDescriptor[] rowToInsert, int insert_slot, LeafControlRow targetleaf) throws StandardException
rowToInsert
- row being insertedinsert_slot
- slot where rowToInsert is being insertedtargetleaf
- page where rowToInsertStandardException
private int doIns(DataValueDescriptor[] rowToInsert) throws StandardException
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.StandardException
- Standard exception policy.private boolean do_load_insert(DataValueDescriptor[] rowToInsert, LeafControlRow leaf, int insert_slot) throws StandardException
StandardException
- Standard exception policy.private LeafControlRow do_load_split(DataValueDescriptor[] rowToInsert, LeafControlRow leaf) throws StandardException
Perform a split pass on the tree which will move the largest key in leaf right to a new leaf, splitting parent branch pages as necessary.
StandardException
- Standard exception policy.public void init(TransactionManager xact_manager, boolean hold, ContainerHandle container, Transaction rawtran, int open_mode, int lock_level, BTreeLockingPolicy btree_locking_policy, BTree conglomerate, LogicalUndo undo, StaticCompiledOpenConglomInfo static_info, DynamicCompiledOpenConglomInfo dynamic_info) throws StandardException
Any changes to this method will probably have to be reflected in close as well.
Currently delegates to OpenBTree. If the btree controller ends up not having any state of its own, we can remove this method (the VM will dispatch to OpenBTree), gaining some small efficiency. For now, this method remains for clarity.
StandardException
- Standard exception policy.public void close() throws StandardException
Any changes to this method will probably have to be reflected in close as well.
Currently delegates to OpenBTree. If the btree controller ends up not having any state of its own, we can remove this method (the VM will dispatch to OpenBTree), gaining some small efficiency. For now, this method remains for clarity.
close
in interface ConglomerateController
close
in class OpenBTree
StandardException
- Standard exception policy.ConglomerateController.close()
public boolean closeForEndTransaction(boolean closeHeldScan) throws StandardException
Use this call to close the conglomerate controller resources as part of committing or aborting a transaction. The normal close() routine may do some cleanup that is either unnecessary, or not correct due to the unknown condition of the controller following a transaction ending error. Use this call when closing all controllers as part of an abort of a transaction.
This call is meant to only be used internally by the Storage system, clients of the storage system should use the simple close() interface.
RESOLVE (mikem) - move this call to ConglomerateManager so it is obvious that non-access clients should not call this.
closeForEndTransaction
in interface ConglomerateController
closeHeldScan
- If true, means to close controller even if
it has been opened to be kept opened
across commit. This is
used to close these controllers on abort.StandardException
- Standard exception policy.public int insert(DataValueDescriptor[] row) throws StandardException
insert
in interface ConglomerateController
row
- 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.StandardException
- Standard exception policy.ConglomerateController.insert(org.apache.derby.iapi.types.DataValueDescriptor[])
public boolean isKeyed()
All b-trees are keyed.
isKeyed
in interface ConglomerateController
ConglomerateController.isKeyed()
public void getTableProperties(java.util.Properties prop) throws StandardException
Request the value of properties that are associated with a table. The following properties can be requested: derby.storage.pageSize derby.storage.pageReservedSpace derby.storage.minimumRecordSize derby.storage.initialPages
To get the value of a particular property add it to the property list, and on return the value of the property will be set to it's current value. For example: get_prop(ConglomerateController cc) { Properties prop = new Properties(); prop.put("derby.storage.pageSize", ""); cc.getTableProperties(prop); System.out.println( "table's page size = " + prop.getProperty("derby.storage.pageSize"); }
getTableProperties
in interface ConglomPropertyQueryable
prop
- Property list to fill in.StandardException
- Standard exception policy.public java.util.Properties getInternalTablePropertySet(java.util.Properties prop) throws StandardException
Returns a property object containing all properties that the store knows about, which are stored persistently by the store. This set of properties may vary from implementation to implementation of the store.
This call is meant to be used only for internal query of the properties by jbms, for instance by language during bulk insert so that it can create a new conglomerate which exactly matches the properties that the original container was created with. This call should not be used by the user interface to present properties to users as it may contain properties that are meant to be internal to jbms. Some properties are meant only to be specified by jbms code and not by users on the command line.
Note that not all properties passed into createConglomerate() are stored persistently, and that set may vary by store implementation.
getInternalTablePropertySet
in interface ConglomPropertyQueryable
prop
- Property list to add properties to. If null, routine will
create a new Properties object, fill it in and return it.StandardException
- Standard exception policy.public long load(TransactionManager xact_manager, boolean createConglom, RowLocationRetRowSource rowSource) throws StandardException
Efficiently load rows into the already opened btree. The btree must be table locked, as no row locks will be requested by this routine. On exit from this routine the conglomerate will be closed (on both error or success).
This routine does an almost bottom up build of a btree. It assumes all rows arrive in sorted order, and inserts them directly into the next (to the right) spot in the current leaf until there is no space. Then it calls the generic split code to add the next leaf (RESOLVE - in the future we could optimize this to split bottom up rather than top down for create index).
StandardException
- Standard exception policy. If conglomerate
supports uniqueness checks and has been
created to disallow duplicates, and one of
the rows being loaded had key columns which
were duplicate of a row already in the
conglomerate, then raise
SQLState.STORE_CONGLOMERATE_DUPLICATE_KEY_EXCEPTION.Conglomerate.load(org.apache.derby.iapi.store.access.conglomerate.TransactionManager, boolean, org.apache.derby.iapi.store.access.RowLocationRetRowSource)
public boolean delete(RowLocation loc) throws StandardException
delete
in interface ConglomerateController
StandardException
- Standard exception policy.ConglomerateController.delete(org.apache.derby.iapi.types.RowLocation)
public boolean fetch(RowLocation loc, DataValueDescriptor[] row, FormatableBitSet validColumns) throws StandardException
fetch
in interface ConglomerateController
loc
- The "RowLocation" which describes the exact row
to fetch from the table.row
- The row to read the data into.validColumns
- A description of which columns to return from
row on the page into "destRow." destRow
and validColumns work together to
describe the row to be returned by the fetch -
see RowUtil for description of how these three
parameters work together to describe a fetched
"row".StandardException
- Standard exception policy.ConglomerateController.fetch(org.apache.derby.iapi.types.RowLocation, org.apache.derby.iapi.types.DataValueDescriptor[], org.apache.derby.iapi.services.io.FormatableBitSet)
public boolean fetch(RowLocation loc, DataValueDescriptor[] row, FormatableBitSet validColumns, boolean waitForLock) throws StandardException
fetch
in interface ConglomerateController
loc
- The "RowLocation" which describes the exact row
to fetch from the table.row
- The row to read the data into.validColumns
- A description of which columns to return from
row on the page into "destRow." destRow
and validColumns work together to
describe the row to be returned by the fetch -
see RowUtil for description of how these three
parameters work together to describe a fetched
"row".waitForLock
- If false, then the call will throw a lock timeout
exception immediately, if the lock can not be
granted without waiting. If true call will
act exactly as fetch() interface with no
waitForLock parameter.StandardException
- Standard exception policy.ConglomerateController.fetch(org.apache.derby.iapi.types.RowLocation, org.apache.derby.iapi.types.DataValueDescriptor[], org.apache.derby.iapi.services.io.FormatableBitSet)
public void insertAndFetchLocation(DataValueDescriptor[] row, RowLocation templateRowLocation) throws StandardException
insertAndFetchLocation
in interface ConglomerateController
row
- 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.templateRowLocation
- The rowlocation to read the inserted row location
into.StandardException
- Standard exception policy.ConglomerateController.insertAndFetchLocation(org.apache.derby.iapi.types.DataValueDescriptor[], org.apache.derby.iapi.types.RowLocation)
public RowLocation newRowLocationTemplate() throws StandardException
newRowLocationTemplate
in interface ConglomerateController
StandardException
- Standard exception policy.ConglomerateController.newRowLocationTemplate()
public boolean lockRow(RowLocation loc, int lock_operation, boolean wait, int lock_duration) throws StandardException
Should only be called by access.
This call can be made on a ConglomerateController that was opened for locking only.
RESOLVE (mikem) - move this call to ConglomerateManager so it is obvious that non-access clients should not call this.
lockRow
in interface ConglomerateController
loc
- The "RowLocation" which describes the exact row to lock.wait
- Should the lock call wait to be granted?lock_operation
- For what operation are we requesting the lock, this
should be one of the following 4 options:
LOCK_READ [read lock],
(LOCK_INS | LOCK_UPD) [ lock for insert],
(LOCK_INSERT_PREVKEY | LOCK_UPD) [lock for
previous key to insert],
(LOCK_UPD) [lock for delete or replace]
(LOCK_UPD | LOCK_UPDATE_LOCKS) [lock scan for
update, will upgrade lock later if actual update
is take place]lock_duration
- If set to TransactionManager.LOCK_INSTANT_DURATION,
then lock will be released immediately after being
granted.StandardException
- Standard exception policy.public boolean lockRow(long page_num, int record_id, int lock_operation, boolean wait, int lock_duration) throws StandardException
ConglomerateController
Should only be called by access, to lock "special" locks formed from the Recordhandle.* reserved constants for page specific locks.
This call can be made on a ConglomerateController that was opened for locking only.
RESOLVE (mikem) - move this call to ConglomerateManager so it is obvious that non-access clients should not call this.
lockRow
in interface ConglomerateController
page_num
- page number of record to lock.record_id
- record id of record to lock.lock_operation
- For what operation are we requesting the lock, this
should be one of the following 4 options:
LOCK_READ [read lock],
(LOCK_INS | LOCK_UPD) [ lock for insert],
(LOCK_INSERT_PREVKEY | LOCK_UPD) [lock for
previous key to insert],
(LOCK_UPD) [lock for delete or replace]
(LOCK_UPD | LOCK_UPDATE_LOCKS) [lock scan for
update, will upgrade lock later if actual update
is take place]wait
- Should the lock call wait to be granted?lock_duration
- If set to TransactionManager.LOCK_INSTANT_DURATION,
then lock will be released immediately after being
granted.StandardException
- Standard exception policy.public void unlockRowAfterRead(RowLocation loc, boolean forUpdate, boolean row_qualifies) throws StandardException
ConglomerateController
Should only be called by access.
This call can be made on a ConglomerateController that was opened for locking only.
RESOLVE (mikem) - move this call to ConglomerateManager so it is obvious that non-access clients should not call this.
unlockRowAfterRead
in interface ConglomerateController
loc
- The "RowLocation" which describes the row to unlock.forUpdate
- Row was locked for read or update.row_qualifies
- Row was qualified and returned to the user.StandardException
- Standard exception policy.public boolean replace(RowLocation loc, DataValueDescriptor[] row, FormatableBitSet validColumns) throws StandardException
replace
in interface ConglomerateController
StandardException
- Standard exception policy.ConglomerateController.replace(org.apache.derby.iapi.types.RowLocation, org.apache.derby.iapi.types.DataValueDescriptor[], org.apache.derby.iapi.services.io.FormatableBitSet)
Apache Derby V10.13 Internals - Copyright © 2004,2016 The Apache Software Foundation. All Rights Reserved.