Class BPlusTree<L,T extends L>
java.lang.Object
org.apache.ignite.internal.DataStructure
org.apache.ignite.internal.persistence.tree.BPlusTree<L,T>
- All Implemented Interfaces:
IgniteTree<L,T>
- Direct Known Subclasses:
BPlusTreeReplaceRemoveRaceTest.TestPairTree,IndexDataTree,LongKeyDataTree,ObjectKeyDataTree
public abstract class BPlusTree<L,T extends L>
extends org.apache.ignite.internal.DataStructure
implements IgniteTree<L,T>
Abstract B+Tree.
B+Tree is a block-based tree structure. Each block is represented with the page (PageIO) and contains a
single tree node. There are two types of pages/nodes: BPlusInnerIO and BPlusLeafIO.
Every page in the tree contains a list of items. Item is just a fixed-size binary payload.
Inner nodes and leaves may have different item sizes. There's a limit on how many items each page can hold.
It is defined by a BPlusIO.getMaxCount(long, int) method of the corresponding IO. There should be no empty
pages in trees, so it's expected to have from 1 to max items in every page.
Items might have different meaning depending on the type of the page. In case of leaves, every item must describe a
key and a value. In case of inner nodes, items describe only keys if canGetRowFromInner is false,
or a key and a value otherwise. Items in every page are sorted according to the order dscribed by
compare(BPlusIO, long, int, Object) method. Specifics of the data stored in items are defined in the
implementation and generally don't matter.
All pages in the tree are divided into levels. Leaves are always at the level 0. Levels of inner pages are
thus positive. Each level represents a singly linked list - each page has a link to the forward page at the
same level. It can be retrieved by calling BPlusIO.getForward(long). This link must be a zero if there's no
forward page. Forward links on level 0 allows iterating trees keys and values effectively without traversing
any inner nodes (AbstractForwardCursor). Forward links in inner nodes have different purpose, more on that
later.
Leaves have no links other than forward links. But inner nodes also have links to their children nodes. Every inner
node can be viewed like the following structure:
item(0) item(1) ... item(N-1)
link(0) link(1) link(2) ... link(N-1) link(N)
There are N items and N+1 links. Each link points to page of a lower level. For example, pages on
level 2 always point to pages of level 1. For an item i left subtree is defined by
link(i) and right subtree is defined by link(i+1) (BPlusInnerIO.getLeft(long, int) and
BPlusInnerIO.getRight(long, int)). All items in the left subtree are less or equal to the original item
(basic property for the trees).
There's one more important property of these links: forward(left(i)) == right(i). It is called a
triangle invariant. More information on B+Tree structure can easily be found online. Following documentation
concentrates more on specifics of this particular B+Tree implementation.
General operations.
This implementation allows for concurrent reads and update. Given that each page locks individually, there are general rules to avoid deadlocks.- Pages within a level always locked from left to right.
- If there's already a lock on the page of level X then no locks should be acquired on levels less than X. In other words, locks are aquired from the bottom to the top. The only exception to this rule is the allocation of a new page on a lower level that no one sees yet.
BPlusTree<L,T extends L>.Get ). It goes recursively
from the root to the leaf (if it's needed). On each level several outcomes are possible.
- Exact value is found and operation can be completed.
- Insertion point is found and recursive procedure continues on the lower level.
- Insertion point is not found due to concurrent modifications, but retry in the same node is possible.
- Insertion point is not found due to concurrent modifications, but retry in the same node is impossible.
BPlusTree.Result. Please refer to its usages for specifics of
each operation. Once the path and the leaf for put/remove is found, the operation is then performed from the bottom
to the top. Specifics are described in corresponding classes (BPlusTree<L,T extends L>.Put , BPlusTree<L,T extends L>.Remove ).-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionclassGet operation.classfinal classInvoke operation.final classPut operation.classRemove operation.protected classThe operation of deleting a range of values.classstatic enumOperation result.classstatic interfaceBPlusTree.TreeRowClosure<L,T extends L> A generic visitor-style interface for performing filtering/modifications/miscellaneous operations on the tree.static interfaceBPlusTree.TreeVisitorClosure<L,T extends L> A generic visitor-style interface for performing inspection/modification operations on the tree.Nested classes/interfaces inherited from interface org.apache.ignite.internal.util.IgniteTree
IgniteTree.InvokeClosure<T>, IgniteTree.OperationType -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringDestroy msg.protected final longprotected final intstatic final ThreadLocal<Boolean>static PageHandlerWrapper<BPlusTree.Result>Wrapper for tree pages operations.Fields inherited from class org.apache.ignite.internal.DataStructure
grpId, grpName, lockLsnr, pageAccessHelper, pageFlag, pageMem, reuseList, rnd, wal -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedBPlusTree(String name, int cacheGrpId, int pageSize, PageMemory pageMem, WalManager wal, org.apache.ignite.internal.PageAccessHelper pageHandler, AtomicLong globalRmvId, long metaPageId, ReuseList reuseList, org.apache.ignite.internal.FailureProcessor failureProcessor, PageLockListener lsnr) protectedBPlusTree(String name, int cacheGrpId, int pageSize, PageMemory pageMem, WalManager wal, org.apache.ignite.internal.PageAccessHelper pageHandler, AtomicLong globalRmvId, long metaPageId, ReuseList reuseList, IOVersions<? extends BPlusInnerIO<L>> innerIos, IOVersions<? extends BPlusLeafIO<L>> leafIos, org.apache.ignite.internal.FailureProcessor failureProcessor, PageLockListener lockLsnr) -
Method Summary
Modifier and TypeMethodDescriptionprotected final longacquirePage(long pageId) protected final voidCheck if the tree is getting destroyed.protected intprotected abstract intprotected CorruptedTreeExceptioncorruptedTreeException(String msg, Throwable cause, int grpId, long... pageIds) Construct the exception and invoke failure processor.final longdestroy()Destroys tree.final longdestroy(IgniteInClosure<L> c, boolean forceDestroy) Destroys tree.protected longdestroyDownPages(LongListReuseBag bag, long pageId, int lvl, IgniteInClosure<L> c, AtomicLong lockHoldStartTime, long lockMaxTime, Deque<GridTuple3<Long, Long, Long>> lockedPages) Recursively destroys tree pages.booleanvoidFlag for enabling single-threaded append-only tree creation.final GridCursor<T>Returns a cursor from lower to upper bounds inclusive.final GridCursor<T>Returns a cursor from lower to upper bounds inclusive.Returns a value mapped to the lowest key, ornullif tree is emptyfindFirst(BPlusTree.TreeRowClosure<L, T> filter) Returns a value mapped to the lowest key, ornullif tree is empty or no entry matches the passed filter.findLast()Returns a value mapped to the greatest key, ornullif tree is emptyReturns a value mapped to the greatest key, ornullif tree is empty or no entry matches the passed filter.final TReturns the value to which the specified key is mapped, ornullif this tree contains no mapping for the key.final <R> Rfinal <R> RgetFirstPageIds(long pageAddr) protected intlongReturns meta page id.final StringgetName()final TGet a full detached data row.abstract TGet data row.protected final voidinitTree(boolean initNew) Initialize new tree.protected final voidinitTree(boolean initNew, int inlineSize) Initialize new tree.static voidInterrupt all operations on all threads and all indexes.voidinvoke(L row, Object z, IgniteTree.InvokeClosure<T> c) final booleanisEmpty()voidfinal BPlusInnerIO<L>final BPlusLeafIO<L>protected StringCreate an error message when reaching the maximum number of repetitions to capture a lock in the B+Tree.booleanprotected longMaximum time for which tree destroy process is allowed to hold the lock, after this time exceeds,temporaryReleaseLock()is called and hold time is reset.final StringFor debug.protected voidprocessFailure(org.apache.ignite.internal.FailureType failureType, Throwable e) Processes failure with failure processor.final TPut value in this tree.booleanfinal TRemoves the mapping for a key from this tree if it is present.final booleanfinal intvoidsetIos(IOVersions<? extends BPlusInnerIO<L>> innerIos, IOVersions<? extends BPlusLeafIO<L>> leafIos) final longsize()Returns number of elements in the tree by scanning pages of the bottom (leaf) level.longsize(BPlusTree.TreeRowClosure<L, T> filter) Returns number of elements in the tree that match the filter by scanning through the pages of the leaf level.protected IoStatisticsHolderprotected voidReleases the lock that is held by long tree destroy process for a short period of time and acquires it again, allowing other processes to acquire it.toString()static Stringfinal voidvoidMethods inherited from class org.apache.ignite.internal.DataStructure
acquireAndWrite, acquirePage, allocatePage, allocatePage, allocatePageNoReuse, close, groupId, init, needWalDeltaRecord, randomInt, read, read, readLock, readUnlock, recyclePage, releasePage, tryWriteLock, tryWriteLock, write, write, write, writeLock, writeLock, writeUnlock, writeUnlock
-
Field Details
-
testHndWrapper
Wrapper for tree pages operations. Noop by default. Override for test purposes. -
suspendFailureDiagnostic
-
CONC_DESTROY_MSG
Destroy msg.- See Also:
-
pageSize
protected final int pageSize -
metaPageId
protected final long metaPageId
-
-
Constructor Details
-
BPlusTree
protected BPlusTree(String name, int cacheGrpId, int pageSize, PageMemory pageMem, WalManager wal, org.apache.ignite.internal.PageAccessHelper pageHandler, AtomicLong globalRmvId, long metaPageId, ReuseList reuseList, IOVersions<? extends BPlusInnerIO<L>> innerIos, IOVersions<? extends BPlusLeafIO<L>> leafIos, org.apache.ignite.internal.FailureProcessor failureProcessor, PageLockListener lockLsnr) throws IgniteCheckedException - Parameters:
name- Tree name.cacheGrpId- Cache group ID.pageSize- Page size.pageMem- Page memory.wal- Write ahead log manager.pageHandler- Page access helper.globalRmvId- Remove ID.metaPageId- Meta page ID.reuseList- Reuse list.innerIos- Inner IO versions.leafIos- Leaf IO versions.failureProcessor- if the tree is corrupted.lockLsnr- Page lock listener.- Throws:
IgniteCheckedException- If failed.
-
BPlusTree
protected BPlusTree(String name, int cacheGrpId, int pageSize, PageMemory pageMem, WalManager wal, org.apache.ignite.internal.PageAccessHelper pageHandler, AtomicLong globalRmvId, long metaPageId, ReuseList reuseList, org.apache.ignite.internal.FailureProcessor failureProcessor, PageLockListener lsnr) throws IgniteCheckedException - Parameters:
name- Tree name.cacheGrpId- Cache group ID.pageSize- Page size.pageMem- Page memory.wal- Write ahead log manager.pageHandler- Page access helper.globalRmvId- Remove ID.metaPageId- Meta page ID.reuseList- Reuse list.failureProcessor- if the tree is corrupted.lockLsnr- Page lock listener.- Throws:
IgniteCheckedException- If failed.
-
-
Method Details
-
setIos
public void setIos(IOVersions<? extends BPlusInnerIO<L>> innerIos, IOVersions<? extends BPlusLeafIO<L>> leafIos) - Parameters:
innerIos- Inner IO versions.leafIos- Leaf IO versions.
-
enableSequentialWriteMode
public void enableSequentialWriteMode()Flag for enabling single-threaded append-only tree creation. -
getName
- Returns:
- Tree name.
-
initTree
Initialize new tree.- Parameters:
initNew-Trueif new tree should be created.- Throws:
IgniteCheckedException- If failed.
-
initTree
Initialize new tree.- Parameters:
initNew-Trueif new tree should be created.inlineSize- Inline size.- Throws:
IgniteCheckedException- If failed.
-
checkDestroyed
Check if the tree is getting destroyed.- Throws:
IgniteCheckedException
-
find
Returns a cursor from lower to upper bounds inclusive.- Specified by:
findin interfaceIgniteTree<L,T extends L> - Parameters:
lower- Lower bound ornullif unbounded.upper- Upper bound ornullif unbounded.- Returns:
- Cursor.
- Throws:
IgniteCheckedException- If failed.
-
find
Returns a cursor from lower to upper bounds inclusive.- Specified by:
findin interfaceIgniteTree<L,T extends L> - Parameters:
lower- Lower bound ornullif unbounded.upper- Upper bound ornullif unbounded.x- Implementation specific argument,nullalways means that we need to return full detached data row.- Returns:
- Cursor.
- Throws:
IgniteCheckedException- If failed.
-
find
public GridCursor<T> find(L lower, L upper, BPlusTree.TreeRowClosure<L, T> c, Object x) throws IgniteCheckedException- Parameters:
lower- Lower bound inclusive ornullif unbounded.upper- Upper bound inclusive ornullif unbounded.c- Filter closure.x- Implementation specific argument,nullalways means that we need to return full detached data row.- Returns:
- Cursor.
- Throws:
IgniteCheckedException- If failed.
-
find
public GridCursor<T> find(L lower, L upper, boolean lowIncl, boolean upIncl, BPlusTree.TreeRowClosure<L, T> c, Object x) throws IgniteCheckedException- Parameters:
lower- Lower bound ornullif unbounded.upper- Upper bound ornullif unbounded.lowIncl-trueif lower bound is inclusive.upIncl-trueif upper bound is inclusive.c- Filter closure.x- Implementation specific argument,nullalways means that we need to return full detached data row.- Returns:
- Cursor.
- Throws:
IgniteCheckedException- If failed.
-
iterate
public void iterate(L lower, L upper, BPlusTree.TreeRowClosure<L, T> c) throws IgniteCheckedException- Parameters:
lower- Lower bound inclusive.upper- Upper bound inclusive.c- Closure applied for all found items, iteration is stopped if closure returnsfalse.- Throws:
IgniteCheckedException- If failed.
-
visit
public void visit(L lower, L upper, BPlusTree.TreeVisitorClosure<L, T> c) throws IgniteCheckedException- Parameters:
lower- Lower bound inclusive.upper- Upper bound inclusive.c- Closure applied for all found items.- Throws:
IgniteCheckedException- If failed.
-
findFirst
Returns a value mapped to the lowest key, ornullif tree is empty- Specified by:
findFirstin interfaceIgniteTree<L,T extends L> - Returns:
- Value.
- Throws:
IgniteCheckedException- If failed.
-
findFirst
Returns a value mapped to the lowest key, ornullif tree is empty or no entry matches the passed filter.- Parameters:
filter- Filter closure.- Returns:
- Value.
- Throws:
IgniteCheckedException- If failed.
-
findLast
Returns a value mapped to the greatest key, ornullif tree is empty- Specified by:
findLastin interfaceIgniteTree<L,T extends L> - Returns:
- Value.
- Throws:
IgniteCheckedException- If failed.
-
findLast
Returns a value mapped to the greatest key, ornullif tree is empty or no entry matches the passed filter.- Parameters:
c- Filter closure.- Returns:
- Value.
- Throws:
IgniteCheckedException- If failed.
-
findOne
- Parameters:
row- Lookup row for exact match.x- Implementation specific argument,nullalways means that we need to return full detached data row.- Returns:
- Found result or
null - Throws:
IgniteCheckedException- If failed.
-
findOne
public final <R> R findOne(L row, BPlusTree.TreeRowClosure<L, T> c, Object x) throws IgniteCheckedException- Parameters:
row- Lookup row for exact match.x- Implementation specific argument,nullalways means that we need to return full detached data row.- Returns:
- Found result or
null. - Throws:
IgniteCheckedException- If failed.
-
findOne
Description copied from interface:IgniteTreeReturns the value to which the specified key is mapped, ornullif this tree contains no mapping for the key.- Specified by:
findOnein interfaceIgniteTree<L,T extends L> - Parameters:
row- Lookup row for exact match.- Returns:
- Found row.
- Throws:
IgniteCheckedException- If failed.
-
treeName
- Parameters:
instance- Instance name.type- Tree type.- Returns:
- Tree name.
-
printTree
For debug.- Returns:
- Tree as
String. - Throws:
IgniteCheckedException- If failed.
-
validateTree
- Throws:
IgniteCheckedException- If failed.
-
interruptAll
public static void interruptAll()Interrupt all operations on all threads and all indexes. -
remove
Description copied from interface:IgniteTreeRemoves the mapping for a key from this tree if it is present.- Specified by:
removein interfaceIgniteTree<L,T extends L> - Parameters:
row- Lookup row.- Returns:
- Removed row.
- Throws:
IgniteCheckedException- If failed.
-
removex
- Parameters:
row- Lookup row.- Returns:
Trueif removed row.- Throws:
IgniteCheckedException- If failed.
-
remove
- Parameters:
lower- Lower bound (inclusive).upper- Upper bound (inclusive).limit- Limit of processed entries by single call,0for no limit.- Returns:
- Removed rows.
- Throws:
IgniteCheckedException- If failed.
-
invoke
- Specified by:
invokein interfaceIgniteTree<L,T extends L> - Parameters:
row- Key.z- Implementation specific argument,nullalways means that we need a full detached data row.c- Closure.- Throws:
IgniteCheckedException- If failed.
-
rootLevel
- Returns:
- Root level.
- Throws:
IgniteCheckedException- If failed.
-
isEmpty
- Returns:
Truein case the tree is empty.- Throws:
IgniteCheckedException- If failed.
-
size
Returns number of elements in the tree by scanning pages of the bottom (leaf) level. Since a concurrent access is permitted, there is no guarantee about momentary consistency: the method may miss updates made in already scanned pages.- Specified by:
sizein interfaceIgniteTree<L,T extends L> - Returns:
- Number of elements in the tree.
- Throws:
IgniteCheckedException- If failed.
-
size
Returns number of elements in the tree that match the filter by scanning through the pages of the leaf level. Since a concurrent access to the tree is permitted, there is no guarantee about momentary consistency: the method may not see updates made in already scanned pages.- Parameters:
filter- The filter to use or null to count all elements.- Returns:
- Number of either all elements in the tree or the elements that match the filter.
- Throws:
IgniteCheckedException- If failed.
-
put
Put value in this tree.- Specified by:
putin interfaceIgniteTree<L,T extends L> - Parameters:
row- Value to be associated with the specified key.- Returns:
- The previous value associated with key.
- Throws:
IgniteCheckedException- If failed.
-
putx
- Parameters:
row- New value.- Returns:
Trueif replaced existing row.- Throws:
IgniteCheckedException- If failed.
-
temporaryReleaseLock
protected void temporaryReleaseLock()Releases the lock that is held by long tree destroy process for a short period of time and acquires it again, allowing other processes to acquire it. -
maxLockHoldTime
protected long maxLockHoldTime()Maximum time for which tree destroy process is allowed to hold the lock, after this time exceeds,temporaryReleaseLock()is called and hold time is reset.- Returns:
- Time, in milliseconds.
-
destroy
Destroys tree. This method is allowed to be invoked only when the tree is out of use (no concurrent operations are trying to read or update the tree after destroy beginning).- Returns:
- Number of pages recycled from this tree. If the tree was destroyed by someone else concurrently returns
0, otherwise it should return at least2(for meta page and root page), unless this tree is used as metadata storage, or-1if we don't have a reuse list and did not do recycling at all. - Throws:
IgniteCheckedException- If failed.
-
destroy
Destroys tree. This method is allowed to be invoked only when the tree is out of use (no concurrent operations are trying to read or update the tree after destroy beginning).- Parameters:
c- Visitor closure. Visits only leaf pages.forceDestroy- Whether to proceed with destroying, even if tree is already marked as destroyed (seemarkDestroyed()).- Returns:
- Number of pages recycled from this tree. If the tree was destroyed by someone else concurrently returns
0, otherwise it should return at least2(for meta page and root page), unless this tree is used as metadata storage, or-1if we don't have a reuse list and did not do recycling at all. - Throws:
IgniteCheckedException- If failed.
-
destroyDownPages
protected long destroyDownPages(LongListReuseBag bag, long pageId, int lvl, IgniteInClosure<L> c, AtomicLong lockHoldStartTime, long lockMaxTime, Deque<GridTuple3<Long, Long, throws IgniteCheckedExceptionLong>> lockedPages) Recursively destroys tree pages. Should be initially called with id of root page aspageIdand root level aslvl.- Parameters:
bag- Reuse bag.pageId- Page id.lvl- Current level of tree.c- Visitor closure. Visits only leaf pages.lockHoldStartTime- When lock has been aquired last time.lockMaxTime- Maximum time to hold the lock.lockedPages- Deque of locked pages. Is used to release write-locked pages when temporary releasing checkpoint read lock.- Returns:
- Count of destroyed pages.
- Throws:
IgniteCheckedException- If failed.
-
markDestroyed
public boolean markDestroyed()- Returns:
Trueif state was changed.
-
destroyed
public boolean destroyed()- Returns:
Trueif marked as destroyed.
-
getFirstPageIds
- Parameters:
pageAddr- Meta page address.- Returns:
- First page IDs.
-
toString
-
latestInnerIO
- Returns:
- Latest version of inner page IO.
-
latestLeafIO
- Returns:
- Latest version of leaf page IO.
-
compare
protected abstract int compare(BPlusIO<L> io, long pageAddr, int idx, L row) throws IgniteCheckedException - Parameters:
io- IO.pageAddr- Page address.idx- Index of row in the given buffer.row- Lookup row.- Returns:
- Comparison result as in
Comparator.compare(Object, Object). - Throws:
IgniteCheckedException- If failed.
-
compare
protected int compare(int lvl, BPlusIO<L> io, long pageAddr, int idx, L row) throws IgniteCheckedException - Parameters:
lvl- Level.io- IO.pageAddr- Page address.idx- Index of row in the given buffer.row- Lookup row.- Returns:
- Comparison result as in
Comparator.compare(Object, Object). - Throws:
IgniteCheckedException- If failed.
-
getRow
Get a full detached data row.- Parameters:
io- IO.pageAddr- Page address.idx- Index.- Returns:
- Full detached data row.
- Throws:
IgniteCheckedException- If failed.
-
getRow
public abstract T getRow(BPlusIO<L> io, long pageAddr, int idx, Object x) throws IgniteCheckedException Get data row. Can be called on inner page only ifcanGetRowFromInneristrue.- Parameters:
io- IO.pageAddr- Page address.idx- Index.x- Implementation specific argument,nullalways means that we need to return full detached data row.- Returns:
- Data row.
- Throws:
IgniteCheckedException- If failed.
-
getLockRetries
protected int getLockRetries()- Returns:
- Return number of retries.
-
acquirePage
- Parameters:
pageId- Page ID.- Returns:
- Page absolute pointer.
- Throws:
IgniteCheckedException- If failed.
-
statisticsHolder
- Returns:
- Statistics holder to track IO operations.
-
corruptedTreeException
protected CorruptedTreeException corruptedTreeException(String msg, Throwable cause, int grpId, long... pageIds) Construct the exception and invoke failure processor.- Parameters:
msg- Message.cause- Cause.grpId- Group id.pageIds- Pages ids.- Returns:
- New CorruptedTreeException instance.
-
processFailure
Processes failure with failure processor.- Parameters:
failureType- Failure type.e- Exception.
-
getMetaPageId
public long getMetaPageId()Returns meta page id.- Returns:
- Meta page id.
-
lockRetryErrorMessage
Create an error message when reaching the maximum number of repetitions to capture a lock in the B+Tree.- Parameters:
op- Operation name, for example: GET, PUT.- Returns:
- Error message.
-