All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.ethz.globis.phtree.v8.NodeIteratorFullNoGC Maven / Gradle / Ivy

There is a newer version: 2.8.1
Show newest version
/*
 * 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