http://git-wip-us.apache.org/repos/asf/jena/blob/5f99f5f3/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/solver/OpExecutorTDB1.java ---------------------------------------------------------------------- diff --git a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/solver/OpExecutorTDB1.java b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/solver/OpExecutorTDB1.java deleted file mode 100644 index 828bcab..0000000 --- a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/solver/OpExecutorTDB1.java +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.jena.tdb2.solver; - -import java.util.function.Predicate; - -import org.apache.jena.atlas.lib.tuple.Tuple ; -import org.apache.jena.atlas.logging.Log ; -import org.apache.jena.graph.Graph ; -import org.apache.jena.graph.Node ; -import org.apache.jena.sparql.ARQInternalErrorException ; -import org.apache.jena.sparql.algebra.Op ; -import org.apache.jena.sparql.algebra.op.* ; -import org.apache.jena.sparql.algebra.optimize.TransformFilterPlacement ; -import org.apache.jena.sparql.core.BasicPattern ; -import org.apache.jena.sparql.core.Quad ; -import org.apache.jena.sparql.core.Substitute ; -import org.apache.jena.sparql.core.Var ; -import org.apache.jena.sparql.engine.ExecutionContext ; -import org.apache.jena.sparql.engine.QueryIterator ; -import org.apache.jena.sparql.engine.iterator.QueryIterPeek ; -import org.apache.jena.sparql.engine.main.OpExecutor ; -import org.apache.jena.sparql.engine.main.OpExecutorFactory ; -import org.apache.jena.sparql.engine.main.QC ; -import org.apache.jena.sparql.engine.main.iterator.QueryIterGraph ; -import org.apache.jena.sparql.engine.optimizer.reorder.ReorderProc ; -import org.apache.jena.sparql.engine.optimizer.reorder.ReorderTransformation ; -import org.apache.jena.sparql.expr.ExprList ; -import org.apache.jena.sparql.mgt.Explain ; -import org.apache.jena.tdb2.store.DatasetGraphTDB; -import org.apache.jena.tdb2.store.GraphTDB; -import org.apache.jena.tdb2.store.NodeId; -import org.slf4j.Logger ; -import org.slf4j.LoggerFactory ; - -/** TDB executor for algebra expressions. It is the standard ARQ executor - * except for basic graph patterns and filtered basic graph patterns (currently). - * - * See also: StageGeneratorDirectTDB, a non-reordering - */ -public class OpExecutorTDB1 extends OpExecutor -{ - private static final Logger log = LoggerFactory.getLogger(OpExecutorTDB1.class) ; - - public final static OpExecutorFactory OpExecFactoryTDB = new OpExecutorFactory() - { - @Override - public OpExecutor create(ExecutionContext execCxt) - { return new OpExecutorTDB1(execCxt) ; } - } ; - - private final boolean isForTDB ; - - // A new compile object is created for each op compilation. - // So the execCxt is changing as we go through the query-compile-execute process - public OpExecutorTDB1(ExecutionContext execCxt) - { - super(execCxt) ; - // NB. The dataset may be a TDB one, or a general one. - // Any merged union graph magic (for a TDB dataset was handled - // in QueryEngineTDB). - - isForTDB = (execCxt.getActiveGraph() instanceof GraphTDB) ; - } - - @Override - protected QueryIterator exec(Op op, QueryIterator input) { - if ( level < 0 ) - // Print only at top level (and we're called before level++) - Explain.explain("TDB", op, super.execCxt.getContext()) ; - return super.exec(op, input) ; - } - - // Retrieving nodes isn't so bad because they will be needed anyway. - // And if their duplicates, likely to be cached. - // Need to work with SolverLib which wraps the NodeId bindgins with a converter. - - @Override - protected QueryIterator execute(OpDistinct opDistinct, QueryIterator input) - { - return super.execute(opDistinct, input) ; - } - - @Override - protected QueryIterator execute(OpReduced opReduced, QueryIterator input) - { - return super.execute(opReduced, input) ; - } - - @Override - protected QueryIterator execute(OpFilter opFilter, QueryIterator input) - { - if ( ! isForTDB ) - return super.execute(opFilter, input) ; - - // If the filter does not apply to the input?? - // Where does ARQ catch this? - - // (filter (bgp ...)) - if ( OpBGP.isBGP(opFilter.getSubOp()) ) - { - // Still may be a TDB graph in a non-TDB dataset (e.g. a named model) - GraphTDB graph = (GraphTDB)execCxt.getActiveGraph() ; - OpBGP opBGP = (OpBGP)opFilter.getSubOp() ; - return executeBGP(graph, opBGP, input, opFilter.getExprs(), execCxt) ; - } - - // (filter (quadpattern ...)) - if ( opFilter.getSubOp() instanceof OpQuadPattern ) - { - OpQuadPattern quadPattern = (OpQuadPattern)opFilter.getSubOp() ; - DatasetGraphTDB ds = (DatasetGraphTDB)execCxt.getDataset() ; - return optimizeExecuteQuads(ds, input, - quadPattern.getGraphNode(), quadPattern.getBasicPattern(), - opFilter.getExprs(), execCxt) ; - } - - // (filter (anything else)) - return super.execute(opFilter, input) ; - } - - // ---- Triple patterns - - @Override - protected QueryIterator execute(OpBGP opBGP, QueryIterator input) - { - if ( ! isForTDB ) - return super.execute(opBGP, input) ; - - GraphTDB graph = (GraphTDB)execCxt.getActiveGraph() ; - return executeBGP(graph, opBGP, input, null, execCxt) ; - - } - - @Override - protected QueryIterator execute(OpQuadPattern quadPattern, QueryIterator input) - { - if ( ! isForTDB ) - return super.execute(quadPattern, input) ; - - // DatasetGraph dg = execCxt.getDataset() ; - // if ( ! ( dg instanceof DatasetGraphTDB ) ) - // throw new InternalErrorException("Not a TDB backed dataset in quad pattern execution") ; - - DatasetGraphTDB ds = (DatasetGraphTDB)execCxt.getDataset() ; - BasicPattern bgp = quadPattern.getBasicPattern() ; - Node gn = quadPattern.getGraphNode() ; - return optimizeExecuteQuads(ds, input, gn, bgp, null, execCxt) ; - } - - @Override - protected QueryIterator execute(OpGraph opGraph, QueryIterator input) - { - // Path evaluation or dataset sets which do not go straight to the DatasetGraphTDB - return new QueryIterGraph(input, opGraph, execCxt) ; - } - - /** Execute a BGP (and filters) on a TDB graph, which may be in default storage or it may be a named graph */ - private static QueryIterator executeBGP(GraphTDB graph, OpBGP opBGP, QueryIterator input, ExprList exprs, - ExecutionContext execCxt) - { - // Is it the real default graph (normal route or explicitly named)? - if ( ! isDefaultGraphStorage(graph.getGraphName())) - { - // Not default storage - it's a named graph in storage. - DatasetGraphTDB ds = graph.getDSG() ; - return optimizeExecuteQuads(ds, input, graph.getGraphName(), opBGP.getPattern(), exprs, execCxt) ; - } - - // Execute a BGP on the real default graph - return optimizeExecuteTriples(graph, input, opBGP.getPattern(), exprs, execCxt) ; - } - - /** Execute, with optimization, a basic graph pattern on the default graph storage */ - private static QueryIterator optimizeExecuteTriples(GraphTDB graph, QueryIterator input, - BasicPattern pattern, ExprList exprs, - ExecutionContext execCxt) - { - if ( ! input.hasNext() ) - return input ; - - // -- Input - // Must pass this iterator into the next stage. - if ( pattern.size() >= 2 ) - { - // Must be 2 or triples to reorder. - ReorderTransformation transform = graph.getDSG().getReorderTransform() ; - if ( transform != null ) - { - QueryIterPeek peek = QueryIterPeek.create(input, execCxt) ; - input = peek ; // Must pass on - pattern = reorder(pattern, peek, transform) ; - } - } - // -- Filter placement - - Op op = null ; - if ( exprs != null ) - op = TransformFilterPlacement.transform(exprs, pattern) ; - else - op = new OpBGP(pattern) ; - - return plainExecute(op, input, execCxt) ; - } - - /** Execute, with optimization, a quad pattern */ - private static QueryIterator optimizeExecuteQuads(DatasetGraphTDB ds, - QueryIterator input, - Node gn, BasicPattern bgp, - ExprList exprs, ExecutionContext execCxt) - { - if ( ! input.hasNext() ) - return input ; - - // ---- Graph names with special meaning. - - gn = decideGraphNode(gn, execCxt) ; - if ( gn == null ) - return optimizeExecuteTriples(ds.getDefaultGraphTDB(), input, bgp, exprs, execCxt) ; - - // ---- Execute quads+filters - if ( bgp.size() >= 2 ) - { - ReorderTransformation transform = ds.getReorderTransform() ; - - if ( transform != null ) - { - QueryIterPeek peek = QueryIterPeek.create(input, execCxt) ; - input = peek ; // Original input now invalid. - bgp = reorder(bgp, peek, transform) ; - } - } - // -- Filter placement - Op op = null ; - if ( exprs != null ) - op = TransformFilterPlacement.transform(exprs, gn, bgp) ; - else - op = new OpQuadPattern(gn, bgp) ; - - return plainExecute(op, input, execCxt) ; - } - - /** Execute without modification of the op - does <b>not</b> apply special graph name translations */ - private static QueryIterator plainExecute(Op op, QueryIterator input, ExecutionContext execCxt) - { - // -- Execute - // Switch to a non-reordering executor - // The Op may be a sequence due to TransformFilterPlacement - // so we need to do a full execution step, not go straight to the SolverLib. - - ExecutionContext ec2 = new ExecutionContext(execCxt) ; - ec2.setExecutor(plainFactory) ; - - // Solve without going through this executor again. - // There would be issues of nested patterns but this is only a - // (filter (bgp...)) or (filter (quadpattern ...)) or sequences of these. - // so there are no nested patterns to reorder. - return QC.execute(op, input, ec2) ; - } - - private static BasicPattern reorder(BasicPattern pattern, QueryIterPeek peek, ReorderTransformation transform) - { - if ( transform != null ) - { - // This works by getting one result from the peek iterator, - // and creating the more gounded BGP. The tranform is used to - // determine the best order and the transformation is returned. This - // transform is applied to the unsubstituted pattern (which will be - // substituted as part of evaluation. - - if ( ! peek.hasNext() ) - throw new ARQInternalErrorException("Peek iterator is already empty") ; - - BasicPattern pattern2 = Substitute.substitute(pattern, peek.peek() ) ; - // Calculate the reordering based on the substituted pattern. - ReorderProc proc = transform.reorderIndexes(pattern2) ; - // Then reorder original patten - pattern = proc.reorder(pattern) ; - } - return pattern ; - } - - /** Handle special graph node names. - * Returns null for default graph in storage (use the triple table). - * Returns Node.ANY for the union graph - */ - public static Node decideGraphNode(Node gn, ExecutionContext execCxt) - { - // ---- Graph names with special meaning. - - // Graph names with special meaning: - // Quad.defaultGraphIRI -- the IRI used in GRAPH <> to mean the default graph. - // Quad.defaultGraphNodeGenerated -- the internal marker node used for the quad form of queries. - // Quad.unionGraph -- the IRI used in GRAPH <> to mean the union of named graphs - - if ( isDefaultGraphStorage(gn) ) - { - // Storage concrete, default graph. - // Either outside GRAPH (no implicit union) - // or using the "name" of the default graph - return null ; - } - - // Not default storage graph. - // ---- Union (RDF Merge) of named graphs - - if ( Quad.isUnionGraph(gn) ) - return Node.ANY ; - boolean doingUnion = false ; - - return gn ; - } - - // Is this a query against the real default graph in the storage (in a 3-tuple table). - private static boolean isDefaultGraphStorage(Node gn) - { - if ( gn == null ) - return true ; - - // Is it the implicit name for default graph. - if ( Quad.isDefaultGraph(gn) ) - // Not accessing the union of named graphs as the default graph - // and pattern is directed to the default graph. - return true ; - - return false ; - } - - @Override - protected QueryIterator execute(OpDatasetNames dsNames, QueryIterator input) - { - DatasetGraphTDB ds = (DatasetGraphTDB)execCxt.getDataset() ; - Predicate<Tuple<NodeId>> filter = QC2.getFilter(execCxt.getContext()) ; - Node gn = dsNames.getGraphNode() ; - if ( Var.isVar(gn) ) - return SolverLib.graphNames(ds, dsNames.getGraphNode(), input, filter, execCxt) ; - else - return SolverLib.testForGraphName(ds, dsNames.getGraphNode(), input, filter, execCxt) ; - } - - // ---- OpExecute factories and plain executor. - - private static OpExecutorFactory plainFactory = new OpExecutorPlainFactoryTDB() ; - private static class OpExecutorPlainFactoryTDB implements OpExecutorFactory - { - @Override - public OpExecutor create(ExecutionContext execCxt) - { - return new OpExecutorPlainTDB(execCxt) ; - } - } - - /** An op executor that simply executes a BGP or QuadPattern without any reordering */ - private static class OpExecutorPlainTDB extends OpExecutor - { - Predicate<Tuple<NodeId>> filter = null ; - - public OpExecutorPlainTDB(ExecutionContext execCxt) - { - super(execCxt) ; - filter = QC2.getFilter(execCxt.getContext()) ; - } - - @Override - public QueryIterator execute(OpBGP opBGP, QueryIterator input) - { - Graph g = execCxt.getActiveGraph() ; - - if ( g instanceof GraphTDB ) - { - BasicPattern bgp = opBGP.getPattern() ; - Explain.explain("Execute", bgp, execCxt.getContext()) ; - // Triple-backed (but may be named as explicit default graph). - //return SolverLib.execute((GraphTDB)g, bgp, input, filter, execCxt) ; - GraphTDB gtdb = (GraphTDB)g ; - Node gn = decideGraphNode(gtdb.getGraphName(), execCxt) ; - return SolverLib.execute(gtdb.getDSG(), gn, bgp, input, filter, execCxt) ; - } - Log.warn(this, "Non-GraphTDB passed to OpExecutorPlainTDB") ; - return super.execute(opBGP, input) ; - } - - @Override - public QueryIterator execute(OpQuadPattern opQuadPattern, QueryIterator input) - { - Node gn = opQuadPattern.getGraphNode() ; - gn = decideGraphNode(gn, execCxt) ; - - if ( execCxt.getDataset() instanceof DatasetGraphTDB ) - { - DatasetGraphTDB ds = (DatasetGraphTDB)execCxt.getDataset() ; - Explain.explain("Execute", opQuadPattern.getPattern(), execCxt.getContext()) ; - BasicPattern bgp = opQuadPattern.getBasicPattern() ; - return SolverLib.execute(ds, gn, bgp, input, filter, execCxt) ; - } - // Maybe a TDB named graph inside a non-TDB dataset. - Graph g = execCxt.getActiveGraph() ; - if ( g instanceof GraphTDB ) - { - // Triples graph from TDB (which is the default graph of the dataset), - // used a named graph in a composite dataset. - BasicPattern bgp = opQuadPattern.getBasicPattern() ; - Explain.explain("Execute", bgp, execCxt.getContext()) ; - // Don't pass in G -- gn may be different. - return SolverLib.execute(((GraphTDB)g).getDSG(), gn, bgp, input, filter, execCxt) ; - } - Log.warn(this, "Non-DatasetGraphTDB passed to OpExecutorPlainTDB") ; - return super.execute(opQuadPattern, input) ; - } - - } -}
http://git-wip-us.apache.org/repos/asf/jena/blob/5f99f5f3/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/solver/OpExecutorTDB2.java ---------------------------------------------------------------------- diff --git a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/solver/OpExecutorTDB2.java b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/solver/OpExecutorTDB2.java new file mode 100644 index 0000000..aa0f5df --- /dev/null +++ b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/solver/OpExecutorTDB2.java @@ -0,0 +1,428 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.tdb2.solver; + +import java.util.function.Predicate; + +import org.apache.jena.atlas.lib.tuple.Tuple ; +import org.apache.jena.atlas.logging.Log ; +import org.apache.jena.graph.Graph ; +import org.apache.jena.graph.Node ; +import org.apache.jena.sparql.ARQInternalErrorException ; +import org.apache.jena.sparql.algebra.Op ; +import org.apache.jena.sparql.algebra.op.* ; +import org.apache.jena.sparql.algebra.optimize.TransformFilterPlacement ; +import org.apache.jena.sparql.core.BasicPattern ; +import org.apache.jena.sparql.core.Quad ; +import org.apache.jena.sparql.core.Substitute ; +import org.apache.jena.sparql.core.Var ; +import org.apache.jena.sparql.engine.ExecutionContext ; +import org.apache.jena.sparql.engine.QueryIterator ; +import org.apache.jena.sparql.engine.iterator.QueryIterPeek ; +import org.apache.jena.sparql.engine.main.OpExecutor ; +import org.apache.jena.sparql.engine.main.OpExecutorFactory ; +import org.apache.jena.sparql.engine.main.QC ; +import org.apache.jena.sparql.engine.main.iterator.QueryIterGraph ; +import org.apache.jena.sparql.engine.optimizer.reorder.ReorderProc ; +import org.apache.jena.sparql.engine.optimizer.reorder.ReorderTransformation ; +import org.apache.jena.sparql.expr.ExprList ; +import org.apache.jena.sparql.mgt.Explain ; +import org.apache.jena.tdb2.store.DatasetGraphTDB; +import org.apache.jena.tdb2.store.GraphTDB; +import org.apache.jena.tdb2.store.NodeId; +import org.slf4j.Logger ; +import org.slf4j.LoggerFactory ; + +/** TDB executor for algebra expressions. It is the standard ARQ executor + * except for basic graph patterns and filtered basic graph patterns (currently). + * + * See also: StageGeneratorDirectTDB, a non-reordering + */ +public class OpExecutorTDB2 extends OpExecutor +{ + private static final Logger log = LoggerFactory.getLogger(OpExecutorTDB2.class) ; + + public final static OpExecutorFactory OpExecFactoryTDB = new OpExecutorFactory() + { + @Override + public OpExecutor create(ExecutionContext execCxt) + { return new OpExecutorTDB2(execCxt) ; } + } ; + + private final boolean isForTDB ; + + // A new compile object is created for each op compilation. + // So the execCxt is changing as we go through the query-compile-execute process + public OpExecutorTDB2(ExecutionContext execCxt) + { + super(execCxt) ; + // NB. The dataset may be a TDB one, or a general one. + // Any merged union graph magic (for a TDB dataset was handled + // in QueryEngineTDB). + + isForTDB = (execCxt.getActiveGraph() instanceof GraphTDB) ; + } + + @Override + protected QueryIterator exec(Op op, QueryIterator input) { + if ( level < 0 ) + // Print only at top level (and we're called before level++) + Explain.explain("TDB", op, super.execCxt.getContext()) ; + return super.exec(op, input) ; + } + + // Retrieving nodes isn't so bad because they will be needed anyway. + // And if their duplicates, likely to be cached. + // Need to work with SolverLib which wraps the NodeId bindgins with a converter. + + @Override + protected QueryIterator execute(OpDistinct opDistinct, QueryIterator input) + { + return super.execute(opDistinct, input) ; + } + + @Override + protected QueryIterator execute(OpReduced opReduced, QueryIterator input) + { + return super.execute(opReduced, input) ; + } + + @Override + protected QueryIterator execute(OpFilter opFilter, QueryIterator input) + { + if ( ! isForTDB ) + return super.execute(opFilter, input) ; + + // If the filter does not apply to the input?? + // Where does ARQ catch this? + + // (filter (bgp ...)) + if ( OpBGP.isBGP(opFilter.getSubOp()) ) + { + // Still may be a TDB graph in a non-TDB dataset (e.g. a named model) + GraphTDB graph = (GraphTDB)execCxt.getActiveGraph() ; + OpBGP opBGP = (OpBGP)opFilter.getSubOp() ; + return executeBGP(graph, opBGP, input, opFilter.getExprs(), execCxt) ; + } + + // (filter (quadpattern ...)) + if ( opFilter.getSubOp() instanceof OpQuadPattern ) + { + OpQuadPattern quadPattern = (OpQuadPattern)opFilter.getSubOp() ; + DatasetGraphTDB ds = (DatasetGraphTDB)execCxt.getDataset() ; + return optimizeExecuteQuads(ds, input, + quadPattern.getGraphNode(), quadPattern.getBasicPattern(), + opFilter.getExprs(), execCxt) ; + } + + // (filter (anything else)) + return super.execute(opFilter, input) ; + } + + // ---- Triple patterns + + @Override + protected QueryIterator execute(OpBGP opBGP, QueryIterator input) + { + if ( ! isForTDB ) + return super.execute(opBGP, input) ; + + GraphTDB graph = (GraphTDB)execCxt.getActiveGraph() ; + return executeBGP(graph, opBGP, input, null, execCxt) ; + + } + + @Override + protected QueryIterator execute(OpQuadPattern quadPattern, QueryIterator input) + { + if ( ! isForTDB ) + return super.execute(quadPattern, input) ; + + // DatasetGraph dg = execCxt.getDataset() ; + // if ( ! ( dg instanceof DatasetGraphTDB ) ) + // throw new InternalErrorException("Not a TDB backed dataset in quad pattern execution") ; + + DatasetGraphTDB ds = (DatasetGraphTDB)execCxt.getDataset() ; + BasicPattern bgp = quadPattern.getBasicPattern() ; + Node gn = quadPattern.getGraphNode() ; + return optimizeExecuteQuads(ds, input, gn, bgp, null, execCxt) ; + } + + @Override + protected QueryIterator execute(OpGraph opGraph, QueryIterator input) + { + // Path evaluation or dataset sets which do not go straight to the DatasetGraphTDB + return new QueryIterGraph(input, opGraph, execCxt) ; + } + + /** Execute a BGP (and filters) on a TDB graph, which may be in default storage or it may be a named graph */ + private static QueryIterator executeBGP(GraphTDB graph, OpBGP opBGP, QueryIterator input, ExprList exprs, + ExecutionContext execCxt) + { + // Is it the real default graph (normal route or explicitly named)? + if ( ! isDefaultGraphStorage(graph.getGraphName())) + { + // Not default storage - it's a named graph in storage. + DatasetGraphTDB ds = graph.getDSG() ; + return optimizeExecuteQuads(ds, input, graph.getGraphName(), opBGP.getPattern(), exprs, execCxt) ; + } + + // Execute a BGP on the real default graph + return optimizeExecuteTriples(graph, input, opBGP.getPattern(), exprs, execCxt) ; + } + + /** Execute, with optimization, a basic graph pattern on the default graph storage */ + private static QueryIterator optimizeExecuteTriples(GraphTDB graph, QueryIterator input, + BasicPattern pattern, ExprList exprs, + ExecutionContext execCxt) + { + if ( ! input.hasNext() ) + return input ; + + // -- Input + // Must pass this iterator into the next stage. + if ( pattern.size() >= 2 ) + { + // Must be 2 or triples to reorder. + ReorderTransformation transform = graph.getDSG().getReorderTransform() ; + if ( transform != null ) + { + QueryIterPeek peek = QueryIterPeek.create(input, execCxt) ; + input = peek ; // Must pass on + pattern = reorder(pattern, peek, transform) ; + } + } + // -- Filter placement + + Op op = null ; + if ( exprs != null ) + op = TransformFilterPlacement.transform(exprs, pattern) ; + else + op = new OpBGP(pattern) ; + + return plainExecute(op, input, execCxt) ; + } + + /** Execute, with optimization, a quad pattern */ + private static QueryIterator optimizeExecuteQuads(DatasetGraphTDB ds, + QueryIterator input, + Node gn, BasicPattern bgp, + ExprList exprs, ExecutionContext execCxt) + { + if ( ! input.hasNext() ) + return input ; + + // ---- Graph names with special meaning. + + gn = decideGraphNode(gn, execCxt) ; + if ( gn == null ) + return optimizeExecuteTriples(ds.getDefaultGraphTDB(), input, bgp, exprs, execCxt) ; + + // ---- Execute quads+filters + if ( bgp.size() >= 2 ) + { + ReorderTransformation transform = ds.getReorderTransform() ; + + if ( transform != null ) + { + QueryIterPeek peek = QueryIterPeek.create(input, execCxt) ; + input = peek ; // Original input now invalid. + bgp = reorder(bgp, peek, transform) ; + } + } + // -- Filter placement + Op op = null ; + if ( exprs != null ) + op = TransformFilterPlacement.transform(exprs, gn, bgp) ; + else + op = new OpQuadPattern(gn, bgp) ; + + return plainExecute(op, input, execCxt) ; + } + + /** Execute without modification of the op - does <b>not</b> apply special graph name translations */ + private static QueryIterator plainExecute(Op op, QueryIterator input, ExecutionContext execCxt) + { + // -- Execute + // Switch to a non-reordering executor + // The Op may be a sequence due to TransformFilterPlacement + // so we need to do a full execution step, not go straight to the SolverLib. + + ExecutionContext ec2 = new ExecutionContext(execCxt) ; + ec2.setExecutor(plainFactory) ; + + // Solve without going through this executor again. + // There would be issues of nested patterns but this is only a + // (filter (bgp...)) or (filter (quadpattern ...)) or sequences of these. + // so there are no nested patterns to reorder. + return QC.execute(op, input, ec2) ; + } + + private static BasicPattern reorder(BasicPattern pattern, QueryIterPeek peek, ReorderTransformation transform) + { + if ( transform != null ) + { + // This works by getting one result from the peek iterator, + // and creating the more gounded BGP. The tranform is used to + // determine the best order and the transformation is returned. This + // transform is applied to the unsubstituted pattern (which will be + // substituted as part of evaluation. + + if ( ! peek.hasNext() ) + throw new ARQInternalErrorException("Peek iterator is already empty") ; + + BasicPattern pattern2 = Substitute.substitute(pattern, peek.peek() ) ; + // Calculate the reordering based on the substituted pattern. + ReorderProc proc = transform.reorderIndexes(pattern2) ; + // Then reorder original patten + pattern = proc.reorder(pattern) ; + } + return pattern ; + } + + /** Handle special graph node names. + * Returns null for default graph in storage (use the triple table). + * Returns Node.ANY for the union graph + */ + public static Node decideGraphNode(Node gn, ExecutionContext execCxt) + { + // ---- Graph names with special meaning. + + // Graph names with special meaning: + // Quad.defaultGraphIRI -- the IRI used in GRAPH <> to mean the default graph. + // Quad.defaultGraphNodeGenerated -- the internal marker node used for the quad form of queries. + // Quad.unionGraph -- the IRI used in GRAPH <> to mean the union of named graphs + + if ( isDefaultGraphStorage(gn) ) + { + // Storage concrete, default graph. + // Either outside GRAPH (no implicit union) + // or using the "name" of the default graph + return null ; + } + + // Not default storage graph. + // ---- Union (RDF Merge) of named graphs + + if ( Quad.isUnionGraph(gn) ) + return Node.ANY ; + boolean doingUnion = false ; + + return gn ; + } + + // Is this a query against the real default graph in the storage (in a 3-tuple table). + private static boolean isDefaultGraphStorage(Node gn) + { + if ( gn == null ) + return true ; + + // Is it the implicit name for default graph. + if ( Quad.isDefaultGraph(gn) ) + // Not accessing the union of named graphs as the default graph + // and pattern is directed to the default graph. + return true ; + + return false ; + } + + @Override + protected QueryIterator execute(OpDatasetNames dsNames, QueryIterator input) + { + DatasetGraphTDB ds = (DatasetGraphTDB)execCxt.getDataset() ; + Predicate<Tuple<NodeId>> filter = QC2.getFilter(execCxt.getContext()) ; + Node gn = dsNames.getGraphNode() ; + if ( Var.isVar(gn) ) + return SolverLib.graphNames(ds, dsNames.getGraphNode(), input, filter, execCxt) ; + else + return SolverLib.testForGraphName(ds, dsNames.getGraphNode(), input, filter, execCxt) ; + } + + // ---- OpExecute factories and plain executor. + + private static OpExecutorFactory plainFactory = new OpExecutorPlainFactoryTDB() ; + private static class OpExecutorPlainFactoryTDB implements OpExecutorFactory + { + @Override + public OpExecutor create(ExecutionContext execCxt) + { + return new OpExecutorPlainTDB(execCxt) ; + } + } + + /** An op executor that simply executes a BGP or QuadPattern without any reordering */ + private static class OpExecutorPlainTDB extends OpExecutor + { + Predicate<Tuple<NodeId>> filter = null ; + + public OpExecutorPlainTDB(ExecutionContext execCxt) + { + super(execCxt) ; + filter = QC2.getFilter(execCxt.getContext()) ; + } + + @Override + public QueryIterator execute(OpBGP opBGP, QueryIterator input) + { + Graph g = execCxt.getActiveGraph() ; + + if ( g instanceof GraphTDB ) + { + BasicPattern bgp = opBGP.getPattern() ; + Explain.explain("Execute", bgp, execCxt.getContext()) ; + // Triple-backed (but may be named as explicit default graph). + //return SolverLib.execute((GraphTDB)g, bgp, input, filter, execCxt) ; + GraphTDB gtdb = (GraphTDB)g ; + Node gn = decideGraphNode(gtdb.getGraphName(), execCxt) ; + return SolverLib.execute(gtdb.getDSG(), gn, bgp, input, filter, execCxt) ; + } + Log.warn(this, "Non-GraphTDB passed to OpExecutorPlainTDB") ; + return super.execute(opBGP, input) ; + } + + @Override + public QueryIterator execute(OpQuadPattern opQuadPattern, QueryIterator input) + { + Node gn = opQuadPattern.getGraphNode() ; + gn = decideGraphNode(gn, execCxt) ; + + if ( execCxt.getDataset() instanceof DatasetGraphTDB ) + { + DatasetGraphTDB ds = (DatasetGraphTDB)execCxt.getDataset() ; + Explain.explain("Execute", opQuadPattern.getPattern(), execCxt.getContext()) ; + BasicPattern bgp = opQuadPattern.getBasicPattern() ; + return SolverLib.execute(ds, gn, bgp, input, filter, execCxt) ; + } + // Maybe a TDB named graph inside a non-TDB dataset. + Graph g = execCxt.getActiveGraph() ; + if ( g instanceof GraphTDB ) + { + // Triples graph from TDB (which is the default graph of the dataset), + // used a named graph in a composite dataset. + BasicPattern bgp = opQuadPattern.getBasicPattern() ; + Explain.explain("Execute", bgp, execCxt.getContext()) ; + // Don't pass in G -- gn may be different. + return SolverLib.execute(((GraphTDB)g).getDSG(), gn, bgp, input, filter, execCxt) ; + } + Log.warn(this, "Non-DatasetGraphTDB passed to OpExecutorPlainTDB") ; + return super.execute(opQuadPattern, input) ; + } + + } +} http://git-wip-us.apache.org/repos/asf/jena/blob/5f99f5f3/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/DatasetGraphSwitchable.java ---------------------------------------------------------------------- diff --git a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/DatasetGraphSwitchable.java b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/DatasetGraphSwitchable.java index a9a2fc0..60b654a 100644 --- a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/DatasetGraphSwitchable.java +++ b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/DatasetGraphSwitchable.java @@ -30,10 +30,11 @@ import org.apache.jena.graph.Node; import org.apache.jena.shared.PrefixMapping; import org.apache.jena.shared.impl.PrefixMappingImpl; import org.apache.jena.sparql.core.DatasetGraph ; +import org.apache.jena.sparql.core.DatasetGraphWrapper; import org.apache.jena.sparql.core.DatasetPrefixStorage ; final -public class DatasetGraphSwitchable extends DatasetGraphWrapperTxn /* Until ARQ catches up with promote */ +public class DatasetGraphSwitchable extends DatasetGraphWrapper { // QueryEngineFactoryWrapper has a QueryEngineFactory that is always loaded that // executes on the unwrapped DSG (recursively). Unwrapping is via getBase, calling http://git-wip-us.apache.org/repos/asf/jena/blob/5f99f5f3/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/DatasetGraphTDB.java ---------------------------------------------------------------------- diff --git a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/DatasetGraphTDB.java b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/DatasetGraphTDB.java index 5acec81..42690b2 100644 --- a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/DatasetGraphTDB.java +++ b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/DatasetGraphTDB.java @@ -174,10 +174,9 @@ public class DatasetGraphTDB extends DatasetGraphTriplesQuads Transaction txn = txnSystem.getThreadTransaction() ; if ( txn == null ) throw new TransactionException("Not in a transaction") ; - if ( txn.isWriteTxn() ) return ; - boolean b = txn.promote() ; + boolean b = promote() ; if ( !b ) throw new TransactionException("Can't write") ; } @@ -445,7 +444,7 @@ public class DatasetGraphTDB extends DatasetGraphTriplesQuads } @Override - public boolean promote(TxnType txnType) { + public boolean promote(Promote txnType) { if ( txnMonitor != null ) txnMonitor.startPromote(); try { return txnSystem.promote(txnType) ; http://git-wip-us.apache.org/repos/asf/jena/blob/5f99f5f3/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/DatasetGraphWrapperTxn.java ---------------------------------------------------------------------- diff --git a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/DatasetGraphWrapperTxn.java b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/DatasetGraphWrapperTxn.java deleted file mode 100644 index 8022165..0000000 --- a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/DatasetGraphWrapperTxn.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.jena.tdb2.store; - -import org.apache.jena.sparql.core.DatasetGraphWrapper ; - -public class DatasetGraphWrapperTxn extends DatasetGraphWrapper implements DatasetGraphTxn { - - public DatasetGraphWrapperTxn(DatasetGraphTxn dsg) { - super(dsg) ; - } - - @Override - public boolean promote() { - return ((DatasetGraphTxn)get()).promote() ; - } - -} http://git-wip-us.apache.org/repos/asf/jena/blob/5f99f5f3/jena-db/jena-tdb2/src/test/java/org/apache/jena/tdb2/store/TestDatasetTDB.java ---------------------------------------------------------------------- diff --git a/jena-db/jena-tdb2/src/test/java/org/apache/jena/tdb2/store/TestDatasetTDB.java b/jena-db/jena-tdb2/src/test/java/org/apache/jena/tdb2/store/TestDatasetTDB.java index 16149df..2c2258f 100644 --- a/jena-db/jena-tdb2/src/test/java/org/apache/jena/tdb2/store/TestDatasetTDB.java +++ b/jena-db/jena-tdb2/src/test/java/org/apache/jena/tdb2/store/TestDatasetTDB.java @@ -28,6 +28,7 @@ import org.apache.jena.riot.Lang ; import org.apache.jena.riot.RDFDataMgr ; import org.apache.jena.sparql.core.Quad ; import org.apache.jena.sparql.sse.SSE ; +import org.apache.jena.system.JenaSystem; import org.apache.jena.tdb2.TDB2; import org.apache.jena.tdb2.junit.TL; import org.junit.After ; @@ -37,6 +38,11 @@ import org.junit.Test ; /** Tests of datasets, prefixes, special URIs etc (see also {@link org.apache.jena.sparql.graph.GraphsTests} */ public class TestDatasetTDB { + static { + JenaSystem.DEBUG_INIT = true ; + JenaSystem.init(); + } + private Dataset dataset ; @Before public void before() { @@ -170,6 +176,7 @@ public class TestDatasetTDB @Test public void special3() { + JenaSystem.init(); Dataset ds = dataset() ; load1(ds.getDefaultModel()) ; http://git-wip-us.apache.org/repos/asf/jena/blob/5f99f5f3/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionLocal.java ---------------------------------------------------------------------- diff --git a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionLocal.java b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionLocal.java index 5c6e42f..362a4be 100644 --- a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionLocal.java +++ b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionLocal.java @@ -295,8 +295,7 @@ public class RDFConnectionLocal implements RDFConnection { @Override public void begin() { dataset.begin(); } @Override public void begin(TxnType txnType) { dataset.begin(txnType); } @Override public void begin(ReadWrite mode) { dataset.begin(mode); } - @Override public boolean promote() { return dataset.promote(); } - @Override public boolean promote(TxnType txnType) { return dataset.promote(txnType); } + @Override public boolean promote(Promote promote) { return dataset.promote(promote); } @Override public void commit() { dataset.commit(); } @Override public void abort() { dataset.abort(); } @Override public boolean isInTransaction() { return dataset.isInTransaction(); } http://git-wip-us.apache.org/repos/asf/jena/blob/5f99f5f3/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionModular.java ---------------------------------------------------------------------- diff --git a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionModular.java b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionModular.java index b6f215e..0cd85cc 100644 --- a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionModular.java +++ b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionModular.java @@ -37,8 +37,7 @@ public class RDFConnectionModular implements RDFConnection { @Override public void begin() { transactional.begin(); } @Override public void begin(TxnType txnType) { transactional.begin(txnType); } @Override public void begin(ReadWrite mode) { transactional.begin(mode); } - @Override public boolean promote() { return transactional.promote(); } - @Override public boolean promote(TxnType txnType) { return transactional.promote(txnType); } + @Override public boolean promote(Promote promote) { return transactional.promote(promote); } @Override public void commit() { transactional.commit(); } @Override public void abort() { transactional.abort(); } @Override public boolean isInTransaction() { return transactional.isInTransaction(); } http://git-wip-us.apache.org/repos/asf/jena/blob/5f99f5f3/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionRemote.java ---------------------------------------------------------------------- diff --git a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionRemote.java b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionRemote.java index 4960484..371945e 100644 --- a/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionRemote.java +++ b/jena-rdfconnection/src/main/java/org/apache/jena/rdfconnection/RDFConnectionRemote.java @@ -421,8 +421,7 @@ public class RDFConnectionRemote implements RDFConnection { @Override public void begin() { txn.begin(); } @Override public void begin(TxnType txnType) { txn.begin(txnType); } @Override public void begin(ReadWrite mode) { txn.begin(mode); } - @Override public boolean promote() { return txn.promote(); } - @Override public boolean promote(TxnType txnType) { return txn.promote(txnType); } + @Override public boolean promote(Promote promote) { return txn.promote(promote); } @Override public void commit() { txn.commit(); } @Override public void abort() { txn.abort(); } @Override public boolean isInTransaction() { return txn.isInTransaction(); } http://git-wip-us.apache.org/repos/asf/jena/blob/5f99f5f3/jena-sdb/src/main/java/org/apache/jena/sdb/store/DatasetGraphSDB.java ---------------------------------------------------------------------- diff --git a/jena-sdb/src/main/java/org/apache/jena/sdb/store/DatasetGraphSDB.java b/jena-sdb/src/main/java/org/apache/jena/sdb/store/DatasetGraphSDB.java index dda35e9..f85a159 100644 --- a/jena-sdb/src/main/java/org/apache/jena/sdb/store/DatasetGraphSDB.java +++ b/jena-sdb/src/main/java/org/apache/jena/sdb/store/DatasetGraphSDB.java @@ -117,8 +117,7 @@ public class DatasetGraphSDB extends DatasetGraphTriplesQuads @Override public void begin() { txn.begin(); } @Override public void begin(TxnType txnType) { txn.begin(txnType); } @Override public void begin(ReadWrite mode) { txn.begin(mode); } - @Override public boolean promote() { return txn.promote(); } - @Override public boolean promote(TxnType txnType) { return txn.promote(txnType); } + @Override public boolean promote(Promote txnType) { return txn.promote(txnType); } @Override public void commit() { txn.commit(); } @Override public void abort() { txn.abort(); } @Override public boolean isInTransaction() { return txn.isInTransaction(); } http://git-wip-us.apache.org/repos/asf/jena/blob/5f99f5f3/jena-tdb/src/main/java/org/apache/jena/tdb/store/DatasetGraphTDB.java ---------------------------------------------------------------------- diff --git a/jena-tdb/src/main/java/org/apache/jena/tdb/store/DatasetGraphTDB.java b/jena-tdb/src/main/java/org/apache/jena/tdb/store/DatasetGraphTDB.java index 13f8c18..f960e99 100644 --- a/jena-tdb/src/main/java/org/apache/jena/tdb/store/DatasetGraphTDB.java +++ b/jena-tdb/src/main/java/org/apache/jena/tdb/store/DatasetGraphTDB.java @@ -260,8 +260,7 @@ public class DatasetGraphTDB extends DatasetGraphTriplesQuads @Override public void begin() { txn.begin(); } @Override public void begin(TxnType txnType) { txn.begin(txnType); } @Override public void begin(ReadWrite mode) { txn.begin(mode); } - @Override public boolean promote() { return txn.promote(); } - @Override public boolean promote(TxnType txnType) { return txn.promote(txnType); } + @Override public boolean promote(Promote txnType) { return txn.promote(txnType); } @Override public void commit() { txn.commit(); } @Override public void abort() { txn.abort(); } @Override public boolean isInTransaction() { return txn.isInTransaction(); } http://git-wip-us.apache.org/repos/asf/jena/blob/5f99f5f3/jena-tdb/src/main/java/org/apache/jena/tdb/transaction/DatasetGraphTransaction.java ---------------------------------------------------------------------- diff --git a/jena-tdb/src/main/java/org/apache/jena/tdb/transaction/DatasetGraphTransaction.java b/jena-tdb/src/main/java/org/apache/jena/tdb/transaction/DatasetGraphTransaction.java index 5b77607..7eedb4e 100644 --- a/jena-tdb/src/main/java/org/apache/jena/tdb/transaction/DatasetGraphTransaction.java +++ b/jena-tdb/src/main/java/org/apache/jena/tdb/transaction/DatasetGraphTransaction.java @@ -93,19 +93,28 @@ import org.apache.jena.tdb.store.GraphTxnTDB ; DatasetGraphTxn dsgTxn = dsgtxn.get() ; if ( dsgTxn.getTransaction().isRead() ) { TxnType txnType = dsgTxn.getTransaction().getTxnType(); + Promote mode; switch(txnType) { case READ : throw new JenaTransactionException("Attempt to update in a read transaction"); case WRITE : // Impossible. We're in read-mode. throw new TDBException("Internal inconsistency: read-mode write transaction"); - case READ_COMMITTED_PROMOTE : case READ_PROMOTE : + mode = Promote.ISOLATED; + break; + case READ_COMMITTED_PROMOTE : + mode = Promote.READ_COMMITTED; + break; + default: + throw new TDBException("Internal inconsistency: null transaction type"); } // Promotion. TransactionManager txnMgr = dsgTxn.getTransaction().getTxnMgr() ; - DatasetGraphTxn dsgTxn2 = txnMgr.promote(dsgTxn, txnType) ; + DatasetGraphTxn dsgTxn2 = txnMgr.promote(dsgTxn, txnType, mode) ; if ( dsgTxn2 == null ) + // We were asked for a write operation and can't promote. + // Returning false makes no sense. throw new JenaTransactionException("Can't promote "+txnType+"- dataset has been written to"); dsgtxn.set(dsgTxn2); } @@ -206,12 +215,12 @@ import org.apache.jena.tdb.store.GraphTxnTDB ; } @Override - protected boolean _promote() { + protected boolean _promote(Promote promoteMode) { // Promotion (TDB1) is a reset of the DatasetGraphTxn. checkNotClosed() ; DatasetGraphTxn dsgTxn = dsgtxn.get(); Transaction transaction = dsgTxn.getTransaction(); - DatasetGraphTxn dsgTxn2 = transaction.getTxnMgr().promote(dsgTxn, transaction.getTxnType()); + DatasetGraphTxn dsgTxn2 = transaction.getTxnMgr().promote(dsgTxn, transaction.getTxnType(), promoteMode); if ( dsgTxn2 == null ) return false; dsgtxn.set(dsgTxn2) ; http://git-wip-us.apache.org/repos/asf/jena/blob/5f99f5f3/jena-tdb/src/main/java/org/apache/jena/tdb/transaction/TransactionManager.java ---------------------------------------------------------------------- diff --git a/jena-tdb/src/main/java/org/apache/jena/tdb/transaction/TransactionManager.java b/jena-tdb/src/main/java/org/apache/jena/tdb/transaction/TransactionManager.java index e9c4797..448c99c 100644 --- a/jena-tdb/src/main/java/org/apache/jena/tdb/transaction/TransactionManager.java +++ b/jena-tdb/src/main/java/org/apache/jena/tdb/transaction/TransactionManager.java @@ -24,7 +24,10 @@ import static org.apache.jena.tdb.transaction.TransactionManager.TxnPoint.BEGIN import static org.apache.jena.tdb.transaction.TransactionManager.TxnPoint.CLOSE ; import java.io.File ; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Set; import java.util.concurrent.BlockingQueue ; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.LinkedBlockingDeque ; @@ -39,6 +42,7 @@ import org.apache.jena.atlas.logging.Log ; import org.apache.jena.query.ReadWrite ; import org.apache.jena.query.TxnType; import org.apache.jena.shared.Lock ; +import org.apache.jena.sparql.core.Transactional.Promote; import org.apache.jena.tdb.store.DatasetGraphTDB ; import org.apache.jena.tdb.sys.SystemTDB ; import org.slf4j.Logger ; @@ -375,24 +379,24 @@ public class TransactionManager * <p> * Return null for "no promote" due to intermediate commits. */ - /*package*/ DatasetGraphTxn promote(DatasetGraphTxn dsgtxn, TxnType txnType) throws TDBTransactionException { + /*package*/ DatasetGraphTxn promote(DatasetGraphTxn dsgtxn, TxnType originalTxnType, Promote promoteType) throws TDBTransactionException { Transaction txn = dsgtxn.getTransaction() ; if ( txn.getState() != TxnState.ACTIVE ) throw new TDBTransactionException("promote: transaction is not active") ; if ( txn.getTxnMode() == ReadWrite.WRITE ) return dsgtxn ; - if ( txn.getTxnType() == TxnType.READ ) { - txn.abort(); - throw new TDBTransactionException("promote: transaction is a READ transaction") ; - } + if ( txn.getTxnType() == TxnType.READ ) + return null; // Did no promote. + //txn.abort(); + //throw new TDBTransactionException("promote: transaction is a READ transaction") ; // Read commit - pick up whatever is current at the point setup. // Can also promote - may need to wait for active writers. // Go through begin for the writers lock. - if ( txnType == TxnType.READ_COMMITTED_PROMOTE ) { + if ( promoteType == Promote.READ_COMMITTED ) { acquireWriterLock(true); // No need to sync - we just queue as a writer. - return promoteExec$(dsgtxn, txnType); + return promoteExec$(dsgtxn, originalTxnType); } // First check, without the writer lock. Fast fail. @@ -414,7 +418,7 @@ public class TransactionManager // can commit/abort. Otherwise, we have deadlock. acquireWriterLock(true) ; // Do the synchronized stuff. - return promoteSync$(dsgtxn, txnType) ; + return promoteSync$(dsgtxn, originalTxnType) ; } synchronized http://git-wip-us.apache.org/repos/asf/jena/blob/5f99f5f3/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 2ccd2f8..8b8df56 100644 --- a/pom.xml +++ b/pom.xml @@ -735,6 +735,7 @@ <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> + <showDeprecation>false</showDeprecation> <encoding>UTF-8</encoding> <debug>true</debug> <debuglevel>source,lines,vars</debuglevel>