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

com.bigdata.relation.AbstractRelation 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 Jun 30, 2008
 */

package com.bigdata.relation;

import java.util.Properties;
import java.util.UUID;

import com.bigdata.bop.BOpContextBase;
import com.bigdata.bop.IPredicate;
import com.bigdata.bop.ap.Predicate;
import com.bigdata.btree.BTree;
import com.bigdata.btree.IIndex;
import com.bigdata.btree.IndexMetadata;
import com.bigdata.btree.IndexTypeEnum;
import com.bigdata.btree.UnisolatedReadWriteIndex;
import com.bigdata.journal.ConcurrencyManager;
import com.bigdata.journal.IIndexManager;
import com.bigdata.journal.IJournal;
import com.bigdata.journal.ITx;
import com.bigdata.journal.Journal;
import com.bigdata.journal.TemporaryRawStore;
import com.bigdata.journal.TemporaryStore;
import com.bigdata.relation.accesspath.AccessPath;
import com.bigdata.relation.accesspath.IAccessPath;
import com.bigdata.relation.locator.ILocatableResource;
import com.bigdata.relation.rule.IAccessPathExpander;
import com.bigdata.service.IBigdataFederation;
import com.bigdata.striterator.IKeyOrder;

/**
 * Base class for {@link IRelation} and {@link IMutableRelation} impls.
 * 
 * @author Bryan Thompson
 * @version $Id$
 * @param 
 *            The generic type of the [E]lements of the relation.
 */
abstract public class AbstractRelation extends AbstractResource> implements
        IMutableRelation {

    /**
     * 
     */
    protected AbstractRelation(final IIndexManager indexManager,
            final String namespace, final Long timestamp,
            final Properties properties) {

        this(null/* container */, indexManager, namespace, timestamp,
                properties);

    }

    /**
     * Alternative version used when a resource exists within some container.
     * The additional container argument provides access to the container
     * before the container has been written to the global row store.
     */
    protected AbstractRelation(final ILocatableResource container,
            final IIndexManager indexManager, final String namespace,
            final Long timestamp, final Properties properties) {

        super(container, indexManager, namespace, timestamp, properties);

    }

    /**
     * The fully qualified name of the index.
     * 
     * @param keyOrder
     *            The natural index order.
     * 
     * @return The index name.
     */
    @Override
    public String getFQN(final IKeyOrder keyOrder) {
        
        return getFQN(this, keyOrder);
        
    }

    /**
     * The fully qualified name of the index.
     * 
     * @param relation
     *            The relation.
     * @param keyOrder
     *            The natural index order.
     * 
     * @return The fully qualified index name.
     */
    static public  String getFQN(final IRelation relation,
            final IKeyOrder keyOrder) {
        
        return getFQN(relation, keyOrder.getIndexName());
        
    }

    /**
     * The fully qualified name of the index.
     * 
     * @param relation
     *            The relation.
     * @param localName
     *            The local name of the index.
     * 
     * @return The fully qualified index name.
     */
    static public  String getFQN(final IRelation relation,
            final String localName) {

        /*
         * TODO We wind up calling this a lot. intern() might help reduce the
         * heap requirements while the returned value is being held, but it is
         * not reducing the heap pressure caused by this string concatenation.
         * To do that we would have to search a cache using the component
         * elements [namespace] and [keyOrder].
         */
        
        return (relation.getNamespace() + "." + localName).intern();

    }
    
    /**
     * Return the index for the {@link IKeyOrder} the timestamp for this view of
     * the relation.
     * 
     * @param keyOrder
     *            The natural index order.
     * 
     * @return The index -or- null iff the index does not exist as
     *         of the timestamp for this view of the relation.
     * 
     * @see #getIndex(String)
     * 
     * @todo For efficiency the concrete implementations need to override this
     *       saving a hard reference to the index and then use a switch like
     *       construct to return the correct hard reference. This behavior
     *       should be encapsulated.
     */
    @Override
    public IIndex getIndex(final IKeyOrder keyOrder) {

        return getIndex(getFQN(keyOrder));
        
    }

    /**
     * Return the named index using the timestamp for this view of the relation.
     * 
     * @param fqn
     *            The fully qualified name of the index.
     * 
     * @return The named index -or- null iff the named index does
     *         not exist as of that timestamp.
     * 
     * @throws IllegalArgumentException
     *             if name is null.
     * 
     * @see BOpContextBase#getIndex(IIndexManager, String, long)
     * 
     * @todo hard references to the indices must be dropped when an abort is
     *       processed. this is a bit awkward. the abort() could be raised into
     *       the relation container (it is for the AbstractTripleStore) and into
     *       the relation itself to facilitate this. alternatively the index
     *       objects themselves could be notified of an abort and make
     *       themselves invalid (this really only applies to the unisolated
     *       index and to indices isolated by a transaction).
     */
    public IIndex getIndex(final String fqn) {

        final IIndexManager indexManager = getIndexManager();

        final long timestamp = getTimestamp();

        return getIndex(indexManager, fqn, timestamp);
        
    }

    /**
     * Return the named index using the timestamp for this view of the relation.
     * 

* While both the {@link IBigdataFederation} imposes the * {@link ConcurrencyManager} on all access to a named index, neither the * {@link Journal} nor the {@link TemporaryRawStore} does this. Therefore * this method encapsulates the unisolated index for the latter classes in * order to impose the correct concurrency constraints. It does this using * an {@link UnisolatedReadWriteIndex}. This allows the caller to use the * returned index view without regard to concurrency controls (it will * appear to be a thread-safe object). * * @param indexManager * indexManager * @param fqn * The fully qualified name of the index. * @param timestamp * The timestamp of the view. * * @return The named index -or- null iff the named index does * not exist as of that timestamp. * * @throws IllegalArgumentException * if indexManager is null. * @throws IllegalArgumentException * if name is null. */ static public IIndex getIndex(final IIndexManager indexManager, final String fqn, final long timestamp) { if (indexManager == null) throw new IllegalArgumentException(); if (fqn == null) throw new IllegalArgumentException(); IIndex ndx = indexManager.getIndex(fqn, timestamp); /** * Note: We need to wrap any unisolated index on the Journal (included the * IsolatedActionJournal managed by the AbstractTask). * * @see #1129 (Concurrent modification error with group commit). */ if (ndx != null && timestamp == ITx.UNISOLATED && (indexManager instanceof IJournal || indexManager instanceof TemporaryStore)) { if(log.isDebugEnabled()) { log.debug("Imposing read-write concurrency controls on index: name=" + fqn); } ndx = new UnisolatedReadWriteIndex((BTree) ndx); } return ndx; } /** * Default factory for {@link IndexMetadata}. * * @param name * The fully qualified index name. * * @return A new {@link IndexMetadata} object for that index. */ protected IndexMetadata newIndexMetadata(final String name) { final IndexMetadata metadata = new IndexMetadata(getIndexManager(), getProperties(), name, UUID.randomUUID(), IndexTypeEnum.BTree); return metadata; } /** * {@link IAccessPath} factory. * * @param localIndexManager * The local index manager (optional, except when there is a * request for a shard local access path in scale-out). * @param predicate * The predicate used to request the access path. * @param keyOrder * The index which the access path will use. * * @return The access path. */ public IAccessPath newAccessPath(//final IRelation relation, final IIndexManager localIndexManager,// final long timestamp, final IPredicate predicate, final IKeyOrder keyOrder // , // final IIndex ndx, final int flags, final int chunkOfChunksCapacity, // final int chunkCapacity, final int fullyBufferedReadThreshold ) { return new AccessPath(this/*relation*/, localIndexManager, //timestamp, predicate, keyOrder // , ndx, flags, chunkOfChunksCapacity, // chunkCapacity, fullyBufferedReadThreshold ).init(); } @Override final public IAccessPath getAccessPath(final IPredicate predicate) { return getAccessPath(getKeyOrder(predicate), predicate); } @Override final public IAccessPath getAccessPath(final IKeyOrder keyOrder, final IPredicate predicate) { return getAccessPath(null/* localIndexManager */, keyOrder, predicate); } @Override @SuppressWarnings("unchecked") final public IAccessPath getAccessPath( final IIndexManager localIndexManager, // final IKeyOrder keyOrder,// final IPredicate predicate// ) { // The optional expander. final IAccessPathExpander expander = predicate.getAccessPathExpander(); IAccessPath accessPath; if (expander != null) { /* * Strip off the expander to prevent recursive application from * within the expander itself. */ final IPredicate predicateWithoutExpander = (IPredicate) ((Predicate) predicate) .clearProperty(IPredicate.Annotations.ACCESS_PATH_EXPANDER); // Obtain access path for the predicate w/o the expander annotation. accessPath = newAccessPath(localIndexManager, predicateWithoutExpander, keyOrder); // wrap the access path with the expander. accessPath = expander.getAccessPath(accessPath); } else { // Obtain access path for the predicate. accessPath = newAccessPath(localIndexManager, predicate, keyOrder); } return accessPath; } // /** // * {@inheritDoc} // *

// * Note: Since the relation may materialize the index views for its various // * access paths, and since we are restricted to a single index partition and // * (presumably) an index manager that only sees the index partitions local // * to a specific data service, we create an access path view for an index // * partition without forcing the relation to be materialized. // * // * @deprecated {@link AccessPath} is handling this directly based on the // * {@link IPredicate.Annotations#PARTITION_ID}. // */ // public IAccessPath getAccessPathForIndexPartition( // final IIndexManager indexManager, // // final IPredicate predicate// // ) { // // return getAccessPath(indexManager,getKeyOrder(predicate),predicate); // //// /* //// * Note: getIndexManager() _always_ returns the federation's index //// * manager because that is how we materialize an ILocatableResource when //// * we locate it. However, the federation's index manager can not be used //// * here because it addresses the scale-out indices. Instead, the caller //// * must pass in the IIndexManager which has access to the local index //// * objects so we can directly read on the shard. //// */ ////// final IIndexManager indexManager = getIndexManager(); //// //// if (indexManager == null) //// throw new IllegalArgumentException(); //// //// if (indexManager instanceof IBigdataFederation) { //// //// /* //// * This will happen if you fail to re-create the JoinNexus within //// * the target execution environment. //// * //// * This is disallowed because the predicate specifies an index //// * partition and expects to have access to the local index objects //// * for that index partition. However, the index partition is only //// * available when running inside of the ConcurrencyManager and when //// * using the IndexManager exposed by the ConcurrencyManager to its //// * tasks. //// */ //// //// throw new IllegalArgumentException( //// "Expecting a local index manager, not: " //// + indexManager.getClass().toString()); //// //// } //// //// if (predicate == null) //// throw new IllegalArgumentException(); //// //// final int partitionId = predicate.getPartitionId(); //// //// if (partitionId == -1) // must be a valid partition identifier. //// throw new IllegalArgumentException(); //// //// /* //// * @todo This condition should probably be an error since the expander //// * will be ignored. //// */ ////// if (predicate.getSolutionExpander() != null) ////// throw new IllegalArgumentException(); //// //// if (predicate.getRelationCount() != 1) { //// //// /* //// * This is disallowed. The predicate must be reading on a single //// * local index partition, not a view comprised of more than one //// * index partition. //// * //// * @todo In fact, we could allow a view here as long as all parts of //// * the view are local. That could be relevant when the other view //// * component was a shard of a focusStore for parallel decomposition //// * of RDFS closure, etc. The best way to handle such views when the //// * components are not local is to use a UNION of the JOIN. When both //// * parts are local we can do better using a UNION of the //// * IAccessPath. //// */ //// //// throw new IllegalStateException(); //// //// } //// //// final String namespace = getNamespace();//predicate.getOnlyRelationName(); //// //// /* //// * Find the best access path for that predicate. //// */ //// final IKeyOrder keyOrder = getKeyOrder(predicate); //// //// // The name of the desired index partition. //// final String name = DataService.getIndexPartitionName(namespace + "." //// + keyOrder.getIndexName(), predicate.getPartitionId()); //// //// /* //// * Note: whether or not we need both keys and values depends on the //// * specific index/predicate. //// * //// * Note: If the timestamp is a historical read, then the iterator will //// * be read only regardless of whether we specify that flag here or not. //// */ ////// * Note: We can specify READ_ONLY here since the tail predicates are not ////// * mutable for rule execution. //// final int flags = IRangeQuery.KEYS | IRangeQuery.VALS;// | IRangeQuery.READONLY; //// //// final long timestamp = getTimestamp();//getReadTimestamp(); //// //// // MUST be a local index view. //// final ILocalBTreeView ndx = (ILocalBTreeView) indexManager //// .getIndex(name, timestamp); //// //// return new AccessPath(this/* relation */, indexManager, timestamp, //// predicate, keyOrder ////// , ndx, flags, getChunkOfChunksCapacity(), ////// getChunkCapacity(), getFullyBufferedReadThreshold() //// ).init(); // // } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy