@Override public String toString() { return "[BTreeNode "+(isBranch()?"branch":"leaf")+": "+Arrays.asList(keys)+"]"; }
/** * Returns the right most leaf from the current btree graph. * @throws IOException */ private BTreeNode<Key,Value> getRightLeaf(Transaction tx) throws IOException { BTreeNode<Key,Value> cur = this; while(cur.isBranch()) { cur = cur.getChild(tx, cur.keys.length); } return cur; }
/** * Returns the left most leaf from the current btree graph. * @throws IOException */ private BTreeNode<Key,Value> getLeftLeaf(Transaction tx) throws IOException { BTreeNode<Key,Value> cur = this; while(cur.isBranch()) { cur = cur.getChild(tx, 0); } return cur; }
public BTreeNode<Key,Value> getFirstLeafNode(Transaction tx) throws IOException { BTreeNode<Key, Value> node = this; while( node .isBranch() ) { node = node.getChild(tx, 0); } return node; }
/** * Internal (to the BTreeNode) method. Because this method is called only by * BTreeNode itself, no synchronization done inside of this method. * @throws IOException */ private BTreeNode<Key,Value> getChild(Transaction tx, int idx) throws IOException { if (isBranch() && idx >= 0 && idx < children.length) { BTreeNode<Key, Value> result = this.index.loadNode(tx, children[idx], this); return result; } else { return null; } }
private static <Key,Value> BTreeNode<Key, Value> getLeafNode(Transaction tx, final BTreeNode<Key, Value> node, Key key) throws IOException { BTreeNode<Key, Value> current = node; while( true ) { if( current.isBranch() ) { int idx = Arrays.binarySearch(current.keys, key); idx = idx < 0 ? -(idx + 1) : idx + 1; BTreeNode<Key, Value> child = current.getChild(tx, idx); // A little cycle detection for sanity's sake if( child == node ) { throw new IOException("BTree corrupted: Cylce detected."); } current = child; } else { break; } } return current; }
public int getMinLeafDepth(Transaction tx, int depth) throws IOException { depth++; if( isBranch() ) { int min = Integer.MAX_VALUE; for(int i=0 ; i < children.length; i++) { min = Math.min(min, getChild(tx, i).getMinLeafDepth(tx, depth)); } return min; } else { // print(depth*2, "- "+page.getPageId()); return depth; } }
public Value get(Transaction tx, Key key) throws IOException { if (key == null) { throw new IllegalArgumentException("Key cannot be null"); } if( isBranch() ) { return getLeafNode(tx, this, key).get(tx, key); } else { int idx = Arrays.binarySearch(keys, key); if (idx < 0) { return null; } else { return values[idx]; } } }
public boolean contains(Transaction tx, Key key) throws IOException { if (key == null) { throw new IllegalArgumentException("Key cannot be null"); } if( isBranch() ) { return getLeafNode(tx, this, key).contains(tx, key); } else { int idx = Arrays.binarySearch(keys, key); if (idx < 0) { return false; } else { return true; } } }
public int getMaxLeafDepth(Transaction tx, int depth) throws IOException { depth++; if( isBranch() ) { int v = 0; for(int i=0 ; i < children.length; i++) { v = Math.max(v, getChild(tx, i).getMaxLeafDepth(tx, depth)); } depth = v; } return depth; }
public Map.Entry<Key,Value> getFirst(Transaction tx) throws IOException { BTreeNode<Key, Value> node = this; while( node .isBranch() ) { node = node.getChild(tx, 0); } if( node.values.length>0 ) { return new KeyValueEntry(node.keys[0], node.values[0]); } else { return null; } }
public Map.Entry<Key,Value> getLast(Transaction tx) throws IOException { BTreeNode<Key, Value> node = this; while( node.isBranch() ) { node = node.getChild(tx, node.children.length-1); } if( node.values.length>0 ) { int idx = node.values.length-1; return new KeyValueEntry(node.keys[idx], node.values[idx]); } else { return null; } }
public void printStructure(Transaction tx, PrintWriter out, String prefix) throws IOException { if( prefix.length()>0 && parent == null ) { throw new IllegalStateException("Cycle back to root node detected."); } if (parent == null) { prefix += "|"; out.println(prefix + getPageId()); } if( isBranch() ) { for(int i=0 ; i < children.length; i++) { BTreeNode<Key, Value> child = getChild(tx, i); if( i == children.length-1) { out.println(prefix+"\\- "+child.getPageId()+(child.isBranch()?" ("+child.children.length+")":"")); child.printStructure(tx, out, prefix+" "); } else { out.println(prefix+"|- "+child.getPageId()+(child.isBranch()?" ("+child.children.length+")":"")+" : "+keys[i]); child.printStructure(tx, out, prefix+" "); } } } }
public Iterator<Map.Entry<Key,Value>> iterator(final Transaction tx, Key startKey, Key endKey) throws IOException { if (startKey == null) { return iterator(tx); } if( isBranch() ) { return getLeafNode(tx, this, startKey).iterator(tx, startKey, endKey); } else { int idx = Arrays.binarySearch(keys, startKey); if (idx < 0) { idx = -(idx + 1); } return new BTreeIterator(tx, this, idx, endKey); } }
public void visit(Transaction tx, BTreeVisitor<Key, Value> visitor) throws IOException { if (visitor == null) { throw new IllegalArgumentException("Visitor cannot be null"); } if( isBranch() ) { for(int i=0; i < this.children.length; i++) { Key key1 = null; if( i!=0 ) { key1 = keys[i-1]; } Key key2 = null; if( i!=this.children.length-1 ) { key2 = keys[i]; } if( visitor.isInterestedInKeysBetween(key1, key2) ) { BTreeNode<Key, Value> child = getChild(tx, i); child.visit(tx, visitor); } } } else { visitor.visit(Arrays.asList(keys), Arrays.asList(values)); } }
if( isBranch() ) { return getLeafNode(tx, this, key).put(tx, key, value); } else {
public void clear(Transaction tx) throws IOException { if( isBranch() ) { for (int i = 0; i < children.length; i++) { BTreeNode<Key, Value> node = index.loadNode(tx, children[i], this); node.clear(tx); tx.free(node.getPage()); } } // Reset the root node to be a leaf. if( parent == null ) { setLeafData(createKeyArray(0), createValueArray(0)); next=-1; index.storeNode(tx, this, true); } }
if( isBranch() ) { BTreeNode<Key,Value> lNode = this.index.createNode(tx, this); if( isBranch() ) { rNode.setBranchData(rightKeys, rightChildren); lNode.setBranchData(leftKeys, leftChildren); BTreeNode<Key,Value> rNode = this.index.createNode(tx, parent); if( isBranch() ) { setBranchData(leftKeys, leftChildren); rNode.setBranchData(rightKeys, rightChildren);
public Map.Entry<Key,Value> getLast(Transaction tx) throws IOException { BTreeNode<Key, Value> node = this; while( node.isBranch() ) { node = node.getChild(tx, node.children.length-1); } if( node.values.length>0 ) { int idx = node.values.length-1; return new KeyValueEntry(node.keys[idx], node.values[idx]); } else { return null; } }