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

com.bigdata.relation.accesspath.AccessPathFusedView 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 31, 2007
 */

package com.bigdata.relation.accesspath;

import org.apache.log4j.Logger;

import com.bigdata.bop.BOp;
import com.bigdata.bop.IPredicate;
import com.bigdata.btree.IIndex;
import com.bigdata.btree.ITuple;
import com.bigdata.btree.ITupleIterator;
import com.bigdata.btree.view.FusedTupleIterator;
import com.bigdata.btree.view.FusedView;
import com.bigdata.striterator.ChunkedWrappedIterator;
import com.bigdata.striterator.IChunkedIterator;
import com.bigdata.striterator.IChunkedOrderedIterator;
import com.bigdata.striterator.IKeyOrder;

import cutthecrap.utils.striterators.Resolver;
import cutthecrap.utils.striterators.Striterator;

/**
 * A read-only fused view of two access paths obtained for the same
 * {@link IPredicate} constraint in two different databases (this is used for
 * truth maintenance when reading on the union of a focus store and the
 * database).
 * 
 * FIXME review impl and write tests.
 * 
 * FIXME Does not support {@link IPredicate.Annotations#ACCESS_PATH_FILTER}
 * 
 * @author Bryan Thompson
 * @version $Id$
 * 
 * @deprecated by {@link BOp}s using the UNION of JOINs. However, also note that
 *             this is only used for TM and that the focus store is always local
 *             for TM.
 */
public class AccessPathFusedView implements IAccessPath {

    protected static final Logger log = Logger.getLogger(IAccessPath.class);

    private final AccessPath path1;

    private final AccessPath path2;

    /**
     * 
     */
    public AccessPathFusedView(AccessPath path1,
            AccessPath path2) {

        if (path1 == null)
            throw new IllegalArgumentException();

        if (path2 == null)
            throw new IllegalArgumentException();

        if (path1 == path2)
            throw new IllegalArgumentException();

        final IPredicate p1 = path1.getPredicate();

        final IPredicate p2 = path2.getPredicate();

        if (p1.arity() != p2.arity())
            throw new IllegalArgumentException();

        final int arity = p1.arity();

        for (int i = 0; i < arity; i++) {

            if (!p1.get(i).equals(p2.get(i))) {

                throw new IllegalArgumentException();

            }

        }

        this.path1 = path1;

        this.path2 = path2;

        // // assume the flags from the first access path.
        // this.flags = path1.flags;

    }

    @Override
    public IPredicate getPredicate() {

        return path1.getPredicate();

    }

    @Override
    public boolean isEmpty() {

        return path1.isEmpty() && path2.isEmpty();

    }

    /**
     * {@inheritDoc}
     * 

* Note: You can not get an exact range count for a view. * * @throws UnsupportedOperationException * if exact == true. * * @todo an exact range count for a view could be written. It would have to * use two iterators (like a {@link FusedView}) that progressed in * sync so that duplicates could be detected. This means a full key * range scan for both source access paths. */ @Override public long rangeCount(boolean exact) { if (exact) { throw new UnsupportedOperationException(); } // @todo check for overflow on Long#Max_value return path1.rangeCount(exact) + path2.rangeCount(exact); } // final private int flags; /** * {@inheritDoc} * * @throws UnsupportedOperationException * always. * * @todo this could be implemented with a variant (or relaxed form) of * {@link FusedView}. */ @Override public IIndex getIndex() { throw new UnsupportedOperationException(); } // @Override // public ITupleIterator rangeIterator() { // // return rangeIterator(0/* capacity */); // // } private ITupleIterator rangeIterator(final int capacity) { /* * assume the flags from the first access path. */ return new FusedTupleIterator, E>(path1.flags,// false, // we do not want to see the deleted tuples. new ITupleIterator[] {// path1 .rangeIterator(capacity, path1.flags, path1.indexLocalFilter),// path2 .rangeIterator(capacity, path2.flags, path2.indexLocalFilter) // }); } @Override public IChunkedOrderedIterator iterator() { return iterator(0L/* offset */, 0L/* limit */, 0/* capacity */); } // public IChunkedOrderedIterator iterator(int limit, int capacity) { // // return iterator(0L/* offset */, limit, capacity); // // } /** * FIXME write tests for optimizations for point tests and small limits. See * {@link AccessPath#iterator(long, long, int) for impl details. * * FIXME handle non-zero offset. */ @Override public IChunkedOrderedIterator iterator(final long offset, long limit, int capacity) { if (offset > 0L) throw new UnsupportedOperationException(); if (limit == Long.MAX_VALUE) { limit = 0L; } if (limit > AccessPath.MAX_FULLY_BUFFERED_READ_LIMIT) { throw new UnsupportedOperationException(); } /* * @todo replace with ChunkedOrderedStriterator. */ if (path1.predicate.isFullyBound(path1.getKeyOrder())) { if(log.isDebugEnabled()) log.debug("Predicate is fully bound."); /* * If the predicate is fully bound then there can be at most one * element matched so we constrain the limit and capacity * accordingly. */ capacity = 1; limit = 1L; } else if (limit > 0) { /* * A [limit] was specified. * * NOTE: When the [limit] is specified (GT ZERO) we MUST NOT let the * DataService layer iterator read more than [limit] elements at a * time. * * This is part of the contract for REMOVEALL - when you set the * [limit] and specify REMOVEALL you are only removing the 1st * [limit] elements in the traversal order. * * This is also part of the atomic queue operations contract - the * head and tail queue operations function by specifying [limit := * 1] (tail also specifies the REVERSE traversal option). */ capacity = (int) limit; } final int chunkSize = (capacity == 0 ? IChunkedIterator.DEFAULT_CHUNK_SIZE : capacity); return new ChunkedWrappedIterator(new Striterator( rangeIterator(capacity)).addFilter(new Resolver() { private static final long serialVersionUID = 0L; @Override protected Object resolve(Object arg0) { final ITuple tuple = (ITuple) arg0; return tuple.getObject(); } }), chunkSize, path1.keyOrder, null/* filter */); } @Override public long removeAll() { throw new UnsupportedOperationException(); } @Override public IKeyOrder getKeyOrder() { return path1.getKeyOrder(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy