/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com 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 20, 2010 */ package com.bigdata.relation.rule.eval; import java.io.IOException; import java.lang.ref.WeakReference; import java.util.Properties; import java.util.WeakHashMap; import org.apache.log4j.Logger; import com.bigdata.bop.IBindingSet; import com.bigdata.bop.joinGraph.IEvaluationPlan; import com.bigdata.bop.joinGraph.IEvaluationPlanFactory; import com.bigdata.journal.IIndexManager; import com.bigdata.relation.IMutableRelation; import com.bigdata.relation.accesspath.IBuffer; import com.bigdata.relation.accesspath.IElementFilter; import com.bigdata.relation.rule.IRule; /** * Base implementation for {@link IJoinNexusFactory}. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ */ abstract public class AbstractJoinNexusFactory implements IJoinNexusFactory { /** * */ private static final long serialVersionUID = 1L; private static final transient Logger log = Logger.getLogger(AbstractJoinNexusFactory.class); private final ActionEnum action; private final long writeTimestamp; private /*final*/ long readTimestamp; private final Properties properties; private final int solutionFlags; // @todo should be generic as IElementFilter<ISolution<?>> private final IElementFilter<?> solutionFilter; private final IEvaluationPlanFactory evaluationPlanFactory; private final IRuleTaskFactory defaultRuleTaskFactory; public String toString() { final StringBuilder sb = new StringBuilder(); sb.append(getClass().getSimpleName()); // sb.append("{ ruleContext=" + ruleContext); sb.append("{ action=" + action); sb.append(", writeTime=" + writeTimestamp); sb.append(", readTime=" + readTimestamp); sb.append(", properties=" + properties); sb.append(", solutionFlags=" + solutionFlags); sb.append(", solutionFilter=" + (solutionFilter == null ? "N/A" : solutionFilter.getClass().getName())); sb.append(", planFactory=" + evaluationPlanFactory.getClass().getName()); sb.append(", defaultRuleTaskFactory=" + defaultRuleTaskFactory.getClass().getName()); // allow extension by derived classes. toString(sb); sb.append("}"); return sb.toString(); } /** * Allows extension of {@link #toString()} by derived classes. * * @param sb */ protected void toString(final StringBuilder sb) { } /** * * @param action * Indicates whether this is a Query, Insert, or Delete * operation. * @param writeTimestamp * The timestamp of the relation view(s) using to write on the * {@link IMutableRelation}s (ignored if you are not execution * mutation programs). * @param readTimestamp * The timestamp of the relation view(s) used to read from the * access paths. * @param solutionFlags * Flags controlling the behavior of * {@link #newSolution(IRule, IBindingSet)}. * @param solutionFilter * An optional filter that will be applied to keep matching * elements out of the {@link IBuffer} for Query or Mutation * operations. * @param evaluationPlanFactory * The factory used to generate {@link IEvaluationPlan}s for * {@link IRule}s. * @param defaultRuleTaskFactory * The factory that will be used to generate the * {@link IStepTask} to execute an {@link IRule} unless the * {@link IRule} explicitly specifies a factory object using * {@link IRule#getTaskFactory()}. */ protected AbstractJoinNexusFactory(// final ActionEnum action,// final long writeTimestamp,// final long readTimestamp,// final Properties properties,// final int solutionFlags, // final IElementFilter<?> solutionFilter,// final IEvaluationPlanFactory evaluationPlanFactory,// final IRuleTaskFactory defaultRuleTaskFactory ) { if (action == null) throw new IllegalArgumentException(); if (evaluationPlanFactory == null) throw new IllegalArgumentException(); this.action = action; this.writeTimestamp = writeTimestamp; this.readTimestamp = readTimestamp; this.properties = properties; this.solutionFlags = solutionFlags; this.solutionFilter = solutionFilter; this.evaluationPlanFactory = evaluationPlanFactory; this.defaultRuleTaskFactory = defaultRuleTaskFactory; joinNexusCache = new WeakHashMap<IIndexManager, WeakReference<IJoinNexus>>(); } // @todo assumes one "central" relation (e.g., SPORelation)? public IJoinNexus newInstance(final IIndexManager indexManager) { if (indexManager == null) throw new IllegalArgumentException(); synchronized (joinNexusCache) { final WeakReference<IJoinNexus> ref = joinNexusCache .get(indexManager); IJoinNexus joinNexus = ref == null ? null : ref.get(); if (joinNexus == null) { joinNexus = newJoinNexus(indexManager); joinNexusCache.put(indexManager, new WeakReference<IJoinNexus>( joinNexus)); } return joinNexus; } } /** * Factory for {@link IJoinNexus} instances used by * {@link #newInstance(IIndexManager)} as past of its singleton pattern. */ abstract protected IJoinNexus newJoinNexus(IIndexManager indexManager); private transient WeakHashMap<IIndexManager, WeakReference<IJoinNexus>> joinNexusCache; final public ActionEnum getAction() { return action; } final public Properties getProperties() { return properties; } final public long getReadTimestamp() { return readTimestamp; } final public void setReadTimestamp(final long readTimestamp) { if (this.readTimestamp == readTimestamp) { // NOP. return; } synchronized(joinNexusCache) { // discard cache since advancing the readTimestamp. joinNexusCache.clear(); this.readTimestamp = readTimestamp; if(log.isInfoEnabled()) log.info("readTimestamp: "+readTimestamp); } } final public long getWriteTimestamp() { return writeTimestamp; } final public int getSolutionFlags() { return solutionFlags; } final public IElementFilter<?> getSolutionFilter() { return solutionFilter; } final public IEvaluationPlanFactory getEvaluationPlanFactory() { return evaluationPlanFactory; } final public IRuleTaskFactory getDefaultRuleTaskFactory() { return defaultRuleTaskFactory; } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { /* * Note: Must be explicitly allocated when de-serialized. */ joinNexusCache = new WeakHashMap<IIndexManager, WeakReference<IJoinNexus>>(); in.defaultReadObject(); } }