com.bigdata.bop.rdf.update.ChunkedResolutionOp 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 Mar 16, 2012
*/
package com.bigdata.bop.rdf.update;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import org.apache.log4j.Logger;
import org.openrdf.model.Value;
import com.bigdata.bop.BOp;
import com.bigdata.bop.BOpContext;
import com.bigdata.bop.BOpUtility;
import com.bigdata.bop.Constant;
import com.bigdata.bop.IBindingSet;
import com.bigdata.bop.IConstant;
import com.bigdata.bop.ILocatableResourceAnnotations;
import com.bigdata.bop.IVariable;
import com.bigdata.bop.PipelineOp;
import com.bigdata.journal.TimestampUtility;
import com.bigdata.rdf.internal.IV;
import com.bigdata.rdf.internal.IVCache;
import com.bigdata.rdf.internal.VTE;
import com.bigdata.rdf.internal.impl.TermId;
import com.bigdata.rdf.lexicon.LexiconRelation;
import com.bigdata.rdf.model.BigdataValue;
import com.bigdata.rdf.model.BigdataValueFactory;
/**
* Vectored operator adds and/or resolves the RDF {@link Value}s associated with
* mock {@link IV}s. On input, the variables must be mock {@link IV}s whose
* {@link IVCache} is set to the corresponding {@link BigdataValue}. On output,
* the bindings of the variables will be replaced by the corresponding
* {@link IV} if it exists or is an inline {@link IV} and (it writing is
* enabled) the newly assigned {@link IV} for the term.
*
* @author Bryan Thompson
* @version $Id: ChunkedResolutionTask.java 6153 2012-03-16 20:10:15Z
* thompsonbry $
*/
public class ChunkedResolutionOp extends PipelineOp {
private static final transient Logger log = Logger
.getLogger(ChunkedResolutionOp.class);
/**
*
*/
private static final long serialVersionUID = 1L;
public interface Annotations extends PipelineOp.Annotations,
ILocatableResourceAnnotations {
/**
* An optional {@link IVariable}[] identifying the variables to be
* resolved. All variables are resolved unless this annotation is
* specified.
*/
String VARS = ChunkedResolutionOp.class.getName() + ".vars";
}
/**
* @param args
* @param annotations
*/
public ChunkedResolutionOp(final BOp[] args,
final Map annotations) {
super(args, annotations);
}
/**
* @param op
*/
public ChunkedResolutionOp(final ChunkedResolutionOp op) {
super(op);
}
@Override
public FutureTask eval(final BOpContext context) {
return new FutureTask(new ChunkTask(context, this));
}
static private class ChunkTask implements Callable {
private final BOpContext context;
private final LexiconRelation lex;
private final boolean readOnly;
/**
* The variables to resolve -or- null
to resolve all
* variables.
*/
private final IVariable>[] vars;
public ChunkTask(final BOpContext context,
final ChunkedResolutionOp op) {
this.context = context;
final String namespace = ((String[]) op
.getRequiredProperty(Annotations.RELATION_NAME))[0];
final long timestamp = (Long) op
.getRequiredProperty(Annotations.TIMESTAMP);
this.lex = (LexiconRelation) context.getResource(namespace,
timestamp);
this.readOnly = TimestampUtility.isReadOnly(timestamp);
this.vars = (IVariable[]) op.getProperty(Annotations.VARS);
}
@Override
public Void call() throws Exception {
/*
* Materialize everything.
*/
final IBindingSet[] a = BOpUtility.toArray(context.getSource(),
context.getStats());
final IBindingSet[] b = resolve(a);
context.getSink().add(b);
context.getSink().flush();
// done.
return null;
}
/**
* Resolve the values.
*
* @return New solutions with resolved {@link IV}s.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
private IBindingSet[] resolve(final IBindingSet[] bindingSets) {
final Map values = new LinkedHashMap();
final BigdataValueFactory valueFactory = lex.getValueFactory();
for (IBindingSet bindings : bindingSets) {
if (vars == null) {
// All bindings.
final Iterator> it = bindings
.iterator();
while (it.hasNext()) {
final Map.Entry e = it.next();
final IV, ?> iv = (IV, ?>) e.getValue().get();
final Value val = iv.getValue();
// add BigdataValue variant of the var's Value.
values.put(val, valueFactory.asValue(val));
}
} else {
// Just the named variables.
for (IVariable> var : vars) {
final IConstant> c = bindings.get(var);
if (c == null)
continue;
final IV, ?> iv = (IV, ?>) c.get();
final BigdataValue val = iv.getValue();
// add BigdataValue variant of the var's Value.
values.put(val, valueFactory.asValue(val));
}
}
}
/*
* Batch resolve term identifiers for those BigdataValues.
*
* Note: If any value does not exist in the lexicon then its term
* identifier will be ZERO (0L).
*/
final long mutationCount;
{
final BigdataValue[] terms = values.values().toArray(
new BigdataValue[] {});
final long ndistinct = lex.addTerms(terms, terms.length,
readOnly);
if (!readOnly) {
mutationCount = ndistinct;
} else {
mutationCount = 0;
}
// cache the BigdataValues on the IVs for later
for (BigdataValue term : terms) {
final IV iv = term.getIV();
if (iv == null) {
/*
* Since the term identifier is NULL this value is not
* known to the kb.
*/
if (log.isInfoEnabled())
log.info("Not in knowledge base: " + term);
/*
* Create a dummy iv and cache the unknown value on it
* so that it can be used during query evalution.
*/
final IV dummy = TermId.mockIV(VTE.valueOf(term));
term.setIV(dummy);
dummy.setValue(term);
} else {
iv.setValue(term);
}
}
}
/*
* Replace the bindings with one's which have their IV set.
*/
// Allocate the output solutions array.
final IBindingSet[] bindingSets2 = new IBindingSet[bindingSets.length];
// Generate each output solution from each source solution.
for (int i = 0; i < bindingSets.length; i++) {
// Make a copy.
final IBindingSet bindingSet = bindingSets2[i] = bindingSets[i]
.clone();
if (vars == null) {
// All bindings.
final Iterator> it = bindingSet
.iterator();
while (it.hasNext()) {
final Map.Entry e = it.next();
final IV, ?> iv = (IV, ?>) e.getValue().get();
final Value val = (Value) iv.getValue();
// Lookup the resolved BigdataValue object.
final BigdataValue val2 = values.get(val);
// Note: if read-only, then val2 can be null.
assert readOnly || val2 != null : "value not found: "
+ val2;
if (log.isDebugEnabled())
log.debug("value: " + val + " : " + val2 + " ("
+ val2.getIV() + ")");
// rewrite the constant in the query.
bindingSet.set(e.getKey(), new Constant(val2.getIV()));
}
} else {
// Just the named variables.
for (IVariable> var : vars) {
final IConstant> c = bindingSet.get(var);
if (c == null)
continue;
final IV, ?> iv = (IV, ?>) c.get();
final BigdataValue val = iv.getValue();
// Lookup the resolved BigdataValue object.
final BigdataValue val2 = values.get(val);
// Note: if read-only, then val2 can be null.
assert readOnly || val2 != null : "value not found: "
+ val2;
// Verify IVCache is set.
assert val2.getIV() == val2;
if (log.isDebugEnabled())
log.debug("value: " + val + " : " + val2 + " ("
+ val2.getIV() + ")");
// rewrite the constant in the query.
bindingSet.set(var, new Constant(val2.getIV()));
}
}
}
if (mutationCount != 0)
context.getStats().mutationCount.add(mutationCount);
return bindingSets2;
}
} // ChunkTask
} // ChunkedResolutionTask
© 2015 - 2025 Weber Informatics LLC | Privacy Policy