You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ch...@apache.org on 2010/06/22 01:56:36 UTC
svn commit: r956741 -
/activemq/trunk/kahadb/src/main/java/org/apache/kahadb/index/BTreeNode.java
Author: chirino
Date: Mon Jun 21 23:56:35 2010
New Revision: 956741
URL: http://svn.apache.org/viewvc?rev=956741&view=rev
Log:
Fix for AMQ-2757 - leaf nodes were not properly getting linked together in some cases.
Modified:
activemq/trunk/kahadb/src/main/java/org/apache/kahadb/index/BTreeNode.java
Modified: activemq/trunk/kahadb/src/main/java/org/apache/kahadb/index/BTreeNode.java
URL: http://svn.apache.org/viewvc/activemq/trunk/kahadb/src/main/java/org/apache/kahadb/index/BTreeNode.java?rev=956741&r1=956740&r2=956741&view=diff
==============================================================================
--- activemq/trunk/kahadb/src/main/java/org/apache/kahadb/index/BTreeNode.java (original)
+++ activemq/trunk/kahadb/src/main/java/org/apache/kahadb/index/BTreeNode.java Mon Jun 21 23:56:35 2010
@@ -101,6 +101,7 @@ public final class BTreeNode<Key,Value>
// we need to roll to the next leaf..
if( current.next >= 0 ) {
current = index.loadNode(tx, current.next, null);
+ assert !current.isBranch() : "Should have linked to the next leaf node.";
nextIndex=0;
} else {
break;
@@ -227,7 +228,53 @@ public final class BTreeNode<Key,Value>
return null;
}
}
-
+
+
+ /**
+ * 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, 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;
+ }
+
+ /**
+ * Returns the left most leaf from the current btree graph.
+ * @throws IOException
+ */
+ private BTreeNode<Key,Value> getLeftPeer(Transaction tx, BTreeNode<Key,Value> x) throws IOException {
+ BTreeNode<Key,Value> cur = x;
+ while( cur.parent !=null ) {
+ if( cur.parent.children[0] == cur.getPageId() ) {
+ cur = cur.parent;
+ } else {
+ for( int i=0; i < cur.parent.children.length; i ++) {
+ if( cur.parent.children[i]==cur.getPageId() ) {
+ return cur.parent.getChild(tx, i-1);
+ }
+ }
+ throw new AssertionError("page "+x+" was decendent of "+cur.getPageId());
+ }
+ }
+ return null;
+ }
+
public Value remove(Transaction tx, Key key) throws IOException {
if(isBranch()) {
@@ -249,14 +296,26 @@ public final class BTreeNode<Key,Value>
} else {
// The child was a leaf. Then we need to actually remove it from this branch node..
+ // and relink the previous leaf to skip to the next leaf.
- // We need to update the previous child's next pointer to skip over the child being removed....
- if( idx > 0 && children.length > 1) {
- BTreeNode<Key, Value> previousChild = getChild(tx, idx-1);
- previousChild.next = child.next;
- index.storeNode(tx, previousChild, true);
+ BTreeNode<Key, Value> previousLeaf = null;
+ if( idx > 0 ) {
+ // easy if we this node hold the previous child.
+ previousLeaf = getChild(tx, idx-1).getRightLeaf(tx);
+ } else {
+ // less easy if we need to go to the parent to find the previous child.
+ BTreeNode<Key, Value> lp = getLeftPeer(tx, this);
+ if( lp!=null ) {
+ previousLeaf = lp.getRightLeaf(tx);
+ }
+ // lp will be null if there was no previous child.
}
-
+
+ if( previousLeaf !=null ) {
+ previousLeaf.next = child.next;
+ index.storeNode(tx, previousLeaf, true);
+ }
+
if( idx < children.length-1 ) {
// Delete it and key to the right.
setBranchData(arrayDelete(keys, idx), arrayDelete(children, idx));