ch.ethz.globis.phtree.v8.NodeIteratorFullNoGC Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of phtree Show documentation
Show all versions of phtree Show documentation
The PH-Tree is a multi-dimensional index
/*
* Copyright 2011-2016 ETH Zurich. All Rights Reserved.
*
* This software is the proprietary information of ETH Zurich.
* Use is subject to license terms.
*/
package ch.ethz.globis.phtree.v8;
import org.zoodb.index.critbit.CritBit64;
import org.zoodb.index.critbit.CritBit64.CBIterator;
import org.zoodb.index.critbit.CritBit64.Entry;
import ch.ethz.globis.phtree.PhEntry;
import ch.ethz.globis.phtree.PhFilter;
import ch.ethz.globis.phtree.PhTreeHelper;
import ch.ethz.globis.phtree.v8.PhTree8.NodeEntry;
/**
* This NodeIterator reuses existing instances, which may be easier on the Java GC.
*
*
* @author ztilmann
*
* @param value type
*/
public class NodeIteratorFullNoGC {
private static final long FINISHED = Long.MAX_VALUE;
private final int DIM;
private boolean isPostHC;
private boolean isPostNI;
private boolean isSubHC;
private int postLen;
private long next = -1;
private long nextPost = -1;
private long nextSub = -1;
private Node nextSubNode;
private Node node;
private int currentOffsetPostKey;
private int currentOffsetPostVal;
private int currentOffsetSub;
private CBIterator> niIterator;
private int nMaxPost;
private int nMaxSub;
private int nPostsFound = 0;
private int posSubLHC = -1; //position in sub-node LHC array
private int postEntryLen;
private final long[] valTemplate;
private PhFilter checker;
private final PhEntry nextPost1;
private final PhEntry nextPost2;
private boolean isNextPost1free;
private final long MAX_POS;
/**
*
* @param DIM dimensions
* @param valTemplate A null indicates that no values are to be extracted.
*/
public NodeIteratorFullNoGC(int DIM, long[] valTemplate) {
this.DIM = DIM;
this.MAX_POS = (1L << DIM) -1;
this.valTemplate = valTemplate;
this.nextPost1 = new PhEntry(new long[DIM], null);
this.nextPost2 = new PhEntry(new long[DIM], null);
}
/**
*
* @param node
* @param rangeMin The minimum value that any found value should have. If the found value is
* lower, the search continues.
* @param rangeMax
* @param lower The minimum HC-Pos that a value should have.
* @param upper
* @param checker result verifier, can be null.
*/
private void reinit(Node node, PhFilter checker) {
next = -1;
nextSubNode = null;
currentOffsetPostKey = 0;
currentOffsetPostVal = 0;
currentOffsetSub = 0;
nPostsFound = 0;
posSubLHC = -1; //position in sub-node LHC array
this.checker = checker;
this.node = node;
this.isPostHC = node.isPostHC();
this.isPostNI = node.isPostNI();
this.isSubHC = node.isSubHC();
this.postLen = node.getPostLen();
nMaxPost = node.getPostCount();
nMaxSub = node.getSubCount();
nextPost = (nMaxPost > 0) ? -1 : FINISHED;
nextSub = (nMaxSub > 0) ? -1 : FINISHED;
//Position of the current entry
currentOffsetSub = node.getBitPos_SubNodeIndex(DIM);
if (isPostNI) {
postEntryLen = -1; //not used
if (niIterator == null) {
niIterator = new CritBit64.CBIterator<>();
}
niIterator.reset(node.ind());
} else {
currentOffsetPostKey = node.getBitPos_PostIndex(DIM);
// -set key offset to position before first element
// -set value offset to first element
if (isPostHC) {
//length of post-fix WITHOUT key
postEntryLen = DIM*postLen;
currentOffsetPostVal = currentOffsetPostKey + (1< getCurrentPost() {
return isNextPost1free ? nextPost2 : nextPost1;
}
/**
* Return whether the next value returned by next() is a sub-node or not.
*
* @return True if the current value (returned by next()) is a sub-node,
* otherwise false
*/
boolean isNextSub() {
return isPostNI ? (nextSubNode != null) : (next == nextSub);
}
/**
*
* @return False if the value does not match the range, otherwise true.
*/
private boolean readValue(long pos, int offsPostKey, PhEntry result) {
long[] key = result.getKey();
System.arraycopy(valTemplate, 0, key, 0, DIM);
PhTreeHelper.applyHcPos(pos, postLen, key);
result.setValue( node.getPostPOB(offsPostKey, pos, key) );
if (checker != null && !checker.isValid(key)) {
return false;
}
//Don't set to 'null' here, that interferes with parallel iteration over post/sub
//nextSubNode = null;
isNextPost1free = !isNextPost1free;
return true;
}
private boolean readValue(long pos, NodeEntry e, PhEntry result) {
//extract postfix
final long mask = postLen < 63 ? (~0L)< sub) {
PhTreeHelper.applyHcPos(pos, postLen, valTemplate);
sub.getInfix(valTemplate);
return (checker == null || checker.isValid(sub.getPostLen()+1, valTemplate));
}
private long getNext(PhEntry result) {
if (node.isPostNI()) {
niFindNext(result);
return next;
}
//Search for next entry if there are more entries and if current
//entry has already been returned (or is -1).
// (nextPost == next) is true when the previously returned entry (=next) was a postfix.
if (nextPost != FINISHED && nextPost == next) {
if (isPostHC) {
getNextPostAHC(result);
} else {
getNextPostLHC(result);
}
}
if (nextSub != FINISHED && nextSub == next) {
if (isSubHC) {
getNextSubAHC();
} else {
getNextSubLHC();
}
}
return (nextSub < nextPost) ? nextSub : nextPost;
}
private void getNextPostAHC(PhEntry result) {
//while loop until 1 is found.
long currentPos = nextPost;
while (true) {
currentPos++; //pos w/o bit-offset
if (currentPos > MAX_POS) {
nextPost = FINISHED;
break;
}
boolean bit = Bits.getBit(node.ba, currentOffsetPostKey);
currentOffsetPostKey += Node.PINN_HC_WIDTH; //pos with bit-offset
if (bit) {
//check post-fix
int offs = (int) (currentOffsetPostVal+currentPos*postEntryLen);
if (!readValue(currentPos, offs, result)) {
continue;
}
nextPost = currentPos;
break;
}
}
}
private void getNextPostLHC(PhEntry result) {
while (true) {
if (++nPostsFound > nMaxPost) {
nextPost = FINISHED;
break;
}
int offs = currentOffsetPostKey;
long currentPos = Bits.readArray(node.ba, offs, Node.PIK_WIDTH(DIM));
currentOffsetPostKey += postEntryLen;
//check post-fix
if (!readValue(currentPos, offs + Node.PIK_WIDTH(DIM), result)) {
continue;
}
nextPost = currentPos;
break;
}
}
private void getNextSubAHC() {
int currentPos = (int) nextSub; //We use (int) because arrays are always (int).
while (true) {
currentPos++;
if (currentPos > MAX_POS) {
nextSub = FINISHED;
break;
}
Node sub = node.subNRef(currentPos);
if (sub != null) {
if (readSub(currentPos, sub)) {
nextSub = currentPos;
nextSubNode = sub;
break;
}
}
}
}
private void getNextSubLHC() {
while (true) {
if (posSubLHC + 1 >= nMaxSub) {
nextSub = FINISHED;
break;
}
long currentPos = Bits.readArray(node.ba, currentOffsetSub, Node.SIK_WIDTH(DIM));
currentOffsetSub += Node.SIK_WIDTH(DIM);
posSubLHC++;
Node sub = node.subNRef(posSubLHC);
if (readSub(currentPos, sub)) {
nextSub = currentPos;
nextSubNode = sub;
break;
}
}
}
private void niFindNext(PhEntry result) {
while (niIterator.hasNext()) {
Entry> e = niIterator.nextEntry();
next = e.key();
nextSubNode = e.value().node;
if (nextSubNode == null) {
if (!readValue(e.key(), e.value(), result)) {
continue;
}
} else {
if (!readSub(e.key(), nextSubNode)) {
continue;
}
}
return;
}
next = FINISHED;
}
public Node getCurrentSubNode() {
return nextSubNode;
}
public Node node() {
return node;
}
void init(Node node, PhFilter checker) {
reinit(node, checker);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy