com.bigdata.bop.BOpContextBase 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 Aug 26, 2010
*/
package com.bigdata.bop;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import com.bigdata.bop.engine.QueryEngine;
import com.bigdata.btree.ILocalBTreeView;
import com.bigdata.journal.IIndexManager;
import com.bigdata.relation.IRelation;
import com.bigdata.relation.accesspath.IAccessPath;
import com.bigdata.relation.locator.ILocatableResource;
import com.bigdata.relation.locator.IResourceLocator;
import com.bigdata.relation.rule.IRule;
import com.bigdata.relation.rule.eval.IJoinNexus;
import com.bigdata.service.IBigdataFederation;
/**
* Base class for the bigdata operation evaluation context (NOT serializable).
*/
public class BOpContextBase {
// static private final transient Logger log = Logger.getLogger(BOpContextBase.class);
/**
* The federation iff running in scale-out.
*/
private final IBigdataFederation> fed;
/**
* The local index manager.
*/
private final IIndexManager indexManager;
/**
* The executor service.
*/
private final Executor executor;
/**
* The local {@link IIndexManager}. Query evaluation occurs
* against the local indices. In scale-out, query evaluation proceeds
* shard-wise and this {@link IIndexManager} MUST be able to read on the
* {@link ILocalBTreeView}.
*/
final public IIndexManager getIndexManager() {
return indexManager;
}
/**
* The {@link IBigdataFederation} IFF the operator is being evaluated on an
* {@link IBigdataFederation} and otherwise null
. When
* evaluating operations against an {@link IBigdataFederation}, this
* reference provides access to the scale-out view of the indices and to
* other bigdata services.
*/
final public IBigdataFederation> getFederation() {
return fed;
}
/**
* Return the {@link Executor} on to which the operator may submit tasks.
*
* Note: The is the {@link ExecutorService} associated with the
* local {@link #getIndexManager() index manager}.
*/
public final Executor getExecutorService() {
return executor;
}
public BOpContextBase(final QueryEngine queryEngine) {
this(queryEngine.getFederation(), queryEngine.getIndexManager());
}
/**
* Core constructor.
*
* @param fed
* The federation iff running in scale-out.
* @param localIndexManager
* The local index manager.
*/
public BOpContextBase(final IBigdataFederation> fed,
final IIndexManager localIndexManager) {
/*
* @todo null is permitted here for the unit tests, but we should really
* mock the IIndexManager and pass in a non-null object here and then
* verify that the reference is non-null.
*/
// if (localIndexManager == null)
// throw new IllegalArgumentException();
this.fed = fed;
this.indexManager = localIndexManager;
this.executor = localIndexManager == null ? null : localIndexManager
.getExecutorService();
}
/**
* Locate and return the view of the relation identified by the
* {@link IPredicate}.
*
* @param pred
* The {@link IPredicate}, which MUST be a tail from some
* {@link IRule}.
*
* @return The {@link IRelation} -or- null
if the relation did
* not exist for that timestamp.
*
* @todo Replaces {@link IJoinNexus#getTailRelationView(IPredicate)}. In
* order to support mutation operator we will also have to pass in the
* {@link #writeTimestamp} or differentiate this in the method name.
*/
@SuppressWarnings("unchecked")
public IRelation getRelation(final IPredicate pred) {
final String namespace = pred.getOnlyRelationName();
final long timestamp = pred.getTimestamp();
return (IRelation) getResource(namespace, timestamp);
}
/**
* Locate and return the view of the identified relation.
*
* @param namespace
* The namespace of the relation.
* @param timestamp
* The timestamp of the view of that relation.
*
* @return The {@link ILocatableResource} -or- null
if the
* relation did not exist for that timestamp.
*/
public ILocatableResource> getResource(final String namespace,
final long timestamp) {
/*
* Note: This uses the federation as the index manager when locating a
* resource for scale-out since that let's us look up the relation in
* the global row store, which is being used as a catalog.
*/
final IIndexManager tmp = getFederation() == null ? getIndexManager()
: getFederation();
return (ILocatableResource>) tmp.getResourceLocator().locate(
namespace, timestamp);
}
// /**
// * Return a writable view of the relation.
// *
// * @param namespace
// * The namespace of the relation.
// *
// * @return A writable view of the relation.
// *
// * @deprecated by getRelation()
// */
// public IRelation getWriteRelation(final String namespace) {
//
// /*
// * @todo Cache the resource locator?
// *
// * @todo This should be using the federation as the index manager when
// * locating a resource for scale-out, right? But s/o writes must use
// * the local index manager when actually obtaining the index view for
// * the relation.
// */
// return (IRelation) getIndexManager().getResourceLocator().locate(
// namespace, getWriteTimestamp());
//
// }
/**
* Obtain an access path reading from the identified {@link IRelation} using
* the specified {@link IPredicate}.
*
* Note: Passing in the {@link IRelation} is important since it otherwise
* must be discovered using the {@link IResourceLocator}. By requiring the
* caller to resolve it before hand and pass it into this method the
* contention and demand on the {@link IResourceLocator} cache is reduced.
*
*
Scale-Out
*
* Note: You MUST be extremely careful when using expanders with a local
* access path for a shared-partitioned or hash-partitioned index. Only
* expanders whose semantics remain valid with a partial view of the index
* will behave as expected. Here are some examples that DO NOT work:
*
* - "DISTINCT" on a partitioned local access path is not coherent
* - Expanders which generate reads against keys not found on that shard
* are not coherent.
*
* If you have requirements such as these, then either use a remote access
* path or change your query plan design more radically to take advantage of
* efficient shard-wise scans in scale-out.
*
* @param relation
* The relation.
* @param pred
* The predicate. When {@link IPredicate#getPartitionId()} is
* set, the returned {@link IAccessPath} MUST read on the
* identified local index partition (directly, not via RMI).
*
* @return The access path.
*
* @todo replaces
* {@link IJoinNexus#getTailAccessPath(IRelation, IPredicate)}.
*
* @todo Support mutable relation views (no - just fix truth maintenance).
*/
public IAccessPath getAccessPath(final IRelation relation,
final IPredicate predicate) {
if (relation == null)
throw new IllegalArgumentException();
if (predicate == null)
throw new IllegalArgumentException();
return relation.getAccessPath(indexManager/* localIndexManager */,
relation.getKeyOrder(predicate), predicate);
}
}