@ -212,34 +212,38 @@ public class kelondroTree extends kelondroRecords implements Comparator {
if ( visitedNodeKeys . containsKey ( otherkey ) ) {
// we have loops in the database.
// to fix this, all affected nodes must be patched
thenode . setOHByte ( new byte [ ] { 1 , 0 } ) ;
thenode . setOHHandle ( new Handle [ ] { null , null , null } ) ;
thenode . setOHByte s ( new byte [ ] { 1 , 0 } ) ;
thenode . setOHHandle s ( new Handle [ ] { null , null , null } ) ;
Iterator fix = visitedNodeKeys . entrySet ( ) . iterator ( ) ;
Map . Entry entry ;
while ( fix . hasNext ( ) ) {
entry = ( Map . Entry ) fix . next ( ) ;
thenode = ( Node ) entry . getValue ( ) ;
thenode . setOHByte ( new byte [ ] { 1 , 0 } ) ;
thenode . setOHHandle ( new Handle [ ] { null , null , null } ) ;
thenode . setOHByte s ( new byte [ ] { 1 , 0 } ) ;
thenode . setOHHandle s ( new Handle [ ] { null , null , null } ) ;
}
thenode . commit ( CP_NONE ) ;
//printCache();
throw new kelondroException ( filename , "database contains loops; the loop-nodes have been auto-fixed" ) ;
}
//System.out.print ("Comparing key = '" + new String(key) + "' with '" + otherkey + "':"); // debug
//System.out.print ln ("Comparing key = '" + new String(key) + "' with '" + otherkey + "':"); // debug
c = compare ( key , thenode . getKey ( ) ) ;
//System.out.println(c); // debug
if ( c = = 0 ) {
found = true ;
//System.out.println("DEBUG: search for " + new String(key) + " ended with status=" + ((found) ? "found" : "not-found") + ", node=" + ((thenode == null) ? "NULL" : thenode.toString()) + ", parent=" + ((parentnode == null) ? "NULL" : parentnode.toString()));
return ;
} else if ( c < 0 ) {
child = - 1 ;
thisHandle = thenode . getOHHandle ( ) [ leftchild ] ;
thisHandle = thenode . getOHHandle s ( ) [ leftchild ] ;
} else {
child = 1 ;
thisHandle = thenode . getOHHandle ( ) [ rightchild ] ;
thisHandle = thenode . getOHHandle s ( ) [ rightchild ] ;
}
visitedNodeKeys . put ( otherkey , thenode ) ;
}
}
//System.out.println("DEBUG: search for " + new String(key) + " ended with status=" + ((found) ? "found" : "not-found") + ", node=" + ((thenode == null) ? "NULL" : thenode.toString()) + ", parent=" + ((parentnode == null) ? "NULL" : parentnode.toString()));
// we reached a node where we must insert the new value
// the parent of this new value can be obtained by getParent()
// all values are set, just return
@ -276,7 +280,7 @@ public class kelondroTree extends kelondroRecords implements Comparator {
public boolean isChild ( Node childn , Node parentn , int child ) throws IOException {
if ( childn = = null ) throw new IllegalArgumentException ( "isLeftChild: Node parameter is NULL" ) ;
Handle lc = parentn . getOHHandle ( ) [ child ] ;
Handle lc = parentn . getOHHandle s ( ) [ child ] ;
if ( lc = = null ) return false ;
return ( lc . equals ( childn . handle ( ) ) ) ;
}
@ -305,11 +309,12 @@ public class kelondroTree extends kelondroRecords implements Comparator {
public synchronized byte [ ] [ ] put ( byte [ ] [ ] newrow ) throws IOException {
if ( newrow . length ! = columns ( ) ) throw new IllegalArgumentException ( "put: wrong row length " + newrow . length + "; must be " + columns ( ) ) ;
// first try to find the key element in the database
Search searchResult = new Search ( newrow [ 0 ] ) ;
if ( searchResult . found ( ) ) {
Search searchResult = new Search ( newrow [ 0 ] ) ;
if ( searchResult . found ( ) ) {
// a node with this key exist. simply overwrite the content and return old content
Node e = searchResult . getMatcher ( ) ;
byte [ ] [ ] result = e . setValues ( newrow ) ;
e . commit ( CP_MEDIUM ) ;
searchResult = null ;
return result ;
} else if ( searchResult . isRoot ( ) ) {
@ -318,13 +323,14 @@ public class kelondroTree extends kelondroRecords implements Comparator {
if ( getHandle ( root ) ! = null )
throw new kelondroException ( filename , "tried to create root node twice" ) ;
// we dont have any Nodes in the file, so start here to create one
Node e = newNode ( newrow ) ;
e . save ( ) ;
Node e = newNode ( ) ;
e . setValues ( newrow ) ;
// write the propetries
e . setOHByte ( new byte [ ] { 1 , 0 } ) ; // {magic, balance}
e . setOHHandle ( new Handle [ ] { null , null , null } ) ; // {parent, leftchild, rightchild}
e . setOHByte s ( new byte [ ] { 1 , 0 } ) ; // {magic, balance}
e . setOHHandle s ( new Handle [ ] { null , null , null } ) ; // {parent, leftchild, rightchild}
// do updates
setHandle ( root , e . handle ( ) ) ;
e . commit ( CP_LOW ) ;
setHandle ( root , e . handle ( ) ) ;
searchResult = null ;
return null ;
} else {
@ -336,16 +342,16 @@ public class kelondroTree extends kelondroRecords implements Comparator {
// that side, but not if the assigned position is appropriate.
// create new node and assign values
Node theNode = newNode ( newrow ) ; theNode . save ( ) ;
Node parentNode = searchResult . getParent ( ) ;
Handle [ ] parentOHHandle ;
byte [ ] parentOHByte ;
theNode . setOHByte ( new byte [ ] { 1 , 0 } ) ; // fresh {magic, balance}
theNode . setOHHandle ( new Handle [ ] { parentNode . handle ( ) , null , null } ) ; // {parent, leftchild, rightchild}
Node parentNode = searchResult . getParent ( ) ;
Node theNode = newNode ( ) ;
theNode . setValues ( newrow ) ;
theNode . setOHBytes ( new byte [ ] { 1 , 0 } ) ; // fresh {magic, balance}
theNode . setOHHandles ( new Handle [ ] { parentNode . handle ( ) , null , null } ) ; // {parent, leftchild, rightchild}
theNode . commit ( CP_LOW ) ;
// check consistency and link new node to parent node
parentOHHandle = parentNode . getOHHandle ( ) ; // {parent, leftchild, rightchild}
byte [ ] parentOHByte ;
Handle [ ] parentOHHandle = parentNode . getOHHandles ( ) ; // {parent, leftchild, rightchild}
if ( searchResult . isLeft ( ) ) {
if ( parentOHHandle [ leftchild ] ! = null ) throw new kelondroException ( filename , "tried to create leftchild node twice" ) ;
parentOHHandle [ leftchild ] = theNode . handle ( ) ;
@ -355,8 +361,9 @@ public class kelondroTree extends kelondroRecords implements Comparator {
} else {
throw new kelondroException ( filename , "neither left nor right child" ) ;
}
parentNode . setOHHandle ( parentOHHandle ) ;
parentNode . setOHHandles ( parentOHHandle ) ;
parentNode . commit ( ( ( parentOHHandle [ leftchild ] = = null ) | | ( parentOHHandle [ rightchild ] = = null ) ) ? CP_MEDIUM : CP_HIGH ) ;
// now update recursively the node balance of the parentNode
// what do we have:
// - new Node, called 'theNode'
@ -369,8 +376,8 @@ public class kelondroTree extends kelondroRecords implements Comparator {
while ( increasedHight ) {
// update balance
parentOHByte = parentNode . getOHByte ( ) ; // {magic, balance}
parentOHHandle = parentNode . getOHHandle ( ) ; // {parent, leftchild, rightchild}
parentOHByte = parentNode . getOHByte s ( ) ; // {magic, balance}
parentOHHandle = parentNode . getOHHandle s ( ) ; // {parent, leftchild, rightchild}
prevHight = parentOHByte [ balance ] ;
if ( ( parentOHHandle [ leftchild ] ! = null ) & & ( parentOHHandle [ leftchild ] . equals ( theNode . handle ( ) ) ) ) {
//isLeftchild
@ -382,7 +389,8 @@ public class kelondroTree extends kelondroRecords implements Comparator {
path = "R" + path ;
}
increasedHight = ( ( java . lang . Math . abs ( ( int ) parentOHByte [ balance ] ) - java . lang . Math . abs ( ( int ) prevHight ) ) > 0 ) ;
parentNode . setOHByte ( parentOHByte ) ;
parentNode . setOHBytes ( parentOHByte ) ;
parentNode . commit ( ( ( parentOHHandle [ leftchild ] = = null ) | | ( parentOHHandle [ rightchild ] = = null ) ) ? CP_MEDIUM : CP_HIGH ) ;
// here we either stop because we had no increased hight,
// or we have a balance greater then 1 or less than -1 and we do rotation
@ -403,16 +411,16 @@ public class kelondroTree extends kelondroRecords implements Comparator {
}
if ( path . startsWith ( "RL" ) ) {
Handle parentHandle = parentNode . handle ( ) ;
LL_RightRotation ( theNode , getNode ( theNode . getOHHandle ( ) [ leftchild ] , theNode , leftchild ) ) ;
LL_RightRotation ( theNode , getNode ( theNode . getOHHandle s ( ) [ leftchild ] , theNode , leftchild ) ) ;
parentNode = getNode ( parentHandle , null , 0 ) ; // reload the parent node
RR_LeftRotation ( parentNode , getNode ( parentNode . getOHHandle ( ) [ rightchild ] , parentNode , rightchild ) ) ;
RR_LeftRotation ( parentNode , getNode ( parentNode . getOHHandle s ( ) [ rightchild ] , parentNode , rightchild ) ) ;
break ;
}
if ( path . startsWith ( "LR" ) ) {
Handle parentHandle = parentNode . handle ( ) ;
RR_LeftRotation ( theNode , getNode ( theNode . getOHHandle ( ) [ rightchild ] , theNode , rightchild ) ) ;
RR_LeftRotation ( theNode , getNode ( theNode . getOHHandle s ( ) [ rightchild ] , theNode , rightchild ) ) ;
parentNode = getNode ( parentHandle , null , 0 ) ; // reload the parent node
LL_RightRotation ( parentNode , getNode ( parentNode . getOHHandle ( ) [ leftchild ] , parentNode , leftchild ) ) ;
LL_RightRotation ( parentNode , getNode ( parentNode . getOHHandle s ( ) [ leftchild ] , parentNode , leftchild ) ) ;
break ;
}
break ;
@ -423,23 +431,26 @@ public class kelondroTree extends kelondroRecords implements Comparator {
break ;
} else {
theNode = parentNode ;
parentNode = getNode ( parentOHHandle [ parent ] /*previous handles*/ , null , 0 ) ;
parentNode = getNode ( parentOHHandle [ parent ] , null , 0 ) ;
}
}
}
return null ; // that means: no previous stored value present
}
}
private void assignChild ( Node parentNode , Node childNode , int childType ) throws IOException {
Handle [ ] parent Handle = parentNode . getOHHandle ( ) ;
Handle [ ] child Handle = childNode . getOHHandle ( ) ;
Handle [ ] parent OH Handle = parentNode . getOHHandle s ( ) ;
Handle [ ] child OH Handle = childNode . getOHHandle s ( ) ;
parent Handle[ childType ] = childNode . handle ( ) ;
child Handle[ parent ] = parentNode . handle ( ) ;
parent OH Handle[ childType ] = childNode . handle ( ) ;
child OH Handle[ parent ] = parentNode . handle ( ) ;
parentNode . setOHHandle ( parentHandle ) ;
childNode . setOHHandle ( childHandle ) ;
parentNode . setOHHandles ( parentOHHandle ) ;
parentNode . commit ( ( ( parentOHHandle [ leftchild ] = = null ) | | ( parentOHHandle [ rightchild ] = = null ) ) ? CP_MEDIUM : CP_HIGH ) ;
childNode . setOHHandles ( childOHHandle ) ;
childNode . commit ( ( ( childOHHandle [ leftchild ] = = null ) | | ( childOHHandle [ rightchild ] = = null ) ) ? CP_MEDIUM : CP_HIGH ) ;
}
private void replace ( Node oldNode , Node oldNodeParent , Node newNode ) throws IOException {
@ -447,18 +458,19 @@ public class kelondroTree extends kelondroRecords implements Comparator {
// the anchor's link to the oldNode by the newNode-link
// the new link gets the anchor as parent link assigned
// the oldNode will not be updated, so this must be done outside this routine
Handle [ ] oldHandle = oldNode . getOHHandle ( ) ; // {parent, leftchild, rightchild}
Handle [ ] oldHandle = oldNode . getOHHandle s ( ) ; // {parent, leftchild, rightchild}
// distinguish case where the oldNode is the root node
if ( oldNodeParent = = null ) {
// this is the root, update root
setHandle ( root , newNode . handle ( ) ) ;
// update new Node
Handle [ ] newHandle = newNode . getOHHandle ( ) ;
Handle [ ] newHandle = newNode . getOHHandle s ( ) ;
newHandle [ parent ] = null ;
newNode . setOHHandle ( newHandle ) ;
newNode . setOHHandles ( newHandle ) ;
newNode . commit ( CP_HIGH ) ;
} else {
// not the root, find parent
Handle [ ] parentHandle = oldNodeParent . getOHHandle ( ) ;
Handle [ ] parentHandle = oldNodeParent . getOHHandle s ( ) ;
// ok, we have the parent, but for updating the child link we must know
// if the oldNode was left or right child
if ( ( parentHandle [ leftchild ] ! = null ) & & ( parentHandle [ leftchild ] . equals ( oldNode . handle ( ) ) ) ) {
@ -469,11 +481,13 @@ public class kelondroTree extends kelondroRecords implements Comparator {
// update right node from parent
parentHandle [ rightchild ] = newNode . handle ( ) ;
}
oldNodeParent . setOHHandle ( parentHandle ) ;
oldNodeParent . setOHHandles ( parentHandle ) ;
oldNodeParent . commit ( ( ( parentHandle [ leftchild ] = = null ) | | ( parentHandle [ rightchild ] = = null ) ) ? CP_MEDIUM : CP_HIGH ) ;
// update new Node
Handle [ ] newHandle = newNode . getOHHandle ( ) ;
Handle [ ] newHandle = newNode . getOHHandle s ( ) ;
newHandle [ parent ] = oldNodeParent . handle ( ) ;
newNode . setOHHandle ( newHandle ) ;
newNode . setOHHandles ( newHandle ) ;
newNode . commit ( ( ( newHandle [ leftchild ] = = null ) | | ( newHandle [ rightchild ] = = null ) ) ? CP_MEDIUM : CP_HIGH ) ;
}
// finished. remember that we did not set the links to the oldNode
// we have also not set the children of the newNode.
@ -491,16 +505,16 @@ public class kelondroTree extends kelondroRecords implements Comparator {
private void LL_RightRotation ( Node parentNode , Node childNode ) throws IOException {
// replace the parent node; the parent is afterwards unlinked
Handle p2Handle = parentNode . getOHHandle ( ) [ parent ] ;
Handle p2Handle = parentNode . getOHHandle s ( ) [ parent ] ;
Node p2Node = ( p2Handle = = null ) ? null : getNode ( p2Handle , null , 0 ) ;
replace ( parentNode , p2Node , childNode ) ;
// set the left son of the parent to the right son of the childNode
Handle childOfChild = childNode . getOHHandle ( ) [ rightchild ] ;
Handle childOfChild = childNode . getOHHandle s ( ) [ rightchild ] ;
if ( childOfChild = = null ) {
Handle [ ] parentHandle = parentNode . getOHHandle ( ) ;
Handle [ ] parentHandle = parentNode . getOHHandle s ( ) ;
parentHandle [ leftchild ] = null ;
parentNode . setOHHandle ( parentHandle ) ;
parentNode . setOHHandle s ( parentHandle ) ;
} else {
assignChild ( parentNode , getNode ( childOfChild , childNode , rightchild ) , leftchild ) ;
}
@ -510,28 +524,30 @@ public class kelondroTree extends kelondroRecords implements Comparator {
// - newBal(parent) = oldBal(parent) - 1 - max(oldBal(leftChild), 0)
// - newBal(leftChild) = oldBal(leftChild) - 1 + min(newBal(parent), 0)
byte [ ] parentBytes = parentNode . getOHByte ( ) ;
byte [ ] childBytes = childNode . getOHByte ( ) ;
byte [ ] parentBytes = parentNode . getOHByte s ( ) ;
byte [ ] childBytes = childNode . getOHByte s ( ) ;
byte oldBalParent = parentBytes [ balance ] ;
byte oldBalChild = childBytes [ balance ] ;
parentBytes [ balance ] = ( byte ) ( oldBalParent - 1 - max0 ( oldBalChild ) ) ;
childBytes [ balance ] = ( byte ) ( oldBalChild - 1 + min0 ( parentBytes [ balance ] ) ) ;
parentNode . setOHByte ( parentBytes ) ;
childNode . setOHByte ( childBytes ) ;
parentNode . setOHBytes ( parentBytes ) ;
childNode . setOHBytes ( childBytes ) ;
parentNode . commit ( CP_NONE ) ;
childNode . commit ( CP_NONE ) ;
}
private void RR_LeftRotation ( Node parentNode , Node childNode ) throws IOException {
// replace the parent node; the parent is afterwards unlinked
Handle p2Handle = parentNode . getOHHandle ( ) [ parent ] ;
Handle p2Handle = parentNode . getOHHandle s ( ) [ parent ] ;
Node p2Node = ( p2Handle = = null ) ? null : getNode ( p2Handle , null , 0 ) ;
replace ( parentNode , p2Node , childNode ) ;
// set the left son of the parent to the right son of the childNode
Handle childOfChild = childNode . getOHHandle ( ) [ leftchild ] ;
Handle childOfChild = childNode . getOHHandle s ( ) [ leftchild ] ;
if ( childOfChild = = null ) {
Handle [ ] parentHandle = parentNode . getOHHandle ( ) ;
Handle [ ] parentHandle = parentNode . getOHHandle s ( ) ;
parentHandle [ rightchild ] = null ;
parentNode . setOHHandle ( parentHandle ) ;
parentNode . setOHHandle s ( parentHandle ) ;
} else {
assignChild ( parentNode , getNode ( childOfChild , childNode , leftchild ) , rightchild ) ;
}
@ -541,14 +557,16 @@ public class kelondroTree extends kelondroRecords implements Comparator {
// - newBal(parent) = oldBal(parent) + 1 - min(oldBal(rightChild), 0)
// - newBal(rightChild) = oldBal(rightChild) + 1 + max(newBal(parent), 0)
byte [ ] parentBytes = parentNode . getOHByte ( ) ;
byte [ ] childBytes = childNode . getOHByte ( ) ;
byte [ ] parentBytes = parentNode . getOHByte s ( ) ;
byte [ ] childBytes = childNode . getOHByte s ( ) ;
byte oldBalParent = parentBytes [ balance ] ;
byte oldBalChild = childBytes [ balance ] ;
parentBytes [ balance ] = ( byte ) ( oldBalParent + 1 - min0 ( oldBalChild ) ) ;
childBytes [ balance ] = ( byte ) ( oldBalChild + 1 + max0 ( parentBytes [ balance ] ) ) ;
parentNode . setOHByte ( parentBytes ) ;
childNode . setOHByte ( childBytes ) ;
parentNode . setOHBytes ( parentBytes ) ;
childNode . setOHBytes ( childBytes ) ;
parentNode . commit ( CP_NONE ) ;
childNode . commit ( CP_NONE ) ;
}
// Associates the specified value with the specified key in this map
@ -586,7 +604,7 @@ public class kelondroTree extends kelondroRecords implements Comparator {
// by the greatest node of the left child or the smallest
// node of the right child
Handle [ ] handles = node . getOHHandle ( ) ;
Handle [ ] handles = node . getOHHandle s ( ) ;
Node childnode ;
if ( ( handles [ leftchild ] = = null ) & & ( handles [ rightchild ] = = null ) ) {
// easy case: the node is a leaf
@ -594,10 +612,11 @@ public class kelondroTree extends kelondroRecords implements Comparator {
// this is the root!
setHandle ( root , null ) ;
} else {
Handle [ ] h = parentOfNode . getOHHandle ( ) ;
Handle [ ] h = parentOfNode . getOHHandle s ( ) ;
if ( ( h [ leftchild ] ! = null ) & & ( h [ leftchild ] . equals ( node . handle ( ) ) ) ) h [ leftchild ] = null ;
if ( ( h [ rightchild ] ! = null ) & & ( h [ rightchild ] . equals ( node . handle ( ) ) ) ) h [ rightchild ] = null ;
parentOfNode . setOHHandle ( h ) ;
parentOfNode . setOHHandles ( h ) ;
parentOfNode . commit ( ( ( h [ leftchild ] = = null ) & & ( h [ rightchild ] = = null ) ) ? CP_LOW : CP_MEDIUM ) ;
}
} else if ( ( handles [ leftchild ] ! = null ) & & ( handles [ rightchild ] = = null ) ) {
replace ( node , parentOfNode , getNode ( handles [ leftchild ] , node , leftchild ) ) ;
@ -610,17 +629,18 @@ public class kelondroTree extends kelondroRecords implements Comparator {
// we remove that replacement node and put it where the node was
// this seems to be recursive, but is not since the replacement
// node cannot have two children (it would not have been the smallest or greatest)
Handle [ ] replha = repl . getOHHandle ( ) ;
Handle [ ] replha = repl . getOHHandle s ( ) ;
Node n ;
Handle [ ] h ;
// remove leaf
if ( ( replha [ leftchild ] = = null ) & & ( replha [ rightchild ] = = null ) ) {
// the replacement cannot be the root, so simply remove from parent node
n = getNode ( replha [ parent ] , null , 0 ) ; // parent node of replacement node
h = n . getOHHandle ( ) ;
h = n . getOHHandle s ( ) ;
if ( ( h [ leftchild ] ! = null ) & & ( h [ leftchild ] . equals ( repl . handle ( ) ) ) ) h [ leftchild ] = null ;
if ( ( h [ rightchild ] ! = null ) & & ( h [ rightchild ] . equals ( repl . handle ( ) ) ) ) h [ rightchild ] = null ;
n . setOHHandle ( h ) ;
n . setOHHandles ( h ) ;
n . commit ( ( ( h [ leftchild ] = = null ) & & ( h [ rightchild ] = = null ) ) ? CP_LOW : CP_MEDIUM ) ;
} else if ( ( replha [ leftchild ] ! = null ) & & ( replha [ rightchild ] = = null ) ) {
try {
childnode = getNode ( replha [ leftchild ] , repl , leftchild ) ;
@ -628,10 +648,11 @@ public class kelondroTree extends kelondroRecords implements Comparator {
} catch ( IllegalArgumentException e ) {
// now treat the situation as if that link had been null before
n = getNode ( replha [ parent ] , null , 0 ) ; // parent node of replacement node
h = n . getOHHandle ( ) ;
h = n . getOHHandle s ( ) ;
if ( ( h [ leftchild ] ! = null ) & & ( h [ leftchild ] . equals ( repl . handle ( ) ) ) ) h [ leftchild ] = null ;
if ( ( h [ rightchild ] ! = null ) & & ( h [ rightchild ] . equals ( repl . handle ( ) ) ) ) h [ rightchild ] = null ;
n . setOHHandle ( h ) ;
n . setOHHandles ( h ) ;
n . commit ( ( ( h [ leftchild ] = = null ) & & ( h [ rightchild ] = = null ) ) ? CP_LOW : CP_MEDIUM ) ;
}
} else if ( ( replha [ leftchild ] = = null ) & & ( replha [ rightchild ] ! = null ) ) {
try {
@ -640,10 +661,11 @@ public class kelondroTree extends kelondroRecords implements Comparator {
} catch ( IllegalArgumentException e ) {
// now treat the situation as if that link had been null before
n = getNode ( replha [ parent ] , null , 0 ) ; // parent node of replacement node
h = n . getOHHandle ( ) ;
h = n . getOHHandle s ( ) ;
if ( ( h [ leftchild ] ! = null ) & & ( h [ leftchild ] . equals ( repl . handle ( ) ) ) ) h [ leftchild ] = null ;
if ( ( h [ rightchild ] ! = null ) & & ( h [ rightchild ] . equals ( repl . handle ( ) ) ) ) h [ rightchild ] = null ;
n . setOHHandle ( h ) ;
n . setOHHandles ( h ) ;
n . commit ( ( ( h [ leftchild ] = = null ) & & ( h [ rightchild ] = = null ) ) ? CP_LOW : CP_MEDIUM ) ;
}
}
//System.out.println("node before reload is " + node.toString());
@ -651,25 +673,29 @@ public class kelondroTree extends kelondroRecords implements Comparator {
//System.out.println("node after reload is " + node.toString());
// now plant in the replha node
byte [ ] b = node . getOHByte ( ) ; // save bytes of disappearing node
handles = node . getOHHandle ( ) ; // save handles of disappearing node
byte [ ] b = node . getOHByte s ( ) ; // save bytes of disappearing node
handles = node . getOHHandle s ( ) ; // save handles of disappearing node
replace ( node , parentOfNode , repl ) ;
repl . setOHByte ( b ) ; // restore bytes
repl . setOHHandle ( handles ) ; // restore handles
repl . setOHBytes ( b ) ; // restore bytes
repl . setOHHandles ( handles ) ; // restore handles
repl . commit ( ( ( handles [ leftchild ] = = null ) | | ( handles [ rightchild ] = = null ) ) ? CP_MEDIUM : CP_HIGH ) ;
// last thing to do: change uplinks of children to this new node
if ( handles [ leftchild ] ! = null ) {
n = getNode ( handles [ leftchild ] , node , leftchild ) ;
h = n . getOHHandle ( ) ;
h = n . getOHHandle s ( ) ;
h [ parent ] = repl . handle ( ) ;
n . setOHHandle ( h ) ;
n . setOHHandles ( h ) ;
n . commit ( ( ( h [ leftchild ] = = null ) | | ( h [ rightchild ] = = null ) ) ? CP_MEDIUM : CP_HIGH ) ;
}
if ( handles [ rightchild ] ! = null ) {
n = getNode ( handles [ rightchild ] , node , rightchild ) ;
h = n . getOHHandle ( ) ;
h = n . getOHHandle s ( ) ;
h [ parent ] = repl . handle ( ) ;
n . setOHHandle ( h ) ;
n . setOHHandles ( h ) ;
n . commit ( ( ( h [ leftchild ] = = null ) | | ( h [ rightchild ] = = null ) ) ? CP_MEDIUM : CP_HIGH ) ;
}
}
// move node to recycling queue
deleteNode ( node . handle ( ) ) ;
}
@ -681,7 +707,7 @@ public class kelondroTree extends kelondroRecords implements Comparator {
private Node firstNode ( Node node ) throws IOException {
if ( node = = null ) throw new IllegalArgumentException ( "firstNode: node=null" ) ;
Handle h = node . getOHHandle ( ) [ leftchild ] ;
Handle h = node . getOHHandle s ( ) [ leftchild ] ;
while ( h ! = null ) {
try {
node = getNode ( h , node , leftchild ) ;
@ -689,7 +715,7 @@ public class kelondroTree extends kelondroRecords implements Comparator {
// return what we have
return node ;
}
h = node . getOHHandle ( ) [ leftchild ] ;
h = node . getOHHandle s ( ) [ leftchild ] ;
}
return node ;
}
@ -702,7 +728,7 @@ public class kelondroTree extends kelondroRecords implements Comparator {
private Node lastNode ( Node node ) throws IOException {
if ( node = = null ) throw new IllegalArgumentException ( "lastNode: node=null" ) ;
Handle h = node . getOHHandle ( ) [ rightchild ] ;
Handle h = node . getOHHandle s ( ) [ rightchild ] ;
while ( h ! = null ) {
try {
node = getNode ( h , node , rightchild ) ;
@ -710,7 +736,7 @@ public class kelondroTree extends kelondroRecords implements Comparator {
// return what we have
return node ;
}
h = node . getOHHandle ( ) [ rightchild ] ;
h = node . getOHHandle s ( ) [ rightchild ] ;
}
return node ;
}
@ -823,7 +849,7 @@ public class kelondroTree extends kelondroRecords implements Comparator {
nodeStack . addLast ( new Object [ ] { searchNode , new Integer ( ct ) } ) ;
// go to next node
searchHandle = searchNode . getOHHandle ( ) [ ct ] ;
searchHandle = searchNode . getOHHandle s ( ) [ ct ] ;
if ( searchHandle = = null ) throw new kelondroException ( filename , "start node does not exist (handle null)" ) ;
searchNode = getNode ( searchHandle , searchNode , ct ) ;
if ( searchNode = = null ) throw new kelondroException ( filename , "start node does not exist (node null)" ) ;
@ -850,14 +876,14 @@ public class kelondroTree extends kelondroRecords implements Comparator {
try {
int childtype = ( up ) ? rightchild : leftchild ;
Handle childHandle = nextNode . getOHHandle ( ) [ childtype ] ;
Handle childHandle = nextNode . getOHHandle s ( ) [ childtype ] ;
if ( childHandle ! = null ) {
//System.out.println("go to other leg, stack size=" + nodeStack.size());
// we have walked one leg of the tree; now go to the other one: step down to next child
nodeStack . addLast ( new Object [ ] { nextNode , new Integer ( childtype ) } ) ;
nextNode = getNode ( childHandle , nextNode , childtype ) ;
childtype = ( up ) ? leftchild : rightchild ;
while ( ( childHandle = nextNode . getOHHandle ( ) [ childtype ] ) ! = null ) {
while ( ( childHandle = nextNode . getOHHandle s ( ) [ childtype ] ) ! = null ) {
try {
nodeStack . addLast ( new Object [ ] { nextNode , new Integer ( childtype ) } ) ;
nextNode = getNode ( childHandle , nextNode , childtype ) ;
@ -1056,7 +1082,7 @@ public class kelondroTree extends kelondroRecords implements Comparator {
private int height ( Node node ) throws IOException {
if ( node = = null ) return 0 ;
Handle [ ] childs = node . getOHHandle ( ) ;
Handle [ ] childs = node . getOHHandle s ( ) ;
int hl = ( childs [ leftchild ] = = null ) ? 0 : height ( getNode ( childs [ leftchild ] , node , leftchild ) ) ;
int hr = ( childs [ rightchild ] = = null ) ? 0 : height ( getNode ( childs [ rightchild ] , node , rightchild ) ) ;
if ( hl > hr ) return hl + 1 ; else return hr + 1 ;
@ -1098,7 +1124,7 @@ public class kelondroTree extends kelondroRecords implements Comparator {
nextline . add ( null ) ;
nextline . add ( null ) ;
} else {
childs = node . getOHHandle ( ) ;
childs = node . getOHHandle s ( ) ;
nextline . add ( childs [ leftchild ] ) ;
nextline . add ( childs [ rightchild ] ) ;
}
@ -1317,9 +1343,9 @@ public class kelondroTree extends kelondroRecords implements Comparator {
}
public static void main ( String [ ] args ) {
cmd ( args ) ;
//cmd(args);
//bigtest(Integer.parseInt(args[0]));
//randomtest(Integer.parseInt(args[0]));
randomtest ( Integer . parseInt ( args [ 0 ] ) ) ;
//smalltest();
}
@ -1348,17 +1374,6 @@ public class kelondroTree extends kelondroRecords implements Comparator {
return new byte [ ] { ( byte ) c , 32 , 32 , 32 } ;
}
public static kelondroTree testTree ( File f , String testentities ) throws IOException {
if ( f . exists ( ) ) f . delete ( ) ;
kelondroTree tt = new kelondroTree ( f , 0 , 4 , 4 ) ;
byte [ ] b ;
for ( int i = 0 ; i < testentities . length ( ) ; i + + ) {
b = testWord ( testentities . charAt ( i ) ) ;
tt . put ( b , b ) ;
}
return tt ;
}
public static void randomtest ( int elements ) {
System . out . println ( "random " + elements + ":" ) ;
String s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" . substring ( 0 , elements ) ;
@ -1371,7 +1386,7 @@ public class kelondroTree extends kelondroRecords implements Comparator {
int steps = 0 ;
while ( true ) {
if ( testFile . exists ( ) ) testFile . delete ( ) ;
tt = new kelondroTree ( testFile , 2000 0, 4 , 4 ) ;
tt = new kelondroTree ( testFile , 0, 4 , 4 ) ;
steps = 10 + ( ( int ) System . currentTimeMillis ( ) % 7 ) * ( ( ( int ) System . currentTimeMillis ( ) + 17 ) % 11 ) ;
t = s ;
d = "" ;
@ -1394,31 +1409,35 @@ public class kelondroTree extends kelondroRecords implements Comparator {
t = t + c ;
System . out . println ( "removed " + new String ( b ) ) ;
}
//tt.printCache();
//tt.print();
if ( countElements ( tt ) ! = tt . size ( ) ) {
System . out . println ( "wrong size for ") ;
System . out . println ( "wrong size for this table: ") ;
tt . print ( ) ;
}
// check all words within
for ( int j = 0 ; j < d . length ( ) ; j + + ) {
if ( tt . get ( testWord ( d . charAt ( j ) ) ) = = null ) {
System . out . println ( "missing entry " + d . charAt ( j ) ) ;
System . out . println ( "missing entry " + d . charAt ( j ) + " in this table:" ) ;
tt . print ( ) ;
}
}
// check all words outside
for ( int j = 0 ; j < t . length ( ) ; j + + ) {
if ( tt . get ( testWord ( t . charAt ( j ) ) ) ! = null ) {
System . out . println ( "superfluous entry " + t . charAt ( j ) ) ;
System . out . println ( "superfluous entry " + t . charAt ( j ) + " in this table:" ) ;
tt . print ( ) ;
}
}
if ( tt . get ( testWord ( 'z' ) ) ! = null ) {
System . out . println ( "superfluous entry z ") ;
System . out . println ( "superfluous entry z in this table: ") ;
tt . print ( ) ;
}
}
tt . print ( ) ;
//tt.print();
tt . close ( ) ;
}
@ -1433,27 +1452,44 @@ public class kelondroTree extends kelondroRecords implements Comparator {
File f = new File ( "test.db" ) ;
if ( f . exists ( ) ) f . delete ( ) ;
try {
kelondroTree tt = new kelondroTree ( f , 100 0, 4 , 4 ) ;
kelondroTree tt = new kelondroTree ( f , 0, 4 , 4 ) ;
byte [ ] b ;
b = testWord ( 'b' ) ; tt . put ( b , b ) ;
b = testWord ( 'c' ) ; tt . put ( b , b ) ;
b = testWord ( 'a' ) ; tt . put ( b , b ) ;
b = testWord ( 'B' ) ; tt . put ( b , b ) ; tt . print ( ) ;
b = testWord ( 'C' ) ; tt . put ( b , b ) ; tt . print ( ) ;
b = testWord ( 'D' ) ; tt . put ( b , b ) ; tt . print ( ) ;
b = testWord ( 'A' ) ; tt . put ( b , b ) ; tt . print ( ) ;
b = testWord ( 'D' ) ; tt . remove ( b ) ; tt . print ( ) ;
b = testWord ( 'B' ) ; tt . remove ( b ) ; tt . print ( ) ;
b = testWord ( 'B' ) ;
tt . put ( b , b ) ; tt . print ( ) ;
System . out . println ( "elements: " + countElements ( tt ) ) ;
tt . print ( ) ;
Sys tem. ou t. print ln ( "TERMINATED" ) ;
} catch ( IOException e ) {
e . printStackTrace ( ) ;
}
}
public static void bigtest ( int elements ) {
System . out . println ( "perm " + elements + ":" ) ;
public static kelondroTree testTree ( File f , String testentities ) throws IOException {
if ( f . exists ( ) ) f . delete ( ) ;
kelondroTree tt = new kelondroTree ( f , 200000 , 4 , 4 ) ;
byte [ ] b ;
for ( int i = 0 ; i < testentities . length ( ) ; i + + ) {
b = testWord ( testentities . charAt ( i ) ) ;
tt . put ( b , b ) ;
}
return tt ;
}
public static void bigtest ( int elements ) {
System . out . println ( "starting big test with " + elements + " elements:" ) ;
long start = System . currentTimeMillis ( ) ;
String [ ] s = permutations ( elements ) ;
kelondroTree tt ;
File testFile = new File ( "test.db" ) ;
byte [ ] b ;
try {
for ( int i = 0 ; i < s . length ; i + + ) {
System . out . println ( "probing tree " + i + " for permutation " + s [ i ] ) ;
System . out . println ( " *** probing tree " + i + " for permutation " + s [ i ] ) ;
// generate tree and delete elements
tt = testTree ( testFile , s [ i ] ) ;
//tt.print();
@ -1491,17 +1527,23 @@ public class kelondroTree extends kelondroRecords implements Comparator {
tt . close ( ) ;
}
}
System . out . println ( "FINISHED ") ;
System . out . println ( "FINISHED test after " + ( ( System . currentTimeMillis ( ) - start ) / 1000 ) + " seconds. ") ;
} catch ( Exception e ) {
e . printStackTrace ( ) ;
System . out . println ( "TERMINATED" ) ;
}
}
public static int countElements ( kelondroTree t ) {
public static int countElements ( kelondroTree t ) throws IOException {
int count = 0 ;
Iterator iter = t . nodeIterator ( true , false ) ;
while ( iter . hasNext ( ) ) { count + + ; if ( iter . next ( ) = = null ) System . out . println ( "ERROR! null element found" ) ; }
Node n ;
while ( iter . hasNext ( ) ) {
count + + ;
n = ( Node ) iter . next ( ) ;
if ( n = = null ) System . out . println ( "ERROR! null element found" ) ;
//else System.out.println("counted element: " + new String(n.getKey()));
}
return count ;
}
}