de-serialized read and write access

git-svn-id: https://svn.berlios.de/svnroot/repos/yacy/trunk@989 6c8d7289-2bf4-0310-a012-ef5d649a1542
pull/1/head
orbiter 20 years ago
parent 09a0e898e0
commit 4fa942511b

@ -76,6 +76,8 @@ public class kelondroTree extends kelondroRecords implements Comparator, kelondr
private static int root = 0; // pointer for FHandles-array: pointer to root node private static int root = 0; // pointer for FHandles-array: pointer to root node
private Search writeSearchObj = new Search();
public kelondroTree(File file, long buffersize, int key, int value) throws IOException { public kelondroTree(File file, long buffersize, int key, int value) throws IOException {
this(file, buffersize, new int[] {key, value}, 1, 8); this(file, buffersize, new int[] {key, value}, 1, 8);
} }
@ -134,17 +136,16 @@ public class kelondroTree extends kelondroRecords implements Comparator, kelondr
} }
// Returns the value to which this map maps the specified key. // Returns the value to which this map maps the specified key.
public synchronized byte[][] get(byte[] key) throws IOException { public byte[][] get(byte[] key) throws IOException {
//System.out.println("kelondroTree.get " + new String(key) + " in " + filename); //System.out.println("kelondroTree.get " + new String(key) + " in " + filename);
Search search = new Search(key); Search search = new Search();
if (search.found()) { search.process(key);
if (search.found()) {
byte[][] result = search.getMatcher().getValues(); byte[][] result = search.getMatcher().getValues();
search = null; return result;
return result; } else {
} else { return null;
search = null; }
return null;
}
} }
public long[] getLong(byte[] key) throws IOException { public long[] getLong(byte[] key) throws IOException {
@ -174,21 +175,16 @@ public class kelondroTree extends kelondroRecords implements Comparator, kelondr
private Node thenode, parentnode; private Node thenode, parentnode;
private boolean found; // property if node was found private boolean found; // property if node was found
private byte child; // -1: left child; 0: root node; 1: right child private byte child; // -1: left child; 0: root node; 1: right child
private Handle thisHandle;
protected Search(byte[] key) throws IOException {
this.key = key; protected Search() {
searchproc();
}
protected Search(Node node) throws IOException {
this.key = node.getKey();
searchproc();
} }
private void searchproc() throws IOException { protected void process(byte[] key) throws IOException {
// searchs the database for the key and stores the result in the thisHandle // searchs the database for the key and stores the result in the thisHandle
// if the key was found, then found=true, thisHandle and leftchild is set; // if the key was found, then found=true, thisHandle and leftchild is set;
// else found=false and thisHandle and leftchild is undefined // else found=false and thisHandle and leftchild is undefined
Handle thisHandle = getHandle(root); thisHandle = getHandle(root);
parentnode = null; parentnode = null;
if (key == null) { if (key == null) {
child = 0; child = 0;
@ -204,7 +200,6 @@ public class kelondroTree extends kelondroRecords implements Comparator, kelondr
child = 0; child = 0;
found = false; found = false;
int c; int c;
Handle[] handles;
HashMap visitedNodeKeys = new HashMap(); // to detect loops HashMap visitedNodeKeys = new HashMap(); // to detect loops
String otherkey; String otherkey;
//System.out.println("Starting Compare Loop in Database " + filename); // debug //System.out.println("Starting Compare Loop in Database " + filename); // debug
@ -328,145 +323,145 @@ public class kelondroTree extends kelondroRecords implements Comparator, kelondr
} }
// Associates the specified value with the specified key in this map // Associates the specified value with the specified key in this map
public synchronized byte[][] put(byte[][] newrow) throws IOException { public byte[][] put(byte[][] newrow) throws IOException {
if (newrow.length != columns()) throw new IllegalArgumentException("put: wrong row length " + newrow.length + "; must be " + columns()); 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 // first try to find the key element in the database
Search searchResult = new Search(newrow[0]); synchronized(writeSearchObj) {
if (searchResult.found()) { writeSearchObj.process(newrow[0]);
// a node with this key exist. simply overwrite the content and return old content if (writeSearchObj.found()) {
Node e = searchResult.getMatcher(); // a node with this key exist. simply overwrite the content and return old content
byte[][] result = e.setValues(newrow); Node e = writeSearchObj.getMatcher();
commitNode(e); byte[][] result = e.setValues(newrow);
searchResult = null; commitNode(e);
return result; return result;
} else if (searchResult.isRoot()) { } else if (writeSearchObj.isRoot()) {
// a node with this key does not exist and there is no node at all // a node with this key does not exist and there is no node at all
// this therefore creates the root node if an only if there was no root Node yet // this therefore creates the root node if an only if there was no root Node yet
if (getHandle(root) != null) if (getHandle(root) != null)
throw new kelondroException(filename, "tried to create root node twice"); throw new kelondroException(filename, "tried to create root node twice");
// we dont have any Nodes in the file, so start here to create one // we dont have any Nodes in the file, so start here to create one
Node e = newNode(); Node e = newNode();
e.setValues(newrow); e.setValues(newrow);
// write the propetries // write the propetries
e.setOHByte(magic, (byte) 1); e.setOHByte(magic, (byte) 1);
e.setOHByte(balance, (byte) 0); e.setOHByte(balance, (byte) 0);
e.setOHHandle(parent, null); e.setOHHandle(parent, null);
e.setOHHandle(leftchild, null); e.setOHHandle(leftchild, null);
e.setOHHandle(rightchild, null); e.setOHHandle(rightchild, null);
// do updates // do updates
e.commit(CP_LOW); e.commit(CP_LOW);
setHandle(root, e.handle()); setHandle(root, e.handle());
searchResult = null; return null;
return null; } else {
} else { // a node with this key does not exist
// a node with this key does not exist // this creates a new node if there is already at least a root node
// this creates a new node if there is already at least a root node // to create the new node, it is necessary to assign it to a parent
// to create the new node, it is necessary to assign it to a parent // it must also be defined weather this new node is a left child of the
// it must also be defined weather this new node is a left child of the // parent or not. It is checked if the parent node already has a child on
// parent or not. It is checked if the parent node already has a child on // that side, but not if the assigned position is appropriate.
// that side, but not if the assigned position is appropriate.
// create new node and assign values
// create new node and assign values Node parentNode = writeSearchObj.getParent();
Node parentNode = searchResult.getParent(); Node theNode = newNode();
Node theNode = newNode(); theNode.setValues(newrow);
theNode.setValues(newrow); theNode.setOHByte(0, (byte) 1); // fresh magic
theNode.setOHByte(0, (byte) 1); // fresh magic theNode.setOHByte(1, (byte) 0); // fresh balance
theNode.setOHByte(1, (byte) 0); // fresh balance theNode.setOHHandle(parent, parentNode.handle());
theNode.setOHHandle(parent, parentNode.handle()); theNode.setOHHandle(leftchild, null);
theNode.setOHHandle(leftchild, null); theNode.setOHHandle(rightchild, null);
theNode.setOHHandle(rightchild, null); theNode.commit(CP_LOW);
theNode.commit(CP_LOW);
// check consistency and link new node to parent node
// check consistency and link new node to parent node byte parentBalance;
byte parentBalance; if (writeSearchObj.isLeft()) {
if (searchResult.isLeft()) { if (parentNode.getOHHandle(leftchild) != null) throw new kelondroException(filename, "tried to create leftchild node twice");
if (parentNode.getOHHandle(leftchild) != null) throw new kelondroException(filename, "tried to create leftchild node twice"); parentNode.setOHHandle(leftchild, theNode.handle());
parentNode.setOHHandle(leftchild, theNode.handle()); } else if (writeSearchObj.isRight()) {
} else if (searchResult.isRight()) { if (parentNode.getOHHandle(rightchild) != null) throw new kelondroException(filename, "tried to create rightchild node twice");
if (parentNode.getOHHandle(rightchild) != null) throw new kelondroException(filename, "tried to create rightchild node twice"); parentNode.setOHHandle(rightchild, theNode.handle());
parentNode.setOHHandle(rightchild, theNode.handle()); } else {
} else { throw new kelondroException(filename, "neither left nor right child");
throw new kelondroException(filename, "neither left nor right child"); }
}
commitNode(parentNode);
// now update recursively the node balance of the parentNode
// what do we have:
// - new Node, called 'theNode'
// - parent Node
// set balance factor in parent node(s)
boolean increasedHight = true;
String path = "";
byte prevHight;
Handle parentSideHandle;
while (increasedHight) {
// update balance
parentBalance = parentNode.getOHByte(balance); // {magic, balance}
prevHight = parentBalance;
parentSideHandle = parentNode.getOHHandle(leftchild);
if ((parentSideHandle != null) && (parentSideHandle.equals(theNode.handle()))) {
// is left child
parentBalance++;
path = "L" + path;
}
parentSideHandle =parentNode.getOHHandle(rightchild);
if ((parentSideHandle != null) && (parentSideHandle.equals(theNode.handle()))) {
// is right child
parentBalance--;
path = "R" + path;
}
increasedHight = ((java.lang.Math.abs((int) parentBalance) - java.lang.Math.abs((int) prevHight)) > 0);
parentNode.setOHByte(balance, parentBalance);
commitNode(parentNode); commitNode(parentNode);
// here we either stop because we had no increased hight, // now update recursively the node balance of the parentNode
// or we have a balance greater then 1 or less than -1 and we do rotation // what do we have:
// or we crawl up the tree and change the next balance // - new Node, called 'theNode'
if (!(increasedHight)) break; // finished // - parent Node
// check rotation need // set balance factor in parent node(s)
if (java.lang.Math.abs((int) parentBalance) > 1) { boolean increasedHight = true;
// rotate and stop then String path = "";
//System.out.println("* DB DEBUG: " + path.substring(0,2) + " ROTATION AT NODE " + parentNode.handle().toString() + ": BALANCE=" + parentOHByte[balance]); byte prevHight;
if (path.startsWith("LL")) { Handle parentSideHandle;
LL_RightRotation(parentNode, theNode); while (increasedHight) {
break;
} // update balance
if (path.startsWith("RR")) { parentBalance = parentNode.getOHByte(balance); // {magic, balance}
RR_LeftRotation(parentNode, theNode); prevHight = parentBalance;
break; parentSideHandle = parentNode.getOHHandle(leftchild);
} if ((parentSideHandle != null) && (parentSideHandle.equals(theNode.handle()))) {
if (path.startsWith("RL")) { // is left child
Handle parentHandle = parentNode.handle(); parentBalance++;
LL_RightRotation(theNode, getNode(theNode.getOHHandle(leftchild), theNode, leftchild)); path = "L" + path;
parentNode = getNode(parentHandle, null, 0); // reload the parent node }
RR_LeftRotation(parentNode, getNode(parentNode.getOHHandle(rightchild), parentNode, rightchild)); parentSideHandle =parentNode.getOHHandle(rightchild);
break; if ((parentSideHandle != null) && (parentSideHandle.equals(theNode.handle()))) {
} // is right child
if (path.startsWith("LR")) { parentBalance--;
Handle parentHandle = parentNode.handle(); path = "R" + path;
RR_LeftRotation(theNode, getNode(theNode.getOHHandle(rightchild), theNode, rightchild)); }
parentNode = getNode(parentHandle, null, 0); // reload the parent node increasedHight = ((java.lang.Math.abs((int) parentBalance) - java.lang.Math.abs((int) prevHight)) > 0);
LL_RightRotation(parentNode, getNode(parentNode.getOHHandle(leftchild), parentNode, leftchild)); parentNode.setOHByte(balance, parentBalance);
break; commitNode(parentNode);
}
break; // here we either stop because we had no increased hight,
} else { // or we have a balance greater then 1 or less than -1 and we do rotation
// crawl up the tree // or we crawl up the tree and change the next balance
if (parentNode.getOHHandle(parent) == null) { if (!(increasedHight)) break; // finished
// root reached: stop
break; // check rotation need
} else { if (java.lang.Math.abs((int) parentBalance) > 1) {
theNode = parentNode; // rotate and stop then
parentNode = getNode(parentNode.getOHHandle(parent), null, 0); //System.out.println("* DB DEBUG: " + path.substring(0,2) + " ROTATION AT NODE " + parentNode.handle().toString() + ": BALANCE=" + parentOHByte[balance]);
} if (path.startsWith("LL")) {
} LL_RightRotation(parentNode, theNode);
} break;
}
return null; // that means: no previous stored value present if (path.startsWith("RR")) {
} RR_LeftRotation(parentNode, theNode);
break;
}
if (path.startsWith("RL")) {
Handle parentHandle = parentNode.handle();
LL_RightRotation(theNode, getNode(theNode.getOHHandle(leftchild), theNode, leftchild));
parentNode = getNode(parentHandle, null, 0); // reload the parent node
RR_LeftRotation(parentNode, getNode(parentNode.getOHHandle(rightchild), parentNode, rightchild));
break;
}
if (path.startsWith("LR")) {
Handle parentHandle = parentNode.handle();
RR_LeftRotation(theNode, getNode(theNode.getOHHandle(rightchild), theNode, rightchild));
parentNode = getNode(parentHandle, null, 0); // reload the parent node
LL_RightRotation(parentNode, getNode(parentNode.getOHHandle(leftchild), parentNode, leftchild));
break;
}
break;
} else {
// crawl up the tree
if (parentNode.getOHHandle(parent) == null) {
// root reached: stop
break;
} else {
theNode = parentNode;
parentNode = getNode(parentNode.getOHHandle(parent), null, 0);
}
}
}
return null; // that means: no previous stored value present
}
}
} }
private void assignChild(Node parentNode, Node childNode, int childType) throws IOException { private void assignChild(Node parentNode, Node childNode, int childType) throws IOException {
@ -593,17 +588,18 @@ public class kelondroTree extends kelondroRecords implements Comparator, kelondr
} }
// Removes the mapping for this key from this map if present (optional operation). // Removes the mapping for this key from this map if present (optional operation).
public synchronized byte[][] remove(byte[] key) throws IOException { public byte[][] remove(byte[] key) throws IOException {
Search search = new Search(key); synchronized(writeSearchObj) {
if (search.found()) { writeSearchObj.process(key);
Node result = search.getMatcher(); if (writeSearchObj.found()) {
byte[][] values = result.getValues(); Node result = writeSearchObj.getMatcher();
remove(result, search.getParent()); byte[][] values = result.getValues();
search = null; remove(result, writeSearchObj.getParent());
return values; return values;
} else { } else {
return null; return null;
} }
}
} }
public void removeAll() throws IOException { public void removeAll() throws IOException {
@ -762,17 +758,16 @@ public class kelondroTree extends kelondroRecords implements Comparator, kelondr
} }
} }
public synchronized Iterator nodeIterator(boolean up, boolean rotating, byte[] firstKey) { public Iterator nodeIterator(boolean up, boolean rotating, byte[] firstKey) {
// iterates the elements in a sorted way. returns Node - type Objects // iterates the elements in a sorted way. returns Node - type Objects
try { try {
Search s = new Search(firstKey); Search search = new Search();
if (s.found()) { search.process(firstKey);
Node matcher = s.getMatcher(); if (search.found()) {
s = null; Node matcher = search.getMatcher();
return new nodeIterator(up, rotating, matcher); return new nodeIterator(up, rotating, matcher);
} else { } else {
Node nn = s.getParent(); Node nn = search.getParent();
s = null;
if (nn == null) { if (nn == null) {
return (new HashSet()).iterator(); // an empty iterator return (new HashSet()).iterator(); // an empty iterator
} else { } else {
@ -944,22 +939,21 @@ public class kelondroTree extends kelondroRecords implements Comparator, kelondr
} }
} }
public synchronized rowIterator rows(boolean up, boolean rotating) throws IOException { public rowIterator rows(boolean up, boolean rotating) throws IOException {
// iterates the rows of the Nodes // iterates the rows of the Nodes
// enumerated objects are of type byte[][] // enumerated objects are of type byte[][]
// iterates the elements in a sorted way. // iterates the elements in a sorted way.
return new rowIterator(new nodeIterator(up, rotating)); return new rowIterator(new nodeIterator(up, rotating));
} }
public synchronized Iterator rows(boolean up, boolean rotating, byte[] firstKey) throws IOException { public Iterator rows(boolean up, boolean rotating, byte[] firstKey) throws IOException {
Search s = new Search(firstKey); Search search = new Search();
if (s.found()) { search.process(firstKey);
Node matcher = s.getMatcher(); if (search.found()) {
s = null; Node matcher = search.getMatcher();
return new rowIterator(new nodeIterator(up, rotating, matcher)); return new rowIterator(new nodeIterator(up, rotating, matcher));
} else { } else {
Node nn = s.getParent(); Node nn = search.getParent();
s = null;
if (nn == null) { if (nn == null) {
return (Iterator) (new HashSet()).iterator(); return (Iterator) (new HashSet()).iterator();
} else { } else {
@ -1002,15 +996,14 @@ public class kelondroTree extends kelondroRecords implements Comparator, kelondr
return new keyIterator(new nodeIterator(up, rotating)); return new keyIterator(new nodeIterator(up, rotating));
} }
public synchronized Iterator keys(boolean up, boolean rotating, byte[] firstKey) throws IOException { public Iterator keys(boolean up, boolean rotating, byte[] firstKey) throws IOException {
Search s = new Search(firstKey); Search search = new Search();
if (s.found()) { search.process(firstKey);
Node matcher = s.getMatcher(); if (search.found()) {
s = null; Node matcher = search.getMatcher();
return new keyIterator(new nodeIterator(up, rotating, matcher)); return new keyIterator(new nodeIterator(up, rotating, matcher));
} else { } else {
Node nn = s.getParent(); Node nn = search.getParent();
s = null;
if (nn == null) { if (nn == null) {
return (Iterator) (new HashSet()).iterator(); return (Iterator) (new HashSet()).iterator();
} else { } else {

Loading…
Cancel
Save