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

com.bigdata.rdf.spo.SPOArrayIterator 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 Oct 24, 2007
 */

package com.bigdata.rdf.spo;

import java.util.Arrays;
import java.util.NoSuchElementException;

import com.bigdata.rdf.inf.TruthMaintenance;
import com.bigdata.rdf.store.AbstractTripleStore;
import com.bigdata.relation.accesspath.IAccessPath;
import com.bigdata.relation.accesspath.IElementFilter;
import com.bigdata.striterator.ChunkedArrayIterator;
import com.bigdata.striterator.IChunkedOrderedIterator;
import com.bigdata.striterator.IKeyOrder;

/**
 * Iterator visits {@link SPO}s and supports removal (fully buffered).
 * 
 * @author Bryan Thompson
 * @version $Id$
 * 
 * @deprecated by {@link ChunkedArrayIterator} but this still has some very
 *             purpose specific uses mainly dealing with
 *             {@link TruthMaintenance} and with fully buffering precisely
 *             because the DB impl is not using concurrency controls.
 */
public class SPOArrayIterator implements IChunkedOrderedIterator {

    /**
     * The maximum capacity for the backing array.
     * 
     * FIXME Array limits in truth maintenance code. This should probably be
     * close to the branching factor or chunk capacity.
     * 
     * @see 
     *      Array limits in truth maintenance code. 
     */
    private static final long MAX_CAPACITY = 10000000;
    
    private boolean open = true;
    
    /**
     * The database (optional).
     */
    private AbstractTripleStore db;

    /**
     * The {@link IKeyOrder} in which statements are being visited and
     * null if not known.
     */
    private final IKeyOrder keyOrder;

    /** SPO buffer. */
    private ISPO[] stmts;

    /** #of valid entries in {@link #stmts}. */
    private int numStmts;

    /**
     * The index of the next entry in {@link #stmts} that will be returned by
     * {@link #next()}.
     */
    private int i = 0;

    /**
     * The {@link SPO} most recently returned by {@link #next()}.
     */
    private ISPO current = null;
    
    /**
     * The #of statements that this iterator buffered.
     */
    public int getStatementCount() {

        return numStmts;
        
    }

    public IKeyOrder getKeyOrder() {
        
        return keyOrder;
        
    }
    
    /**
     * An iterator that visits the {@link SPO}s in the given array whose
     * {@link IKeyOrder} is NOT known.
     * 

* Note: This constructor variant results in an iterator that does NOT * support {@link #remove()} and whose {@link #getKeyOrder()} method returns * null. * * @param stmts * The statements. * @param numStmts * The #of entries in stmts that are valid. */ public SPOArrayIterator(final ISPO[] stmts, final int numStmts) { this.db = null; // not available (remove is disabled). this.keyOrder = null; // not known. this.stmts = stmts; this.numStmts = numStmts; // this.filter = null; } // /** // * An iterator that visits the {@link SPO}s in the given array and // * optionally supports {@link #remove()}. // * // * @param db // * The database - when non-null the iterator will // * support {@link #remove()}. // * @param keyOrder // * The order of the data in stmts and null // * IFF the order is NOT known. // * @param stmts // * The statements. // * @param numStmts // * The #of entries in stmts that are valid. // */ // public SPOArrayIterator(AbstractTripleStore db, IKeyOrder keyOrder, // ISPO[] stmts, int numStmts, IElementFilter filter) { // // this.db = db; // MAY be null (remove() will be disabled). // // this.keyOrder = keyOrder; // MAY be null (implies not known). // // this.stmts = stmts; // // this.numStmts = numStmts; // //// this.filter = filter; // // } /** * Fully buffers all statements selected by the {@link IAccessPath}. *

* Note: This constructor variant supports {@link #remove()}. *

* Note: This constructor is much lighter weight than the * {@link SPOIterator} when you are trying to do an existance test (limit of * 1) or read only a few 100 {@link SPO}s. * * @param db * The database (MAY be null, but then {@link #remove()} is not * supported). * * @param accessPath * The access path (including the triple pattern). * * @param limit * When non-zero, this is the maximum #of {@link SPO}s that will * be read. When zero, all {@link SPO}s for that access path * will be read and buffered. * * @param filter * An optional filter. When non-null, only * matching statements will be visited. */ public SPOArrayIterator(final AbstractTripleStore db, final IAccessPath accessPath, final int limit, final IElementFilter filter) { if (accessPath == null) throw new IllegalArgumentException(); if (limit < 0) throw new IllegalArgumentException(); this.db = db; // MAY be null. this.keyOrder = accessPath.getKeyOrder(); // this.filter = filter; final long rangeCount = accessPath.rangeCount(false/*exact*/); if (rangeCount >= MAX_CAPACITY) { /* * Note: This is a relatively high limit (10M statements). You are * much better off processing smaller chunks! */ throw new RuntimeException( "Too many statements to read into memory: rangeCount=" + rangeCount + ", maxCapacity=" + MAX_CAPACITY); } final int n = (int) (limit > 0 ? Math.min(rangeCount, limit) : rangeCount); this.stmts = new ISPO[ n ]; /* * Materialize the matching statements. * * @todo for scale-out, pass the filter to the data service. */ // ITupleIterator itr = accessPath.rangeIterator(); // // int i = 0; // // while (itr.hasNext() && i < n) { // // final ISPO spo = (SPO) itr.next().getObject(); // // if (filter != null && !filter.isValid(spo)) { // // continue; // // } // // stmts[i++] = spo; // // } final IChunkedOrderedIterator itr = accessPath.iterator(0L, (long) n, 0/* chunkSize */); int i = 0; while (itr.hasNext()) { final ISPO spo = itr.next(); stmts[i++] = spo; } this.numStmts = i; } public boolean hasNext() { if(!open) return false; assert i <= numStmts; if (i == numStmts) { return false; } return true; } public ISPO next() { if (!hasNext()) { throw new NoSuchElementException(); } current = stmts[i++]; return current; } /** * Removes the last statement visited from the database (non-batch API). *

* Note If you are trying to remove a set of statements then you are MUCH * better off collecting up a set of SPOs to be removed and then batching * the remove requests on all indices in parallel. * * @throws UnsupportedOperationException * if a ctor variant was used that did not convey the database * reference. */ public void remove() { assertOpen(); if (db == null) { throw new UnsupportedOperationException(); } if (current == null) { throw new IllegalStateException(); } db.removeStatements(new ISPO[] { current }, 1); // clear the reference. current = null; } /** * Return the backing array. * * @see #getStatementCount() */ public ISPO[] array() { assertOpen(); return stmts; } /** * Returns the remaining statements. * * @throws NoSuchElementException * if {@link #hasNext()} returns false. */ public ISPO[] nextChunk() { if (!hasNext()) { throw new NoSuchElementException(); } final ISPO[] ret; if (i == 0 && numStmts == stmts.length) { /* * The SPO[] does not have any unused elements and nothing has been * returned to the caller by next() so we can just return the * backing array in this case. * * Note: If the caller then sorts the chunk it will have a * side-effect on the original SPO[] since we are returning a * reference to that array. */ ret = stmts; } else { /* * Create and return a new SPO[] containing only the statements * remaining in the iterator. */ final int remaining = numStmts - i; ret = new ISPO[remaining]; System.arraycopy(stmts, i, ret, 0, remaining); } // indicate that all statements have been consumed. i = numStmts; return ret; } public ISPO[] nextChunk(final IKeyOrder keyOrder) { if (keyOrder == null) throw new IllegalArgumentException(); final ISPO[] stmts = nextChunk(); if (keyOrder != this.keyOrder) { // sort into the required order. Arrays.sort(stmts, 0, stmts.length, keyOrder.getComparator()); } return stmts; } /* * Note: Do NOT eagerly close the iterator since the makes it impossible to * implement {@link #remove()}. */ public void close() { if (!open) { // already closed. return; } open = false; db = null; stmts = null; current = null; i = numStmts = 0; } private final void assertOpen() { if (!open) { throw new IllegalStateException(); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy