|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||
java.lang.Objectcom.bigdata.btree.PO
com.bigdata.btree.AbstractNode<T>
public abstract class AbstractNode<T extends AbstractNode>
Abstract node supporting incremental persistence and copy-on-write semantics.
| Field Summary | |
|---|---|
protected AbstractBTree |
btree
The BTree. |
protected static boolean |
INFO
True iff the log level is INFO or less. |
protected static org.apache.log4j.Logger |
log
Log for node and leaf operations. |
protected Reference<Node> |
parent
The parent of this node. |
protected int |
referenceCount
The #of times that this node is present on the HardReferenceQueue . |
protected Reference<? extends AbstractNode<T>> |
self
A Reference to this Node. |
| Fields inherited from class com.bigdata.btree.PO |
|---|
deleted, dirty, identity |
| Fields inherited from interface com.bigdata.btree.IIdentityAccess |
|---|
NULL |
| Constructor Summary | |
|---|---|
protected |
AbstractNode(AbstractBTree btree,
boolean dirty)
All constructors delegate to this constructor to set the btree and branching factor and to compute the minimum and maximum #of keys for the node. |
protected |
AbstractNode(AbstractNode<T> src)
Copy constructor. |
| Method Summary | |
|---|---|
protected void |
assertInvariants()
Invariants: A node with nkeys + 1 children. A node must have between [m/2:m] children (alternatively, between [m/2-1:m-1] keys since nkeys + 1 == nchildren for a node). A leaf has no children and has between [m/2:m] key-value pairs (the same as the #of children on a node). The root leaf may be deficient (may have less than m/2 key-value pairs). where m is the branching factor and a node is understood
to be a non-leaf node in the tree. |
protected void |
assertKeysMonotonic()
Verify keys are monotonically increasing. |
protected void |
copyKey(int dstpos,
IRaba srckeys,
int srcpos)
Copy a key from the source node into this node. |
protected AbstractNode<?> |
copyOnWrite()
Return this leaf iff it is dirty (aka mutable) and otherwise return a copy of this leaf. |
protected AbstractNode<T> |
copyOnWrite(long triggeredByChildId)
Return this node or leaf iff it is dirty (aka mutable) and otherwise return a copy of this node or leaf. |
void |
delete()
Deletes the persistence capable object. |
boolean |
dump(org.apache.log4j.Level level,
PrintStream out)
Dump the data onto the PrintStream. |
abstract boolean |
dump(org.apache.log4j.Level level,
PrintStream out,
int height,
boolean recursive)
Dump the data onto the PrintStream. |
boolean |
dump(PrintStream out)
Dump the data onto the PrintStream (non-recursive). |
ITupleIterator |
entryIterator()
Traversal of index values in key order. |
int |
getBranchingFactor()
|
Node |
getParent()
The parent iff the node has been added as the child of another node and the parent reference has not been cleared. |
abstract long |
indexOf(byte[] searchKey)
Recursive search locates the appropriate leaf and returns the index position of the entry. |
abstract Tuple |
insert(byte[] key,
byte[] val,
boolean delete,
long timestamp,
Tuple tuple)
Insert or update a value. |
abstract boolean |
isLeaf()
True iff this is a leaf node. |
protected boolean |
isLeftMostNode()
Return true if this node is the left-most node at its
level within the tree. |
protected boolean |
isRightMostNode()
Return true if this node is the right-most node at its
level within the tree. |
protected void |
join()
Join this node (must be deficient) with either its left or right sibling. |
protected static String |
keyAsString(byte[] key)
Return a human readable representation of the key. |
abstract byte[] |
keyAt(long index)
Recursive search locates the entry at the specified index position in the btree and returns the key for that entry. |
abstract Tuple |
lookup(byte[] searchKey,
Tuple tuple)
Lookup a key. |
protected abstract int |
maxKeys()
The maximum #of keys. |
protected abstract void |
merge(AbstractNode sibling,
boolean isRightSibling)
Merge the sibling into this node. |
protected abstract int |
minKeys()
The minimum #of keys. |
abstract Iterator<AbstractNode> |
postOrderIterator(byte[] fromKey,
byte[] toKey)
Post-order traversal of nodes and leaves in the tree with a key range constraint. |
Iterator<AbstractNode> |
postOrderNodeIterator()
Post-order traveral of nodes and leaves in the tree. |
Iterator<AbstractNode> |
postOrderNodeIterator(boolean dirtyNodesOnly)
Post-order traversal of nodes and leaves in the tree. |
abstract Iterator<AbstractNode> |
postOrderNodeIterator(boolean dirtyNodesOnly,
boolean nodesOnly)
Post-order traversal of nodes and leaves in the tree. |
ITupleIterator |
rangeIterator(byte[] fromKey,
byte[] toKey,
int flags)
Return an iterator that visits the entries in a half-open key range but filters the values. |
protected abstract void |
redistributeKeys(AbstractNode sibling,
boolean isRightSibling)
Redistribute the one key from the sibling into this node. |
abstract Tuple |
remove(byte[] searchKey,
Tuple tuple)
Recursive search locates the appropriate leaf and removes the entry for the key. |
protected abstract IAbstractNode |
split()
Split a node or leaf that is over capacity (by one). |
abstract void |
valueAt(long index,
Tuple tuple)
Recursive search locates the entry at the specified index position in the btree and returns the value for that entry. |
| Methods inherited from class com.bigdata.btree.PO |
|---|
getIdentity, indent, isDeleted, isDirty, isPersistent, setDirty, setIdentity, toShortString, toString |
| Methods inherited from class java.lang.Object |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
| Methods inherited from interface com.bigdata.btree.data.IAbstractNodeData |
|---|
data, getMaximumVersionTimestamp, getMinimumVersionTimestamp, hasVersionTimestamps, isCoded, isReadOnly |
| Methods inherited from interface com.bigdata.btree.data.IKeysData |
|---|
getKeyCount, getKeys |
| Field Detail |
|---|
protected static final org.apache.log4j.Logger log
Category.isInfoEnabled() before generating log
messages at this level to avoid string concatenation operations would
otherwise kill performance.Category.isDebugEnabled() before generating log
messages at this level to avoid string concatenation operations would
otherwise kill performance.
AbstractBTree.log,
AbstractBTree.dumpLogprotected static final boolean INFO
log level is INFO or less.
protected final transient AbstractBTree btree
protected transient Reference<Node> parent
BTree) or a dirty child (held by the Node). The parent
reference is set when a node is attached as the child of another node.
Note: When a node is cloned by copyOnWrite() the parent
references for its clean children are set to the new copy of the
node. This is referred to in several places as "stealing" the children
since they are no longer linked back to their old parents via their
parent reference.
protected final transient Reference<? extends AbstractNode<T extends AbstractNode>> self
A Reference to this Node. This is created when the node
is created and is reused by a children of the node as the
Reference to their parent. This results in few Reference
objects in use by the B+Tree since it effectively provides a canonical
Reference object for any given Node.
protected transient int referenceCount
HardReferenceQueue .
This value is incremented each time the node is added to the queue and is
decremented each time the node is evicted from the queue. On eviction, if
the counter is zero(0) after it is decremented then the node is written
on the store. This mechanism is critical because it prevents a node
entering the queue from forcing IO for the same node in the edge case
where the node is also on the tail on the queue. Since the counter is
incremented before it is added to the queue, it is guaranteed to be
non-zero when the node forces its own eviction from the tail of the
queue. Preventing this edge case is important since the node can
otherwise become immutable at the very moment that it is touched to
indicate that we are going to update its state, e.g., during an insert,
split, or remove operation. This mechanism also helps to defer IOs since
IO can not occur until the last reference to the node is evicted from the
queue.
Note that only mutable BTrees may have dirty nodes and the
BTree is NOT thread-safe for writers so we do not need to use
synchronization or an AtomicInteger for the referenceCount
field.
| Constructor Detail |
|---|
protected AbstractNode(AbstractBTree btree,
boolean dirty)
final data fields
rather than permitting that logic to be replicated throughout the code
with the corresponding difficulty in ensuring that the logic is correct
throughout.
btree - The btree to which the node belongs.branchingFactor - The branching factor for the node. By passing the branching
factor rather than using the branching factor declared on the
btree we are able to support different branching factors at
different levels of the tree.dirty - Used to set the PO.dirty state. All nodes and leaves
created by non-deserialization constructors begin their life
cycle as dirty := true All nodes or leaves
de-serialized from the backing store begin their life cycle as
clean (dirty := false). This we read nodes and leaves into
immutable objects, those objects will remain clean. Eventually
a copy-on-write will create a mutable node or leaf from the
immutable one and that node or leaf will be dirty.protected AbstractNode(AbstractNode<T> src)
Note: The copy constructor steals the state of the source node, creating a new node with the same state but a distinct (and not yet assigned) address on the backing store. If the source node has immutable data for some aspect of its state, then a mutable copy of that data is made.
Note: The caller MUST delete() the source node
after invoking this copy constructor. If the backing store supports the
operation, the source node will be reclaimed as free space at the next
commit.
The source node must be deleted since it is no longer accessible and various aspects of its state have been stolen by the copy constructor. If the btree is committed then both the delete of the source node and the new tree structure will be made restart-safe atomically and all is well. If the operation is aborted then both changes will be undone and all is well. In no case can we access the source node after this operation unless all changes have been aborted, in which case it will simply be re-read from the backing store.
src - The source node.| Method Detail |
|---|
protected abstract int minKeys()
Node, the minimum #of children is
minKeys + 1. For a Leaf, the minimum #of values
is minKeys.
protected abstract int maxKeys()
branchingFactor - 1 for a
Node and branchingFactor for a Leaf. For a
Node, the maximum #of children is maxKeys + 1. For a
Leaf, the maximum #of values is maxKeys.
public void delete()
IIdentityAccess
delete in interface IIdentityAccesspublic final Node getParent()
WeakReference to the parent has been cleared.protected AbstractNode<?> copyOnWrite()
Return this leaf iff it is dirty (aka mutable) and otherwise return a
copy of this leaf. If a copy is made of the leaf, then a copy will also
be made of each immutable parent up to the first mutable parent or the
root of the tree, which ever comes first. If the root is copied, then the
new root will be set on the BTree. This method must MUST be
invoked any time an mutative operation is requested for the leaf.
Note: You can not modify a node that has been written onto the store. Instead, you have to clone the node causing it and all nodes up to the root to be dirty and transient. This method handles that cloning process, but the caller MUST test whether or not the node was copied by this method, MUST delegate the mutation operation to the copy iff a copy was made, and MUST result in an awareness in the caller that the copy exists and needs to be used in place of the immutable version of the node.
protected AbstractNode<T> copyOnWrite(long triggeredByChildId)
Return this node or leaf iff it is dirty (aka mutable) and otherwise
return a copy of this node or leaf. If a copy is made of the node, then a
copy will also be made of each immutable parent up to the first mutable
parent or the root of the tree, which ever comes first. If the root is
copied, then the new root will be set on the BTree. This method
must MUST be invoked any time an mutative operation is requested for the
leaf.
Note: You can not modify a node that has been written onto the store. Instead, you have to clone the node causing it and all nodes up to the root to be dirty and transient. This method handles that cloning process, but the caller MUST test whether or not the node was copied by this method, MUST delegate the mutation operation to the copy iff a copy was made, and MUST be aware that the copy exists and needs to be used in place of the immutable version of the node.
triggeredByChildId - The persistent identity of child that triggered this event if
any.
public final Iterator<AbstractNode> postOrderNodeIterator()
IAbstractNode
postOrderNodeIterator in interface IAbstractNodeIAbstractNodes.public final Iterator<AbstractNode> postOrderNodeIterator(boolean dirtyNodesOnly)
dirtyNodesOnly - When true, only dirty nodes and leaves will be visited
AbstractNodes.
public abstract Iterator<AbstractNode> postOrderNodeIterator(boolean dirtyNodesOnly,
boolean nodesOnly)
dirtyNodesOnly - When true, only dirty nodes and leaves will be visitednodesOnly - When true, the leaves will not be visited.
AbstractNodes.public ITupleIterator entryIterator()
IAbstractNode
entryIterator in interface IAbstractNode
public ITupleIterator rangeIterator(byte[] fromKey,
byte[] toKey,
int flags)
fromKey - The first key that will be visited (inclusive). When
null there is no lower bound.toKey - The first key that will NOT be visited (exclusive). When
null there is no upper bound.flags - indicating whether the keys and/or values will be
materialized.
public abstract Iterator<AbstractNode> postOrderIterator(byte[] fromKey,
byte[] toKey)
fromKey - The first key that will be visited (inclusive). When
null there is no lower bound.toKey - The first key that will NOT be visited (exclusive). When
null there is no upper bound.
AbstractNodes.protected final void assertInvariants()
Invariants:
m is the branching factor and a node is understood
to be a non-leaf node in the tree.
In addition, all leaves are at the same level (not tested by this assertion).
protected final void assertKeysMonotonic()
protected static final String keyAsString(byte[] key)
Object.toString().
key - The key.
protected final void copyKey(int dstpos,
IRaba srckeys,
int srcpos)
Note: Whenever possible the key reference is copied rather than copying the data. This optimization is valid since we never modify the contents of a key.
dstpos - The index position to which the key will be copied on this
node.srckeys - The source keys.srcpos - The index position from which the key will be copied.public abstract boolean isLeaf()
IAbstractNodeData
isLeaf in interface IAbstractNodeDatapublic final int getBranchingFactor()
protected abstract IAbstractNode split()
Split a node or leaf that is over capacity (by one).
protected void join()
Join this node (must be deficient) with either its left or right sibling. A join will either cause a single key and value (child) to be redistributed from a sibling to this leaf (node) or it will cause a sibling leaf (node) to be merged into this leaf (node). Both situations also cause the separator key in the parent to be adjusted.
Join is invoked when a leaf has become deficient (too few keys/values). This method is never invoked for the root leaf therefore the parent of this leaf must be defined. Further, since the minimum #of children is two (2) for the smallest branching factor three (3), there is always a sibling to consider.
Join first considers the immediate siblings. if either is materialized and has more than the minimum #of values, then it redistributes one key and value (child) from the sibling into this leaf (node). If either sibling is materialized and has only the minimum #of values, then it merges this leaf (node) with that sibling.
If no materialized immediate sibling meets these criteria, then first materialize and test the right sibling. if the right sibling does not meet these criteria, then materialize and test the left sibling.
Note that (a) we prefer to merge a materialized sibling with this leaf to materializing a sibling; and (b) merging siblings is the only way that a separator key is removed from a parent. If the parent becomes deficient through merging then join is invoked on the parent as well. Note that join is never invoked on the root node (or leaf) since it by definition has no siblings.
Note that we must invoked copy-on-write before modifying a sibling. However, the parent of the leaf MUST already be mutable (aka dirty) since that is a precondition for removing a key from the leaf. This means that copy-on-write will not force the parent to be cloned.
protected boolean isLeftMostNode()
true if this node is the left-most node at its
level within the tree.
true iff the child is the left-most node at its
level within the tree.protected boolean isRightMostNode()
true if this node is the right-most node at its
level within the tree.
true iff the child is the right-most node at its
level within the tree.
protected abstract void redistributeKeys(AbstractNode sibling,
boolean isRightSibling)
sibling - The sibling.isRightSibling - True iff the sibling is the rightSibling of this node.
protected abstract void merge(AbstractNode sibling,
boolean isRightSibling)
sibling - The sibling.isRightSibling - True iff the sibling is the rightSibling of this node.
public abstract Tuple insert(byte[] key,
byte[] val,
boolean delete,
long timestamp,
Tuple tuple)
key - The key (non-null).val - The value (may be null).delete - true iff the entry is to marked as deleted
(delete markers must be supported for if this is true).timestamp - The timestamp associated with the version (the value is
ignored unless version metadata is being maintained).tuple - A tuple that may be used to obtain the data and metadata for
the pre-existing index entry overwritten by the insert
operation (optional).
null otherwise.
public abstract Tuple remove(byte[] searchKey,
Tuple tuple)
Note: It is an error to call this method if delete markers are in use.
searchKey - The search key.tuple - A tuple that may be used to obtain the data and metadata for
the pre-existing index entry that was either removed by the
remove operation (optional).
null otherwise.
public abstract Tuple lookup(byte[] searchKey,
Tuple tuple)
searchKey - The search key.tuple - A tuple that may be used to obtain the data and metadata for
the pre-existing index entry (required).
null otherwise.public abstract long indexOf(byte[] searchKey)
searchKey - The search key.
(-(insertion point) - 1). The insertion point is
defined as the point at which the key would be found it it were
inserted into the btree without intervening mutations. Note that
this guarantees that the return value will be >= 0 if and only if
the key is found.public abstract byte[] keyAt(long index)
index - The index position of the entry (origin zero and relative to
this node or leaf).
IndexOutOfBoundsException - if index is less than zero.
IndexOutOfBoundsException - if index is greater than the #of entries.
public abstract void valueAt(long index,
Tuple tuple)
index - The index position of the entry (origin zero and relative to
this node or leaf).tuple - A tuple that may be used to obtain the data and metadata for
the pre-existing index entry (required).
IndexOutOfBoundsException - if index is less than zero.
IndexOutOfBoundsException - if index is greater than the #of entries.public boolean dump(PrintStream out)
PrintStream (non-recursive).
out - Where to write the dump.
public boolean dump(org.apache.log4j.Level level,
PrintStream out)
PrintStream.
level - The logging level.out - Where to write the dump.
public abstract boolean dump(org.apache.log4j.Level level,
PrintStream out,
int height,
boolean recursive)
PrintStream.
level - The logging level.out - Where to write the dump.height - The height of this node in the tree or -1 iff you need to
invoke this method on a node or leaf whose height in the tree
is not known.recursive - When true, the node will be dumped recursively using a
pre-order traversal.
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||