diff --git a/source/de/anomic/kelondro/kelondroAbstractOrder.java b/source/de/anomic/kelondro/kelondroAbstractOrder.java index 7bd2408ac..e738da591 100644 --- a/source/de/anomic/kelondro/kelondroAbstractOrder.java +++ b/source/de/anomic/kelondro/kelondroAbstractOrder.java @@ -47,22 +47,49 @@ package de.anomic.kelondro; import de.anomic.kelondro.kelondroRecords.Node; -public abstract class kelondroAbstractOrder implements kelondroOrder { +public abstract class kelondroAbstractOrder implements kelondroOrder, Cloneable { + protected byte[] zero = null; + + public Object clone() { + Object theClone = this.clone(); + ((kelondroOrder) theClone).rotate(this.zero); + return theClone; + } + public long partition(byte[] key, int forks) { final long d = (Long.MAX_VALUE / forks) + ((Long.MAX_VALUE % forks) + 1) / forks; return cardinal(key) / d; } + public int compareI(byte[] a, byte[] b) { + if (zero == null) return compare(a, b); + // we have an artificial start point. check all combinations + int az = compare(a, zero); // -1 if a < z; 0 if a == z; 1 if a > z + int bz = compare(b, zero); // -1 if b < z; 0 if b == z; 1 if b > z + if ((az == 0) && (bz == 0)) return 0; + if (az == 0) return -1; + if (bz == 0) return 1; + if (az == bz) return compare(a, b); + return bz; + } + public int compare(Object a, Object b) { if ((a instanceof byte[]) && (b instanceof byte[])) { - return compare((byte[]) a, (byte[]) b); + return compareI((byte[]) a, (byte[]) b); } else if ((a instanceof Node) && (b instanceof Node)) { - return compare(((Node) a).getKey(), ((Node) b).getKey()); + return compareI(((Node) a).getKey(), ((Node) b).getKey()); } else if ((a instanceof String) && (b instanceof String)) { - return compare(((String) a).getBytes(), ((String) b).getBytes()); + return compareI(((String) a).getBytes(), ((String) b).getBytes()); } else throw new IllegalArgumentException("Object type or Object type combination not supported: a=" + a + ", b=" + b); } + public byte[] zero() { + return zero; + } + + public void rotate(byte[] zero) { + this.zero = zero; + } } diff --git a/source/de/anomic/kelondro/kelondroBase64Order.java b/source/de/anomic/kelondro/kelondroBase64Order.java index 991b12800..ae549b44d 100644 --- a/source/de/anomic/kelondro/kelondroBase64Order.java +++ b/source/de/anomic/kelondro/kelondroBase64Order.java @@ -222,7 +222,7 @@ public class kelondroBase64Order extends kelondroAbstractOrder implements kelond } } - public long cardinal(byte[] key) { + private long cardinalI(byte[] key) { // returns a cardinal number in the range of 0 .. Long.MAX_VALUE long c = 0; int p = 0; @@ -232,6 +232,14 @@ public class kelondroBase64Order extends kelondroAbstractOrder implements kelond return c; } + public long cardinal(byte[] key) { + if (this.zero == null) return cardinalI(key); + long zeroCardinal = cardinalI(this.zero); + long keyCardinal = cardinalI(key); + if (keyCardinal > zeroCardinal) return keyCardinal - zeroCardinal; + return Long.MAX_VALUE - keyCardinal + zeroCardinal + 1; + } + public int compare(byte[] a, byte[] b) { int i = 0; final int al = a.length; diff --git a/source/de/anomic/kelondro/kelondroNaturalOrder.java b/source/de/anomic/kelondro/kelondroNaturalOrder.java index c4bcc2b8e..097a54b20 100644 --- a/source/de/anomic/kelondro/kelondroNaturalOrder.java +++ b/source/de/anomic/kelondro/kelondroNaturalOrder.java @@ -69,7 +69,7 @@ public class kelondroNaturalOrder extends kelondroAbstractOrder implements kelon return null; } - public long cardinal(byte[] key) { + private static long cardinalI(byte[] key) { // returns a cardinal number in the range of 0 .. Long.MAX_VALUE long c = 0; int p = 0; @@ -78,6 +78,14 @@ public class kelondroNaturalOrder extends kelondroAbstractOrder implements kelon c = c >>> 1; return c; } + + public long cardinal(byte[] key) { + if (this.zero == null) return cardinalI(key); + long zeroCardinal = cardinalI(this.zero); + long keyCardinal = cardinalI(key); + if (keyCardinal > zeroCardinal) return keyCardinal - zeroCardinal; + return Long.MAX_VALUE - keyCardinal + zeroCardinal + 1; + } public static byte[] encodeLong(long c, int length) { byte[] b = new byte[length]; diff --git a/source/de/anomic/kelondro/kelondroOrder.java b/source/de/anomic/kelondro/kelondroOrder.java index f08775972..89e5dd601 100644 --- a/source/de/anomic/kelondro/kelondroOrder.java +++ b/source/de/anomic/kelondro/kelondroOrder.java @@ -49,6 +49,8 @@ import java.util.Comparator; public interface kelondroOrder extends Comparator { + public Object clone(); + public String signature(); // returns a signature String so that different orderings have different signatures public long partition(byte[] key, int forkes); @@ -57,4 +59,7 @@ public interface kelondroOrder extends Comparator { public int compare(byte[] a, byte[] b); + public byte[] zero(); // returns the zero point of the Ordering; null if not defined + + public void rotate(byte[] zero); // defines that the ordering rotates, and sets the zero point for the rotation } diff --git a/source/de/anomic/kelondro/kelondroTree.java b/source/de/anomic/kelondro/kelondroTree.java index e966af5ef..e3a08f8eb 100644 --- a/source/de/anomic/kelondro/kelondroTree.java +++ b/source/de/anomic/kelondro/kelondroTree.java @@ -167,6 +167,11 @@ public class kelondroTree extends kelondroRecords implements kelondroIndex { return oo; } + public kelondroOrder getOrder() { + // returns the order of this tree + return this.objectOrder; + } + public void clear() throws IOException { super.clear(); setHandle(root, null); // reset the root value diff --git a/source/de/anomic/plasma/plasmaWordIndex.java b/source/de/anomic/plasma/plasmaWordIndex.java index f190b32d8..8a615616b 100644 --- a/source/de/anomic/plasma/plasmaWordIndex.java +++ b/source/de/anomic/plasma/plasmaWordIndex.java @@ -62,6 +62,7 @@ import de.anomic.kelondro.kelondroBase64Order; import de.anomic.kelondro.kelondroException; import de.anomic.kelondro.kelondroMergeIterator; import de.anomic.kelondro.kelondroNaturalOrder; +import de.anomic.kelondro.kelondroOrder; import de.anomic.server.logging.serverLog; public final class plasmaWordIndex { @@ -74,7 +75,8 @@ public final class plasmaWordIndex { private final plasmaWordIndexAssortmentCluster assortmentCluster; private int assortmentBufferSize; //kb private final plasmaWordIndexClassicDB backend; - + private final kelondroOrder indexOrder = new kelondroNaturalOrder(true); + public plasmaWordIndex(File databaseRoot, int bufferkb, serverLog log) { this.databaseRoot = databaseRoot; this.backend = new plasmaWordIndexClassicDB(databaseRoot, log); @@ -382,7 +384,9 @@ public final class plasmaWordIndex { public static final int RL_WORDFILES = 3; public synchronized TreeSet wordHashes(String startHash, int resourceLevel, boolean rot, int count) { - TreeSet hashes = new TreeSet(); + kelondroOrder hashOrder = (kelondroOrder) indexOrder.clone(); + if (rot) hashOrder.rotate(startHash.getBytes()); else hashOrder.rotate(null); + TreeSet hashes = new TreeSet(hashOrder); Iterator i = wordHashes(startHash, resourceLevel, rot); String hash; while ((hashes.size() < count) && (i.hasNext())) {