com.bigdata.htree.DirtyChildIterator Maven / Gradle / Ivy
/**
Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved.
Contact:
SYSTAP, LLC DBA Blazegraph
2501 Calvert ST NW #106
Washington, DC 20008
[email protected]
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.htree;
import java.lang.ref.Reference;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Visits the direct dirty children of a {@link DirectoryPage} in the index
* ordering. Since dirty nodes are always resident this iterator never forces a
* child to be loaded from the store.
*
* @author Bryan Thompson
* @version $Id: DirtyChildIterator.java 2265 2009-10-26 12:51:06Z thompsonbry $
*/
class DirtyChildIterator implements Iterator {
private final DirectoryPage node;
/**
* The index of the next child to return.
*/
private int index = 0;
/**
* The index of the last child that was returned to the caller via
* {@link #next()}.
*/
private int lastVisited = -1;
/**
* The next child to return or null if we need to scan for the next child.
* We always test to verify that the child is in fact dirty in
* {@link #next()} since it may have been written out between
* {@link #hasNext()} and {@link #next()}.
*/
private AbstractPage child = null;
/**
*
* @param node
* The node whose direct dirty children will be visited in key
* order.
*/
public DirtyChildIterator(final DirectoryPage node) {
assert node != null;
this.node = node;
}
/**
* @return true iff there is a dirty child having a separator key greater
* than the last visited dirty child at the moment that this method
* was invoked. If this method returns true
then an
* immediate invocation of {@link #next()} will succeed. However,
* that guarantee does not hold if intervening code forces the
* scheduled dirty child to be written onto the store.
*/
public boolean hasNext() {
/*
* If we are only visiting dirty children, then we need to test the
* current index. If it is not a dirty child, then we need to scan until
* we either exhaust the children or find a dirty index.
*/
if( child != null && child.isDirty() ) {
/*
* We have a child reference and it is still dirty.
*/
return true;
}
final int slotsPerPage = 1 << node.htree.addressBits;
for (; index < slotsPerPage; index++) {
final Reference childRef = node.getChildRef(index);
if (childRef == null)
continue;
child = childRef.get();
if (child == null)
continue;
if (!child.isDirty())
continue;
/*
* Note: We do NOT touch the hard reference queue here since the
* DirtyChildrenIterator is used when persisting a node using a
* post-order traversal. If a hard reference queue eviction drives
* the serialization of a node and we touch the hard reference queue
* during the post-order traversal then we break down the semantics
* of HardReferenceQueue#append(...) as the eviction does not
* necessarily cause the queue to reduce in length.
*/
// /*
// * Touch the child so that it will not be a candidate for eviction
// * to the store.
// */
// node.btree.touch(node);
for (; (index + 1) < slotsPerPage; index++) {
if (node.childRefs[index + 1] != childRef) {
/*
* Skip over all references to the same child until we are
* on the last directory slot which a reference to this
* child. This way, when hasNext() is called again to
* advance to the next distinct child, the visited child
* will not be another pointer to the same child page as the
* last visited child.
*/
break;
}
}
break;
}
return index < slotsPerPage;
}
public AbstractPage next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
assert child != null;
assert child.isDirty();
final AbstractPage tmp = child;
// advance the index where the scan will start next() time.
lastVisited = index++;
// clear the reference to force another scan.
child = null;
return tmp;
}
public AbstractPage getNode() {
if( lastVisited == -1 ) {
throw new IllegalStateException();
}
return node.getChild(lastVisited);
}
/**
* @exception UnsupportedOperationException
*/
public void remove() {
throw new UnsupportedOperationException();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy