/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Created on Nov 15, 2006 */ package com.bigdata.btree; import java.util.NoSuchElementException; /** * Visits the values of a {@link Leaf} in the external key ordering. There is * exactly one value per key for a leaf node. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ */ public class LeafTupleIterator<E> implements ITupleIterator<E> { private final Leaf leaf; private final AbstractTuple<E> tuple; private int index; private int lastVisited = -1; // private final byte[] fromKey; // // private final byte[] toKey; // first index to visit. private final int fromIndex; // first index to NOT visit. private final int toIndex; private final boolean hasDeleteMarkers; private final boolean visitDeleted; public LeafTupleIterator(Leaf leaf) { this(leaf, new Tuple<E>(leaf.btree, IRangeQuery.DEFAULT), null, null); } public LeafTupleIterator(final Leaf leaf, final AbstractTuple<E> tuple) { this(leaf, tuple, null, null); } /** * * @param leaf * The leaf whose entries will be traversed (required). * @param tuple * Used to hold the output values (required). * @param fromKey * The first key whose entry will be visited or <code>null</code> * if the lower bound on the key traversal is not constrained. * @param toKey * The first key whose entry will NOT be visited or * <code>null</code> if the upper bound on the key traversal is * not constrained. * @param flags * Flags specifying whether the keys and/or values will be * materialized. * * @exception IllegalArgumentException * if fromKey is given and is greater than toKey. */ public LeafTupleIterator(final Leaf leaf, final AbstractTuple<E> tuple, final byte[] fromKey, final byte[] toKey) { assert leaf != null; assert tuple != null; this.leaf = leaf; this.tuple = tuple; this.hasDeleteMarkers = leaf.hasDeleteMarkers(); this.visitDeleted = (tuple.flags() & IRangeQuery.DELETED) != 0; // this.fromKey = fromKey; // may be null (no lower bound). // // this.toKey = toKey; // may be null (no upper bound). { // figure out the first index to visit. int fromIndex; if (fromKey != null) { fromIndex = leaf.getKeys().search(fromKey); if (fromIndex < 0) { fromIndex = -fromIndex - 1; } } else { fromIndex = 0; } this.fromIndex = fromIndex; } { // figure out the first index to NOT visit. int toIndex; if (toKey != null) { toIndex = leaf.getKeys().search(toKey); if (toIndex < 0) { toIndex = -toIndex - 1; } } else { toIndex = leaf.getKeyCount(); } this.toIndex = toIndex; } if (fromIndex > toIndex) { throw new IllegalArgumentException("fromKey > toKey"); } // starting index is the lower bound. index = fromIndex; } /** * Examines the entry at {@link #index}. If it passes the criteria for an * entry to visit then return true. Otherwise increment the {@link #index} * until either all entries in this leaf have been exhausted -or- the an * entry is identified that passes the various criteria. */ public boolean hasNext() { // if(filter == null) { // // return index >= fromIndex && index < toIndex; // // } for( ; index >= fromIndex && index < toIndex; index++) { /* * Skip deleted entries unless specifically requested. */ if (hasDeleteMarkers && !visitDeleted && leaf.getDeleteMarker(index)) { // skipping a deleted version. continue; } // entry @ index is next to visit. return true; } // nothing left to visit in this leaf. return false; } public ITuple<E> next() { if (!hasNext()) { throw new NoSuchElementException(); } lastVisited = index++; tuple.copy(lastVisited, leaf); return tuple; } /** * This operation is not supported. * <p> * Note: There are two ways in which you can achieve the semantics of * {@link #remove()}. One is to use an {@link ITupleCursor}, which * correctly handles traversal with concurrent modification. The other is to * use a {@link AbstractChunkedTupleIterator}, which buffers the tuples * first and then does a "delete" behind in order to avoid concurrent * modification during traversal. * * @throws UnsupportedOperationException * always. */ public void remove() { throw new UnsupportedOperationException(); } }