From: <tho...@us...> - 2012-06-25 15:41:08
|
Revision: 6356 http://bigdata.svn.sourceforge.net/bigdata/?rev=6356&view=rev Author: thompsonbry Date: 2012-06-25 15:41:02 +0000 (Mon, 25 Jun 2012) Log Message: ----------- Mike has been reporting significant performance improvements associated with the use of the POS index for point tests on fully bound access paths for triple patterns such as "P??" and "PO?". The rationale for improved performance is that the index accesses are concentrated in the same region of the index because the P is a constant in this triple pattern. Historically, we have been using SPO (or SPOC for quads) whenever the predicate became fully bound during query evaluation (as a result of the propagation of variable bindings from solutions). After talking this through with Mike, we have decided to change the code in SPOKeyOrder#getKeyOrder()/2 to use the index associated with the original triple pattern rather than the SPO/SPOC index. The ASTStaticJoinOptimizer currently annotations the predicates with AST2BOpBase.Annotations.ORIGINAL_INDEX. This is the index associated with the original triple or quad pattern without regard to any propagation of variable bindings. Therefore, I have modified SPOKeyOrder#getKeyOrder()/2 to use this ORIGINAL_INDEX annotation (if present) when the predicate is fully bound during evaluation and to default to the SPO / SPOC index if the predicate is fully bound by the ORIGINAL_INDEX annotation is not present. The only drawback with this approach is that the ORIGINAL_INDEX annotation is not present if the static join order optimizer is disabled. However, the ORIGINAL_INDEX annotation COULD be lifted into another ASTOptimizer in order to guarantee that it is always predicate. Since point tests can now occur against any statement index, I also modified SPORelation#getStatementIndexMetadata() to enable the bloom filter for ALL statement indices, not just SPO. Also, through an oversight, we were not enabling the bloom filter for ANY of the statement indices in quads mode. It is now enabled it both triples and quads modes. Changes to SPOKeyOrder#getKeyOrder()/2 and SPORelation#getStatementIndexMetadata(). @see https://sourceforge.net/apps/trac/bigdata/ticket/150 (choosing the index for testing fully bound access paths based on index locality) Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/IPredicate.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPOKeyOrder.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPORelation.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/IPredicate.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/IPredicate.java 2012-06-22 18:23:43 UTC (rev 6355) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/IPredicate.java 2012-06-25 15:41:02 UTC (rev 6356) @@ -500,7 +500,7 @@ * query optimizer. * * @return The assigned {@link IKeyOrder} or <code>null</code> if the - * {@link IKeyOrder} was not overriden. + * {@link IKeyOrder} was not overridden. * * @see Annotations#KEY_ORDER */ Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPOKeyOrder.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPOKeyOrder.java 2012-06-22 18:23:43 UTC (rev 6355) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPOKeyOrder.java 2012-06-25 15:41:02 UTC (rev 6356) @@ -46,7 +46,9 @@ import com.bigdata.rdf.internal.IVUtility; import com.bigdata.rdf.internal.constraints.RangeBOp; import com.bigdata.rdf.model.StatementEnum; +import com.bigdata.rdf.sparql.ast.eval.AST2BOpBase; import com.bigdata.striterator.AbstractKeyOrder; +import com.bigdata.striterator.IKeyOrder; /** * Represents the key order used by an index for a triple relation. @@ -876,6 +878,10 @@ * the keyArity parameter. That parameter is only there because we * support two distinct families of natural orders in this class: one * for triples and one for quads. + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/150" > + * Choosing the index for testing fully bound access paths based on + * index locality</a> */ static public SPOKeyOrder getKeyOrder(final IPredicate<ISPO> predicate, final int keyArity) { @@ -906,7 +912,24 @@ // Note: Context is ignored! if (s && p && o) { - return SPO; + + /* + * If the access path is all bound, then we want to use the + * index associated with the original predicate (which typically + * had variables in one or more positions). This index will have + * better locality since it will naturally group the index + * accesses in the same region of the index. + * + * @see https://sourceforge.net/apps/trac/bigdata/ticket/150 + * (chosing the index for testing fully bound access paths based + * on index locality) + */ + + final SPOKeyOrder tmp = predicate.getProperty( + AST2BOpBase.Annotations.ORIGINAL_INDEX, SPO); + + return tmp; // SPO + } else if (s && p) { return SPO; } else if (s && o) { @@ -956,8 +979,23 @@ return SOPC; } - return SPOC; + /* + * If the access path is all bound, then we want to use the + * index associated with the original predicate (which typically + * had variables in one or more positions). This index will have + * better locality since it will naturally group the index + * accesses in the same region of the index. + * + * @see https://sourceforge.net/apps/trac/bigdata/ticket/150 + * (chosing the index for testing fully bound access paths based + * on index locality) + */ + final SPOKeyOrder tmp = predicate.getProperty( + AST2BOpBase.Annotations.ORIGINAL_INDEX, SPOC); + + return tmp;// SPOC; + } } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPORelation.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPORelation.java 2012-06-22 18:23:43 UTC (rev 6355) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPORelation.java 2012-06-25 15:41:02 UTC (rev 6356) @@ -652,6 +652,10 @@ /** * Overrides for the statement indices. + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/150" > + * Choosing the index for testing fully bound access paths based on + * index locality</a> */ protected IndexMetadata getStatementIndexMetadata(final SPOKeyOrder keyOrder) { @@ -714,19 +718,48 @@ } - if (bloomFilter && keyOrder.equals(SPOKeyOrder.SPO)) { + if (bloomFilter) {// && keyOrder.equals(SPOKeyOrder.SPO)) { +// * Enable the bloom filter for the SPO index only. +// * +// * Note: This SPO index is used any time we have an access path that +// * is a point test. Therefore this is the only index for which it +// * makes sense to maintain a bloom filter. + /* - * Enable the bloom filter for the SPO index only. + * Enable the bloom filter. * - * Note: This SPO index is used any time we have an access path that - * is a point test. Therefore this is the only index for which it - * makes sense to maintain a bloom filter. + * Historically, the bloom filter was only enabled in for the SPO + * index because the SPO index was always used for a point test. + * Further, by oversight, it was never enabled for a quads mode KB + * instance. However, in order to improve the locality of reference + * for point tests, the SPOKeyOrder#getKeyOrder() method was + * modified to use the index which would be used if we evaluated the + * original predicate rather than the "as-bound" predicate. This + * change provides better locality of access since the variables + * indicate the region of variability in the index while the + * constants indicate the region of locality. Therefore, fully bound + * (aka point tests) can now occur on ANY statement index and the + * bloom filter is now enabled on all statement indices. * + * @see https://sourceforge.net/apps/trac/bigdata/ticket/150 + * (chosing the index for testing fully bound access paths based on + * index locality) + */ + + /* * Note: The maximum error rate (maxP) applies to the mutable BTree * only. For scale-out indices, there is one mutable BTree per index * partition and a new (empty) BTree is allocated each time the live * journal for the index partitions overflows. + * + * Note: The bloom filter is disabled once the error rate grows too + * large. However, in scale-out, we are able to put a perfect fit + * bloom filter in each index segment. This can significantly reduce + * the IO costs associated with point tests. This can not be done in + * the single machine database mode because the error rate of the + * bloom filter is a function of the size of the bloom filter and + * the #of entries in the index. */ // // good performance up to ~2M triples. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2012-06-28 12:03:58
|
Revision: 6366 http://bigdata.svn.sourceforge.net/bigdata/?rev=6366&view=rev Author: thompsonbry Date: 2012-06-28 12:03:47 +0000 (Thu, 28 Jun 2012) Log Message: ----------- The root cause is that the GRAPH clause within a QuadData pattern was not being translated into a JoinGroupNode. However, the QuadData AST node is not legal within a WHERE clause. The fix was to translate the QuadData into an appropriate JoinGroupNode when building the group for the WHERE clause in the parser. @see https://sourceforge.net/apps/trac/bigdata/ticket/568 (DELETE WHERE fails with Java AssertionError) Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/QuadData.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/sparql/GroupGraphPattern.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/sparql/UpdateExprBuilder.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/sparql/TestUpdateExprBuilder.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/org/openrdf/query/parser/sparql/SPARQLUpdateTest.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/QuadData.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/QuadData.java 2012-06-27 17:41:16 UTC (rev 6365) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/QuadData.java 2012-06-28 12:03:47 UTC (rev 6366) @@ -30,6 +30,9 @@ import java.util.Iterator; import java.util.Map; +import org.openrdf.query.algebra.StatementPattern; +import org.openrdf.query.algebra.StatementPattern.Scope; + import com.bigdata.bop.BOp; import com.bigdata.bop.BOpUtility; import com.bigdata.rdf.spo.ISPO; @@ -84,12 +87,15 @@ * {@link ConstructNode} MAY use variables as well as constants and supports * the context position, so this is really a quads construct template. * - * TODO Maybe we could just flatten this in UpdateExprBuilder? + * @param template + * The {@link ConstructNode} for the template. + * + * @return The argument. + * + * TODO Maybe we could just flatten this in UpdateExprBuilder? */ - public ConstructNode flatten() { + public ConstructNode flatten(final ConstructNode template) { - final ConstructNode template = new ConstructNode(); - final QuadData quadData = this; final Iterator<StatementPatternNode> itr = BOpUtility.visitAll( @@ -107,7 +113,56 @@ return template; } + + /** + * Flatten the {@link StatementPatternNode}s into the caller's + * {@link JoinGroupNode}. + * + * @param container + * The caller's container. + * + * @return The caller's container. + */ + public JoinGroupNode flatten(final JoinGroupNode container) { + final QuadData quadData = this; + + final Iterator<StatementPatternNode> itr = BOpUtility.visitAll( + quadData, StatementPatternNode.class); + + while (itr.hasNext()) { + + final StatementPatternNode sp = (StatementPatternNode) (itr.next() + .clone()); + +// if (sp.getScope() == Scope.NAMED_CONTEXTS) { +// +// /* +// * Statement pattern must be in a GRAPH group. +// * +// * TODO We should coalesce statement patterns which are observed +// * to be in the same graph group (same constant or the same +// * variable). Note that the lexical scope is not an issue for +// * the QuadsData - there are no nested sub-groups or +// * sub-selects. +// */ +// +// container.addChild(new JoinGroupNode(sp.getContext(), sp)); +// +// } else { +// +// container.addChild(sp); +// +// } + + container.addChild(sp); + + } + + return container; + + } + @Override public String toString(final int indent) { Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java 2012-06-27 17:41:16 UTC (rev 6365) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java 2012-06-28 12:03:47 UTC (rev 6366) @@ -717,7 +717,7 @@ */ final ConstructNode template = op.getDeleteClause() - .getQuadData().flatten(); + .getQuadData().flatten(new ConstructNode()); final ASTConstructIterator itr = new ASTConstructIterator( context.conn.getTripleStore(), template, @@ -785,7 +785,7 @@ */ final ConstructNode template = op.getInsertClause() - .getQuadData().flatten(); + .getQuadData().flatten(new ConstructNode()); final ASTConstructIterator itr = new ASTConstructIterator( context.conn.getTripleStore(), template, @@ -891,7 +891,10 @@ final QuadData quadData = (insertClause == null ? deleteClause : insertClause).getQuadData(); - final ConstructNode template = quadData.flatten(); + // Flatten the original WHERE clause into a CONSTRUCT + // template. + final ConstructNode template = quadData + .flatten(new ConstructNode()); // Set the CONSTRUCT template (quads patterns). queryRoot.setConstruct(template); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/sparql/GroupGraphPattern.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/sparql/GroupGraphPattern.java 2012-06-27 17:41:16 UTC (rev 6365) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/sparql/GroupGraphPattern.java 2012-06-28 12:03:47 UTC (rev 6366) @@ -34,6 +34,7 @@ import org.apache.log4j.Logger; import org.openrdf.query.algebra.StatementPattern; +import org.openrdf.query.algebra.StatementPattern.Scope; import com.bigdata.bop.BOp; import com.bigdata.bop.BOpUtility; @@ -41,6 +42,7 @@ import com.bigdata.rdf.sparql.ast.GroupNodeBase; import com.bigdata.rdf.sparql.ast.IGroupMemberNode; import com.bigdata.rdf.sparql.ast.JoinGroupNode; +import com.bigdata.rdf.sparql.ast.QuadData; import com.bigdata.rdf.sparql.ast.StatementPatternNode; import com.bigdata.rdf.sparql.ast.TermNode; import com.bigdata.rdf.sparql.ast.UnionNode; @@ -265,8 +267,48 @@ for (IGroupMemberNode child : children) { - groupNode.addChild(child); + if (child instanceof QuadData + && groupNode instanceof JoinGroupNode) { + + /* + * We need to flatten out the QuadData when it appears + * within a WHERE clause for a DELETE WHERE shortcut. + * + * @see https://sourceforge.net/apps/trac/bigdata/ticket/568 + * (DELETE WHERE fails with Java AssertionError) + */ + + final JoinGroupNode newGroup = new JoinGroupNode(); + ((QuadData) child).flatten(newGroup); + + // A statement pattern node from the nested GRAPH group. + // They will all share the same context. + + final StatementPatternNode sp = (StatementPatternNode) newGroup + .get(0); + + // The context for the SPs in that GRAPH group. + final TermNode context = (TermNode) sp.get(3); + + // Must be defined. + assert context != null; + + // Must be a named graph scope. + assert sp.getScope() == Scope.NAMED_CONTEXTS; + + // Set on the new group. + newGroup.setContext(context); + + // Add the new group to the outer group. + groupNode.addChild(newGroup); + + } else { + + groupNode.addChild(child); + + } + } } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/sparql/UpdateExprBuilder.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/sparql/UpdateExprBuilder.java 2012-06-27 17:41:16 UTC (rev 6365) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/sparql/UpdateExprBuilder.java 2012-06-28 12:03:47 UTC (rev 6366) @@ -196,6 +196,15 @@ * This is similar to a CONSTRUCT without an explicit template. The WHERE * clause provides both the pattern to match and the template for the quads * to be removed. + * <p> + * Note: The grammar production for the WHERE clause for the DELETE WHERE + * shortcut form is the same production that is used for the DELETE and + * INSERT clauses. This results in a {@link QuadData} object containing + * {@link StatementPatternNode}s. That object must be transformed into a + * {@link JoinGroupNode} in order to be valid as a WHERE clause. + * + * @see https://sourceforge.net/apps/trac/bigdata/ticket/568 (DELETE WHERE + * fails with Java AssertionError) */ @Override public DeleteInsertGraph visit(final ASTDeleteWhere node, final Object data) Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/sparql/TestUpdateExprBuilder.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/sparql/TestUpdateExprBuilder.java 2012-06-27 17:41:16 UTC (rev 6365) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/sparql/TestUpdateExprBuilder.java 2012-06-28 12:03:47 UTC (rev 6366) @@ -2325,6 +2325,7 @@ } /** + * A unit test for the DELETE WHERE "shortcut" form. * <pre> * DELETE WHERE {?x foaf:name ?y } * </pre> @@ -2364,6 +2365,110 @@ } + /** + * A unit test for the DELETE WHERE "shortcut" form. + * <pre> + * DELETE WHERE { GRAPH ?g { ?x foaf:name ?y } } + * </pre> + * + * @see https://sourceforge.net/apps/trac/bigdata/ticket/568 (DELETE WHERE + * fails with Java AssertionError) + */ + public void test_delete_where_02() throws MalformedQueryException, + TokenMgrError, ParseException { + + final String sparql = "DELETE WHERE { GRAPH ?g { ?x <http://xmlns.com/foaf/0.1/name> ?y } }"; + + @SuppressWarnings("rawtypes") + final IV foafName = makeIV(valueFactory + .createURI("http://xmlns.com/foaf/0.1/name")); + + final UpdateRoot expected = new UpdateRoot(); + { + + final DeleteInsertGraph op = new DeleteInsertGraph(); + + expected.addChild(op); + + { + + final JoinGroupNode whereClause = new JoinGroupNode(); + + final JoinGroupNode graphClause = new JoinGroupNode(); + + graphClause.setContext(new VarNode("g")); + + whereClause.addChild(graphClause); + + graphClause.addChild(new StatementPatternNode(new VarNode("x"), + new ConstantNode(foafName), new VarNode("y"), + new VarNode("g"), Scope.NAMED_CONTEXTS)); + + op.setWhereClause(whereClause); + + } + + } + + final UpdateRoot actual = parseUpdate(sparql, baseURI); + + assertSameAST(sparql, expected, actual); + + } + + /** + * A unit test for the DELETE WHERE form without the shortcut, but + * there the template and the where clause are the same. + * <pre> + * DELETE {?x foaf:name ?y } WHERE {?x foaf:name ?y } + * </pre> + */ + public void test_delete_where_without_shortcut_02() throws MalformedQueryException, + TokenMgrError, ParseException { + + final String sparql = "DELETE {?x <http://xmlns.com/foaf/0.1/name> ?y}\n" + + " WHERE {?x <http://xmlns.com/foaf/0.1/name> ?y }"; + + @SuppressWarnings("rawtypes") + final IV foafName = makeIV(valueFactory + .createURI("http://xmlns.com/foaf/0.1/name")); + + final UpdateRoot expected = new UpdateRoot(); + { + + final DeleteInsertGraph op = new DeleteInsertGraph(); + + expected.addChild(op); + + { + + final QuadData deleteClause = new QuadData(); + + deleteClause.addChild(new StatementPatternNode(new VarNode("x"), + new ConstantNode(foafName), new VarNode("y"))); + + op.setDeleteClause(new QuadsDataOrNamedSolutionSet(deleteClause)); + + } + { + + final JoinGroupNode whereClause = new JoinGroupNode(); + + whereClause.addChild(new StatementPatternNode(new VarNode("x"), + new ConstantNode(foafName), new VarNode("y"))); + + op.setWhereClause(whereClause); + + } + + } + + final UpdateRoot actual = parseUpdate(sparql, baseURI); + + assertSameAST(sparql, expected, actual); + + } + /** * A sequences of DELETE/INSERT operations with different data sets and no * WITH clause. Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/org/openrdf/query/parser/sparql/SPARQLUpdateTest.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/org/openrdf/query/parser/sparql/SPARQLUpdateTest.java 2012-06-27 17:41:16 UTC (rev 6365) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/org/openrdf/query/parser/sparql/SPARQLUpdateTest.java 2012-06-28 12:03:47 UTC (rev 6366) @@ -243,6 +243,12 @@ assertFalse(message, con.hasStatement(alice, RDFS.LABEL, f.createLiteral("Alice"), true, graph1)); } + /** + * <pre> + * DELETE WHERE {?x foaf:name ?y } + * </pre> + * @throws Exception + */ //@Test public void testDeleteWhereShortcut() throws Exception @@ -269,7 +275,48 @@ assertTrue(msg, con.hasStatement(alice, FOAF.KNOWS, null, true)); } - //@Test + /** + * <pre> + * DELETE WHERE {GRAPH ?g {?x foaf:name ?y} } + * </pre> + * + * @see https://sourceforge.net/apps/trac/bigdata/ticket/568 (DELETE WHERE + * fails with Java AssertionError) + */ + //@Test + public void testDeleteWhereShortcut2() + throws Exception + { + + logger.debug("executing testDeleteWhereShortcut2"); + + StringBuilder update = new StringBuilder(); + update.append(getNamespaceDeclarations()); + update.append("DELETE WHERE { GRAPH ?g {?x foaf:name ?y } }"); + + Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); + + assertTrue(con.hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); + assertTrue(con.hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); + + operation.execute(); + + String msg = "foaf:name properties should have been deleted"; + assertFalse(msg, con.hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); + assertFalse(msg, con.hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); + + msg = "foaf:knows properties should not have been deleted"; + assertTrue(msg, con.hasStatement(bob, FOAF.KNOWS, null, true)); + assertTrue(msg, con.hasStatement(alice, FOAF.KNOWS, null, true)); + + } + + /** + * <pre> + * DELETE {?x foaf:name ?y } WHERE {?x foaf:name ?y } + * </pre> + */ + //@Test public void testDeleteWhere() throws Exception { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2012-06-28 18:07:02
|
Revision: 6370 http://bigdata.svn.sourceforge.net/bigdata/?rev=6370&view=rev Author: thompsonbry Date: 2012-06-28 18:06:53 +0000 (Thu, 28 Jun 2012) Log Message: ----------- A further refactoring of the IRWStore and related interfaces. Several bugs were identified with respect to the RWStrategy and MemStrategy where logic was testing on RWStrategy rather than IRWStrategy. This would have caused memory leaks against the MemoryManager when wrapped as a MemStrategy by a Journal. Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/BTree.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/AbstractBufferStrategy.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/AbstractJournal.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/DiskOnlyStrategy.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/DumpJournal.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/IBufferStrategy.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/RWStrategy.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/VerifyCommitRecordIndex.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/WORMStrategy.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rawstore/IAddressManager.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/IHistoryManager.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/IRWStrategy.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/IStore.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/RWStore.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/AllocationContext.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/IMemoryManager.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/MemStore.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/MemStrategy.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/MemoryManager.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/SectorAllocator.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/rwstore/TestRWJournal.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/ISparqlCache.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/SolutionSetMetadata.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/SparqlCache.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/store/DataLoader.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/BigdataSail.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/BigdataSailRepositoryConnection.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFContext.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/samples/com/bigdata/samples/LoadNamedGraphs.java branches/BIGDATA_RELEASE_1_2_0/build.xml Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/BTree.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/BTree.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/BTree.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -47,6 +47,7 @@ import com.bigdata.mdi.LocalPartitionMetadata; import com.bigdata.rawstore.Bytes; import com.bigdata.rawstore.IRawStore; +import com.bigdata.rwstore.IRWStrategy; /** * <p> @@ -1273,7 +1274,7 @@ * FIXME simplify conditionals - mgc */ if (!getIndexMetadata().getDeleteMarkers() - && getStore() instanceof RWStrategy) { + && getStore() instanceof IRWStrategy) { /* * Per https://sourceforge.net/apps/trac/bigdata/ticket/221, we @@ -1333,7 +1334,7 @@ replaceRootWithEmptyLeaf(); } else if (getIndexMetadata().getDeleteMarkers() - || getStore() instanceof RWStrategy// + || getStore() instanceof IRWStrategy// || metadata.getRawRecords()// ) { Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/AbstractBufferStrategy.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/AbstractBufferStrategy.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/AbstractBufferStrategy.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -602,7 +602,8 @@ } /** The default is a NOP. */ - public void commit(IJournal journal) { + @Override + public void commit() { // NOP for WORM. } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/AbstractJournal.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/AbstractJournal.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -902,7 +902,8 @@ case MemStore: { _bufferStrategy = new MemStrategy(new MemoryManager( - DirectBufferPool.INSTANCE), properties); + DirectBufferPool.INSTANCE, + Integer.MAX_VALUE/* maxSectors */, properties)); break; @@ -2558,7 +2559,7 @@ * until commit, leading to invalid addresses for recent store * allocations. */ - _bufferStrategy.commit(this); + _bufferStrategy.commit(); /* * next offset at which user data would be written. Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/DiskOnlyStrategy.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/DiskOnlyStrategy.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/DiskOnlyStrategy.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -483,7 +483,8 @@ * Note that the internal call to flush the writeCache must be synchronized * or concurrent writers to the cache will cause problems. */ - public void commit(IJournal journal) { + @Override + public void commit() { if (writeCache != null) { synchronized(this) { flushWriteCache(); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/DumpJournal.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/DumpJournal.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/DumpJournal.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -268,7 +268,7 @@ if (strategy instanceof RWStrategy) { - final RWStore store = ((RWStrategy) strategy).getRWStore(); + final RWStore store = ((RWStrategy) strategy).getStore(); final StringBuilder sb = new StringBuilder(); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/IBufferStrategy.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/IBufferStrategy.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/IBufferStrategy.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -220,10 +220,8 @@ * must be managed as part of the protocol outside of the RootBlock, and * this is the method that triggers that management. The caller MUST provide * appropriate synchronization. - * - * @param abstractJournal */ - public void commit(IJournal journal); + public void commit(); /** * A method that requires the implementation to discard its buffered write Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/RWStrategy.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/RWStrategy.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/RWStrategy.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -78,7 +78,8 @@ * * @author Martyn Cutcher */ -public class RWStrategy extends AbstractRawStore implements IBufferStrategy, IHABufferStrategy, IRWStrategy { +public class RWStrategy extends AbstractRawStore implements IBufferStrategy, + IHABufferStrategy, IRWStrategy { private static final transient Logger log = Logger.getLogger(RWStrategy.class); @@ -427,9 +428,10 @@ } - public void commit(final IJournal journal) { + @Override + public void commit() { - m_store.commitChanges((Journal) journal); // includes a force(false) + m_store.commit(); } @@ -587,17 +589,24 @@ } - /** - * Used for unit tests, could also be used to access raw statistics. - * - * @return the associated RWStore - */ - public RWStore getRWStore() { - - return m_store; - - } +// /** +// * Used for unit tests, could also be used to access raw statistics. +// * +// * @return the associated RWStore +// */ +// @Deprecated +// public RWStore getRWStore() { +// +// return m_store; +// +// } + public RWStore getStore() { + + return m_store; + + } + public long getPhysicalAddress(final long addr) { final int rwaddr = decodeAddr(addr); @@ -671,14 +680,15 @@ return true; } - /** - * If history is retained this returns the time for which - * data was most recently released. No request can be made for data - * earlier than this. - * @return latest data release time - */ +// /** +// * If history is retained this returns the time for which +// * data was most recently released. No request can be made for data +// * earlier than this. +// * @return latest data release time +// */ + @Override public long getLastReleaseTime() { - return m_store.getLastDeferredReleaseTime(); + return m_store.getLastReleaseTime(); } /** Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/VerifyCommitRecordIndex.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/VerifyCommitRecordIndex.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/VerifyCommitRecordIndex.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -32,10 +32,6 @@ import com.bigdata.btree.IIndex; import com.bigdata.btree.IndexMetadata; -import com.bigdata.journal.BufferMode; -import com.bigdata.journal.Journal; -import com.bigdata.journal.Options; -import com.bigdata.journal.RWStrategy; import com.bigdata.rwstore.RWStore; /** @@ -79,7 +75,7 @@ } final RWStrategy rwstrategy = (RWStrategy) jrnl.getBufferStrategy(); - final RWStore rwstore = rwstrategy.getRWStore(); + final RWStore rwstore = rwstrategy.getStore(); final IIndex commitRecordIndex = jrnl.getReadOnlyCommitRecordIndex(); if (commitRecordIndex == null) { @@ -94,7 +90,7 @@ .serializeKey(0L); final byte[] releaseKey = metadata.getTupleSerializer() - .serializeKey( rwstore.getLastDeferredReleaseTime()); + .serializeKey( rwstore.getLastReleaseTime()); final int removed = jrnl.removeCommitRecordEntries(zeroKey, releaseKey); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/WORMStrategy.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/WORMStrategy.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/WORMStrategy.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -1048,13 +1048,15 @@ } /** - * Flushes the write cache (if enabled). + * {@inheritDoc} + * <p> + * This implementation flushes the write cache (if enabled). * * @todo Should be a NOP for the WORM? Check * {@link AbstractJournal#commitNow(long)} */ @Override - public void commit(IJournal journal) { + public void commit() { flushWriteCache(); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rawstore/IAddressManager.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rawstore/IAddressManager.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rawstore/IAddressManager.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -144,11 +144,14 @@ */ public String toString(long addr); - /** + /** * Determine the unencoded physical address - * @param addr - the encoded address + * + * @param addr + * The encoded address + * * @return an unencoded address offset */ - public long getPhysicalAddress(long addr); + public long getPhysicalAddress(long addr); } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/IHistoryManager.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/IHistoryManager.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/IHistoryManager.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -93,4 +93,12 @@ ConcurrentWeakValueCache<Long, ICommitter> historicalIndexCache, int byteCount); + /** + * If history is retained this returns the time for which data was most + * recently released. No request can be made for data earlier than this. + * + * @return latest data release time + */ + public long getLastReleaseTime(); + } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/IRWStrategy.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/IRWStrategy.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/IRWStrategy.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -1,12 +1,6 @@ package com.bigdata.rwstore; -import java.io.InputStream; -import java.nio.ByteBuffer; - -import com.bigdata.cache.ConcurrentWeakValueCache; -import com.bigdata.journal.AbstractJournal; import com.bigdata.journal.IBufferStrategy; -import com.bigdata.journal.ICommitter; /** * Defines a marker interface to be used to indicate strategies @@ -21,6 +15,11 @@ public interface IRWStrategy extends IBufferStrategy, IAllocationManager, IAllocationManagerStore, IStreamStore, IHistoryManager { + /** + * Return the backing {@link IStore}. + */ + IStore getStore(); + // /** // * @return IRawTx to enable activate/deactvate // */ @@ -73,10 +72,13 @@ // */ // int checkDeferredFrees(AbstractJournal abstractJournal); - /** - * Checked by AbstractJournal for index validation - */ - long getLastReleaseTime(); +// /** +// * If history is retained this returns the time for which data was most +// * recently released. No request can be made for data earlier than this. +// * +// * @return latest data release time +// */ +// long getLastReleaseTime(); /** * Return <code>true</code> iff the allocation having that address is Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/IStore.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/IStore.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/IStore.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -46,13 +46,21 @@ public long alloc(byte buf[], int size, IAllocationContext context); /** - * Frees allocated storage + * Frees allocated storage (clears the bit to enable recycling after + * the next commit). * * @param addr * the storage address to be freed */ public void free(long addr, int size); + /** + * Global commit on the backing store. Previously committed data which has + * been marked as {@link #free(long, int)} is now available for recycling. + * However, recycling can not occur if session protection is active. + */ + public void commit(); + // /************************************************************** // * Odd method needed by PSInputStream to fetch data of unknown // * size into a buffer @@ -122,7 +130,7 @@ * @return the File object */ public File getStoreFile(); - + // /** // * Called by the PSOutputStream to register the header block of a blob. The // * store must return a new address that is used to retrieve the blob header. Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/RWStore.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/RWStore.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/RWStore.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -47,7 +47,6 @@ import org.apache.log4j.Logger; -import com.bigdata.btree.BTree; import com.bigdata.btree.BTree.Counter; import com.bigdata.btree.IIndex; import com.bigdata.btree.ITuple; @@ -1474,7 +1473,7 @@ free(laddr, sze, null/* AlocationContext */); } - private long m_unsafeFrees = 0; +// private long m_unsafeFrees = 0; /** * free * <p> @@ -1588,7 +1587,7 @@ * either a positive activeTxCount incremented by the TransactionManager * or if there are active AllocationContexts. * - * The activeTxCount esentially protects read-only transactions while the + * The activeTxCount essentially protects read-only transactions while the * AllocationContexts enable concurrent store allocations, whilst also * supporting immediate re-cycling of localized allocations (those made * and released within the same AllocationContext). @@ -2151,7 +2150,7 @@ // return "RWStore " + s_version; // } - public void commitChanges(final AbstractJournal journal) { + public void commit() { assertOpen(); checkCoreAllocations(); @@ -2167,13 +2166,13 @@ // } // free old storageStatsAddr if (m_storageStatsAddr != 0) { - int len = (int) (m_storageStatsAddr & 0xFFFF); - int addr = (int) (m_storageStatsAddr >> 16); - immediateFree(addr, len); + final int len = (int) (m_storageStatsAddr & 0xFFFF); + final int addr = (int) (m_storageStatsAddr >> 16); + immediateFree(addr, len); } if (m_storageStats != null) { - byte[] buf = m_storageStats.getData(); - long addr = alloc(buf, buf.length, null); + final byte[] buf = m_storageStats.getData(); + final long addr = alloc(buf, buf.length, null); m_storageStatsAddr = (addr << 16) + buf.length; } @@ -2827,6 +2826,7 @@ * <dt>%StoreFile</dt><dd>How much of the backing file is reserved for each allocator (BytesReserved/Sum(BytesReserved)).</dd> * <dt>%StoreWaste</dt><dd>How much of the total waste on the store is waste for this allocator size ((BytesReserved-BytesAppData)/(Sum(BytesReserved)-Sum(BytesAppData))).</dd> * </dl> + * @see StorageStats#showStats(StringBuilder) */ public void showAllocators(final StringBuilder str) { m_storageStats.showStats(str); @@ -2886,32 +2886,32 @@ // str.append("\nFile size: " + convertAddr(m_fileSize) + "bytes\n"); } - private String padLeft(String str, int minlen) { - if (str.length() >= minlen) - return str; - - StringBuffer out = new StringBuffer(); - int pad = minlen - str.length(); - while (pad-- > 0) { - out.append(' '); - } - out.append(str); - - return out.toString(); - } - private String padRight(String str, int minlen) { - if (str.length() >= minlen) - return str; - - StringBuffer out = new StringBuffer(); - out.append(str); - int pad = minlen - str.length(); - while (pad-- > 0) { - out.append(' '); - } - - return out.toString(); - } +// private String padLeft(String str, int minlen) { +// if (str.length() >= minlen) +// return str; +// +// StringBuffer out = new StringBuffer(); +// int pad = minlen - str.length(); +// while (pad-- > 0) { +// out.append(' '); +// } +// out.append(str); +// +// return out.toString(); +// } +// private String padRight(String str, int minlen) { +// if (str.length() >= minlen) +// return str; +// +// StringBuffer out = new StringBuffer(); +// out.append(str); +// int pad = minlen - str.length(); +// while (pad-- > 0) { +// out.append(' '); +// } +// +// return out.toString(); +// } // public ArrayList<Allocator> getStorageBlockAddresses() { // final ArrayList<Allocator> addrs = new ArrayList<Allocator>(m_allocs.size()); @@ -4575,13 +4575,13 @@ return m_writeCache.getCounters(); } - /** - * If historical data is maintained then this will return the earliest time for which - * data can be safely retrieved. - * - * @return time of last release - */ - public long getLastDeferredReleaseTime() { +// /** +// * If historical data is maintained then this will return the earliest time for which +// * data can be safely retrieved. +// * +// * @return time of last release +// */ + public long getLastReleaseTime() { return m_lastDeferredReleaseTime; } @@ -4627,8 +4627,10 @@ } } - public boolean inWriteCache(int rwaddr) { - return m_writeCache.isPresent(physicalAddress(rwaddr, true)); + public boolean inWriteCache(final int rwaddr) { + + return m_writeCache.isPresent(physicalAddress(rwaddr, true)); + } public InputStream getInputStream(long addr) { Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/AllocationContext.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/AllocationContext.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/AllocationContext.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -412,10 +412,10 @@ throw new UnsupportedOperationException(); } - @Override - public void setRetention(final long parseLong) { - throw new UnsupportedOperationException(); - } +// @Override +// public void setRetention(final long parseLong) { +// throw new UnsupportedOperationException(); +// } @Override public boolean isCommitted(final long addr) { Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/IMemoryManager.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/IMemoryManager.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/IMemoryManager.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -221,6 +221,10 @@ */ public void clear(); +// public void close(); +// +// public void commit(); + /** * Create a child allocation context within which the caller may make and * release allocations. @@ -299,13 +303,9 @@ */ public int getMaxSectors(); -// public void close(); - - public void commit(); - // public long saveDeferrals(); - public long getLastReleaseTime(); +// public long getLastReleaseTime(); // public void abortContext(IAllocationContext context); // @@ -313,7 +313,7 @@ // // public void registerContext(IAllocationContext context); - public void setRetention(long parseLong); +// public void setRetention(long parseLong); /** * Return <code>true</code> iff the allocation having that address is Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/MemStore.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/MemStore.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/MemStore.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -139,7 +139,7 @@ */ public IMemoryManager getMemoryManager() { - return m_strategy.getMemoryManager(); + return m_strategy.getStore(); } @@ -154,7 +154,7 @@ */ public MemStore createAllocationContext() { - return new MemStore(m_strategy.getMemoryManager().createAllocationContext(), m_uuid); + return new MemStore(m_strategy.getStore().createAllocationContext(), m_uuid); } @@ -183,7 +183,7 @@ root.addCounter("UUID", new OneShotInstrument<String>(getUUID() .toString())); - root.attach(m_strategy.getMemoryManager().getCounters()); + root.attach(m_strategy.getStore().getCounters()); return root; Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/MemStrategy.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/MemStrategy.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/MemStrategy.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -1,3 +1,26 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2011. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 + */ package com.bigdata.rwstore.sector; import java.io.File; @@ -5,7 +28,6 @@ import java.io.InputStream; import java.io.RandomAccessFile; import java.nio.ByteBuffer; -import java.util.Properties; import java.util.UUID; import com.bigdata.cache.ConcurrentWeakValueCache; @@ -25,7 +47,6 @@ import com.bigdata.rwstore.IPSOutputStream; import com.bigdata.rwstore.IRWStrategy; import com.bigdata.rwstore.IRawTx; -import com.bigdata.service.AbstractTransactionService; import com.bigdata.util.ChecksumUtility; /** @@ -47,12 +68,8 @@ private volatile IRootBlockView m_rb0 = null; private volatile IRootBlockView m_rb1 = null; - public MemStrategy(final IMemoryManager mmgr) { - this(mmgr, null); - } - - public MemStrategy(final IMemoryManager mmgr, final Properties props) { - + public MemStrategy(final IMemoryManager mmgr) { + if (mmgr == null) throw new IllegalArgumentException(); @@ -87,7 +104,7 @@ }; - // initialise RootBlocks + // initialize RootBlocks final UUID uuid = UUID.randomUUID(); // Journal's UUID. final long createTime = System.currentTimeMillis(); final ChecksumUtility checker = new ChecksumUtility(); @@ -105,18 +122,23 @@ StoreTypeEnum.RW, createTime, 0, RootBlockView.currentVersion, checker); - // store minimum release age - if (props != null) { - m_mmgr.setRetention(Long.parseLong(props.getProperty( - AbstractTransactionService.Options.MIN_RELEASE_AGE, - AbstractTransactionService.Options.DEFAULT_MIN_RELEASE_AGE))); - } +// // store minimum release age +// if (props != null) { +// m_mmgr.setRetention(Long.parseLong(props.getProperty( +// AbstractTransactionService.Options.MIN_RELEASE_AGE, +// AbstractTransactionService.Options.DEFAULT_MIN_RELEASE_AGE))); +// } } - public IMemoryManager getMemoryManager() { - return m_mmgr; + public IMemoryManager getStore() { + return m_mmgr; } + +// @Deprecated +// public IMemoryManager getMemoryManager() { +// return m_mmgr; +// } @Override public void abort() { @@ -129,7 +151,7 @@ } @Override - public void commit(IJournal journal) { + public void commit() { m_mmgr.commit(); m_dirty = false; } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/MemoryManager.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/MemoryManager.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/MemoryManager.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -32,6 +32,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.Map; +import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -235,7 +236,64 @@ * if <i>sectors</i> is non-positive. */ public MemoryManager(final DirectBufferPool pool, final int sectors) { - + + this(pool, sectors, null/* properties */); + + } + + /** + * Create a new {@link MemoryManager}. + * <p> + * The backing {@link DirectBufferPool} may be either bounded or + * (effectively) unbounded. The {@link MemoryManager} may also be bounded or + * (effectively) unbounded. If either the pool or the memory manager is + * bounded, then <em>blocking</em> allocation requests may block. Neither + * non-blocking allocation requests nor allocation requests made against an + * unbounded memory manager backed by an unbounded pool will block. The + * preferred method for bounding the memory manager is to specify a maximum + * #of buffers which it may consume from the pool. + * <p> + * The garbage collection of direct {@link ByteBuffer}s depends on a full GC + * pass. In an application which managers its heap pressure well, full GC + * passes are rare. Therefore, the best practice is to share an unbounded + * pool across multiple purposes. Since there are typically multiple users + * of the pool, the demand can not always be predicated and deadlocks can + * arise with a bounded pool. + * <p> + * Individual buffers will be allocated as necessary and released if they + * become empty. However, since allocation patterns may cause the in use + * data to be scattered across the allocated buffers, the backing buffers + * may not be returned to the backing pool until the top-level allocation + * context is cleared. + * <p> + * Any storage allocated by this instance will be released no later than + * when the instance is {@link #finalize() finalized}. Storage may be + * returned to the pool within the life cycle of the {@link MemoryManager} + * using {@link #clear()}. Nested allocation contexts may be created and + * managed using {@link #createAllocationContext()}. + * + * @param pool + * The pool from which the {@link MemoryManager} will allocate + * its buffers (each "sector" is one buffer). + * @param sectors + * The maximum #of buffers which the {@link MemoryManager} will + * allocate from that pool (each "sector" is one buffer). This + * may be {@link Integer#MAX_VALUE} for an effectively unbounded + * capacity. + * @param properties + * Used to communicate various configuration properties, + * including + * {@link AbstractTransactionService.Options#MIN_RELEASE_AGE} + * (optional). + * + * @throws IllegalArgumentException + * if <i>pool</i> is <code>null</code>. + * @throws IllegalArgumentException + * if <i>sectors</i> is non-positive. + */ + public MemoryManager(final DirectBufferPool pool, final int sectors, + final Properties properties) { + if (pool == null) throw new IllegalArgumentException(); @@ -251,6 +309,14 @@ m_sectorSize = pool.getBufferCapacity(); m_deferredFreeOut = PSOutputStream.getNew(this, SectorAllocator.BLOB_SIZE+4 /*allow for checksum*/, null); + + // store minimum release age + if (properties != null) { + m_retention = Long.parseLong(properties.getProperty( + AbstractTransactionService.Options.MIN_RELEASE_AGE, + AbstractTransactionService.Options.DEFAULT_MIN_RELEASE_AGE)); + } + } protected void finalize() throws Throwable { @@ -1076,13 +1142,16 @@ } @Override - public void free(long addr, int size) { - free((addr << 32) + size); + public void free(final long addr, final int size) { + + free((addr << 32) + size); + } @Override - public int getAssociatedSlotSize(int addr) { - final SectorAllocator sector = getSector(addr); + public int getAssociatedSlotSize(final int addr) { + + final SectorAllocator sector = getSector(addr); final int offset = SectorAllocator.getSectorOffset(addr); @@ -1133,20 +1202,20 @@ private ConcurrentWeakValueCache<Long, ICommitter> m_externalCache = null; private int m_cachedDatasize = 0; - private long m_lastReleaseTime; +// private long m_lastReleaseTime; private long m_lastDeferredReleaseTime = 0; - /** - * Call made from AbstractJournal to register the cache used. This can then - * be accessed to clear entries when storage is made availabel for re-cycling. - * - * It is not safe to clear at the point of the delete request since the data - * could still be loaded if the data is retained for a period due to a non-zero - * retention period or session protection. - * - * @param externalCache - used by the Journal to cache historical BTree references - * @param dataSize - the size of the checkpoint data (fixed for any version) - */ +// /** +// * Call made from AbstractJournal to register the cache used. This can then +// * be accessed to clear entries when storage is made availabel for re-cycling. +// * +// * It is not safe to clear at the point of the delete request since the data +// * could still be loaded if the data is retained for a period due to a non-zero +// * retention period or session protection. +// * +// * @param externalCache - used by the Journal to cache historical BTree references +// * @param dataSize - the size of the checkpoint data (fixed for any version) +// */ public void registerExternalCache( final ConcurrentWeakValueCache<Long, ICommitter> externalCache, final int dataSize) { @@ -1175,7 +1244,7 @@ } } - private int getSlotSize(int size) { + private int getSlotSize(final int size) { return SectorAllocator.getBlockForSize(size); } @@ -1454,11 +1523,11 @@ @Override public long getLastReleaseTime() { - return m_lastReleaseTime; + return m_lastDeferredReleaseTime; } @Override - public void abortContext(IAllocationContext context) { + public void abortContext(final IAllocationContext context) { m_allocationLock.lock(); try { final AllocationContext alloc = m_contexts.remove(context); @@ -1477,7 +1546,7 @@ } @Override - public void detachContext(IAllocationContext context) { + public void detachContext(final IAllocationContext context) { m_allocationLock.lock(); try { final AllocationContext alloc = m_contexts.remove(context); @@ -1498,7 +1567,7 @@ } @Override - public void registerContext(IAllocationContext context) { + public void registerContext(final IAllocationContext context) { m_allocationLock.lock(); try { establishContextAllocation(context); @@ -1583,10 +1652,10 @@ * given size against a new sector. */ - @Override - public void setRetention(final long retention) { - m_retention = retention; - } +// @Override +// public void setRetention(final long retention) { +// m_retention = retention; +// } @Override public boolean isCommitted(final long addr) { Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/SectorAllocator.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/SectorAllocator.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/rwstore/sector/SectorAllocator.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -24,15 +24,10 @@ package com.bigdata.rwstore.sector; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; import java.util.ArrayList; import org.apache.log4j.Logger; -import com.bigdata.rwstore.FixedOutputStream; -import com.bigdata.rwstore.IAllocationContext; import com.bigdata.rwstore.IWriteCacheManager; /** @@ -130,7 +125,7 @@ final ISectorManager m_store; boolean m_onFreeList = false; - private int m_diskAddr; +// private int m_diskAddr; private final IWriteCacheManager m_writes; private boolean m_preserveSession; @@ -230,7 +225,7 @@ int allocated = 0; for (int i = 0; i < m_tags.length; i++) { if (m_tags[i] == -1) { - int block = this.ALLOC_SIZES[tag] * 32; + final int block = SectorAllocator.ALLOC_SIZES[tag] * 32; if ((allocated + block) <= m_maxSectorSize) { m_tags[i] = tag; m_free[tag] += 32; @@ -339,7 +334,7 @@ * @param bit * @return the offset in the sector */ - int bit2Offset(int bit) { + int bit2Offset(final int bit) { final int entry = bit / 32; final int entryBit = bit % 32; @@ -350,45 +345,46 @@ return offset; } + +// /** +// * A previous version of bit2Offset that calculated the offset dynamically +// * @param bit +// * @return the offset in the sector +// */ +// int calcBit2Offset(int bit) { +// int offset = 0; +// for (int t = 0; t < NUM_ENTRIES; t++) { +// int tag = m_tags[t]; +// if (tag == -1) { +// throw new IllegalStateException("bit offset too large"); +// } +// int bits = ALLOC_BITS[tag]; +// if (bit < bits) { +// offset += ALLOC_SIZES[tag] * bit; +// return offset; +// } else { +// offset += ALLOC_SIZES[tag] * bits; +// bit -= bits; +// } +// } +// +// return 0; +// } /** - * A previous version of bit2Offset that calculated the offset dynamically - * @param bit - * @return the offset in the sector - */ - int calcBit2Offset(int bit) { - int offset = 0; - for (int t = 0; t < NUM_ENTRIES; t++) { - int tag = m_tags[t]; - if (tag == -1) { - throw new IllegalStateException("bit offset too large"); - } - int bits = ALLOC_BITS[tag]; - if (bit < bits) { - offset += ALLOC_SIZES[tag] * bit; - return offset; - } else { - offset += ALLOC_SIZES[tag] * bits; - bit -= bits; - } - } - - return 0; - } - /** * Since we know that all allocations are 32 bits each, there is no need to * scan through the array. * * @param bit * @return the tag of the bit */ - public int bit2tag(int bit) { + public int bit2tag(final int bit) { return m_tags[bit/32]; } /** * */ - public long getPhysicalAddress(int offset) { + public long getPhysicalAddress(final int offset) { if (!tstBit(m_transientbits, offset)) { return 0L; } else { @@ -396,7 +392,7 @@ } } - public int getPhysicalSize(int offset) { + public int getPhysicalSize(final int offset) { return bit2Size(offset); } @@ -414,7 +410,7 @@ * @param threshold the minimum number of bits free per 32 bit block * @return whether there are sufficient free for all block sizes */ - public boolean hasFree(int threshold) { + public boolean hasFree(final int threshold) { for (int i = 0; i < m_free.length; i++) { if (m_free[i] < (threshold * m_total[i])) return false; @@ -434,77 +430,78 @@ m_preserveSession = true; } - public void read(DataInputStream str) { - try { - m_index = str.readInt(); - m_sectorAddress = str.readLong(); - - System.out.println("Sector: " + m_index + " managing sector at " + m_sectorAddress); - - int taglen = str.read(m_tags); - assert taglen == m_tags.length; - - m_addresses[0] = 0; - for (int i = 0; i < NUM_ENTRIES; i++) { - m_commitbits[i] = m_transientbits[i] = m_bits[i] = str.readInt(); - - // maintain cached block offset - if (i < (NUM_ENTRIES-1)) { - final int tag = m_tags[i]; - if (tag != -1) { - m_addresses[i+1] = m_addresses[i] + (32 * ALLOC_SIZES[tag]); - } - } - } - } catch (IOException ioe) { - throw new RuntimeException(ioe); - } - } +// public void read(DataInputStream str) { +// try { +// m_index = str.readInt(); +// m_sectorAddress = str.readLong(); +// +// System.out.println("Sector: " + m_index + " managing sector at " + m_sectorAddress); +// +// int taglen = str.read(m_tags); +// assert taglen == m_tags.length; +// +// m_addresses[0] = 0; +// for (int i = 0; i < NUM_ENTRIES; i++) { +// m_commitbits[i] = m_transientbits[i] = m_bits[i] = str.readInt(); +// +// // maintain cached block offset +// if (i < (NUM_ENTRIES-1)) { +// final int tag = m_tags[i]; +// if (tag != -1) { +// m_addresses[i+1] = m_addresses[i] + (32 * ALLOC_SIZES[tag]); +// } +// } +// } +// } catch (IOException ioe) { +// throw new RuntimeException(ioe); +// } +// } - public int getDiskAddr() { - return m_diskAddr; - } - - public void setDiskAddr(int addr) { - m_diskAddr = addr; - } +// public int getDiskAddr() { +// return m_diskAddr; +// } +// +// public void setDiskAddr(int addr) { +// m_diskAddr = addr; +// } - public boolean verify(int addr) { - // TODO Auto-generated method stub - return false; - } +// public boolean verify(int addr) { +// // TODO Auto-generated method stub +// return false; +// } - public byte[] write() { - byte[] buf = new byte[META_SIZE]; - DataOutputStream str = new DataOutputStream(new FixedOutputStream(buf)); - try { - str.writeInt(m_index); - str.writeLong(m_sectorAddress); - str.write(m_tags); - for (int i = 0; i < NUM_ENTRIES; i++) { - str.writeInt(m_bits[i]); - } - - m_transientbits = (int[]) m_bits.clone(); - m_commitbits = (int[]) m_bits.clone(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - try { - str.close(); - } catch (IOException e) { - // ignore - } - } - - return buf; - } +// public byte[] write() { +// final byte[] buf = new byte[META_SIZE]; +// final DataOutputStream str = new DataOutputStream( +// new FixedOutputStream(buf)); +// try { +// str.writeInt(m_index); +// str.writeLong(m_sectorAddress); +// str.write(m_tags); +// for (int i = 0; i < NUM_ENTRIES; i++) { +// str.writeInt(m_bits[i]); +// } +// +// m_transientbits = (int[]) m_bits.clone(); +// m_commitbits = (int[]) m_bits.clone(); +// } catch (IOException e) { +// e.printStackTrace(); +// } finally { +// try { +// str.close(); +// } catch (IOException e) { +// // ignore +// } +// } +// +// return buf; +// } - public int addressSize(int offset) { + public int addressSize(final int offset) { return bit2Size(offset); } - public void setIndex(int index) { + public void setIndex(final int index) { assert m_index == 0; m_index = index; @@ -514,27 +511,27 @@ addrs.add(Long.valueOf(m_sectorAddress)); } - static void clrBit(int[] bits, int bitnum) { - int index = bitnum / 32; - int bit = bitnum % 32; + static void clrBit(final int[] bits, final int bitnum) { + final int index = bitnum / 32; + final int bit = bitnum % 32; - int val = bits[index]; + int val = bits[index]; val &= ~(1 << bit); bits[index] = val; } - static void setBit(int[] bits, int bitnum) { - int index = bitnum / 32; - int bit = bitnum % 32; + static void setBit(final int[] bits, final int bitnum) { + final int index = bitnum / 32; + final int bit = bitnum % 32; bits[index] |= 1 << bit; } - static boolean tstBit(int[] bits, int bitnum) { - int index = bitnum / 32; - int bit = bitnum % 32; + static boolean tstBit(final int[] bits, final int bitnum) { + final int index = bitnum / 32; + final int bit = bitnum % 32; return (bits[index] & 1 << bit) != 0; } @@ -586,21 +583,21 @@ m_store.addToFreeList(this); } - public static int getSectorIndex(int rwaddr) { + public static int getSectorIndex(final int rwaddr) { return ((-rwaddr) >>> SECTOR_OFFSET_BITS) - 1; } - public static int getSectorOffset(int rwaddr) { + public static int getSectorOffset(final int rwaddr) { return (-rwaddr) & SECTOR_OFFSET_MASK; } - public static int getBlobBlockCount(int size) { + public static int getBlobBlockCount(final int size) { final int nblocks = (size + BLOB_SIZE - 1) / BLOB_SIZE; return nblocks; } - public static int getBlockForSize(int size) { + public static int getBlockForSize(final int size) { for (int i = 0; i < ALLOC_SIZES.length; i++) { if (size <= ALLOC_SIZES[i]) { return ALLOC_SIZES[i]; @@ -631,48 +628,43 @@ m_preserveSession = false; } - public boolean addressInRange(int addr) { - // TODO Auto-generated method stub - return false; - } +// public boolean addressInRange(int addr) { +// return false; +// } - public int getAllocatedBlocks() { - // TODO Auto-generated method stub - return 0; - } +// public int getAllocatedBlocks() { +// return 0; +// } - public long getFileStorage() { - // TODO Auto-generated method stub - return 0; - } +// public long getFileStorage() { +// return 0; +// } - public long getAllocatedSlots() { - // TODO Auto-generated method stub - return 0; - } +// public long getAllocatedSlots() { +// return 0; +// } - public boolean canImmediatelyFree(int addr, int sze, IAllocationContext context) { - // TODO Auto-generated method stub - return false; - } +// public boolean canImmediatelyFree(int addr, int sze, IAllocationContext context) { +// return false; +// } - public boolean isAllocated(int addrOffset) { - return tstBit(m_bits, addrOffset); - } +// public boolean isAllocated(final int addrOffset) { +// return tstBit(m_bits, addrOffset); +// } - public void free(int addr, int sze, boolean overrideSession) { - free(addr); - } +// public void free(int addr, int sze, boolean overrideSession) { +// free(addr); +// } - public void setAllocationContext(IAllocationContext m_context) { - throw new UnsupportedOperationException(); - } +// public void setAllocationContext(IAllocationContext m_context) { +// throw new UnsupportedOperationException(); +// } +// +// public int alloc(final int size, final IAllocationContext context) { +// +// return alloc(size); +// } - public int alloc(int size, IAllocationContext context) { - - return alloc(size); - } - public String toString() { final StringBuilder str = new StringBuilder(); @@ -700,11 +692,11 @@ } } - public boolean isCommitted(int offset) { + public boolean isCommitted(final int offset) { return tstBit(m_commitbits, offset); } - public boolean isGettable(int offset) { + public boolean isGettable(final int offset) { return tstBit(m_transientbits, offset); } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/rwstore/TestRWJournal.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/rwstore/TestRWJournal.java 2012-06-28 16:16:59 UTC (rev 6369) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/rwstore/TestRWJournal.java 2012-06-28 18:06:53 UTC (rev 6370) @@ -514,14 +514,14 @@ try { - byte[] buf = new byte[1024]; // 2Mb buffer of random data + final byte[] buf = new byte[1024]; // 2Mb buffer of random data r.nextBytes(buf); - ByteBuffer bb = ByteBuffer.wrap(buf); + final ByteBuffer bb = ByteBuffer.wrap(buf); - RWStrategy bs = (RWStrategy) store.getBufferStrategy(); + final RWStrategy bs = (RWStrategy) store.getBufferStrategy(); - RWStore rw = bs.getRWStore(); + final RWStore rw = bs.getStore(); long faddr1 = bs.write(bb); bb.position(0); @@ -565,25 +565,25 @@ try { - RWStrategy bufferStrategy = (RWStrategy) store.getBufferStrategy(); + final RWStrategy bufferStrategy = (RWStrategy) store.getBufferStrategy(); - RWStore rw = bufferStrategy.getRWStore(); - ArrayList<Integer> sizes = new ArrayList<Integer>(); - TreeMap<Long, Integer> paddrs = new TreeMap<Long, Integer>(); + final RWStore rw = bufferStrategy.getStore(); + final ArrayList<Integer> sizes = new ArrayList<Integer>(); + final TreeMap<Long, Integer> paddrs = new TreeMap<Long, Integer>(); for (int i = 0; i < 100000; i++) { - int s = r.nextInt(250) + 1; + final int s = r.nextInt(250) + 1; sizes.add(s); - int a = rw.alloc(s, null); - long pa = rw.physicalAddress(a); + final int a = rw.alloc(s, null); + final long pa = rw.physicalAddress(a); assertTrue(paddrs.get(pa) == null); paddrs.put(pa, a); } for (int i = 0; i < 50; i++) { - int s = r.nextInt(500) + 1; + final int s = r.nextInt(500) + 1; sizes.add(s); - int a = rw.alloc(s, null); - long pa = rw.physicalAddress(a); + final int a = rw.alloc(s, null); + final long pa = rw.physicalAddress(a); paddrs.put(pa, a); } @@ -609,11 +609,11 @@ try { - RWStrategy bufferStrategy = (RWStrategy) store.getBufferStrategy(); + final RWStrategy bufferStrategy = (RWStrategy) store.getBufferStrategy(); - RWStore rw = bufferStrategy.getRWStore(); - long numAllocs = rw.getTotalAllocations(); - long startAllocations = rw.getTotalAllocationsSize(); + final RWStore rw = bufferStrategy.getStore(); + final long numAllocs = rw.getTotalAllocations(); + final long startAllocations = rw.getTotalAllocationsSize(); long faddr = allocBatch(rw, 1000, 275, 320); faddr = allocBatch(rw, 10000, 90, 128); faddr = allocBatch(rw, 20000, 45, 64); @@ -727,7 +727,7 @@ RWStrategy bufferStrategy = (RWStrategy) store.getBufferStrategy(); - RWStore rw = bufferStrategy.getRWStore(); + RWStore rw = bufferStrategy.getStore(); long numAllocs = rw.getTotalAllocations(); long startAllocations = rw.getTotalAllocationsSize(); @@ -737,7 +737,7 @@ store.close(); store = new Journal(properties); bufferStrategy = (RWStrategy) store.getBufferStrategy(); - rw = bufferStrategy.getRWStore(); + rw = bufferStrategy.getStore(); reallocBatch(rw, 1000, 100, 1000); @@ -745,7 +745,7 @@ store.close(); store = new Journal(properties); bufferStrategy = (RWStrategy) store.getBufferStrategy(); - rw = bufferStrategy.getRWStore(); + rw = bufferStrategy.getStore(); reallocBatch(rw, 1000, 100, 1000); @@ -753,7 +753,7 @@ store.close(); store = new Journal(properties); bufferStrategy = (RWStrategy) store.getBufferStrategy(); - rw = bufferStrategy.getRWStore(); + rw = bufferStrategy.getStore(); if(log.isInfoEnabled()) log.info("Final allocations: " + (rw.getTotalAllocations() - numAllocs) @@ -794,7 +794,7 @@ RWStrategy bufferStrategy = (RWStrategy) store.getBufferStrategy(); - RWStore rw = bufferStrategy.getRWStore(); + RWStore rw = bufferStrategy.getStore(); final int tcount = 5000; // increase to ramp up stress levels @@ -837,7 +837,7 @@ bufferStrategy = (RWStrategy) store.getBufferStrategy(); - rw = bufferStrategy.getRWStore(); + rw = bufferStrategy.getStore(); if(log.isInfoEnabled())log.info("Final allocations: " + (rw.getTotalAllocations() - numAllocs) + ", allocated bytes: " + (rw.getTotalAllocationsSize() - startAllocations) + ", file length: " @@ -858,13 +858,13 @@ public void testAllocationContexts() { - Journal store = (Journal) getStore(); + final Journal store = (Journal) getStore(); try { - RWStrategy bufferStrategy = (RWStrategy) store.getBufferStrategy(); + final RWStrategy bufferStrategy = (RWStrategy) store.getBufferStrategy(); - RWStore rw = bufferStrategy.getRWStore(); + final RWStore rw = bufferStrategy.getStore(); IAllocationContext cntxt1 = new IAllocationContext() {}; @@ -897,7 +897,7 @@ final RWStrategy bufferStrategy = (RWStrategy) store.getBufferStrategy(); - final RWStore rw = bufferStrategy.getRWStore(); + final RWStore rw = bufferStrategy.getStore(); if(log.isInfoEnabled())log.info("Fixed Allocators: " + rw.getFixedAllocatorCount() + ", heap allocated: " + rw.getFileStorage() + ", utilised bytes: " + rw.getAllocatedSlots() + ", file length: " @@ -912,21 +912,21 @@ boolean reopen) { allocChar = (byte) (allocChar + 1); - RWStrategy bs = (RWStrategy) store.getBufferStrategy(); + final RWStrategy bs = (RWStrategy) store.getBufferStrategy(); - byte[] buf = new byte[sze + 4]; // extra for checksum + final byte[] buf = new byte[sze + 4]; // extra for checksum // r.nextBytes(buf); for (int i = 0; i < buf.length; i++) { buf[i] = allocChar; } - RWStore rw = bs.getRWStore(); + final RWStore rw = bs.getStore(); - long[] addr = new long[grp / 5]; - int[] szes = new int[grp]; + final long[] addr = new long[grp / 5]; + final int[] szes = new int[grp]; for (int i = 0; i < grp; i++) { szes[i] = min + r.nextInt(sze - min); - ByteBuffer bb = ByteBuffer.wrap(buf, 0, szes[i]); + final ByteBuffer bb = ByteBuffer.wrap(buf, 0, szes[i]); if (i % 5 == 0) addr[i / 5] = bs.write(bb); } @@ -944,7 +944,7 @@ throw new RuntimeException("problem handling read: " + i + " in test: " + t + " from address: " + old, e); } - ByteBuffer bb = ByteBuffer.wrap(buf, 0, szes[i]); + final ByteBuffer bb = ByteBuffer.wrap(buf, 0, szes[i]); addr[i] = bs.write(bb); bb.flip(); bs.delete(old); @@ -972,9 +972,9 @@ final int tcount = 1000; // increase to ramp up stress levels - RWStrategy bufferStrategy = (RWStrategy) store.getBufferStrategy(); + final RWStrategy bufferStrategy = (RWStrategy) store.getBufferStrategy(); - RWStore rw = bufferStrategy.getRWStore(); + final RWStore rw = bufferStrategy.getStore(); long numAllocs = rw.getTotalAllocations(); long startAllocations = rw.getTotalAllocationsSize(); @@ -1044,26 +1044,28 @@ * allocation */ public void test_blob_allocs() { - if (false) { - return; - } +// if (false) { +// return; +// } final Journal store = (Journal) getStore(); try { - RWStrategy bufferStrategy = (RWStrategy) store.getBufferStrategy(); + final RWStrategy bufferStrategy = (RWStrategy) store.getBufferStrategy(); - RWStore rw = bufferStrategy.getRWStore(); - long numAllocs = rw.getTotalAllocations(); - long startAllocations = rw.getTotalAllocationsSize(); - int startBlob = 1024 * 256; - int endBlob = 1024 * 1256; - int[] faddrs = allocBatchBuffer(rw, 100, startBlob, endBlob); + final RWStore rw = bufferStrategy.getStore(); + final long numAllocs = rw.getTotalAllocations(); + final long startAllocations = rw.getTotalAllocationsSize(); + final int startBlob = 1024 * 256; + final int endBlob = 1024 * 1256; + final int[] faddrs = allocBatchBuffer(rw, 100, startBlob, endBlob); - final StringBuilder str = new StringBuilder(); - rw.getStorageStats().showStats(str); - if(log.isInfoEnabled())log.info(str); + if (log.isInfoEnabled()) { + final StringBuilder str = new StringBuilder(); + rw.showAllocators(str); + log.info(str); + } } finally { store.destroy(); @@ -1083,15 +1085,15 @@ try { final RWStrategy bs = (RWStrategy) store.getBufferStrategy(); - final RWStore rw = bs.getRWStore(); + final RWStore rw = bs.getStore(); - byte[] buf = new byte[2 * 1024 * 1024]; // 5Mb buffer of random + final byte[] buf = new byte[2 * 1024 * 1024]; // 5Mb buffer of random // data r.nextBytes(buf); - ByteBuffer bb = ByteBuffer.wrap(buf); + final ByteBuffer bb = ByteBuffer.wrap(buf); - long faddr = bs.write(bb); // rw.alloc(buf, buf.length); + final long faddr = bs.write(bb); // rw.alloc(buf, buf.length); if(log.isInfoEnabled())log.info("Blob Allocation at " + rw.convertFromAddr(faddr)); @@ -1145,7 +1147,7 @@ final RWStrategy bs = (RWStrategy) store.getBufferStrategy(); - final RWStore rw = bs.getRWStore(); + final RWStore rw = bs.getStore(); long faddr = bs.write(bb); // rw.alloc(buf, buf.length); @@ -1296,9 +1298,9 @@ Journal store = (Journal) getStore(); try { - RWStrategy bs = (RWStrategy) store.getBufferStrategy(); + final RWStrategy bs = (RWStrategy) store.getBufferStrategy(); - RWStore rw = bs.getRWStore(); + final RWStore rw = bs.getStore(); long realAddr = 0; for (int i = 0; i < 100000; i++) { int allocAddr = rw.metaAlloc(); @@ -1331,18 +1333,18 @@ public void test_allocationContexts() throws IOException { Journal store = (Journal) getStore(); try { - RWStrategy bs = (RWStrategy) store.getBufferStrategy(); + final RWStrategy bs = (RWStrategy) store.getBufferStrategy(); - RWStore rw = bs.getRWStore(); + final RWStore rw = bs.getStore(); // JournalShadow shadow = new JournalShadow(store); // Create a couple of contexts - IAllocationContext allocContext1 = new DummyAllocationContext(); - IAllocationContext allocContext2 = new DummyAllocationContext(); + final IAllocationContext allocContext1 = new DummyAllocationContext(); + final IAllocationContext allocContext2 = new DummyAllocationContext(); - int sze = 650; - byte[] buf = new byte[sze + 4]; // extra for checksum + final int sze = 650; + final byte[] buf = new byte[sze + 4]; // extra for checksum r.nextBytes(buf); long addr1a = bs.write(ByteBuffer.wrap(buf), allocContext1); @@ -1443,13 +1445,15 @@ } - private void commitSomeData(Journal store) { - RWStrategy bs = (RWStrategy) store.getBufferStrategy(); + private void commitSomeData(final Journal store) { + + final IRWStrategy bs = (IRWStrategy) store.getBufferStrategy(); - RWStore rw = bs.getRWStore(); +// final IStore rw = bs.getStore(); // byte[] buf = new byte[r.nextInt(1024)]; // extra for checksum - byte[] buf = new byte[863]; // extra for checksum + final byte[] buf = new byte[863]; // extra for checksum + r.nextBytes(buf); bs.write(ByteBuffer.wrap(buf)); @@ -1464,7 +1468,7 @@ final RWStrategy bs = (RWStrategy) store.getBufferStrategy(); - final RWStore rw = bs.getRWStore(); + final RWStore rw = bs.getStore(); // long realAddr = 0; // allocBatch(store, 1, 32, 650, 100000000); allocBatch(store, 1, 32, 650, 50000); @@ -1493,12 +1497,12 @@ final Journal store = (Journal) getStore(); try { final ... [truncated message content] |
From: <tho...@us...> - 2012-06-29 20:39:50
|
Revision: 6372 http://bigdata.svn.sourceforge.net/bigdata/?rev=6372&view=rev Author: thompsonbry Date: 2012-06-29 20:39:41 +0000 (Fri, 29 Jun 2012) Log Message: ----------- I have finished relayering the Checkpoint, ICheckpointProtocol, ISolutionSet, and SolutionSetStream classes. There is now a durable SolutionSetStream which can be backed by an IRWStrategy. Once we resolve [1], we will be able to generalize this to any IRawStore. The SparqlCache is still wired to a ConcurrentHashMap. I have not yet derived versions of the ISolutionSetCache for the HTree and the BTree. There is some remaining work to be done there concerning the integration with the Checkpoint record. Specifically, I need to establish a protocol to store the address of the ISolutionSetStats in the checkpoint record. Right now the ISolutionSetStats is hacked into the bloom filter addr since that is not used by the SolutionSetStream. There is plenty of room in the Checkpoint record, we just need to establish a protocol to make this work. There is now a top-level durable Stream. SolutionSetStream extends this. The Stream is based on the PSOutputStream mechanism but it implements the ICheckpointProtocol and hence can be stored in Name2Addr just like the BTree or HTree. This also makes it compatible with a MemStore mode Journal for the SPARQL cache. I still need to review the integration of the SparqlCache with the SolutionSetStream and provide appropriate layering of access (query scope => cache scope => database scope) through the resource locator protocol. There are notes on this above and also in the committed files. [1] https://sourceforge.net/apps/trac/bigdata/ticket/555 (Support PSOutputStream/InputStream at IRawStore) @see https://sourceforge.net/apps/trac/bigdata/ticket/524 (SPARQL Cache) Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/AbstractBTree.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/BTree.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/Checkpoint.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/HTreeIndexMetadata.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/ICheckpointProtocol.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/IndexMetadata.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/IndexTypeEnum.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/htree/AbstractHTree.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/htree/HTree.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/resources/logging/log4j-dev.properties branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/SparqlCache.java branches/BIGDATA_RELEASE_1_2_0/ctc-striterators/src/java/cutthecrap/utils/striterators/ArrayIterator.java Added Paths: ----------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/ISolutionSet.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/SolutionSetStream.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/EntryScanIterator.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/stream/ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/stream/Stream.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/internal/encoder/SolutionSetStreamDecoder.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/internal/encoder/SolutionSetStreamEncoder.java Removed Paths: ------------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/SolutionSetMetadata.java Added: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/ISolutionSet.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/ISolutionSet.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/ISolutionSet.java 2012-06-29 20:39:41 UTC (rev 6372) @@ -0,0 +1,108 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 Apr 9, 2012 + */ +package com.bigdata.bop.solutions; + +import com.bigdata.bop.IBindingSet; +import com.bigdata.bop.controller.NamedSolutionSetRef; +import com.bigdata.btree.BTree; +import com.bigdata.btree.ICheckpointProtocol; +import com.bigdata.htree.HTree; +import com.bigdata.rdf.sparql.ast.ISolutionSetStats; +import com.bigdata.relation.accesspath.AccessPath; +import com.bigdata.relation.accesspath.IAccessPath; +import com.bigdata.stream.Stream; +import com.bigdata.striterator.ICloseableIterator; + +/** + * Interface for durable solution sets. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + * + * FIXME Provide {@link ISolutionSet} implementations derived from {@link HTree} + * and {@link BTree}. + * <p> + * Reconcile the {@link HTree} version with the hash join code and + * {@link NamedSolutionSetRef}. + * <p> + * Add an {@link IAccessPath} for HTree and {@link Stream} backed solution sets + * so they can be played out through a simple iterator model. The + * {@link AccessPath} can be used for the {@link BTree} backed solution sets. + */ +public interface ISolutionSet extends ICheckpointProtocol { + + /** + * Return the {@link ISolutionSetStats} for the saved solution set. This may + * be used for query planning and should not require the backing solutions + * to be materialized. + * + * @return The {@link ISolutionSetStats}. + */ + public ISolutionSetStats getStats(); + +// /** +// * Return the CREATE schema for the solution set (this is the metadata used +// * to provision the characteristics of the solution set). +// * +// * TODO This should be stored in a "root" on the checkpoint record. +// */ +// public ISPO[] getDeclation(); + + /** + * Visit all entries in the index in the natural order of the index. + */ + public ICloseableIterator<IBindingSet> scan(); + + /** + * Return an {@link ICloseableIterator} reading the solutions from the + * stream. + */ + public ICloseableIterator<IBindingSet[]> get(); + + /** + * Replace the contents of the stream with the solutions read from the + * source. + * + * @param src + * The source. + */ + public void put(final ICloseableIterator<IBindingSet[]> src); + + /** + * The {@link IVariable[]} specifying the join variables (required). The + * order of the entries is used when forming the as-bound keys for the hash + * table. Duplicate elements and null elements are not permitted. + * + * TODO We will also need a method to report the JOIN_VARS if the backing + * data structure is an HTree or BTree. [Really, what we need is a method to + * describe how the index key will be generated, or just a method to + * generate the key. Also, it is possible that + * {@link ISolutionSetStats#getAlwaysBound} will report variables which are + * always bound but which are not part of the key for the index. + */ +// public String[] getJoinVars(); + +} Copied: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/SolutionSetStream.java (from rev 6370, branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/SolutionSetMetadata.java) =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/SolutionSetStream.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/SolutionSetStream.java 2012-06-29 20:39:41 UTC (rev 6372) @@ -0,0 +1,432 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 Apr 9, 2012 + */ + +package com.bigdata.bop.solutions; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.apache.log4j.Logger; + +import com.bigdata.bop.IBindingSet; +import com.bigdata.bop.IConstant; +import com.bigdata.bop.IVariable; +import com.bigdata.bop.controller.NamedSolutionSetRef; +import com.bigdata.btree.BTree; +import com.bigdata.btree.Checkpoint; +import com.bigdata.btree.IndexMetadata; +import com.bigdata.htree.HTree; +import com.bigdata.io.SerializerUtil; +import com.bigdata.rawstore.IRawStore; +import com.bigdata.rdf.internal.encoder.SolutionSetStreamDecoder; +import com.bigdata.rdf.internal.encoder.SolutionSetStreamEncoder; +import com.bigdata.rdf.sparql.ast.ISolutionSetStats; +import com.bigdata.relation.accesspath.AccessPath; +import com.bigdata.relation.accesspath.IAccessPath; +import com.bigdata.rwstore.IPSOutputStream; +import com.bigdata.stream.Stream; +import com.bigdata.striterator.Chunkerator; +import com.bigdata.striterator.ICloseableIterator; + +import cutthecrap.utils.striterators.ArrayIterator; +import cutthecrap.utils.striterators.Expander; +import cutthecrap.utils.striterators.Striterator; + +/** + * A persistence capable solution set stored using a stream oriented API. The + * order of the solutions on playback is their write order. This data structure + * provides fast read/write performance, but does not provide key-based access + * into the solution sets. + * + * TODO Test performance with and without gzip. Extract into the CREATE schema / + * IndexMetadata so we can do this declaratively. + */ +public final class SolutionSetStream extends Stream implements + ISolutionSet { + + private static final Logger log = Logger.getLogger(SolutionSetStream.class); + + /** + * Encapsulates the address and the data. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ + private final class MySolutionSetStats implements ISolutionSetStats { + + private ISolutionSetStats delegate; + private long addr; + + public MySolutionSetStats(final ISolutionSetStats stats) { + + this.delegate = stats; + + } + + public long getSolutionSetSize() { + return delegate.getSolutionSetSize(); + } + + public Set<IVariable<?>> getUsedVars() { + return delegate.getUsedVars(); + } + + public Set<IVariable<?>> getAlwaysBound() { + return delegate.getAlwaysBound(); + } + + public Set<IVariable<?>> getNotAlwaysBound() { + return delegate.getNotAlwaysBound(); + } + + public Set<IVariable<?>> getMaterialized() { + return delegate.getMaterialized(); + } + + public Map<IVariable<?>, IConstant<?>> getConstants() { + return delegate.getConstants(); + } + + } + + /** + * The {@link ISolutionSetStats} are collected when the solution are written + * by {@link #put(ICloseableIterator)}. + * + * @see #needsCheckpoint() + * @see #flush() + * + * FIXME This is hacked into the bloomFilterAddr. It should have its + * own address. The Checkpoint class needs a protocol for populating + * and reporting fields which are specific to derived classes, not just + * BTree, HTree, and Stream. Or we need to add a general concept of a + * "summary statistics object" for a persistent data structure. + */ + private MySolutionSetStats solutionSetStats; + + /** + * Required constructor. This constructor is used both to create a new named + * solution set, and to load an existing named solution set from the store + * using a {@link Checkpoint} record. + * + * @param store + * The store. + * @param checkpoint + * The {@link Checkpoint} record. + * @param metadata + * The metadata record. + * @param readOnly + * When <code>true</code> the view will be immutable. + * + * @see #create(IRawStore, StreamIndexMetadata) + * @see #load(IRawStore, long, boolean) + */ + public SolutionSetStream(final IRawStore store, + final Checkpoint checkpoint, final IndexMetadata metadata, + final boolean readOnly) { + + super(store, checkpoint, metadata, readOnly); + + /* + * Note: The SolutionSetStats will be loaded by setCheckpoint(). + */ + + } + + /** + * Create a stream for an ordered solution set. + * <p> + * {@inheritDoc} + */ + public static SolutionSetStream create(final IRawStore store, + final StreamIndexMetadata metadata) { + + /* + * Must override the implementation class name: + */ + + metadata.setStreamClassName(SolutionSetStream.class.getName()); + + return Stream.create(store, metadata); + + } + + /** + * Return the {@link ISolutionSetStats} for the saved solution set. + * + * @return The {@link ISolutionSetStats}. + */ + public ISolutionSetStats getStats() { + + return solutionSetStats; + + } + + public ICloseableIterator<IBindingSet[]> get() { + + if (rootAddr == IRawStore.NULL) + throw new IllegalStateException(); + + // Open input stream reading decompressed data from store. + final DataInputStream in = new DataInputStream( + wrapInputStream(getStore().getInputStream(rootAddr))); + + // Wrap with iterator pattern that will decode solutions. + final SolutionSetStreamDecoder decoder = new SolutionSetStreamDecoder( + metadata.getName(), in, rangeCount()); + + // Return the iterator to the caller. + return decoder; + + } + + public void put(final ICloseableIterator<IBindingSet[]> src2) { + + if (src2 == null) + throw new IllegalArgumentException(); + + assertNotReadOnly(); + + final String name = metadata.getName(); + + // Address from which the solutions may be read. + final long newAddr; + + // Used to encode the solutions on the stream. + final SolutionSetStreamEncoder encoder = new SolutionSetStreamEncoder( + name); + + // Stream writes onto the backing store. + final IPSOutputStream out = getStore().getOutputStream(); + + try { + + // Wrap with data output stream and compression. + final DataOutputStream os = new DataOutputStream( + wrapOutputStream(out)); + + try { + + // Encode the solutions onto the stream. + encoder.encode(os, src2); + + // Flush the stream. + os.flush(); + + } finally { + + try { + os.close(); + } catch (IOException e) { + // Unexpected exception. + log.error(e, e); + } + + } + + // Flush + out.flush(); + + // Note address of the stream. + newAddr = out.getAddr(); + + } catch (IOException e) { + + throw new RuntimeException(e); + + } finally { + + try { + out.close(); + } catch (IOException e) { + // Unexpected exception. + log.error(e, e); + } + + } + + if (rootAddr != IRawStore.NULL) { + + /* + * Release the old solution set. + */ + + recycle(rootAddr); + + } + + if (solutionSetStats != null && solutionSetStats.addr != IRawStore.NULL) { + + recycle(solutionSetStats.addr); + + } + + rootAddr = newAddr; + entryCount = encoder.getSolutionCount(); + solutionSetStats = new MySolutionSetStats(encoder.getStats()); + fireDirtyEvent(); + + } + + /* + * ICheckpointProtocol + */ + + @SuppressWarnings("unchecked") + @Override + public ICloseableIterator<IBindingSet> scan() { + + return (ICloseableIterator<IBindingSet>) new Striterator(get()) + .addFilter(new Expander() { + + /** + * + */ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("rawtypes") + @Override + protected Iterator expand(final Object obj) { + + return new ArrayIterator((IBindingSet[]) obj); + + } + }); + + } + + @Override + public void clear() { + + super.clear(); + + solutionSetStats = null; + + } + + @Override + protected boolean needsCheckpoint() { + + if (super.needsCheckpoint()) + return true; + + if (solutionSetStats != null + && solutionSetStats.addr != getCheckpoint() + .getBloomFilterAddr()) { + + // The statistics field was updated. + return true; + + } + + if (solutionSetStats == null + && getCheckpoint().getBloomFilterAddr() != IRawStore.NULL) { + + // The statistics field was cleared. + return true; + + } + + return false; + + } + + @Override + protected void flush() { + + super.flush(); + + /* + * If the solutionSetStats are dirty, then write them out and set the + * addr so it will be propagated to the checkpoint record. + */ + + if (solutionSetStats != null + && solutionSetStats.addr != getCheckpoint() + .getBloomFilterAddr()) { + + solutionSetStats.addr = getStore() + .write(ByteBuffer.wrap(SerializerUtil + .serialize(solutionSetStats.delegate))); + + } + + } + + /** + * {@inheritDoc} + * <p> + * Extended to persist the {@link ISolutionSetStats}. + */ + @Override + protected void setCheckpoint(final Checkpoint checkpoint) { + + super.setCheckpoint(checkpoint); + + { + + final long addr = checkpoint.getBloomFilterAddr(); + + if(addr != IRawStore.NULL) { + + this.solutionSetStats = new MySolutionSetStats( + (ISolutionSetStats) SerializerUtil + .deserialize(getStore().read(addr))); + + this.solutionSetStats.addr = addr; + + } + + } + + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public void write(final ICloseableIterator<?> src) { + + try { + + /* + * Chunk up the solutions and write them onto the stream. + */ + + put(new Chunkerator(src)); + + } finally { + + src.close(); + + } + + } + +} Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/AbstractBTree.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/AbstractBTree.java 2012-06-29 13:00:40 UTC (rev 6371) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/AbstractBTree.java 2012-06-29 20:39:41 UTC (rev 6372) @@ -73,14 +73,12 @@ import com.bigdata.io.ByteArrayBuffer; import com.bigdata.io.DirectBufferPool; import com.bigdata.io.compression.IRecordCompressorFactory; -import com.bigdata.journal.AbstractTask; import com.bigdata.journal.CompactTask; import com.bigdata.journal.IAtomicStore; import com.bigdata.journal.IConcurrencyManager; import com.bigdata.journal.IIndexManager; import com.bigdata.journal.Journal; import com.bigdata.mdi.IResourceMetadata; -import com.bigdata.mdi.LocalPartitionMetadata; import com.bigdata.rawstore.IRawStore; import com.bigdata.rawstore.TransientResourceMetadata; import com.bigdata.resources.IndexManager; @@ -1108,23 +1106,8 @@ // abstract protected int getReadRetentionQueueScan(); /** - * The contract for {@link #close()} is to reduce the resource burden of the - * index (by discarding buffers) while not rendering the index inoperative. - * Unless the {@link AbstractBTree} {@link #isTransient()}, a B+Tree that - * has been {@link #close() closed} MAY be {@link #reopen() reopened} at any - * time (conditional on the continued availability of the backing store). - * Such an index reference remains valid after a {@link #close()}. A closed - * index is transparently restored by either {@link #getRoot()} or - * {@link #reopen()}. + * {@inheritDoc} * <p> - * Note: A {@link #close()} on a dirty index MUST discard writes rather than - * flushing them to the store and MUST NOT update its {@link Checkpoint} - * record - ({@link #close()} is used to discard indices with partial - * writes when an {@link AbstractTask} fails). If you are seeking to - * {@link #close()} a mutable {@link BTree} that it state can be recovered - * by {@link #reopen()} then you MUST write a new {@link Checkpoint} record - * before closing the index. - * <p> * Note: CLOSING A TRANSIENT INDEX WILL DISCARD ALL DATA! * <p> * This implementation clears the hard reference queue (releasing all node @@ -1215,19 +1198,15 @@ } /** - * This is part of a {@link #close()}/{@link #reopen()} protocol that may - * be used to reduce the resource burden of an {@link AbstractBTree}. The - * method delegates to {@link #_reopen()} if double-checked locking - * demonstrates that the {@link #root} is <code>null</code> (indicating - * that the index has been closed). This method is automatically invoked by - * a variety of methods that need to ensure that the index is available for + * {@inheritDoc}. + * <p> + * This method delegates to {@link #_reopen()} if double-checked locking + * demonstrates that the {@link #root} is <code>null</code> (indicating that + * the index has been closed). This method is automatically invoked by a + * variety of methods that need to ensure that the index is available for * use. - * - * @see #close() - * @see #isOpen() - * @see #getRoot() */ - final protected void reopen() { + final public void reopen() { if (root == null) { @@ -1269,16 +1248,6 @@ */ abstract protected void _reopen(); - /** - * An "open" index has its buffers and root node in place rather than having - * to reallocate buffers or reload the root node from the store. - * - * @return If the index is "open". - * - * @see #close() - * @see #reopen() - * @see #getRoot() - */ final public boolean isOpen() { return root != null; Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/BTree.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/BTree.java 2012-06-29 13:00:40 UTC (rev 6371) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/BTree.java 2012-06-29 20:39:41 UTC (rev 6372) @@ -41,13 +41,13 @@ import com.bigdata.journal.AbstractJournal; import com.bigdata.journal.ICommitter; import com.bigdata.journal.IIndexManager; -import com.bigdata.journal.RWStrategy; import com.bigdata.mdi.IResourceMetadata; import com.bigdata.mdi.JournalMetadata; import com.bigdata.mdi.LocalPartitionMetadata; import com.bigdata.rawstore.Bytes; import com.bigdata.rawstore.IRawStore; import com.bigdata.rwstore.IRWStrategy; +import com.bigdata.striterator.ICloseableIterator; /** * <p> @@ -159,8 +159,9 @@ * @author <a href="mailto:tho...@us...">Bryan Thompson</a> * @version $Id$ */ -public class BTree extends AbstractBTree implements ICommitter, ICheckpointProtocol {// ILocalBTreeView { - +public class BTree extends AbstractBTree implements ICommitter, + ICheckpointProtocol {// ILocalBTreeView { + final public int getHeight() { return height; @@ -1009,11 +1010,14 @@ */ if (checkpoint != null && getRoot() != null && checkpoint.getRootAddr() != getRoot().identity) { - recycle(checkpoint != null ? checkpoint.getRootAddr() : IRawStore.NULL); + + recycle(checkpoint != null ? checkpoint.getRootAddr() + : IRawStore.NULL); + } // create new checkpoint record. - checkpoint = metadata.newCheckpoint(this); + checkpoint = newCheckpoint(); // write it on the store. checkpoint.write(store); @@ -1034,6 +1038,55 @@ } + /** + * Create a {@link Checkpoint} for a {@link BTree}. + * <p> + * The caller is responsible for writing the {@link Checkpoint} record onto + * the store. + * <p> + * The class identified by {@link IndexMetadata#getCheckpointClassName()} + * MUST declare a public constructor with the following method signature + * + * <pre> + * ...( BTree btree ) + * </pre> + * + * @return The {@link Checkpoint}. + */ + @SuppressWarnings("unchecked") + final private Checkpoint newCheckpoint() { + + try { + + @SuppressWarnings("rawtypes") + final Class cl = Class.forName(metadata.getCheckpointClassName()); + + /* + * Note: A NoSuchMethodException thrown here means that you did not + * declare the required public constructor on the Checkpoint class + * [cl]. + */ + + @SuppressWarnings("rawtypes") + final Constructor ctor = cl.getConstructor(new Class[] { + BTree.class // + }); + + final Checkpoint checkpoint = (Checkpoint) ctor + .newInstance(new Object[] { // + this // + }); + + return checkpoint; + + } catch(Exception ex) { + + throw new RuntimeException(ex); + + } + + } + final public Checkpoint getCheckpoint() { if (checkpoint == null) @@ -1249,6 +1302,12 @@ } + final public ICloseableIterator<?> scan() { + + return new EntryScanIterator(rangeIterator()); + + } + /** * Remove all entries in the B+Tree. * <p> Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/Checkpoint.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/Checkpoint.java 2012-06-29 13:00:40 UTC (rev 6371) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/Checkpoint.java 2012-06-29 20:39:41 UTC (rev 6372) @@ -31,7 +31,10 @@ import com.bigdata.htree.HTree; import com.bigdata.io.SerializerUtil; +import com.bigdata.journal.AbstractJournal; +import com.bigdata.journal.Name2Addr; import com.bigdata.rawstore.IRawStore; +import com.bigdata.stream.Stream; /** * A checkpoint record is written each time the btree is flushed to the @@ -335,6 +338,8 @@ * clean and the root address from the last {@link Checkpoint} record is * used. Otherwise the address of the root is used (in which case it MUST be * defined). + * <p> + * Note: <strong>This method is invoked by reflection.</strong> * * @param btree * The btree. @@ -399,6 +404,8 @@ * clean and the root address from the last {@link Checkpoint} record is * used. Otherwise the address of the root is used (in which case it MUST be * defined). + * <p> + * Note: <strong>This method is invoked by reflection.</strong> * * @param htree * The {@link HTree}. @@ -441,6 +448,63 @@ } + /** + * Creates a {@link Checkpoint} record from an {@link HTree}. + * <p> + * Pre-conditions: + * <ul> + * <li>The root is clean.</li> + * <li>The metadata record is clean.</li> + * <li>The optional bloom filter is clean if it is defined.</li> + * </ul> + * Note: if the root is <code>null</code> then the root is assumed to be + * clean and the root address from the last {@link Checkpoint} record is + * used. Otherwise the address of the root is used (in which case it MUST be + * defined). + * <p> + * Note: <strong>This method is invoked by reflection.</strong> + * + * @param stream + * The {@link HTree}. + */ + public Checkpoint(final Stream stream) { + + this(stream.getMetadataAddr(),// + /* + * root node or leaf. + * + * Note: if the [root] reference is not defined then we use the + * address in the last checkpoint record. if that is 0L then + * there is no root and a new root leaf will be created on + * demand. + */ + stream.getRootAddr(),// + /* + * optional bloom filter. + * + * Note: if the [bloomFilter] reference is not defined then we + * use the address in the last checkpoint record. if that is 0L + * then there is no bloom filter. If the [bloomFilter] reference + * is defined but the bloom filter has been disabled, then we + * also write a 0L so that the bloom filter is no longer + * reachable from the new checkpoint. + */ +// (htree.bloomFilter == null ? htree.getCheckpoint() +// .getBloomFilterAddr() +// : htree.bloomFilter.isEnabled() ? htree.bloomFilter +// .getAddr() : 0L),// + 0L, // TODO No bloom filter yet. Do we want to support this? + 0, // htree.height,// Note: HTree is not balanced (height not uniform) + 0L,//stream.getNodeCount(),// + 0L,//stream.getLeafCount(),// + stream.rangeCount(),// + 0L,//stream.getCounter().get(),// + stream.getRecordVersion(),// + IndexTypeEnum.Stream // IndexTypeEnum + ); + + } + private Checkpoint(final long addrMetadata, final long addrRoot, final long addrBloomFilter, final int height, final long nnodes, final long nleaves, final long nentries, final long counter, Added: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/EntryScanIterator.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/EntryScanIterator.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/EntryScanIterator.java 2012-06-29 20:39:41 UTC (rev 6372) @@ -0,0 +1,76 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 29, 2012 + */ +package com.bigdata.btree; + +import com.bigdata.striterator.ICloseableIterator; + +/** + * Iterator visits index entries (dereferencing visited tuples to the + * application objects stored within those tuples). + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ +@SuppressWarnings("rawtypes") +public final class EntryScanIterator implements ICloseableIterator { + + private final ITupleIterator src; + + public EntryScanIterator(final ITupleIterator src) { + + if (src == null) + throw new IllegalArgumentException(); + + this.src = src; + + } + + @Override + public boolean hasNext() { + return src.hasNext(); + } + + @Override + public Object next() { + + final ITuple t = src.next(); + + // Resolve to the index entry. + return t.getObject(); + + } + + @Override + public void remove() { + src.remove(); + } + + @Override + public void close() { + // NOP + } + +} \ No newline at end of file Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/HTreeIndexMetadata.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/HTreeIndexMetadata.java 2012-06-29 13:00:40 UTC (rev 6371) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/HTreeIndexMetadata.java 2012-06-29 20:39:41 UTC (rev 6372) @@ -273,12 +273,24 @@ } - @Override + /** + * The initial version. + */ + private static transient final int VERSION0 = 0x0; + + /** + * The version that will be serialized by this class. + */ + private static transient final int CURRENT_VERSION = VERSION0; + + @Override public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException { super.readExternal(in); + final int version = LongPacker.unpackInt(in); + keyLen = LongPacker.unpackInt(in); addressBits = LongPacker.unpackInt(in); @@ -290,10 +302,12 @@ @Override public void writeExternal(final ObjectOutput out) throws IOException { - final int version = CURRENT_VERSION; - super.writeExternal(out); + final int version = CURRENT_VERSION; + + LongPacker.packLong(out, version); + LongPacker.packLong(out, keyLen); LongPacker.packLong(out, addressBits); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/ICheckpointProtocol.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/ICheckpointProtocol.java 2012-06-29 13:00:40 UTC (rev 6371) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/ICheckpointProtocol.java 2012-06-29 20:39:41 UTC (rev 6372) @@ -1,9 +1,8 @@ package com.bigdata.btree; -import java.util.Iterator; - import com.bigdata.counters.ICounterSetAccess; import com.bigdata.journal.AbstractJournal; +import com.bigdata.journal.AbstractTask; import com.bigdata.journal.ICommitter; import com.bigdata.journal.Name2Addr; import com.bigdata.journal.Name2Addr.Entry; @@ -13,6 +12,15 @@ * Interface in support of the {@link Checkpoint} record protocol. * * @author tho...@us... + * + * TODO There should be a high level method to insert objects into the + * index (index "entries" not tuples - the index will need to compute + * the appropriate key, etc. in an implementation dependent manner). + * + * TODO Try to lift out an abstract implementation of this interface for + * HTree, BTree, and Stream. This will be another step towards GIST + * support. There are protected methods which are used on those classes + * which should be lifted into the abstract base class. */ public interface ICheckpointProtocol extends ICommitter, ICounterSetAccess { @@ -42,8 +50,9 @@ public long getMetadataAddr(); /** - * The address of the last written root node or leaf -or- 0L if there is - * no root and one should be created on demand. + * The address of the last written root of the persistent data structure + * -or- <code>0L</code> if there is no root. A <code>0L</code> return may be + * an indication that an empty data structure will be created on demand. */ public long getRootAddr(); @@ -122,10 +131,6 @@ * scale-out. * * @see IIndex#getIndexMetadata() - * - * TODO This needs to be abstracted to an interface with different - * implementation classes for different kinds of persistence capable - * data structures (HTree, BTree, named solution sets, etc). */ public IndexMetadata getIndexMetadata(); @@ -149,18 +154,59 @@ /** * Visit all entries in the index in the natural order of the index. - * <p> - * Note: Some implementations MAY return an {@link ICloseableIterator}. The - * caller needs to be aware of this and handle close any obtained iterator - * which implements that interface. - * - * @see IRangeQuery#rangeIterator() */ - public Iterator rangeIterator(); + public ICloseableIterator<?> scan(); /** * Remove all entries in the index. */ public void removeAll(); + /* + * reopen() / close() protocol + */ + + /** + * (Re-) open the index. This method is part of a {@link #close()} / + * {@link #reopen()} protocol. That protocol may be used to reduce the + * resource burden of an index. This method is automatically invoked by a + * variety of methods that need to ensure that the index is available for + * use. + * + * @see #close() + * @see #isOpen() + * @see #getRoot() + */ + public void reopen(); + + /** + * The contract for {@link #close()} is to reduce the resource burden of the + * index while not rendering the index inoperative. An index that has been + * {@link #close() closed} MAY be {@link #reopen() reopened} at any time + * (conditional on the continued availability of the backing store). Such an + * index reference remains valid after a {@link #close()}. A closed index is + * transparently {@link #reopen() reopened} by any access to the index data + * (scanning the index, probing the index, etc). + * <p> + * Note: A {@link #close()} on a dirty index MUST discard writes rather than + * flushing them to the store and MUST NOT update its {@link Checkpoint} + * record - ({@link #close()} is used to discard indices with partial writes + * when an {@link AbstractTask} fails). If you are seeking to + * {@link #close()} a mutable index view that state can be recovered by + * {@link #reopen()} then you MUST write a new {@link Checkpoint} record + * before closing the index. + */ + public void close(); + + /** + * An "open" index has may have some buffered data. A closed index will have + * to re-read any backing data from the backing store. + * + * @return If the index is "open". + * + * @see #close() + * @see #reopen() + */ + public boolean isOpen(); + } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/IndexMetadata.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/IndexMetadata.java 2012-06-29 13:00:40 UTC (rev 6371) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/IndexMetadata.java 2012-06-29 20:39:41 UTC (rev 6372) @@ -2444,7 +2444,7 @@ /** * The initial version. */ - protected static transient final int VERSION0 = 0x0; + private static transient final int VERSION0 = 0x0; /** * This version adds support for {@link ILeafData#getRawRecord(int)} and @@ -2452,19 +2452,19 @@ * earlier versions and {@link IndexMetadata#getMaxRecLen()} will report * {@link Options#DEFAULT_MAX_REC_LEN}. */ - protected static transient final int VERSION1 = 0x1; + private static transient final int VERSION1 = 0x1; /** * This version adds support for {@link HTree}. This includes * {@link #addressBits} and {@link #htreeClassName}. */ - protected static transient final int VERSION2 = 0x2; + private static transient final int VERSION2 = 0x2; /** * This version adds support for a fixed length key option for the * {@link HTree} using {@link #keyLen}. */ - protected static transient final int VERSION3 = 0x3; + private static transient final int VERSION3 = 0x3; /** * This version moves the {@link HTree} specific metadata into a derived @@ -2474,18 +2474,18 @@ * {@link #indexType} field. This field defaults to * {@link IndexTypeEnum#BTree} for all prior versions. */ - protected static transient final int VERSION4 = 0x4; + private static transient final int VERSION4 = 0x4; /** * The version that will be serialized by this class. */ - protected static transient final int CURRENT_VERSION = VERSION4; + private static transient final int CURRENT_VERSION = VERSION4; /** * The actual version as set by {@link #readExternal(ObjectInput)} and * {@link #writeExternal(ObjectOutput)}. */ - protected transient int version; + private transient int version; /** * @todo review generated record for compactness. @@ -2871,105 +2871,7 @@ } /** - * Create a {@link Checkpoint} for a {@link BTree}. * <p> - * The caller is responsible for writing the {@link Checkpoint} record onto - * the store. - * <p> - * The class identified by {@link #getCheckpointClassName()} MUST declare a - * public constructor with the following method signature - * - * <pre> - * ...( BTree btree ) - * </pre> - * - * @param btree - * The {@link BTree}. - * - * @return The {@link Checkpoint}. - */ - @SuppressWarnings("unchecked") - final public Checkpoint newCheckpoint(final BTree btree) { - - try { - - final Class cl = Class.forName(getCheckpointClassName()); - - /* - * Note: A NoSuchMethodException thrown here means that you did not - * declare the required public constructor. - */ - - final Constructor ctor = cl.getConstructor(new Class[] { - BTree.class // - }); - - final Checkpoint checkpoint = (Checkpoint) ctor - .newInstance(new Object[] { // - btree // - }); - - return checkpoint; - - } catch(Exception ex) { - - throw new RuntimeException(ex); - - } - - } - - /** - * Create a {@link Checkpoint} for a {@link BTree}. - * <p> - * The caller is responsible for writing the {@link Checkpoint} record onto - * the store. - * <p> - * The class identified by {@link #getCheckpointClassName()} MUST declare a - * public constructor with the following method signature - * - * <pre> - * ...( HTree btree ) - * </pre> - * - * @param htree - * The {@link HTree}. - * - * @return The {@link Checkpoint}. - */ - @SuppressWarnings("unchecked") - final public Checkpoint newCheckpoint(final HTree htree) { - - try { - - final Class cl = Class.forName(getCheckpointClassName()); - - /* - * Note: A NoSuchMethodException thrown here means that you did not - * declare the required public constructor. - */ - - final Constructor ctor = cl.getConstructor(new Class[] { - HTree.class // - }); - - final Checkpoint checkpoint = (Checkpoint) ctor - .newInstance(new Object[] { // - htree // - }); - - return checkpoint; - - } catch(Exception ex) { - - throw new RuntimeException(ex); - - } - - } - - /** - * <p> * Factory for thread-safe {@link IKeyBuilder} objects for use by * {@link ITupleSerializer#serializeKey(Object)} and possibly others. * </p> Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/IndexTypeEnum.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/IndexTypeEnum.java 2012-06-29 13:00:40 UTC (rev 6371) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/IndexTypeEnum.java 2012-06-29 20:39:41 UTC (rev 6372) @@ -31,15 +31,15 @@ */ public enum IndexTypeEnum { - /** BTree. */ - BTree((short) 0), + /** BTree. */ + BTree((short) 0), - /** Extendable hash tree. */ - HTree((short) 1), - - /** Order preserving solution set. */ - SolutionSet((short) 2); + /** Extendible hash tree. */ + HTree((short) 1), + /** Stream. */ + Stream((short) 2); + private IndexTypeEnum(final short code) { this.code = code; @@ -61,7 +61,7 @@ case 1: return HTree; case 2: - return SolutionSet; + return Stream; default: throw new IllegalArgumentException("code=" + code); } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/htree/AbstractHTree.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/htree/AbstractHTree.java 2012-06-29 13:00:40 UTC (rev 6371) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/htree/AbstractHTree.java 2012-06-29 20:39:41 UTC (rev 6372) @@ -632,23 +632,8 @@ final protected NodeSerializer nodeSer; /** - * The contract for {@link #close()} is to reduce the resource burden of the - * index (by discarding buffers) while not rendering the index inoperative. - * Unless the {@link AbstractHTree} {@link #isTransient()}, a HTree that - * has been {@link #close() closed} MAY be {@link #reopen() reopened} at any - * time (conditional on the continued availability of the backing store). - * Such an index reference remains valid after a {@link #close()}. A closed - * index is transparently restored by either {@link #getRoot()} or - * {@link #reopen()}. + * {@inheritDoc} * <p> - * Note: A {@link #close()} on a dirty index MUST discard writes rather than - * flushing them to the store and MUST NOT update its {@link Checkpoint} - * record - ({@link #close()} is used to discard indices with partial - * writes when an {@link AbstractTask} fails). If you are seeking to - * {@link #close()} a mutable {@link HTree} that it state can be recovered - * by {@link #reopen()} then you MUST write a new {@link Checkpoint} record - * before closing the index. - * <p> * Note: CLOSING A TRANSIENT INDEX WILL DISCARD ALL DATA! * <p> * This implementation clears the hard reference queue (releasing all node @@ -739,19 +724,15 @@ } /** - * This is part of a {@link #close()}/{@link #reopen()} protocol that may - * be used to reduce the resource burden of an {@link AbstractBTree}. The - * method delegates to {@link #_reopen()} if double-checked locking - * demonstrates that the {@link #root} is <code>null</code> (indicating - * that the index has been closed). This method is automatically invoked by - * a variety of methods that need to ensure that the index is available for + * {@inheritDoc}. + * <p> + * This method delegates to {@link #_reopen()} if double-checked locking + * demonstrates that the {@link #root} is <code>null</code> (indicating that + * the index has been closed). This method is automatically invoked by a + * variety of methods that need to ensure that the index is available for * use. - * - * @see #close() - * @see #isOpen() - * @see #getRoot() */ - final protected void reopen() { + final public void reopen() { if (root == null) { @@ -793,16 +774,6 @@ */ abstract protected void _reopen(); - /** - * An "open" index has its buffers and root node in place rather than having - * to reallocate buffers or reload the root node from the store. - * - * @return If the index is "open". - * - * @see #close() - * @see #reopen() - * @see #getRoot() - */ final public boolean isOpen() { return root != null; Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/htree/HTree.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/htree/HTree.java 2012-06-29 13:00:40 UTC (rev 6371) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/htree/HTree.java 2012-06-29 20:39:41 UTC (rev 6372) @@ -44,6 +44,7 @@ import com.bigdata.btree.BTreeCounters; import com.bigdata.btree.BytesUtil; import com.bigdata.btree.Checkpoint; +import com.bigdata.btree.EntryScanIterator; import com.bigdata.btree.HTreeIndexMetadata; import com.bigdata.btree.ICounter; import com.bigdata.btree.IDirtyListener; @@ -62,6 +63,7 @@ import com.bigdata.mdi.LocalPartitionMetadata; import com.bigdata.rawstore.Bytes; import com.bigdata.rawstore.IRawStore; +import com.bigdata.striterator.ICloseableIterator; /** * An mutable persistence capable extensible hash tree. @@ -425,14 +427,14 @@ * @param store * The store. * @param checkpoint - * A {@link Checkpoint} record for that {@link BTree}. + * A {@link Checkpoint} record for that {@link HTree}. * @param metadata - * The metadata record for that {@link BTree}. + * The metadata record for that {@link HTree}. * @param readOnly - * When <code>true</code> the {@link BTree} will be immutable. + * When <code>true</code> the {@link HTree} will be immutable. * - * @see BTree#create(IRawStore, IndexMetadata) - * @see BTree#load(IRawStore, long, boolean) + * @see HTree#create(IRawStore, IndexMetadata) + * @see HTree#load(IRawStore, long, boolean) */ // * @throws IllegalArgumentException // * if addressBits is LT ONE (1). @@ -521,13 +523,13 @@ } /** - * Sets the {@link #checkpoint} and initializes the mutable fields from the - * � * checkpoint record. In order for this operation to be atomic, the - * caller must be synchronized on the {@link HTree} or otherwise guaranteed - * to have exclusive access, e.g., during the ctor or when the {@link HTree} - * is mutable and access is therefore required to be single-threaded. - */ - private void setCheckpoint(final Checkpoint checkpoint) { + * Sets the {@link #checkpoint} and initializes the mutable fields from the + * checkpoint record. In order for this operation to be atomic, the caller + * must be synchronized on the {@link HTree} or otherwise guaranteed to have + * exclusive access, e.g., during the ctor or when the {@link HTree} is + * mutable and access is therefore required to be single-threaded. + */ + protected void setCheckpoint(final Checkpoint checkpoint) { this.checkpoint = checkpoint; // save reference. @@ -1000,15 +1002,19 @@ if (checkpoint != null && getRoot() != null && checkpoint.getRootAddr() != getRoot().getIdentity()) { + recycle(checkpoint.getRootAddr()); + } if (checkpoint != null) { - recycle(checkpoint.getCheckpointAddr()); + + recycle(checkpoint.getCheckpointAddr()); + } // create new checkpoint record. - checkpoint = metadata.newCheckpoint(this); + checkpoint = newCheckpoint(); // write it on the store. checkpoint.write(store); @@ -1029,6 +1035,55 @@ } + /** + * Create a {@link Checkpoint} for a {@link HTree}. + * <p> + * The caller is responsible for writing the {@link Checkpoint} record onto + * the store. + * <p> + * The class identified by {@link IndexMetadata#getCheckpointClassName()} + * MUST declare a public constructor with the following method signature + * + * <pre> + * ...( HTree htree ) + * </pre> + * + * @return The {@link Checkpoint}. + */ + @SuppressWarnings("unchecked") + final private Checkpoint newCheckpoint() { + + try { + + @SuppressWarnings("rawtypes") + final Class cl = Class.forName(metadata.getCheckpointClassName()); + + /* + * Note: A NoSuchMethodException thrown here means that you did not + * declare the required public constructor on the Checkpoint class + * [cl]. + */ + + @SuppressWarnings("rawtypes") + final Constructor ctor = cl.getConstructor(new Class[] { + HTree.class // + }); + + final Checkpoint checkpoint = (Checkpoint) ctor + .newInstance(new Object[] { // + this // + }); + + return checkpoint; + + } catch(Exception ex) { + + throw new RuntimeException(ex); + + } + + } + /* * CRUD API. * @@ -1609,7 +1664,13 @@ } } - public void removeAll() { + final public ICloseableIterator<?> scan() { + + return new EntryScanIterator(rangeIterator()); + + } + + public void removeAll() { DirectoryPage root = getRoot(); root.removeAll(); @@ -1656,7 +1717,7 @@ * * @return The newly created {@link HTree}. * - * @see #load(IRawStore, long) + * @see #load(IRawStore, long, boolean) * * @throws IllegalStateException * If you attempt to create two {@link HTree} objects from the Added: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/stream/Stream.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/stream/Stream.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/stream/Stream.java 2012-06-29 20:39:41 UTC (rev 6372) @@ -0,0 +1,1329 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 29, 2012 + */ +package com.bigdata.stream; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.OutputStream; +import java.lang.reflect.Constructor; +import java.util.Properties; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Lock; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.InflaterInputStream; + +import org.apache.log4j.Logger; + +import com.bigdata.Banner; +import com.bigdata.BigdataStatics; +import com.bigdata.bop.solutions.SolutionSetStream; +import com.bigdata.btree.AbstractBTree; +import com.bigdata.btree.AbstractNode; +import com.bigdata.btree.BTree; +import com.bigdata.btree.BTreeCounters; +import com.bigdata.btree.Checkpoint; +import com.bigdata.btree.ICheckpointProtocol; +import com.bigdata.btree.IDirtyListener; +import com.bigdata.btree.IndexMetadata; +import com.bigdata.btree.IndexTypeEnum; +import com.bigdata.btree.Node; +import com.bigdata.btree.UnisolatedReadWriteIndex; +import com.bigdata.counters.CounterSet; +import com.bigdata.counters.OneShotInstrument; +import com.bigdata.htree.HTree; +import com.bigdata.io.LongPacker; +import com.bigdata.journal.IIndexManager; +import com.bigdata.rawstore.IRawStore; +import com.bigdata.rwstore.IRWStrategy; +import com.bigdata.service.IBigdataFederation; +import com.bigdata.striterator.ICloseableIterator; + +/** + * A persistence capable stream of "index" entries. The stream maintains the + * order in which the entries were written. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + * + * TODO Write unit tests ({@link Stream} is abstract right now which + * makes that difficult). Focus on the checkpoint protocol as the + * underlying stream is implemented by the low level storage engine and + * tested separately. + */ +abstract public class Stream implements ICheckpointProtocol { + + private static final Logger log = Logger.getLogger(Stream.class); + + /** + * The index is already closed. + */ + protected static final String ERROR_CLOSED = "Closed"; + + // /** + // * A parameter was less than zero. + // */ + // protected static final String ERROR_LESS_THAN_ZERO = "Less than zero"; + // + // /** + // * A parameter was too large. + // */ + // protected static final String ERROR_TOO_LARGE = "Too large"; + // + /** + * The index is read-only but a mutation operation was requested. + */ + protected static final String... [truncated message content] |
From: <tho...@us...> - 2012-07-01 21:37:23
|
Revision: 6374 http://bigdata.svn.sourceforge.net/bigdata/?rev=6374&view=rev Author: thompsonbry Date: 2012-07-01 21:37:12 +0000 (Sun, 01 Jul 2012) Log Message: ----------- The root cause is the pre-mature resolution of the IV from the RDF Value. The ISPO[] obtained by parsing the INSERT DATA statement does not have the RDF Value objects any more, just the IV objects. Thus, anything unknown can wind up disappearing. Also, it is processing the QuadsData into StatementPatternNodes. Those objects already have blank nodes translated into anonymous variables. The original bnode identity is lost during that translation. The translation is performed by the BlankNodeVarProcessor, which runs before we process the javacc parse tree into the bigdata AST. It seems that we need to do two things: 1. Probably change the ISPO[] to an BigdataStatement[] to ensure that the Value remains available for deferred resolution to the IV. (While I am not convinced that we need to make this change, it is easy to get into trouble because BigdataStatement implements ISPO but the IV does not always have the back reference to the Value). 2. Either (a) associate the anonymous variable with the bnode (this is difficult since variables are canonical in bigdata); (b) do not translate blank nodes to anonymous variables when they appear within a QUAD_DATA production for the INSERT DATA or DELETE DATA clause; or (c) establish a 1-1 correspondence between the name of the anonymous variable and the ID of the blank node such that blank nodes are correlated within the INSERT DATA or DELETE DATA clause (the problem with this last approach is that it does not support "told bnodes"). I have taken approach (1) and (2c). @see https://sourceforge.net/apps/trac/bigdata/ticket/573 (NullPointerException when attempting to INSERT DATA containing a blank node) Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/AbstractGraphDataUpdate.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/CreateGraph.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/update/TestAll.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/update/TestUpdateBootstrap.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/sparql/UpdateExprBuilder.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/sparql/TestUpdateExprBuilder.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/sparql/TestUpdateExprBuilder2.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/TestSparqlUpdate.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/org/openrdf/query/parser/sparql/SPARQLUpdateTest.java Added Paths: ----------- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/dataset-update-example9.trig Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/AbstractGraphDataUpdate.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/AbstractGraphDataUpdate.java 2012-06-30 20:32:50 UTC (rev 6373) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/AbstractGraphDataUpdate.java 2012-07-01 21:37:12 UTC (rev 6374) @@ -30,6 +30,7 @@ import java.util.Map; import com.bigdata.bop.BOp; +import com.bigdata.rdf.model.BigdataStatement; import com.bigdata.rdf.spo.ISPO; /** @@ -49,7 +50,7 @@ interface Annotations extends GraphUpdate.Annotations { /** - * The {@link ISPO}[] data. + * The {@link BigdataStatement}[] data. */ String DATA = "data"; @@ -81,13 +82,13 @@ } - public ISPO[] getData() { + public BigdataStatement[] getData() { - return (ISPO[]) getProperty(Annotations.DATA); + return (BigdataStatement[]) getProperty(Annotations.DATA); } - public void setData(final ISPO[] data) { + public void setData(final BigdataStatement[] data) { setProperty(Annotations.DATA, data); @@ -101,7 +102,7 @@ sb.append(getUpdateType()); - final ISPO[] data = getData(); + final BigdataStatement[] data = getData(); if (data != null) { Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/CreateGraph.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/CreateGraph.java 2012-06-30 20:32:50 UTC (rev 6373) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/CreateGraph.java 2012-07-01 21:37:12 UTC (rev 6374) @@ -30,7 +30,7 @@ import java.util.Map; import com.bigdata.bop.BOp; -import com.bigdata.rdf.spo.ISPO; +import com.bigdata.rdf.model.BigdataStatement; /** * This operation creates a graph in the Graph Store (this operation is a NOP @@ -55,9 +55,9 @@ public interface Annotations extends AbstractOneGraphManagement.Annotations { /** - * The {@link ISPO}[] which provides the provisioning information for - * the named solution set (optional, even when creating a named solution - * set). + * The {@link BigdataStatement}[] which provides the provisioning + * information for the named solution set (optional, even when creating + * a named solution set). */ String PARAMS = "params"; @@ -91,16 +91,16 @@ /** * Return the parameters used to provision a named solution set. */ - public ISPO[] getParams() { + public BigdataStatement[] getParams() { - return (ISPO[]) getProperty(Annotations.PARAMS); - + return (BigdataStatement[]) getProperty(Annotations.PARAMS); + } - public void setParams(final ISPO[] params) { + public void setParams(final BigdataStatement[] params) { setProperty(Annotations.PARAMS, params); - + } } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java 2012-06-30 20:32:50 UTC (rev 6373) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java 2012-07-01 21:37:12 UTC (rev 6374) @@ -1755,7 +1755,7 @@ if (!runOnQueryEngine) { - final ISPO[] stmts = op.getData(); + final BigdataStatement[] stmts = op.getData(); if (log.isDebugEnabled()) log.debug((insert ? "INSERT" : "DELETE") + " DATA: #stmts=" @@ -1763,9 +1763,9 @@ final BigdataSailConnection conn = context.conn.getSailConnection(); - for (ISPO spo : stmts) { + for (BigdataStatement s : stmts) { - addOrRemoveStatement(conn, spo, insert); + addOrRemoveStatementData(conn, s, insert); } @@ -1882,7 +1882,7 @@ } /** - * Insert or remove a statement. + * Insert or remove a statement (INSERT DATA or DELETE DATA). * * @param conn * The connection on which to write the mutation. @@ -1893,15 +1893,21 @@ * <code>false</code> iff the statement is to be removed. * @throws SailException */ - private static void addOrRemoveStatement(final BigdataSailConnection conn, - final ISPO spo, final boolean insert) throws SailException { + private static void addOrRemoveStatementData(final BigdataSailConnection conn, + final BigdataStatement stmt, final boolean insert) throws SailException { - final Resource s = (Resource) spo.s().getValue(); +// final Resource s = (Resource) spo.s().getValue(); +// +// final URI p = (URI) spo.p().getValue(); +// +// final Value o = (Value) spo.o().getValue(); - final URI p = (URI) spo.p().getValue(); + final Resource s = stmt.getSubject(); - final Value o = (Value) spo.o().getValue(); + final URI p = stmt.getPredicate(); + final Value o = stmt.getObject(); + /* * If [c] is not bound, then using an empty Resource[] for the contexts. * @@ -1911,9 +1917,9 @@ * contexts (on remove it is interpreted as a wildcard). */ - final Resource c = (Resource) (spo.c() == null ? null : spo.c() - .getValue()); - + final Resource c = (Resource) (stmt.getContext() == null ? null : stmt + .getContext()); + final Resource[] contexts = (Resource[]) (c == null ? NO_CONTEXTS : new Resource[] { c }); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/update/TestAll.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/update/TestAll.java 2012-06-30 20:32:50 UTC (rev 6373) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/update/TestAll.java 2012-07-01 21:37:12 UTC (rev 6374) @@ -64,11 +64,14 @@ final TestSuite suite = new TestSuite("SPARQL Update Evaluation"); /* - * Boot strapped test suite for core UPDATE functionality. + * Bootstrapped test suite for core UPDATE functionality based on + * BOP evaluation. + * + * Note: This test has been disabled. We are not using the query + * engine to evaluate SPARQL update at this time. */ +// suite.addTestSuite(TestUpdateBootstrap.class); - suite.addTestSuite(TestUpdateBootstrap.class); - /* * The openrdf SPARQL UPDATE test suite. * Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/update/TestUpdateBootstrap.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/update/TestUpdateBootstrap.java 2012-06-30 20:32:50 UTC (rev 6373) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/update/TestUpdateBootstrap.java 2012-07-01 21:37:12 UTC (rev 6374) @@ -68,10 +68,15 @@ import com.bigdata.rdf.spo.SPO; /** - * Boot strapped test suite for core UPDATE functionality. + * Bootstrapped test suite for core UPDATE functionality based on BOP + * evaluation. + * <p> + * Note: We are not using BOP evaluation for SPARQL UPDATE at this time, so this + * test is NOT being run in CI. * * @author <a href="mailto:tho...@us...">Bryan Thompson</a> - * @version $Id$ + * @version $Id: TestUpdateBootstrap.java 6167 2012-03-20 17:47:30Z thompsonbry + * $ */ public class TestUpdateBootstrap extends AbstractASTEvaluationTestCase { @@ -141,7 +146,22 @@ new SPO(dc, rdfsLabel, dcL, g1, StatementEnum.Explicit),// }; - op.setData(data); + /* + * FIXME Finish this test up (again). It is running into a conflict + * with the Value to IV resolution. It seems that it should be using + * BigdataValues here since the lexicon add/resolve step has not yet + * been executed (it runs below). Note that this code is old. It was + * a mock up for the evaluation of SPARQL UPDATE on the query engine. + * We do not evaluate SPARQL update that way, so this class could just + * go away. + * + * @see <a + * href="https://sourceforge.net/apps/trac/bigdata/ticket/573"> + * NullPointerException when attempting to INSERT DATA containing a + * blank node </a> + */ + //op.setData(data); + fail("Finish test"); } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/sparql/UpdateExprBuilder.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/sparql/UpdateExprBuilder.java 2012-06-30 20:32:50 UTC (rev 6373) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/sparql/UpdateExprBuilder.java 2012-07-01 21:37:12 UTC (rev 6374) @@ -38,7 +38,11 @@ import org.openrdf.query.algebra.StatementPattern.Scope; import com.bigdata.bop.BOpUtility; +import com.bigdata.rdf.model.BigdataBNode; +import com.bigdata.rdf.model.BigdataResource; import com.bigdata.rdf.model.BigdataStatement; +import com.bigdata.rdf.model.BigdataURI; +import com.bigdata.rdf.model.BigdataValue; import com.bigdata.rdf.model.StatementEnum; import com.bigdata.rdf.sail.sparql.ast.ASTAdd; import com.bigdata.rdf.sail.sparql.ast.ASTClear; @@ -130,7 +134,7 @@ final InsertData op = new InsertData(); - op.setData(doQuadsData(node, data)); + op.setData(doQuadsData(node, data, true/* allowBlankNodes */)); return op; @@ -148,7 +152,8 @@ final DeleteData op = new DeleteData(); - op.setData(doQuadsData(node, data)); + // blank nodes are disallowed within DELETE DATA (per the spec). + op.setData(doQuadsData(node, data, false/* allowBlankNodes */)); return op; @@ -403,14 +408,14 @@ op.setTargetSolutionSet(target.getValueExpression().getName()); - final ISPO[] params = doQuadsData(node, data); + final BigdataStatement[] params = doQuadsData(node, data, true/* allowBlankNodes */); if (params != null && params.length > 0) { - + op.setParams(params); - + } - + } if (node.isSilent()) @@ -689,9 +694,13 @@ * @return A flat {@link ISPO}[] modeling the quad data. * * @throws VisitorException + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/573"> + * NullPointerException when attempting to INSERT DATA containing a + * blank node </a> */ - private ISPO[] doQuadsData(final Node node, final Object data) - throws VisitorException { + private BigdataStatement[] doQuadsData(final Node node, final Object data, + final boolean allowBlankNodes) throws VisitorException { final GroupGraphPattern parentGP = graphPattern; graphPattern = new GroupGraphPattern(); @@ -746,26 +755,88 @@ while (itr.hasNext()) { final StatementPatternNode sp = itr.next(); + + if (!allowBlankNodes) { + // Blank nodes are not permitted in DELETE DATA. + assertNotAnonymousVariable(sp.s()); + assertNotAnonymousVariable(sp.o()); + } - final ISPO spo = new SPO(// - sp.s().getValue().getIV(), // - sp.p().getValue().getIV(), // - sp.o().getValue().getIV(),// - (sp.c() != null ? sp.c().getValue().getIV() : null),// - StatementEnum.Explicit// - ); + final BigdataResource s = (BigdataResource) toValue(sp.s()); + final BigdataValue o = toValue(sp.o()); + + final BigdataStatement spo = context.valueFactory.createStatement(// + (BigdataResource) s, // + (BigdataURI) sp.p().getValue(), // + (BigdataValue) o,// + (BigdataResource) (sp.c() != null ? sp.c().getValue(): null),// + StatementEnum.Explicit// + ); +// final ISPO spo = new SPO(// +// sp.s().getValue().getIV(), // +// sp.p().getValue().getIV(), // +// sp.o().getValue().getIV(),// +// (sp.c() != null ? sp.c().getValue().getIV() : null),// +// StatementEnum.Explicit// +// ); stmts.add(spo); } - final ISPO[] a = stmts.toArray(new ISPO[stmts.size()]); + final BigdataStatement[] a = stmts.toArray(new BigdataStatement[stmts + .size()]); return a; } /** + * Method used to correctly reject blank nodes in a DELETE DATA clause. + * + * @param t + * A Subject or Object term. + */ + private void assertNotAnonymousVariable(final TermNode t) + throws VisitorException { + + if (!t.isVariable()) + return; + + final VarNode v = (VarNode) t; + + if (v.isAnonymous()) + throw new VisitorException( + "BlankNode not permitted in this context: " + t); + + } + + /** + * Convert the {@link TermNode} to a {@link BigdataValue}. IFF the + * {@link TermNode} is an anonymous variable, then it is converted into a + * blank node whose ID is the name of that anonymous variable. This is used + * to turn anonymous variables back into blank nodes for INSERT DATA (DELETE + * DATA does not allow blank nodes). + * + * @param t + * The {@link TermNode}. + * + * @return The {@link BigdataValue}. + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/573"> + * NullPointerException when attempting to INSERT DATA containing a + * blank node </a> + */ + private BigdataValue toValue(final TermNode t) { + if (t.isVariable() && ((VarNode) t).isAnonymous()) { + final BigdataBNode s = context.valueFactory.createBNode(t + .getValueExpression().getName()); + return s; + } + return t.getValue(); + } + + /** * Collect quads patterns for a DELETE/INSERT operation. This form allows * variables in the quads patterns. * Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/sparql/TestUpdateExprBuilder.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/sparql/TestUpdateExprBuilder.java 2012-06-30 20:32:50 UTC (rev 6373) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/sparql/TestUpdateExprBuilder.java 2012-07-01 21:37:12 UTC (rev 6374) @@ -31,9 +31,16 @@ import org.openrdf.query.MalformedQueryException; import org.openrdf.query.algebra.StatementPattern.Scope; +import org.semanticweb.yars.nx.namespace.RDF; import com.bigdata.rdf.internal.IV; import com.bigdata.rdf.internal.XSD; +import com.bigdata.rdf.model.BigdataBNode; +import com.bigdata.rdf.model.BigdataLiteral; +import com.bigdata.rdf.model.BigdataResource; +import com.bigdata.rdf.model.BigdataStatement; +import com.bigdata.rdf.model.BigdataURI; +import com.bigdata.rdf.model.BigdataValue; import com.bigdata.rdf.model.StatementEnum; import com.bigdata.rdf.sail.sparql.ast.ParseException; import com.bigdata.rdf.sail.sparql.ast.TokenMgrError; @@ -60,8 +67,6 @@ import com.bigdata.rdf.sparql.ast.SubqueryRoot; import com.bigdata.rdf.sparql.ast.UpdateRoot; import com.bigdata.rdf.sparql.ast.VarNode; -import com.bigdata.rdf.spo.ISPO; -import com.bigdata.rdf.spo.SPO; /** * Test suite for {@link UpdateExprBuilder}. @@ -991,7 +996,7 @@ * } * </pre> */ - @SuppressWarnings("rawtypes") +// @SuppressWarnings("rawtypes") public void test_insert_data() throws MalformedQueryException, TokenMgrError, ParseException { @@ -1009,17 +1014,29 @@ expected.addChild(op); - final IV book1 = makeIV(valueFactory.createURI("http://example/book1")); - final IV dcCreator = makeIV(valueFactory.createURI("http://purl.org/dc/elements/1.1/creator")); - final IV dcTitle = makeIV(valueFactory.createURI("http://purl.org/dc/elements/1.1/title")); - final IV label1 = makeIV(valueFactory.createLiteral("A new book")); - final IV label2 = makeIV(valueFactory.createLiteral("A.N.Other")); + final BigdataURI book1 = valueFactory.createURI("http://example/book1"); + final BigdataURI dcCreator = valueFactory.createURI("http://purl.org/dc/elements/1.1/creator"); + final BigdataURI dcTitle = valueFactory.createURI("http://purl.org/dc/elements/1.1/title"); + final BigdataLiteral label1 = valueFactory.createLiteral("A new book"); + final BigdataLiteral label2 = valueFactory.createLiteral("A.N.Other"); - final ISPO[] data = new ISPO[] { // - new SPO(book1, dcTitle, label1, null, + final BigdataStatement[] data = new BigdataStatement[] { // + valueFactory.createStatement(// + (BigdataResource)book1,// + (BigdataURI)dcTitle,// + (BigdataValue)label1, // + null, StatementEnum.Explicit),// - new SPO(book1, dcCreator, label2, null, + valueFactory.createStatement(// + (BigdataResource)book1, // + (BigdataURI)dcCreator, // + (BigdataValue) label2, // + null,// StatementEnum.Explicit),// +// new SPO(book1, dcTitle, label1, null, +// StatementEnum.Explicit),// +// new SPO(book1, dcCreator, label2, null, +// StatementEnum.Explicit),// }; op.setData(data); @@ -1039,7 +1056,7 @@ * { GRAPH <http://example/bookStore> { <http://example/book1> ns:price 42 } } * </pre> */ - @SuppressWarnings("rawtypes") +// @SuppressWarnings("rawtypes") public void test_insert_data_quads() throws MalformedQueryException, TokenMgrError, ParseException { @@ -1055,13 +1072,18 @@ expected.addChild(op); - final IV bookstore = makeIV(valueFactory.createURI("http://example/bookStore")); - final IV book1 = makeIV(valueFactory.createURI("http://example/book1")); - final IV price = makeIV(valueFactory.createURI("http://example.org/ns#price")); - final IV i42 = makeIV(valueFactory.createLiteral("42",XSD.INTEGER)); + final BigdataURI bookstore = valueFactory.createURI("http://example/bookStore"); + final BigdataURI book1 = valueFactory.createURI("http://example/book1"); + final BigdataURI price = valueFactory.createURI("http://example.org/ns#price"); + final BigdataLiteral i42 = valueFactory.createLiteral("42",XSD.INTEGER); - final ISPO[] data = new ISPO[] { // - new SPO(book1, price, i42, bookstore, StatementEnum.Explicit),// + final BigdataStatement[] data = new BigdataStatement[] { // + valueFactory.createStatement(// + (BigdataResource)book1,// + (BigdataURI)price, // + (BigdataValue)i42, // + (BigdataResource)bookstore, // + StatementEnum.Explicit),// }; op.setData(data); @@ -1076,6 +1098,51 @@ /** * <pre> + * INSERT DATA { _:bnode a <http://example/Foo> . } + * </pre> + * @throws MalformedQueryException + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/573"> + * NullPointerException when attempting to INSERT DATA containing a + * blank node </a> + */ + public void test_insert_data_ticket573() throws MalformedQueryException { + + final String sparql = "INSERT DATA { _:bnode a <http://example/Foo> . }"; + + final UpdateRoot expected = new UpdateRoot(); + { + + final InsertData op = new InsertData(); + + expected.addChild(op); + + final BigdataBNode bnode = valueFactory.createBNode("-anon-1"); +// final BigdataBNode bnode = valueFactory.createBNode("bnode"); + final BigdataURI rdfType = valueFactory.createURI(RDF.TYPE.toString()); + final BigdataURI foo = valueFactory.createURI("http://example/Foo"); + + final BigdataStatement[] data = new BigdataStatement[] { // + valueFactory.createStatement(// + bnode,// + rdfType,// + foo, // + null,// c + StatementEnum.Explicit),// + }; + + op.setData(data); + + } + + final UpdateRoot actual = parseUpdate(sparql, baseURI); + + assertSameAST(sparql, expected, actual); + + } + + /** + * <pre> * PREFIX dc: <http://purl.org/dc/elements/1.1/> * PREFIX ns: <http://example.org/ns#> * INSERT DATA @@ -1086,7 +1153,7 @@ * } * </pre> */ - @SuppressWarnings("rawtypes") +// @SuppressWarnings("rawtypes") public void test_insert_data_triples_then_quads() throws MalformedQueryException, TokenMgrError, ParseException { @@ -1106,21 +1173,33 @@ expected.addChild(op); - final IV book1 = makeIV(valueFactory.createURI("http://example/book1")); - final IV dcCreator = makeIV(valueFactory.createURI("http://purl.org/dc/elements/1.1/creator")); - final IV dcTitle = makeIV(valueFactory.createURI("http://purl.org/dc/elements/1.1/title")); - final IV label1 = makeIV(valueFactory.createLiteral("A new book")); - final IV label2 = makeIV(valueFactory.createLiteral("A.N.Other")); - final IV bookstore = makeIV(valueFactory.createURI("http://example/bookStore")); - final IV price = makeIV(valueFactory.createURI("http://example.org/ns#price")); - final IV i42 = makeIV(valueFactory.createLiteral("42",XSD.INTEGER)); + final BigdataURI book1 = valueFactory.createURI("http://example/book1"); + final BigdataURI dcCreator = valueFactory.createURI("http://purl.org/dc/elements/1.1/creator"); + final BigdataURI dcTitle = valueFactory.createURI("http://purl.org/dc/elements/1.1/title"); + final BigdataLiteral label1 = valueFactory.createLiteral("A new book"); + final BigdataLiteral label2 = valueFactory.createLiteral("A.N.Other"); + final BigdataURI bookstore = valueFactory.createURI("http://example/bookStore"); + final BigdataURI price = valueFactory.createURI("http://example.org/ns#price"); + final BigdataLiteral i42 = valueFactory.createLiteral("42",XSD.INTEGER); - final ISPO[] data = new ISPO[] { // - new SPO(book1, dcTitle, label1, null, + final BigdataStatement[] data = new BigdataStatement[] { // + valueFactory.createStatement(// + (BigdataResource)book1,// + (BigdataURI)dcTitle,// + (BigdataValue)label1,// + null,// StatementEnum.Explicit),// - new SPO(book1, dcCreator, label2, null, + valueFactory.createStatement(// + (BigdataResource)book1,// + (BigdataURI)dcCreator, // + (BigdataValue)label2,// + null,// StatementEnum.Explicit),// - new SPO(book1, price, i42, bookstore, + valueFactory.createStatement(// + (BigdataResource)book1, // + (BigdataURI)price, // + (BigdataValue)i42, // + (BigdataResource)bookstore,// StatementEnum.Explicit),// }; @@ -1146,7 +1225,7 @@ * } * </pre> */ - @SuppressWarnings("rawtypes") +// @SuppressWarnings("rawtypes") public void test_insert_data_quads_then_triples() throws MalformedQueryException, TokenMgrError, ParseException { @@ -1166,21 +1245,33 @@ expected.addChild(op); - final IV book1 = makeIV(valueFactory.createURI("http://example/book1")); - final IV dcCreator = makeIV(valueFactory.createURI("http://purl.org/dc/elements/1.1/creator")); - final IV dcTitle = makeIV(valueFactory.createURI("http://purl.org/dc/elements/1.1/title")); - final IV label1 = makeIV(valueFactory.createLiteral("A new book")); - final IV label2 = makeIV(valueFactory.createLiteral("A.N.Other")); - final IV bookstore = makeIV(valueFactory.createURI("http://example/bookStore")); - final IV price = makeIV(valueFactory.createURI("http://example.org/ns#price")); - final IV i42 = makeIV(valueFactory.createLiteral("42",XSD.INTEGER)); + final BigdataURI book1 = valueFactory.createURI("http://example/book1"); + final BigdataURI dcCreator = valueFactory.createURI("http://purl.org/dc/elements/1.1/creator"); + final BigdataURI dcTitle = valueFactory.createURI("http://purl.org/dc/elements/1.1/title"); + final BigdataLiteral label1 = valueFactory.createLiteral("A new book"); + final BigdataLiteral label2 = valueFactory.createLiteral("A.N.Other"); + final BigdataURI bookstore = valueFactory.createURI("http://example/bookStore"); + final BigdataURI price = valueFactory.createURI("http://example.org/ns#price"); + final BigdataLiteral i42 = valueFactory.createLiteral("42",XSD.INTEGER); - final ISPO[] data = new ISPO[] { // - new SPO(book1, price, i42, bookstore, + final BigdataStatement[] data = new BigdataStatement[] { // + valueFactory.createStatement(// + (BigdataResource)book1, // + (BigdataURI)price, // + (BigdataValue)i42, // + (BigdataResource)bookstore,// StatementEnum.Explicit),// - new SPO(book1, dcTitle, label1, null, + valueFactory.createStatement(// + (BigdataResource)book1,// + (BigdataURI)dcTitle,// + (BigdataValue)label1,// + null,// StatementEnum.Explicit),// - new SPO(book1, dcCreator, label2, null, + valueFactory.createStatement(// + (BigdataResource)book1, // + (BigdataURI)dcCreator,// + (BigdataValue)label2, // + null,// StatementEnum.Explicit),// }; op.setData(data); @@ -1205,7 +1296,7 @@ * } * </pre> */ - @SuppressWarnings("rawtypes") +// @SuppressWarnings("rawtypes") public void test_insert_data_triples_quads_triples() throws MalformedQueryException, TokenMgrError, ParseException { @@ -1225,25 +1316,37 @@ expected.addChild(op); - final IV book1 = makeIV(valueFactory.createURI("http://example/book1")); - final IV dcCreator = makeIV(valueFactory.createURI("http://purl.org/dc/elements/1.1/creator")); - final IV dcTitle = makeIV(valueFactory.createURI("http://purl.org/dc/elements/1.1/title")); - final IV label1 = makeIV(valueFactory.createLiteral("A new book")); - final IV label2 = makeIV(valueFactory.createLiteral("A.N.Other")); - final IV bookstore = makeIV(valueFactory.createURI("http://example/bookStore")); - final IV price = makeIV(valueFactory.createURI("http://example.org/ns#price")); - final IV i42 = makeIV(valueFactory.createLiteral("42",XSD.INTEGER)); + final BigdataURI book1 = valueFactory.createURI("http://example/book1"); + final BigdataURI dcCreator = valueFactory.createURI("http://purl.org/dc/elements/1.1/creator"); + final BigdataURI dcTitle = valueFactory.createURI("http://purl.org/dc/elements/1.1/title"); + final BigdataLiteral label1 = valueFactory.createLiteral("A new book"); + final BigdataLiteral label2 = valueFactory.createLiteral("A.N.Other"); + final BigdataURI bookstore = valueFactory.createURI("http://example/bookStore"); + final BigdataURI price = valueFactory.createURI("http://example.org/ns#price"); + final BigdataLiteral i42 = valueFactory.createLiteral("42",XSD.INTEGER); - final ISPO[] data = new ISPO[] { // + final BigdataStatement[] data = new BigdataStatement[] { // - new SPO( - book1, dcTitle, label1, null, StatementEnum.Explicit),// + valueFactory.createStatement(// + (BigdataResource)book1,// + (BigdataURI)dcTitle,// + (BigdataValue)label1, // + null, // + StatementEnum.Explicit),// - new SPO(book1, price, i42, bookstore, - StatementEnum.Explicit),// + valueFactory.createStatement(// + (BigdataResource)book1,// + (BigdataURI)price,// + (BigdataValue)i42,// + (BigdataResource)bookstore,// + StatementEnum.Explicit),// - new SPO( - book1, dcCreator, label2, null, StatementEnum.Explicit),// + valueFactory.createStatement(// + (BigdataResource)book1,// + (BigdataURI)dcCreator,// + (BigdataValue)label2,// + null,// + StatementEnum.Explicit),// }; op.setData(data); @@ -1292,10 +1395,16 @@ expected.addChild(op); - final ISPO[] data = new ISPO[] { // + final BigdataStatement[] data = new BigdataStatement[] { // - new SPO(book1, dcTitle, label1, bookstore, StatementEnum.Explicit),// - + valueFactory.createStatement(// + (BigdataResource) book1.getValue(),// + (BigdataURI) dcTitle.getValue(),// + (BigdataValue) label1.getValue(),// + (BigdataResource) bookstore.getValue(),// + StatementEnum.Explicit// + ),// + }; op.setData(data); @@ -1307,9 +1416,16 @@ expected.addChild(op); - final ISPO[] data = new ISPO[] { // + final BigdataStatement[] data = new BigdataStatement[] { // - new SPO(book1, dcTitle, label2, bookstore, StatementEnum.Explicit),// + valueFactory.createStatement(// + (BigdataResource) book1.getValue(),// + (BigdataURI) dcTitle.getValue(),// + (BigdataValue) label2.getValue(),// + (BigdataResource) bookstore.getValue(),// + StatementEnum.Explicit// + ),// +// new SPO(book1, dcTitle, label2, bookstore, StatementEnum.Explicit),// }; op.setData(data); @@ -2912,4 +3028,5 @@ assertSameAST(sparql, expected, actual); } + } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/sparql/TestUpdateExprBuilder2.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/sparql/TestUpdateExprBuilder2.java 2012-06-30 20:32:50 UTC (rev 6373) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/sparql/TestUpdateExprBuilder2.java 2012-07-01 21:37:12 UTC (rev 6374) @@ -30,6 +30,11 @@ import com.bigdata.rdf.internal.IV; import com.bigdata.rdf.internal.XSD; +import com.bigdata.rdf.model.BigdataLiteral; +import com.bigdata.rdf.model.BigdataResource; +import com.bigdata.rdf.model.BigdataStatement; +import com.bigdata.rdf.model.BigdataURI; +import com.bigdata.rdf.model.BigdataValue; import com.bigdata.rdf.model.StatementEnum; import com.bigdata.rdf.sail.sparql.ast.ParseException; import com.bigdata.rdf.sail.sparql.ast.TokenMgrError; @@ -48,8 +53,6 @@ import com.bigdata.rdf.sparql.ast.UpdateRoot; import com.bigdata.rdf.sparql.ast.VarNode; import com.bigdata.rdf.sparql.ast.hints.QueryHintScope; -import com.bigdata.rdf.spo.ISPO; -import com.bigdata.rdf.spo.SPO; /** * Test suite for bigdata specific extensions in {@link UpdateExprBuilder}. @@ -340,7 +343,7 @@ * * TODO Maybe specify the implementation class for the persistence? */ - @SuppressWarnings("rawtypes") +// @SuppressWarnings("rawtypes") public void test_create_solutions_silent_params() throws MalformedQueryException, TokenMgrError, ParseException { @@ -351,12 +354,6 @@ +"}" ; - final IV hintQuery = makeIV(valueFactory.createURI(QueryHints.NAMESPACE+QueryHintScope.Query)); - final IV hintEngine = makeIV(valueFactory.createURI(QueryHints.NAMESPACE+"engine")); - final IV hintExpireAge = makeIV(valueFactory.createURI(QueryHints.NAMESPACE+"expireAge")); - final IV cache = makeIV(valueFactory.createLiteral("cache")); - final IV millis = makeIV(valueFactory.createLiteral("100000",XSD.LONG)); - final UpdateRoot expected = new UpdateRoot(); { @@ -368,6 +365,12 @@ op.setSilent(true); +// final IV hintQuery = makeIV(valueFactory.createURI(QueryHints.NAMESPACE+QueryHintScope.Query)); +// final IV hintEngine = makeIV(valueFactory.createURI(QueryHints.NAMESPACE+"engine")); +// final IV hintExpireAge = makeIV(valueFactory.createURI(QueryHints.NAMESPACE+"expireAge")); +// final IV cache = makeIV(valueFactory.createLiteral("cache")); +// final IV millis = makeIV(valueFactory.createLiteral("100000",XSD.LONG)); + // final QuadData params = new QuadData(); // // params.addChild(new StatementPatternNode( @@ -378,11 +381,25 @@ // new ConstantNode(hintQuery), new ConstantNode(hintExpireAge), // new ConstantNode(millis))); - final ISPO[] params = new ISPO[] { - new SPO(hintQuery, hintEngine, - cache, null/* c */, StatementEnum.Explicit),// - new SPO(hintQuery, hintExpireAge, - millis, null/* c */, StatementEnum.Explicit),// + final BigdataURI hintQuery = valueFactory.createURI(QueryHints.NAMESPACE+QueryHintScope.Query); + final BigdataURI hintEngine = valueFactory.createURI(QueryHints.NAMESPACE+"engine"); + final BigdataURI hintExpireAge = valueFactory.createURI(QueryHints.NAMESPACE+"expireAge"); + final BigdataLiteral cache = valueFactory.createLiteral("cache"); + final BigdataLiteral millis = valueFactory.createLiteral("100000",XSD.LONG); + + final BigdataStatement[] params = new BigdataStatement[] { + valueFactory.createStatement(// + (BigdataResource)hintQuery, // + (BigdataURI)hintEngine,// + (BigdataValue)cache, // + null, // c + StatementEnum.Explicit),// + valueFactory.createStatement(// + (BigdataResource)hintQuery,// + (BigdataURI)hintExpireAge,// + (BigdataValue)millis,// + null,// c + StatementEnum.Explicit),// }; op.setParams(params); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/TestSparqlUpdate.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/TestSparqlUpdate.java 2012-06-30 20:32:50 UTC (rev 6373) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/TestSparqlUpdate.java 2012-07-01 21:37:12 UTC (rev 6374) @@ -66,6 +66,7 @@ import org.openrdf.model.vocabulary.XMLSchema; import org.openrdf.query.parser.sparql.DC; import org.openrdf.query.parser.sparql.FOAF; +import org.openrdf.query.parser.sparql.SPARQLUpdateTest; import org.openrdf.repository.RepositoryException; import org.openrdf.rio.RDFFormat; @@ -75,8 +76,16 @@ /** * Proxied test suite. - * + * <p> + * Note: Also see {@link SPARQLUpdateTest}. These two test suites SHOULD be kept + * synchronized. {@link SPARQLUpdateTest} runs against a local kb instance while + * this class runs against the NSS. The two test suites are not exactly the same + * because one uses the {@link RemoteRepository} to commuicate with the NSS + * while the other uses the local API. + * * @param <S> + * + * @see SPARQLUpdateTest */ public class TestSparqlUpdate<S extends IIndexManager> extends AbstractTestNanoSparqlClient<S> { @@ -109,12 +118,9 @@ * * TODO Do this using LOAD or just write tests for LOAD? */ - final AddOp add = new AddOp( - new File( - "bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/dataset-update.trig"), + loadFile( + "bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/dataset-update.trig", RDFFormat.TRIG); - - m_repo.add(add); bob = f.createURI(EX_NS, "bob"); alice = f.createURI(EX_NS, "alice"); @@ -132,8 +138,26 @@ super.tearDown(); } - + /** + * Load a file. + * + * @param file + * The file. + * @param format + * The file format. + * @throws Exception + */ + protected void loadFile(final String file, RDFFormat format) + throws Exception { + + final AddOp add = new AddOp(new File(file), format); + + m_repo.add(add); + + } + + /** * Get a set of useful namespace prefix declarations. * * @return namespace prefix declarations for rdf, rdfs, dc, foaf and ex. @@ -340,7 +364,41 @@ assertTrue(msg, hasStatement(alice, FOAF.KNOWS, null, true)); } + /** + * <pre> + * DELETE WHERE {GRAPH ?g {?x foaf:name ?y} } + * </pre> + * + * @see https://sourceforge.net/apps/trac/bigdata/ticket/568 (DELETE WHERE + * fails with Java AssertionError) + */ //@Test + public void testDeleteWhereShortcut2() + throws Exception + { + +// logger.debug("executing testDeleteWhereShortcut2"); + + final StringBuilder update = new StringBuilder(); + update.append(getNamespaceDeclarations()); + update.append("DELETE WHERE { GRAPH ?g {?x foaf:name ?y } }"); + + assertTrue(hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); + assertTrue(hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); + + m_repo.prepareUpdate(update.toString()).evaluate(); + + String msg = "foaf:name properties should have been deleted"; + assertFalse(msg, hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); + assertFalse(msg, hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); + + msg = "foaf:knows properties should not have been deleted"; + assertTrue(msg, hasStatement(bob, FOAF.KNOWS, null, true)); + assertTrue(msg, hasStatement(alice, FOAF.KNOWS, null, true)); + + } + + //@Test public void testDeleteWhere() throws Exception { @@ -1170,6 +1228,113 @@ assertTrue(msg, hasStatement(bob, FOAF.KNOWS, alice, true, graph2)); } + //@Test + public void testUpdateSequenceInsertDeleteExample9() + throws Exception + { +// logger.debug("executing testUpdateSequenceInsertDeleteExample9"); + + // replace the standard dataset with one specific to this case. + m_repo.prepareUpdate("DROP ALL").evaluate(); + // Note: local copy of: /testdata-update/dataset-update-example9.trig + m_repo.prepareUpdate( + "LOAD <file:bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/dataset-update-example9.trig>") + .evaluate(); + + final URI book1 = f.createURI("http://example/book1"); +// URI book3 = f.createURI("http://example/book3"); + final URI bookStore = f.createURI("http://example/bookStore"); + final URI bookStore2 = f.createURI("http://example/bookStore2"); + + final StringBuilder update = new StringBuilder(); + update.append("prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> "); + update.append("prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> "); + update.append("prefix xsd: <http://www.w3.org/2001/XMLSchema#> "); + update.append("prefix dc: <http://purl.org/dc/elements/1.1/> "); + update.append("prefix dcmitype: <http://purl.org/dc/dcmitype/> "); + update.append("INSERT { GRAPH <http://example/bookStore2> { ?book ?p ?v } } "); + update.append(" WHERE "); + update.append(" { GRAPH <http://example/bookStore> "); + update.append(" { ?book dc:date ?date . "); + update.append(" FILTER ( ?date < \"2000-01-01T00:00:00-02:00\"^^xsd:dateTime ) "); + update.append(" ?book ?p ?v "); + update.append(" } "); + update.append(" } ;"); + update.append("WITH <http://example/bookStore> "); + update.append(" DELETE { ?book ?p ?v } "); + update.append(" WHERE "); + update.append(" { ?book dc:date ?date ; "); + update.append(" a dcmitype:PhysicalObject ."); + update.append(" FILTER ( ?date < \"2000-01-01T00:00:00-02:00\"^^xsd:dateTime ) "); + update.append(" ?book ?p ?v"); + update.append(" } "); + + m_repo.prepareUpdate(update.toString()).evaluate(); + + String msg = "statements about book1 should have been removed from bookStore"; + assertFalse(msg, hasStatement(book1, null, null, true, bookStore)); + + msg = "statements about book1 should have been added to bookStore2"; + assertTrue(msg, hasStatement(book1, RDF.TYPE, null, true, bookStore2)); + assertTrue(msg, hasStatement(book1, DC.DATE, null, true, bookStore2)); + assertTrue(msg, hasStatement(book1, DC.TITLE, null, true, bookStore2)); + } + + /** + * Unit test for + * + * <pre> + * DROP ALL; + * INSERT DATA { + * GRAPH <http://example.org/one> { + * <a> <b> <c> . + * <d> <e> <f> . + * }}; + * ADD SILENT GRAPH <http://example.org/one> TO GRAPH <http://example.org/two> ; + * DROP SILENT GRAPH <http://example.org/one> ; + * </pre> + * + * The IV cache was not not being propagated correctly with the result that + * we were seeing mock IVs for "one" and "two". The UPDATE would work + * correctly the 2nd time since the URIs had been entered into the + * dictionary by then. + * + * @throws Exception + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/567" > + * Failure to set cached value on IV results in incorrect behavior for + * complex UPDATE operation </a> + */ + public void testTicket567() throws Exception { + + // replace the standard dataset with one specific to this case. +// con.clear(); +// con.commit(); + m_repo.prepareUpdate("DROP ALL").evaluate(); + + final StringBuilder update = new StringBuilder(); + update.append("DROP ALL;\n"); + update.append("INSERT DATA {\n"); + update.append(" GRAPH <http://example.org/one> {\n"); + update.append(" <http://example.org/a> <http://example.org/b> <http://example.org/c> .\n"); + update.append(" <http://example.org/d> <http://example.org/e> <http://example.org/f> .\n"); + update.append("}};\n"); + update.append("ADD SILENT GRAPH <http://example.org/one> TO GRAPH <http://example.org/two> ;\n"); + update.append("DROP SILENT GRAPH <http://example.org/one> ;\n"); + + m_repo.prepareUpdate(update.toString()).evaluate(); + + final URI one = f.createURI("http://example.org/one"); + final URI two = f.createURI("http://example.org/two"); + + String msg = "Nothing in graph <one>"; + assertFalse(msg, hasStatement(null, null, null, true, one)); + + msg = "statements are in graph <two>"; + assertTrue(msg, hasStatement(null, null, null, true, two)); + + } + public void testLoad() throws Exception { Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/dataset-update-example9.trig =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/dataset-update-example9.trig (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/dataset-update-example9.trig 2012-07-01 21:37:12 UTC (rev 6374) @@ -0,0 +1,17 @@ +@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . +@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . +@prefix dc: <http://purl.org/dc/elements/1.1/> . +@prefix dcmitype: <http://purl.org/dc/dcmitype/> . + +<http://example/bookStore> { + <http://example/book1> dc:title "Fundamentals of Compiler Design" . + <http://example/book1> dc:date "1996-01-01T00:00:00-02:00"^^xsd:dateTime . + <http://example/book1> a dcmitype:PhysicalObject . + + <http://example/book3> dc:title "SPARQL 1.1 Tutorial" . +} + +<http://example/bookStore2> { + <http://example/book4> dc:title "SPARQL 1.0 Tutorial" . +} Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/org/openrdf/query/parser/sparql/SPARQLUpdateTest.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/org/openrdf/query/parser/sparql/SPARQLUpdateTest.java 2012-06-30 20:32:50 UTC (rev 6373) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/org/openrdf/query/parser/sparql/SPARQLUpdateTest.java 2012-07-01 21:37:12 UTC (rev 6374) @@ -10,6 +10,7 @@ import junit.framework.TestCase; +import org.openrdf.model.Literal; import org.openrdf.model.Resource; import org.openrdf.model.URI; import org.openrdf.model.ValueFactory; @@ -28,13 +29,24 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.bigdata.rdf.internal.XSD; import com.bigdata.rdf.sail.BigdataSailRepositoryConnection; +import com.bigdata.rdf.sail.webapp.TestSparqlUpdate; +import com.bigdata.rdf.sail.webapp.client.RemoteRepository; /** * Tests for SPARQL 1.1 Update functionality. + * <p> + * Note: Also see {@link TestSparqlUpdate}. These two test suites SHOULD be kept + * synchronized. {@link TestSparqlUpdate} runs against the NSS while this test + * suite runs against a local kb instance. The two test suites are not exactly + * the same because one uses the {@link RemoteRepository} to commuicate with the + * NSS while the other uses the local API. * * @author Jeen Broekstra * + * @see TestSparqlUpdate + * * FIXME This was imported in order to expose {@link #con} to our * implementation of the class, which let's us override * {@link #loadDataset(String)} in order to turn off auto-commit. I've @@ -1082,12 +1094,12 @@ con.commit(); loadDataset("/testdata-update/dataset-update-example9.trig"); - URI book1 = f.createURI("http://example/book1"); - URI book3 = f.createURI("http://example/book3"); - URI bookStore = f.createURI("http://example/bookStore"); - URI bookStore2 = f.createURI("http://example/bookStore2"); + final URI book1 = f.createURI("http://example/book1"); +// URI book3 = f.createURI("http://example/book3"); + final URI bookStore = f.createURI("http://example/bookStore"); + final URI bookStore2 = f.createURI("http://example/bookStore2"); - StringBuilder update = new StringBuilder(); + final StringBuilder update = new StringBuilder(); update.append("prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> "); update.append("prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> "); update.append("prefix xsd: <http://www.w3.org/2001/XMLSchema#> "); @@ -1110,7 +1122,7 @@ update.append(" ?book ?p ?v"); update.append(" } "); - Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); + final Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); operation.execute(); @@ -1156,7 +1168,7 @@ con.clear(); con.commit(); - StringBuilder update = new StringBuilder(); + final StringBuilder update = new StringBuilder(); update.append("DROP ALL;\n"); update.append("INSERT DATA {\n"); update.append(" GRAPH <http://example.org/one> {\n"); @@ -1170,8 +1182,8 @@ operation.execute(); - URI one = f.createURI("http://example.org/one"); - URI two = f.createURI("http://example.org/two"); + final URI one = f.createURI("http://example.org/one"); + final URI two = f.createURI("http://example.org/two"); String msg = "Nothing in graph <one>"; assertFalse(msg, con.hasStatement(null, null, null, true, one)); @@ -1181,6 +1193,200 @@ } +// /** +// * File contains +// * +// * <pre> +// * _:bnode <http://example/p> 2 . +// * _:bnode a <http://example/Foo> . +// * <http://example/s> <http://example/p> 2 . +// * </pre> +// * +// * Load into graphA: +// * +// * <pre> +// * PREFIX graphA: <http://example/graphA> +// * PREFIX tempGraph: <http://example/temp> +// * DROP SILENT GRAPH tempGraph: ; +// * DROP SILENT GRAPH graphA: ; +// * INSERT DATA { +// * GRAPH graphA: { +// * <http://example/x> <http://example/p> 2 . +// * <http://example/x> a <http://example/Foo> . +// * <http://example/s> <http://example/p> 2 . +// * }} +// * </pre> +// * // Note: was LOAD <file:///tmp/junk.ttl> INTO GRAPH graphA: ; +// * +// * Verify that all three triples are in graphA: +// * +// * <pre> +// * PREFIX graphA: <http://example/graphA> +// * PREFIX tempGraph: <http://example/temp> +// * SELECT * WHERE { GRAPH graphA: { ?s ?p ?v . } } +// * </pre> +// * +// * Now delete some triples from graphA while inserting the deleted triples +// * into tempGraph: +// * +// * <pre> +// * PREFIX graphA: <http://example/graphA> +// * PREFIX tempGraph: <http://example/temp> +// * DROP SILENT GRAPH tempGraph: ; +// * DELETE { GRAPH graphA: { ?s ?p ?v . } } +// * INSERT { GRAPH tempGraph: { ?s ?p ?v . } } +// * WHERE { GRAPH graphA: { +// * ?s a <http://example/Foo> . +// * ?s ?p ?v . } } +// * </pre> +// * +// * The result should be that the combination of tempGraph and graphA should +// * have the exact same number of triples that we started with. But now +// * notice that graphA has 0 triples: +// * +// * <pre> +// * PREFIX graphA: <http://example/graphA> +// * PREFIX tempGraph: <http://example/temp> +// * SELECT * WHERE { GRAPH graphA: { ?s ?p ?v . } } +// * </pre> +// * +// * However, tempGraph has only 2 triples: +// * +// * <pre> +// * PREFIX graphA: <http://example/graphA> +// * PREFIX tempGraph: <http://example/temp> +// * SELECT * WHERE { GRAPH tempGraph: { ?s ?p ?v . } } +// * </pre> +// * +// * so one triple is missing: +// * +// * <pre> +// * <http://example/s> <http://example/p> 2 . +// * </pre> +// */ +// public void testTicket571() throws RepositoryException, MalformedQueryException, UpdateExecutionException { +// +// final URI graphA = f.createURI("http://example.org/graphA"); +// final URI tempGraph = f.createURI("http://example.org/tmp"); +// final URI s = f.createURI("http://example/s>"); +// final URI p = f.createURI("http://example/p>"); +// final URI x = f.createURI("http://example/x>"); +// final URI foo = f.createURI("http://example/Foo>"); +// final URI rdfType = f.createURI(RDF.TYPE.stringValue()); +// final Literal two = f.createLiteral("2", XSD.INTEGER); +// +// // replace the standard dataset with one specific to this case. +// con.prepareUpdate(QueryLanguage.SPARQL, "DROP ALL").execute(); +// +// /** +// * Load into graphA (note: file is "file:///tmp/junk.ttl" in the +// * ticket). +// * +// * <pre> +// * PREFIX graphA: <http://example/graphA> +// * PREFIX tempGraph: <http://example/temp> +// * DROP SILENT GRAPH tempGraph: ; +// * DROP SILENT GRAPH graphA: ; +// * LOAD <file:///tmp/junk.ttl> INTO GRAPH graphA: ; +// * </pre> +// */ +// con.prepareUpdate(// +// QueryLanguage.SPARQL,// +// "PREFIX graphA: <http://example/graphA> \n" + // +// "PREFIX tempGraph: <http://example/temp> \n"+// +// "DROP SILENT GRAPH tempGraph: ;\n"+// +// "DROP SILENT GRAPH graphA: ;\n"+// +// "INSERT DATA { \n"+// +// " GRAPH graphA: { \n" +// +// " <http://example/x> <http://example/p> 2 . \n"+// +// " <http://example/x> a <http://example/Foo> . \n"+// +// " <http://example/s> <http://example/p> 2 . \n"+// +// "}}\n"// +//// "LOAD <file:bigdata-sails/src/test/org/openrdf/query/parser/sparql/ticket571.ttl> INTO GRAPH graphA: ;\n"// +// ).execute(); +// +// /** +// * Now delete some triples from graphA while inserting the deleted +// * triples into tempGraph: +// * +// * <pre> +// * PREFIX graphA: <http://example/graphA> +// * PREFIX tempGraph: <http://example/temp> +// * DROP SILENT GRAPH tempGraph: ; ### Note: redundant +// * DELETE { GRAPH graphA: { ?s ?p ?v . } } +// * INSERT { GRAPH tempGraph: { ?s ?p ?v . } } +// * WHERE { GRAPH graphA: { +// * ?s a <http://example/Foo> . +// * ?s ?p ?v . } } +// * </pre> +// */ +// con.prepareUpdate(// +// QueryLanguage.SPARQL, // +// "PREFIX graphA: <http://example/gra... [truncated message content] |
From: <tho...@us...> - 2012-07-02 15:00:42
|
Revision: 6376 http://bigdata.svn.sourceforge.net/bigdata/?rev=6376&view=rev Author: thompsonbry Date: 2012-07-02 15:00:31 +0000 (Mon, 02 Jul 2012) Log Message: ----------- The following three openrdf SPARQL UPDATE tests have been disabled since they violate the SPARQL UPDATE specification by having blank nodes in the DELETE template: - testDeleteTransformedWhere - testUpdateSequenceDeleteInsert - testUpdateSequenceInsertDelete I have also picked up several new SPARQL UPDATE tests from Sesame releases up through 2.6.6 (this is not a general dependency upgrade - I only looked at this one file). The changes to the SPARQL update test suite have been applied to both the local and NSS versions of the test suite. The UpdateExprBuilder was modified to forbid blank nodes in the DELETE clause template. It also forbids blank nodes in a DELETE DATA clause. The test suite for the UpdateExprBuilder was extended to verify correct rejection for blank nodes in those locations. The AST2BOpUpdate class was modified to NOT replace blank nodes with wildcards. The test now runs green. @see https://sourceforge.net/apps/trac/bigdata/ticket/571 (DELETE/INSERT WHERE handling of blank nodes.) Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/sparql/UpdateExprBuilder.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/sparql/TestUpdateExprBuilder.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/TestSparqlUpdate.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/org/openrdf/query/parser/sparql/SPARQLUpdateTest.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java 2012-07-02 00:13:15 UTC (rev 6375) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java 2012-07-02 15:00:31 UTC (rev 6376) @@ -1866,17 +1866,25 @@ } else { - /* - * We need to handle blank nodes (which can appear in the subject or - * object position) as unbound variables. +// /* +// * We need to handle blank nodes (which can appear in the subject or +// * object position) as unbound variables. +// */ +// +// final Resource s1 = s instanceof BNode ? null : s; +// +// final Value o1 = o instanceof BNode ? null : o; +// +// conn.removeStatements(s1, p, o1, contexts); + + /** + * + * @see <a + * href="https://sourceforge.net/apps/trac/bigdata/ticket/571"> + * DELETE/INSERT WHERE handling of blank nodes </a> */ - - final Resource s1 = s instanceof BNode ? null : s; + conn.removeStatements(s, p, o, contexts); - final Value o1 = o instanceof BNode ? null : o; - - conn.removeStatements(s1, p, o1, contexts); - } } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/sparql/UpdateExprBuilder.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/sparql/UpdateExprBuilder.java 2012-07-02 00:13:15 UTC (rev 6375) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/sparql/UpdateExprBuilder.java 2012-07-02 15:00:31 UTC (rev 6376) @@ -662,22 +662,21 @@ return op; - } + } - @Override - public QuadData visit(final ASTDeleteClause node, final Object data) - throws VisitorException - { + @Override + public QuadData visit(final ASTDeleteClause node, final Object data) + throws VisitorException { - return doQuadsPatternClause(node, data); - + return doQuadsPatternClause(node, data, false/* allowBlankNodes */); + } @Override public QuadData visit(final ASTInsertClause node, final Object data) throws VisitorException { - return doQuadsPatternClause(node, data); + return doQuadsPatternClause(node, data, true/* allowBlankNodes */); } @@ -845,9 +844,12 @@ * @return The {@link QuadData} (aka template). The {@link QuadData} as * returned by this method is not flattened, but the context has * been applied within any GRAPH section. + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/571"> + * DELETE/INSERT WHERE handling of blank nodes </a> */ - private QuadData doQuadsPatternClause(final Node node, final Object data) - throws VisitorException { + private QuadData doQuadsPatternClause(final Node node, final Object data, + final boolean allowBlankNodes) throws VisitorException { // Collect construct triples final GroupGraphPattern parentGP = graphPattern; @@ -866,6 +868,27 @@ final QuadData quadData = graphPattern.buildGroup(new QuadData()); + if (!allowBlankNodes) { + + /* + * Blank nodes are not allowed in the DELETE clause template. + */ + + final Iterator<StatementPatternNode> itr = BOpUtility.visitAll( + quadData, StatementPatternNode.class); + + while (itr.hasNext()) { + + final StatementPatternNode sp = itr.next(); + + assertNotAnonymousVariable(sp.s()); + + assertNotAnonymousVariable(sp.o()); + + } + + } + graphPattern = parentGP; return quadData; Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/sparql/TestUpdateExprBuilder.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/sparql/TestUpdateExprBuilder.java 2012-07-02 00:13:15 UTC (rev 6375) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/sparql/TestUpdateExprBuilder.java 2012-07-02 15:00:31 UTC (rev 6376) @@ -2533,6 +2533,74 @@ } /** + * DELETE/INSERT with blank node in the DELETE template. + * <p> + * Note: blank nodes are not allowed in the DELETE clause template (nor in + * DELETE DATA). This is because the blank nodes in the DELETE clause are + * distinct for each solution plugged into that template. Thus they can not + * match anything in the database. + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/571"> + * DELETE/INSERT WHERE handling of blank nodes </a> + */ + public void test_delete_insert_blankNodes01() throws MalformedQueryException, + TokenMgrError, ParseException { + + final String sparql = "PREFIX foaf: <http://xmlns.com/foaf/0.1/>\n" + + "DELETE { [] foaf:givenName 'Bill' }\n"// + + "INSERT { ?person foaf:givenName 'William' }\n"// + + "WHERE {\n"// + + " ?person foaf:givenName 'Bill'. \n"// + + " GRAPH <http://example/addresses> {\n"// + + " ?person foaf:givenName 'Bill'\n"// + + " }\n"// + + "}"; + + try { + parseUpdate(sparql, baseURI); + fail("Expecting exception: blank nodes not allowed in DELETE template"); + } catch (MalformedQueryException ex) { + // Ignore expected exception. +// ex.printStackTrace(); + } + + } + + /** + * DELETE/INSERT with blank node in the DELETE template. + * <p> + * Note: blank nodes are not allowed in the DELETE clause template (nor in + * DELETE DATA). This is because the blank nodes in the DELETE clause are + * distinct for each solution plugged into that template. Thus they can not + * match anything in the database. + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/571"> + * DELETE/INSERT WHERE handling of blank nodes </a> + */ + public void test_delete_insert_blankNodes02() + throws MalformedQueryException, TokenMgrError, ParseException { + + final String sparql = "PREFIX foaf: <http://xmlns.com/foaf/0.1/>\n" + + "DELETE { ?person foaf:givenName [] }\n"// + + "INSERT { ?person foaf:givenName 'William' }\n"// + + "WHERE {\n"// + + " ?person foaf:givenName 'Bill'. \n"// + + " GRAPH <http://example/addresses> {\n"// + + " ?person foaf:givenName 'Bill'\n"// + + " }\n"// + + "}"; + + try { + parseUpdate(sparql, baseURI); + fail("Expecting exception: blank nodes not allowed in DELETE template"); + } catch (MalformedQueryException ex) { + // Ignore expected exception. +// ex.printStackTrace(); + } + + } + + /** * A unit test for the DELETE WHERE form without the shortcut, but * there the template and the where clause are the same. * <pre> Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/TestSparqlUpdate.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/TestSparqlUpdate.java 2012-07-02 00:13:15 UTC (rev 6375) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/TestSparqlUpdate.java 2012-07-02 15:00:31 UTC (rev 6376) @@ -56,6 +56,7 @@ import java.io.File; +import org.openrdf.model.Literal; import org.openrdf.model.Resource; import org.openrdf.model.URI; import org.openrdf.model.Value; @@ -90,6 +91,14 @@ public class TestSparqlUpdate<S extends IIndexManager> extends AbstractTestNanoSparqlClient<S> { + /** + * When <code>true</code>, the unit tests of the BINDINGS clause are + * enabled. + * + * FIXME BINDINGS does not work correctly for UPDATE. + */ + private static boolean BINDINGS = false; + public TestSparqlUpdate() { } @@ -208,11 +217,234 @@ assertTrue(hasStatement(alice, RDFS.LABEL, f.createLiteral("Alice"), true)); } -//// //@Test +// /** +// * TODO Requires BINDINGS support for {@link RemoteRepository} +// * +// * @since openrdf 2.6.3 +// */ +//// @Test +// public void testInsertWhereWithBinding() +// throws Exception +// { +// if (!BINDINGS) +// return; +// log.debug("executing test testInsertWhereWithBinding"); +// final StringBuilder update = new StringBuilder(); +// update.append(getNamespaceDeclarations()); +// update.append("INSERT {?x rdfs:label ?y . } WHERE {?x foaf:name ?y }"); +// +// final Update operation = con.prepareUpdate(QueryLanguage.SPARQL,update.toString()); +// operation.setBinding("x", bob); +// +// assertFalse(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bob"), true)); +// assertFalse(con.hasStatement(alice, RDFS.LABEL, f.createLiteral("Alice"), true)); +// +// operation.execute(); +// +// assertTrue(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bob"), true)); +// assertFalse(con.hasStatement(alice, RDFS.LABEL, f.createLiteral("Alice"), true)); +// } +// +// /** +// * TODO Requires BINDINGS support for {@link RemoteRepository} +// * +// * @since openrdf 2.6.6 +// */ +// public void testInsertWhereWithBindings2() +// throws Exception +// { +// if (!BINDINGS) +// return; +// log.debug("executing test testInsertWhereWithBindings2"); +// StringBuilder update = new StringBuilder(); +// update.append(getNamespaceDeclarations()); +// update.append("INSERT {?x rdfs:label ?z . } WHERE {?x foaf:name ?y }"); +// +// Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); +// operation.setBinding("z", f.createLiteral("Bobbie")); +// operation.setBinding("x", bob); +// +// assertFalse(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bobbie"), true)); +// assertFalse(con.hasStatement(alice, RDFS.LABEL, null, true)); +// +// operation.execute(); +// +// assertTrue(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bobbie"), true)); +// assertFalse(con.hasStatement(alice, RDFS.LABEL, f.createLiteral("Alice"), true)); +// } + + /** + * @since openrdf 2.6.3 + */ +// @Test + public void testInsertEmptyWhere() + throws Exception + { + log.debug("executing test testInsertEmptyWhere"); + final StringBuilder update = new StringBuilder(); + update.append(getNamespaceDeclarations()); + update.append("INSERT { <" + bob + "> rdfs:label \"Bob\" . } WHERE { }"); + + assertFalse(hasStatement(bob, RDFS.LABEL, f.createLiteral("Bob"), true)); + + m_repo.prepareUpdate(update.toString()).evaluate(); + + assertTrue(hasStatement(bob, RDFS.LABEL, f.createLiteral("Bob"), true)); + } + +// /** +// * TODO Requires BINDINGS support for {@link RemoteRepository} +// * +// * @since openrdf 2.6.3 +// */ +//// @Test +// public void testInsertEmptyWhereWithBinding() +// throws Exception +// { +// if (!BINDINGS) +// return; +// log.debug("executing test testInsertEmptyWhereWithBinding"); +// final StringBuilder update = new StringBuilder(); +// update.append(getNamespaceDeclarations()); +// update.append("INSERT {?x rdfs:label ?y . } WHERE { }"); +// +// final Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); +// operation.setBinding("x", bob); +// operation.setBinding("y", f.createLiteral("Bob")); +// +// assertFalse(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bob"), true)); +// +// operation.execute(); +// +// assertTrue(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bob"), true)); +// } + + /** + * @since openrdf 2.6.3 + */ +// @Test + public void testInsertNonMatchingWhere() + throws Exception + { + log.debug("executing test testInsertNonMatchingWhere"); + final StringBuilder update = new StringBuilder(); + update.append(getNamespaceDeclarations()); + update.append("INSERT { ?x rdfs:label ?y . } WHERE { ?x rdfs:comment ?y }"); + + assertFalse(hasStatement(bob, RDFS.LABEL, null, true)); + + m_repo.prepareUpdate(update.toString()).evaluate(); + + assertFalse(hasStatement(bob, RDFS.LABEL, null, true)); + } + +// /** +// * TODO Requires BINDINGS support for {@link RemoteRepository} +// * +// * @since openrdf 2.6.3 +// */ +//// @Test +// public void testInsertNonMatchingWhereWithBindings() +// throws Exception +// { +// if (!BINDINGS) +// return; +// log.debug("executing test testInsertNonMatchingWhereWithBindings"); +// final StringBuilder update = new StringBuilder(); +// update.append(getNamespaceDeclarations()); +// update.append("INSERT { ?x rdfs:label ?y . } WHERE { ?x rdfs:comment ?y }"); +// +// final Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); +// operation.setBinding("x", bob); +// operation.setBinding("y", f.createLiteral("Bob")); +// +// assertFalse(con.hasStatement(bob, RDFS.LABEL, null, true)); +// +// operation.execute(); +// +// assertFalse(con.hasStatement(bob, RDFS.LABEL, null, true)); +// } + +// /** +// * TODO Requires BINDINGS support for {@link RemoteRepository} +// * +// * @since openrdf 2.6.3 +// */ +//// @Test +// public void testInsertWhereWithBindings() +// throws Exception +// { +// if (!BINDINGS) +// return; +// log.debug("executing test testInsertWhereWithBindings"); +// final StringBuilder update = new StringBuilder(); +// update.append(getNamespaceDeclarations()); +// update.append("INSERT { ?x rdfs:comment ?z . } WHERE { ?x foaf:name ?y }"); +// +// final Literal comment = f.createLiteral("Bob has a comment"); +// +// final Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); +// operation.setBinding("x", bob); +// operation.setBinding("z", comment); +// +// assertFalse(con.hasStatement(null, RDFS.COMMENT, comment, true)); +// +// operation.execute(); +// +// assertTrue(con.hasStatement(bob, RDFS.COMMENT, comment, true)); +// assertFalse(con.hasStatement(alice, RDFS.COMMENT, comment, true)); +// +// } + + /** + * @since openrdf 2.6.3 + */ +// @Test + public void testInsertWhereWithOptional() + throws Exception + { + log.debug("executing testInsertWhereWithOptional"); + + final StringBuilder update = new StringBuilder(); + update.append(getNamespaceDeclarations()); + update.append(" INSERT { ?s ex:age ?incAge } "); + // update.append(" DELETE { ?s ex:age ?age } "); + update.append(" WHERE { ?s foaf:name ?name . "); + update.append(" OPTIONAL {?s ex:age ?age . BIND ((?age + 1) as ?incAge) } "); + update.append(" } "); + + final URI age = f.createURI(EX_NS, "age"); + + assertFalse(hasStatement(alice, age, null, true)); + assertTrue(hasStatement(bob, age, null, true)); + + m_repo.prepareUpdate(update.toString()).evaluate(); + +// RepositoryResult<Statement> result = m_repo.getStatements(bob, age, null, true); +// +// while (result.hasNext()) { +// final Statement stmt = result.next(); +// if (log.isInfoEnabled()) +// log.info(stmt.toString()); +// } + + assertTrue(hasStatement(bob, age, f.createLiteral("43", XMLSchema.INTEGER), true)); + +// result = m_repo.getStatements(alice, age, null, true); +// +// while (result.hasNext()) { +// final Statement stmt = result.next(); +// if (log.isInfoEnabled()) +// log.info(stmt.toString()); +// } + assertFalse(hasStatement(alice, age, null, true)); + } + + //// //@Test public void testDeleteInsertWhere() throws Exception { -// logger.debug("executing test DeleteInsertWhere"); +// log.debug("executing test DeleteInsertWhere"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); update.append("DELETE { ?x foaf:name ?y } INSERT {?x rdfs:label ?y . } WHERE {?x foaf:name ?y }"); @@ -230,11 +462,68 @@ } - //@Test +// /** +// * TODO Requires BINDINGS support for {@link RemoteRepository} +// * +// * @since OPENRDF 2.6.6. */ +//// @Test +// public void testDeleteInsertWhereWithBindings2() +// throws Exception +// { +// if (!BINDINGS) +// return; +// log.debug("executing test testDeleteInsertWhereWithBindings2"); +// final StringBuilder update = new StringBuilder(); +// update.append(getNamespaceDeclarations()); +// update.append("DELETE { ?x foaf:name ?y } INSERT {?x rdfs:label ?z . } WHERE {?x foaf:name ?y }"); +// +// final Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); +// +// operation.setBinding("z", f.createLiteral("person")); +// +// assertFalse(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bob"), true)); +// assertFalse(con.hasStatement(alice, RDFS.LABEL, f.createLiteral("Alice"), true)); +// +// operation.execute(); +// +// assertTrue(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("person"), true)); +// assertTrue(con.hasStatement(alice, RDFS.LABEL, f.createLiteral("person"), true)); +// +// assertFalse(con.hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); +// assertFalse(con.hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); +// } + + /** @since openrdf 2.6.3 */ + public void testDeleteInsertWhereLoopingBehavior() throws Exception { + log.debug("executing test testDeleteInsertWhereLoopingBehavior"); + final StringBuilder update = new StringBuilder(); + update.append(getNamespaceDeclarations()); + update.append(" DELETE { ?x ex:age ?y } INSERT {?x ex:age ?z }"); + update.append(" WHERE { "); + update.append(" ?x ex:age ?y ."); + update.append(" BIND((?y + 1) as ?z) "); + update.append(" FILTER( ?y < 46 ) "); + update.append(" } "); + + final URI age = f.createURI(EX_NS, "age"); + final Literal originalAgeValue = f.createLiteral("42", XMLSchema.INTEGER); + final Literal correctAgeValue = f.createLiteral("43", XMLSchema.INTEGER); + final Literal inCorrectAgeValue = f.createLiteral("46", XMLSchema.INTEGER); + + assertTrue(hasStatement(bob, age, originalAgeValue, true)); + + m_repo.prepareUpdate(update.toString()).evaluate(); + + assertFalse(hasStatement(bob, age, originalAgeValue, true)); + assertTrue(hasStatement(bob, age, correctAgeValue, true)); + assertFalse(hasStatement(bob, age, inCorrectAgeValue, true)); + } + + //@Test public void testInsertTransformedWhere() throws Exception { -// logger.debug("executing test InsertTransformedWhere"); +// log.debug("executing test InsertTransformedWhere"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -268,7 +557,7 @@ public void testInsertWhereGraph() throws Exception { -// logger.debug("executing testInsertWhereGraph"); +// log.debug("executing testInsertWhereGraph"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); update.append("INSERT {GRAPH ?g {?x rdfs:label ?y . }} WHERE {GRAPH ?g {?x foaf:name ?y }}"); @@ -291,7 +580,7 @@ throws Exception { -// logger.debug("executing testInsertWhereUsing"); +// log.debug("executing testInsertWhereUsing"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); update.append("INSERT {?x rdfs:label ?y . } USING ex:graph1 WHERE {?x foaf:name ?y }"); @@ -319,7 +608,7 @@ public void testInsertWhereWith() throws Exception { -// logger.debug("executing testInsertWhereWith"); +// log.debug("executing testInsertWhereWith"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -342,7 +631,7 @@ public void testDeleteWhereShortcut() throws Exception { -// logger.debug("executing testDeleteWhereShortcut"); +// log.debug("executing testDeleteWhereShortcut"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -377,7 +666,7 @@ throws Exception { -// logger.debug("executing testDeleteWhereShortcut2"); +// log.debug("executing testDeleteWhereShortcut2"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -402,7 +691,7 @@ public void testDeleteWhere() throws Exception { -// logger.debug("executing testDeleteWhere"); +// log.debug("executing testDeleteWhere"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -422,39 +711,45 @@ } - //@Test - public void testDeleteTransformedWhere() - throws Exception - { -// logger.debug("executing testDeleteTransformedWhere"); +// /** +// * Note: blank nodes are not permitted in the DELETE clause template. +// * +// * <a href="https://sourceforge.net/apps/trac/bigdata/ticket/571"> +// * DELETE/INSERT WHERE handling of blank nodes </a> +// */ +// //@Test +// public void testDeleteTransformedWhere() +// throws Exception +// { +//// log.debug("executing testDeleteTransformedWhere"); +// +// final StringBuilder update = new StringBuilder(); +// update.append(getNamespaceDeclarations()); +// update.append("DELETE {?y foaf:name [] } WHERE {?x ex:containsPerson ?y }"); +// +//// Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); +// +// assertTrue(hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); +// assertTrue(hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); +// +//// operation.execute(); +// m_repo.prepareUpdate(update.toString()).evaluate(); +// +// String msg = "foaf:name properties should have been deleted"; +// assertFalse(msg, hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); +// assertFalse(msg, hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); +// +// msg = "ex:containsPerson properties should not have been deleted"; +// assertTrue(msg, hasStatement(graph1, f.createURI(EX_NS, "containsPerson"), bob, true)); +// assertTrue(msg, hasStatement(graph2, f.createURI(EX_NS, "containsPerson"), alice, true)); +// +// } - final StringBuilder update = new StringBuilder(); - update.append(getNamespaceDeclarations()); - update.append("DELETE {?y foaf:name [] } WHERE {?x ex:containsPerson ?y }"); - -// Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); - - assertTrue(hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); - assertTrue(hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); - -// operation.execute(); - m_repo.prepareUpdate(update.toString()).evaluate(); - - String msg = "foaf:name properties should have been deleted"; - assertFalse(msg, hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); - assertFalse(msg, hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); - - msg = "ex:containsPerson properties should not have been deleted"; - assertTrue(msg, hasStatement(graph1, f.createURI(EX_NS, "containsPerson"), bob, true)); - assertTrue(msg, hasStatement(graph2, f.createURI(EX_NS, "containsPerson"), alice, true)); - - } - //@Test public void testInsertData() throws Exception { -// logger.debug("executing testInsertData"); +// log.debug("executing testInsertData"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -479,7 +774,7 @@ public void testInsertDataMultiplePatterns() throws Exception { -// logger.debug("executing testInsertData"); +// log.debug("executing testInsertData"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -507,7 +802,7 @@ public void testInsertDataInGraph() throws Exception { -// logger.debug("executing testInsertDataInGraph"); +// log.debug("executing testInsertDataInGraph"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -528,11 +823,33 @@ assertTrue(msg, hasStatement(book1, DC.CREATOR, f.createLiteral("Ringo"), true, graph1)); } + /** @since OPENRDF 2.6.3 */ +// @Test + public void testInsertDataInGraph2() + throws Exception + { + log.debug("executing testInsertDataInGraph2"); + + final StringBuilder update = new StringBuilder(); + update.append(getNamespaceDeclarations()); + update.append("INSERT DATA { GRAPH ex:graph1 { ex:Human rdfs:subClassOf ex:Mammal. ex:Mammal rdfs:subClassOf ex:Animal. ex:george a ex:Human. ex:ringo a ex:Human. } } "); + + final URI human = f.createURI(EX_NS, "Human"); + final URI mammal = f.createURI(EX_NS, "Mammal"); + final URI george = f.createURI(EX_NS, "george"); + + m_repo.prepareUpdate(update.toString()).evaluate(); + + assertTrue(hasStatement(human, RDFS.SUBCLASSOF, mammal, true, graph1)); + assertTrue(hasStatement(mammal, RDFS.SUBCLASSOF, null, true, graph1)); + assertTrue(hasStatement(george, RDF.TYPE, human, true, graph1)); + } + //@Test public void testDeleteData() throws Exception { -// logger.debug("executing testDeleteData"); +// log.debug("executing testDeleteData"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); update.append("DELETE DATA { ex:alice foaf:knows ex:bob. } "); @@ -552,7 +869,7 @@ public void testDeleteDataMultiplePatterns() throws Exception { -// logger.debug("executing testDeleteData"); +// log.debug("executing testDeleteData"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); update.append("DELETE DATA { ex:alice foaf:knows ex:bob. ex:alice foaf:mbox \"al...@ex...\" .} "); @@ -574,7 +891,7 @@ public void testDeleteDataFromGraph() throws Exception { -// logger.debug("executing testDeleteDataFromGraph"); +// log.debug("executing testDeleteDataFromGraph"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -595,7 +912,7 @@ public void testDeleteDataFromWrongGraph() throws Exception { -// logger.debug("executing testDeleteDataFromWrongGraph"); +// log.debug("executing testDeleteDataFromWrongGraph"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -619,7 +936,7 @@ public void testCreateNewGraph() throws Exception { -// logger.debug("executing testCreateNewGraph"); +// log.debug("executing testCreateNewGraph"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -643,7 +960,7 @@ public void testCreateExistingGraph() throws Exception { -// logger.debug("executing testCreateExistingGraph"); +// log.debug("executing testCreateExistingGraph"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -668,7 +985,7 @@ public void testCopyToDefault() throws Exception { -// logger.debug("executing testCopyToDefault"); +// log.debug("executing testCopyToDefault"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); update.append("COPY GRAPH <" + graph1.stringValue() + "> TO DEFAULT"); @@ -691,7 +1008,7 @@ public void testCopyToExistingNamed() throws Exception { -// logger.debug("executing testCopyToExistingNamed"); +// log.debug("executing testCopyToExistingNamed"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -711,7 +1028,7 @@ public void testCopyToNewNamed() throws Exception { -// logger.debug("executing testCopyToNewNamed"); +// log.debug("executing testCopyToNewNamed"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -731,7 +1048,7 @@ public void testCopyFromDefault() throws Exception { -// logger.debug("executing testCopyFromDefault"); +// log.debug("executing testCopyFromDefault"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -756,7 +1073,7 @@ public void testCopyFromDefaultToDefault() throws Exception { -// logger.debug("executing testCopyFromDefaultToDefault"); +// log.debug("executing testCopyFromDefaultToDefault"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -778,7 +1095,7 @@ public void testAddToDefault() throws Exception { -// logger.debug("executing testAddToDefault"); +// log.debug("executing testAddToDefault"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -802,7 +1119,7 @@ public void testAddToExistingNamed() throws Exception { -// logger.debug("executing testAddToExistingNamed"); +// log.debug("executing testAddToExistingNamed"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -822,7 +1139,7 @@ public void testAddToNewNamed() throws Exception { -// logger.debug("executing testAddToNewNamed"); +// log.debug("executing testAddToNewNamed"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -842,7 +1159,7 @@ public void testAddFromDefault() throws Exception { -// logger.debug("executing testAddFromDefault"); +// log.debug("executing testAddFromDefault"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -867,7 +1184,7 @@ public void testAddFromDefaultToDefault() throws Exception { -// logger.debug("executing testAddFromDefaultToDefault"); +// log.debug("executing testAddFromDefaultToDefault"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -889,7 +1206,7 @@ public void testMoveToDefault() throws Exception { -// logger.debug("executing testMoveToDefault"); +// log.debug("executing testMoveToDefault"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -913,7 +1230,7 @@ public void testMoveToNewNamed() throws Exception { -// logger.debug("executing testMoveToNewNamed"); +// log.debug("executing testMoveToNewNamed"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); update.append("MOVE GRAPH ex:graph1 TO ex:graph3"); @@ -932,7 +1249,7 @@ public void testMoveFromDefault() throws Exception { -// logger.debug("executing testMoveFromDefault"); +// log.debug("executing testMoveFromDefault"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); update.append("MOVE DEFAULT TO ex:graph3"); @@ -956,7 +1273,7 @@ public void testMoveFromDefaultToDefault() throws Exception { -// logger.debug("executing testMoveFromDefaultToDefault"); +// log.debug("executing testMoveFromDefaultToDefault"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); update.append("MOVE DEFAULT TO DEFAULT"); @@ -977,7 +1294,7 @@ public void testClearAll() throws Exception { -// logger.debug("executing testClearAll"); +// log.debug("executing testClearAll"); String update = "CLEAR ALL"; // Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update); @@ -994,7 +1311,7 @@ public void testClearGraph() throws Exception { -// logger.debug("executing testClearGraph"); +// log.debug("executing testClearGraph"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); update.append("CLEAR GRAPH <" + graph1.stringValue() + "> "); @@ -1014,7 +1331,7 @@ public void testClearNamed() throws Exception { -// logger.debug("executing testClearNamed"); +// log.debug("executing testClearNamed"); String update = "CLEAR NAMED"; // Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update); @@ -1033,7 +1350,7 @@ public void testClearDefault() throws Exception { -// logger.debug("executing testClearDefault"); +// log.debug("executing testClearDefault"); String update = "CLEAR DEFAULT"; @@ -1062,7 +1379,7 @@ public void testDropAll() throws Exception { -// logger.debug("executing testDropAll"); +// log.debug("executing testDropAll"); String update = "DROP ALL"; // Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update); @@ -1079,7 +1396,7 @@ public void testDropGraph() throws Exception { -// logger.debug("executing testDropGraph"); +// log.debug("executing testDropGraph"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); update.append("DROP GRAPH <" + graph1.stringValue() + "> "); @@ -1099,7 +1416,7 @@ public void testDropNamed() throws Exception { -// logger.debug("executing testDropNamed"); +// log.debug("executing testDropNamed"); String update = "DROP NAMED"; @@ -1118,7 +1435,7 @@ public void testDropDefault() throws Exception { -// logger.debug("executing testDropDefault"); +// log.debug("executing testDropDefault"); String update = "DROP DEFAULT"; @@ -1141,70 +1458,82 @@ } - //@Test - public void testUpdateSequenceDeleteInsert() - throws Exception - { -// logger.debug("executing testUpdateSequenceDeleteInsert"); +// /** +// * Note: blank nodes are not permitted in the DELETE clause template. +// * +// * <a href="https://sourceforge.net/apps/trac/bigdata/ticket/571"> +// * DELETE/INSERT WHERE handling of blank nodes </a> +// */ +// //@Test +// public void testUpdateSequenceDeleteInsert() +// throws Exception +// { +//// log.debug("executing testUpdateSequenceDeleteInsert"); +// +// final StringBuilder update = new StringBuilder(); +// update.append(getNamespaceDeclarations()); +// update.append("DELETE {?y foaf:name [] } WHERE {?x ex:containsPerson ?y }; "); +// update.append(getNamespaceDeclarations()); +// update.append("INSERT {?x foaf:name \"foo\" } WHERE {?y ex:containsPerson ?x} "); +// +//// Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); +// +// assertTrue(hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); +// assertTrue(hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); +// +//// operation.execute(); +// +// m_repo.prepareUpdate(update.toString()).evaluate(); +// +// String msg = "foaf:name properties should have been deleted"; +// assertFalse(msg, hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); +// assertFalse(msg, hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); +// +// msg = "foaf:name properties with value 'foo' should have been added"; +// assertTrue(msg, hasStatement(bob, FOAF.NAME, f.createLiteral("foo"), true)); +// assertTrue(msg, hasStatement(alice, FOAF.NAME, f.createLiteral("foo"), true)); +// } - final StringBuilder update = new StringBuilder(); - update.append(getNamespaceDeclarations()); - update.append("DELETE {?y foaf:name [] } WHERE {?x ex:containsPerson ?y }; "); - update.append(getNamespaceDeclarations()); - update.append("INSERT {?x foaf:name \"foo\" } WHERE {?y ex:containsPerson ?x} "); +// /** +// * Note: blank nodes are not permitted in the DELETE clause template. +// * +// * <a href="https://sourceforge.net/apps/trac/bigdata/ticket/571"> +// * DELETE/INSERT WHERE handling of blank nodes </a> +// */ +// //@Test +// public void testUpdateSequenceInsertDelete() +// throws Exception +// { +//// log.debug("executing testUpdateSequenceInsertDelete"); +// +// final StringBuilder update = new StringBuilder(); +// update.append(getNamespaceDeclarations()); +// update.append("INSERT {?x foaf:name \"foo\" } WHERE {?y ex:containsPerson ?x}; "); +// update.append(getNamespaceDeclarations()); +// update.append("DELETE {?y foaf:name [] } WHERE {?x ex:containsPerson ?y } "); +// +//// Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); +// +// assertTrue(hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); +// assertTrue(hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); +// +//// operation.execute(); +// m_repo.prepareUpdate(update.toString()).evaluate(); +// +// String msg = "foaf:name properties should have been deleted"; +// assertFalse(msg, hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); +// assertFalse(msg, hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); +// +// msg = "foaf:name properties with value 'foo' should not have been added"; +// assertFalse(msg, hasStatement(bob, FOAF.NAME, f.createLiteral("foo"), true)); +// assertFalse(msg, hasStatement(alice, FOAF.NAME, f.createLiteral("foo"), true)); +// } -// Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); - - assertTrue(hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); - assertTrue(hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); - -// operation.execute(); - - m_repo.prepareUpdate(update.toString()).evaluate(); - - String msg = "foaf:name properties should have been deleted"; - assertFalse(msg, hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); - assertFalse(msg, hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); - - msg = "foaf:name properties with value 'foo' should have been added"; - assertTrue(msg, hasStatement(bob, FOAF.NAME, f.createLiteral("foo"), true)); - assertTrue(msg, hasStatement(alice, FOAF.NAME, f.createLiteral("foo"), true)); - } - //@Test - public void testUpdateSequenceInsertDelete() - throws Exception - { -// logger.debug("executing testUpdateSequenceInsertDelete"); - - final StringBuilder update = new StringBuilder(); - update.append(getNamespaceDeclarations()); - update.append("INSERT {?x foaf:name \"foo\" } WHERE {?y ex:containsPerson ?x}; "); - update.append(getNamespaceDeclarations()); - update.append("DELETE {?y foaf:name [] } WHERE {?x ex:containsPerson ?y } "); - -// Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); - - assertTrue(hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); - assertTrue(hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); - -// operation.execute(); - m_repo.prepareUpdate(update.toString()).evaluate(); - - String msg = "foaf:name properties should have been deleted"; - assertFalse(msg, hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); - assertFalse(msg, hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); - - msg = "foaf:name properties with value 'foo' should not have been added"; - assertFalse(msg, hasStatement(bob, FOAF.NAME, f.createLiteral("foo"), true)); - assertFalse(msg, hasStatement(alice, FOAF.NAME, f.createLiteral("foo"), true)); - } - - //@Test public void testUpdateSequenceInsertDelete2() throws Exception { -// logger.debug("executing testUpdateSequenceInsertDelete2"); +// log.debug("executing testUpdateSequenceInsertDelete2"); final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); @@ -1232,7 +1561,7 @@ public void testUpdateSequenceInsertDeleteExample9() throws Exception { -// logger.debug("executing testUpdateSequenceInsertDeleteExample9"); +// log.debug("executing testUpdateSequenceInsertDeleteExample9"); // replace the standard dataset with one specific to this case. m_repo.prepareUpdate("DROP ALL").evaluate(); @@ -1390,7 +1719,7 @@ // public void testUpdateSequenceInsertDeleteExample9() // throws Exception // { -// logger.debug("executing testUpdateSequenceInsertDeleteExample9"); +// log.debug("executing testUpdateSequenceInsertDeleteExample9"); // // // replace the standard dataset with one specific to this case. // con.clear(); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/org/openrdf/query/parser/sparql/SPARQLUpdateTest.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/org/openrdf/query/parser/sparql/SPARQLUpdateTest.java 2012-07-02 00:13:15 UTC (rev 6375) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/org/openrdf/query/parser/sparql/SPARQLUpdateTest.java 2012-07-02 15:00:31 UTC (rev 6376) @@ -12,18 +12,23 @@ import org.openrdf.model.Literal; import org.openrdf.model.Resource; +import org.openrdf.model.Statement; import org.openrdf.model.URI; import org.openrdf.model.ValueFactory; import org.openrdf.model.vocabulary.RDF; import org.openrdf.model.vocabulary.RDFS; import org.openrdf.model.vocabulary.XMLSchema; +import org.openrdf.query.BindingSet; import org.openrdf.query.MalformedQueryException; +import org.openrdf.query.QueryEvaluationException; import org.openrdf.query.QueryLanguage; +import org.openrdf.query.TupleQueryResult; import org.openrdf.query.Update; import org.openrdf.query.UpdateExecutionException; import org.openrdf.repository.Repository; import org.openrdf.repository.RepositoryConnection; import org.openrdf.repository.RepositoryException; +import org.openrdf.repository.RepositoryResult; import org.openrdf.rio.RDFFormat; import org.openrdf.rio.RDFParseException; import org.slf4j.Logger; @@ -42,23 +47,31 @@ * suite runs against a local kb instance. The two test suites are not exactly * the same because one uses the {@link RemoteRepository} to commuicate with the * NSS while the other uses the local API. + * <p> + * Note: This was imported in order to expose {@link #con} to our implementation + * of the class, which let's us override {@link #loadDataset(String)} in order + * to turn off auto-commit. I've written Jeen to request the appropriate changes + * to the class in the openrdf SVN. Since then, we have added several of our own + * tests here. * * @author Jeen Broekstra + * @author Bryan Thompson * * @see TestSparqlUpdate - * - * FIXME This was imported in order to expose {@link #con} to our - * implementation of the class, which let's us override - * {@link #loadDataset(String)} in order to turn off auto-commit. I've - * written Jeen to request the appropriate changes to the class in the - * openrdf SVN, at which point we should be able to drop this class from - * our SVN repository. */ public abstract class SPARQLUpdateTest extends TestCase { static final Logger logger = LoggerFactory.getLogger(SPARQLUpdateTest.class); - private Repository rep; + /** + * When <code>true</code>, the unit tests of the BINDINGS clause are + * enabled. + * + * FIXME BINDINGS does not work correctly for UPDATE. + */ + private static boolean BINDINGS = false; + + private Repository rep; protected RepositoryConnection con; @@ -123,11 +136,11 @@ throws Exception { logger.debug("executing test InsertWhere"); - StringBuilder update = new StringBuilder(); + final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); update.append("INSERT {?x rdfs:label ?y . } WHERE {?x foaf:name ?y }"); - Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); + final Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); assertFalse(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bob"), true)); assertFalse(con.hasStatement(alice, RDFS.LABEL, f.createLiteral("Alice"), true)); @@ -138,16 +151,235 @@ assertTrue(con.hasStatement(alice, RDFS.LABEL, f.createLiteral("Alice"), true)); } + /** + * @since openrdf 2.6.3 + */ +// @Test + public void testInsertWhereWithBinding() + throws Exception + { + if (!BINDINGS) + return; + logger.debug("executing test testInsertWhereWithBinding"); + final StringBuilder update = new StringBuilder(); + update.append(getNamespaceDeclarations()); + update.append("INSERT {?x rdfs:label ?y . } WHERE {?x foaf:name ?y }"); + + final Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); + operation.setBinding("x", bob); + + assertFalse(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bob"), true)); + assertFalse(con.hasStatement(alice, RDFS.LABEL, f.createLiteral("Alice"), true)); + + operation.execute(); + + assertTrue(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bob"), true)); + assertFalse(con.hasStatement(alice, RDFS.LABEL, f.createLiteral("Alice"), true)); + } + + /** + * @since openrdf 2.6.6 + */ + public void testInsertWhereWithBindings2() + throws Exception + { + if (!BINDINGS) + return; + logger.debug("executing test testInsertWhereWithBindings2"); + StringBuilder update = new StringBuilder(); + update.append(getNamespaceDeclarations()); + update.append("INSERT {?x rdfs:label ?z . } WHERE {?x foaf:name ?y }"); + + Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); + operation.setBinding("z", f.createLiteral("Bobbie")); + operation.setBinding("x", bob); + + assertFalse(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bobbie"), true)); + assertFalse(con.hasStatement(alice, RDFS.LABEL, null, true)); + + operation.execute(); + + assertTrue(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bobbie"), true)); + assertFalse(con.hasStatement(alice, RDFS.LABEL, f.createLiteral("Alice"), true)); + } + + /** + * @since openrdf 2.6.3 + */ +// @Test + public void testInsertEmptyWhere() + throws Exception + { + logger.debug("executing test testInsertEmptyWhere"); + final StringBuilder update = new StringBuilder(); + update.append(getNamespaceDeclarations()); + update.append("INSERT { <" + bob + "> rdfs:label \"Bob\" . } WHERE { }"); + + final Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); + + assertFalse(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bob"), true)); + + operation.execute(); + + assertTrue(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bob"), true)); + } + + /** + * @since openrdf 2.6.3 + */ +// @Test + public void testInsertEmptyWhereWithBinding() + throws Exception + { + if (!BINDINGS) + return; + logger.debug("executing test testInsertEmptyWhereWithBinding"); + final StringBuilder update = new StringBuilder(); + update.append(getNamespaceDeclarations()); + update.append("INSERT {?x rdfs:label ?y . } WHERE { }"); + + final Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); + operation.setBinding("x", bob); + operation.setBinding("y", f.createLiteral("Bob")); + + assertFalse(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bob"), true)); + + operation.execute(); + + assertTrue(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bob"), true)); + } + + /** + * @since openrdf 2.6.3 + */ +// @Test + public void testInsertNonMatchingWhere() + throws Exception + { + logger.debug("executing test testInsertNonMatchingWhere"); + final StringBuilder update = new StringBuilder(); + update.append(getNamespaceDeclarations()); + update.append("INSERT { ?x rdfs:label ?y . } WHERE { ?x rdfs:comment ?y }"); + + final Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); + + assertFalse(con.hasStatement(bob, RDFS.LABEL, null, true)); + + operation.execute(); + + assertFalse(con.hasStatement(bob, RDFS.LABEL, null, true)); + } + + /** + * @since openrdf 2.6.3 + */ +// @Test + public void testInsertNonMatchingWhereWithBindings() + throws Exception + { + if (!BINDINGS) + return; + logger.debug("executing test testInsertNonMatchingWhereWithBindings"); + final StringBuilder update = new StringBuilder(); + update.append(getNamespaceDeclarations()); + update.append("INSERT { ?x rdfs:label ?y . } WHERE { ?x rdfs:comment ?y }"); + + final Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); + operation.setBinding("x", bob); + operation.setBinding("y", f.createLiteral("Bob")); + + assertFalse(con.hasStatement(bob, RDFS.LABEL, null, true)); + + operation.execute(); + + assertFalse(con.hasStatement(bob, RDFS.LABEL, null, true)); + } + + /** + * @since openrdf 2.6.3 + */ +// @Test + public void testInsertWhereWithBindings() + throws Exception + { + if (!BINDINGS) + return; + logger.debug("executing test testInsertWhereWithBindings"); + final StringBuilder update = new StringBuilder(); + update.append(getNamespaceDeclarations()); + update.append("INSERT { ?x rdfs:comment ?z . } WHERE { ?x foaf:name ?y }"); + + final Literal comment = f.createLiteral("Bob has a comment"); + + final Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); + operation.setBinding("x", bob); + operation.setBinding("z", comment); + + assertFalse(con.hasStatement(null, RDFS.COMMENT, comment, true)); + + operation.execute(); + + assertTrue(con.hasStatement(bob, RDFS.COMMENT, comment, true)); + assertFalse(con.hasStatement(alice, RDFS.COMMENT, comment, true)); + + } + + /** + * @since openrdf 2.6.3 + */ +// @Test + public void testInsertWhereWithOptional() + throws Exception + { + logger.debug("executing testInsertWhereWithOptional"); + + final StringBuilder update = new StringBuilder(); + update.append(getNamespaceDeclarations()); + update.append(" INSERT { ?s ex:age ?incAge } "); + // update.append(" DELETE { ?s ex:age ?age } "); + update.append(" WHERE { ?s foaf:name ?name . "); + update.append(" OPTIONAL {?s ex:age ?age . BIND ((?age + 1) as ?incAge) } "); + update.append(" } "); + + final Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); + + final URI age = f.createURI(EX_NS, "age"); + + assertFalse(con.hasStatement(alice, age, null, true)); + assertTrue(con.hasStatement(bob, age, null, true)); + + operation.execute(); + + RepositoryResult<Statement> result = con.getStatements(bob, age, null, true); + + while (result.hasNext()) { + final Statement stmt = result.next(); + if (logger.isInfoEnabled()) + logger.info(stmt.toString()); + } + + assertTrue(con.hasStatement(bob, age, f.createLiteral("43", XMLSchema.INTEGER), true)); + + result = con.getStatements(alice, age, null, true); + + while (result.hasNext()) { + final Statement stmt = result.next(); + if (logger.isInfoEnabled()) + logger.info(stmt.toString()); + } + assertFalse(con.hasStatement(alice, age, null, true)); + } + //@Test public void testDeleteInsertWhere() throws Exception { logger.debug("executing test DeleteInsertWhere"); - StringBuilder update = new StringBuilder(); + final StringBuilder update = new StringBuilder(); update.append(getNamespaceDeclarations()); update.append("DELETE { ?x foaf:name ?y } INSERT {?x rdfs:label ?y . } WHERE {?x foaf:name ?y }"); - Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); + final Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); assertFalse(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bob"), true)); assertFalse(con.hasStatement(alice, RDFS.LABEL, f.createLiteral("Alice"), true)); @@ -166,7 +398,64 @@ } - //@Test + /** @since OPENRDF 2.6.6. */ +// @Test + public void testDeleteInsertWhereWithBindings2() + throws Exception + { + if (!BINDINGS) + return; + logger.debug("executing test testDeleteInsertWhereWithBindings2"); + final StringBuilder update = new StringBuilder(); + update.append(getNamespaceDeclarations()); + update.append("DELETE { ?x foaf:name ?y } INSERT {?x rdfs:label ?z . } WHERE {?x foaf:name ?y }"); + + final Update operation = con.prepareUpdate(QueryLanguage.SPARQL, update.toString()); + + operation.setBinding("z", f.createLiteral("person")); + + assertFalse(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("Bob"), true)); + assertFalse(con.hasStatement(alice, RDFS.LABEL, f.createLiteral("Alice"), true)); + + operation.execute(); + + assertTrue(con.hasStatement(bob, RDFS.LABEL, f.createLiteral("person"), true)); + assertTrue(con.hasStatement(alice, RDFS.LABEL, f.createLiteral("person"), true)); + + assertFalse(con.hasStatement(bob, FOAF.NAME, f.createLiteral("Bob"), true)); + assertFalse(con.hasStatement(alice, FOAF.NAME, f.createLiteral("Alice"), true)); + } + + /** @since openrdf 2.6.3 */ + public void testDeleteInsertWhereLoopingBehavior() throws Exception { + logger.debug("executing test testDeleteInsertWhereLoopingBehavior"); + final StringBuilder update = new StringBuilder(); + update.append(getNamespaceDeclarations()); + update.append(" DELETE { ?x ex:age ?y } INSERT {?x ex:age ?z }"); + update.append(" WHERE { "); + update.append(" ?x ex:age ?y ."); + update.append(" BIND((?y + 1) as ?z) "); + update.append(" FILTER( ?y < 46 ) "); + update.append(" } "); + + final Update operation = con.prepareUpdate(QueryLanguage.SPARQL, + update.toString()); + + final URI age = f.createURI(EX_NS, "age"); + final Literal originalAgeValue = f.createLiteral("42", XMLSchema.INTEGER); + final Literal correctAgeValue = f.createLiteral("43", XMLSchema.INTEGER); + final Literal inCorrectAgeValue = f.createLiteral("46", XMLSchema.INTEGER); + + assertTrue(con.hasStatement(bob, age, originalAgeValue, true)); + + operation.execute(); + + assertFalse(con.hasStatement(bob, age, originalAgeValue, true)); + assertTrue(con.hasStatement(bob, age, correctAgeValue, true)); + assertFalse(con.hasStatement(bob, age, inCorrectAgeValue, true)); + } + + //@Test public void testInsertTransformedWhere() throws Exception { @@ -186,7 +475,7 @@ assertTrue(con.hasStatement(bob, RDFS.LABEL, null, true)); assertTrue(con.hasStatement(alice, RDFS.LABEL, null, true)); } - + //@Test public void testInsertWhereGraph() throws Exception @@ -240,19 +529,20 @@ { logger.debug("executing testInsertWhereWith"); - StringBuilder update = new... [truncated message content] |
From: <mrp...@us...> - 2012-07-12 20:18:05
|
Revision: 6383 http://bigdata.svn.sourceforge.net/bigdata/?rev=6383&view=rev Author: mrpersonick Date: 2012-07-12 20:17:58 +0000 (Thu, 12 Jul 2012) Log Message: ----------- added a regex feature to full text search and exposed it via a magic predicate Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/search/FullTextIndex.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/search/TestPrefixSearch.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/search/TestSearch.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/search/TestSearchRestartSafe.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/lexicon/BigdataValueCentricFullTextIndex.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/lexicon/ITextIndexer.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ASTSearchOptimizer.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SearchServiceFactory.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/store/BD.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/lexicon/TestFullTextIndex.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/lexicon/TestSubjectCentricFullTextIndex.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/TestSearchQuery.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/search/FullTextIndex.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/search/FullTextIndex.java 2012-07-12 20:16:24 UTC (rev 6382) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/search/FullTextIndex.java 2012-07-12 20:17:58 UTC (rev 6383) @@ -42,9 +42,9 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; import org.apache.log4j.Logger; import org.apache.lucene.analysis.Analyzer; @@ -951,10 +951,10 @@ final double minCosine, final double maxCosine, final int minRank, final int maxRank, final boolean matchAllTerms, final boolean matchExact, - long timeout, final TimeUnit unit) { + long timeout, final TimeUnit unit, final String regex) { final Hit<V>[] a = _search(query, languageCode, prefixMatch, minCosine, - maxCosine, minRank, maxRank, matchAllTerms, matchExact, timeout, unit); + maxCosine, minRank, maxRank, matchAllTerms, matchExact, timeout, unit, regex); return new Hiterator<Hit<V>>(// Arrays.asList(a)// @@ -972,7 +972,7 @@ return count(query, languageCode, prefixMatch, 0.0d, 1.0d, 1, 10000, false, false, this.timeout,// - TimeUnit.MILLISECONDS); + TimeUnit.MILLISECONDS, null); } @@ -982,10 +982,10 @@ final double minCosine, final double maxCosine, final int minRank, final int maxRank, final boolean matchAllTerms, final boolean matchExact, - long timeout, final TimeUnit unit) { + long timeout, final TimeUnit unit, final String regex) { final Hit[] a = _search(query, languageCode, prefixMatch, minCosine, - maxCosine, minRank, maxRank, matchAllTerms, matchExact, timeout, unit); + maxCosine, minRank, maxRank, matchAllTerms, matchExact, timeout, unit, regex); return a.length; @@ -997,7 +997,7 @@ final double minCosine, final double maxCosine, final int minRank, final int maxRank, final boolean matchAllTerms, final boolean matchExact, - long timeout, final TimeUnit unit) { + long timeout, final TimeUnit unit, final String regex) { final long begin = System.currentTimeMillis(); @@ -1039,7 +1039,7 @@ } final FullTextSearchQuery cacheKey = new FullTextSearchQuery( - query, matchAllTerms, matchExact, prefixMatch, timeout, unit + query, matchAllTerms, matchExact, prefixMatch, timeout, unit, regex ); Hit<V>[] a; @@ -1243,6 +1243,28 @@ return a; } + + /* + * Do regex matching. + */ + if (regex != null) { + + final Pattern pattern = Pattern.compile(regex); + + a = applyRegex(a, pattern); + + } + + if (a.length == 0) { + + log.warn("No hits after regex pruning: languageCode=[" + languageCode + "], query=[" + + query + "], regex=[" + regex + "]"); + + cache.put(cacheKey, a); + + return a; + + } /* * Rank order the hits by relevance. @@ -1419,6 +1441,19 @@ throw new UnsupportedOperationException(); } + + /** + * Subclasses can override this method to do regex post-processing. This + * involves materializing the hits into their original text values and + * checking against the regex string in the materialized value. Not possible + * from the base class. The value-centric RDF version can use the lexicon to + * materialize the hits and check them against the regex. + */ + protected Hit<V>[] applyRegex(final Hit<V>[] hits, final Pattern regex) { + + throw new UnsupportedOperationException(); + + } /* * @todo implement the relevant methods. @@ -1468,6 +1503,7 @@ private final boolean prefixMatch; private final long timeout; private final TimeUnit unit; + private final String regex; public FullTextSearchQuery( final String search, @@ -1475,7 +1511,8 @@ final boolean matchExact, final boolean prefixMatch, final long timeout, - final TimeUnit unit) { + final TimeUnit unit, + final String regex) { this.search = search; this.matchAllTerms = matchAllTerms; @@ -1483,12 +1520,13 @@ this.prefixMatch = prefixMatch; this.timeout = timeout; this.unit = unit; + this.regex = regex; } - /** - * Generated by Eclipse. - */ + /** + * Generated by Eclipse. + */ @Override public int hashCode() { final int prime = 31; @@ -1496,6 +1534,7 @@ result = prime * result + (matchAllTerms ? 1231 : 1237); result = prime * result + (matchExact ? 1231 : 1237); result = prime * result + (prefixMatch ? 1231 : 1237); + result = prime * result + ((regex == null) ? 0 : regex.hashCode()); result = prime * result + ((search == null) ? 0 : search.hashCode()); result = prime * result + (int) (timeout ^ (timeout >>> 32)); @@ -1503,9 +1542,9 @@ return result; } - /** - * Generated by Eclipse. - */ + /** + * Generated by Eclipse. + */ @Override public boolean equals(Object obj) { if (this == obj) @@ -1521,6 +1560,11 @@ return false; if (prefixMatch != other.prefixMatch) return false; + if (regex == null) { + if (other.regex != null) + return false; + } else if (!regex.equals(other.regex)) + return false; if (search == null) { if (other.search != null) return false; @@ -1532,6 +1576,7 @@ return false; return true; } + } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/search/TestPrefixSearch.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/search/TestPrefixSearch.java 2012-07-12 20:16:24 UTC (rev 6382) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/search/TestPrefixSearch.java 2012-07-12 20:17:58 UTC (rev 6383) @@ -71,6 +71,7 @@ final boolean matchAllTerms = false; final long timeout = Long.MAX_VALUE; final TimeUnit unit = TimeUnit.MILLISECONDS; + final String regex = null; final Properties properties = getProperties(); @@ -113,7 +114,7 @@ final Hiterator<?> itr = ndx.search("The quick brown dog", languageCode, false/* prefixMatch */ , minCosine, maxCosine, - minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit); + minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit, regex); if (log.isInfoEnabled()) log.info("hits:" + itr); @@ -143,7 +144,7 @@ final Hiterator<?> itr = ndx.search("The qui bro do", languageCode, true/*prefixMatch*/, minCosine, maxCosine, - minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit); + minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit, regex); if(log.isInfoEnabled()) log.info("hits:" + itr); @@ -172,14 +173,14 @@ final Hiterator<?> itr = ndx .search("brown", languageCode, false/* prefixMatch */, minCosine, maxCosine, - minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit); + minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit, regex); if(log.isInfoEnabled()) log.info("hits:" + itr); assertEquals(2, ndx .count("brown", languageCode, false/* prefixMatch */, minCosine, maxCosine, - minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit)); + minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit, regex)); } @@ -190,13 +191,13 @@ final Hiterator<?> itr = ndx .search("brown", languageCode, true/* prefixMatch */, minCosine, maxCosine, - minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit); + minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit, regex); if(log.isInfoEnabled()) log.info("hits:" + itr); assertEquals(2, ndx .count("brown", languageCode, true/* prefixMatch */, minCosine, maxCosine, - minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit)); + minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit, regex)); } @@ -207,13 +208,13 @@ final Hiterator<?> itr = ndx .search("bro", languageCode, true/* prefixMatch */, minCosine, maxCosine, - minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit); + minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit, regex); if(log.isInfoEnabled()) log.info("hits:" + itr); assertEquals(2, ndx .count("bro", languageCode, true/* prefixMatch */, minCosine, maxCosine, - minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit)); + minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit, regex)); } @@ -224,7 +225,7 @@ final Hiterator<?> itr = ndx .search("bro", languageCode, false/* prefixMatch */, minCosine, maxCosine, - minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit); + minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit, regex); if(log.isInfoEnabled()) log.info("hits:" + itr); @@ -240,7 +241,7 @@ final Hiterator<?> itr = ndx .search("qui", languageCode, true/* prefixMatch */, minCosine, maxCosine, - minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit); + minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit, regex); if(log.isInfoEnabled()) log.info("hits:" + itr); @@ -256,7 +257,7 @@ final Hiterator<?> itr = ndx .search("qui", languageCode, false/* prefixMatch */, minCosine, maxCosine, - minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit); + minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit, regex); if (log.isInfoEnabled()) log.info("hits:" + itr); @@ -272,7 +273,7 @@ final Hiterator<?> itr = ndx .search("quick", languageCode, false/* prefixMatch */, minCosine, maxCosine, - minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit); + minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit, regex); if (log.isInfoEnabled()) log.info("hits:" + itr); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/search/TestSearch.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/search/TestSearch.java 2012-07-12 20:16:24 UTC (rev 6382) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/search/TestSearch.java 2012-07-12 20:17:58 UTC (rev 6383) @@ -114,6 +114,7 @@ final boolean matchAllTerms = false; final long timeout = Long.MAX_VALUE; final TimeUnit unit = TimeUnit.MILLISECONDS; + final String regex = null; final Properties properties = getProperties(); @@ -154,7 +155,7 @@ final Hiterator<Hit<Long>> itr = ndx.search(query, languageCode, prefixMatch, minCosine, maxCosine, - minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit); + minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit, regex); // query, languageCode, 0d/* minCosine */, // Integer.MAX_VALUE/* maxRank */); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/search/TestSearchRestartSafe.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/search/TestSearchRestartSafe.java 2012-07-12 20:16:24 UTC (rev 6382) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/search/TestSearchRestartSafe.java 2012-07-12 20:17:58 UTC (rev 6383) @@ -97,6 +97,7 @@ final boolean matchAllTerms = false; final long timeout = Long.MAX_VALUE; final TimeUnit unit = TimeUnit.MILLISECONDS; + final String regex = null; final Properties properties = getProperties(); @@ -144,7 +145,7 @@ // ); ndx.search(text, languageCode, prefixMatch, minCosine, maxCosine, - minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit); + minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit, regex); assertEquals(1, itr.size()); // Note: 2nd result pruned by cosine. @@ -177,7 +178,7 @@ final Hiterator<?> itr = // ndx.search(text, languageCode); ndx.search(text, languageCode, prefixMatch, minCosine, maxCosine, - minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit); + minRank, maxRank, matchAllTerms, false/* matchExact*/, timeout, unit, regex); assertEquals(1, itr.size()); // Note: 2nd result pruned by cosine. Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/lexicon/BigdataValueCentricFullTextIndex.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/lexicon/BigdataValueCentricFullTextIndex.java 2012-07-12 20:16:24 UTC (rev 6382) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/lexicon/BigdataValueCentricFullTextIndex.java 2012-07-12 20:17:58 UTC (rev 6383) @@ -33,6 +33,8 @@ import java.util.Map; import java.util.Properties; import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.apache.log4j.Logger; import org.openrdf.model.Literal; @@ -449,5 +451,74 @@ } + @Override + protected Hit[] applyRegex(final Hit[] hits, final Pattern regex) { + +// /* +// * Too big to do efficient exact matching. +// */ +// if (hits.length > 10000) { +// +// return hits; +// +// } + + final int chunkSize = 1000; + + final Hit[] tmp = new Hit[hits.length]; + + final Map<IV<?,?>, Hit> iv2Hit = new HashMap<IV<?,?>, Hit>(chunkSize); + + final LexiconRelation lex = getLexiconRelation(); + + int i = 0, k = 0; + while (i < hits.length) { + + iv2Hit.clear(); + + for (int j = 0; j < chunkSize && i < hits.length; j++) { + + final Hit h = hits[i++]; + + iv2Hit.put((IV<?,?>) h.getDocId(), h); + + } + + final Map<IV<?,?>, BigdataValue> terms = lex.getTerms(iv2Hit.keySet()); + + for (Map.Entry<IV<?,?>, BigdataValue> e : terms.entrySet()) { + + final IV<?,?> iv = e.getKey(); + + final BigdataValue term = e.getValue(); + + final String s = term.stringValue(); + + final Matcher matcher = regex.matcher(s); + + if (matcher.find()) { + + tmp[k++] = iv2Hit.get(iv); + + } + + } + + } + + if (k < hits.length) { + + final Hit[] a = new Hit[k]; + System.arraycopy(tmp, 0, a, 0, k); + return a; + + } else { + + return hits; + + } + + } + } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/lexicon/ITextIndexer.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/lexicon/ITextIndexer.java 2012-07-12 20:16:24 UTC (rev 6382) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/lexicon/ITextIndexer.java 2012-07-12 20:17:58 UTC (rev 6383) @@ -117,6 +117,8 @@ * to using {@link Long#MAX_VALUE}). * @param unit * The unit in which the timeout is expressed. + * @param regex + * A regex filter to apply to the search. * * @return The result set. */ @@ -125,7 +127,7 @@ final double minCosine, final double maxCosine, final int minRank, final int maxRank, final boolean matchAllTerms, final boolean matchExact, - long timeout, final TimeUnit unit); + long timeout, final TimeUnit unit, final String regex); /** * Count free text search results. @@ -164,6 +166,8 @@ * to using {@link Long#MAX_VALUE}). * @param unit * The unit in which the timeout is expressed. + * @param regex + * A regex filter to apply to the search. * * @return The result count. */ @@ -172,6 +176,6 @@ final double minCosine, final double maxCosine, final int minRank, final int maxRank, final boolean matchAllTerms, final boolean matchExact, - long timeout, final TimeUnit unit); + long timeout, final TimeUnit unit, final String regex); } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ASTSearchOptimizer.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ASTSearchOptimizer.java 2012-07-12 20:16:24 UTC (rev 6382) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ASTSearchOptimizer.java 2012-07-12 20:17:58 UTC (rev 6383) @@ -107,6 +107,7 @@ set.add(BD.MATCH_EXACT); set.add(BD.SUBJECT_SEARCH); set.add(BD.SEARCH_TIMEOUT); + set.add(BD.MATCH_REGEX); searchUris = Collections.unmodifiableSet(set); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SearchServiceFactory.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SearchServiceFactory.java 2012-07-12 20:16:24 UTC (rev 6382) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/SearchServiceFactory.java 2012-07-12 20:17:58 UTC (rev 6383) @@ -295,6 +295,11 @@ assertObjectIsLiteral(sp); + } else if(uri.equals(BD.MATCH_REGEX)) { + + // a variable for the object is equivalent to regex = null +// assertObjectIsLiteral(sp); + } else { throw new AssertionError("Unverified search predicate: " + sp); @@ -355,6 +360,7 @@ private final boolean matchExact; private final boolean subjectSearch; private final Literal searchTimeout; + private final Literal matchRegex; public SearchCall( final AbstractTripleStore store, @@ -401,6 +407,7 @@ boolean matchExact = false; boolean subjectSearch = false; Literal searchTimeout = null; + Literal matchRegex = null; for (StatementPatternNode meta : statementPatterns.values()) { @@ -432,6 +439,8 @@ subjectSearch = ((Literal) oVal).booleanValue(); } else if (BD.SEARCH_TIMEOUT.equals(p)) { searchTimeout = (Literal) oVal; + } else if (BD.MATCH_REGEX.equals(p)) { + matchRegex = (Literal) oVal; } } @@ -449,6 +458,7 @@ this.matchExact = matchExact; this.subjectSearch = subjectSearch; this.searchTimeout = searchTimeout; + this.matchRegex = matchRegex; } @@ -485,7 +495,8 @@ matchAllTerms, matchExact, searchTimeout == null ? BD.DEFAULT_TIMEOUT/*0L*/ : searchTimeout.longValue()/* timeout */, - TimeUnit.MILLISECONDS); + TimeUnit.MILLISECONDS, + matchRegex == null ? null : matchRegex.stringValue()); } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/store/BD.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/store/BD.java 2012-07-12 20:16:24 UTC (rev 6382) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/store/BD.java 2012-07-12 20:17:58 UTC (rev 6383) @@ -302,6 +302,27 @@ final boolean DEFAULT_MATCH_EXACT = false; + /** + * Magic predicate used to query for free text search metadata. Use + * in conjunction with {@link #SEARCH} as follows: + * <p> + * <pre> + * + * select ?s + * where { + * ?s bd:search "scale-out RDF triplestore" . + * ?s bd:matchRegex "regex to apply to ?s bindings" . + * } + * + * </pre> + * <p> + * This operation will be rather expensive as it will require materializing + * all the hits to check their values. + */ + final URI MATCH_REGEX = new URIImpl(SEARCH_NAMESPACE+"matchRegex"); + + final String DEFAULT_MATCH_REGEX = null; + final boolean DEFAULT_PREFIX_MATCH = false; /** Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/lexicon/TestFullTextIndex.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/lexicon/TestFullTextIndex.java 2012-07-12 20:16:24 UTC (rev 6382) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/lexicon/TestFullTextIndex.java 2012-07-12 20:17:58 UTC (rev 6383) @@ -134,7 +134,8 @@ false/* matchAllTerms */, false, // matchExact Long.MAX_VALUE,//2L/* timeout */, - TimeUnit.MILLISECONDS// TimeUnit.SECONDS + TimeUnit.MILLISECONDS,// TimeUnit.SECONDS + null//regex ); // assertEquals("#hits", (long) expected.length, itr.size()); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/lexicon/TestSubjectCentricFullTextIndex.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/lexicon/TestSubjectCentricFullTextIndex.java 2012-07-12 20:16:24 UTC (rev 6382) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/lexicon/TestSubjectCentricFullTextIndex.java 2012-07-12 20:17:58 UTC (rev 6383) @@ -139,7 +139,8 @@ false/* matchAllTerms */, false, // matchExact Long.MAX_VALUE,//2L/* timeout */, - TimeUnit.MILLISECONDS// TimeUnit.SECONDS + TimeUnit.MILLISECONDS,// TimeUnit.SECONDS + null//regex ); // assertEquals("#hits", (long) expected.length, itr.size()); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/TestSearchQuery.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/TestSearchQuery.java 2012-07-12 20:16:24 UTC (rev 6382) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/TestSearchQuery.java 2012-07-12 20:17:58 UTC (rev 6383) @@ -801,7 +801,8 @@ BD.DEFAULT_MATCH_ALL_TERMS,//false, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { @@ -869,7 +870,8 @@ BD.DEFAULT_MATCH_ALL_TERMS,//false, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { @@ -940,7 +942,8 @@ BD.DEFAULT_MATCH_ALL_TERMS,//false, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { @@ -1015,7 +1018,8 @@ BD.DEFAULT_MATCH_ALL_TERMS,//false, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { @@ -1092,7 +1096,8 @@ BD.DEFAULT_MATCH_ALL_TERMS,//false, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { @@ -1167,7 +1172,8 @@ BD.DEFAULT_MATCH_ALL_TERMS,//false, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { @@ -1238,7 +1244,8 @@ true, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { @@ -1308,7 +1315,8 @@ false, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { @@ -1348,7 +1356,8 @@ false, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); if (log.isInfoEnabled()) { @@ -1488,7 +1497,8 @@ BD.DEFAULT_MATCH_ALL_TERMS,//false, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { @@ -1554,7 +1564,8 @@ BD.DEFAULT_MATCH_ALL_TERMS,//false, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { @@ -1626,7 +1637,8 @@ BD.DEFAULT_MATCH_ALL_TERMS,//false, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { @@ -1703,7 +1715,8 @@ BD.DEFAULT_MATCH_ALL_TERMS,//false, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { @@ -1781,7 +1794,8 @@ BD.DEFAULT_MATCH_ALL_TERMS,//false, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { @@ -1857,7 +1871,8 @@ BD.DEFAULT_MATCH_ALL_TERMS,//false, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { @@ -1929,7 +1944,8 @@ true, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { @@ -2001,7 +2017,8 @@ false, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { @@ -2041,7 +2058,8 @@ false, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); if (log.isInfoEnabled()) { @@ -2187,7 +2205,8 @@ BD.DEFAULT_MATCH_ALL_TERMS,//false, // matchAllTerms false, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { @@ -2569,7 +2588,8 @@ BD.DEFAULT_MATCH_ALL_TERMS,//false, // matchAllTerms true, // matchExact BD.DEFAULT_TIMEOUT,//1000L, // timeout - TimeUnit.MILLISECONDS // unit + TimeUnit.MILLISECONDS, // unit + null // regex ); while (hits.hasNext()) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2012-07-20 21:21:16
|
Revision: 6385 http://bigdata.svn.sourceforge.net/bigdata/?rev=6385&view=rev Author: thompsonbry Date: 2012-07-20 21:21:08 +0000 (Fri, 20 Jul 2012) Log Message: ----------- Added a DISTINCT (s,p,o) filter to the CONSTRUCT iterator (ASTConstructIterator) in support of [1]. The DISTINCT SPO filter is always enabled. When the hint:analytic mode is enabled or when the hint:nativeDistinctSPO mode are enabled, then the CONSTUCT will use a filter backed by the native process heap. Otherwise it will use a filter backed by the JVM heap. Some unit tests have been added to verify that the NativeDistinctFilter is used when the appropriate query hint is specified. I pulled out an ICloseable interface from ICloseableIterator. The NativeDistinctFilter's internal DistinctFilterImpl class now implements ICloseable. An issue [2] has been created to extend the striterator protocol to support the ICloseable interface on IFilter and IFilterTest. [1] https://sourceforge.net/apps/trac/bigdata/ticket/579 (CONSTRUCT should impose distinct (s,p,o) filter) [2] http://sourceforge.net/apps/trac/bigdata/ticket/582 (IStriterator does not support close() protocol for IFilter) Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/ap/filter/DistinctFilter.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/striterator/ICloseableIterator.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/bop/rdf/filter/NativeDistinctFilter.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/ConstructNode.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ASTConstructIterator.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTConstructOptimizer.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTDescribeOptimizer.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/bop/rdf/filter/TestNativeDistinctFilter.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/TestBasicQuery.java branches/BIGDATA_RELEASE_1_2_0/ctc-striterators/src/java/cutthecrap/utils/striterators/IFilter.java Added Paths: ----------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/striterator/ICloseable.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/construct-1a.rq branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/construct-1b.rq Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/ap/filter/DistinctFilter.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/ap/filter/DistinctFilter.java 2012-07-18 13:48:50 UTC (rev 6384) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/ap/filter/DistinctFilter.java 2012-07-20 21:21:08 UTC (rev 6385) @@ -1,21 +1,27 @@ package com.bigdata.bop.ap.filter; +import java.util.HashSet; import java.util.Iterator; -import java.util.LinkedHashSet; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import com.bigdata.bop.BOp; import com.bigdata.bop.HashMapAnnotations; +import com.bigdata.rdf.spo.SPO; import com.bigdata.striterator.IChunkConverter; import com.bigdata.striterator.MergeFilter; import cutthecrap.utils.striterators.Filter; import cutthecrap.utils.striterators.Filterator; +import cutthecrap.utils.striterators.IPropertySet; /** * A DISTINCT operator based for elements in a relation. The operator is based * on an in-memory hash table. + * <p> + * Note: This is used for the in-memory {@link SPO} distinct filter, but + * it is more general and can be applied to any data type that can be + * inserted into a set. * * @author <a href="mailto:tho...@us...">Bryan Thompson</a> * @version $Id: DistinctElementFilter.java 3466 2010-08-27 14:28:04Z @@ -46,7 +52,9 @@ * A instance using the default configuration for the in memory hash map. */ public static DistinctFilter newInstance() { + return new DistinctFilter(BOp.NOARGS, BOp.NOANNS); + } /** @@ -66,34 +74,39 @@ } - /** - * @see Annotations#INITIAL_CAPACITY - */ - public int getInitialCapacity() { +// /** +// * @see Annotations#INITIAL_CAPACITY +// */ +// public int getInitialCapacity() { +// +// return getProperty(Annotations.INITIAL_CAPACITY, +// Annotations.DEFAULT_INITIAL_CAPACITY); +// +// } +// +// /** +// * @see Annotations#LOAD_FACTOR +// */ +// public float getLoadFactor() { +// +// return getProperty(Annotations.LOAD_FACTOR, +// Annotations.DEFAULT_LOAD_FACTOR); +// +// } - return getProperty(Annotations.INITIAL_CAPACITY, - Annotations.DEFAULT_INITIAL_CAPACITY); - - } - - /** - * @see Annotations#LOAD_FACTOR - */ - public float getLoadFactor() { - - return getProperty(Annotations.LOAD_FACTOR, - Annotations.DEFAULT_LOAD_FACTOR); - - } - @Override final protected Iterator filterOnce(Iterator src, final Object context) { - return new Filterator(src, context, new DistinctFilterImpl()); + return new Filterator(src, context, new DistinctFilterImpl(this)); } - private class DistinctFilterImpl extends Filter { + /** + * DISTINCT filter based on Java heap data structures. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ + public static class DistinctFilterImpl extends Filter { private static final long serialVersionUID = 1L; @@ -102,18 +115,46 @@ * {@link ConcurrentHashMap} here. */ @SuppressWarnings("rawtypes") - private final LinkedHashSet members; + private final HashSet members; + @SuppressWarnings("unchecked") + static private <T> T getProperty(final IPropertySet pset, + final String name, final T defaultValue) { + + final Object val = pset.getProperty(name); + + if (val != null) + return (T) val; + + return defaultValue; + + } + + /** + * DISTINCT filter based on Java heap data structures. + * + * @param propertySet + * Used to configured the DISTINCT filter. + * + * @see DistinctFilter.Annotations + */ @SuppressWarnings("rawtypes") - public DistinctFilterImpl() { + public DistinctFilterImpl(final IPropertySet propertySet) { + + final int initialCapacity = getProperty(propertySet, + Annotations.INITIAL_CAPACITY, + Annotations.DEFAULT_INITIAL_CAPACITY); - members = new LinkedHashSet(getInitialCapacity(), getLoadFactor()); + final float loadFactor = getProperty(propertySet, + Annotations.LOAD_FACTOR, Annotations.DEFAULT_LOAD_FACTOR); + members = new HashSet(initialCapacity, loadFactor); + } @SuppressWarnings("unchecked") @Override - public boolean isValid(Object obj) { + public boolean isValid(final Object obj) { return members.add(obj); Added: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/striterator/ICloseable.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/striterator/ICloseable.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/striterator/ICloseable.java 2012-07-20 21:21:08 UTC (rev 6385) @@ -0,0 +1,46 @@ +/* + +Copyright (C) SYSTAP, LLC 2006-2008. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 Jul 20, 2012 + */ +package com.bigdata.striterator; + +/** + * Interface for objects which can have resources which must be explicitly + * closed (typically iterators). + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ +public interface ICloseable { + + /** + * Closes the object, releasing any associated resources. This method MAY be + * invoked safely if the object is already closed. Implementations of this + * interface MUST invoke {@link #close()} once it is known that the object + * will no longer be used. + */ + public void close(); + +} Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/striterator/ICloseableIterator.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/striterator/ICloseableIterator.java 2012-07-18 13:48:50 UTC (rev 6384) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/striterator/ICloseableIterator.java 2012-07-20 21:21:08 UTC (rev 6385) @@ -38,7 +38,7 @@ * @author <a href="mailto:tho...@us...">Bryan Thompson</a> * @version $Id$ */ -public interface ICloseableIterator<E> extends Iterator<E> { +public interface ICloseableIterator<E> extends Iterator<E>, ICloseable { /** * Closes the iterator, releasing any associated resources. This method MAY Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/bop/rdf/filter/NativeDistinctFilter.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/bop/rdf/filter/NativeDistinctFilter.java 2012-07-18 13:48:50 UTC (rev 6384) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/bop/rdf/filter/NativeDistinctFilter.java 2012-07-20 21:21:08 UTC (rev 6385) @@ -7,12 +7,14 @@ import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; import com.bigdata.bop.BOp; import com.bigdata.bop.BTreeAnnotations; import com.bigdata.bop.HTreeAnnotations; import com.bigdata.bop.HashMapAnnotations; import com.bigdata.bop.ap.filter.BOpFilterBase; +import com.bigdata.bop.ap.filter.DistinctFilter; import com.bigdata.bop.engine.IRunningQuery; import com.bigdata.btree.BTree; import com.bigdata.btree.BloomFilterFactory; @@ -30,14 +32,17 @@ import com.bigdata.io.DirectBufferPool; import com.bigdata.rdf.internal.IV; import com.bigdata.rdf.internal.IVUtility; +import com.bigdata.rdf.sparql.ast.eval.ASTConstructIterator; import com.bigdata.rdf.spo.ISPO; import com.bigdata.rdf.spo.SPO; import com.bigdata.rdf.spo.SPOKeyOrder; import com.bigdata.rwstore.sector.MemStore; import com.bigdata.rwstore.sector.MemoryManager; +import com.bigdata.striterator.ICloseable; import cutthecrap.utils.striterators.Filter; import cutthecrap.utils.striterators.Filterator; +import cutthecrap.utils.striterators.IPropertySet; /** * A scalable DISTINCT operator based for {@link SPO}s. @@ -144,18 +149,18 @@ @Override final protected Iterator filterOnce(Iterator src, final Object context) { - return new Filterator(src, context, new DistinctFilterImpl()); + return new Filterator(src, context, new DistinctFilterImpl(this)); } /** * Return the 3-component key order which has the best locality given that - * the SPOs will be ariving in the natural order of the + * the SPOs will be arriving in the natural order of the * <i>indexKeyOrder</i>. This is the keyOrder that we will use for the * filter. This gives the filter index structure the best possible locality * in terms of the order in which the SPOs are arriving. * <p> - * The return valuer is an <code>int[3]</code>. The index is the orderinal + * The return valuer is an <code>int[3]</code>. The index is the ordinal * position of the triples mode key component for the filter keys. The value * at that index is the position in the {@link SPOKeyOrder} of the quads * mode index whose natural order determines the order of arrival of the @@ -183,19 +188,36 @@ * * which models the <code>PSO</code> key order for the purposes of this * class. + * <p> + * Note: This method now accepts triples in support of the + * {@link ASTConstructIterator} * * @see Annotations#INDEX_KEY_ORDER + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/579"> + * CONSTRUCT should apply DISTINCT (s,p,o) filter </a> */ - public static int[] getFilterKeyOrder(SPOKeyOrder indexKeyOrder) { + public static int[] getFilterKeyOrder(final SPOKeyOrder indexKeyOrder) { if (indexKeyOrder == null) throw new IllegalArgumentException(); - if (indexKeyOrder.getKeyArity() != 4) - throw new IllegalArgumentException(); +// if (indexKeyOrder.getKeyArity() != 4) +// throw new IllegalArgumentException(); final int[] filterKeyOrder; switch (indexKeyOrder.index()) { + // TRIPLES + case SPOKeyOrder._SPO: + filterKeyOrder = new int[] { 0, 1, 2 }; + break; + case SPOKeyOrder._POS: + filterKeyOrder = new int[] { 1, 2, 0 }; + break; + case SPOKeyOrder._OSP: + filterKeyOrder = new int[] { 2, 0, 1 }; + break; + // QUADS case SPOKeyOrder._SPOC: filterKeyOrder = new int[] { 0, 1, 2 }; break; @@ -220,7 +242,15 @@ return filterKeyOrder; } - private class DistinctFilterImpl extends Filter { + /** + * A {@link Filter} which passes only the DISTINCT {@link ISPO}s and is + * backed by a scalable data structure (BTree or HTree). + * + * @author <a href="mailto:tho...@us...">Bryan + * Thompson</a> + */ + static public class DistinctFilterImpl extends Filter implements + ICloseable { private static final long serialVersionUID = 1L; @@ -232,7 +262,7 @@ /** * The fast JVM based cache. This is always allocated. */ - private final LinkedHashMap<SPO, byte[]> lru; + private final LinkedHashMap<ISPO, byte[]> lru; /** * The metadata used to create the index. @@ -262,10 +292,15 @@ private volatile ICheckpointProtocol index; /** + * <code>true</code> until {@link #close() closed}. + */ + private final AtomicBoolean open = new AtomicBoolean(true); + + /** * When <code>true</code>, the {@link BTree} will be used. When * <code>false</code> the {@link HTree}. * <p> - * Note: Hisorical testing indicated that the {@link BTree} was faster + * Note: Historical testing indicated that the {@link BTree} was faster * for this application. * * TODO Edit HTree/BTree here. @@ -279,28 +314,85 @@ @Override protected void finalize() throws Throwable { + close(); super.finalize(); - if (index != null) { - index.close(); - index = null; + } + + /** + * Release resources associated with the filter. + * <p> + * Note: This is done automatically by {@link #finalize()}, but it + * should be done pro-actively whenever possible. + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/582"> + * IStriterator does not support close() protocol for Ifilter </a> + */ + @Override + public void close() { + if (open.compareAndSet(true/* expect */, false/* update */)) { + /* + * Close when first invoked. + */ + if (index != null) { + index.close(); + index = null; + } + if (store != null) { + store.close(); + store = null; + } } - if (store != null) { - store.close(); - store = null; - } } + + @SuppressWarnings("unchecked") + static private <T> T getRequiredProperty(final IPropertySet pset, + final String name) { + + final Object val = pset.getProperty(name); + + if (val == null) + + if (val == null) + throw new IllegalStateException("Required property: " + + name + " : " + NativeDistinctFilter.class); + + return (T) val; + + } + + @SuppressWarnings("unchecked") + static private <T> T getProperty(final IPropertySet pset, + final String name, final T defaultValue) { + + final Object val = pset.getProperty(name); + + if (val != null) + return (T) val; + + return defaultValue; + + } - public DistinctFilterImpl() { + /** + * DISTINCT {@link ISPO} filter based on persistence capable data + * structures. + * + * @param properties + * Used to configure the DISTINCT filter. + * + * @see DistinctFilter.Annotations + */ + public DistinctFilterImpl(final IPropertySet properties) { - final int initialCapacity = NativeDistinctFilter.this.getProperty( + final int initialCapacity = getProperty(properties, Annotations.INITIAL_CAPACITY, Annotations.DEFAULT_INITIAL_CAPACITY); - final float loadFactor = NativeDistinctFilter.this.getProperty( + final float loadFactor = getProperty(properties, Annotations.LOAD_FACTOR, Annotations.DEFAULT_LOAD_FACTOR); - lru = new LinkedHashMap<SPO, byte[]>(initialCapacity, loadFactor); + lru = new LinkedHashMap<ISPO, byte[]>(initialCapacity, loadFactor); this.nominalCapacity = initialCapacity; @@ -312,8 +404,8 @@ */ { - final SPOKeyOrder indexKeyOrder = (SPOKeyOrder) NativeDistinctFilter.this - .getRequiredProperty(Annotations.KEY_ORDER); + final SPOKeyOrder indexKeyOrder = (SPOKeyOrder) getRequiredProperty( + properties, Annotations.KEY_ORDER); filterKeyOrder = getFilterKeyOrder(indexKeyOrder); @@ -322,20 +414,19 @@ : new HTreeIndexMetadata(UUID.randomUUID()); // IFF BTree - metadata.setBranchingFactor(NativeDistinctFilter.this.getProperty( + metadata.setBranchingFactor(getProperty(properties, BTreeAnnotations.BRANCHING_FACTOR, 256));// TODO Overridden here. BTreeAnnotations.DEFAULT_BRANCHING_FACTOR)); // IFF HTree if (metadata instanceof HTreeIndexMetadata) { ((HTreeIndexMetadata) metadata) - .setAddressBits(NativeDistinctFilter.this - .getProperty( + .setAddressBits(getProperty(properties, HTreeAnnotations.ADDRESS_BITS, HTreeAnnotations.DEFAULT_ADDRESS_BITS)); } - metadata.setRawRecords(NativeDistinctFilter.this.getProperty( + metadata.setRawRecords(getProperty(properties, Annotations.RAW_RECORDS, Annotations.DEFAULT_RAW_RECORDS)); @@ -344,10 +435,9 @@ metadata.setBloomFilterFactory(BloomFilterFactory.DEFAULT); - metadata.setWriteRetentionQueueCapacity(NativeDistinctFilter.this - .getProperty( - Annotations.WRITE_RETENTION_QUEUE_CAPACITY, - Annotations.DEFAULT_WRITE_RETENTION_QUEUE_CAPACITY)); + metadata.setWriteRetentionQueueCapacity(getProperty(properties, + Annotations.WRITE_RETENTION_QUEUE_CAPACITY, + Annotations.DEFAULT_WRITE_RETENTION_QUEUE_CAPACITY)); final int ratio = 32; // TODO Config/tune front-coding ratio. @@ -378,8 +468,8 @@ final int n = lru.size(); final byte[][] a = new byte[n][]; { - // Evict everthing into an array. - final Iterator<Map.Entry<SPO, byte[]>> itr = lru.entrySet() + // Evict everything into an array. + final Iterator<Map.Entry<ISPO, byte[]>> itr = lru.entrySet() .iterator(); int i = 0; while (itr.hasNext()) { @@ -409,6 +499,11 @@ if (index != null) throw new IllegalStateException(); + + if (!open.get()) { + // Explicitly closed. + throw new IllegalStateException(); + } /* * This wraps an efficient raw store interface around a child memory @@ -435,7 +530,7 @@ @Override public boolean isValid(final Object obj) { - final SPO spo = (SPO) obj; + final ISPO spo = (ISPO) obj; return add(spo); @@ -457,7 +552,7 @@ * * @return <code>true</code> if the collection was modified. */ - private boolean add(final SPO spo) { + private boolean add(final ISPO spo) { if(lru.containsKey(spo)) { // already in the LRU Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/ConstructNode.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/ConstructNode.java 2012-07-18 13:48:50 UTC (rev 6384) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/ConstructNode.java 2012-07-20 21:21:08 UTC (rev 6385) @@ -30,6 +30,8 @@ import java.util.Map; import com.bigdata.bop.BOp; +import com.bigdata.rdf.sparql.ast.eval.AST2BOpContext; +import com.bigdata.rdf.spo.ISPO; /** * A template for the construction of one or more graphs based on the solutions @@ -47,10 +49,47 @@ */ private static final long serialVersionUID = 1L; + public interface Annotations extends AbstractStatementContainer.Annotations { + + /** + * Boolean property (default {@value #DEFAULT_ALL_GRAPHS}) which is + * <code>true</code> iff a native DISTINCT {@link ISPO} filter should be + * applied (large cardinality is expected for the constructed graph). + * When <code>false</code>, a JVM based DISTINCT {@link ISPO} filter + * will be applied. + * <p> + * Note: This can be set using either {@link QueryHints#ANALYTIC} or + * {@link QueryHints#NATIVE_DISTINCT_SPO}. + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/579"> + * CONSTRUCT should apply DISTINCT (s,p,o) filter </a> + */ + String NATIVE_DISTINCT = "nativeDistinct"; + + boolean DEFAULT_NATIVE_DISTINCT = false; + + } + public ConstructNode() { + super(); + } + public ConstructNode(final AST2BOpContext ctx) { + + super(); + + if (ctx.nativeDistinctSPO) { + + // Native DISTINCT SPO FILTER is requested. + + setNativeDistinct(true); + + } + + } + /** * Required deep copy constructor. */ @@ -80,6 +119,29 @@ return this; } + + /** + * When <code>true</code>, a native DISTINCT {@link ISPO} filter will be + * applied to the constructed graph, otherwise a Java Heap based DISTINCT + * {@link ISPO} filter will be applied. + * + * @see Annotations#NATIVE_DISTINCT + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/579"> + * CONSTRUCT should apply DISTINCT (s,p,o) filter </a> + */ + public boolean isNativeDistinct() { + + return getProperty(Annotations.NATIVE_DISTINCT, + Annotations.DEFAULT_NATIVE_DISTINCT); + + } + + public void setNativeDistinct(final boolean nativeDistinct) { + + setProperty(Annotations.NATIVE_DISTINCT, nativeDistinct); + + } @Override public String toString(final int indent) { @@ -97,7 +159,10 @@ } sb.append("\n").append(s).append("}"); - + + if (isNativeDistinct()) + sb.append(" [nativeDistinct]"); + return sb.toString(); } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java 2012-07-18 13:48:50 UTC (rev 6384) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java 2012-07-20 21:21:08 UTC (rev 6385) @@ -721,7 +721,7 @@ */ final ConstructNode template = op.getDeleteClause() - .getQuadData().flatten(new ConstructNode()); + .getQuadData().flatten(new ConstructNode(context)); final ASTConstructIterator itr = new ASTConstructIterator( context.conn.getTripleStore(), template, @@ -789,7 +789,7 @@ */ final ConstructNode template = op.getInsertClause() - .getQuadData().flatten(new ConstructNode()); + .getQuadData().flatten(new ConstructNode(context)); final ASTConstructIterator itr = new ASTConstructIterator( context.conn.getTripleStore(), template, @@ -898,7 +898,7 @@ // Flatten the original WHERE clause into a CONSTRUCT // template. final ConstructNode template = quadData - .flatten(new ConstructNode()); + .flatten(new ConstructNode(context)); // Set the CONSTRUCT template (quads patterns). queryRoot.setConstruct(template); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ASTConstructIterator.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ASTConstructIterator.java 2012-07-18 13:48:50 UTC (rev 6384) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ASTConstructIterator.java 2012-07-20 21:21:08 UTC (rev 6385) @@ -44,6 +44,12 @@ import org.openrdf.query.QueryEvaluationException; import org.openrdf.query.impl.EmptyBindingSet; +import com.bigdata.bop.BOp; +import com.bigdata.bop.IPredicate; +import com.bigdata.bop.IVariableOrConstant; +import com.bigdata.bop.ap.filter.DistinctFilter; +import com.bigdata.bop.rdf.filter.NativeDistinctFilter; +import com.bigdata.rdf.internal.IV; import com.bigdata.rdf.model.BigdataBNode; import com.bigdata.rdf.model.BigdataStatement; import com.bigdata.rdf.model.BigdataValue; @@ -53,8 +59,14 @@ import com.bigdata.rdf.sparql.ast.StatementPatternNode; import com.bigdata.rdf.sparql.ast.TermNode; import com.bigdata.rdf.sparql.ast.VarNode; +import com.bigdata.rdf.spo.ISPO; +import com.bigdata.rdf.spo.SPOKeyOrder; +import com.bigdata.rdf.spo.SPOPredicate; import com.bigdata.rdf.store.AbstractTripleStore; +import com.bigdata.striterator.ICloseable; +import cutthecrap.utils.striterators.IFilterTest; + /** * Iterator consumes the solutions from a query and interprets them according to * a {@link ConstructNode}. Ground triples in the template are output @@ -98,6 +110,24 @@ */ private final List<BigdataStatement> buffer = new LinkedList<BigdataStatement>(); + /** + * A filter which restricts the emitted statements to the distinct + * {@link ISPO}. The {@link DistinctFilter} is based on the Java heap. The + * {@link NativeDistinctFilter} is based on persistence capable data + * structures and can scale to high cardinality outputs. Unfortunately, a + * complex CONSTRUCT template can make it impossible to predict the + * <p> + * Note: It is possible to disable this filter (in the code) by setting it + * to <code>null</code>. + * + * @see DistinctFilter + * @see NativeDistinctFilter + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/579"> + * CONSTRUCT should apply DISTINCT (s,p,o) filter </a> + */ + private final IFilterTest filter; + // /** // * Return <code>true</code>iff {@link LexiconRelation#isStoreBlankNodes()} // * is <code>true</code>. @@ -176,6 +206,57 @@ this.src = src; + /* + * Setup the DISTINCT SPO filter. + */ + + final boolean nativeDistinct = construct.isNativeDistinct(); + if (nativeDistinct) { + + /* + * Construct a predicate for the first triple template. We will use + * that as the bias for the scalable DISTINCT SPO filter. + */ + final IPredicate pred; + { + + final StatementPatternNode sp = templates.get(0/* index */); + + final IVariableOrConstant<IV> s = sp.s().getValueExpression(); + final IVariableOrConstant<IV> p = sp.p().getValueExpression(); + final IVariableOrConstant<IV> o = sp.o().getValueExpression(); + +// // The graph term/variable iff specified by the query. +// final TermNode cvar = sp.c(); +// final IVariableOrConstant<IV> c = cvar == null ? null : cvar +// .getValueExpression(); + + final BOp[] vars = new BOp[] { s, p, o /*, c*/ }; + + pred = new SPOPredicate(vars, BOp.NOANNS); + + } + + /* + * The index that will be used to read on the B+Tree access path. + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + final SPOKeyOrder indexKeyOrder = SPOKeyOrder.getKeyOrder( + (IPredicate) pred, 3/* keyArity */); + + construct.setProperty(NativeDistinctFilter.Annotations.KEY_ORDER, + indexKeyOrder); + + // Native memory based DISTINCT filter. + filter = new NativeDistinctFilter.DistinctFilterImpl(construct); + + } else { + + // JVM Based DISTINCT filter. + filter = new DistinctFilter.DistinctFilterImpl(construct); + + } + } public boolean hasNext() throws QueryEvaluationException { @@ -243,6 +324,21 @@ src.close(); + if (filter instanceof ICloseable) { + + /* + * Ensure that we release the backing MemoryManager in a timely + * fashion. + * + * @see <a + * href="https://sourceforge.net/apps/trac/bigdata/ticket/582"> + * IStriterator does not support close() protocol for IFilter + * </a> + */ + ((ICloseable) filter).close(); + + } + } } @@ -316,7 +412,28 @@ if(log.isDebugEnabled()) log.debug(stmt.toString()); - buffer.add(stmt); + if(filter != null) { + + /* + * Impose a DISTINCT SPO filter on the generated statements in the + * constructed graph. + * + * @see <a + * href="https://sourceforge.net/apps/trac/bigdata/ticket/579"> + * CONSTRUCT should apply DISTINCT (s,p,o) filter </a> + */ + + if(filter.isValid(stmt)) { + + buffer.add(stmt); + + } + + } else { + + buffer.add(stmt); + + } } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTConstructOptimizer.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTConstructOptimizer.java 2012-07-18 13:48:50 UTC (rev 6384) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTConstructOptimizer.java 2012-07-20 21:21:08 UTC (rev 6385) @@ -95,7 +95,13 @@ projection.addProjectionVar(new VarNode(itr.next().getName())); } - + + if (context.nativeDistinctSPO) { + + constructNode.setNativeDistinct(true); + + } + return queryRoot; } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTDescribeOptimizer.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTDescribeOptimizer.java 2012-07-18 13:48:50 UTC (rev 6384) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTDescribeOptimizer.java 2012-07-20 21:21:08 UTC (rev 6385) @@ -118,7 +118,7 @@ where.addChild(union); // append UNION to WHERE clause. - final ConstructNode construct = new ConstructNode(); + final ConstructNode construct = new ConstructNode(context); final ProjectionNode projection = queryRoot.getProjection(); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/bop/rdf/filter/TestNativeDistinctFilter.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/bop/rdf/filter/TestNativeDistinctFilter.java 2012-07-18 13:48:50 UTC (rev 6384) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/bop/rdf/filter/TestNativeDistinctFilter.java 2012-07-20 21:21:08 UTC (rev 6385) @@ -175,7 +175,7 @@ /** * Unit test for {@link NativeDistinctFilter#getFilterKeyOrder(SPOKeyOrder)} */ - public void test_filterKeyOrder() { + public void test_filterKeyOrder_quads() { assertEquals(new int[] {0,1,2}, NativeDistinctFilter.getFilterKeyOrder(SPOKeyOrder.SPOC)); @@ -197,6 +197,22 @@ } + /** + * Unit test for {@link NativeDistinctFilter#getFilterKeyOrder(SPOKeyOrder)} + */ + public void test_filterKeyOrder_triples() { + + assertEquals(new int[] { 0, 1, 2 }, + NativeDistinctFilter.getFilterKeyOrder(SPOKeyOrder.SPO)); + + assertEquals(new int[] { 1, 2, 0 }, + NativeDistinctFilter.getFilterKeyOrder(SPOKeyOrder.POS)); + + assertEquals(new int[] { 2, 0, 1 }, + NativeDistinctFilter.getFilterKeyOrder(SPOKeyOrder.OSP)); + + } + public void test_htreeDistinctSPOFilter() { final JoinSetup setup = new JoinSetup(getName()); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/TestBasicQuery.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/TestBasicQuery.java 2012-07-18 13:48:50 UTC (rev 6384) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/TestBasicQuery.java 2012-07-20 21:21:08 UTC (rev 6385) @@ -27,6 +27,9 @@ package com.bigdata.rdf.sparql.ast.eval; +import com.bigdata.rdf.sparql.ast.ASTContainer; +import com.bigdata.rdf.sparql.ast.ConstructNode; + /** * Data driven test suite. * @@ -93,16 +96,93 @@ */ public void test_construct_1() throws Exception { - new TestHelper( + final ASTContainer ast = new TestHelper( "construct-1", // testURI, "construct-1.rq",// queryFileURL "construct-1.trig",// dataFileURL "construct-1-result.trig"// resultFileURL ).runTest(); + final ConstructNode construct = ast.getOptimizedAST().getConstruct(); + + assertNotNull(construct); + + assertFalse(construct.isNativeDistinct()); + } /** + * A simple CONSTRUCT query using a native DISTINCT filter. + * + * <pre> + * PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> + * PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> + * PREFIX foaf: <http://xmlns.com/foaf/0.1/> + * + * CONSTRUCT { + * <http://www.bigdata.com/DC> rdfs:label "DC" . + * ?x rdf:type foaf:Person . + * } where { + * # Enable the native DISTINCT SPO filter. + * hint:Query hint:nativeDistinctSPO true . + * ?x rdf:type foaf:Person + * } + * </pre> + */ + public void test_construct_1a() throws Exception { + + final ASTContainer ast = new TestHelper( + "construct-1", // testURI, + "construct-1a.rq",// queryFileURL + "construct-1.trig",// dataFileURL + "construct-1-result.trig"// resultFileURL + ).runTest(); + + final ConstructNode construct = ast.getOptimizedAST().getConstruct(); + + assertNotNull(construct); + + assertTrue(construct.isNativeDistinct()); + + } + + /** + * A simple CONSTRUCT query using a native DISTINCT filter (enabled + * via the "analytic" query hint). + * + * <pre> + * PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> + * PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> + * PREFIX foaf: <http://xmlns.com/foaf/0.1/> + * + * CONSTRUCT { + * <http://www.bigdata.com/DC> rdfs:label "DC" . + * ?x rdf:type foaf:Person . + * } where { + * # Enable the native DISTINCT SPO filter. + * hint:Query hint:analytic true . + * ?x rdf:type foaf:Person + * } + * </pre> + */ + public void test_construct_1b() throws Exception { + + final ASTContainer ast = new TestHelper( + "construct-1", // testURI, + "construct-1b.rq",// queryFileURL + "construct-1.trig",// dataFileURL + "construct-1-result.trig"// resultFileURL + ).runTest(); + + final ConstructNode construct = ast.getOptimizedAST().getConstruct(); + + assertNotNull(construct); + + assertTrue(construct.isNativeDistinct()); + + } + + /** * A CONSTRUCT without a template and having a ground triple in the WHERE * clause. For this variant of the test, the triple is not in the KB. * Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/construct-1a.rq =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/construct-1a.rq (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/construct-1a.rq 2012-07-20 21:21:08 UTC (rev 6385) @@ -0,0 +1,12 @@ +PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> +PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> +PREFIX foaf: <http://xmlns.com/foaf/0.1/> + +CONSTRUCT { + <http://www.bigdata.com/DC> rdfs:label "DC" . + ?x rdf:type foaf:Person . +} where { + # Enable the native DISTINCT SPO filter. + hint:Query hint:nativeDistinctSPO true . + ?x rdf:type foaf:Person +} \ No newline at end of file Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/construct-1b.rq =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/construct-1b.rq (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/construct-1b.rq 2012-07-20 21:21:08 UTC (rev 6385) @@ -0,0 +1,12 @@ +PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> +PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> +PREFIX foaf: <http://xmlns.com/foaf/0.1/> + +CONSTRUCT { + <http://www.bigdata.com/DC> rdfs:label "DC" . + ?x rdf:type foaf:Person . +} where { + # Enable the native DISTINCT SPO filter. + hint:Query hint:nativeDistinctSPO true . + ?x rdf:type foaf:Person +} \ No newline at end of file Modified: branches/BIGDATA_RELEASE_1_2_0/ctc-striterators/src/java/cutthecrap/utils/striterators/IFilter.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/ctc-striterators/src/java/cutthecrap/utils/striterators/IFilter.java 2012-07-18 13:48:50 UTC (rev 6384) +++ branches/BIGDATA_RELEASE_1_2_0/ctc-striterators/src/java/cutthecrap/utils/striterators/IFilter.java 2012-07-20 21:21:08 UTC (rev 6385) @@ -29,8 +29,17 @@ import java.util.Iterator; import java.io.Serializable; +import com.bigdata.striterator.ICloseableIterator; + /** * Provides the hook interface that allows use by Striterators + * + * TODO The {@link Striterator} protocol does not support a close() method for + * {@link Filter}s. That method should be invoked by an + * {@link ICloseableIterator}. + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/582"> + * IStriterator does not support close() protocol for Ifilter </a> */ public interface IFilter extends Serializable, IPropertySet { /** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2012-07-23 20:18:42
|
Revision: 6388 http://bigdata.svn.sourceforge.net/bigdata/?rev=6388&view=rev Author: thompsonbry Date: 2012-07-23 20:18:34 +0000 (Mon, 23 Jul 2012) Log Message: ----------- It also reports the #of triples in the default graph (note that the default graph is the RDF Merge of the named graphs, so it is a summary of the entire KB instance). I've found some bugs in the current (1.2.1) ServiceDescription?, notably having to do with not using blank nodes to model the service and the nested dataset, defaultGraph, etc. I've added a VoidVocabularyClass which is now used by RDFSVocabulary2. I've extended the ServiceDescription to report the vocabularies which are in use in the default graph and the predicate partition and class partition statistics. Those statistics are computed efficiently using a distinct term scan / advancer pattern. There was a bug in the distinct multi-term scanner code where it failed to specify the elementClass for the chunked iterator. I have removed the old predicateUsage() method on AbstractTripleStore. You can now use the ServiceDescription instead and get more information in a standards oriented manner. index.html now contains a link to the ServiceDescription. Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPORelation.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/store/AbstractTripleStore.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/vocab/RDFSVocabulary.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/rio/AbstractRIOTestCase.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/QueryServlet.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/SD.java branches/BIGDATA_RELEASE_1_2_0/bigdata-war/src/html/index.html Added Paths: ----------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/vocab/RDFSVocabularyV2.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/vocab/decls/VoidVocabularyDecl.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPORelation.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPORelation.java 2012-07-21 18:37:51 UTC (rev 6387) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPORelation.java 2012-07-23 20:18:34 UTC (rev 6388) @@ -1733,7 +1733,10 @@ }); - return new ChunkedWrappedIterator<IV>(itr); + return new ChunkedWrappedIterator<IV>(itr,// + ChunkedWrappedIterator.DEFAULT_CHUNK_SIZE,// chunkSize + IV.class// elementClass + ); } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/store/AbstractTripleStore.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/store/AbstractTripleStore.java 2012-07-21 18:37:51 UTC (rev 6387) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/store/AbstractTripleStore.java 2012-07-23 20:18:34 UTC (rev 6388) @@ -3165,72 +3165,75 @@ } - final public StringBuilder predicateUsage() { +// final public StringBuilder predicateUsage() { +// +// return predicateUsage(this); +// +// } +// +// /** +// * Dumps the #of statements using each predicate in the kb (tab delimited, +// * unordered). +// * +// * @param resolveTerms +// * Used to resolve term identifiers to terms (you can use this to +// * dump a {@link TempTripleStore} that is using the term +// * dictionary of the main database). +// * +// * @see SD, which can now compute and report both the predicate partition +// * usage and the class partition usage. +// */ +// final public StringBuilder predicateUsage( +// final AbstractTripleStore resolveTerms) { +// +// if (getSPORelation().oneAccessPath) { +// +// // The necessary index (POS or POCS) does not exist. +// throw new UnsupportedOperationException(); +// +// } +// +// // visit distinct term identifiers for the predicate position. +// final IChunkedIterator<IV> itr = getSPORelation().distinctTermScan( +// quads ? SPOKeyOrder.POCS : SPOKeyOrder.POS); +// +// // resolve term identifiers to terms efficiently during iteration. +// final BigdataValueIterator itr2 = new BigdataValueIteratorImpl( +// resolveTerms, itr); +// +// try { +// +// final StringBuilder sb = new StringBuilder(); +// +// while (itr2.hasNext()) { +// +// final BigdataValue term = itr2.next(); +// +// final IV p = term.getIV(); +// +// final long n = getSPORelation().getAccessPath(null, p, null, +// null).rangeCount(false/* exact */); +// +// /* +// * FIXME do efficient term resolution for scale-out. This will +// * require an expander pattern where we feed one iterator into +// * another and both are chunked. +// */ +// sb.append(n + "\t" + resolveTerms.toString(p) + "\n"); +// +// } +// +// return sb; +// +// } finally { +// +// itr2.close(); +// +// } +// +// } - return predicateUsage(this); - - } - /** - * Dumps the #of statements using each predicate in the kb (tab delimited, - * unordered). - * - * @param resolveTerms - * Used to resolve term identifiers to terms (you can use this to - * dump a {@link TempTripleStore} that is using the term - * dictionary of the main database). - */ - final public StringBuilder predicateUsage( - final AbstractTripleStore resolveTerms) { - - if (getSPORelation().oneAccessPath) { - - // The necessary index (POS or POCS) does not exist. - throw new UnsupportedOperationException(); - - } - - // visit distinct term identifiers for the predicate position. - final IChunkedIterator<IV> itr = getSPORelation().distinctTermScan( - quads ? SPOKeyOrder.POCS : SPOKeyOrder.POS); - - // resolve term identifiers to terms efficiently during iteration. - final BigdataValueIterator itr2 = new BigdataValueIteratorImpl( - resolveTerms, itr); - - try { - - final StringBuilder sb = new StringBuilder(); - - while (itr2.hasNext()) { - - final BigdataValue term = itr2.next(); - - final IV p = term.getIV(); - - final long n = getSPORelation().getAccessPath(null, p, null, - null).rangeCount(false/* exact */); - - /* - * FIXME do efficient term resolution for scale-out. This will - * require an expander pattern where we feed one iterator into - * another and both are chunked. - */ - sb.append(n + "\t" + resolveTerms.toString(p) + "\n"); - - } - - return sb; - - } finally { - - itr2.close(); - - } - - } - - /** * Utility method dumps the statements in the store using the SPO index * (subject order). */ Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/vocab/RDFSVocabulary.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/vocab/RDFSVocabulary.java 2012-07-21 18:37:51 UTC (rev 6387) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/vocab/RDFSVocabulary.java 2012-07-23 20:18:34 UTC (rev 6388) @@ -27,6 +27,7 @@ package com.bigdata.rdf.vocab; +import org.openrdf.Sesame; import org.openrdf.model.Value; import org.openrdf.model.vocabulary.OWL; import org.openrdf.model.vocabulary.RDF; @@ -41,6 +42,7 @@ import com.bigdata.rdf.vocab.decls.RDFVocabularyDecl; import com.bigdata.rdf.vocab.decls.SKOSVocabularyDecl; import com.bigdata.rdf.vocab.decls.SesameVocabularyDecl; +import com.bigdata.rdf.vocab.decls.VoidVocabularyDecl; import com.bigdata.rdf.vocab.decls.XMLSchemaVocabularyDecl; /** Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/vocab/RDFSVocabularyV2.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/vocab/RDFSVocabularyV2.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/vocab/RDFSVocabularyV2.java 2012-07-23 20:18:34 UTC (rev 6388) @@ -0,0 +1,72 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2007. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 Oct 28, 2007 + */ + +package com.bigdata.rdf.vocab; + +import com.bigdata.rdf.store.AbstractTripleStore; +import com.bigdata.rdf.vocab.decls.RDFVocabularyDecl; +import com.bigdata.rdf.vocab.decls.VoidVocabularyDecl; + +/** + * Extended vocabulary to include {@link VoidVocabularyDecl}. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + * @version $Id: RDFSVocabulary.java 4632 2011-06-06 15:11:53Z thompsonbry $ + */ +public class RDFSVocabularyV2 extends RDFSVocabulary { + + /** + * De-serialization ctor. + */ + public RDFSVocabularyV2() { + + super(); + + } + + /** + * Used by {@link AbstractTripleStore#create()}. + * + * @param namespace + * The namespace of the KB instance. + */ + public RDFSVocabularyV2(final String namespace) { + + super( namespace ); + + } + + @Override + protected void addValues() { + + super.addValues(); + + addDecl(new RDFVocabularyDecl()); + + } + +} Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/vocab/decls/VoidVocabularyDecl.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/vocab/decls/VoidVocabularyDecl.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/vocab/decls/VoidVocabularyDecl.java 2012-07-23 20:18:34 UTC (rev 6388) @@ -0,0 +1,118 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2011. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 Jul 23, 2012 + */ + +package com.bigdata.rdf.vocab.decls; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; + +import org.openrdf.model.URI; +import org.openrdf.model.impl.URIImpl; + +import com.bigdata.rdf.vocab.VocabularyDecl; + +/** + * Vocabulary and namespace for VOID. + * + * @see <a href="http://www.w3.org/TR/void/"> Describing Linked Datasets with + * the VoiD Vocabulary </a> + * @see <a href="http://vocab.deri.ie/void/"> Vocabulary of Interlinked Datasets + * (VoID) </a> + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + * @version $Id: RDFVocabularyDecl.java 4631 2011-06-06 15:06:48Z thompsonbry $ + */ +public class VoidVocabularyDecl implements VocabularyDecl { + + public static final String NAMESPACE = "http://rdfs.org/ns/void#"; + + // Classes. + public static final URI // + Dataset = new URIImpl(NAMESPACE + "Dataset"),// + DatasetDescription = new URIImpl(NAMESPACE + "DatasetDescription"),// + Linkset = new URIImpl(NAMESPACE + "Linkset"),// + TechnicalFeature = new URIImpl(NAMESPACE + "TechnicalFeature")// + ; + + // Properties. + public static final URI // + class_ = new URIImpl(NAMESPACE+"class"),// + classPartition = new URIImpl(NAMESPACE+"classPartition"),// + classes = new URIImpl(NAMESPACE+"classes"),// + dataDump = new URIImpl(NAMESPACE+"dataDump"),// + distinctObjects = new URIImpl(NAMESPACE+"distinctObjects"),// + distinctSubjects = new URIImpl(NAMESPACE+"distinctSubjects"),// + documents = new URIImpl(NAMESPACE+"documents"),// + entities = new URIImpl(NAMESPACE+"entities"),// + exampleResource = new URIImpl(NAMESPACE+"exampleResource"),// + feature = new URIImpl(NAMESPACE+"feature"),// + inDataset = new URIImpl(NAMESPACE+"inDataset"),// + linkPredicate = new URIImpl(NAMESPACE+"linkPredicate"),// + objectsTarget = new URIImpl(NAMESPACE+"objectsTarget"),// + openSearchDescription = new URIImpl(NAMESPACE+"openSearchDescription"),// + properties = new URIImpl(NAMESPACE+"properties"),// + property = new URIImpl(NAMESPACE+"property"),// + propertyPartition = new URIImpl(NAMESPACE+"propertyPartition"),// + rootResource = new URIImpl(NAMESPACE+"rootResource"),// + sparqlEndpoint = new URIImpl(NAMESPACE+"sparqlEndpoint"),// + subjectsTarget = new URIImpl(NAMESPACE+"subjectsTarget"),// + subset = new URIImpl(NAMESPACE+"subset"),// + target = new URIImpl(NAMESPACE+"target"),// + triples = new URIImpl(NAMESPACE+"triples"),// + uriLookupEndpoint = new URIImpl(NAMESPACE+"uriLookupEndpoint"),// + uriRegexPattern = new URIImpl(NAMESPACE+"uriRegexPattern"),// + uriSpace = new URIImpl(NAMESPACE+"uriSpace"),// + vocabulary = new URIImpl(NAMESPACE+"vocabulary")// + ; + + static private final URI[] uris = new URI[]{ + new URIImpl(NAMESPACE), + // classes + Dataset, + DatasetDescription, + Linkset, + TechnicalFeature, + // properties + class_, classPartition, classes, dataDump, distinctObjects, + distinctSubjects, documents, entities, exampleResource, feature, + inDataset, linkPredicate, objectsTarget, openSearchDescription, + properties, property, propertyPartition, rootResource, + sparqlEndpoint, subjectsTarget, subset, target, triples, + uriLookupEndpoint, uriRegexPattern, uriSpace, vocabulary// + }; + + public VoidVocabularyDecl() { + } + + public Iterator<URI> values() { + + return Collections.unmodifiableList(Arrays.asList(uris)).iterator(); + + } + +} Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/rio/AbstractRIOTestCase.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/rio/AbstractRIOTestCase.java 2012-07-21 18:37:51 UTC (rev 6387) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/rio/AbstractRIOTestCase.java 2012-07-23 20:18:34 UTC (rev 6388) @@ -641,7 +641,7 @@ if (log.isInfoEnabled()) { log.info("computing predicate usage..."); - log.info("\n" + store.predicateUsage()); +// log.info("\n" + store.predicateUsage()); } /* Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/QueryServlet.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/QueryServlet.java 2012-07-21 18:37:51 UTC (rev 6387) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/QueryServlet.java 2012-07-23 20:18:34 UTC (rev 6388) @@ -175,31 +175,26 @@ buildResponse(resp, HTTP_NOTFOUND, MIME_TEXT_PLAIN); return; } - - final Graph g = SD.describeService(tripleStore); - + /* - * Add the service end point. - * - * TODO Report alternative end points? + * Figure out the service end point. */ + final String serviceURI; { final StringBuffer sb = req.getRequestURL(); final int indexOf = sb.indexOf("?"); - final String serviceURI; if (indexOf == -1) { serviceURI = sb.toString(); } else { serviceURI = sb.substring(0, indexOf); } - g.add(SD.Service, SD.endpoint, - g.getValueFactory().createURI(serviceURI)); - } + final Graph g = SD.describeService(tripleStore, serviceURI); + /* * CONNEG for the MIME type. * Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/SD.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/SD.java 2012-07-21 18:37:51 UTC (rev 6387) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/SD.java 2012-07-23 20:18:34 UTC (rev 6388) @@ -27,16 +27,34 @@ package com.bigdata.rdf.sail.webapp; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import org.openrdf.model.BNode; import org.openrdf.model.Graph; import org.openrdf.model.URI; +import org.openrdf.model.ValueFactory; import org.openrdf.model.impl.GraphImpl; import org.openrdf.model.impl.URIImpl; +import org.openrdf.model.vocabulary.RDF; import com.bigdata.rdf.axioms.Axioms; import com.bigdata.rdf.axioms.NoAxioms; import com.bigdata.rdf.axioms.OwlAxioms; import com.bigdata.rdf.axioms.RdfsAxioms; +import com.bigdata.rdf.internal.IV; +import com.bigdata.rdf.internal.NotMaterializedException; +import com.bigdata.rdf.model.BigdataURI; +import com.bigdata.rdf.model.BigdataValue; +import com.bigdata.rdf.spo.SPOKeyOrder; import com.bigdata.rdf.store.AbstractTripleStore; +import com.bigdata.rdf.store.BigdataValueIterator; +import com.bigdata.rdf.store.BigdataValueIteratorImpl; +import com.bigdata.rdf.vocab.decls.VoidVocabularyDecl; +import com.bigdata.striterator.IChunkedIterator; /** * SPARQL 1.1 Service Description vocabulary class. @@ -321,20 +339,35 @@ /** * Collect various information, building up a service description graph. * - * TODO I am disinclined to enumerate all named and default graphs when - * there is a GET against the SPARQL end point. That can be WAY too much - * information. + * @param tripleStore + * The KB instance to be described. + * @param serviceURIs + * One or more service end points for that KB instance. */ - public static Graph describeService(final AbstractTripleStore tripleStore) { + public static Graph describeService(final AbstractTripleStore tripleStore, + final String serviceURI) { final Graph g = new GraphImpl(); + final ValueFactory f = g.getValueFactory(); + + final BNode service = f.createBNode("service"); + + final BNode defaultDataset = f.createBNode("defaultDataset"); + + final BNode defaultGraph = f.createBNode("defaultGraph"); + + g.add(service, RDF.TYPE, SD.Service); + + // Service end point. + g.add(service, SD.endpoint, g.getValueFactory().createURI(serviceURI)); + /* * Supported Query Languages */ - g.add(SD.Service, SD.supportedLanguage, SD.SPARQL10Query); - g.add(SD.Service, SD.supportedLanguage, SD.SPARQL11Query); - g.add(SD.Service, SD.supportedLanguage, SD.SPARQL11Update); + g.add(service, SD.supportedLanguage, SD.SPARQL10Query); + g.add(service, SD.supportedLanguage, SD.SPARQL11Query); + g.add(service, SD.supportedLanguage, SD.SPARQL11Update); /* * RDF and SPARQL Formats. @@ -342,46 +375,46 @@ * @see http://www.openrdf.org/issues/browse/RIO-79 (Request for unique * URIs) * - * TODO Add an explict declation for SIDS mode data interchange? + * TODO Add an explicit declaration for SIDS mode data interchange? */ // InputFormats { - g.add(SD.Service, SD.inputFormat, SD.RDFXML); - g.add(SD.Service, SD.inputFormat, SD.NTRIPLES); - g.add(SD.Service, SD.inputFormat, SD.TURTLE); - g.add(SD.Service, SD.inputFormat, SD.N3); - // g.add(SD.Service, SD.inputFormat, SD.TRIX); // TODO TRIX - g.add(SD.Service, SD.inputFormat, SD.TRIG); - // g.add(SD.Service, SD.inputFormat, SD.BINARY); // TODO BINARY - g.add(SD.Service, SD.inputFormat, SD.NQUADS); + g.add(service, SD.inputFormat, SD.RDFXML); + g.add(service, SD.inputFormat, SD.NTRIPLES); + g.add(service, SD.inputFormat, SD.TURTLE); + g.add(service, SD.inputFormat, SD.N3); + // g.add(service, SD.inputFormat, SD.TRIX); // TODO TRIX + g.add(service, SD.inputFormat, SD.TRIG); + // g.add(service, SD.inputFormat, SD.BINARY); // TODO BINARY + g.add(service, SD.inputFormat, SD.NQUADS); - g.add(SD.Service, SD.inputFormat, SD.SPARQL_RESULTS_XML); - g.add(SD.Service, SD.inputFormat, SD.SPARQL_RESULTS_JSON); - g.add(SD.Service, SD.inputFormat, SD.SPARQL_RESULTS_CSV); - g.add(SD.Service, SD.inputFormat, SD.SPARQL_RESULTS_TSV); - // g.add(SD.Service, SD.inputFormat, + g.add(service, SD.inputFormat, SD.SPARQL_RESULTS_XML); + g.add(service, SD.inputFormat, SD.SPARQL_RESULTS_JSON); + g.add(service, SD.inputFormat, SD.SPARQL_RESULTS_CSV); + g.add(service, SD.inputFormat, SD.SPARQL_RESULTS_TSV); + // g.add(service, SD.inputFormat, // SD.SPARQL_RESULTS_OPENRDF_BINARY); } // ResultFormats { - g.add(SD.Service, SD.resultFormat, SD.RDFXML); - g.add(SD.Service, SD.resultFormat, SD.NTRIPLES); - g.add(SD.Service, SD.resultFormat, SD.TURTLE); - g.add(SD.Service, SD.resultFormat, SD.N3); - // g.add(SD.Service, SD.resultFormat, SD.TRIX); // TODO TRIX - g.add(SD.Service, SD.resultFormat, SD.TRIG); - // g.add(SD.Service, SD.resultFormat, SD.BINARY); // TODO BINARY - // g.add(SD.Service, SD.resultFormat, SD.NQUADS); // TODO NQuads + g.add(service, SD.resultFormat, SD.RDFXML); + g.add(service, SD.resultFormat, SD.NTRIPLES); + g.add(service, SD.resultFormat, SD.TURTLE); + g.add(service, SD.resultFormat, SD.N3); + // g.add(service, SD.resultFormat, SD.TRIX); // TODO TRIX + g.add(service, SD.resultFormat, SD.TRIG); + // g.add(service, SD.resultFormat, SD.BINARY); // TODO BINARY + // g.add(service, SD.resultFormat, SD.NQUADS); // TODO NQuads // writer - g.add(SD.Service, SD.resultFormat, SD.SPARQL_RESULTS_XML); - g.add(SD.Service, SD.resultFormat, SD.SPARQL_RESULTS_JSON); - g.add(SD.Service, SD.resultFormat, SD.SPARQL_RESULTS_CSV); - g.add(SD.Service, SD.resultFormat, SD.SPARQL_RESULTS_TSV); - // g.add(SD.Service, SD.resultFormat, + g.add(service, SD.resultFormat, SD.SPARQL_RESULTS_XML); + g.add(service, SD.resultFormat, SD.SPARQL_RESULTS_JSON); + g.add(service, SD.resultFormat, SD.SPARQL_RESULTS_CSV); + g.add(service, SD.resultFormat, SD.SPARQL_RESULTS_TSV); + // g.add(service, SD.resultFormat, // SD.SPARQL_RESULTS_OPENRDF_BINARY); } @@ -397,7 +430,7 @@ if (tripleStore.isQuads()) { - g.add(SD.Service, SD.feature, SD.UnionDefaultGraph); + g.add(service, SD.feature, SD.UnionDefaultGraph); } else { @@ -418,13 +451,421 @@ entailmentRegime = null; } if (entailmentRegime != null) - g.add(SD.Service, SD.entailmentRegime, entailmentRegime); + g.add(service, SD.entailmentRegime, entailmentRegime); } - g.add(SD.Service, SD.feature, SD.BasicFederatedQuery); + // Other features. + g.add(service, SD.feature, SD.BasicFederatedQuery); + /* + * Information about the defaultGraph. + * + * TODO This could all be generalized and then run for each known named + * graph as well. + */ + { + + // Default data set + g.add(service, SD.defaultDataset, defaultDataset); + + g.add(defaultDataset, RDF.TYPE, SD.Dataset); + + // any URI is considered to be an entity. + g.add(defaultDataset, VoidVocabularyDecl.uriRegexPattern, + f.createLiteral("^.*")); + + // Default graph in the default data set. + g.add(defaultDataset, SD.defaultGraph, defaultGraph); + + // defautGraph description. + { + + // #of triples in the default graph + g.add(defaultGraph, VoidVocabularyDecl.triples, + f.createLiteral(tripleStore.getStatementCount())); + + // #of entities in the default graph. + g.add(defaultGraph, VoidVocabularyDecl.entities, + f.createLiteral(tripleStore.getURICount())); + + // The distinct vocabularies in use. + final Set<String> namespaces = new LinkedHashSet<String>(); + + /* + * property partition statistics & used vocabularies. + * + * Note: A temporary graph is used to hold these data so we can + * first output the vocabulary summary. This gives the output a + * neater (and more human consumable) appearance. + */ + final Graph propertyPartitions = new GraphImpl(); + + // Frequency count of the predicates in the default graph. + final IVCount[] predicatePartitionCounts = predicateUsage(tripleStore); + + // Frequency count of the classes in the default graph. + final IVCount[] classPartitionCounts = classUsage(tripleStore); + + { + + // property partitions. + for (IVCount tmp : predicatePartitionCounts) { + + final BNode propertyPartition = f.createBNode(); + + final URI p = (URI) tmp.getValue(); + + propertyPartitions.add(defaultGraph, + VoidVocabularyDecl.propertyPartition, + propertyPartition); + + propertyPartitions.add(propertyPartition, + VoidVocabularyDecl.property, p); + + propertyPartitions.add(propertyPartition, + VoidVocabularyDecl.triples, + f.createLiteral(tmp.count)); + + String namespace = p.getNamespace(); + + if (namespace.endsWith("#")) { + + // Strip trailing '#' per VoID specification. + namespace = namespace.substring(0, + namespace.length() - 1); + + } + + namespaces.add(namespace); + + } + + } + + // emit the in use vocabularies. + for (String namespace : namespaces) { + + g.add(defaultDataset, VoidVocabularyDecl.vocabulary, + f.createURI(namespace)); + + } + + // #of distinct predicates in the default graph. + g.add(defaultGraph, VoidVocabularyDecl.properties, + f.createLiteral(predicatePartitionCounts.length)); + + // #of distinct classes in the default graph. + g.add(defaultGraph, VoidVocabularyDecl.classes, + f.createLiteral(classPartitionCounts.length)); + + // now emit the property partition statistics. + g.addAll(propertyPartitions); + + // class partition statistics. + { + + // per class partition statistics. + for (IVCount tmp : classPartitionCounts) { + + final BNode classPartition = f.createBNode(); + + final BigdataValue cls = tmp.getValue(); + + g.add(defaultGraph, VoidVocabularyDecl.classPartition, + classPartition); + + g.add(classPartition, VoidVocabularyDecl.class_, cls); + + g.add(classPartition, VoidVocabularyDecl.triples, + f.createLiteral(tmp.count)); + + } + + } // end class partition statistics. + + } // end defaultGraph + +// sb.append("termCount\t = " + tripleStore.getTermCount() + "\n"); +// +// sb.append("uriCount\t = " + tripleStore.getURICount() + "\n"); +// +// sb.append("literalCount\t = " + tripleStore.getLiteralCount() + "\n"); +// +// /* +// * Note: The blank node count is only available when using the told +// * bnodes mode. +// */ +// sb +// .append("bnodeCount\t = " +// + (tripleStore.getLexiconRelation() +// .isStoreBlankNodes() ? "" +// + tripleStore.getBNodeCount() : "N/A") +// + "\n"); + + } + return g; + } + /** + * An {@link IV} and a counter for that {@link IV}. + */ + private static class IVCount implements Comparable<IVCount> { + + public final IV<?,?> iv; + + public final long count; + + private BigdataValue val; + + /** + * Return the associated {@link BigdataValue}. + * <p> + * Note: A resolution set is necessary if you want to attach the + * {@link BigdataValue} to the {@link IV}. + * + * @throws NotMaterializedException + */ + public BigdataValue getValue() { + + if(val == null) + throw new NotMaterializedException(iv.toString()); + + return val; + + } + + public void setValue(final BigdataValue val) { + + if (val == null) + throw new IllegalArgumentException(); + + if (this.val != null && !this.val.equals(val)) + throw new IllegalArgumentException(); + + this.val = val; + + } + + public IVCount(final IV<?,?> iv, final long count) { + + if (iv == null) + throw new IllegalArgumentException(); + + this.iv = iv; + + this.count = count; + + } + + /** + * Place into order by descending count. + */ + @Override + public int compareTo(IVCount arg0) { + + if (count < arg0.count) + return 1; + + if (count > arg0.count) + return -1; + + return 0; + + } + + } + + /** + * Return an array of the distinct predicates in the KB ordered by their + * descending frequency of use. The {@link IV}s in the returned array will + * have been resolved to the corresponding {@link BigdataURI}s which can be + * accessed using {@link IV#getValue()}. + */ + private static IVCount[] predicateUsage(final AbstractTripleStore kb) { + + if (kb.getSPORelation().oneAccessPath) { + + // The necessary index (POS or POCS) does not exist. + throw new UnsupportedOperationException(); + + } + + final boolean quads = kb.isQuads(); + + // visit distinct term identifiers for the predicate position. + @SuppressWarnings("rawtypes") + final IChunkedIterator<IV> itr = kb.getSPORelation().distinctTermScan( + quads ? SPOKeyOrder.POCS : SPOKeyOrder.POS); + + // resolve term identifiers to terms efficiently during iteration. + final BigdataValueIterator itr2 = new BigdataValueIteratorImpl( + kb/* resolveTerms */, itr); + + try { + + final Set<IV<?,?>> ivs = new LinkedHashSet<IV<?,?>>(); + + final Map<IV<?, ?>, IVCount> counts = new LinkedHashMap<IV<?, ?>, IVCount>(); + + while (itr2.hasNext()) { + + final BigdataValue term = itr2.next(); + + final IV<?,?> iv = term.getIV(); + + final long n = kb.getSPORelation() + .getAccessPath(null, iv, null, null) + .rangeCount(false/* exact */); + + ivs.add(iv); + + counts.put(iv, new IVCount(iv, n)); + + } + + // Batch resolve IVs to Values + final Map<IV<?, ?>, BigdataValue> x = kb.getLexiconRelation() + .getTerms(ivs); + + for (Map.Entry<IV<?, ?>, BigdataValue> e : x.entrySet()) { + + final IVCount count = counts.get(e.getKey()); + + count.setValue(e.getValue()); + + } + + final IVCount[] a = counts.values().toArray( + new IVCount[counts.size()]); + + // Order by descending count. + Arrays.sort(a); + + return a; + + } finally { + + itr2.close(); + + } + + } + + /** + * Return an efficient statistical summary for the class partitions. The + * SPARQL query for this is + * + * <pre> + * SELECT ?class (COUNT(?s) AS ?count ) { ?s a ?class } GROUP BY ?class ORDER BY ?count + * </pre> + * + * However, it is much efficient to scan POS for + * + * <pre> + * rdf:type ?o ?s + * </pre> + * + * and report the range count of + * + * <pre> + * rdf:type ?o ?s + * </pre> + * + * for each distinct value of <code>?o</code>. + * + * @param kb + * The KB instance. + * + * @return The class usage statistics. + */ + private static IVCount[] classUsage(final AbstractTripleStore kb) { + + if (kb.getSPORelation().oneAccessPath) { + + // The necessary index (POS or POCS) does not exist. + throw new UnsupportedOperationException(); + + } + + final boolean quads = kb.isQuads(); + + final SPOKeyOrder keyOrder = quads ? SPOKeyOrder.POCS : SPOKeyOrder.POS; + + // Resolve IV for rdf:type + final BigdataURI rdfType = kb.getValueFactory().asValue(RDF.TYPE); + + kb.getLexiconRelation().addTerms(new BigdataValue[] { rdfType }, + 1/* numTerms */, true/* readOnly */); + + if (rdfType.getIV() == null) { + + // No rdf:type assertions since rdf:type is unknown term. + return new IVCount[0]; + + } + + // visit distinct term identifiers for the rdf:type predicate. + @SuppressWarnings("rawtypes") + final IChunkedIterator<IV> itr = kb + .getSPORelation() + .distinctMultiTermScan(keyOrder, new IV[] { rdfType.getIV() }/* knownTerms */); + + // resolve term identifiers to terms efficiently during iteration. + final BigdataValueIterator itr2 = new BigdataValueIteratorImpl( + kb/* resolveTerms */, itr); + + try { + + final Set<IV<?,?>> ivs = new LinkedHashSet<IV<?,?>>(); + + final Map<IV<?, ?>, IVCount> counts = new LinkedHashMap<IV<?, ?>, IVCount>(); + + while (itr2.hasNext()) { + + final BigdataValue term = itr2.next(); + + final IV<?,?> iv = term.getIV(); + + final long n = kb + .getSPORelation() + .getAccessPath(null, rdfType.getIV()/* p */, iv/* o */, + null).rangeCount(false/* exact */); + + ivs.add(iv); + + counts.put(iv, new IVCount(iv, n)); + + } + + // Batch resolve IVs to Values + final Map<IV<?, ?>, BigdataValue> x = kb.getLexiconRelation() + .getTerms(ivs); + + for (Map.Entry<IV<?, ?>, BigdataValue> e : x.entrySet()) { + + final IVCount count = counts.get(e.getKey()); + + count.setValue(e.getValue()); + + } + + final IVCount[] a = counts.values().toArray( + new IVCount[counts.size()]); + + // Order by descending count. + Arrays.sort(a); + + return a; + + } finally { + + itr2.close(); + + } + + } + } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-war/src/html/index.html =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-war/src/html/index.html 2012-07-21 18:37:51 UTC (rev 6387) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-war/src/html/index.html 2012-07-23 20:18:34 UTC (rev 6388) @@ -21,7 +21,7 @@ <dt>http://hostname:port/bigdata</dt> <dd>This page.</dd> <dt>http://hostname:port/bigdata/sparql</dt> -<dd>The SPARQL REST API.</dd> +<dd>The SPARQL REST API (<a href="sparql">Service Description</a>).</dd> <dt>http://hostname:port/bigdata/status</dt> <dd>A <a href="status">status</a> page.</dd> <dt>http://hostname:port/bigdata/counters</dt> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2012-07-24 14:05:11
|
Revision: 6390 http://bigdata.svn.sourceforge.net/bigdata/?rev=6390&view=rev Author: thompsonbry Date: 2012-07-24 14:04:39 +0000 (Tue, 24 Jul 2012) Log Message: ----------- I've extended the VoID support to include the description of each named graph. This behavior can be disabled using the webapp configuration parameters but defaults to true. I have relayered the service description into a set of protected methods and added a constructor. This should make it easier to extend the base behavior. I've also added some reporting for interesting bigdata features. Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/lexicon/LexiconRelation.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServletContextListener.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataServlet.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/ConfigParams.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/QueryServlet.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/SD.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/SparqlEndpointConfig.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/lexicon/LexiconRelation.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/lexicon/LexiconRelation.java 2012-07-24 00:33:16 UTC (rev 6389) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/lexicon/LexiconRelation.java 2012-07-24 14:04:39 UTC (rev 6390) @@ -890,7 +890,7 @@ } /** - * <code>true</code> iff the full text index is enabled. + * <code>true</code> iff the (value centric) full text index is enabled. * * @see AbstractTripleStore.Options#TEXT_INDEX */ Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServletContextListener.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServletContextListener.java 2012-07-24 00:33:16 UTC (rev 6389) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServletContextListener.java 2012-07-24 14:04:39 UTC (rev 6390) @@ -286,8 +286,23 @@ } + final boolean describeEachNamedGraph; + { + + final String s = context + .getInitParameter(ConfigParams.DESCRIBE_EACH_NAMED_GRAPH); + + describeEachNamedGraph = s == null ? ConfigParams.DEFAULT_DESCRIBE_EACH_NAMED_GRAPH + : Boolean.valueOf(s); + + if (log.isInfoEnabled()) + log.info(ConfigParams.DESCRIBE_EACH_NAMED_GRAPH + "=" + + describeEachNamedGraph); + + } + final SparqlEndpointConfig config = new SparqlEndpointConfig(namespace, - timestamp, queryThreadPoolSize); + timestamp, queryThreadPoolSize, describeEachNamedGraph); rdfContext = new BigdataRDFContext(config, indexManager); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataServlet.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataServlet.java 2012-07-24 00:33:16 UTC (rev 6389) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataServlet.java 2012-07-24 14:04:39 UTC (rev 6390) @@ -32,6 +32,7 @@ import javax.servlet.ServletContext; import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; @@ -248,4 +249,25 @@ } + /** + * Figure out and return the service end point. + */ + protected String getServiceURI(final HttpServletRequest req) { + + final String serviceURI; + + final StringBuffer sb = req.getRequestURL(); + + final int indexOf = sb.indexOf("?"); + + if (indexOf == -1) { + serviceURI = sb.toString(); + } else { + serviceURI = sb.substring(0, indexOf); + } + + return serviceURI; + + } + } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/ConfigParams.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/ConfigParams.java 2012-07-24 00:33:16 UTC (rev 6389) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/ConfigParams.java 2012-07-24 14:04:39 UTC (rev 6390) @@ -80,4 +80,15 @@ */ String READ_LOCK = "read-lock"; + /** + * When <code>true</code> and the KB instance is in the <code>quads</code> + * mode, each named graph will also be described in in the same level of + * detail as the default graph (default + * {@value #DEFAULT_DESCRIBE_EACH_NAMED_GRAPH}). Otherwise only the default + * graph will be described. + */ + String DESCRIBE_EACH_NAMED_GRAPH = "describe-each-named-graph"; + + boolean DEFAULT_DESCRIBE_EACH_NAMED_GRAPH = true; + } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/QueryServlet.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/QueryServlet.java 2012-07-24 00:33:16 UTC (rev 6389) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/QueryServlet.java 2012-07-24 14:04:39 UTC (rev 6390) @@ -28,7 +28,6 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; -import java.nio.charset.Charset; import java.util.Iterator; import java.util.Map; import java.util.TreeMap; @@ -48,6 +47,7 @@ import org.openrdf.model.Statement; import org.openrdf.model.URI; import org.openrdf.model.Value; +import org.openrdf.model.impl.GraphImpl; import org.openrdf.query.MalformedQueryException; import org.openrdf.rio.RDFFormat; import org.openrdf.rio.RDFHandlerException; @@ -175,25 +175,22 @@ buildResponse(resp, HTTP_NOTFOUND, MIME_TEXT_PLAIN); return; } + + // Figure out the service end point. + final String serviceURI = getServiceURI(req); /* - * Figure out the service end point. + * TODO Resolve the SD class name and ctor via a configuration property + * for extensible descriptions. */ - final String serviceURI; + final Graph g = new GraphImpl(); { - final StringBuffer sb = req.getRequestURL(); - final int indexOf = sb.indexOf("?"); + final SD sd = new SD(g, tripleStore, serviceURI); - if (indexOf == -1) { - serviceURI = sb.toString(); - } else { - serviceURI = sb.substring(0, indexOf); - } + sd.describeService(getBigdataRDFContext().getConfig().describeEachNamedGraph); } - - final Graph g = SD.describeService(tripleStore, serviceURI); /* * CONNEG for the MIME type. Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/SD.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/SD.java 2012-07-24 00:33:16 UTC (rev 6389) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/SD.java 2012-07-24 14:04:39 UTC (rev 6390) @@ -30,14 +30,17 @@ import java.util.Arrays; import java.util.LinkedHashMap; import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.Set; import org.openrdf.model.BNode; import org.openrdf.model.Graph; +import org.openrdf.model.Resource; import org.openrdf.model.URI; import org.openrdf.model.ValueFactory; -import org.openrdf.model.impl.GraphImpl; import org.openrdf.model.impl.URIImpl; import org.openrdf.model.vocabulary.RDF; @@ -47,10 +50,14 @@ import com.bigdata.rdf.axioms.RdfsAxioms; import com.bigdata.rdf.internal.IV; import com.bigdata.rdf.internal.NotMaterializedException; +import com.bigdata.rdf.model.BigdataResource; import com.bigdata.rdf.model.BigdataURI; import com.bigdata.rdf.model.BigdataValue; +import com.bigdata.rdf.sail.BigdataSail; import com.bigdata.rdf.spo.SPOKeyOrder; +import com.bigdata.rdf.spo.SPORelation; import com.bigdata.rdf.store.AbstractTripleStore; +import com.bigdata.rdf.store.BD; import com.bigdata.rdf.store.BigdataValueIterator; import com.bigdata.rdf.store.BigdataValueIteratorImpl; import com.bigdata.rdf.vocab.decls.VoidVocabularyDecl; @@ -139,6 +146,36 @@ static public final URI BasicFederatedQuery = new URIImpl(NS + "BasicFederatedQuery"); /** + * The namespace for the bigdata specific features. + */ + static public final String BDFNS = BD.NAMESPACE+"/features/"; + + /* + * KB modes. + */ + static public final URI ModeTriples = new URIImpl(BDFNS + "KB/Mode/Triples"); + static public final URI ModeQuads = new URIImpl(BDFNS + "KB/Mode/Quads"); + static public final URI ModeSids = new URIImpl(BDFNS + "KB/Mode/Sids"); + + /* + * Text Index modes. + */ + static public final URI TextIndexValueCentric = new URIImpl(BDFNS + + "KB/TextIndex/ValueCentric"); + + static public final URI TextIndexSubjectCentric = new URIImpl(BDFNS + + "KB/TextIndex/SubjectCentric"); + + /* + * Misc KB features. + */ + static public final URI TruthMaintenance = new URIImpl(BDFNS + + "KB/TruthMaintenance"); + + static public final URI IsolatableIndices = new URIImpl(BDFNS + + "KB/IsolatableIndices"); + + /** * <pre> * http://www.w3.org/ns/entailment/OWL-RDF-Based * http://www.w3.org/ns/entailment/RDFS @@ -337,285 +374,548 @@ // "http://www.w3.org/ns/formats/SPARQL_Results_TSV"); /** - * Collect various information, building up a service description graph. + * The graph in which the service description is accumulated (from the + * constructor). + */ + protected final Graph g; + + /** + * The KB instance that is being described (from the constructor). + */ + protected final AbstractTripleStore tripleStore; + + /** + * The service end point (from the constructor). + */ + protected final String serviceURI; + + /** + * The value factory used to create values for the service description graph + * {@link #g}. + */ + protected final ValueFactory f; + + /** + * The resource which models the service. + */ + protected final BNode aService; + + /** + * The resource which models the default data set for the service. + */ + protected final BNode aDefaultDataset; + + /** + * The resource which models the default graph in the default data set for + * the service. + */ + protected final BNode aDefaultGraph; + + /** * + * @param g + * Where to assemble the description. * @param tripleStore * The KB instance to be described. * @param serviceURIs * One or more service end points for that KB instance. + * + * @see #describeService() */ - public static Graph describeService(final AbstractTripleStore tripleStore, + public SD(final Graph g, final AbstractTripleStore tripleStore, final String serviceURI) { - final Graph g = new GraphImpl(); + if (g == null) + throw new IllegalArgumentException(); - final ValueFactory f = g.getValueFactory(); + if (tripleStore == null) + throw new IllegalArgumentException(); + + if (serviceURI == null) + throw new IllegalArgumentException(); - final BNode service = f.createBNode("service"); + this.g = g; + + this.tripleStore = tripleStore; + + this.serviceURI = serviceURI; + + this.f = g.getValueFactory(); + + aService = f.createBNode("service"); - final BNode defaultDataset = f.createBNode("defaultDataset"); + aDefaultDataset = f.createBNode("defaultDataset"); - final BNode defaultGraph = f.createBNode("defaultGraph"); + aDefaultGraph = f.createBNode("defaultGraph"); + + } + + /** + * Collect various information, building up a service description graph. + * + * @param describeNamedGraphs + * When <code>true</code> and the KB instance is in the + * <code>quads</code> mode, each named graph will also be + * described in in the same level of detail as the default graph. + * Otherwise only the default graph will be described. + */ + public void describeService(final boolean describeNamedGraphs) { - g.add(service, RDF.TYPE, SD.Service); + g.add(aService, RDF.TYPE, SD.Service); // Service end point. - g.add(service, SD.endpoint, g.getValueFactory().createURI(serviceURI)); + describeServiceEndpoints(); - /* - * Supported Query Languages - */ - g.add(service, SD.supportedLanguage, SD.SPARQL10Query); - g.add(service, SD.supportedLanguage, SD.SPARQL11Query); - g.add(service, SD.supportedLanguage, SD.SPARQL11Update); + // Describe the supported languages (SPARQL Query, Update, etc). + describeLanguages(); - /* - * RDF and SPARQL Formats. - * - * @see http://www.openrdf.org/issues/browse/RIO-79 (Request for unique - * URIs) - * - * TODO Add an explicit declaration for SIDS mode data interchange? - */ + // Describe other supported features. + describeOtherFeatures(); + + // Describe the supported data formats. + describeInputFormats(); + describeResultFormats(); - // InputFormats - { - g.add(service, SD.inputFormat, SD.RDFXML); - g.add(service, SD.inputFormat, SD.NTRIPLES); - g.add(service, SD.inputFormat, SD.TURTLE); - g.add(service, SD.inputFormat, SD.N3); - // g.add(service, SD.inputFormat, SD.TRIX); // TODO TRIX - g.add(service, SD.inputFormat, SD.TRIG); - // g.add(service, SD.inputFormat, SD.BINARY); // TODO BINARY - g.add(service, SD.inputFormat, SD.NQUADS); + // Describe the entailment regime (if any). + describeEntailmentRegime(); + + // Describe the default graph of the default data set. + describeDefaultDataSet(describeNamedGraphs); - g.add(service, SD.inputFormat, SD.SPARQL_RESULTS_XML); - g.add(service, SD.inputFormat, SD.SPARQL_RESULTS_JSON); - g.add(service, SD.inputFormat, SD.SPARQL_RESULTS_CSV); - g.add(service, SD.inputFormat, SD.SPARQL_RESULTS_TSV); - // g.add(service, SD.inputFormat, - // SD.SPARQL_RESULTS_OPENRDF_BINARY); + } - } + /** + * Describe the service end point(s). + * + * @see #endpoint + */ + protected void describeServiceEndpoints() { - // ResultFormats - { - g.add(service, SD.resultFormat, SD.RDFXML); - g.add(service, SD.resultFormat, SD.NTRIPLES); - g.add(service, SD.resultFormat, SD.TURTLE); - g.add(service, SD.resultFormat, SD.N3); - // g.add(service, SD.resultFormat, SD.TRIX); // TODO TRIX - g.add(service, SD.resultFormat, SD.TRIG); - // g.add(service, SD.resultFormat, SD.BINARY); // TODO BINARY - // g.add(service, SD.resultFormat, SD.NQUADS); // TODO NQuads - // writer + g.add(aService, SD.endpoint, g.getValueFactory().createURI(serviceURI)); - g.add(service, SD.resultFormat, SD.SPARQL_RESULTS_XML); - g.add(service, SD.resultFormat, SD.SPARQL_RESULTS_JSON); - g.add(service, SD.resultFormat, SD.SPARQL_RESULTS_CSV); - g.add(service, SD.resultFormat, SD.SPARQL_RESULTS_TSV); - // g.add(service, SD.resultFormat, - // SD.SPARQL_RESULTS_OPENRDF_BINARY); - } + } + + /** + * Describe the supported Query Languages + */ + protected void describeLanguages() { - /* - * TODO Report out the database mode {triples, provenance, or quads} and - * the entailment regieme for that mode (only for triples or quads at - * this point). Report out when truth maintenance is enabled and whether - * or not the full text index is enabled. - * - * TODO sd:languageExtension or sd:feature could be used for query - * hints, NAMED SUBQUERY, etc. - */ + g.add(aService, SD.supportedLanguage, SD.SPARQL10Query); + + g.add(aService, SD.supportedLanguage, SD.SPARQL11Query); + g.add(aService, SD.supportedLanguage, SD.SPARQL11Update); + + } + + /** + * Describe the supported input formats. + * + * @see http://www.openrdf.org/issues/browse/RIO-79 (Request for unique + * URIs) + * + * @see #inputFormat + * + * TODO Add an explicit declaration for SIDS mode data interchange? + */ + protected void describeInputFormats() { + + g.add(aService, SD.inputFormat, SD.RDFXML); + g.add(aService, SD.inputFormat, SD.NTRIPLES); + g.add(aService, SD.inputFormat, SD.TURTLE); + g.add(aService, SD.inputFormat, SD.N3); + // g.add(service, SD.inputFormat, SD.TRIX); // TODO TRIX + g.add(aService, SD.inputFormat, SD.TRIG); + // g.add(service, SD.inputFormat, SD.BINARY); // TODO BINARY + g.add(aService, SD.inputFormat, SD.NQUADS); + + g.add(aService, SD.inputFormat, SD.SPARQL_RESULTS_XML); + g.add(aService, SD.inputFormat, SD.SPARQL_RESULTS_JSON); + g.add(aService, SD.inputFormat, SD.SPARQL_RESULTS_CSV); + g.add(aService, SD.inputFormat, SD.SPARQL_RESULTS_TSV); + // g.add(service,SD.inputFormat,SD.SPARQL_RESULTS_OPENRDF_BINARY); + + } + + /** + * Describe the supported result formats. + * + * @see #resultFormat + */ + protected void describeResultFormats() { + + g.add(aService, SD.resultFormat, SD.RDFXML); + g.add(aService, SD.resultFormat, SD.NTRIPLES); + g.add(aService, SD.resultFormat, SD.TURTLE); + g.add(aService, SD.resultFormat, SD.N3); + // g.add(service, SD.resultFormat, SD.TRIX); // TODO TRIX + g.add(aService, SD.resultFormat, SD.TRIG); + // g.add(service, SD.resultFormat, SD.BINARY); // TODO BINARY + // g.add(service, SD.resultFormat, SD.NQUADS); // TODO NQuads + // writer + + g.add(aService, SD.resultFormat, SD.SPARQL_RESULTS_XML); + g.add(aService, SD.resultFormat, SD.SPARQL_RESULTS_JSON); + g.add(aService, SD.resultFormat, SD.SPARQL_RESULTS_CSV); + g.add(aService, SD.resultFormat, SD.SPARQL_RESULTS_TSV); + // g.add(service, SD.resultFormat, + // SD.SPARQL_RESULTS_OPENRDF_BINARY); + + } + + /** + * Describe non-language features. + * + * TODO sd:languageExtension or sd:feature could be used for query hints, + * NAMED SUBQUERY, the NSS REST API features, etc. + * + * TODO Report the backing store type (Journal, TemporaryStore, Federation) + * and the journal buffer mode. + */ + protected void describeOtherFeatures() { + + g.add(aService, SD.feature, SD.BasicFederatedQuery); + if (tripleStore.isQuads()) { - g.add(service, SD.feature, SD.UnionDefaultGraph); + g.add(aService, SD.feature, SD.UnionDefaultGraph); + g.add(aService, SD.feature, ModeQuads); + + } else if(tripleStore.isStatementIdentifiers()) { + + g.add(aService, SD.feature, ModeSids); + } else { - /* - * TODO The Axioms interface could self-report this. - */ - final URI entailmentRegime; - final Axioms axioms = tripleStore.getAxioms(); - if (axioms == null || axioms instanceof NoAxioms) { - entailmentRegime = SD.simpleEntailment; - } else if (axioms instanceof OwlAxioms) { - // TODO This is really the RDFS+ entailment regime. - entailmentRegime = SD.rdfsEntailment; - } else if (axioms instanceof RdfsAxioms) { - entailmentRegime = SD.rdfsEntailment; - } else { - // Unknown. - entailmentRegime = null; - } - if (entailmentRegime != null) - g.add(service, SD.entailmentRegime, entailmentRegime); + g.add(aService, SD.feature, ModeTriples); } - // Other features. - g.add(service, SD.feature, SD.BasicFederatedQuery); + if (tripleStore.getLexiconRelation().isTextIndex()) { + g.add(aService, SD.feature, TextIndexValueCentric); + + } + + if (tripleStore.getLexiconRelation().isSubjectCentricTextIndex()) { + + g.add(aService, SD.feature, TextIndexSubjectCentric); + + } + + // TODO Report when justification chains are being tracked? +// if(tripleStore.isJustify()) + + final Properties properties = tripleStore.getProperties(); + + if (Boolean.valueOf(properties.getProperty( + BigdataSail.Options.TRUTH_MAINTENANCE, + BigdataSail.Options.DEFAULT_TRUTH_MAINTENANCE))) { + + g.add(aService, SD.feature, TruthMaintenance); + + } + + if (Boolean.valueOf(properties.getProperty( + BigdataSail.Options.ISOLATABLE_INDICES, + BigdataSail.Options.DEFAULT_ISOLATABLE_INDICES))) { + + g.add(aService, SD.feature, IsolatableIndices); + + } + /* - * Information about the defaultGraph. + * TODO Report properties from the BigdataSail * - * TODO This could all be generalized and then run for each known named - * graph as well. + * NAMESPACE? */ + + } + + /** + * Describe the entailment regime. + * + * TODO The Axioms interface could self-report this. + */ + protected void describeEntailmentRegime() { + + if (!tripleStore.isQuads()) + return; + + final URI entailmentRegime; + final Axioms axioms = tripleStore.getAxioms(); + if (axioms == null || axioms instanceof NoAxioms) { + entailmentRegime = SD.simpleEntailment; + } else if (axioms instanceof OwlAxioms) { + // TODO This is really the RDFS+ entailment regime. + entailmentRegime = SD.rdfsEntailment; + } else if (axioms instanceof RdfsAxioms) { + entailmentRegime = SD.rdfsEntailment; + } else { + // Unknown. + entailmentRegime = null; + } + if (entailmentRegime != null) + g.add(aService, SD.entailmentRegime, entailmentRegime); + + } + + /** + * Describe the default data set. + * + * @param describeNamedGraph + * When <code>true</code>, each named graph will also be + * described in in the same level of detail as the default graph. + * Otherwise only the default graph will be described. + */ + protected void describeDefaultDataSet(final boolean describeNamedGraph) { + + // Default data set + g.add(aService, SD.defaultDataset, aDefaultDataset); + + g.add(aDefaultDataset, RDF.TYPE, SD.Dataset); + + // any URI is considered to be an entity. + g.add(aDefaultDataset, VoidVocabularyDecl.uriRegexPattern, + f.createLiteral("^.*")); + + // Frequency count of the predicates in the default graph. + final IVCount[] predicatePartitionCounts = predicateUsage( + tripleStore); + + // Frequency count of the classes in the default graph. + final IVCount[] classPartitionCounts = classUsage(tripleStore); + + // Describe vocabularies based on the predicate partitions. + describeVocabularies(predicatePartitionCounts); + + // defaultGraph description. { + + // Default graph in the default data set. + g.add(aDefaultDataset, SD.defaultGraph, aDefaultGraph); - // Default data set - g.add(service, SD.defaultDataset, defaultDataset); + // Describe the default graph using statistics. + describeGraph(aDefaultGraph, predicatePartitionCounts, + classPartitionCounts); - g.add(defaultDataset, RDF.TYPE, SD.Dataset); + } // end defaultGraph - // any URI is considered to be an entity. - g.add(defaultDataset, VoidVocabularyDecl.uriRegexPattern, - f.createLiteral("^.*")); + // sb.append("termCount\t = " + tripleStore.getTermCount() + "\n"); + // + // sb.append("uriCount\t = " + tripleStore.getURICount() + "\n"); + // + // sb.append("literalCount\t = " + tripleStore.getLiteralCount() + + // "\n"); + // + // /* + // * Note: The blank node count is only available when using the told + // * bnodes mode. + // */ + // sb + // .append("bnodeCount\t = " + // + (tripleStore.getLexiconRelation() + // .isStoreBlankNodes() ? "" + // + tripleStore.getBNodeCount() : "N/A") + // + "\n"); - // Default graph in the default data set. - g.add(defaultDataset, SD.defaultGraph, defaultGraph); + /* + * Report for each named graph. + */ + if (describeNamedGraph && tripleStore.isQuads()) { - // defautGraph description. - { + final SPORelation r = tripleStore.getSPORelation(); - // #of triples in the default graph - g.add(defaultGraph, VoidVocabularyDecl.triples, - f.createLiteral(tripleStore.getStatementCount())); + // the index to use for distinct term scan. + final SPOKeyOrder keyOrder = SPOKeyOrder.CSPO; - // #of entities in the default graph. - g.add(defaultGraph, VoidVocabularyDecl.entities, - f.createLiteral(tripleStore.getURICount())); + // visit distinct IVs for context position on that index. + @SuppressWarnings("rawtypes") + final IChunkedIterator<IV> itr = r.distinctTermScan(keyOrder); - // The distinct vocabularies in use. - final Set<String> namespaces = new LinkedHashSet<String>(); + // resolve IVs to terms efficiently during iteration. + final BigdataValueIterator itr2 = new BigdataValueIteratorImpl( + tripleStore/* resolveTerms */, itr); - /* - * property partition statistics & used vocabularies. - * - * Note: A temporary graph is used to hold these data so we can - * first output the vocabulary summary. This gives the output a - * neater (and more human consumable) appearance. - */ - final Graph propertyPartitions = new GraphImpl(); + try { - // Frequency count of the predicates in the default graph. - final IVCount[] predicatePartitionCounts = predicateUsage(tripleStore); + while (itr2.hasNext()) { - // Frequency count of the classes in the default graph. - final IVCount[] classPartitionCounts = classUsage(tripleStore); + /* + * Describe this named graph. + * + * Note: This is using the predicate and class partition + * statistics from the default graph (RDF merge) to identify + * the set of all possible predicates and classes within + * each named graph. It then tests each predicate and class + * partition against the named graph and ignores those which + * are not present in a given named graph. This is being + * done because we do not have a CPxx index. + */ - { + final BigdataResource graph = (BigdataResource) itr2.next(); - // property partitions. - for (IVCount tmp : predicatePartitionCounts) { + final IVCount[] predicatePartitionCounts2 = predicateUsage( + tripleStore, graph.getIV(), + predicatePartitionCounts); - final BNode propertyPartition = f.createBNode(); + final IVCount[] classPartitionCounts2 = classUsage( + tripleStore, graph.getIV(), classPartitionCounts); - final URI p = (URI) tmp.getValue(); + final BNode aNamedGraph = f.createBNode(); - propertyPartitions.add(defaultGraph, - VoidVocabularyDecl.propertyPartition, - propertyPartition); + // Named graph in the default data set. + g.add(aDefaultDataset, SD.namedGraph, aNamedGraph); - propertyPartitions.add(propertyPartition, - VoidVocabularyDecl.property, p); + // The name of that named graph. + g.add(aNamedGraph, SD.name, graph); - propertyPartitions.add(propertyPartition, - VoidVocabularyDecl.triples, - f.createLiteral(tmp.count)); + // Describe the named graph. + describeGraph(aNamedGraph, predicatePartitionCounts2, + classPartitionCounts2); - String namespace = p.getNamespace(); + } + + } finally { - if (namespace.endsWith("#")) { + itr2.close(); - // Strip trailing '#' per VoID specification. - namespace = namespace.substring(0, - namespace.length() - 1); + } - } + } - namespaces.add(namespace); + } - } + /** + * Describe the vocabularies which are in use in the KB based on the + * predicate partition statistics. + * + * @param predicateParitionCounts + * The predicate partition statistics. + */ + protected void describeVocabularies(final IVCount[] predicatePartitionCounts) { - } + // Find the distinct vocabularies in use. + final Set<String> namespaces = new LinkedHashSet<String>(); + { - // emit the in use vocabularies. - for (String namespace : namespaces) { + // property partitions. + for (IVCount tmp : predicatePartitionCounts) { - g.add(defaultDataset, VoidVocabularyDecl.vocabulary, - f.createURI(namespace)); + final URI p = (URI) tmp.getValue(); + String namespace = p.getNamespace(); + + if (namespace.endsWith("#")) { + + // Strip trailing '#' per VoID specification. + namespace = namespace.substring(0, + namespace.length() - 1); + } - // #of distinct predicates in the default graph. - g.add(defaultGraph, VoidVocabularyDecl.properties, - f.createLiteral(predicatePartitionCounts.length)); + namespaces.add(namespace); - // #of distinct classes in the default graph. - g.add(defaultGraph, VoidVocabularyDecl.classes, - f.createLiteral(classPartitionCounts.length)); + } - // now emit the property partition statistics. - g.addAll(propertyPartitions); - - // class partition statistics. - { + } - // per class partition statistics. - for (IVCount tmp : classPartitionCounts) { + // Sort into dictionary order. + final String[] a = namespaces.toArray(new String[namespaces.size()]); + + Arrays.sort(a); - final BNode classPartition = f.createBNode(); + for (String namespace : a) { - final BigdataValue cls = tmp.getValue(); + g.add(aDefaultDataset, VoidVocabularyDecl.vocabulary, + f.createURI(namespace)); - g.add(defaultGraph, VoidVocabularyDecl.classPartition, - classPartition); + } - g.add(classPartition, VoidVocabularyDecl.class_, cls); + } + + /** + * Describe a named or default graph. + * + * @param graph + * The named graph. + * @param predicatePartitionCounts + * The predicate partition statistics for that graph. + * @param classPartitionCounts + * The class partition statistics for that graph. + */ + protected void describeGraph(final Resource graph, + final IVCount[] predicatePartitionCounts, + final IVCount[] classPartitionCounts) { - g.add(classPartition, VoidVocabularyDecl.triples, - f.createLiteral(tmp.count)); + // The graph is a Graph. + g.add(graph, RDF.TYPE, SD.Graph); - } + // #of triples in the default graph + g.add(graph, VoidVocabularyDecl.triples, + f.createLiteral(tripleStore.getStatementCount())); - } // end class partition statistics. + // #of entities in the default graph. + g.add(graph, VoidVocabularyDecl.entities, + f.createLiteral(tripleStore.getURICount())); - } // end defaultGraph - -// sb.append("termCount\t = " + tripleStore.getTermCount() + "\n"); -// -// sb.append("uriCount\t = " + tripleStore.getURICount() + "\n"); -// -// sb.append("literalCount\t = " + tripleStore.getLiteralCount() + "\n"); -// -// /* -// * Note: The blank node count is only available when using the told -// * bnodes mode. -// */ -// sb -// .append("bnodeCount\t = " -// + (tripleStore.getLexiconRelation() -// .isStoreBlankNodes() ? "" -// + tripleStore.getBNodeCount() : "N/A") -// + "\n"); + // #of distinct predicates in the default graph. + g.add(graph, VoidVocabularyDecl.properties, + f.createLiteral(predicatePartitionCounts.length)); + // #of distinct classes in the default graph. + g.add(graph, VoidVocabularyDecl.classes, + f.createLiteral(classPartitionCounts.length)); + + // property partition statistics. + for (IVCount tmp : predicatePartitionCounts) { + + final BNode propertyPartition = f.createBNode(); + + final URI p = (URI) tmp.getValue(); + + g.add(graph, VoidVocabularyDecl.propertyPartition, + propertyPartition); + + g.add(propertyPartition, VoidVocabularyDecl.property, p); + + g.add(propertyPartition, VoidVocabularyDecl.triples, + f.createLiteral(tmp.count)); + } - return g; - + // class partition statistics. + { + + // per class partition statistics. + for (IVCount tmp : classPartitionCounts) { + + final BNode classPartition = f.createBNode(); + + final BigdataValue cls = tmp.getValue(); + + g.add(graph, VoidVocabularyDecl.classPartition, + classPartition); + + g.add(classPartition, VoidVocabularyDecl.class_, cls); + + g.add(classPartition, VoidVocabularyDecl.triples, + f.createLiteral(tmp.count)); + + } + + } // end class partition statistics. + } /** * An {@link IV} and a counter for that {@link IV}. */ - private static class IVCount implements Comparable<IVCount> { + protected static class IVCount implements Comparable<IVCount> { - public final IV<?,?> iv; - + public final IV<?, ?> iv; + public final long count; private BigdataValue val; @@ -677,16 +977,21 @@ } } - + /** * Return an array of the distinct predicates in the KB ordered by their * descending frequency of use. The {@link IV}s in the returned array will * have been resolved to the corresponding {@link BigdataURI}s which can be * accessed using {@link IV#getValue()}. + * + * @param kb + * The KB instance. */ - private static IVCount[] predicateUsage(final AbstractTripleStore kb) { + protected static IVCount[] predicateUsage(final AbstractTripleStore kb) { - if (kb.getSPORelation().oneAccessPath) { + final SPORelation r = kb.getSPORelation(); + + if (r.oneAccessPath) { // The necessary index (POS or POCS) does not exist. throw new UnsupportedOperationException(); @@ -695,10 +1000,12 @@ final boolean quads = kb.isQuads(); - // visit distinct term identifiers for the predicate position. + // the index to use for distinct predicate scan. + final SPOKeyOrder keyOrder = quads ? SPOKeyOrder.POCS : SPOKeyOrder.POS; + + // visit distinct term identifiers for predicate position on that index. @SuppressWarnings("rawtypes") - final IChunkedIterator<IV> itr = kb.getSPORelation().distinctTermScan( - quads ? SPOKeyOrder.POCS : SPOKeyOrder.POS); + final IChunkedIterator<IV> itr = r.distinctTermScan(keyOrder); // resolve term identifiers to terms efficiently during iteration. final BigdataValueIterator itr2 = new BigdataValueIteratorImpl( @@ -716,8 +1023,7 @@ final IV<?,?> iv = term.getIV(); - final long n = kb.getSPORelation() - .getAccessPath(null, iv, null, null) + final long n = r.getAccessPath(null, iv, null, null) .rangeCount(false/* exact */); ivs.add(iv); @@ -755,6 +1061,61 @@ } /** + * Return the predicate partition statistics for the named graph. + * + * @param kb + * The KB instance. + * @param civ + * The {@link IV} of a named graph (required). + * + * @return The predicate partition statistics for that named graph. Only + * predicate partitions which are non-empty are returned. + */ + protected static IVCount[] predicateUsage(final AbstractTripleStore kb, + final IV<?, ?> civ, final IVCount[] predicatePartitionCounts) { + + final SPORelation r = kb.getSPORelation(); + + final boolean quads = kb.isQuads(); + + if (!quads) { + + // Named graph only valid in quads mode. + throw new IllegalArgumentException(); + + } + + // The non-zero counts. + final List<IVCount> counts = new LinkedList<IVCount>(); + + // Check the known non-empty predicate partitions. + for(IVCount in : predicatePartitionCounts){ + + final long n = r.getAccessPath(null, in.iv, null, civ).rangeCount( + false/* exact */); + + if (n == 0) + continue; + + final IVCount out = new IVCount(in.iv, n); + + out.setValue(in.getValue()); + + counts.add(out); + + } + + + final IVCount[] a = counts.toArray(new IVCount[counts.size()]); + + // Order by descending count. + Arrays.sort(a); + + return a; + + } + + /** * Return an efficient statistical summary for the class partitions. The * SPARQL query for this is * @@ -781,10 +1142,12 @@ * * @return The class usage statistics. */ - private static IVCount[] classUsage(final AbstractTripleStore kb) { + protected static IVCount[] classUsage(final AbstractTripleStore kb) { - if (kb.getSPORelation().oneAccessPath) { + final SPORelation r = kb.getSPORelation(); + if (r.oneAccessPath) { + // The necessary index (POS or POCS) does not exist. throw new UnsupportedOperationException(); @@ -809,9 +1172,8 @@ // visit distinct term identifiers for the rdf:type predicate. @SuppressWarnings("rawtypes") - final IChunkedIterator<IV> itr = kb - .getSPORelation() - .distinctMultiTermScan(keyOrder, new IV[] { rdfType.getIV() }/* knownTerms */); + final IChunkedIterator<IV> itr = r.distinctMultiTermScan(keyOrder, + new IV[] { rdfType.getIV() }/* knownTerms */); // resolve term identifiers to terms efficiently during iteration. final BigdataValueIterator itr2 = new BigdataValueIteratorImpl( @@ -829,10 +1191,8 @@ final IV<?,?> iv = term.getIV(); - final long n = kb - .getSPORelation() - .getAccessPath(null, rdfType.getIV()/* p */, iv/* o */, - null).rangeCount(false/* exact */); + final long n = r.getAccessPath(null, rdfType.getIV()/* p */, + iv/* o */, null).rangeCount(false/* exact */); ivs.add(iv); @@ -868,4 +1228,71 @@ } + /** + * Return the class partition statistics for the named graph. + * + * @param kb + * The KB instance. + * @param civ + * The {@link IV} of a named graph (required). + * + * @return The class partition statistics for that named graph. Only class + * partitions which are non-empty are returned. + */ + protected static IVCount[] classUsage(final AbstractTripleStore kb, + final IV<?, ?> civ, final IVCount[] classPartitionCounts) { + + final SPORelation r = kb.getSPORelation(); + + final boolean quads = kb.isQuads(); + + if (!quads) { + + // Named graph only valid in quads mode. + throw new IllegalArgumentException(); + + } + + // Resolve IV for rdf:type + final BigdataURI rdfType = kb.getValueFactory().asValue(RDF.TYPE); + + kb.getLexiconRelation().addTerms(new BigdataValue[] { rdfType }, + 1/* numTerms */, true/* readOnly */); + + if (rdfType.getIV() == null) { + + // No rdf:type assertions since rdf:type is unknown term. + return new IVCount[0]; + + } + + // The non-zero counts. + final List<IVCount> counts = new LinkedList<IVCount>(); + + // Check the known non-empty predicate partitions. + for (IVCount in : classPartitionCounts) { + + final long n = r.getAccessPath(null, rdfType.getIV()/* p */, + in.iv/* o */, civ).rangeCount(false/* exact */); + + if (n == 0) + continue; + + final IVCount out = new IVCount(in.iv, n); + + out.setValue(in.getValue()); + + counts.add(out); + + } + + final IVCount[] a = counts.toArray(new IVCount[counts.size()]); + + // Order by descending count. + Arrays.sort(a); + + return a; + + } + } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/SparqlEndpointConfig.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/SparqlEndpointConfig.java 2012-07-24 00:33:16 UTC (rev 6389) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/SparqlEndpointConfig.java 2012-07-24 14:04:39 UTC (rev 6390) @@ -50,8 +50,16 @@ */ final public int queryThreadPoolSize; + /** + * When <code>true</code> and the KB instance is in the <code>quads</code> + * mode, each named graph will also be described in in the same level of + * detail as the default graph. Otherwise only the default graph will be + * described. + */ + final public boolean describeEachNamedGraph; + public SparqlEndpointConfig(final String namespace, final long timestamp, - final int queryThreadPoolSize) { + final int queryThreadPoolSize, final boolean describeEachNamedGraph) { if (namespace == null) throw new IllegalArgumentException(); @@ -61,6 +69,8 @@ this.timestamp = timestamp; this.queryThreadPoolSize = queryThreadPoolSize; + + this.describeEachNamedGraph = describeEachNamedGraph; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2012-07-26 16:02:47
|
Revision: 6393 http://bigdata.svn.sourceforge.net/bigdata/?rev=6393&view=rev Author: thompsonbry Date: 2012-07-26 16:02:36 +0000 (Thu, 26 Jul 2012) Log Message: ----------- Support for the interchange of java.util.Properties objects using the rio patterns (registeries, factories, writers and parsers). Support exists for text and xml interchange. This was done to support the REST CREATE for the NSS API. Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/util/PropertyUtil.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/ServiceProviderHook.java Added Paths: ----------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesFormat.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesParser.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesParserFactory.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesParserRegistry.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesWriter.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesWriterFactory.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesWriterRegistry.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/text/ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/text/PropertiesTextParser.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/text/PropertiesTextParserFactory.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/text/PropertiesTextWriter.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/text/PropertiesTextWriterFactory.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/xml/ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/xml/PropertiesXMLParser.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/xml/PropertiesXMLParserFactory.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/xml/PropertiesXMLWriter.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/xml/PropertiesXMLWriterFactory.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/resources/service-providers/META-INF/services/com.bigdata.rdf.properties.PropertiesParserFactory branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/resources/service-providers/META-INF/services/com.bigdata.rdf.properties.PropertiesWriterFactory Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/util/PropertyUtil.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/util/PropertyUtil.java 2012-07-26 16:00:36 UTC (rev 6392) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/util/PropertyUtil.java 2012-07-26 16:02:36 UTC (rev 6393) @@ -56,18 +56,22 @@ { /** - * Return a flatten copy of the specified {@link Properties}. The - * returned object does not share any structure with the source - * object, but it does share key and value references. Since keys - * and values are {@link String}s for a {@link Properties} instance - * this SHOULD NOT be a problem. The behavior is equivilent to: + * Return a flatten copy of the specified {@link Properties}. The returned + * object does not share any structure with the source object, but it does + * share key and value references. Since keys and values are {@link String}s + * for a {@link Properties} instance this SHOULD NOT be a problem. The + * behavior is equivalent to: + * * <pre> * Properties tmp = new Properties(); - * tmp.putAll( flatten( props ) ); + * tmp.putAll(flatten(props)); * </pre> * - * @param props The properties to be flattened and copied. + * except that it handles <code>null</code> values. * + * @param props + * The properties to be flattened and copied. + * * @return A flat copy. */ @@ -76,8 +80,29 @@ final Properties tmp = new Properties(); - tmp.putAll( flatten( props ) ); +// tmp.putAll( flatten( props ) ); + final Map<String, Object> map = flatten(props); + + for(Map.Entry<String,Object> e : map.entrySet()) { + + final String name = e.getKey(); + + final Object val = e.getValue(); + +// if (val == null || !(val instanceof String)) { +// System.err.println("name=" + name + ", val=" + val); +// } + + if (val != null) { + + // Note: Hashtable does not allow nulls. + tmp.put(name, val); + + } + + } + return tmp; } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/ServiceProviderHook.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/ServiceProviderHook.java 2012-07-26 16:00:36 UTC (rev 6392) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/ServiceProviderHook.java 2012-07-26 16:02:36 UTC (rev 6393) @@ -124,6 +124,24 @@ r.add(new BigdataRDFXMLWriterFactory()); } + +// { +// final PropertiesParserRegistry r = PropertiesParserRegistry.getInstance(); +// +// r.add(new PropertiesXMLParserFactory()); +// +// r.add(new PropertiesTextParserFactory()); +// +// } +// +// { +// final PropertiesWriterRegistry r = PropertiesWriterRegistry.getInstance(); +// +// r.add(new PropertiesXMLWriterFactory()); +// +// r.add(new PropertiesTextWriterFactory()); +// +// } loaded = true; Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesFormat.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesFormat.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesFormat.java 2012-07-26 16:02:36 UTC (rev 6393) @@ -0,0 +1,209 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ +/* +Portions of this code are: + +Copyright Aduna (http://www.aduna-software.com/) � 2001-2007 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +/* + * Created on Jul 25, 2012 + */ +package com.bigdata.rdf.properties; + +import info.aduna.lang.FileFormat; + +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.concurrent.CopyOnWriteArraySet; + +import org.openrdf.rio.RDFFormat; + +/** + * Formats for a properties file. + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ +public class PropertiesFormat extends FileFormat implements Iterable<PropertiesFormat> { + + /** + * All known/registered formats for this class. + */ + private static final CopyOnWriteArraySet<PropertiesFormat> formats = new CopyOnWriteArraySet<PropertiesFormat>(); + + /** + * A thread-safe iterator that will visit all known formats (declared by + * {@link Iterable}). + */ + public Iterator<PropertiesFormat> iterator() { + + return formats.iterator(); + + } + + /** + * Alternative static method signature. + */ + static public Iterator<PropertiesFormat> getFormats() { + + return formats.iterator(); + + } + + /** + * Text properties file using <code>text/plain</code> and + * <code>UTF-8</code>. + */ + public static final PropertiesFormat TEXT = new PropertiesFormat(// + "text/plain",// + Arrays.asList("text/plain"),// + Charset.forName("UTF-8"), // + Arrays.asList("properties")// + ); + + /** + * XML properties file using <code>application/xml</code> and + * <code>UTF-8</code>. + */ + public static final PropertiesFormat XML = new PropertiesFormat(// + "application/xml",// + Arrays.asList("application/xml"),// + Charset.forName("UTF-8"),// charset + Arrays.asList("xml")// known-file-extensions + ); + + /** + * Registers the specified format. + */ + public static void register(final PropertiesFormat format) { + + formats.add(format); + + } + + static { + + register(TEXT); + register(XML); + + } + +// /** +// * Binary properties file using <code>application/octet-stream</code> +// */ +// public static final PropertiesFormat BINARY = new PropertiesFormat(// +// "application/octet-stream",// +// Arrays.asList("application/octet-stream"),// +// null,// charset +// (List) Collections.emptyList()// known-file-extensions +// ); + + /** + * Creates a new RDFFormat object. + * + * @param name + * The name of the RDF file format, e.g. "RDF/XML". + * @param mimeTypes + * The MIME types of the RDF file format, e.g. + * <tt>application/rdf+xml</tt> for the RDF/XML file format. + * The first item in the list is interpreted as the default + * MIME type for the format. + * @param charset + * The default character encoding of the RDF file format. + * Specify <tt>null</tt> if not applicable. + * @param fileExtensions + * The RDF format's file extensions, e.g. <tt>rdf</tt> for + * RDF/XML files. The first item in the list is interpreted + * as the default file extension for the format. + */ + public PropertiesFormat(final String name, + final Collection<String> mimeTypes, final Charset charset, + final Collection<String> fileExtensions) { + + super(name, mimeTypes, charset, fileExtensions); + + } + + /** + * Tries to determine the appropriate file format based on the a MIME + * type that describes the content type. + * + * @param mimeType + * A MIME type, e.g. "text/html". + * @return An {@link PropertiesFormat} object if the MIME type was recognized, or + * <tt>null</tt> otherwise. + * @see #forMIMEType(String,PropertiesFormat) + * @see #getMIMETypes() + */ + public static PropertiesFormat forMIMEType(final String mimeType) { + return forMIMEType(mimeType, null); + } + + /** + * Tries to determine the appropriate file format based on the a MIME + * type that describes the content type. The supplied fallback format will be + * returned when the MIME type was not recognized. + * + * @param mimeType + * A file name. + * @return An {@link PropertiesFormat} that matches the MIME type, or the fallback format if + * the extension was not recognized. + * @see #forMIMEType(String) + * @see #getMIMETypes() + */ + public static PropertiesFormat forMIMEType(String mimeType, + PropertiesFormat fallback) { + + return matchMIMEType(mimeType, formats/* Iterable<FileFormat> */, + fallback); + + } + +} \ No newline at end of file Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesParser.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesParser.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesParser.java 2012-07-26 16:02:36 UTC (rev 6393) @@ -0,0 +1,100 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ +/* +Portions of this code are: + +Copyright Aduna (http://www.aduna-software.com/) � 2001-2007 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +/* + * Created on Jul 25, 2012 + */ +package com.bigdata.rdf.properties; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.Properties; + +/** + * An interface for {@link Properties} document readers. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ +public interface PropertiesParser { + + /** + * Gets the {@link PropertiesFormat} that this {@link PropertiesParser} + * uses. + */ + public PropertiesFormat getFormat(); + + /** + * Parses the data from the supplied {@link InputStream}. + * + * @param in + * The InputStream from which to read the data. + * @throws IOException + * If an I/O error occurred while data was read from the + * InputStream. + */ + public Properties parse(InputStream in) throws IOException; + + /** + * Parses the data from the supplied {@link Reader}. + * + * @param reader + * The Reader from which to read the data. + * @throws IOException + * If an I/O error occurred while data was read from the + * InputStream. + */ + public Properties parse(Reader reader) throws IOException; + +} Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesParserFactory.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesParserFactory.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesParserFactory.java 2012-07-26 16:02:36 UTC (rev 6393) @@ -0,0 +1,75 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ +/* +Portions of this code are: + +Copyright Aduna (http://www.aduna-software.com/) � 2001-2007 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +/* + * Created on Jul 25, 2012 + */ +package com.bigdata.rdf.properties; + +/** + * A {@link PropertiesParserFactory} returns {@link PropertiesParser}s for a + * specific {@link PropertiesFormat}. + */ +public interface PropertiesParserFactory { + + /** + * Returns the format for this factory. + */ + public PropertiesFormat getFormat(); + + /** + * Returns a {@link PropertiesParser} instance. + */ + public PropertiesParser getParser(); +} Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesParserRegistry.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesParserRegistry.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesParserRegistry.java 2012-07-26 16:02:36 UTC (rev 6393) @@ -0,0 +1,95 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ +/* +Portions of this code are: + +Copyright Aduna (http://www.aduna-software.com/) � 2001-2007 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +/* + * Created on Jul 25, 2012 + */ +package com.bigdata.rdf.properties; + +import info.aduna.lang.service.FileFormatServiceRegistry; + +import org.openrdf.rio.RDFParserFactory; + +/** + * A registry that keeps track of the available {@link RDFParserFactory}s. + * + * @author Bryan Thompson + */ +public class PropertiesParserRegistry extends + FileFormatServiceRegistry<PropertiesFormat, PropertiesParserFactory> { + + private static PropertiesParserRegistry defaultRegistry; + + /** + * Gets the default {@link PropertiesParserRegistry}. + * + * @return The default registry. + */ + public static synchronized PropertiesParserRegistry getInstance() { + if (defaultRegistry == null) { + defaultRegistry = new PropertiesParserRegistry(); + } + + return defaultRegistry; + } + + public PropertiesParserRegistry() { + super(PropertiesParserFactory.class); + } + + @Override + protected PropertiesFormat getKey(PropertiesParserFactory factory) { + return factory.getFormat(); + } +} Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesWriter.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesWriter.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesWriter.java 2012-07-26 16:02:36 UTC (rev 6393) @@ -0,0 +1,79 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ +/* +Portions of this code are: + +Copyright Aduna (http://www.aduna-software.com/) � 2001-2007 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +/* + * Created on Jul 25, 2012 + */ +package com.bigdata.rdf.properties; + +import java.io.IOException; +import java.util.Properties; + +/** + * An interface for properties document writers. + */ +public interface PropertiesWriter { + + /** + * Gets the {@link PropertiesFormat} that this {@link PropertiesWriter} + * uses. + */ + public PropertiesFormat getFormat(); + + /** + * Write the properties object. + */ + public void write(Properties properties) throws IOException; + +} Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesWriterFactory.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesWriterFactory.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesWriterFactory.java 2012-07-26 16:02:36 UTC (rev 6393) @@ -0,0 +1,93 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ +/* +Portions of this code are: + +Copyright Aduna (http://www.aduna-software.com/) � 2001-2007 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +/* + * Created on Jul 25, 2012 + */ +package com.bigdata.rdf.properties; + +import java.io.OutputStream; +import java.io.Writer; + +/** + * A {@link PropertiesWriterFactory} returns {@link PropertiesWriter}s for a + * specific {@link PropertiesFormat}. + * + * @author Arjohn Kampman + */ +public interface PropertiesWriterFactory { + + /** + * Returns the PropertiesFactory for this factory. + */ + public PropertiesFormat getRDFFormat(); + + /** + * Returns an {@link PropertiesWriter} instance that will write to the + * supplied output stream. + * + * @param out + * The OutputStream to write the RDF to. + */ + public PropertiesWriter getWriter(OutputStream out); + + /** + * Returns an {@link PropertiesWriter} instance that will write to the + * supplied writer. + * + * @param writer + * The Writer to write the RDF to. + */ + public PropertiesWriter getWriter(Writer writer); +} Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesWriterRegistry.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesWriterRegistry.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/PropertiesWriterRegistry.java 2012-07-26 16:02:36 UTC (rev 6393) @@ -0,0 +1,95 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ +/* +Portions of this code are: + +Copyright Aduna (http://www.aduna-software.com/) � 2001-2007 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +/* + * Created on Jul 25, 2012 + */ +package com.bigdata.rdf.properties; + +import info.aduna.lang.service.FileFormatServiceRegistry; + +/** + * A registry that keeps track of the available {@link PropertiesWriterFactory} + * s. + * + * @author Arjohn Kampman + * @author Bryan Thompson + */ +public class PropertiesWriterRegistry extends + FileFormatServiceRegistry<PropertiesFormat, PropertiesWriterFactory> { + + private static PropertiesWriterRegistry defaultRegistry; + + /** + * Gets the default {@link PropertiesWriterRegistry}. + * + * @return The default registry. + */ + public static synchronized PropertiesWriterRegistry getInstance() { + if (defaultRegistry == null) { + defaultRegistry = new PropertiesWriterRegistry(); + } + + return defaultRegistry; + } + + public PropertiesWriterRegistry() { + super(PropertiesWriterFactory.class); + } + + @Override + protected PropertiesFormat getKey(final PropertiesWriterFactory factory) { + return factory.getRDFFormat(); + } +} Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/text/PropertiesTextParser.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/text/PropertiesTextParser.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/text/PropertiesTextParser.java 2012-07-26 16:02:36 UTC (rev 6393) @@ -0,0 +1,107 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ +/* +Portions of this code are: + +Copyright Aduna (http://www.aduna-software.com/) � 2001-2007 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +/* + * Created on Jul 25, 2012 + */ +package com.bigdata.rdf.properties.text; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.Properties; + +import com.bigdata.rdf.properties.PropertiesFormat; +import com.bigdata.rdf.properties.PropertiesParser; + +/** + * An {@link PropertiesParser} for {@link Properties} objects in the text + * listing format. + * + * @author Bryan THompson + */ +public class PropertiesTextParser implements PropertiesParser { + + /** + * Returns {@link PropertiesFormat#TEXT}. + */ + public PropertiesFormat getFormat() { + + return PropertiesFormat.TEXT; + + } + + @Override + public Properties parse(final InputStream in) throws IOException { + + final Properties p = new Properties(); + + p.load(in); + + return p; + + } + + @Override + public Properties parse(final Reader reader) throws IOException { + + final Properties p = new Properties(); + + p.load(reader); + + return p; + + } + +} Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/text/PropertiesTextParserFactory.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/text/PropertiesTextParserFactory.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/text/PropertiesTextParserFactory.java 2012-07-26 16:02:36 UTC (rev 6393) @@ -0,0 +1,91 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ +/* +Portions of this code are: + +Copyright Aduna (http://www.aduna-software.com/) � 2001-2007 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +/* + * Created on Jul 25, 2012 + */ +package com.bigdata.rdf.properties.text; + +import java.util.Properties; + +import com.bigdata.rdf.properties.PropertiesFormat; +import com.bigdata.rdf.properties.PropertiesParser; +import com.bigdata.rdf.properties.PropertiesParserFactory; + +/** + * An {@link PropertiesParserFactory} for {@link Properties} objects in the text + * listing format. + * + * @author Bryan THompson + */ +public class PropertiesTextParserFactory implements PropertiesParserFactory { + + /** + * Returns {@link PropertiesFormat#TEXT}. + */ + public PropertiesFormat getFormat() { + + return PropertiesFormat.TEXT; + + } + + /** + * Returns a new instance of {@link PropertiesTextParser}. + */ + public PropertiesParser getParser() { + + return new PropertiesTextParser(); + + } +} Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/text/PropertiesTextWriter.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/text/PropertiesTextWriter.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/text/PropertiesTextWriter.java 2012-07-26 16:02:36 UTC (rev 6393) @@ -0,0 +1,120 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ +/* +Portions of this code are: + +Copyright Aduna (http://www.aduna-software.com/) � 2001-2007 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +/* + * Created on Jul 25, 2012 + */ +package com.bigdata.rdf.properties.text; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +import java.util.Properties; + +import org.apache.commons.io.output.WriterOutputStream; + +import com.bigdata.rdf.properties.PropertiesFormat; +import com.bigdata.rdf.properties.PropertiesWriter; + +/** + * {@link PropertiesFormat#TEXT} writer. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ +public class PropertiesTextWriter implements PropertiesWriter { + + private final OutputStream os; + + /** + * Creates a new {@link PropertiesTextWriter} that will write to the + * supplied {@link OutputStream}. + * + * @param out + * The OutputStream to write the {@link Properties} document to. + */ + public PropertiesTextWriter(final OutputStream out) { + + this.os = out; + + } + + /** + * Creates a new {@link PropertiesTextWriter} that will write to the supplied + * {@link Writer}. + * + * @param writer + * The {@link Writer} to write the {@link Properties} document + * to. + */ + public PropertiesTextWriter(final Writer writer) { + + this.os = new WriterOutputStream(writer, + PropertiesFormat.TEXT.getCharset()); + + } + + public PropertiesFormat getFormat() { + + return PropertiesFormat.TEXT; + + } + + @Override + public void write(final Properties properties) throws IOException { + + properties.store(os, null/*comment*/); + + } + +} Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/text/PropertiesTextWriterFactory.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/text/PropertiesTextWriterFactory.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/text/PropertiesTextWriterFactory.java 2012-07-26 16:02:36 UTC (rev 6393) @@ -0,0 +1,99 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ +/* +Portions of this code are: + +Copyright Aduna (http://www.aduna-software.com/) � 2001-2007 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +/* + * Created on Jul 25, 2012 + */ +package com.bigdata.rdf.properties.text; + +import java.io.OutputStream; +import java.io.Writer; + +import com.bigdata.rdf.properties.PropertiesFormat; +import com.bigdata.rdf.properties.PropertiesWriter; +import com.bigdata.rdf.properties.PropertiesWriterFactory; + +/** + * An {@link PropertiesWriterFactory} for text writers. + */ +public class PropertiesTextWriterFactory implements PropertiesWriterFactory { + + /** + * Returns {@link PropertiesFormat#TEXT}. + */ + public PropertiesFormat getRDFFormat() { + + return PropertiesFormat.TEXT; + + } + + /** + * Returns a new instance of {@link PropertiesTextWriter}. + */ + public PropertiesWriter getWriter(final OutputStream out) { + + return new PropertiesTextWriter(out); + + } + + /** + * Returns a new instance of {@link PropertiesTextWriter}. + */ + public PropertiesWriter getWriter(final Writer writer) { + + return new PropertiesTextWriter(writer); + + } + +} Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/xml/PropertiesXMLParser.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/xml/PropertiesXMLParser.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/xml/PropertiesXMLParser.java 2012-07-26 16:02:36 UTC (rev 6393) @@ -0,0 +1,119 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ +/* +Portions of this code are: + +Copyright Aduna (http://www.aduna-software.com/) � 2001-2007 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +/* + * Created on Jul 25, 2012 + */ +package com.bigdata.rdf.properties.xml; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.Properties; + +import org.apache.commons.io.input.ReaderInputStream; + +import com.bigdata.rdf.properties.PropertiesFormat; +import com.bigdata.rdf.properties.PropertiesParser; + +/** + * An {@link PropertiesParser} for {@link Properties} objects in XML. + * + * @author Bryan THompson + */ +public class PropertiesXMLParser implements PropertiesParser { + + /** + * Returns {@link PropertiesFormat#XML}. + */ + public PropertiesFormat getFormat() { + + return PropertiesFormat.XML; + + } + + @Override + public Properties parse(final InputStream in) throws IOException { + + final Properties p = new Properties(); + + p.loadFromXML(in); + + return p; + + } + + @Override + public Properties parse(final Reader reader) throws IOException { + + final InputStream in = new ReaderInputStream(reader, getFormat() + .getCharset()); + + try { + + final Properties p = new Properties(); + + p.loadFromXML(in); + + return p; + + } finally { + + in.close(); + + } + + } + +} Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/xml/PropertiesXMLParserFactory.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/xml/PropertiesXMLParserFactory.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/properties/xml/PropertiesXMLParserFactory.java 2012-07-26 16:02:36 UTC (rev 6393) @@ -0,0 +1,90 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ +/* +Portions of this code are: + +Copyright Aduna (http://www.aduna-software.com/) � 2001-2007 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT L... [truncated message content] |
From: <tho...@us...> - 2012-07-26 16:31:42
|
Revision: 6395 http://bigdata.svn.sourceforge.net/bigdata/?rev=6395&view=rev Author: thompsonbry Date: 2012-07-26 16:31:31 +0000 (Thu, 26 Jul 2012) Log Message: ----------- AbstractResource#destroy() now passes through a "destroyed" boolean to the resource locator. This is used to clear the read-committed and unisolated views of the resource from the cache. Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/AbstractResource.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/locator/DefaultResourceLocator.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/locator/IResourceLocator.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/store/AbstractTripleStore.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/AbstractResource.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/AbstractResource.java 2012-07-26 16:30:44 UTC (rev 6394) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/AbstractResource.java 2012-07-26 16:31:31 UTC (rev 6395) @@ -694,7 +694,7 @@ namespace); // Clear the entry from the resource locator cache. - indexManager.getResourceLocator().discard(this); + indexManager.getResourceLocator().discard(this, true/* destroyed */); } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/locator/DefaultResourceLocator.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/locator/DefaultResourceLocator.java 2012-07-26 16:30:44 UTC (rev 6394) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/locator/DefaultResourceLocator.java 2012-07-26 16:31:31 UTC (rev 6395) @@ -48,6 +48,7 @@ import com.bigdata.journal.ICommitRecord; import com.bigdata.journal.IIndexManager; import com.bigdata.journal.IIndexStore; +import com.bigdata.journal.ITx; import com.bigdata.journal.Journal; import com.bigdata.journal.TemporaryStore; import com.bigdata.journal.TimestampUtility; @@ -959,18 +960,20 @@ } - public void discard(final ILocatableResource<T> instance) { - + public void discard(final ILocatableResource<T> instance, + final boolean destroyed) { + if (instance == null) throw new IllegalArgumentException(); final String namespace = instance.getNamespace(); - + final long timestamp = instance.getTimestamp(); - + if (log.isInfoEnabled()) { - log.info("namespace=" + namespace + ", timestamp=" + timestamp); + log.info("namespace=" + namespace + ", timestamp=" + timestamp + + ", destroyed=" + destroyed); } @@ -992,7 +995,17 @@ log.info("instance=" + instance + ", found=" + found); } - + + if (destroyed) { + + // Also discard the unisolated view. + resourceCache.remove(new NT(namespace, ITx.UNISOLATED)); + + // Also discard the read-committed view. + resourceCache.remove(new NT(namespace, ITx.READ_COMMITTED)); + + } + } finally { lock.unlock(); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/locator/IResourceLocator.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/locator/IResourceLocator.java 2012-07-26 16:30:44 UTC (rev 6394) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/locator/IResourceLocator.java 2012-07-26 16:31:31 UTC (rev 6395) @@ -76,7 +76,15 @@ * will be returned from the cache and buffered writes on the indices for * those relations (if they are local index objects) will still be visible, * thus defeating the abort semantics. + * + * @param instance + * The instance whose cached references should be discarded. + * @param destroyed + * <code>true</code> iff the resource was destroyed, in which + * case the read-committed and unisolated views must also be + * discarded even if they do not correspond to the + * <i>instance</i>. */ - public void discard(final ILocatableResource<T> instance); + public void discard(final ILocatableResource<T> instance,boolean destroyed); } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/store/AbstractTripleStore.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/store/AbstractTripleStore.java 2012-07-26 16:30:44 UTC (rev 6394) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/store/AbstractTripleStore.java 2012-07-26 16:31:31 UTC (rev 6395) @@ -2014,7 +2014,7 @@ if (lexiconRelation != null) { - locator.discard(lexiconRelation); + locator.discard(lexiconRelation, false/*destroyed*/); lexiconRelation = null; @@ -2022,7 +2022,7 @@ if (spoRelation != null) { - locator.discard(spoRelation); + locator.discard(spoRelation, false/*destroyed*/); spoRelation = null; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2012-07-26 16:33:17
|
Revision: 6396 http://bigdata.svn.sourceforge.net/bigdata/?rev=6396&view=rev Author: thompsonbry Date: 2012-07-26 16:33:04 +0000 (Thu, 26 Jul 2012) Log Message: ----------- I have developed a test suite for the multi-tenancy API. The test suite exercises the ability to create a data set (a KB instance in an unused bigdata namespace), to list the data sets, to obtain the configuration properties for a data set, to issue SPARQL Query and Update requests against the data set, and to destroy the data set. The test suite passes for the embedded jetty deployment. I have done some point tests using a web browser and it appears to also be working in a WAR deployment, but we do not have automated test for the WAR deployment (the testing that I did was sufficient to verify that the servlet context paths in web.xml are correct). @see https://sourceforge.net/apps/trac/bigdata/ticket/575 (Multi-tenancy API) Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFContext.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServlet.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServletContextListener.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataServlet.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/ConnegUtil.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/DeleteServlet.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/NanoSparqlServer.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/QueryServlet.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/SD.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/UpdateServlet.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/client/ConnectOptions.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/client/RemoteRepository.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/AbstractTestNanoSparqlClient.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/ProxyTestCase.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/TestNanoSparqlClient.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/TestNanoSparqlServerWithProxyIndexManager.java branches/BIGDATA_RELEASE_1_2_0/bigdata-war/src/resources/WEB-INF/web.xml branches/BIGDATA_RELEASE_1_2_0/build.xml Added Paths: ----------- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/DatasetNotFoundException.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/MultiTenancyServlet.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/VoID.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/client/HttpException.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/client/RemoteRepositoryManager.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/TestMultiTenancyAPI.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFContext.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFContext.java 2012-07-26 16:31:31 UTC (rev 6395) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFContext.java 2012-07-26 16:33:04 UTC (rev 6396) @@ -22,6 +22,7 @@ */ package com.bigdata.rdf.sail.webapp; +import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; @@ -1100,9 +1101,10 @@ * @param update * <code>true</code> iff this is a SPARQL UPDATE request. * - * @return The task. - * - * @throws MalformedQueryException + * @return The task -or- <code>null</code> if the named data set was not + * found. When <code>null</code> is returned, the + * {@link HttpServletResponse} will also have been committed. + * @throws IOException */ public AbstractQueryTask getQueryTask(// final String namespace,// @@ -1110,15 +1112,28 @@ final String queryStr,// final String acceptOverride,// final HttpServletRequest req,// + final HttpServletResponse resp,// final OutputStream os,// final boolean update// - ) throws MalformedQueryException { + ) throws MalformedQueryException, IOException { /* * Setup the baseURI for this request. It will be set to the requestURI. */ final String baseURI = req.getRequestURL().toString(); + final AbstractTripleStore tripleStore = getTripleStore(namespace, + timestamp); + + if (tripleStore == null) { + /* + * There is no such triple/quad store instance. + */ + BigdataServlet.buildResponse(resp, BigdataServlet.HTTP_NOTFOUND, + BigdataServlet.MIME_TEXT_PLAIN); + return null; + } + if (update) { /* @@ -1129,8 +1144,7 @@ * the query parser. */ final ASTContainer astContainer = new Bigdata2ASTSPARQLParser( - getTripleStore(namespace, timestamp)).parseUpdate2( - queryStr, baseURI); + tripleStore).parseUpdate2(queryStr, baseURI); if (log.isDebugEnabled()) log.debug(astContainer.toString()); @@ -1148,8 +1162,7 @@ * the query parser. */ final ASTContainer astContainer = new Bigdata2ASTSPARQLParser( - getTripleStore(namespace, timestamp)).parseQuery2(queryStr, - baseURI); + tripleStore).parseQuery2(queryStr, baseURI); if (log.isDebugEnabled()) log.debug(astContainer.toString()); @@ -1280,6 +1293,14 @@ final AbstractTripleStore tripleStore = getTripleStore(namespace, timestamp); + if (tripleStore == null) { + + throw new DatasetNotFoundException("Not found: namespace=" + + namespace + ", timestamp=" + + TimestampUtility.toString(timestamp)); + + } + // Wrap with SAIL. final BigdataSail sail = new BigdataSail(tripleStore); @@ -1313,7 +1334,8 @@ * @param timestamp * The timestamp. * - * @throws RepositoryException + * @return The {@link AbstractTripleStore} -or- <code>null</code> if none is + * found for that namespace and timestamp. * * @todo enforce historical query by making sure timestamps conform (we do * not want to allow read/write tx queries unless update semantics are @@ -1324,7 +1346,7 @@ */ public AbstractTripleStore getTripleStore(final String namespace, final long timestamp) { - + // if (timestamp == ITx.UNISOLATED) // throw new IllegalArgumentException("UNISOLATED reads disallowed."); @@ -1332,13 +1354,6 @@ final AbstractTripleStore tripleStore = (AbstractTripleStore) getIndexManager() .getResourceLocator().locate(namespace, timestamp); - if (tripleStore == null) { - - throw new RuntimeException("Not found: namespace=" + namespace - + ", timestamp=" + TimestampUtility.toString(timestamp)); - - } - return tripleStore; } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServlet.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServlet.java 2012-07-26 16:31:31 UTC (rev 6395) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServlet.java 2012-07-26 16:33:04 UTC (rev 6396) @@ -33,14 +33,25 @@ import java.io.PipedOutputStream; import java.io.PrintWriter; import java.io.StringWriter; +import java.util.Iterator; +import java.util.Properties; import javax.servlet.Servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; +import org.openrdf.model.Graph; +import org.openrdf.model.Statement; +import org.openrdf.rio.RDFFormat; +import org.openrdf.rio.RDFHandlerException; +import org.openrdf.rio.RDFWriter; +import org.openrdf.rio.RDFWriterRegistry; import com.bigdata.journal.IAtomicStore; +import com.bigdata.rdf.properties.PropertiesFormat; +import com.bigdata.rdf.properties.PropertiesWriter; +import com.bigdata.rdf.properties.PropertiesWriterRegistry; /** * Abstract base class for {@link Servlet}s which interact with the bigdata RDF @@ -313,5 +324,120 @@ buildResponse(resp, HTTP_OK, MIME_APPLICATION_XML, w.toString()); } + + /** + * Send an RDF Graph as a response using content negotiation. + * + * @param req + * @param resp + */ + protected void sendGraph(final HttpServletRequest req, + final HttpServletResponse resp, final Graph g) throws IOException { + /* + * CONNEG for the MIME type. + */ + { + final String acceptStr = req.getHeader("Accept"); + + final ConnegUtil util = new ConnegUtil(acceptStr); + + // The best RDFFormat for that Accept header. + RDFFormat format = util.getRDFFormat(); + + if (format == null) + format = RDFFormat.RDFXML; + + resp.setStatus(HTTP_OK); + + resp.setContentType(format.getDefaultMIMEType()); + + final OutputStream os = resp.getOutputStream(); + try { + final RDFWriter writer = RDFWriterRegistry.getInstance() + .get(format).getWriter(os); + writer.startRDF(); + final Iterator<Statement> itr = g.iterator(); + while (itr.hasNext()) { + final Statement stmt = itr.next(); + writer.handleStatement(stmt); + } + writer.endRDF(); + os.flush(); + } catch (RDFHandlerException e) { + log.error(e, e); + throw launderThrowable(e, resp, ""); + } finally { + os.close(); + } + } + } + + /** + * Send a properties file as a response using content negotiation. + * + * @param req + * @param resp + */ + protected void sendProperties(final HttpServletRequest req, + final HttpServletResponse resp, final Properties properties) + throws IOException { + /* + * CONNEG for the MIME type. + */ + { + + final String acceptStr = req.getHeader("Accept"); + + final ConnegUtil util = new ConnegUtil(acceptStr); + + // The best format for that Accept header. + PropertiesFormat format = util.getPropertiesFormat(); + + if (format == null) + format = PropertiesFormat.XML; + + resp.setStatus(HTTP_OK); + + resp.setContentType(format.getDefaultMIMEType()); + + final OutputStream os = resp.getOutputStream(); + try { + final PropertiesWriter writer = PropertiesWriterRegistry.getInstance() + .get(format).getWriter(os); + writer.write(properties); + os.flush(); + } catch (IOException e) { + log.error(e, e); + throw launderThrowable(e, resp, ""); + } finally { + os.close(); + } + } + } + + /** + * Return <code>true</code> if the <code>Content-disposition</code> header + * should be set to indicate that the response body should be handled as an + * attachment rather than presented inline. This is just a hint to the user + * agent. How the user agent handles this hint is up to it. + * + * @param mimeType + * The mime type. + * + * @return <code>true</code> if it should be handled as an attachment. + */ + protected static boolean isAttachment(final String mimeType) { + if(mimeType.equals(MIME_TEXT_PLAIN)) { + return false; + } else if(mimeType.equals(MIME_SPARQL_RESULTS_XML)) { + return false; + } else if(mimeType.equals(MIME_SPARQL_RESULTS_JSON)) { + return false; + } else if(mimeType.equals(MIME_APPLICATION_XML)) { + return false; + } + return true; + } + } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServletContextListener.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServletContextListener.java 2012-07-26 16:31:31 UTC (rev 6395) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServletContextListener.java 2012-07-26 16:33:04 UTC (rev 6396) @@ -301,6 +301,12 @@ } + /* + * FIXME We should figure out a default serviceURI here but prefer one + * configured in web.xml. That will be the "official" URI reported out + * for ServiceDescription and VoID. + */ + final SparqlEndpointConfig config = new SparqlEndpointConfig(namespace, timestamp, queryThreadPoolSize, describeEachNamedGraph); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataServlet.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataServlet.java 2012-07-26 16:31:31 UTC (rev 6395) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataServlet.java 2012-07-26 16:33:04 UTC (rev 6396) @@ -99,6 +99,9 @@ MIME_TEXT_PLAIN = "text/plain", MIME_TEXT_HTML = "text/html", // MIME_TEXT_XML = "text/xml", + /** + * General purpose binary <code>application/octet-stream</code>. + */ MIME_DEFAULT_BINARY = "application/octet-stream", MIME_APPLICATION_XML = "application/xml", MIME_TEXT_JAVASCRIPT = "text/javascript", @@ -138,7 +141,7 @@ // // } - static protected void buildResponse(final HttpServletResponse resp, + static public void buildResponse(final HttpServletResponse resp, final int status, final String mimeType) throws IOException { resp.setStatus(status); @@ -147,7 +150,7 @@ } - static protected void buildResponse(final HttpServletResponse resp, final int status, + static public void buildResponse(final HttpServletResponse resp, final int status, final String mimeType, final String content) throws IOException { buildResponse(resp, status, mimeType); @@ -249,25 +252,4 @@ } - /** - * Figure out and return the service end point. - */ - protected String getServiceURI(final HttpServletRequest req) { - - final String serviceURI; - - final StringBuffer sb = req.getRequestURL(); - - final int indexOf = sb.indexOf("?"); - - if (indexOf == -1) { - serviceURI = sb.toString(); - } else { - serviceURI = sb.substring(0, indexOf); - } - - return serviceURI; - - } - } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/ConnegUtil.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/ConnegUtil.java 2012-07-26 16:31:31 UTC (rev 6395) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/ConnegUtil.java 2012-07-26 16:33:04 UTC (rev 6396) @@ -27,6 +27,7 @@ package com.bigdata.rdf.sail.webapp; + import java.util.Arrays; import java.util.LinkedList; import java.util.List; @@ -37,7 +38,9 @@ import org.openrdf.query.resultio.TupleQueryResultFormat; import org.openrdf.rio.RDFFormat; +import com.bigdata.rdf.properties.PropertiesFormat; + /** * Helper class for content negotiation. * @@ -55,10 +58,6 @@ private final ConnegScore<?>[] scores; - // private final RDFFormat rdfFormat; - // - // private final TupleQueryResultFormat tupleQueryResultFormat; - /** * * @param acceptStr @@ -122,6 +121,21 @@ } + // PropertiesFormat + { + + final PropertiesFormat format = PropertiesFormat + .forMIMEType(t.getMimeType()); + + if (format != null) { + + scores.add(new ConnegScore<PropertiesFormat>(t.q, + format)); + + } + + } + } } @@ -260,6 +274,46 @@ } /** + * Return the best {@link PropertiesFormat} from the <code>Accept</code> + * header, where "best" is measured by the <code>q</code> parameter. + * + * @return The best {@link PropertiesFormat} -or- <code>null</code> if no + * {@link PropertiesFormat} was requested. + */ + public PropertiesFormat getPropertiesFormat() { + + return getPropertiesFormat(null/* fallback */); + + } + + /** + * Return the best {@link PropertiesFormat} from the <code>Accept</code> + * header, where "best" is measured by the <code>q</code> parameter. + * + * @param fallback + * The caller's default, which is returned if no match was + * specified. + * + * @return The best {@link PropertiesFormat} -or- <i>fallback</i> if no + * {@link PropertiesFormat} was requested. + */ + public PropertiesFormat getPropertiesFormat(final PropertiesFormat fallback) { + + for (ConnegScore<?> s : scores) { + + if (s.format instanceof PropertiesFormat) { + + return (PropertiesFormat) s.format; + + } + + } + + return fallback; + + } + + /** * Return an ordered list of the {@link ConnegScore}s for MIME Types which * are consistent with the desired format type. * Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/DatasetNotFoundException.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/DatasetNotFoundException.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/DatasetNotFoundException.java 2012-07-26 16:33:04 UTC (rev 6396) @@ -0,0 +1,54 @@ +/** +Copyright (C) SYSTAP, LLC 2006-2007. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ +package com.bigdata.rdf.sail.webapp; + +import org.openrdf.repository.RepositoryException; + +/** + * Exception thrown when a named data set is addressed and does not exist. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ +public class DatasetNotFoundException extends RepositoryException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public DatasetNotFoundException() { + } + + public DatasetNotFoundException(String message) { + super(message); + } + + public DatasetNotFoundException(Throwable cause) { + super(cause); + } + + public DatasetNotFoundException(String message, Throwable cause) { + super(message, cause); + } + +} Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/DeleteServlet.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/DeleteServlet.java 2012-07-26 16:31:31 UTC (rev 6395) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/DeleteServlet.java 2012-07-26 16:33:04 UTC (rev 6396) @@ -132,8 +132,13 @@ final AbstractQueryTask queryTask = getBigdataRDFContext() .getQueryTask(namespace, ITx.READ_COMMITTED, queryStr, format.getDefaultMIMEType(), - req, os, false/*update*/); + req, resp, os, false/*update*/); + if(queryTask == null) { + // KB not found. Response already committed. + return; + } + switch (queryTask.queryType) { case DESCRIBE: case CONSTRUCT: Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/MultiTenancyServlet.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/MultiTenancyServlet.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/MultiTenancyServlet.java 2012-07-26 16:33:04 UTC (rev 6396) @@ -0,0 +1,534 @@ +/** +Copyright (C) SYSTAP, LLC 2006-2007. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ +package com.bigdata.rdf.sail.webapp; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.openrdf.model.BNode; +import org.openrdf.model.Graph; +import org.openrdf.model.impl.GraphImpl; + +import com.bigdata.journal.IIndexManager; +import com.bigdata.journal.ITx; +import com.bigdata.journal.Journal; +import com.bigdata.rdf.properties.PropertiesFormat; +import com.bigdata.rdf.properties.PropertiesParser; +import com.bigdata.rdf.properties.PropertiesParserFactory; +import com.bigdata.rdf.properties.PropertiesParserRegistry; +import com.bigdata.rdf.sail.BigdataSail; +import com.bigdata.rdf.sail.BigdataSail.BigdataSailConnection; +import com.bigdata.rdf.store.AbstractTripleStore; +import com.bigdata.rdf.store.ScaleOutTripleStore; +import com.bigdata.service.IBigdataFederation; +import com.bigdata.service.jini.JiniFederation; +import com.bigdata.util.PropertyUtil; + +/** + * Mult-tenancy Administration Servlet (management for bigdata namespaces). A + * bigdata namespace corresponds to a partition in the naming of durable + * resources. A {@link Journal} or {@link IBigdataFederation} may have multiple + * KB instances, each in their own namespace. This servlet allows you to manage + * those KB instances using CRUD operations. + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/575"> + * NanoSparqlServer Admin API for Multi-tenant deployments</a> + * + * @author thompsonbry + */ +public class MultiTenancyServlet extends BigdataRDFServlet { + + /** + * + */ + private static final long serialVersionUID = 1L; + + static private final transient Logger log = Logger.getLogger(MultiTenancyServlet.class); + + /** + * Delegate for the sparql end point expressed by + * <code>.../namespace/NAMESPACE/sparql</code>. + */ + private RESTServlet m_restServlet; + + public MultiTenancyServlet() { + + } + + /** + * Overridden to create and initialize the delegate {@link Servlet} + * instances. + */ + @Override + public void init() throws ServletException { + + super.init(); + + m_restServlet = new RESTServlet(); + + m_restServlet.init(getServletConfig()); + + } + + /** + * Handle namespace create. + */ + @Override + protected void doPost(final HttpServletRequest req, + final HttpServletResponse resp) throws IOException { + + if (req.getRequestURI().endsWith("/namespace")) { + + doCreateNamespace(req, resp); + + return; + + } + + // Pass through to the SPARQL end point REST API. + m_restServlet.doPost(req, resp); + + } + + /** + * Delete the KB associated with the effective namespace. + */ + @Override + protected void doDelete(final HttpServletRequest req, + final HttpServletResponse resp) throws IOException { + + final String namespace = getNamespace(req); + + if (req.getRequestURI().endsWith("/namespace/" + namespace)) { + + // Delete that namespace. + doDeleteNamespace(req, resp); + + return; + + } + + // Pass through to the SPARQL end point REST API. + m_restServlet.doDelete(req, resp); + + } + + @Override + protected void doPut(final HttpServletRequest req, + final HttpServletResponse resp) throws IOException { + + // Pass through to the SPARQL end point REST API. + m_restServlet.doPut(req, resp); + + } + + /** + * Handles all read-only namespace oriented administration requests. + */ + @Override + protected void doGet(final HttpServletRequest req, + final HttpServletResponse resp) throws IOException { + + if (req.getRequestURI().endsWith("/namespace")) { + + // Describe all namespaces. + + doDescribeNamespaces(req, resp); + + return; + + } else if (req.getRequestURI().endsWith("/properties")) { + + // Show properties. + + doShowProperties(req, resp); + + return; + + } + + // Pass through to the SPARQL end point REST API. + m_restServlet.doGet(req, resp); + + return; + + } + + /** + * Create a new namespace. + * + * <pre> + * Request-URI + * ... + * Content-Type=... + * ... + * PropertySet + * </pre> + * + * @param req + * @param resp + * @throws IOException + */ + private void doCreateNamespace(final HttpServletRequest req, + final HttpServletResponse resp) throws IOException { + + final BigdataRDFContext context = getBigdataRDFContext(); + + final IIndexManager indexManager = context.getIndexManager(); + + /* + * 1. Read the request entity, which must be some kind of Properties + * object. The BigdataSail.Options.NAMESPACE property defaults to "kb". + * A non-default value SHOULD be specified by the client. + * + * 2. Wrap and flatten the base properties for the Journal or + * Federation. This provides defaults for properties which were not + * explicitly configured for this KB instance. + * + * 3. Add the given properties to the flattened defaults to obtain the + * effective properties. + */ + final Properties given, defaults, effective; + { + + final String contentType = req.getContentType(); + + if (log.isInfoEnabled()) + log.info("Request body: " + contentType); + + final PropertiesFormat format = PropertiesFormat.forMIMEType(contentType); + + if (format == null) { + + buildResponse(resp, HTTP_BADREQUEST, MIME_TEXT_PLAIN, + "Content-Type not recognized as Properties: " + + contentType); + + return; + + } + + if (log.isInfoEnabled()) + log.info("Format=" + format); + + final PropertiesParserFactory parserFactory = PropertiesParserRegistry + .getInstance().get(format); + + if (parserFactory == null) { + + buildResponse(resp, HTTP_INTERNALERROR, MIME_TEXT_PLAIN, + "Parser factory not found: Content-Type=" + + contentType + ", format=" + format); + + return; + + } + + /* + * There is a request body, so let's try and parse it. + */ + + final PropertiesParser parser = parserFactory.getParser(); + + // The given Properties. + given = parser.parse(req.getInputStream()); + + /* + * Get the default Properties. + */ + if (indexManager instanceof Journal) { + + final Journal jnl = (Journal) indexManager; + + defaults = new Properties(jnl.getProperties()); + + } else { + + final JiniFederation<?> fed = (JiniFederation<?>) indexManager; + + defaults = fed.getClient().getProperties(); + + } + + /* + * Produce the effective properties. + */ + { + + effective = PropertyUtil.flatCopy(defaults); + + for (Map.Entry<Object, Object> e : given.entrySet()) { + + final String name = (String) e.getKey(); + + final Object val = e.getValue(); + + if (val != null) { + + // Note: Hashtable does not allow nulls. + effective.put(name, val); + + } + + } + + } + + } + + // The effective namespace for the new KB. + final String namespace = effective.getProperty( + BigdataSail.Options.NAMESPACE, + BigdataSail.Options.DEFAULT_NAMESPACE); + + final long timestamp = ITx.UNISOLATED; + + // resolve the namespace. + final AbstractTripleStore tripleStore = (AbstractTripleStore) getIndexManager() + .getResourceLocator().locate(namespace, timestamp); + + if (tripleStore != null) { + /* + * Already exists. + */ + buildResponse(resp, HTTP_BADREQUEST, MIME_TEXT_PLAIN, "EXISTS: " + + namespace); + return; + } + + try { + + if (indexManager instanceof Journal) { + + /* + * Create a local triple store. + * + * Note: This hands over the logic to some custom code located + * on the BigdataSail. + */ + + final Journal jnl = (Journal) indexManager; + + // create the appropriate as configured triple/quad store. + BigdataSail.createLTS(jnl, effective); + + } else { + + /* + * Register triple store for scale-out. + * + * TODO Review guidance for creation of KBs on a cluster. + */ + + final ScaleOutTripleStore ts = new ScaleOutTripleStore( + indexManager, namespace, ITx.UNISOLATED, effective); + + ts.create(); + + } + + buildResponse(resp, HTTP_OK, MIME_TEXT_PLAIN, "CREATED: " + + namespace); + + } catch (Throwable e) { + + log.error(e, e); + + throw launderThrowable(e, resp, ""); + + } + + } + + /** + * Delete an existing namespace. + * + * @param req + * @param resp + * @throws IOException + */ + private void doDeleteNamespace(final HttpServletRequest req, + final HttpServletResponse resp) throws IOException { + + final String namespace = getNamespace(req); + + final long timestamp = ITx.UNISOLATED; + + final AbstractTripleStore tripleStore = getBigdataRDFContext() + .getTripleStore(namespace, timestamp); + + if (tripleStore == null) { + /* + * There is no such triple/quad store instance. + */ + buildResponse(resp, HTTP_NOTFOUND, MIME_TEXT_PLAIN); + return; + } + + try { + + final BigdataSail sail = new BigdataSail(tripleStore); + + BigdataSailConnection con = null; + + try { + + sail.initialize(); + // This basically puts a lock on the KB instance. + con = sail.getUnisolatedConnection(); + // Destroy the KB instance. + tripleStore.destroy(); + // Commit. + con.commit(); + + } finally { + + if (con != null) + con.close(); + + sail.shutDown(); + + } + + buildResponse(resp, HTTP_OK, MIME_TEXT_PLAIN, "DELETED: " + + namespace); + + } catch (Throwable e) { + + log.error(e, e); + + throw launderThrowable(e, resp, ""); + + } + + } + + /** + * Send the configuration properties for the addressed KB instance. + * + * @param req + * @param resp + * @throws IOException + */ + private void doShowProperties(final HttpServletRequest req, + final HttpServletResponse resp) throws IOException { + + final String namespace = getNamespace(req); + + final long timestamp = getTimestamp(req); + + final AbstractTripleStore tripleStore = getBigdataRDFContext() + .getTripleStore(namespace, timestamp); + + if (tripleStore == null) { + /* + * There is no such triple/quad store instance. + */ + buildResponse(resp, HTTP_NOTFOUND, MIME_TEXT_PLAIN); + return; + } + + final Properties properties = PropertyUtil.flatCopy(tripleStore + .getProperties()); + + sendProperties(req, resp, properties); + + } + + /** + * Generate a VoID Description for the known namespaces. + */ + private void doDescribeNamespaces(final HttpServletRequest req, + final HttpServletResponse resp) throws IOException { + + /* + * The set of registered namespaces for KBs. + */ + final List<String> namespaces = getBigdataRDFContext() + .getNamespaces(); + + final Graph g = new GraphImpl(); + + for(String namespace : namespaces) { + + // Get a view onto that KB instance. + final AbstractTripleStore tripleStore = getBigdataRDFContext() + .getTripleStore(namespace, ITx.READ_COMMITTED); + + if (tripleStore == null) { + + /* + * There is no such triple/quad store instance (could be a + * concurrent delete of the namespace). + */ + + continue; + + } + + final BNode aDataSet = g.getValueFactory().createBNode(); + + /* + * Figure out the service end point. + * + * FIXME This needs to be an explicitly configured (or intelligently + * defaulted) URL in order for us to get the actual deployment URL + * correct in the generated VoID description. See NanoSparqlServer, + * web.xml, QueryServlet.doServiceDescription(), and + * BigdataRDFServletContext. + */ + final String serviceURI; + { + + final StringBuffer sb = req.getRequestURL(); + + final int indexOf = sb.indexOf("?"); + + if (indexOf == -1) { + serviceURI = sb.toString(); + } else { + serviceURI = sb.substring(0, indexOf); + } + + } + + final VoID v = new VoID(g, tripleStore, serviceURI, aDataSet); + + v.describeDataSet(false/* describeStatistics */, + getBigdataRDFContext().getConfig().describeEachNamedGraph); + + } + + sendGraph(req, resp, g); + + } + +} Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/NanoSparqlServer.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/NanoSparqlServer.java 2012-07-26 16:31:31 UTC (rev 6395) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/NanoSparqlServer.java 2012-07-26 16:33:04 UTC (rev 6396) @@ -30,10 +30,12 @@ import org.apache.log4j.Logger; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.server.handler.ResourceHandler; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.webapp.WebAppContext; import org.openrdf.rio.RDFParser; import com.bigdata.Banner; @@ -275,11 +277,23 @@ Long.toString(readLock)); } + // Create the service. final Server server = NanoSparqlServer.newInstance(port, propertyFile, initParams); + // Start the service. server.start(); + /* + * Report the effective URL of this service. + * + * TODO This is only the effective local URL (and only one of them, and + * even then only one for the first connector). It does not reflect any + * knowledge about the desired external deployment URL for the service + * end point. That should probably be directly configured so it can be + * exposed correctly for VoID and ServiceDescription responses. + */ + final String serviceURL; { final int actualPort = server.getConnectors()[0].getLocalPort(); @@ -293,13 +307,14 @@ } - final String serviceURL = new URL("http", hostAddr, actualPort, ""/* file */) + serviceURL = new URL("http", hostAddr, actualPort, ""/* file */) .toExternalForm(); System.out.println("serviceURL: " + serviceURL); } + // Wait for the service to terminate. server.join(); } @@ -317,6 +332,9 @@ * by {@link ConfigParams}. * * @return The server instance. + * + * @see <a href="http://wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty"> + * Embedding Jetty </a> */ static public Server newInstance(final int port, final IIndexManager indexManager, @@ -363,23 +381,50 @@ * by {@link ConfigParams}. * * @return The server instance. + * + * @see <a href="http://wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty"> + * Embedding Jetty </a> */ static public Server newInstance(final int port, final String propertyFile, final Map<String, String> initParams) { final Server server = new Server(port); - final ServletContextHandler context = getContextHandler(server,initParams); - + final ServletContextHandler context = getContextHandler(server, + initParams); + final HandlerList handlers = new HandlerList(); + /* TODO The webappHandler should be able to handle this also if + * we put the JSP pages into the top-level directory. + */ final ResourceHandler resourceHandler = new ResourceHandler(); setupStaticResources(server, resourceHandler); - + + /** + * FIXME The WebAppContext is resulting in a + * "JSP Support not Configured" message (500 status code). Try this + * using the JSPServlet instead and/or in addition. + * + * FIXME Also support this in the alternative newInstance() method + * above. + * + * @see <a + * href="http://thinking.awirtz.com/2011/11/03/embedded-jetty-servlets-and-jsp/"> + * embedded jetty servlets and jsp </a> + */ +//// final URL warUrl = this.class.getClassLoader().getResource(WEBAPPDIR); +//// final String warUrlString = warUrl.toExternalForm(); +//// final WebAppContext webappHandler = new WebAppContext(warUrlString, CONTEXTPATH); +// final URL warUrl = getStaticResourceURL(server, "jsp"/* path */); +// final WebAppContext webappHandler = new WebAppContext( +// warUrl.toExternalForm(), "/jsp"); + handlers.setHandlers(new Handler[] { context,// resourceHandler,// +// webappHandler, // new DefaultHandler()// }); @@ -391,6 +436,9 @@ /** * Construct a {@link ServletContextHandler}. + * <p> + * Note: The {@link ContextHandler} uses the longest prefix of the request + * URI (the contextPath) to select a specific {@link Handler}. * * @param initParams * The init parameters, per the web.xml definition. @@ -404,7 +452,8 @@ final ServletContextHandler context = new ServletContextHandler( ServletContextHandler.NO_SECURITY - | ServletContextHandler.NO_SESSIONS); +// | ServletContextHandler.NO_SESSIONS + ); // /* // * Setup resolution for the static web app resources (index.html). @@ -436,6 +485,24 @@ // Core RDF REST API, including SPARQL query and update. context.addServlet(new ServletHolder(new RESTServlet()), "/sparql/*"); + // Multi-Tenancy API. + context.addServlet(new ServletHolder(new MultiTenancyServlet()), + "/namespace/*"); + + /** + * Note: JSP pages for the servlet 2.5 specification add the following + * dependencies: + * + * <pre> + * ant-1.6.5.jar + * core-3.1.1.jar + * jsp-2.1.jar + * jsp-api-2.1.jar + * </pre> + * + * @see http://docs.codehaus.org/display/JETTY/Embedding+Jetty + */ + // context.setResourceBase("bigdata-war/src/html"); // // context.setWelcomeFiles(new String[]{"index.html"}); @@ -455,7 +522,7 @@ private static void setupStaticResources(final Server server, final ServletContextHandler context) { - final URL url = getStaticResourceURL(server); + final URL url = getStaticResourceURL(server, "html"); if(url != null) { @@ -482,7 +549,7 @@ context.setDirectoriesListed(false); // Nope! - final URL url = getStaticResourceURL(server); + final URL url = getStaticResourceURL(server, "html"); if(url != null) { @@ -520,32 +587,33 @@ * * @see https://sourceforge.net/apps/trac/bigdata/ticket/330 */ - private static URL getStaticResourceURL(final Server server) { + private static URL getStaticResourceURL(final Server server, final String path) { /* * This is the resource path in the JAR. */ - final String WEB_DIR_JAR = "bigdata-war/src/html"; + final String WEB_DIR_JAR = "bigdata-war/src" + + (path == null ? "" : "/" + path); /* * This is the resource path in the IDE when NOT using the JAR. * * Note: You MUST have "bigdata-war/src" on the build path for the IDE. */ - final String WEB_DIR_IDE = "html"; + final String WEB_DIR_IDE = path; // "html"; URL url = server.getClass().getClassLoader().getResource(WEB_DIR_JAR); - if (url == null) { + if (url == null && path != null) { - url = server.getClass().getClassLoader().getResource("html"); + url = server.getClass().getClassLoader().getResource(path);// "html"); } if (url == null) { - log.error("Could not locate: " + WEB_DIR_JAR + " -or- " - + WEB_DIR_IDE); + log.error("Could not locate: " + WEB_DIR_JAR + ", " + WEB_DIR_IDE + + ", -or- " + path); } return url; Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/QueryServlet.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/QueryServlet.java 2012-07-26 16:31:31 UTC (rev 6395) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/QueryServlet.java 2012-07-26 16:33:04 UTC (rev 6396) @@ -44,15 +44,10 @@ import org.apache.log4j.Logger; import org.openrdf.model.Graph; import org.openrdf.model.Resource; -import org.openrdf.model.Statement; import org.openrdf.model.URI; import org.openrdf.model.Value; import org.openrdf.model.impl.GraphImpl; import org.openrdf.query.MalformedQueryException; -import org.openrdf.rio.RDFFormat; -import org.openrdf.rio.RDFHandlerException; -import org.openrdf.rio.RDFWriter; -import org.openrdf.rio.RDFWriterRegistry; import com.bigdata.bop.BOpUtility; import com.bigdata.bop.PipelineOp; @@ -176,93 +171,52 @@ return; } - // Figure out the service end point. - final String serviceURI = getServiceURI(req); - /* - * TODO Resolve the SD class name and ctor via a configuration property - * for extensible descriptions. + * Figure out the service end point. + * + * Note: This code to figure out the service end point is a hack. It + * tends to work for the special case of ServiceDescription because + * there is an identity between the request URL and the service end + * point in this special case. */ - final Graph g = new GraphImpl(); + + final String serviceURI; { + + final StringBuffer sb = req.getRequestURL(); - final SD sd = new SD(g, tripleStore, serviceURI); + final int indexOf = sb.indexOf("?"); - sd.describeService(getBigdataRDFContext().getConfig().describeEachNamedGraph); + if (indexOf == -1) { + serviceURI = sb.toString(); + } else { + serviceURI = sb.substring(0, indexOf); + } } /* - * CONNEG for the MIME type. - * - * Note: An attempt to CONNEG for a MIME type which can not be used with - * a give type of query will result in a response using a default MIME - * Type for that query. - * - * TODO We could also do RDFa embedded in XHTML. + * TODO Resolve the SD class name and ctor via a configuration property + * for extensible descriptions. */ + final Graph g = new GraphImpl(); { - final String acceptStr = req.getHeader("Accept"); + final SD sd = new SD(g, tripleStore, serviceURI); - final ConnegUtil util = new ConnegUtil(acceptStr); + final SparqlEndpointConfig config = getBigdataRDFContext() + .getConfig(); - // The best RDFFormat for that Accept header. - RDFFormat format = util.getRDFFormat(); - - if (format == null) - format = RDFFormat.RDFXML; + sd.describeService(true/* describeStatistics */, + config.describeEachNamedGraph); - resp.setStatus(HTTP_OK); + } - resp.setContentType(format.getDefaultMIMEType()); + sendGraph(req, resp, g); - final OutputStream os = resp.getOutputStream(); - try { - final RDFWriter writer = RDFWriterRegistry.getInstance() - .get(format).getWriter(os); - writer.startRDF(); - final Iterator<Statement> itr = g.iterator(); - while (itr.hasNext()) { - final Statement stmt = itr.next(); - writer.handleStatement(stmt); - } - writer.endRDF(); - os.flush(); - } catch (RDFHandlerException e) { - log.error(e, e); - throw launderThrowable(e, resp, ""); - } finally { - os.close(); - } - } } /** - * Return <code>true</code> if the <code>Content-disposition</code> header - * should be set to indicate that the response body should be handled as an - * attachment rather than presented inline. This is just a hint to the user - * agent. How the user agent handles this hint is up to it. - * - * @param mimeType - * The mime type. - * - * @return <code>true</code> if it should be handled as an attachment. - */ - private boolean isAttachment(final String mimeType) { - if(mimeType.equals(MIME_TEXT_PLAIN)) { - return false; - } else if(mimeType.equals(MIME_SPARQL_RESULTS_XML)) { - return false; - } else if(mimeType.equals(MIME_SPARQL_RESULTS_JSON)) { - return false; - } else if(mimeType.equals(MIME_APPLICATION_XML)) { - return false; - } - return true; - } - - /** * Handles SPARQL UPDATE. * * <pre> @@ -314,13 +268,21 @@ final UpdateTask updateTask; try { + /* * Attempt to construct a task which we can use to evaluate the * query. */ + updateTask = (UpdateTask) context.getQueryTask(namespace, timestamp, updateStr, null/* acceptOverride */, req, - os, true/* update */); + resp, os, true/* update */); + + if(updateTask == null) { + // KB not found. Response already committed. + return; + } + } catch (MalformedQueryException ex) { /* * Send back a BAD REQUEST (400) along with the text of the @@ -464,13 +426,21 @@ final AbstractQueryTask queryTask; try { + /* * Attempt to construct a task which we can use to evaluate the * query. */ - queryTask = context - .getQueryTask(namespace, timestamp, queryStr, - null/* acceptOverride */, req, os, false/* update */); + + queryTask = context.getQueryTask(namespace, timestamp, + queryStr, null/* acceptOverride */, req, resp, os, + false/* update */); + + if(queryTask == null) { + // KB not found. Response already committed. + return; + } + } catch (MalformedQueryException ex) { /* * Send back a BAD REQUEST (400) along with the text of the Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/SD.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/SD.java 2012-07-26 16:31:31 UTC (rev 6395) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/SD.java 2012-07-26 16:33:04 UTC (rev 6396) @@ -27,18 +27,10 @@ package com.bigdata.rdf.sail.webapp; -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; import java.util.Properties; -import java.util.Set; import org.openrdf.model.BNode; import org.openrdf.model.Graph; -import org.openrdf.model.Resource; import org.openrdf.model.URI; import org.openrdf.model.ValueFactory; import org.openrdf.model.impl.URIImpl; @@ -48,20 +40,10 @@ import com.bigdata.rdf.axioms.NoAxioms; import com.bigdata.rdf.axioms.OwlAxioms; import com.bigdata.rdf.axioms.RdfsAxioms; -import com.bigdata.rdf.internal.IV; -import com.bigdata.rdf.internal.NotMaterializedException; -import com.bigdata.rdf.model.BigdataResource; -import com.bigdata.rdf.model.BigdataURI; -import com.bigdata.rdf.model.BigdataValue; import com.bigdata.rdf.sail.BigdataSail; -import com.bigdata.rdf.spo.SPOKeyOrder; -import com.bigdata.rdf.spo.SPORelation; import com.bigdata.rdf.store.AbstractTripleStore; import com.bigdata.rdf.store.BD; -import com.bigdata.rdf.store.BigdataValueIterator; -import com.bigdata.rdf.store.BigdataValueIteratorImpl; import com.bigdata.rdf.vocab.decls.VoidVocabularyDecl; -import com.bigdata.striterator.IChunkedIterator; /** * SPARQL 1.1 Service Description vocabulary class. @@ -176,6 +158,13 @@ + "KB/IsolatableIndices"); /** + * The <code>namespace</code> for this KB instance as configured by the + * {@link BigdataSail.Options#NAMESPACE} property. + */ + static public final URI KB_NAMESPACE = new URIImpl(BDFNS + + "KB/Namespace"); + + /** * <pre> * http://www.w3.org/ns/entailment/OWL-RDF-Based * http://www.w3.org/ns/entailment/RDFS @@ -241,24 +230,12 @@ static public final URI NamedGraph = new URIImpl(NS + "NamedGraph"); static public final URI name = new URIImpl(NS + "name"); - /** - * TODO Move VOID vocabulary to its own class. - * - * <pre> - * <sd:Graph> - * <void:triples rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">100</void:triples> - * </sd:Graph> - * </pre> - */ - static public final String NS_VOID = "http://rdfs.org/ns/void#"; - /* * RDF data * * TODO RDFa: http://www.w3.org/ns/formats/RDFa */ - /** * Unique URI for RDF/XML * @@ -405,11 +382,11 @@ */ protected final BNode aDefaultDataset; - /** - * The resource which models the default graph in the default data set for - * the service. - */ - protected final BNode aDefaultGraph; +// /** +// * The resource which models the default graph in the default data set for +// * the service. +// */ +// protected final BNode aDefaultGraph; /** * @@ -446,20 +423,24 @@ aDefaultDataset = f.createBNode("defaultDataset"); - aDefaultGraph = f.createBNode("defaultGraph"); - } /** * Collect various information, building up a service description graph. * + * @param describeStatistics + * When <code>true</code>, the VoID description will include the + * {@link VoidVocabularyDecl#vocabulary} declarations, the + * property partition statistics, and the class partition + * statistics. * @param describeNamedGraphs * When <code>true</code> and the KB instance is in the * <code>quads</code> mode, each named graph will also be * described in in the same level of detail as the default graph. * Otherwise only the default graph will be described. */ - public void describeService(final boolean describeNamedGraphs) { + public void describeService(final boolean describeStatistics, + final boolean describeNamedGraphs) { g.add(aService, RDF.TYPE, SD.Service); @@ -479,9 +460,20 @@ // Describe the entailment regime (if any). describeEntailmentRegime(); - // Describe the default graph of the default data set. - describeDefaultDataSet(describeNamedGraphs); + // Describe the data set for this KB instance. + { + + // Default data set + g.add(aService, SD.defaultDataset, aDefaultDataset); + g.add(aDefaultDataset, RDF.TYPE, SD.Dataset); + + final VoID v = new VoID(g, tripleStore, serviceURI, aDefaultDataset); + + v.describeDataSet(describeStatistics, describeNamedGraphs); + + } + } /** @@ -565,12 +557,15 @@ /** * Describe non-language features. + * <p> + * Note: Do NOT report the backing store type (Journal, TemporaryStore, + * Federation), the journal buffer mode, etc. here. That is all back end + * stuff and should be visible through an API which can be separately + * secured. The ServiceDescription is supposed to be "web" facing so it + * should not have that low level stuff. * * TODO sd:languageExtension or sd:feature could be used for query hints, * NAMED SUBQUERY, the NSS REST API features, etc. - * - * TODO Report the backing store type (Journal, TemporaryStore, Federation) - * and the journal buffer mode. */ protected void describeOtherFeatures() { @@ -604,9 +599,6 @@ } - // TODO Report when justification chains are being tracked? -// if(tripleStore.isJustify()) - final Properties properties = tripleStore.getProperties(); if (Boolean.valueOf(properties.getProperty( @@ -625,12 +617,6 @@ } - /* - * TODO Report properties from the BigdataSail - * - * NAMESPACE? - */ - } /** @@ -661,638 +647,4 @@ } - /** - * Describe the default data set. - * - * @param describeNamedGraph - * When <code>true</code>, each named graph will also... [truncated message content] |
From: <tho...@us...> - 2012-07-27 13:43:54
|
Revision: 6397 http://bigdata.svn.sourceforge.net/bigdata/?rev=6397&view=rev Author: thompsonbry Date: 2012-07-27 13:43:48 +0000 (Fri, 27 Jul 2012) Log Message: ----------- Modified InnerCause to examine the root causes of an ExecutionExceptions class. This class can have multiple root causes. They are now searched. Modified the test suite for TestRuleOwlFunctionalProperty to use InnerCause rather than custom code. Modified BigdataRDFServlet to use InnerCause to look for a ConstraintViolationException and report the request as a BAD_REQUEST rather than an SERVER ERROR. Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/util/InnerCause.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/rules/TestRuleOwlFunctionalProperty.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServlet.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/CountersServlet.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/util/InnerCause.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/util/InnerCause.java 2012-07-26 16:33:04 UTC (rev 6396) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/util/InnerCause.java 2012-07-27 13:43:48 UTC (rev 6397) @@ -66,6 +66,20 @@ { Class x = t.getClass(); + + // Check for Iterable<Throwable> + if(Iterable.class.isAssignableFrom(x)) { + for (Object o : (Iterable) t) { + if (!(o instanceof Throwable)) { + continue; + } + final Throwable tx = getInnerCause((Throwable) o, cls); + if (tx != null) + return tx; + } + } + + // Check the class hierarchy. while(x != null){ if( x == cls) return t; @@ -73,7 +87,8 @@ } } - + + // Check the nested cause. t = t.getCause(); if (t == null) Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/rules/TestRuleOwlFunctionalProperty.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/rules/TestRuleOwlFunctionalProperty.java 2012-07-26 16:33:04 UTC (rev 6396) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/rules/TestRuleOwlFunctionalProperty.java 2012-07-27 13:43:48 UTC (rev 6397) @@ -121,16 +121,21 @@ } catch (Exception ex) { - final ExecutionExceptions ex2 = (ExecutionExceptions) - InnerCause.getInnerCause(ex, ExecutionExceptions.class); + if (!InnerCause.isInnerCause(ex, + ConstraintViolationException.class)) { + fail("Expected: " + ConstraintViolationException.class); + } + +// final ExecutionExceptions ex2 = (ExecutionExceptions) +// InnerCause.getInnerCause(ex, ExecutionExceptions.class); +// +// Throwable t = ex2.causes().get(0); +// while (t.getCause() != null) +// t = t.getCause(); +// +// if (!(t instanceof ConstraintViolationException)) +// fail("inner cause should be a ConstraintViolationException"); - Throwable t = ex2.causes().get(0); - while (t.getCause() != null) - t = t.getCause(); - - if (!(t instanceof ConstraintViolationException)) - fail("inner cause should be a ConstraintViolationException"); - } } finally { @@ -197,16 +202,20 @@ } catch (Exception ex) { - final ExecutionExceptions ex2 = (ExecutionExceptions) - InnerCause.getInnerCause(ex, ExecutionExceptions.class); + if (!InnerCause.isInnerCause(ex, + ConstraintViolationException.class)) { + fail("Expected: " + ConstraintViolationException.class); + } +// final ExecutionExceptions ex2 = (ExecutionExceptions) +// InnerCause.getInnerCause(ex, ExecutionExceptions.class); +// +// Throwable t = ex2.causes().get(0); +// while (t.getCause() != null) +// t = t.getCause(); +// +// if (!(t instanceof ConstraintViolationException)) +// fail("inner cause should be a ConstraintViolationException"); - Throwable t = ex2.causes().get(0); - while (t.getCause() != null) - t = t.getCause(); - - if (!(t instanceof ConstraintViolationException)) - fail("inner cause should be a ConstraintViolationException"); - } } finally { Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServlet.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServlet.java 2012-07-26 16:33:04 UTC (rev 6396) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServlet.java 2012-07-27 13:43:48 UTC (rev 6397) @@ -52,6 +52,8 @@ import com.bigdata.rdf.properties.PropertiesFormat; import com.bigdata.rdf.properties.PropertiesWriter; import com.bigdata.rdf.properties.PropertiesWriterRegistry; +import com.bigdata.rdf.rules.ConstraintViolationException; +import com.bigdata.util.InnerCause; /** * Abstract base class for {@link Servlet}s which interact with the bigdata RDF @@ -149,10 +151,21 @@ } finally { // ignore any problems here. } - if (resp != null) { + if (resp != null) { if (!resp.isCommitted()) { - resp.setStatus(HTTP_INTERNALERROR); - resp.setContentType(MIME_TEXT_PLAIN); + if (InnerCause.isInnerCause(t, + ConstraintViolationException.class)) { + /* + * A constraint violation is a bad request (the data + * violates the rules) not a server error. + */ + resp.setStatus(HTTP_BADREQUEST); + resp.setContentType(MIME_TEXT_PLAIN); + } else { + // Internal server error. + resp.setStatus(HTTP_INTERNALERROR); + resp.setContentType(MIME_TEXT_PLAIN); + } } OutputStream os = null; try { Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/CountersServlet.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/CountersServlet.java 2012-07-26 16:33:04 UTC (rev 6396) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/CountersServlet.java 2012-07-27 13:43:48 UTC (rev 6397) @@ -50,7 +50,7 @@ * @author <a href="mailto:tho...@us...">Bryan Thompson</a> * @version $Id$ * - * FIXME The SPARQL layer needs to be separated from the core bigdata + * TODO The SPARQL layer needs to be separated from the core bigdata * layer, with the BigdataContext moving into a servlet package in the * bigdata module and the CountersServlet moving into a servlet package * in the com.bigdata.counters package namespace. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2012-07-31 13:27:54
|
Revision: 6399 http://bigdata.svn.sourceforge.net/bigdata/?rev=6399&view=rev Author: thompsonbry Date: 2012-07-31 13:27:43 +0000 (Tue, 31 Jul 2012) Log Message: ----------- Updated the nxparser jar version to 1.2.2 from 6-22-2010 and parameterized the build.xml file with the nxparser version (declared in build.properties). Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/.classpath branches/BIGDATA_RELEASE_1_2_0/build.properties branches/BIGDATA_RELEASE_1_2_0/build.xml Added Paths: ----------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/lib/nxparser-1.2.2.jar Removed Paths: ------------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/lib/nxparser-6-22-2010.jar Modified: branches/BIGDATA_RELEASE_1_2_0/.classpath =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/.classpath 2012-07-30 17:27:39 UTC (rev 6398) +++ branches/BIGDATA_RELEASE_1_2_0/.classpath 2012-07-31 13:27:43 UTC (rev 6399) @@ -32,14 +32,14 @@ <classpathentry exported="true" kind="lib" path="bigdata/lib/dsi-utils-1.0.6-020610.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/lgpl-utils-1.0.6-020610.jar"/> <classpathentry exported="true" kind="lib" path="bigdata-jini/lib/apache/zookeeper-3.3.3.jar"/> - <classpathentry exported="true" kind="lib" path="bigdata-rdf/lib/nxparser-6-22-2010.jar"/> + <classpathentry exported="true" kind="lib" path="bigdata-rdf/lib/nxparser-1.2.2.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-continuation-7.2.2.v20101205.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-http-7.2.2.v20101205.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-io-7.2.2.v20101205.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-server-7.2.2.v20101205.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-util-7.2.2.v20101205.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/servlet-api-2.5.jar"/> - <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-servlet-7.2.2.v20101205.jar"/> + <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-servlet-7.2.2.v20101205.jar" sourcepath="/Users/bryan/Downloads/jetty-hightide-7.2.2.v20101205-src"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-security-7.2.2.v20101205.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-webapp-7.2.2.v20101205.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-xml-7.2.2.v20101205.jar"/> @@ -74,7 +74,7 @@ <classpathentry exported="true" kind="lib" path="bigdata-rdf/lib/slf4j-api-1.6.1.jar"/> <classpathentry exported="true" kind="lib" path="bigdata-rdf/lib/slf4j-log4j12-1.6.1.jar"/> <classpathentry kind="lib" path="bigdata-rdf/lib/openrdf-sesame-2.6.3-onejar.jar" sourcepath="/Users/bryan/Documents/workspace/org.openrdf.sesame-2.6.3"/> - <classpathentry kind="lib" path="bigdata-sails/lib/sesame-sparql-testsuite-2.6.3.jar"/> + <classpathentry kind="lib" path="bigdata-sails/lib/sesame-sparql-testsuite-2.6.3.jar" sourcepath="/org.openrdf.sesame-2.6.3"/> <classpathentry kind="lib" path="bigdata-sails/lib/sesame-store-testsuite-2.6.3.jar"/> <classpathentry kind="lib" path="bigdata-sails/lib/httpcomponents/commons-codec-1.4.jar"/> <classpathentry kind="lib" path="bigdata-sails/lib/httpcomponents/commons-logging-1.1.1.jar"/> Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/lib/nxparser-1.2.2.jar =================================================================== (Binary files differ) Property changes on: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/lib/nxparser-1.2.2.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Deleted: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/lib/nxparser-6-22-2010.jar =================================================================== (Binary files differ) Modified: branches/BIGDATA_RELEASE_1_2_0/build.properties =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/build.properties 2012-07-30 17:27:39 UTC (rev 6398) +++ branches/BIGDATA_RELEASE_1_2_0/build.properties 2012-07-31 13:27:43 UTC (rev 6399) @@ -46,6 +46,7 @@ apache.httpclient_cache.version=4.1.3 apache.httpcore.version=4.1.4 apache.httpmime.version=4.1.3 +nxparser.version=1.2.2 # Set to false to NOT start services (zookeeper, lookup server, class server, etc). # When false, tests which depend on those services will not run. (This can also be Modified: branches/BIGDATA_RELEASE_1_2_0/build.xml =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/build.xml 2012-07-30 17:27:39 UTC (rev 6398) +++ branches/BIGDATA_RELEASE_1_2_0/build.xml 2012-07-31 13:27:43 UTC (rev 6399) @@ -353,7 +353,7 @@ <bndwrap jars="${build.dir}/lib/high-scale-lib-v1.1.2.jar" output="${build.dir}/bundles/high-scale-lib-v1.1.2.jar" definitions="${basedir}/osgi/" /> <bndwrap jars="${build.dir}/lib/openrdf-sesame-${sesame.version}-onejar.jar" output="${build.dir}/bundles/openrdf-sesame-${sesame.version}.jar" definitions="${basedir}/osgi/" /> <bndwrap jars="${build.dir}/lib/apache/zookeeper-${zookeeper.version}.jar" output="${build.dir}/bundles/zookeeper-${zookeeper.version}.jar" definitions="${basedir}/osgi/" /> - <bndwrap jars="${build.dir}/lib/nxparser-6-22-2010.jar" output="${build.dir}/bundles/nxparser-2010.6.22.jar" definitions="${basedir}/osgi/" /> + <bndwrap jars="${build.dir}/lib/nxparser-${nxparser.version}.jar" output="${build.dir}/bundles/nxparser-2010.6.22.jar" definitions="${basedir}/osgi/" /> </target> @@ -923,7 +923,7 @@ tofile="${dist.lib}/servlet-api.jar" /> <!-- NxParser (RDF NQuads support) --> - <copy file="${bigdata-rdf.lib}/nxparser-6-22-2010.jar" + <copy file="${bigdata-rdf.lib}/nxparser-${nxparser.version}.jar" tofile="${dist.lib}/nxparser.jar" /> <!-- apache http components (SPARQL connections). --> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2012-08-01 13:50:30
|
Revision: 6400 http://bigdata.svn.sourceforge.net/bigdata/?rev=6400&view=rev Author: thompsonbry Date: 2012-08-01 13:50:21 +0000 (Wed, 01 Aug 2012) Log Message: ----------- Simplified the AccessPath class by moving AccessPath#get(int index) into the test suite. It was only used by two of the backchaining expander test suites. Removed IAccessPath#tupleIterator(). It is still implemented internally by AccessPath, but it is no longer exposed and it is not present on the other IAccessPath implementation classes. Lifted out an ISimpleIndexAccess interface from ICheckpointProtocol with rangeCount(), scan(), and removeAll() methods. Isolated a getAccessPath() method returning an IBindingSetAccessPath in the HTreeHashJoinOp and JVMHashJoinOp classes. This currently uses BOpContext.getAccessPath(Relation,Predicate). However, this should be the only method that we need to change in order to execute a hash join against a SolutionSetStream. The next step is to test a change from modeling named subquery outputs as hash indices to modeling those outputs as streams. I will have to change the named solution set resolution mechanism (to be simpler) and the query plans (to build the hash index from the pipeline). I will also need to do a performance assessment for this change, probably for BSBM and the govtrack data sets. @see https://sourceforge.net/apps/trac/bigdata/ticket/531 (SPARQL UPDATE for SOLUTION SETS) Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContextBase.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/ap/Predicate.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/JVMHashJoinOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/ISolutionSet.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/SolutionSetStream.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/ICheckpointProtocol.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/AbstractResource.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/AccessPath.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/AccessPathFusedView.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/ArrayAccessPath.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/BlockingBuffer.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/ChunkConsumerIterator.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/EmptyAccessPath.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/IAbstractAccessPath.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/IAccessPath.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/IBindingSetAccessPath.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/rule/eval/IJoinNexus.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/inf/OwlSameAsPropertiesExpandingIterator.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/inf/TruthMaintenance.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/rules/BackchainAccessPath.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/DGExpander.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPOAccessPath.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPOArrayIterator.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/spo/SPOPredicate.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/rules/AbstractInferenceEngineTestCase.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/rules/TestBackchainOwlSameAsPropertiesIterator.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/rules/TestOwlSameAsPropertiesExpandingIterator.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/rules/TestRuleExpansion.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/NanoSparqlServer.java Added Paths: ----------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/ISimpleIndexAccess.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContextBase.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContextBase.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContextBase.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -213,8 +213,7 @@ // } /** - * Obtain an access path reading from relation for the specified predicate - * (from the tail of some rule). + * Obtain an access path reading from relation for the specified predicate. * <p> * Note: Passing in the {@link IRelation} is important since it otherwise * must be discovered using the {@link IResourceLocator}. By requiring the @@ -250,6 +249,9 @@ * * @todo Support mutable relation views (no - just fix truth maintenance). */ +// * <h2>Non-Relation Access Paths</h2> +// * <p> +// * public <E> IAccessPath<E> getAccessPath(final IRelation<E> relation, final IPredicate<E> predicate) { Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/ap/Predicate.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/ap/Predicate.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/ap/Predicate.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -226,7 +226,7 @@ return new Constant(((IElement) e).get(index)); } - + final public boolean isOptional() { return (Boolean) getProperty(Annotations.OPTIONAL,Annotations.DEFAULT_OPTIONAL); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinOp.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinOp.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinOp.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -369,16 +369,27 @@ } /** + * Return the access path that to be scanned. Solutions read from this + * access path will be used to probe the hash index to identify + * solutions that can join. + */ + private IBindingSetAccessPath<?> getAccessPath() { + + return (IBindingSetAccessPath<?>) context.getAccessPath(relation, + pred); + + } + + /** * Do a hash join of the buffered solutions with the access path. */ private void doHashJoin() { if (state.isEmpty()) return; - - final IAccessPath<?> accessPath = context.getAccessPath(relation, - pred); + final IBindingSetAccessPath<?> accessPath = getAccessPath(); + if (log.isInfoEnabled()) log.info("accessPath=" + accessPath); @@ -395,7 +406,7 @@ IPredicate.Annotations.DEFAULT_CUTOFF_LIMIT); // Obtain the iterator for the current join dimension. - final ICloseableIterator<IBindingSet> itr = ((IBindingSetAccessPath<?>) accessPath) + final ICloseableIterator<IBindingSet> itr = accessPath .solutions(cutoffLimit, stats); state.hashJoin( Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/JVMHashJoinOp.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/JVMHashJoinOp.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/JVMHashJoinOp.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -305,6 +305,17 @@ } /** + * Return the access path that to be scanned. Solutions read from this + * access path will be used to probe the hash index to identify + * solutions that can join. + */ + private IBindingSetAccessPath<?> getAccessPath() { + + return (IBindingSetAccessPath<?>) context.getAccessPath(relation, + pred); + + } + /** * Do a hash join of the buffered solutions with the access path. */ private void doHashJoin() { @@ -312,8 +323,7 @@ if (state.isEmpty()) return; - final IAccessPath<?> accessPath = context.getAccessPath(relation, - pred); + final IBindingSetAccessPath<?> accessPath = getAccessPath(); if (log.isDebugEnabled()) log.debug("accessPath=" + accessPath); @@ -331,8 +341,8 @@ IPredicate.Annotations.DEFAULT_CUTOFF_LIMIT); // Obtain the iterator for the current join dimension. - final ICloseableIterator<IBindingSet> itr = ((IBindingSetAccessPath<?>) accessPath) - .solutions(cutoffLimit, stats); + final ICloseableIterator<IBindingSet> itr = accessPath.solutions( + cutoffLimit, stats); state.hashJoin( itr,// left Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/ISolutionSet.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/ISolutionSet.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/ISolutionSet.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -42,15 +42,19 @@ * * @author <a href="mailto:tho...@us...">Bryan Thompson</a> * - * FIXME Provide {@link ISolutionSet} implementations derived from {@link HTree} - * and {@link BTree}. - * <p> - * Reconcile the {@link HTree} version with the hash join code and - * {@link NamedSolutionSetRef}. - * <p> - * Add an {@link IAccessPath} for HTree and {@link Stream} backed solution sets - * so they can be played out through a simple iterator model. The - * {@link AccessPath} can be used for the {@link BTree} backed solution sets. + * FIXME Provide {@link ISolutionSet} implementations derived from + * {@link HTree} and {@link BTree}. + * <P> + * I am not sure that we will require this. We can probably use the + * Stream for named solution sets for quite a while without supporting + * declaration of named solution sets with specific join variables. + * However, if we do add support for this, then we need to reconcile the + * {@link HTree} version with the hash join code and + * {@link NamedSolutionSetRef} and also add an {@link IAccessPath} for + * {@link HTree} and {@link Stream} backed solution sets so they can be + * played out through a simple iterator model. The {@link AccessPath} is + * relation specific, but it could be relayered to provide support for + * the {@link BTree} backed solution sets. */ public interface ISolutionSet extends ICheckpointProtocol { @@ -91,18 +95,18 @@ */ public void put(final ICloseableIterator<IBindingSet[]> src); - /** - * The {@link IVariable[]} specifying the join variables (required). The - * order of the entries is used when forming the as-bound keys for the hash - * table. Duplicate elements and null elements are not permitted. - * - * TODO We will also need a method to report the JOIN_VARS if the backing - * data structure is an HTree or BTree. [Really, what we need is a method to - * describe how the index key will be generated, or just a method to - * generate the key. Also, it is possible that - * {@link ISolutionSetStats#getAlwaysBound} will report variables which are - * always bound but which are not part of the key for the index. - */ +// /** +// * The {@link IVariable[]} specifying the join variables (required). The +// * order of the entries is used when forming the as-bound keys for the hash +// * table. Duplicate elements and null elements are not permitted. +// * +// * TODO We will also need a method to report the JOIN_VARS if the backing +// * data structure is an HTree or BTree. [Really, what we need is a method to +// * describe how the index key will be generated, or just a method to +// * generate the key. Also, it is possible that +// * {@link ISolutionSetStats#getAlwaysBound} will report variables which are +// * always bound but which are not part of the key for the index. +// */ // public String[] getJoinVars(); } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/SolutionSetStream.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/SolutionSetStream.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/SolutionSetStream.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -37,24 +37,25 @@ import org.apache.log4j.Logger; +import com.bigdata.bop.BOpContext; import com.bigdata.bop.IBindingSet; import com.bigdata.bop.IConstant; +import com.bigdata.bop.IPredicate; import com.bigdata.bop.IVariable; -import com.bigdata.bop.controller.NamedSolutionSetRef; -import com.bigdata.btree.BTree; +import com.bigdata.bop.join.BaseJoinStats; import com.bigdata.btree.Checkpoint; import com.bigdata.btree.IndexMetadata; -import com.bigdata.htree.HTree; import com.bigdata.io.SerializerUtil; import com.bigdata.rawstore.IRawStore; import com.bigdata.rdf.internal.encoder.SolutionSetStreamDecoder; import com.bigdata.rdf.internal.encoder.SolutionSetStreamEncoder; import com.bigdata.rdf.sparql.ast.ISolutionSetStats; -import com.bigdata.relation.accesspath.AccessPath; -import com.bigdata.relation.accesspath.IAccessPath; +import com.bigdata.relation.accesspath.ChunkConsumerIterator; +import com.bigdata.relation.accesspath.IBindingSetAccessPath; import com.bigdata.rwstore.IPSOutputStream; import com.bigdata.stream.Stream; import com.bigdata.striterator.Chunkerator; +import com.bigdata.striterator.IChunkedIterator; import com.bigdata.striterator.ICloseableIterator; import cutthecrap.utils.striterators.ArrayIterator; @@ -428,5 +429,146 @@ } } - + + /** + * Return an access path that can be used to scan the solutions. + * + * @param pred + * ignored. + * + * @return The access path. + * + * TODO FILTERS: (A) Any filter attached to the predicate must be + * applied by the AP to remove solutions which do not satisfy the + * filter; + * <p> + * (B) When the AP has a filter, then an exact range count must scan + * the solutions to decide how many will match. + */ + public IBindingSetAccessPath<IBindingSet> getAccessPath( + final IPredicate<IBindingSet> pred) { + + return new SolutionSetAP(this, pred); + + } + + /** + * Class provides basic access path suitable for full scans. + * + * @author <a href="mailto:tho...@us...">Bryan + * Thompson</a> + */ + private static class SolutionSetAP implements + IBindingSetAccessPath<IBindingSet> { + + private final SolutionSetStream stream; + private final IPredicate<IBindingSet> predicate; + + public SolutionSetAP(final SolutionSetStream stream, + final IPredicate<IBindingSet> pred) { + + this.stream = stream; + + this.predicate = pred; + + } + + @Override + public IPredicate<IBindingSet> getPredicate() { + + return predicate; + + } + + @Override + public boolean isEmpty() { + + /* + * Note: If we develop streams which can have non-exact range counts + * (due to deleted tuples) then this would have to be revisited. + */ + + return stream.entryCount == 0; + + } + + @Override + public long rangeCount(boolean exact) { + + return stream.entryCount; + + } + + @Override + public ICloseableIterator<IBindingSet> solutions(final long limit, + final BaseJoinStats stats) { + + if (limit != 0L && limit != Long.MAX_VALUE) + throw new UnsupportedOperationException(); + + final IChunkedIterator<IBindingSet> itr = new ChunkConsumerIterator<IBindingSet>( + stream.get()); + + return BOpContext.solutions(itr, predicate, stats); + + } + + @Override + public long removeAll() { + + final long n = stream.rangeCount(); + + stream.removeAll(); + + return n; + + } + + } + +// /** +// * A predicate that can be used with an {@link ISolutionSet} without having +// * to resolve the {@link ISolutionSet} as an {@link IRelation}. +// * +// * @author <a href="mailto:tho...@us...">Bryan +// * Thompson</a> +// * @param <E> +// */ +// public static class SolutionSetPredicate<E extends IBindingSet> extends +// Predicate<E> { +// +// public SolutionSetPredicate(BOp[] args, Map<String, Object> annotations) { +// super(args, annotations); +// } +// +// public SolutionSetPredicate(BOp[] args, NV... annotations) { +// super(args, annotations); +// } +// +// public SolutionSetPredicate(IVariableOrConstant<?>[] values, +// String relationName, int partitionId, boolean optional, +// IElementFilter<E> constraint, IAccessPathExpander<E> expander, +// long timestamp) { +// super(values, relationName, partitionId, optional, constraint, +// expander, timestamp); +// } +// +// public SolutionSetPredicate(IVariableOrConstant<?>[] values, +// String relationName, long timestamp) { +// super(values, relationName, timestamp); +// // TODO Auto-generated constructor stub +// } +// +// public SolutionSetPredicate(Predicate<E> op) { +// super(op); +// // TODO Auto-generated constructor stub +// } +// +// /** +// * +// */ +// private static final long serialVersionUID = 1L; +// +// } + } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/ICheckpointProtocol.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/ICheckpointProtocol.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/ICheckpointProtocol.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -1,3 +1,26 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2011. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ package com.bigdata.btree; import com.bigdata.counters.ICounterSetAccess; @@ -6,23 +29,19 @@ import com.bigdata.journal.ICommitter; import com.bigdata.journal.Name2Addr; import com.bigdata.journal.Name2Addr.Entry; -import com.bigdata.striterator.ICloseableIterator; /** * Interface in support of the {@link Checkpoint} record protocol. * * @author tho...@us... * - * TODO There should be a high level method to insert objects into the - * index (index "entries" not tuples - the index will need to compute - * the appropriate key, etc. in an implementation dependent manner). - * * TODO Try to lift out an abstract implementation of this interface for * HTree, BTree, and Stream. This will be another step towards GIST * support. There are protected methods which are used on those classes * which should be lifted into the abstract base class. */ -public interface ICheckpointProtocol extends ICommitter, ICounterSetAccess { +public interface ICheckpointProtocol extends ICommitter, ICounterSetAccess, + ISimpleIndexAccess { /** * The value of the record version number that will be assigned to the next @@ -134,34 +153,36 @@ */ public IndexMetadata getIndexMetadata(); - /* - * Generic data access methods defined for all persistence capable - * data structures. - */ +// /* +// * Generic data access methods defined for all persistence capable +// * data structures. +// */ +// +// /** +// * Return the #of entries in the index. +// * <p> +// * Note: If the index supports deletion markers then the range count will be +// * an upper bound and may double count tuples which have been overwritten, +// * including the special case where the overwrite is a delete. +// * +// * @return The #of tuples in the index. +// * +// * @see IRangeQuery#rangeCount() +// */ +// public long rangeCount(); +// +// /** +// * Visit all entries in the index in the natural order of the index +// * (dereferencing visited tuples to the application objects stored within +// * those tuples). +// */ +// public ICloseableIterator<?> scan(); +// +// /** +// * Remove all entries in the index. +// */ +// public void removeAll(); - /** - * Return the #of entries in the index. - * <p> - * Note: If the index supports deletion markers then the range count will be - * an upper bound and may double count tuples which have been overwritten, - * including the special case where the overwrite is a delete. - * - * @return The #of tuples in the index. - * - * @see IRangeQuery#rangeCount() - */ - public long rangeCount(); - - /** - * Visit all entries in the index in the natural order of the index. - */ - public ICloseableIterator<?> scan(); - - /** - * Remove all entries in the index. - */ - public void removeAll(); - /* * reopen() / close() protocol */ Added: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/ISimpleIndexAccess.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/ISimpleIndexAccess.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/ISimpleIndexAccess.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -0,0 +1,66 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2011. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 1, 2012 + */ +package com.bigdata.btree; + +import com.bigdata.striterator.ICloseableIterator; + +/** + * Generic data access methods defined for all persistence capable data + * structures. + * + * TODO There should be a high level method to insert objects into the index + * (index "entries" not tuples - the index will need to compute the appropriate + * key, etc. in an implementation dependent manner). + */ +public interface ISimpleIndexAccess { + + /** + * Return the #of entries in the index. + * <p> + * Note: If the index supports deletion markers then the range count will be + * an upper bound and may double count tuples which have been overwritten, + * including the special case where the overwrite is a delete. + * + * @return The #of tuples in the index. + * + * @see IRangeQuery#rangeCount() + */ + public long rangeCount(); + + /** + * Visit all entries in the index in the natural order of the index + * (dereferencing visited tuples to the application objects stored within + * those tuples). + */ + public ICloseableIterator<?> scan(); + + /** + * Remove all entries in the index. + */ + public void removeAll(); + +} Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/AbstractResource.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/AbstractResource.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/AbstractResource.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -138,9 +138,9 @@ /** * If the estimated range count for an - * {@link IAccessPath#iterator(int, int)} is LTE this threshold then do a - * fully buffered (synchronous) read. Otherwise we will do an asynchronous - * read. + * {@link IAccessPath#iterator(long,long, int)} is LTE this threshold then + * do a fully buffered (synchronous) read. Otherwise we will do an + * asynchronous read. * * @see Options#FULLY_BUFFERED_READ_THRESHOLD * Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/AccessPath.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/AccessPath.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/AccessPath.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -40,7 +40,6 @@ import com.bigdata.bop.BufferAnnotations; import com.bigdata.bop.IBindingSet; import com.bigdata.bop.IPredicate; -import com.bigdata.bop.IVariableOrConstant; import com.bigdata.bop.ap.filter.SameVariableConstraint; import com.bigdata.bop.cost.BTreeCostModel; import com.bigdata.bop.cost.DiskCostModel; @@ -693,7 +692,8 @@ } - final IChunkedIterator<R> itr = iterator(1,1); + final IChunkedIterator<R> itr = iterator(0L/* offset */, 1L/* limit */, + 1/* capacity */); try { @@ -744,8 +744,9 @@ // final IVariable<?>[] vars = BOpUtility // .getDistinctArgumentVariables(predicate); - return BOpContext.solutions(iterator(0, limit, 0/* (int) limit */), - predicate, /* vars, */stats); + return BOpContext.solutions( + iterator(0L/* offset */, limit, 0/* capacity */), predicate, + stats); } @@ -755,13 +756,13 @@ } - final public IChunkedOrderedIterator<R> iterator(final int limit, - final int capacity) { +// final public IChunkedOrderedIterator<R> iterator(final int limit, +// final int capacity) { +// +// return iterator(0L/* offset */, limit, capacity); +// +// } - return iterator(0L/* offset */, limit, capacity); - - } - /** * @throws RejectedExecutionException * if the iterator is run asynchronously and the @@ -1381,12 +1382,13 @@ } - final public ITupleIterator<R> rangeIterator() { +// @Override +// final public ITupleIterator<R> rangeIterator() { +// +// return rangeIterator(0/* capacity */, flags, indexLocalFilter); +// +// } - return rangeIterator(0/* capacity */, flags, indexLocalFilter); - - } - @SuppressWarnings( { "unchecked" }) protected ITupleIterator<R> rangeIterator(final int capacity, final int flags, final IFilter filter) { @@ -1446,25 +1448,6 @@ } /** - * Return the constant bound on the {@link #getPredicate() predicate} for - * this access path at the specified index -or- {@link #NULL} iff the - * predicate is not bound at that position. - * - * @param index - * The index. - * - * @return Either the bound value -or- {@link #NULL} iff the index is - * unbound for the predicate for this access path. - */ - public Object get(final int index) { - - final IVariableOrConstant<?> t = predicate.get(index); - - return t == null || t.isVar() ? null : t.get(); - - } - - /** * Return an estimate of the cost of a scan on the predicate. * * @param pred Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/AccessPathFusedView.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/AccessPathFusedView.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/AccessPathFusedView.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -112,12 +112,14 @@ } + @Override public IPredicate<E> getPredicate() { return path1.getPredicate(); } + @Override public boolean isEmpty() { return path1.isEmpty() && path2.isEmpty(); @@ -125,6 +127,8 @@ } /** + * {@inheritDoc} + * <P> * Note: You can not get an exact range count for a view. * * @throws UnsupportedOperationException @@ -135,6 +139,7 @@ * sync so that duplicates could be detected. This means a full key * range scan for both source access paths. */ + @Override public long rangeCount(boolean exact) { if (exact) { @@ -152,24 +157,28 @@ // final private int flags; /** + * {@inheritDoc} + * * @throws UnsupportedOperationException * always. * * @todo this could be implemented with a variant (or relaxed form) of * {@link FusedView}. */ + @Override public IIndex getIndex() { throw new UnsupportedOperationException(); } - public ITupleIterator<E> rangeIterator() { +// @Override +// public ITupleIterator<E> rangeIterator() { +// +// return rangeIterator(0/* capacity */); +// +// } - return rangeIterator(0/* capacity */); - - } - private ITupleIterator<E> rangeIterator(final int capacity) { /* @@ -188,17 +197,18 @@ } + @Override public IChunkedOrderedIterator<E> iterator() { return iterator(0L/* offset */, 0L/* limit */, 0/* capacity */); } - public IChunkedOrderedIterator<E> iterator(int limit, int capacity) { - - return iterator(0L/* offset */, limit, capacity); - - } +// public IChunkedOrderedIterator<E> iterator(int limit, int capacity) { +// +// return iterator(0L/* offset */, limit, capacity); +// +// } /** * FIXME write tests for optimizations for point tests and small limits. See @@ -206,7 +216,9 @@ * * FIXME handle non-zero offset. */ - public IChunkedOrderedIterator<E> iterator(long offset, long limit, int capacity) { + @Override + public IChunkedOrderedIterator<E> iterator(final long offset, long limit, + int capacity) { if (offset > 0L) throw new UnsupportedOperationException(); @@ -283,12 +295,14 @@ } + @Override public long removeAll() { throw new UnsupportedOperationException(); } + @Override public IKeyOrder<E> getKeyOrder() { return path1.getKeyOrder(); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/ArrayAccessPath.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/ArrayAccessPath.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/ArrayAccessPath.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -26,7 +26,6 @@ import com.bigdata.bop.IPredicate; import com.bigdata.btree.IIndex; -import com.bigdata.btree.ITupleIterator; import com.bigdata.striterator.ChunkedArrayIterator; import com.bigdata.striterator.ChunkedWrappedIterator; import com.bigdata.striterator.IChunkedOrderedIterator; @@ -74,10 +73,13 @@ } /** + * {@inheritDoc} + * * @throws UnsupportedOperationException * unless the caller specified an {@link IPredicate} to the * ctor. */ + @Override public IPredicate<E> getPredicate() { if (predicate == null) @@ -88,31 +90,40 @@ } /** + * {@inheritDoc} + * * @throws UnsupportedOperationException * unless the caller specified an {@link IKeyOrder} to the ctor. */ + @Override public IKeyOrder<E> getKeyOrder() { if (keyOrder == null) throw new UnsupportedOperationException(); return keyOrder; - + } /** + * {@inheritDoc} + * * @throws UnsupportedOperationException * since no index is associated with this array */ + @Override public IIndex getIndex() { - + throw new UnsupportedOperationException(); } - + /** + * {@inheritDoc} + * <p> * Returns <code>true</code> when the array of elements is empty. */ + @Override public boolean isEmpty() { return e.length == 0; @@ -120,47 +131,57 @@ } /** + * {@inheritDoc} + * <p> * Returns the size of the array of elements. */ + @Override public long rangeCount(boolean exact) { return e.length; } - /** - * @throws UnsupportedOperationException - * since no index is associated with this array - */ - public ITupleIterator<E> rangeIterator() { +// /** +// * @throws UnsupportedOperationException +// * since no index is associated with this array +// */ +// @Override +// public ITupleIterator<E> rangeIterator() { +// +// throw new UnsupportedOperationException(); +// +// } - throw new UnsupportedOperationException(); - - } - /** + * {@inheritDoc} + * <p> * Visits the entire array of elements. */ + @Override public IChunkedOrderedIterator<E> iterator() { - return iterator(0/* limit */, 0/* capacity */); + return iterator(0L/* offset */, 0L/* limit */, 0/* capacity */); } - /** - * Visits the array of elements up to the specified limit. - */ - public IChunkedOrderedIterator<E> iterator(final int limit, - final int capacity) { +// /** +// * Visits the array of elements up to the specified limit. +// */ +// public IChunkedOrderedIterator<E> iterator(final int limit, +// final int capacity) { +// +// return iterator(0L/* offset */, limit, capacity); +// +// } - return iterator(0L/* offset */, limit, capacity); - - } - /** - * Visits the array of elements from the specified offset up to the + * {@inheritDoc} + * <p> + * Visits the array of elements from the specified offset up to the * specified limit. */ + @Override @SuppressWarnings("unchecked") public IChunkedOrderedIterator<E> iterator(final long offset, long limit, final int capacity) { @@ -232,8 +253,11 @@ } /** + * {@inheritDoc} + * <P> * Does nothing and always returns ZERO(0). */ + @Override public long removeAll() { return 0L; Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/BlockingBuffer.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/BlockingBuffer.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/BlockingBuffer.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -1172,7 +1172,7 @@ * <p> * The most common reason to close an iterator early are that you want to * only visit a limited #of elements. However, if you use either - * {@link IAccessPath#iterator(int, int)} or {@link IRule} with an + * {@link IAccessPath#iterator(long,long, int)} or {@link IRule} with an * {@link IQueryOptions} to impose that limit, then most processes that * produce {@link IAsynchronousIterator}s will automatically terminate when * they reach the desired limit, thereby avoiding issuing interrupts. Those Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/ChunkConsumerIterator.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/ChunkConsumerIterator.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/ChunkConsumerIterator.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -10,12 +10,16 @@ import com.bigdata.striterator.IKeyOrder; /** - * A class that aligns a buffer of <code>E[]</code>s (a buffer of chunks) - * with an {@link IChunkedOrderedIterator}. + * A class that aligns a buffer of <code>E[]</code>s (a buffer of chunks) with + * an {@link IChunkedOrderedIterator}. * * @author <a href="mailto:tho...@us...">Bryan Thompson</a> - * @version $Id$ + * @version $Id: ChunkConsumerIterator.java 6130 2012-03-15 10:31:25Z + * thompsonbry $ * @param <E> + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/483"> + * Eliminate unnecessary dechunking and rechunking </a> */ public class ChunkConsumerIterator<E> implements IChunkedOrderedIterator<E> { Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/EmptyAccessPath.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/EmptyAccessPath.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/EmptyAccessPath.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -4,8 +4,6 @@ import com.bigdata.bop.IPredicate; import com.bigdata.btree.IIndex; -import com.bigdata.btree.ITupleIterator; -import com.bigdata.btree.filter.EmptyTupleIterator; import com.bigdata.striterator.ChunkedWrappedIterator; import com.bigdata.striterator.IChunkedOrderedIterator; import com.bigdata.striterator.IKeyOrder; @@ -56,10 +54,12 @@ } /** + * {@inheritDoc} * @throws UnsupportedOperationException * unless the caller specified an {@link IPredicate} to the * ctor. */ + @Override public IPredicate<E> getPredicate() { if (predicate == null) @@ -70,9 +70,11 @@ } /** + * {@inheritDoc} * @throws UnsupportedOperationException * unless the caller specified an {@link IKeyOrder} to the ctor. */ + @Override public IKeyOrder<E> getKeyOrder() { if (keyOrder == null) @@ -83,9 +85,11 @@ } /** + * {@inheritDoc} * @throws UnsupportedOperationException * since no index was selected. */ + @Override public IIndex getIndex() { throw new UnsupportedOperationException(); @@ -93,8 +97,10 @@ } /** + * {@inheritDoc}<p> * Always returns <code>true</code>. */ + @Override public boolean isEmpty() { return true; @@ -102,48 +108,52 @@ } /** - * Always returns ZERO(0). + * {@inheritDoc}<p>Always returns ZERO(0). */ + @Override public long rangeCount(boolean exact) { return 0; } - /** - * Visits nothing. - */ - @SuppressWarnings("unchecked") - public ITupleIterator<E> rangeIterator() { +// /** +// * Visits nothing. +// */ +// @SuppressWarnings("unchecked") +// @Override +// public ITupleIterator<E> rangeIterator() { +// +// return EmptyTupleIterator.INSTANCE; +// +// } - return EmptyTupleIterator.INSTANCE; - - } - /** * Visits nothing. */ + @Override public IChunkedOrderedIterator<E> iterator() { return iterator(0L/* offset */, 0L/* limit */, 0/* capacity */); } - /** - * Visits nothing. - */ - public IChunkedOrderedIterator<E> iterator(int limit, int capacity) { +// /** +// * Visits nothing. +// */ +// public IChunkedOrderedIterator<E> iterator(int limit, int capacity) { +// +// return iterator(0L/* offset */, limit, capacity); +// +// } - return iterator(0L/* offset */, limit, capacity); - - } - /** * Visits nothing. */ + @Override @SuppressWarnings("unchecked") - public IChunkedOrderedIterator<E> iterator(long offset, long limit, - int capacity) { + public IChunkedOrderedIterator<E> iterator(final long offset, + final long limit, final int capacity) { return new ChunkedWrappedIterator<E>(Collections.EMPTY_LIST.iterator()); @@ -152,6 +162,7 @@ /** * Does nothing and always returns ZERO(0). */ + @Override public long removeAll() { return 0L; Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/IAbstractAccessPath.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/IAbstractAccessPath.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/IAbstractAccessPath.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -78,4 +78,12 @@ */ long rangeCount(boolean exact); + /** + * Remove all elements selected by the {@link IPredicate} (optional + * operation). + * + * @return The #of elements that were removed. + */ + public long removeAll(); + } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/IAccessPath.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/IAccessPath.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/IAccessPath.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -28,9 +28,9 @@ package com.bigdata.relation.accesspath; +import com.bigdata.bop.IElement; import com.bigdata.bop.IPredicate; import com.bigdata.btree.IIndex; -import com.bigdata.btree.ITupleIterator; import com.bigdata.relation.IRelation; import com.bigdata.relation.rule.IQueryOptions; import com.bigdata.relation.rule.IRule; @@ -68,15 +68,15 @@ */ public IIndex getIndex(); - /** - * The raw iterator for traversing the selected index within the key range - * implied by {@link IPredicate}. - * <p> - * Note: The access path may incorporate additional constraints from the - * specified {@link IPredicate} that are not present on the raw - * {@link ITupleIterator} returned by this method. - */ - public ITupleIterator<R> rangeIterator(); +// /** +// * The raw iterator for traversing the selected index within the key range +// * implied by {@link IPredicate}. +// * <p> +// * Note: The access path may incorporate additional constraints from the +// * specified {@link IPredicate} that are not present on the raw +// * {@link ITupleIterator} returned by this method. +// */ +// public ITupleIterator<R> rangeIterator(); /** * An iterator visiting elements using the natural order of the index @@ -102,25 +102,25 @@ */ public IChunkedOrderedIterator<R> iterator(); - /** - * An iterator visiting elements using the natural order of the index - * selected for the {@link IPredicate}. - * - * @param limit - * The maximum #of elements that will be visited -or- ZERO (0) if - * there is no limit. - * - * @param capacity - * The maximum capacity for the buffer used by the iterator. When - * ZERO(0), a default capacity will be used. When a <i>limit</i> - * is specified, the capacity will never exceed the <i>limit</i>. - * - * @return The iterator. - * - * @deprecated by {@link #iterator(long, long, int)}. Also, [limit] should - * have been a long, not an int. - */ - public IChunkedOrderedIterator<R> iterator(int limit, int capacity); +// /** +// * An iterator visiting elements using the natural order of the index +// * selected for the {@link IPredicate}. +// * +// * @param limit +// * The maximum #of elements that will be visited -or- ZERO (0) if +// * there is no limit. +// * +// * @param capacity +// * The maximum capacity for the buffer used by the iterator. When +// * ZERO(0), a default capacity will be used. When a <i>limit</i> +// * is specified, the capacity will never exceed the <i>limit</i>. +// * +// * @return The iterator. +// * +// * @deprecated by {@link #iterator(long, long, int)}. Also, [limit] should +// * have been a long, not an int. +// */ +// public IChunkedOrderedIterator<R> iterator(int limit, int capacity); /** * An iterator visiting elements using the natural order of the index @@ -166,12 +166,12 @@ public IChunkedOrderedIterator<R> iterator(long offset, long limit, int capacity); - /** - * Remove all elements selected by the {@link IPredicate} (optional - * operation). - * - * @return The #of elements that were removed. - */ - public long removeAll(); +// /** +// * Remove all elements selected by the {@link IPredicate} (optional +// * operation). +// * +// * @return The #of elements that were removed. +// */ +// public long removeAll(); } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/IBindingSetAccessPath.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/IBindingSetAccessPath.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/accesspath/IBindingSetAccessPath.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -50,8 +50,16 @@ * Return an iterator which will visit the solutions drawn from the access * path with a limit on the number of solutions drawn. * - * TODO Should this be visiting IBindingSet[]s? + * @param limit + * The maximum #of solutions to visit. + * @param stats + * Some statistics are updated as solutions are visited. * + * @return The iterator. + * + * TODO Should this be visiting IBindingSet[]s or be an + * IChunkedIterator<IBindingSet>? + * * @see https://sourceforge.net/apps/trac/bigdata/ticket/209 (Access path * should visit solutions for high level query). */ Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/rule/eval/IJoinNexus.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/rule/eval/IJoinNexus.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/relation/rule/eval/IJoinNexus.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -156,7 +156,7 @@ * {@link IAccessPath} will use an {@link IAsynchronousIterator} instead. * This value should on the order of {@link #getChunkCapacity()}. * - * @see IAccessPath#iterator(int, int) + * @see IAccessPath#iterator(long,long, int) * @see AbstractResource.Options#FULLY_BUFFERED_READ_THRESHOLD * @deprecated by bop annotations. */ Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/inf/OwlSameAsPropertiesExpandingIterator.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/inf/OwlSameAsPropertiesExpandingIterator.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/inf/OwlSameAsPropertiesExpandingIterator.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -409,22 +409,27 @@ } } + @Override public IIndex getIndex() { return accessPath.getIndex(); } + @Override public IKeyOrder<ISPO> getKeyOrder() { return accessPath.getKeyOrder(); } + @Override public IPredicate<ISPO> getPredicate() { return accessPath.getPredicate(); } + @Override public boolean isEmpty() { return false; } + @Override public IChunkedOrderedIterator<ISPO> iterator() { final IChunkedOrderedIterator<ISPO> appender = getAppender(); final IChunkedOrderedIterator<ISPO> delegate = @@ -476,22 +481,26 @@ }; } - public IChunkedOrderedIterator<ISPO> iterator(int limit, int capacity) { - throw new UnsupportedOperationException(); - } +// public IChunkedOrderedIterator<ISPO> iterator(int limit, int capacity) { +// throw new UnsupportedOperationException(); +// } + @Override public IChunkedOrderedIterator<ISPO> iterator(long offset, long limit, int capacity) { throw new UnsupportedOperationException(); } + @Override public long rangeCount(boolean exact) { return accessPath.rangeCount(exact) + 1; } - public ITupleIterator<ISPO> rangeIterator() { - throw new UnsupportedOperationException(); - } +// @Override +// public ITupleIterator<ISPO> rangeIterator() { +// throw new UnsupportedOperationException(); +// } + @Override public long removeAll() { throw new UnsupportedOperationException(); } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/inf/TruthMaintenance.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/inf/TruthMaintenance.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/inf/TruthMaintenance.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -1001,6 +1001,19 @@ /* * Suck everything in the focusStore into an SPO[]. + * + * TODO There are some scalability and "old code" issues with this. + * It is reading everything into an SPO[], which is a scalability + * problem. This is also the only code which uses the + * SPOArrayIterator and the IAccessPath#rangeIterator(). If we + * change this, we can get rid of both of those things. + * + * There are other alternatives to pulling it all into an ISPO[]. We + * are doing this so we can remove all these ISPOs later (see + * below). The backing temp store does not support multiple commit + * points, but we could write the new data onto a different temp + * triple store and then read from the old temp triple store when + * deleting the data. */ final SPOArrayIterator tmp = new SPOArrayIterator(focusStore, focusStore Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/rules/BackchainAccessPath.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/rules/BackchainAccessPath.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/rules/BackchainAccessPath.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -34,7 +34,6 @@ import com.bigdata.bop.IPredicate; import com.bigdata.btree.IIndex; -import com.bigdata.btree.ITupleIterator; import com.bigdata.rdf.axioms.Axioms; import com.bigdata.rdf.inf.BackchainTypeResourceIterator; import com.bigdata.rdf.inf.OwlSameAsPropertiesExpandingIterator; @@ -51,9 +50,6 @@ import com.bigdata.striterator.IChunkedOrderedIterator; import com.bigdata.striterator.IKeyOrder; -import cutthecrap.utils.striterators.IFilter; -import cutthecrap.utils.striterators.Striterator; - /** * A read-only {@link IAccessPath} that backchains certain inferences. * <p> @@ -160,30 +156,32 @@ } - /** - * The {@link IIndex} for the source {@link IAccessPath}. - */ + @Override final public IIndex getIndex() { return accessPath.getIndex(); } + @Override final public IKeyOrder<ISPO> getKeyOrder() { return accessPath.getKeyOrder(); } + @Override final public IPredicate<ISPO> getPredicate() { return accessPath.getPredicate(); } + @Override public boolean isEmpty() { - final IChunkedIterator<ISPO> itr = iterator(1,1); + final IChunkedIterator<ISPO> itr = iterator(0L/* offset */, + 1L/* limit */, 1/* capacity */); try { @@ -198,20 +196,36 @@ } /** + * {@inheritDoc} + * <p> * Visits elements in the source {@link IAccessPath} plus all entailments * licensed by the {@link InferenceEngine}. */ + @Override public IChunkedOrderedIterator<ISPO> iterator() { return iterator(0L/* offset */, 0L/* limit */, 0/* capacity */); } +// /** +// * Visits elements in the source {@link IAccessPath} plus all entailments +// * licensed by the {@link InferenceEngine} as configured. +// */ +// public IChunkedOrderedIterator<ISPO> iterator(final int limit, +// final int capacity) { +// +// return iterator(0L/*offset*/,limit,capacity); +// +// } + /** + * {@inheritDoc} * @todo handle non-zero offset and larger limits? */ - public IChunkedOrderedIterator<ISPO> iterator(long offset, long limit, - int capacity) { + @Override + public IChunkedOrderedIterator<ISPO> iterator(final long offset, + long limit, int capacity) { if (offset > 0L) throw new UnsupportedOperationException(); @@ -222,17 +236,17 @@ if (limit > Integer.MAX_VALUE) throw new UnsupportedOperationException(); - return iterator((int) limit, capacity); +// return iterator((int) limit, capacity); +// +// } +// +// /** +// * Visits elements in the source {@link IAccessPath} plus all entailments +// * licensed by the {@link InferenceEngine} as configured. +// */ +// public IChunkedOrderedIterator<ISPO> iterator(final int limit, +// final int capacity) { - } - - /** - * Visits elements in the source {@link IAccessPath} plus all entailments - * licensed by the {@link InferenceEngine} as configured. - */ - public IChunkedOrderedIterator<ISPO> iterator(final int limit, - final int capacity) { - if (INFO) { log.info(accessPath.getPredicate().toString()); @@ -345,7 +359,7 @@ // tmp.addFilter(accessPathFilter); IChunkedOrderedIterator<ISPO> itr = (owlSameAsItr == null// - ? accessPath.iterator(limit, capacity) // + ? accessPath.iterator(offset, limit, capacity) // : new ChunkedWrappedIterator<ISPO>(owlSameAsItr, capacity == 0 ? inf.database.getChunkCapacity() : capacity, null/* keyOrder */, filter)// @@ -477,12 +491,15 @@ /** + * {@inheritDoc} + * <p> * When <code>exact == false</code> this does not count the backchained * entailments. When <code>exact == true</code> traverses the * {@link #iterator()} so as to produce an exact count of the #of elements * that would in fact be visited, which combines those from the database * with those generated dynamically (NOT efficient). */ + @Override public long rangeCount(boolean exact) { if (!exact) @@ -514,19 +531,18 @@ } - /** - * Delegated to the source {@link IAccessPath} (does not visit any - * entailments). - */ - public ITupleIterator<ISPO> rangeIterator() { - - return accessPath.rangeIterator(); - - } +// /** +// * Delegated to the source {@link IAccessPath} (does not visit any +// * entailments). +// */ +// @Override +// public ITupleIterator<ISPO> rangeIterator() { +// +// return accessPath.rangeIterator(); +// +// } - /** - * Delegated to the source {@link IAccessPath}. - */ + @Override public long removeAll() { return accessPath.removeAll(); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/DGExpander.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/DGExpander.java 2012-07-31 13:27:43 UTC (rev 6399) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/DGExpander.java 2012-08-01 13:50:21 UTC (rev 6400) @@ -144,24 +144,28 @@ } + @Override public IIndex getIndex() { return sourceAccessPath.getIndex(); } + @Override public IKeyOrder<ISPO> getKeyOrder() { return sourceAccessPath.getKeyOrder(); } + @Override pub... [truncated message content] |
From: <tho...@us...> - 2012-08-03 14:07:18
|
Revision: 6402 http://bigdata.svn.sourceforge.net/bigdata/?rev=6402&view=rev Author: thompsonbry Date: 2012-08-03 14:07:07 +0000 (Fri, 03 Aug 2012) Log Message: ----------- I have changed the log4j version from 1.2.15 to 1.2.17 to work around a dependency inclusion problem in the earlier version of log4j. I have renamed the ICU dependencies to have version numbers that are consistent with the version numbers used in maven repositories for ICU (4_8 => 4.8). I have added a pom for the embedded bigdata mode based on one contributed by Gerjon of the Open Sahara project - many thanks to Gerjon for his input on this effort. The dependency version information is now maintained in build.properties (for ant), pom.xml (for maven), and .classpath (for Eclipse). The maven pom should work at this point, but only for people who want to build their own version of bigdata since there are no published releases of bigdata yet in our maven repository. We will publish 1.2.2 in this fashion. Note that I have not taken on some of the challenges of the "maven-branch". There are still plenty of cycles in the project packages. @see https://sourceforge.net/apps/trac/bigdata/ticket/168 (Mavenization of bigdata) Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/.classpath branches/BIGDATA_RELEASE_1_2_0/build.properties Added Paths: ----------- branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/apache/log4j-1.2.17.jar branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/icu/icu4j-4.8.jar branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/icu/icu4j-charset-4.8.jar branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/icu/icu4j-localespi-4.8.jar branches/BIGDATA_RELEASE_1_2_0/pom.xml Removed Paths: ------------- branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/apache/log4j-1.2.15.jar branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/icu/icu4j-4_8.jar branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/icu/icu4j-charset-4_8.jar branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/icu/icu4j-localespi-4_8.jar Modified: branches/BIGDATA_RELEASE_1_2_0/.classpath =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/.classpath 2012-08-02 18:32:11 UTC (rev 6401) +++ branches/BIGDATA_RELEASE_1_2_0/.classpath 2012-08-03 14:07:07 UTC (rev 6402) @@ -44,8 +44,9 @@ <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-webapp-7.2.2.v20101205.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/jetty/jetty-xml-7.2.2.v20101205.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/unimi/colt-1.2.0.jar"/> + <classpathentry kind="lib" path="bigdata/lib/icu/icu4j-4.8.jar"/> + <classpathentry kind="lib" path="bigdata/lib/icu/icu4j-charset-4.8.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/junit-3.8.1.jar" sourcepath="/root/.m2/repository/junit/junit/3.8.1/junit-3.8.1-sources.jar"/> - <classpathentry exported="true" kind="lib" path="bigdata/lib/apache/log4j-1.2.15.jar"/> <classpathentry exported="true" kind="lib" path="bigdata-jini/lib/jini/lib/browser.jar"/> <classpathentry exported="true" kind="lib" path="bigdata-jini/lib/jini/lib/classserver.jar"/> <classpathentry exported="true" kind="lib" path="bigdata-jini/lib/jini/lib/fiddler.jar"/> @@ -68,8 +69,6 @@ <classpathentry kind="lib" path="bigdata-rdf/lib/sesame-rio-testsuite-2.6.3.jar" sourcepath="/org.openrdf.sesame-2.6.3"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/high-scale-lib-v1.1.2.jar"/> - <classpathentry exported="true" kind="lib" path="bigdata/lib/icu/icu4j-4_8.jar"/> - <classpathentry exported="true" kind="lib" path="bigdata/lib/icu/icu4j-charset-4_8.jar"/> <classpathentry exported="true" kind="lib" path="bigdata/lib/junit-ext-1.1-b3-dev.jar"/> <classpathentry exported="true" kind="lib" path="bigdata-rdf/lib/slf4j-api-1.6.1.jar"/> <classpathentry exported="true" kind="lib" path="bigdata-rdf/lib/slf4j-log4j12-1.6.1.jar"/> @@ -84,5 +83,6 @@ <classpathentry kind="lib" path="bigdata-sails/lib/httpcomponents/httpmime-4.1.3.jar"/> <classpathentry kind="lib" path="bigdata-sails/lib/httpcomponents/commons-fileupload-1.2.2.jar"/> <classpathentry kind="lib" path="bigdata-sails/lib/httpcomponents/commons-io-2.1.jar"/> + <classpathentry kind="lib" path="bigdata/lib/apache/log4j-1.2.17.jar"/> <classpathentry kind="output" path="bin"/> </classpath> Deleted: branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/apache/log4j-1.2.15.jar =================================================================== (Binary files differ) Added: branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/apache/log4j-1.2.17.jar =================================================================== (Binary files differ) Property changes on: branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/apache/log4j-1.2.17.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Copied: branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/icu/icu4j-4.8.jar (from rev 6391, branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/icu/icu4j-4_8.jar) =================================================================== (Binary files differ) Deleted: branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/icu/icu4j-4_8.jar =================================================================== (Binary files differ) Copied: branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/icu/icu4j-charset-4.8.jar (from rev 6391, branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/icu/icu4j-charset-4_8.jar) =================================================================== (Binary files differ) Deleted: branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/icu/icu4j-charset-4_8.jar =================================================================== (Binary files differ) Copied: branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/icu/icu4j-localespi-4.8.jar (from rev 6391, branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/icu/icu4j-localespi-4_8.jar) =================================================================== (Binary files differ) Deleted: branches/BIGDATA_RELEASE_1_2_0/bigdata/lib/icu/icu4j-localespi-4_8.jar =================================================================== (Binary files differ) Modified: branches/BIGDATA_RELEASE_1_2_0/build.properties =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/build.properties 2012-08-02 18:32:11 UTC (rev 6401) +++ branches/BIGDATA_RELEASE_1_2_0/build.properties 2012-08-03 14:07:07 UTC (rev 6402) @@ -31,8 +31,21 @@ # javacc is required to compile the SPARQL grammar. javacc.home=/usr/java/javacc-5.0 +## # Versions to use of various dependencies. -icu.version=4_8 +# +# Note: You must also update pom.xml when versions are changed. +# +# Note: The ICU version number for the downloaded jar is 4_8, which is +# how it is published by that project. However, the version number for +# the corresponding maven dependency is 4.8. I have renamed the jar to +# have consistent version numbers for ant and maven. +# +# Note: There is also a naming inconsistency for highscalelib. That +# project publishes "high-scale-lib-vXXXX.jar", but the maven dependency +# is named "high-scale-lib-XXXX.jar". +# +icu.version=4.8 zookeeper.version=3.3.3 sesame.version=2.6.3 slf4j.version=1.6.1 @@ -47,6 +60,12 @@ apache.httpcore.version=4.1.4 apache.httpmime.version=4.1.3 nxparser.version=1.2.2 +colt.version=1.2.0 +highscalelib.version=1.1.2 +log4j.version=1.2.17 +fastutil.version=5.1.5 +dsiutils.version=1.0.6-020610 +lgplutils.version=1.0.6-020610 # Set to false to NOT start services (zookeeper, lookup server, class server, etc). # When false, tests which depend on those services will not run. (This can also be Added: branches/BIGDATA_RELEASE_1_2_0/pom.xml =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/pom.xml (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/pom.xml 2012-08-03 14:07:07 UTC (rev 6402) @@ -0,0 +1,383 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Copyright (C) SYSTAP, LLC 2006-2010. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 + +Copyright 2010 by TalkingTrends (Amsterdam, The Netherlands) +--><!-- +This POM is intended to support the use of bigdata(R) as an embedded +database as part of your own maven project. It declares the +dependencies for the embedded database, but does not include the +dependencies for the NanoSparqlServer or the clustered database - use +the ant build.xml file to generate and deploy those artifacts. + +To install the dependencies into your local maven repository, do: + + mvn clean install + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" + > + <modelVersion>4.0.0</modelVersion> + <groupId>com.bigdata</groupId> + <artifactId>bigdata</artifactId> + <version>1.2.1</version> + <packaging>pom</packaging> + <name>bigdata(R)</name> + <description>Bigdata(R) Maven Build</description> + <url>http://www.systap.com/bigdata.htm</url> + <organization> + <name>SYSTAP, LLC</name> + <url>http://www.systap.com/</url> + </organization> + <inceptionYear>2006</inceptionYear> + <licenses> + <license> + <name>GNU General Public License Version 2 (GPLv2)</name> + <url>http://www.gnu.org/licenses/gpl-2.0.html</url> + </license> + </licenses> + <properties> + <!-- --> + <!-- Note: Dependency versions are declared in build.properties --> + <!-- This is a copy of that information. However, there are a --> + <!-- few subtle differences. See build.properties for details. --> + <!-- --> + <icu.version>4.8</icu.version> + <zookeeper.version>3.3.3</zookeeper.version> + <sesame.version>2.6.3</sesame.version> + <slf4j.version>1.6.1</slf4j.version> + <jetty.version>7.2.2.v20101205</jetty.version> + <lucene.version>3.0.0</lucene.version> + <apache.commons_codec.version>1.4</apache.commons_codec.version> + <apache.commons_fileupload.version>1.2.2</apache.commons_fileupload.version> + <apache.commons_io.version>2.1</apache.commons_io.version> + <apache.commons_logging.version>1.1.1</apache.commons_logging.version> + <apache.httpclient.version>4.1.3</apache.httpclient.version> + <apache.httpclient_cache.version>4.1.3</apache.httpclient_cache.version> + <apache.httpcore.version>4.1.4</apache.httpcore.version> + <apache.httpmime.version>4.1.3</apache.httpmime.version> + <nxparser.version>1.2.2</nxparser.version> + <colt.version>1.2.0</colt.version> + <highscalelib.version>1.1.2</highscalelib.version> + <log4j.version>1.2.17</log4j.version> + <fastutil.version>5.1.5</fastutil.version> + <dsiutils.version>1.0.6-020610</dsiutils.version> + <lgplutils.version>1.0.6-020610</lgplutils.version> + <bigdata.ganglia.version>1.0.1</bigdata.ganglia.version> + </properties> + <!-- TODO Can we declare the versions of the dependencies here as + properties and have them be substituted in for us? Can we pick + up those dependency versions from a properties file so we can + share the version declarations in build.properties? If we do + that, will the version numbers be filled in when this POM is + deployed to the systap repository? + + TODO Add ant target to deploy the dependencies that we use that + are not widely (publicly) available to the systap repository. + --> + + <build> + <plugins> + <plugin> + <artifactId>maven-antrun-plugin</artifactId> + <version>1.6</version> + <executions> + <execution> + <goals> + <goal>run</goal> + </goals> + <phase>process-resources</phase> + <configuration> + <target> + <property name="build.ver" value="${project.version}"/> + <property name="build.ver.osgi" value="${project.version}"/> + <property name="snapshot" value="false"/> + <ant antfile="build.xml" target="clean"/> + <ant antfile="build.xml" target="jar"/> + </target> + </configuration> + </execution> + <execution> + <id>attach-artifact</id> + <phase>package</phase> + <goals> + <goal>run</goal> + </goals> + <configuration> + <target> + <attachartifact file="ant-build/bigdata-${project.version}.jar" type="jar"/> + </target> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + <extensions> + <!-- Enabling the use of SSH. --> + <extension> + <groupId>org.apache.maven.wagon</groupId> + <artifactId>wagon-ssh-external</artifactId> + <version>1.0-beta-6</version> + </extension> + </extensions> + </build> + + <distributionManagement> + <repository> + <id>bigdata.releases</id> + <name>bigdata(R) releases</name> + <url>scpexe://shell.speakeasy.net/home/t/thompsonbry/systap.com/maven/releases</url> + </repository> + </distributionManagement> + + <repositories> + <repository> + <id>bigdata.releases</id> + <url>http://www.systap.com/maven/releases/</url> + </repository> + <repository> + <id>nxparser-repo</id> + <url>http://nxparser.googlecode.com/svn/repository</url> + </repository> + <repository> + <id>nxparser-snapshots</id> + <url>http://nxparser.googlecode.com/svn/snapshots</url> + </repository> + <repository> + <id>aduna-opensource.releases</id> + <url>http://repo.aduna-software.org/maven2/releases/</url> + </repository> + <!-- + <repository> + <id>jetty.releases</id> + <url>https://oss.sonatype.org/content/groups/jetty/</url> + </repository> + --> + </repositories> + + <!-- This declares the basic dependencies that you need to use --> + <!-- bigdata as an embedded database. Use ant (build.xml) for --> + <!-- NanoSparqlServer or cluster builds and deployments. --> + + <dependencies> + <!-- --> + <!-- artifacts already present in public repositories --> + <!-- --> + <dependency> + <groupId>com.github.stephenc.high-scale-lib</groupId> + <artifactId>high-scale-lib</artifactId> + <version>${highscalelib.version}</version> + </dependency> + <dependency> + <groupId>org.semanticweb.yars</groupId> + <artifactId>nxparser</artifactId> + <version>${nxparser.version}</version> + </dependency> + <dependency> + <groupId>colt</groupId> + <artifactId>colt</artifactId> + <version>${colt.version}</version> + </dependency> + <dependency> + <groupId>org.apache.lucene</groupId> + <artifactId>lucene-core</artifactId> + <version>${lucene.version}</version> + </dependency> + <dependency> + <groupId>org.apache.lucene</groupId> + <artifactId>lucene-analyzers</artifactId> + <version>${lucene.version}</version> + </dependency> + <dependency> + <groupId>com.ibm.icu</groupId> + <artifactId>icu4j</artifactId> + <version>${icu.version}</version> + </dependency> + <dependency> + <!-- log4j is the primary logger for bigdata. --> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <version>${log4j.version}</version> + <!-- There is a bug with log4j 1.2.15 where it has a lot --> + <!-- of dependencies that we do not need in its POM. The --> + <!-- exclusions are only necessary with that version. --> + <!-- + <exclusions> + <exclusion> + <groupId>javax.jms</groupId> + <artifactId>jms</artifactId> + </exclusion> + <exclusion> + <groupId>com.sun.jdmk</groupId> + <artifactId>jmxtools</artifactId> + </exclusion> + <exclusion> + <groupId>com.sun.jmx</groupId> + <artifactId>jmxri</artifactId> + </exclusion> + </exclusions> + --> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>${apache.httpclient.version}</version> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient-cache</artifactId> + <version>${apache.httpclient_cache.version}</version> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpcore</artifactId> + <version>${apache.httpcore.version}</version> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpmime</artifactId> + <version>${apache.httpmime.version}</version> + </dependency> + <dependency> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + <version>${apache.commons_codec.version}</version> + </dependency> + <dependency> + <groupId>commons-fileupload</groupId> + <artifactId>commons-fileupload</artifactId> + <version>${apache.commons_fileupload.version}</version> + </dependency> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>${apache.commons_io.version}</version> + </dependency> + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + <version>${apache.commons_logging.version}</version> + </dependency> + <!-- --> + <!-- artifacts that we publish (because they are not readily --> + <!-- available) but we do not maintain. --> + <!-- --> + <dependency> + <!-- fastutil.fastutil & it.unimi.dsi.fastutil from central have different versions --> + <!-- fastutil 6.1.0+ is on maven central. --> + <!-- +mvn deploy:deploy-file \ + -DgroupId=it.unimi \ + -DartifactId=fastutil \ + -Dversion=5.1.5 \ + -Dpackaging=jar \ + -DrepositoryId=bigdata.releases \ + -Durl=scpexe://shell.speakeasy.net/home/t/thompsonbry/systap.com/maven/releases/ \ + -Dfile=bigdata/lib/unimi/fastutil-5.1.5.jar + --> + <groupId>it.unimi</groupId> + <artifactId>fastutil</artifactId> + <version>${fastutil.version}</version> + </dependency> + <dependency> + <!-- This ICU dependency is not widely available. --> + <!-- +mvn deploy:deploy-file \ + -DgroupId=com.ibm.icu \ + -DartifactId=icu4j-charset \ + -Dversion=4.8 \ + -Dpackaging=jar \ + -DrepositoryId=bigdata.releases \ + -Durl=scpexe://shell.speakeasy.net/home/t/thompsonbry/systap.com/maven/releases/ \ + -Dfile=bigdata/lib/icu/icu4j-charset-4.8.jar + --> + <groupId>com.ibm.icu</groupId> + <artifactId>icu4j-charset</artifactId> + <version>${icu.version}</version> + </dependency> + <dependency> + <!-- sesame-runtime will pull in the various openrdf compoents. --> + <groupId>org.openrdf.sesame</groupId> + <artifactId>sesame-runtime</artifactId> + <version>${sesame.version}</version> + </dependency> + <!-- --> + <!-- artifacts maintained and published by the bigdata project --> + <dependency> + <!-- +mvn deploy:deploy-file \ + -DgroupId=com.bigdata \ + -DartifactId=bigdata-ganglia \ + -Dversion=1.0.1 \ + -Dpackaging=jar \ + -DrepositoryId=bigdata.releases \ + -Durl=scpexe://shell.speakeasy.net/home/t/thompsonbry/systap.com/maven/releases/ \ + -Dfile=bigdata/lib/bigdata-ganglia-1.0.1.jar + --> + <groupId>com.bigdata</groupId> + <artifactId>bigdata-ganglia</artifactId> + <version>1.0.1</version> + </dependency> + <!-- +mvn deploy:deploy-file \ + -DgroupId=com.bigdata \ + -DartifactId=dsi-utils \ + -Dversion=1.0.6-020610 \ + -Dpackaging=jar \ + -DrepositoryId=bigdata.releases \ + -Durl=scpexe://shell.speakeasy.net/home/t/thompsonbry/systap.com/maven/releases/ \ + -Dfile=bigdata/lib/dsi-utils-1.0.6-020610.jar + --> + <dependency> + <groupId>com.bigdata</groupId> + <artifactId>dsi-utils</artifactId> + <version>${dsiutils.version}</version> + </dependency> + <dependency> + <!-- +mvn deploy:deploy-file \ + -DgroupId=com.bigdata \ + -DartifactId=lgpl-utils \ + -Dversion=1.0.6-020610 \ + -Dpackaging=jar \ + -DrepositoryId=bigdata.releases \ + -Durl=scpexe://shell.speakeasy.net/home/t/thompsonbry/systap.com/maven/releases/ \ + -Dfile=bigdata/lib/lgpl-utils-1.0.6-020610.jar + --> + <groupId>com.bigdata</groupId> + <artifactId>lgpl-utils</artifactId> + <version>${lgplutils.version}</version> + </dependency> + </dependencies> +</project> \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2012-08-03 15:07:07
|
Revision: 6407 http://bigdata.svn.sourceforge.net/bigdata/?rev=6407&view=rev Author: thompsonbry Date: 2012-08-03 15:06:58 +0000 (Fri, 03 Aug 2012) Log Message: ----------- exposed something to GOM Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/web/GOMListener.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServletContextListener.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/web/GOMListener.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/web/GOMListener.java 2012-08-03 15:00:43 UTC (rev 6406) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/web/GOMListener.java 2012-08-03 15:06:58 UTC (rev 6407) @@ -1,26 +1,16 @@ package com.bigdata.gom.web; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.Properties; import java.util.UUID; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; import org.openrdf.repository.RepositoryException; import org.openrdf.sail.SailException; -import com.bigdata.gom.om.IObjectManager; import com.bigdata.gom.om.ObjectManager; -import com.bigdata.rdf.sail.BigdataSail; -import com.bigdata.rdf.sail.BigdataSailRepository; -import com.bigdata.rdf.sail.BigdataSailRepositoryConnection; +import com.bigdata.rdf.sail.webapp.BigdataRDFContext; import com.bigdata.rdf.sail.webapp.BigdataRDFServletContextListener; -import com.bigdata.rdf.sail.webapp.ConfigParams; /** * Extends the BigdataRDFServletContextListener to add a local ObjectManager @@ -43,6 +33,8 @@ final UUID uuid = UUID.fromString(context.getInitParameter("om-uuid")); + final BigdataRDFContext rdfContext = getBigdataRDFContext(); + final String namespace = rdfContext.getConfig().namespace; try { final ObjectManager om = new ObjectManager(uuid, rdfContext.getUnisolatedConnection(namespace)); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServletContextListener.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServletContextListener.java 2012-08-03 15:00:43 UTC (rev 6406) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServletContextListener.java 2012-08-03 15:06:58 UTC (rev 6407) @@ -90,6 +90,12 @@ * which case it will close it at the appropriate life cycle event. */ private boolean closeIndexManager; + + protected BigdataRDFContext getBigdataRDFContext() { + + return rdfContext; + + } public void contextInitialized(final ServletContextEvent e) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2012-08-03 18:58:44
|
Revision: 6408 http://bigdata.svn.sourceforge.net/bigdata/?rev=6408&view=rev Author: thompsonbry Date: 2012-08-03 18:58:38 +0000 (Fri, 03 Aug 2012) Log Message: ----------- Enabling generation of maven snapshots during CI. Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/build.xml branches/BIGDATA_RELEASE_1_2_0/pom.xml Modified: branches/BIGDATA_RELEASE_1_2_0/build.xml =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/build.xml 2012-08-03 15:06:58 UTC (rev 6407) +++ branches/BIGDATA_RELEASE_1_2_0/build.xml 2012-08-03 18:58:38 UTC (rev 6408) @@ -322,6 +322,15 @@ </manifest> </jar> </target> + + <!-- Deploy the JAR to the maven repository. --> + <target name="maven-deploy" depends="jar" + description="Deploy the jar to the maven repository."> + <exec command="mvn"> + <arg value="clean"/> + <arg value="deploy"/> + </exec> + </target> <!-- This generates an osgi bundle jar, but does not bundle the dependencies. See 'bundleJar'. --> Modified: branches/BIGDATA_RELEASE_1_2_0/pom.xml =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/pom.xml 2012-08-03 15:06:58 UTC (rev 6407) +++ branches/BIGDATA_RELEASE_1_2_0/pom.xml 2012-08-03 18:58:38 UTC (rev 6408) @@ -48,7 +48,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>com.bigdata</groupId> <artifactId>bigdata</artifactId> - <version>1.2.1</version> + <version>1.2.2-SNAPSHOT</version> <packaging>pom</packaging> <name>bigdata(R)</name> <description>Bigdata(R) Maven Build</description> @@ -156,6 +156,12 @@ <name>bigdata(R) releases</name> <url>scpexe://shell.speakeasy.net/home/t/thompsonbry/systap.com/maven/releases</url> </repository> + <snapshotRepository> + <id>bigdata.snapshots</id> + <name>bigdata(R) snapshots</name> + <url>scpexe://shell.speakeasy.net/home/t/thompsonbry/systap.com/maven/snapshots</url> + <uniqueVersion>true</uniqueVersion> + </snapshotRepository> </distributionManagement> <repositories> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2012-08-06 11:37:17
|
Revision: 6415 http://bigdata.svn.sourceforge.net/bigdata/?rev=6415&view=rev Author: thompsonbry Date: 2012-08-06 11:37:09 +0000 (Mon, 06 Aug 2012) Log Message: ----------- Rationalized the SolutionSetHashJoinOp by extracting a common base class for both HTree and JVM implementations. Rationalized the HashIndexBuildOp by extracting a common base class for both HTree and JVM implementations. Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContext.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContextBase.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/controller/HTreeNamedSubqueryOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/controller/JVMNamedSubqueryOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/engine/QueryEngine.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashIndexOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinUtility.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeSolutionSetHashJoinOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/IHashJoinUtility.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/JVMHashIndexOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/JVMHashJoinUtility.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/JVMSolutionSetHashJoinOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/joinGraph/rto/Path.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/SolutionSetStream.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/bop/engine/TestQueryEngine_Slice.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/bop/engine/TestQueryEngine_SortOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/QueryHints.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpContext.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ASTEvalHelper.java Added Paths: ----------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HashIndexOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/SolutionSetHashJoinOp.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContext.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContext.java 2012-08-06 11:35:19 UTC (rev 6414) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContext.java 2012-08-06 11:37:09 UTC (rev 6415) @@ -42,6 +42,10 @@ import com.bigdata.bop.engine.IRunningQuery; import com.bigdata.bop.engine.QueryEngine; import com.bigdata.bop.join.BaseJoinStats; +import com.bigdata.bop.solutions.SolutionSetStream; +import com.bigdata.bop.solutions.SolutionSetStream.SolutionSetStreamPredicate; +import com.bigdata.btree.BTree; +import com.bigdata.htree.HTree; import com.bigdata.rdf.internal.IV; import com.bigdata.rdf.internal.impl.bnode.SidIV; import com.bigdata.rdf.model.BigdataBNode; @@ -51,8 +55,10 @@ import com.bigdata.rdf.spo.SPOPredicate; import com.bigdata.relation.accesspath.AccessPath; import com.bigdata.relation.accesspath.IAccessPath; +import com.bigdata.relation.accesspath.IBindingSetAccessPath; import com.bigdata.relation.accesspath.IBlockingBuffer; import com.bigdata.rwstore.sector.IMemoryManager; +import com.bigdata.stream.Stream; import com.bigdata.striterator.ChunkedFilter; import com.bigdata.striterator.CloseableIteratorWrapper; import com.bigdata.striterator.IChunkedIterator; @@ -459,8 +465,83 @@ return getRunningQuery().getAttributes(); } - + /** + * Return an access path for a predicate that identifies a data structure + * which can be resolved to a reference attached to as a query attribute. + * <p> + * This method is used for data structures (including {@link Stream}s, + * {@link HTree}s, and {@link BTree} indices as well as non-durable data + * structures, such as JVM collection classes. When the data structure is + * pre-existing (such as a named solution set whose life cycle is broader + * than the query), then the data structure MUST be resolved during query + * optimization and attached to the {@link IRunningQuery} before operators + * with a dependency on those data structures can execute. + * + * @param predicate + * The predicate. + * + * @return The access path. + * + * @throws RuntimeException + * if the access path could not be resolved. + * + * @see #getQueryAttributes() + */ + public IBindingSetAccessPath<?> getAccessPath(final IPredicate predicate) { + + if (predicate == null) + throw new IllegalArgumentException(); + + /* + * FIXME There are several cases here, one for each type of + * data structure we need to access and each means of identifying + * that data structure. The main case is Stream (for named solution sets). + * If we wind up always modeling a named solution set as a Stream, then + * that is the only case that we need to address. + */ + if(predicate instanceof SolutionSetStream.SolutionSetStreamPredicate) { + + /* + * Resolve the name of the Stream against the query attributes for + * the running query, obtaining a reference to the Stream. Then + * request the access path from the Stream. + * + * TODO We might need to also include the UUID of the top-level + * query since that is where any subquery will have to look to find + * the named solution set. + */ + + @SuppressWarnings("unchecked") + final SolutionSetStreamPredicate<IBindingSet> p = (SolutionSetStreamPredicate<IBindingSet>) predicate; + + final String attributeName = p.getOnlyRelationName(); + + final SolutionSetStream tmp = (SolutionSetStream) getQueryAttributes().get( + attributeName); + + if (tmp == null) { + + /* + * Likely causes include a failure to attach the solution set to + * the query attributes when setting up the query or attaching + * and/or resolving the solution set against the wrong running + * query (especially when the queries are nested). + */ + throw new RuntimeException( + "Could not resolve Stream: predicate=" + predicate); + + } + + return tmp.getAccessPath(predicate); + + } + + throw new UnsupportedOperationException(); + + } + + /** * Return the {@link IMemoryManager} associated with the specified query. * * @param queryId Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContextBase.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContextBase.java 2012-08-06 11:35:19 UTC (rev 6414) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContextBase.java 2012-08-06 11:37:09 UTC (rev 6415) @@ -213,7 +213,8 @@ // } /** - * Obtain an access path reading from relation for the specified predicate. + * Obtain an access path reading from the identified {@link IRelation} using + * the specified {@link IPredicate}. * <p> * Note: Passing in the {@link IRelation} is important since it otherwise * must be discovered using the {@link IResourceLocator}. By requiring the @@ -249,9 +250,6 @@ * * @todo Support mutable relation views (no - just fix truth maintenance). */ -// * <h2>Non-Relation Access Paths</h2> -// * <p> -// * public <E> IAccessPath<E> getAccessPath(final IRelation<E> relation, final IPredicate<E> predicate) { Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/controller/HTreeNamedSubqueryOp.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/controller/HTreeNamedSubqueryOp.java 2012-08-06 11:35:19 UTC (rev 6414) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/controller/HTreeNamedSubqueryOp.java 2012-08-06 11:37:09 UTC (rev 6415) @@ -302,7 +302,7 @@ null, // mergeSolution (aka parent's source solution). null, // selectVars (aka projection). null, // constraints - null // stats updated above. + null // stats were updated above. //context.getStats()// ); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/controller/JVMNamedSubqueryOp.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/controller/JVMNamedSubqueryOp.java 2012-08-06 11:35:19 UTC (rev 6414) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/controller/JVMNamedSubqueryOp.java 2012-08-06 11:37:09 UTC (rev 6415) @@ -182,12 +182,6 @@ */ private final IQueryAttributes attrs; -// /** -// * The join variables. -// */ -// @SuppressWarnings("rawtypes") -// private final IVariable[] joinVars; - /** * <code>true</code> iff this is the first time the task is being * invoked, in which case we will evaluate the subquery and save its @@ -329,7 +323,7 @@ private final BOpContext<IBindingSet> parentContext; /** - * The source binding sets + * The source binding sets. */ private final IBindingSet[] bindingSets; @@ -376,9 +370,6 @@ // Buffer the solutions on the hash index. final long ncopied = state.acceptSolutions( subquerySolutionItr, stats); -// final long ncopied = JVMHashJoinUtility.acceptSolutions( -// subquerySolutionItr, joinVars, stats, -// solutions, false/* optional */); // Wait for the subquery to halt / test for errors. runningSubquery.get(); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/engine/QueryEngine.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/engine/QueryEngine.java 2012-08-06 11:35:19 UTC (rev 6414) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/engine/QueryEngine.java 2012-08-06 11:37:09 UTC (rev 6415) @@ -52,6 +52,7 @@ import com.bigdata.bop.BOp; import com.bigdata.bop.BOpUtility; import com.bigdata.bop.IBindingSet; +import com.bigdata.bop.IQueryAttributes; import com.bigdata.bop.PipelineOp; import com.bigdata.bop.bindingSet.ListBindingSet; import com.bigdata.bop.fed.QueryEngineFactory; @@ -61,9 +62,7 @@ import com.bigdata.concurrent.FutureTaskMon; import com.bigdata.counters.CounterSet; import com.bigdata.counters.ICounterSetAccess; -import com.bigdata.journal.ConcurrencyManager; import com.bigdata.journal.IIndexManager; -import com.bigdata.journal.Journal; import com.bigdata.rawstore.IRawStore; import com.bigdata.rdf.sail.webapp.client.DefaultClientConnectionManagerFactory; import com.bigdata.resources.IndexManager; @@ -1135,8 +1134,8 @@ throws Exception { final UUID queryId = getQueryUUID(op); - - return eval(queryId, (PipelineOp) op, + + return eval(queryId, (PipelineOp) op, null/* attributes */, newLocalChunkMessage(queryId, op, bset)); } @@ -1144,7 +1143,7 @@ public AbstractRunningQuery eval(final UUID queryId, final BOp op, final IBindingSet bset) throws Exception { - return eval(queryId, (PipelineOp) op, + return eval(queryId, (PipelineOp) op, null/* attributes */, newLocalChunkMessage(queryId, op, bset)); } @@ -1152,18 +1151,15 @@ public AbstractRunningQuery eval(final UUID queryId, final BOp op, final IBindingSet[] bset) throws Exception { - return eval(queryId, (PipelineOp) op, + return eval(queryId, (PipelineOp) op, null/* attributes */, newLocalChunkMessage(queryId, op, bset)); -// return eval(queryId, op, bset.length/* solutionCount */, -// newBindingSetIterator(bset)); - } public AbstractRunningQuery eval(final UUID queryId, final BOp op, final IBindingSet[][] bset) throws Exception { - return eval(queryId, (PipelineOp) op, + return eval(queryId, (PipelineOp) op, null/* attributes */, newLocalChunkMessage(queryId, op, bset)); } @@ -1185,14 +1181,35 @@ public AbstractRunningQuery eval(final BOp op, final IBindingSet[] bsets) throws Exception { + return eval(op, bsets, null/* attributes */); + + } + + /** + * Evaluate a query. This node will serve as the controller for the query. + * + * @param query + * The query to evaluate. + * @param bsets + * The initial binding sets to present. + * + * @return The {@link IRunningQuery}. + * + * @throws IllegalStateException + * if the {@link QueryEngine} has been {@link #shutdown()}. + * @throws Exception + */ + public AbstractRunningQuery eval(final BOp op, final IBindingSet[] bsets, + final Map<Object, Object> attribs) throws Exception { + final UUID queryId = getQueryUUID(op); - return eval(queryId, (PipelineOp) op, + return eval(queryId, (PipelineOp) op, attribs, newLocalChunkMessage(queryId, op, bsets)); } - -// /** + + // /** // * Evaluate a query. This node will serve as the controller for the query. // * // * @param query @@ -1261,6 +1278,9 @@ * The unique identifier for the query. * @param query * The query to evaluate. + * @param attribs + * Attributes to be attached to the query before it begins to + * execute (optional). * @param msg * A message providing access to the initial {@link IBindingSet * binding set(s)} used to begin query evaluation. @@ -1274,10 +1294,11 @@ public AbstractRunningQuery eval(// final UUID queryId,// final PipelineOp query,// + final Map<Object,Object> attribs,// final IChunkMessage<IBindingSet> msg// ) throws Exception { - return startEval(queryId, query, msg); + return startEval(queryId, query, null/* attribs */, msg); } @@ -1290,6 +1311,9 @@ * The unique identifier for the query. * @param query * The query to evaluate. + * @param attribs + * Attributes to be attached to the query before it begins to + * execute (optional). * @param msg * A message providing access to the initial {@link IBindingSet * binding set(s)} used to begin query evaluation. @@ -1303,6 +1327,7 @@ private AbstractRunningQuery startEval(// final UUID queryId,// final PipelineOp query,// + final Map<Object, Object> attribs,// final IChunkMessage<IBindingSet> msg// ) throws Exception { @@ -1327,6 +1352,22 @@ true/* controller */, getProxy()/* queryController */, getServiceUUID(), query, msg/* realSource */); + if (attribs != null) { + + /* + * Propagate any initial attributes to the query. + */ + + final IQueryAttributes tmp = runningQuery.getAttributes(); + + for (Map.Entry<Object, Object> e : attribs.entrySet()) { + + tmp.put(e.getKey(), e.getValue()); + + } + + } + final long timeout = query.getProperty(BOp.Annotations.TIMEOUT, BOp.Annotations.DEFAULT_TIMEOUT); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashIndexOp.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashIndexOp.java 2012-08-06 11:35:19 UTC (rev 6414) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashIndexOp.java 2012-08-06 11:37:09 UTC (rev 6415) @@ -28,66 +28,29 @@ package com.bigdata.bop.join; import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.FutureTask; import com.bigdata.bop.BOp; import com.bigdata.bop.BOpContext; -import com.bigdata.bop.BOpEvaluationContext; import com.bigdata.bop.IBindingSet; -import com.bigdata.bop.IQueryAttributes; -import com.bigdata.bop.IVariable; import com.bigdata.bop.NV; -import com.bigdata.bop.PipelineOp; -import com.bigdata.bop.controller.NamedSetAnnotations; import com.bigdata.bop.controller.NamedSolutionSetRef; -import com.bigdata.bop.engine.BOpStats; -import com.bigdata.bop.engine.IRunningQuery; -import com.bigdata.htree.HTree; -import com.bigdata.relation.accesspath.IBlockingBuffer; -import com.bigdata.relation.accesspath.UnsyncLocalOutputBuffer; /** - * Operator builds an {@link HTree} index from the source solutions. Once all - * source solutions have been materialized on the {@link HTree}, the source - * solutions are output on the default sink. The set of variables to be copied - * to the sink may be restricted by an annotation. - * <p> - * There are two basic use cases for the {@link HTreeHashIndexOp}, both of which rely - * on a {@link HTreeSolutionSetHashJoinOp} to re-integrate the results buffered on - * the {@link HTree}. - * <p> - * The first use case is when we will run an OPTIONAL group. In this case, an - * OPTIONAL hash join will be used and a buffered solution will be output if - * there was no solution in the optional group for that buffered solution. All - * known bound variables should be used as the join variables. All variables - * should be selected. - * <p> - * The second use case is when we will run a sub-select. In this case, only the - * variables which are projected by the subquery should be selected. Those will - * also serve as the join variables. The hash join will integrate the solutions - * from the subquery with the buffered solutions using those join variables. The - * integrated solutions will be the net output of the hash join. - * <p> - * This operator is NOT thread-safe. It relies on the query engine to provide - * synchronization. The operator MUST be run on the query controller. + * Concrete implementation based on the {@link HTreeHashJoinUtility}. * * @see HTreeSolutionSetHashJoinOp * * @author <a href="mailto:tho...@us...">Bryan Thompson</a> */ -public class HTreeHashIndexOp extends PipelineOp { +public class HTreeHashIndexOp extends HashIndexOp { -// static private final transient Logger log = Logger -// .getLogger(HashIndexOp.class); - /** * */ private static final long serialVersionUID = 1L; - public interface Annotations extends HTreeHashJoinAnnotations, - NamedSetAnnotations { + public interface Annotations extends HashIndexOp.Annotations, + HTreeHashJoinAnnotations { } @@ -109,50 +72,50 @@ super(args, annotations); - if (getEvaluationContext() != BOpEvaluationContext.CONTROLLER) { - throw new IllegalArgumentException( - BOp.Annotations.EVALUATION_CONTEXT + "=" - + getEvaluationContext()); - } +// if (getEvaluationContext() != BOpEvaluationContext.CONTROLLER) { +// throw new IllegalArgumentException( +// BOp.Annotations.EVALUATION_CONTEXT + "=" +// + getEvaluationContext()); +// } +// +// if (getMaxParallel() != 1) { +// /* +// * Parallel evaluation is not allowed. This operator writes on an +// * object that is not thread-safe for mutation. +// */ +// throw new IllegalArgumentException( +// PipelineOp.Annotations.MAX_PARALLEL + "=" +// + getMaxParallel()); +// } +// +// if (!isLastPassRequested()) { +// /* +// * Last pass evaluation must be requested. This operator will not +// * produce any outputs until all source solutions have been +// * buffered. +// */ +// throw new IllegalArgumentException(PipelineOp.Annotations.LAST_PASS +// + "=" + isLastPassRequested()); +// } +// +// getRequiredProperty(Annotations.NAMED_SET_REF); +// +// @SuppressWarnings("unused") +// final JoinTypeEnum joinType = (JoinTypeEnum) getRequiredProperty(Annotations.JOIN_TYPE); +// +// // Join variables must be specified. +// final IVariable<?>[] joinVars = (IVariable[]) getRequiredProperty(Annotations.JOIN_VARS); +// +//// if (joinVars.length == 0) +//// throw new IllegalArgumentException(Annotations.JOIN_VARS); +// +// for (IVariable<?> var : joinVars) { +// +// if (var == null) +// throw new IllegalArgumentException(Annotations.JOIN_VARS); +// +// } - if (getMaxParallel() != 1) { - /* - * Parallel evaluation is not allowed. This operator writes on an - * HTree and that object is not thread-safe for mutation. - */ - throw new IllegalArgumentException( - PipelineOp.Annotations.MAX_PARALLEL + "=" - + getMaxParallel()); - } - - if (!isLastPassRequested()) { - /* - * Last pass evaluation must be requested. This operator will not - * produce any outputs until all source solutions have been - * buffered. - */ - throw new IllegalArgumentException(PipelineOp.Annotations.LAST_PASS - + "=" + isLastPassRequested()); - } - - getRequiredProperty(Annotations.NAMED_SET_REF); - - @SuppressWarnings("unused") - final JoinTypeEnum joinType = (JoinTypeEnum) getRequiredProperty(Annotations.JOIN_TYPE); - - // Join variables must be specified. - final IVariable<?>[] joinVars = (IVariable[]) getRequiredProperty(Annotations.JOIN_VARS); - -// if (joinVars.length == 0) -// throw new IllegalArgumentException(Annotations.JOIN_VARS); - - for (IVariable<?> var : joinVars) { - - if (var == null) - throw new IllegalArgumentException(Annotations.JOIN_VARS); - - } - } public HTreeHashIndexOp(final BOp[] args, NV... annotations) { @@ -161,211 +124,170 @@ } -// /** -// * Return <code>true</code> iff the solutions on the hash index will be -// * re-integrated using an OPTIONAL join. -// * -// * @see Annotations#OPTIONAL -// */ -// public boolean isOptional() { -// -// return getProperty(Annotations.OPTIONAL, Annotations.DEFAULT_OPTIONAL); -// +// @Override +// public BOpStats newStats() { +// +// return new NamedSolutionSetStats(); +// // } - + @Override - public BOpStats newStats() { + protected HTreeHashJoinUtility newState( + final BOpContext<IBindingSet> context, + final NamedSolutionSetRef namedSetRef, final JoinTypeEnum joinType) { - return new NamedSolutionSetStats(); + return new HTreeHashJoinUtility( + context.getMemoryManager(namedSetRef.queryId), this, joinType); } - -// /** -// * Adds reporting for the size of the named solution set. -// */ -// public static class NamedSolutionSetStats extends BOpStats { + +// public FutureTask<Void> eval(final BOpContext<IBindingSet> context) { +// +// return new FutureTask<Void>(new ControllerTask(this, context)); // -// private static final long serialVersionUID = 1L; +// } + +// /** +// * Evaluates the subquery for each source binding set. If the controller +// * operator is interrupted, then the subqueries are cancelled. If a subquery +// * fails, then all subqueries are cancelled. +// */ +// private static class ControllerTask implements Callable<Void> { +// +// private final BOpContext<IBindingSet> context; +// +// private final HTreeHashIndexOp op; // -// final AtomicLong solutionSetSize = new AtomicLong(); +// private final NamedSolutionSetStats stats; +// +// private final IHashJoinUtility state; +// +// public ControllerTask(final HTreeHashIndexOp op, +// final BOpContext<IBindingSet> context) { // -// public void add(final BOpStats o) { +// if (op == null) +// throw new IllegalArgumentException(); // -// super.add(o); +// if (context == null) +// throw new IllegalArgumentException(); // -// if (o instanceof NamedSolutionSetStats) { +// this.context = context; // -// final NamedSolutionSetStats t = (NamedSolutionSetStats) o; +// this.op = op; +// +// this.stats = ((NamedSolutionSetStats) context.getStats()); // -// solutionSetSize.addAndGet(t.solutionSetSize.get()); +// // Metadata to identify the named solution set. +// final NamedSolutionSetRef namedSetRef = (NamedSolutionSetRef) op +// .getRequiredProperty(Annotations.NAMED_SET_REF); +// +// { // +// /* +// * First, see if the map already exists. +// * +// * Note: Since the operator is not thread-safe, we do not need +// * to use a putIfAbsent pattern here. +// */ +// +// // Lookup the attributes for the query on which we will hang the +// // solution set. +// final IQueryAttributes attrs = context +// .getQueryAttributes(namedSetRef.queryId); +// +// HTreeHashJoinUtility state = (HTreeHashJoinUtility) attrs +// .get(namedSetRef); +// +// if (state == null) { +// +// final JoinTypeEnum joinType = (JoinTypeEnum) op +// .getRequiredProperty(Annotations.JOIN_TYPE); +// +// state = new HTreeHashJoinUtility( +// context.getMemoryManager(namedSetRef.queryId), op, +// joinType); +// +// if (attrs.putIfAbsent(namedSetRef, state) != null) +// throw new AssertionError(); +// +// } +// +// this.state = state; +// // } +// +// } // +// /** +// * Evaluate. +// */ +// public Void call() throws Exception { +// +// try { +// +// // Buffer all source solutions. +// acceptSolutions(); +// +// if(context.isLastInvocation()) { +// +// // Checkpoint the solution set. +// checkpointSolutionSet(); +// +// // Output the buffered solutions. +// outputSolutions(); +// +// } +// +// // Done. +// return null; +// +// } finally { +// +// context.getSource().close(); +// +// context.getSink().close(); +// +// } +// // } // -// @Override -// protected void toString(final StringBuilder sb) { -// super.toString(sb); -// sb.append(",solutionSetSize=" + solutionSetSize.get()); +// /** +// * Buffer intermediate resources. +// */ +// private void acceptSolutions() { +// +// state.acceptSolutions(context.getSource(), stats); +// // } // -// } - - public FutureTask<Void> eval(final BOpContext<IBindingSet> context) { +// /** +// * Checkpoint and save the solution set. +// */ +// private void checkpointSolutionSet() { +// +// state.saveSolutionSet(); +// +// } +// +// /** +// * Output the buffered solutions. +// */ +// private void outputSolutions() { +// +// // default sink +// final IBlockingBuffer<IBindingSet[]> sink = context.getSink(); +// +// final UnsyncLocalOutputBuffer<IBindingSet> unsyncBuffer = new UnsyncLocalOutputBuffer<IBindingSet>( +// op.getChunkCapacity(), sink); +// +// state.outputSolutions(unsyncBuffer); +// +// unsyncBuffer.flush(); +// +// sink.flush(); +// +// } +// +// } // ControllerTask - return new FutureTask<Void>(new ControllerTask(this, context)); - - } - - /** - * Evaluates the subquery for each source binding set. If the controller - * operator is interrupted, then the subqueries are cancelled. If a subquery - * fails, then all subqueries are cancelled. - */ - private static class ControllerTask implements Callable<Void> { - - private final BOpContext<IBindingSet> context; - - private final HTreeHashIndexOp op; - - private final NamedSolutionSetStats stats; - - /** Metadata to identify the named solution set. */ - private final NamedSolutionSetRef namedSetRef; - - /** - * The {@link IQueryAttributes} for the {@link IRunningQuery} off which - * we will hang the named solution set. - */ - private final IQueryAttributes attrs; - - private final HTreeHashJoinUtility state; - - public ControllerTask(final HTreeHashIndexOp op, - final BOpContext<IBindingSet> context) { - - if (op == null) - throw new IllegalArgumentException(); - - if (context == null) - throw new IllegalArgumentException(); - - this.context = context; - - this.op = op; - - this.stats = ((NamedSolutionSetStats) context.getStats()); - - this.namedSetRef = (NamedSolutionSetRef) op - .getRequiredProperty(Annotations.NAMED_SET_REF); - - { - - /* - * First, see if the map already exists. - * - * Note: Since the operator is not thread-safe, we do not need - * to use a putIfAbsent pattern here. - */ - - // Lookup the attributes for the query on which we will hang the - // solution set. - attrs = context.getQueryAttributes(namedSetRef.queryId); - - HTreeHashJoinUtility state = (HTreeHashJoinUtility) attrs - .get(namedSetRef); - - if (state == null) { - - final JoinTypeEnum joinType = (JoinTypeEnum) op - .getRequiredProperty(Annotations.JOIN_TYPE); - - state = new HTreeHashJoinUtility( - context.getMemoryManager(namedSetRef.queryId), op, - joinType); - - if (attrs.putIfAbsent(namedSetRef, state) != null) - throw new AssertionError(); - - } - - this.state = state; - - } - - } - - /** - * Evaluate. - */ - public Void call() throws Exception { - - try { - - // Buffer all source solutions. - state.acceptSolutions(context.getSource(), stats); - - if(context.isLastInvocation()) { - - /* - * Note: The [HTree] object is already present on the - * IQueryAttributes. However, it is the mutable HTree - * object. We convert it to an immutable HTree object here - * by check pointing the HTree and updating the reference on - * the IQueryAttributes. That would allow the consumer of - * the HTree to be safe for concurrent readers. - * - * Note: We must checkpoint the solution set before we - * output anything. Otherwise the chunks output by this - * operator could appear at the SolutionSetHashJoinOp before - * this operator is done and it would have the mutable view - * of the HTree rather than the concurrent read-only view of - * the HTree. - */ - - // Checkpoint and save the solution set. - state.saveSolutionSet(); - - // Output the buffered solutions. - outputSolutions(); - - } - - // Done. - return null; - - } finally { - - context.getSource().close(); - - context.getSink().close(); - -// if (context.getSink2() != null) -// context.getSink2().close(); - - } - - } - - /** - * Output the buffered solutions. - */ - private void outputSolutions() { - - // default sink - final IBlockingBuffer<IBindingSet[]> sink = context.getSink(); - - final UnsyncLocalOutputBuffer<IBindingSet> unsyncBuffer = new UnsyncLocalOutputBuffer<IBindingSet>( - op.getChunkCapacity(), sink); - - state.outputSolutions(unsyncBuffer); - - unsyncBuffer.flush(); - - sink.flush(); - - } - - } // ControllerTask - } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinUtility.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinUtility.java 2012-08-06 11:35:19 UTC (rev 6414) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinUtility.java 2012-08-06 11:37:09 UTC (rev 6415) @@ -43,6 +43,7 @@ import com.bigdata.bop.IBindingSet; import com.bigdata.bop.IConstant; import com.bigdata.bop.IConstraint; +import com.bigdata.bop.IQueryAttributes; import com.bigdata.bop.IVariable; import com.bigdata.bop.IndexAnnotations; import com.bigdata.bop.PipelineOp; @@ -559,10 +560,12 @@ } /** - * Checkpoint the {@link HTree} instance(s) used to buffer the source - * solutions ({@link #rightSolutions} and {@link #ivCache}) and then - * re-load the them in a read-only mode from their checkpoint(s). This - * exposes a view of the {@link HTree} which is safe for concurrent + * {@inheritDoc} + * <p> + * This implementation checkpoints the {@link HTree} instance(s) used to + * buffer the source solutions ({@link #rightSolutions} and {@link #ivCache} + * ) and then re-load the them in a read-only mode from their checkpoint(s). + * This exposes a view of the {@link HTree} which is safe for concurrent * readers. */ public void saveSolutionSet() { @@ -582,22 +585,22 @@ } - /** - * Checkpoint the join set (used to buffer the optional solutions). - * <p> - * Note: Since we always output the solutions which did not join from a - * single thread as part of last pass evaluation there is no need to - * checkpoint the {@link #joinSet}. - */ - public void checkpointJoinSet() { +// /** +// * Checkpoint the join set (used to buffer the optional solutions). +// * <p> +// * Note: Since we always output the solutions which did not join from a +// * single thread as part of last pass evaluation there is no need to +// * checkpoint the {@link #joinSet}. +// */ +// public void checkpointJoinSet() { +// +// if (!open.get()) +// throw new IllegalStateException(); +// +// checkpointHTree(joinSet); +// +// } - if (!open.get()) - throw new IllegalStateException(); - - checkpointHTree(joinSet); - - } - private void checkpointHTree(final AtomicReference<HTree> ref) { final HTree tmp = ref.get(); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeSolutionSetHashJoinOp.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeSolutionSetHashJoinOp.java 2012-08-06 11:35:19 UTC (rev 6414) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeSolutionSetHashJoinOp.java 2012-08-06 11:37:09 UTC (rev 6415) @@ -28,53 +28,23 @@ package com.bigdata.bop.join; import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.FutureTask; import com.bigdata.bop.BOp; -import com.bigdata.bop.BOpContext; -import com.bigdata.bop.BOpUtility; -import com.bigdata.bop.IBindingSet; -import com.bigdata.bop.IConstraint; -import com.bigdata.bop.IQueryAttributes; -import com.bigdata.bop.IVariable; import com.bigdata.bop.NV; -import com.bigdata.bop.PipelineOp; -import com.bigdata.bop.controller.HTreeNamedSubqueryOp; -import com.bigdata.bop.controller.NamedSetAnnotations; -import com.bigdata.bop.controller.NamedSolutionSetRef; -import com.bigdata.bop.engine.IRunningQuery; import com.bigdata.htree.HTree; -import com.bigdata.relation.accesspath.AbstractUnsynchronizedArrayBuffer; -import com.bigdata.relation.accesspath.IBlockingBuffer; -import com.bigdata.relation.accesspath.UnsyncLocalOutputBuffer; -import com.bigdata.striterator.Dechunkerator; -import com.bigdata.striterator.ICloseableIterator; /** - * Operator joins a solution set into the pipeline. The solution set must be be - * constructed by a {@link HTreeNamedSubqueryOp} or a {@link HTreeHashIndexOp}. While this - * JOIN requires the RHS {@link HTree} to be fully materialized, evaluation of - * the LHS source solutions is pipelined. Parallel evaluation of source chunks - * is permitted, but the RHS {@link HTree} must have been checkpointed before - * this operator begins evaluation (the read-only {@link HTree} is thread-safe - * for concurrent readers). + * {@inheritDoc} + * <p> + * {@link HTree} Specific version. * - * <h2>Handling OPTIONAL</h2> - * - * {@link PipelineOp.Annotations#LAST_PASS} evaluation MUST be requested for an - * OPTIONAL JOIN because we must have ALL solutions on hand in order to decide - * which solutions did not join. If the JOIN is OPTIONAL, then solutions which - * join will be output for each source chunk but the "optional" solutions will - * not be reported until ALL source chunks have been processed. - * * @see HTreeHashJoinUtility * * @author <a href="mailto:tho...@us...">Bryan Thompson</a> * @version $Id: NamedSubqueryIncludeOp.java 5178 2011-09-12 19:09:23Z * thompsonbry $ */ -public class HTreeSolutionSetHashJoinOp extends PipelineOp { +public class HTreeSolutionSetHashJoinOp extends SolutionSetHashJoinOp { // static private final transient Logger log = Logger // .getLogger(HTreeSolutionSetHashJoinOp.class); @@ -84,66 +54,32 @@ */ private static final long serialVersionUID = 1L; - public interface Annotations extends PipelineOp.Annotations, - NamedSetAnnotations { - - /** - * Constraints to be applied by the join (in addition to any associated - * with the {@link HTreeHashJoinUtility} state in the - * {@link #NAMED_SET_REF}). - */ - final String CONSTRAINTS = JoinAnnotations.CONSTRAINTS; - +// public interface Annotations extends PipelineOp.Annotations, +// NamedSetAnnotations { +// // /** -// * When <code>true</code>, the source is presumed to have very low -// * cardinality (typically one solution, often with no bindings) and the -// * JOIN is performed using a full scan of the hash index, joining each -// * solution in turn against each of the source solution(s) (default -// * <code>false</code>). This approach allows us to perform a join when -// * the hash index was build using join variable(s) but the source -// * solution(s) will not have binding(s) for those join variable(s). +// * An {@link IConstraint}[] to be applied to solutions when they are +// * joined (optional). +// */ +// final String CONSTRAINTS = JoinAnnotations.CONSTRAINTS; +// +// /** +// * When <code>true</code> the hash index identified by +// * {@link #NAMED_SET_REF} will be released when this operator is done +// * (default {@value #DEFAULT_RELEASE}). // * <p> -// * The most common use case is an INCLUDE of a named solution set at the -// * start of a (sub-)query plan. There is just one empty solution flowing -// * into the hash join. Since there is nothing bound in that solution, if -// * we restrict the hash index to share join variables with that solution -// * it will not have any join variables. -// * -// * @see bigdata-perf/CI/govtrack/queries/query10.rq -// * @see bigdata-perf/CI/govtrack/queries/query0021.rq +// * Note: Whether or not the hash index can be released depends on +// * whether or not the hash index will be consumed by more than one +// * operator in the query plan. For example, a named solution set can be +// * consumed by more than one operator and thus must not be released +// * until all such operators are done. // */ -// String FLIP_JOIN = HashJoinAnnotations.class.getName() + ".flipJoin"; +// final String RELEASE = HTreeSolutionSetHashJoinOp.class + ".release"; +// +// final boolean DEFAULT_RELEASE = true; // -// boolean DEFAULT_FLIP_JOIN = false; +// } - /** - * When <code>true</code> the hash index identified by - * {@link #NAMED_SET_REF} will be released when this operator is done - * (default {@value #DEFAULT_RELEASE}). - * <p> - * Note: Whether or not the hash index can be released depends on - * whether or not the hash index will be consumed by more than one - * operator in the query plan. For example, a named solution set can be - * consumed by more than one operator and thus must not be released - * until all such operators are done. - * - * TODO Alternatively, we could specify the #of different locations in - * the query plan where the named solution set will be consumed. This - * could be part of the {@link HTreeHashJoinUtility} state, in which - * case it would only be set as an annotation on the operator which - * generates the hash index. - * <p> - * Note: Any memory associated with the {@link IRunningQuery} will be - * released no later than when the {@link IRunningQuery#isDone()}. This - * only provides a means to release data as soon as it is known that the - * data will not be referenced again during the query. - */ - final String RELEASE = HTreeSolutionSetHashJoinOp.class + ".release"; - - final boolean DEFAULT_RELEASE = true; - - } - /** * Deep copy constructor. */ @@ -164,19 +100,19 @@ super(args, annotations); - if (getProperty(Annotations.RELEASE, Annotations.DEFAULT_RELEASE) - && !isLastPassRequested()) { - /* - * In order to release the hash index, this operator needs to be - * notified when no more source solutions will become available. - */ - throw new IllegalArgumentException(Annotations.RELEASE - + " requires " + Annotations.LAST_PASS); - } +// if (getProperty(Annotations.RELEASE, Annotations.DEFAULT_RELEASE) +// && !isLastPassRequested()) { +// /* +// * In order to release the hash index, this operator needs to be +// * notified when no more source solutions will become available. +// */ +// throw new IllegalArgumentException(Annotations.RELEASE +// + " requires " + Annotations.LAST_PASS); +// } +// +// // The RHS annotation must be specified. +// getRequiredProperty(Annotations.NAMED_SET_REF); - // The RHS HTree annotation must be specified. - getRequiredProperty(Annotations.NAMED_SET_REF); - } public HTreeSolutionSetHashJoinOp(final BOp[] args, NV... annotations) { @@ -184,239 +120,216 @@ this(args, NV.asMap(annotations)); } - + +// public BaseJoinStats newStats() { +// +// return new BaseJoinStats(); +// +// } +// +// @Override +// public FutureTask<Void> eval(BOpContext<IBindingSet> context) { +// +// return new FutureTask<Void>(new ChunkTask<IBindingSet>(context, this)); +// +// } +// // /** -// * @see Annotations#RELEASE +// * Task executing on the node. // */ -// protected boolean isRelease() { +// private static class ChunkTask<E> implements Callable<Void> { +// +// private final BOpContext<IBindingSet> context; +// +// private final HTreeSolutionSetHashJoinOp op; +// +// private final HTreeHashJoinUtility state; +// +// private final IConstraint[] constraints; // -// return getProperty(Annotations.RELEASE, Annotations.DEFAULT_RELEASE); +// private final boolean release; // -// } - - public BaseJoinStats newStats() { - - return new BaseJoinStats(); - - } - - @Override - public FutureTask<Void> eval(BOpContext<IBindingSet> context) { - - return new FutureTask<Void>(new ChunkTask<IBindingSet>(context, this)); - - } - - /** - * Task executing on the node. - */ - private static class ChunkTask<E> implements Callable<Void> { - - private final BOpContext<IBindingSet> context; - - private final HTreeSolutionSetHashJoinOp op; - - private final boolean release; - - private final BaseJoinStats stats; - - private final IBlockingBuffer<IBindingSet[]> sink; - - private final IBlockingBuffer<IBindingSet[]> sink2; - - private final IConstraint[] constraints; - - private final HTreeHashJoinUtility state; - - public ChunkTask(final BOpContext<IBindingSet> context, - final HTreeSolutionSetHashJoinOp op) { - - this.context = context; - - this.stats = (BaseJoinStats) context.getStats(); - - this.release = op.getProperty(Annotations.RELEASE, - Annotations.DEFAULT_RELEASE); - - this.sink = context.getSink(); - - this.sink2 = context.getSink2(); - - this.op = op; - - // The name of the attribute used to discover the solution set. - final NamedSolutionSetRef namedSetRef = (NamedSolutionSetRef) op - .getRequiredProperty(Annotations.NAMED_SET_REF); - - // Lookup the attributes for the query on which we will hang the - // solution set. - final IQueryAttributes attrs = context - .getQueryAttributes(namedSetRef.queryId); - - state = (HTreeHashJoinUtility) attrs.get(namedSetRef); - - if (state == null) { - - // The solution set was not found! - - throw new RuntimeException("Not found: " + namedSetRef); - - } - - if (!state.getJoinType().isNormal() && !op.isLastPassRequested()) { - - /* - * An optional join requires that we observe all solutions - * before we report "optional" solutions so we can identify - * those which do not join. - */ - - throw new UnsupportedOperationException(state.getJoinType() - + " requires " + Annotations.LAST_PASS); - - } - - /* - * Combine the original constraints (if any) with those attached to - * this operator (if any). - * - * Note: The solution set hash join is used to join in a hash index - * generated by some other part of the query plan. Since it is also - * used for named subqueries, which can be included in more than one - * location, it is necessary that we can override/expand on the join - * constraints for this operator. - */ - this.constraints = BOpUtility.concat( - (IConstraint[]) op.getProperty(Annotations.CONSTRAINTS), - state.getConstraints()); - - } - - public Void call() throws Exception { - - try { - - doHashJoin(); - - // Done. - return null; - - } finally { - - if (release && context.isLastInvocation()) { - - /* - * Note: It is possible to INCLUDE the named temporary - * solution set multiple times within a query. If we want to - * release() the hash tree then we need to know how many - * times the temporary solution set is being included and - * decrement a counter each time. When the counter reaches - * zero, we can release the HTree. - */ - state.release(); - - } - - sink.close(); - - if (sink2 != null) - sink2.close(); - - } - - } - - /** - * Do a hash join of the buffered solutions with the access path. - */ - private void doHashJoin() { - - if (state.isEmpty()) - return; - - stats.accessPathCount.increment(); - - stats.accessPathRangeCount.add(state.getRightSolutionCount()); - - final UnsyncLocalOutputBuffer<IBindingSet> unsyncBuffer = new UnsyncLocalOutputBuffer<IBindingSet>( - op.getChunkCapacity(), sink); - - final ICloseableIterator<IBindingSet> leftItr = new Dechunkerator<IBindingSet>( - context.getSource()); - - state.hashJoin2(leftItr, unsyncBuffer, //true/* leftIsPipeline */, - constraints); - - if (context.isLastInvocation()) { - - switch (state.getJoinType()) { - case Normal: - /* - * Nothing to do. - */ - break; - case Optional: - case NotExists: { - /* - * Output the optional solutions. - */ - - // where to write the optional solutions. - final AbstractUnsynchronizedArrayBuffer<IBindingSet> unsyncBuffer2 = sink2 == null ? unsyncBuffer - : new UnsyncLocalOutputBuffer<IBindingSet>( - op.getChunkCapacity(), sink2); - - state.outputOptionals(unsyncBuffer2); - - unsyncBuffer2.flush(); - if (sink2 != null) - sink2.flush(); - - break; - } - case Exists: { - /* - * Output the join set. - * - * Note: This has special hooks to support (NOT) EXISTS - * graph patterns, which must bind the "ASK_VAR" depending - * on whether or not the graph pattern is satisified. - */ - final IVariable<?> askVar = state.getAskVar(); - // askVar := true - state.outputJoinSet(unsyncBuffer); - if (askVar != null) { - // askVar := false; - state.outputOptionals(unsyncBuffer); - } - break; - } - default: - throw new AssertionError(); - } - - } - -// if (!state.getJoinType().isNormal() && context.isLastInvocation()) { +// private final BaseJoinStats stats; // -// // where to write the optional solutions. -// final AbstractUnsynchronizedArrayBuffer<IBindingSet> unsyncBuffer2 = sink2 == null ? unsyncBuffer -// : new UnsyncLocalOutputBuffer<IBindingSet>( -// op.getChunkCapacity(), sink2); +// private final IBlockingBuffer<IBindingSet[]> sink; +// +// private final IBlockingBuffer<IBindingSet[]> sink2; // -// state.outputOptionals(unsyncBuffer2); +// public ChunkTask(final BOpContext<IBindingSet> context, +// final HTreeSolutionSetHashJoinOp op) { // -// unsyncBuffer2.flush(); +// this.context = context; +// +// this.stats = (BaseJoinStats) context.getStats(); +// +// this.release = op.getProperty(Annotations.RELEASE, +// Annotations.DEFAULT_RELEASE); +// +// this.sink = context.getSink(); +// +// this.sink2 = context.getSink2(); +// +// this.op = op; +// +// // The name of the attribute used to discover the solution set. +// final NamedSolutionSetRef namedSetRef = (NamedSolutionSetRef) op +// .getRequiredProperty(Annotations.NAMED_SET_REF); +// +// // Lookup the attributes for the query on which we will hang the +// // solution set. +// final IQueryAttributes attrs = context +// .getQueryAttributes(namedSetRef.queryId); +// +// state = (HTreeHashJoinUtility) attrs.get(namedSetRef); +// +// if (state == null) { +// +// // The solution set was not found! +// +// throw new RuntimeException("Not found: " + namedSetRef); +// +// } +// +// if (!state.getJoinType().isNormal() && !op.isLastPassRequested()) { +// +// /* +// * Anything but a Normal join requires that we observe all solutions +// * and then do some final reporting. This is necessary for Optional, +// * Exists, and NotExists. +// */ +// +// throw new UnsupportedOperationException(state.getJoinType() +// + " requires " + Annotations.LAST_PASS); +// +// } +// +// /* +// * Combine the original constraints (if any) with those attached to +// * this operator (if any). +// * +// * Note: The solution set hash join is used to join in a hash index +// * generated by some other part of the query plan. Since it is also +// * used for named subqueries, which can be included in more than one +// * location, it is necessary that we can override/expand on the join +// * constraints for this operator. +// */ +// this.constraints = BOpUtility.concat( +// (IConstraint[]) op.getProperty(Annotations.CONSTRAINTS), +// state.getConstraints()); +// +// } +// +// public Void call() throws Exception { +// +// try { +// +// doHashJoin(); +// +// // Done. +// return null; +// +// } finally { +// +// if (release && context.isLastInvocation()) { +// +// /* +// * Note: It is possible to INCLUDE the named temporary +// * solution set multiple times within a query. If we want to +// * release() the hash tree then we need to know how many +// * times the temporary solution set is being included and +// * decrement a counter each time. When the counter reaches +// * zero, we can release the hash index. +// */ +// +// state.release(); +// +// } +// +// sink.close(); +// // if (sink2 != null) -// sink2.flush(); +// sink2.close(); +// +// } // +// } +// +// /** +// * Do a hash join of the buffered solutions with the access path. +// */ +// private void doHashJoin() { +// +// if (state.isEmpty()) +// return; +// +// stats.accessPathCount.increment(); +// +// stats.accessPathRangeCount.add(state.getRightSolutionCount()); +// +// final UnsyncLocalOutputBuffer<IBindingSet> unsyncBuffer = new UnsyncLocalOutputBuffer<IBindingSet>( +// op.getChunkCapacity(), sink); +// +// final ICloseableIterator<IBindingSet> leftItr = new Dechunkerator<IBindingSet>( +// context.getSource()); +// +// state.hashJoin2(leftItr, unsyncBuffer, //true/* leftIsPipeline */, +// constraints); +// +// if (context.isLastInvocation()) { +// +// switch (state.getJoinType()) { +// case Normal: +// /* +// * Nothing to do. +// */ +// break; +// case Optional: +// case NotExists: { +// /* +// * Output the optional solutions. +// */ +// +// // where to write the optional solutions. +// final AbstractUnsynchronizedArrayBuffer<IBindingSet> unsyncBuffer2 = sink2 == null ? unsyncBuffer +// : new UnsyncLocalOutputBuffer<IBindingSet>( +// op.getChunkCapacity(), sink2); +// +// ... [truncated message content] |
From: <mrp...@us...> - 2012-08-06 15:47:52
|
Revision: 6417 http://bigdata.svn.sourceforge.net/bigdata/?rev=6417&view=rev Author: mrpersonick Date: 2012-08-06 15:47:41 +0000 (Mon, 06 Aug 2012) Log Message: ----------- fixed a problem where StatementPatternNode was incorrectly reporting its produced bindings in the case where we'd replaced a VarNode with a ConstantNode when the var is known to be bound. related to ticket 405 Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/Constant.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/StatementPatternNode.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/Constant.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/Constant.java 2012-08-06 15:46:27 UTC (rev 6416) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/Constant.java 2012-08-06 15:47:41 UTC (rev 6417) @@ -265,5 +265,12 @@ throw new UnsupportedOperationException(); } + + @SuppressWarnings("unchecked") + final public IVariable<E> getVar() { + + return (IVariable<E>) getProperty(Annotations.VAR); + + } } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/StatementPatternNode.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/StatementPatternNode.java 2012-08-06 15:46:27 UTC (rev 6416) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/StatementPatternNode.java 2012-08-06 15:47:41 UTC (rev 6417) @@ -9,6 +9,7 @@ import org.openrdf.query.algebra.StatementPattern.Scope; import com.bigdata.bop.BOp; +import com.bigdata.bop.Constant; import com.bigdata.bop.IVariable; import com.bigdata.bop.NV; import com.bigdata.htree.HTree; @@ -481,25 +482,56 @@ final TermNode o = o(); final TermNode c = c(); - if (s instanceof VarNode) { - producedBindings.add(((VarNode) s).getValueExpression()); - } +// if (s instanceof VarNode) { +// producedBindings.add(((VarNode) s).getValueExpression()); +// } +// +// if (p instanceof VarNode) { +// producedBindings.add(((VarNode) p).getValueExpression()); +// } +// +// if (o instanceof VarNode) { +// producedBindings.add(((VarNode) o).getValueExpression()); +// } +// +// if (c != null && c instanceof VarNode) { +// producedBindings.add(((VarNode) c).getValueExpression()); +// } - if (p instanceof VarNode) { - producedBindings.add(((VarNode) p).getValueExpression()); - } - - if (o instanceof VarNode) { - producedBindings.add(((VarNode) o).getValueExpression()); - } - - if (c != null && c instanceof VarNode) { - producedBindings.add(((VarNode) c).getValueExpression()); - } - + addProducedBindings(s, producedBindings); + addProducedBindings(p, producedBindings); + addProducedBindings(o, producedBindings); + addProducedBindings(c, producedBindings); + return producedBindings; } + + /** + * This handles the special case where we've wrapped a Var with a Constant + * because we know it's bound, perhaps by the exogenous bindings. If we + * don't handle this case then we get the join vars wrong. + * + * @see StaticAnalysis._getJoinVars + */ + private void addProducedBindings(final TermNode t, final Set<IVariable<?>> producedBindings) { + + if (t instanceof VarNode) { + + producedBindings.add(((VarNode) t).getValueExpression()); + + } else if (t instanceof ConstantNode) { + + final ConstantNode cNode = (ConstantNode) t; + final Constant<?> c = (Constant<?>) cNode.getValueExpression(); + final IVariable<?> var = c.getVar(); + if (var != null) { + producedBindings.add(var); + } + + } + + } public String toString(final int indent) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2012-08-07 19:26:49
|
Revision: 6421 http://bigdata.svn.sourceforge.net/bigdata/?rev=6421&view=rev Author: thompsonbry Date: 2012-08-07 19:26:40 +0000 (Tue, 07 Aug 2012) Log Message: ----------- - Added indexScan() method to IHashJoinUtility and unit tests for that method. - Added NAMED_SET_SOURCE_REF to HashIndexOp. When specified, the hash index is generated for the solutions read from this named solution set rather than the solutions read from the pipelined. Wrote unit test for building a hash index from a SolutionSetStream. - Abstracted HTreeHashJoinOp and JVMHashJoinOp with most logic now residing in the abstract base class HashJoinOp. - A nested loop join has been implemented. This was originally called NamedSolutionSetScanOp, but it just just a nested loop join so I have renamed it as "NestedLoopJoinOp" and generalized the operator such that it can accept named solution sets, streams, etc. for the access path to be scanned for each source solution. - Generalized HashJoinOp, HashIndexOp, and NestedLoopJoin to support any of the following as inputs: IHashJoinUtility (existing named subquery solution sets), IPredicate (AP on locatable relation), or solutions on an ISimpleIndexAccess (HTree, BTree, SolutionSetStream). These operators only require a scan of the right hand solutions. That "scan" should be compatible even with a remote or distributed SPARQL cache. The access path and predicate abstractions are not be necessary for SolutionSetStream, at least for now. I have commented them out. Resolution is now handled by BOpContext. It currently handles named subqueries and the SPARQL CACHE. I still need to add in support for the local index manager and the federation index manager. It seems that support is not quite finished in AbstractJournal for accessing named indices other than B+Tree and (to a lesser extent) HTree. - The solution set cache test suite is now passing. - Exposed getUnisolatedView(String name) on AbstractJournal. This version works for any type of persistence capable index. There are also type-safe methods for HTree, BTree, and (now) Stream. AbstractJournal#getIndexWithCheckpointAddr(long:addr) is also exposed now. There is a type-safe version of this method for BTree and HTree, but I am not sure that we really need those type-safe versions. Ditto for getIndexWithCommitRecord(name,commitRecord). Dropped getHTree(long) [unused] in favor of the version that is not type specific. Dropped getIndex(long) in favor of the version that is not type specific. Dropped getIndex(String:name,ICommitRecord:commitRecord) in favor of the version that is not type specific. There are callers of this method that need to be reviewed. For example, DumpJournal assumes that the only named indices are BTree objects. Added getIndexLocal(name,timestamp) that is specific for local named index data structures, but not specific to the B+Tree (HTree, Stream, etc. are all supported). Added TODO on getIndexLocal( name, timestamp) to finish resolving the tension at this point in the API. @see https://sourceforge.net/apps/trac/bigdata/ticket/531 (SPARQL UPDATE for SOLUTION SETS) Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContext.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContextBase.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpUtility.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/controller/NamedSetAnnotations.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/engine/QueryEngine.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinUtility.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HashIndexOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/IHashJoinUtility.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/JVMHashJoinOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/JVMHashJoinUtility.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/solutions/SolutionSetStream.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/BTree.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/btree/ReadCommittedView.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/AbstractJournal.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/CompactTask.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/DumpJournal.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/journal/Options.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/resources/IndexManager.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/stream/Stream.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/bop/engine/TestQueryEngine.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/bop/fed/TestFederatedQueryEngine.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/bop/join/AbstractHashJoinUtilityTestCase.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/bop/join/TestAll.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/bop/join/TestHTreeHashIndexOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/journal/TestCommitHistory.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/QueryHints.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/SolutionSetStatserator.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/SparqlCache.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpContext.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpJoins.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUpdate.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpUtility.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/cache/TestSparqlCache.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/TestInclude.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/TestNamedSubQuery.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/TestQueryHints.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/include_03.srx branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestASTBottomUpOptimizer.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFContext.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/tck/BigdataSPARQLUpdateTest.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/test/com/bigdata/rdf/sail/tck/BigdataSPARQLUpdateTest2.java Added Paths: ----------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HashJoinOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/NestedLoopJoinOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/bop/join/HashIndexOpTestCase.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/bop/join/TestJVMHashIndexOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/bop/join/TestNestedLoopJoinOp.java Removed Paths: ------------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/AbstractHashJoinOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/NamedSolutionSetScanOp.java branches/BIGDATA_RELEASE_1_2_0/bigdata/src/test/com/bigdata/bop/join/TestNamedSolutionSetScanOp.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContext.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContext.java 2012-08-06 19:03:39 UTC (rev 6420) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContext.java 2012-08-07 19:26:40 UTC (rev 6421) @@ -36,30 +36,30 @@ import org.apache.http.conn.ClientConnectionManager; import com.bigdata.bop.bindingSet.ListBindingSet; +import com.bigdata.bop.controller.NamedSolutionSetRef; import com.bigdata.bop.engine.BOpStats; import com.bigdata.bop.engine.IChunkMessage; import com.bigdata.bop.engine.IQueryClient; import com.bigdata.bop.engine.IRunningQuery; import com.bigdata.bop.engine.QueryEngine; import com.bigdata.bop.join.BaseJoinStats; -import com.bigdata.bop.solutions.SolutionSetStream; -import com.bigdata.bop.solutions.SolutionSetStream.SolutionSetStreamPredicate; -import com.bigdata.btree.BTree; -import com.bigdata.htree.HTree; +import com.bigdata.bop.join.IHashJoinUtility; +import com.bigdata.btree.ISimpleIndexAccess; import com.bigdata.rdf.internal.IV; import com.bigdata.rdf.internal.impl.bnode.SidIV; import com.bigdata.rdf.model.BigdataBNode; import com.bigdata.rdf.sparql.ast.QueryHints; +import com.bigdata.rdf.sparql.ast.cache.ISparqlCache; +import com.bigdata.rdf.sparql.ast.cache.SparqlCacheFactory; import com.bigdata.rdf.spo.ISPO; import com.bigdata.rdf.spo.SPO; import com.bigdata.rdf.spo.SPOPredicate; import com.bigdata.relation.accesspath.AccessPath; import com.bigdata.relation.accesspath.IAccessPath; -import com.bigdata.relation.accesspath.IBindingSetAccessPath; import com.bigdata.relation.accesspath.IBlockingBuffer; import com.bigdata.rwstore.sector.IMemoryManager; -import com.bigdata.stream.Stream; import com.bigdata.striterator.ChunkedFilter; +import com.bigdata.striterator.Chunkerator; import com.bigdata.striterator.CloseableIteratorWrapper; import com.bigdata.striterator.IChunkedIterator; import com.bigdata.striterator.ICloseableIterator; @@ -466,81 +466,199 @@ } +// /** +// * Return an access path for a predicate that identifies a data structure +// * which can be resolved to a reference attached to as a query attribute. +// * <p> +// * This method is used for data structures (including {@link Stream}s, +// * {@link HTree}s, and {@link BTree} indices as well as non-durable data +// * structures, such as JVM collection classes. When the data structure is +// * pre-existing (such as a named solution set whose life cycle is broader +// * than the query), then the data structure MUST be resolved during query +// * optimization and attached to the {@link IRunningQuery} before operators +// * with a dependency on those data structures can execute. +// * +// * @param predicate +// * The predicate. +// * +// * @return The access path. +// * +// * @throws RuntimeException +// * if the access path could not be resolved. +// * +// * @see #getQueryAttributes() +// */ +// public IBindingSetAccessPath<?> getAccessPath(final IPredicate predicate) { +// +// if (predicate == null) +// throw new IllegalArgumentException(); +// +// /* +// * FIXME There are several cases here, one for each type of +// * data structure we need to access and each means of identifying +// * that data structure. The main case is Stream (for named solution sets). +// * If we wind up always modeling a named solution set as a Stream, then +// * that is the only case that we need to address. +// */ +// if(predicate instanceof SolutionSetStream.SolutionSetStreamPredicate) { +// +// /* +// * Resolve the name of the Stream against the query attributes for +// * the running query, obtaining a reference to the Stream. Then +// * request the access path from the Stream. +// * +// * TODO We might need to also include the UUID of the top-level +// * query since that is where any subquery will have to look to find +// * the named solution set. +// */ +// +// @SuppressWarnings("unchecked") +// final SolutionSetStreamPredicate<IBindingSet> p = (SolutionSetStreamPredicate<IBindingSet>) predicate; +// +// final String attributeName = p.getOnlyRelationName(); +// +// final SolutionSetStream tmp = (SolutionSetStream) getQueryAttributes().get( +// attributeName); +// +// if (tmp == null) { +// +// /* +// * Likely causes include a failure to attach the solution set to +// * the query attributes when setting up the query or attaching +// * and/or resolving the solution set against the wrong running +// * query (especially when the queries are nested). +// */ +// throw new RuntimeException( +// "Could not resolve Stream: predicate=" + predicate); +// +// } +// +// return tmp.getAccessPath(predicate); +// +// } +// +// throw new UnsupportedOperationException(); +// +// } + /** - * Return an access path for a predicate that identifies a data structure - * which can be resolved to a reference attached to as a query attribute. - * <p> - * This method is used for data structures (including {@link Stream}s, - * {@link HTree}s, and {@link BTree} indices as well as non-durable data - * structures, such as JVM collection classes. When the data structure is - * pre-existing (such as a named solution set whose life cycle is broader - * than the query), then the data structure MUST be resolved during query - * optimization and attached to the {@link IRunningQuery} before operators - * with a dependency on those data structures can execute. + * Return an {@link ICloseableIterator} that can be used to read the + * solutions to be indexed from a source other than the pipeline. The + * returned iterator is intentionally aligned with the type returned by + * {@link BOpContext#getSource()}. * - * @param predicate - * The predicate. + * @return An iterator visiting the solutions to be indexed and never + * <code>null</code>. * - * @return The access path. - * * @throws RuntimeException - * if the access path could not be resolved. + * if the source can not be resolved. * - * @see #getQueryAttributes() + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/531"> + * SPARQL UPDATE for SOLUTION SETS </a> */ - public IBindingSetAccessPath<?> getAccessPath(final IPredicate predicate) { + @SuppressWarnings("unchecked") + public ICloseableIterator<IBindingSet[]> getAlternateSource( + final PipelineOp op, final NamedSolutionSetRef namedSetRef) { - if (predicate == null) - throw new IllegalArgumentException(); - /* - * FIXME There are several cases here, one for each type of - * data structure we need to access and each means of identifying - * that data structure. The main case is Stream (for named solution sets). - * If we wind up always modeling a named solution set as a Stream, then - * that is the only case that we need to address. + * Lookup the attributes for the query that will be used to resolve the + * named solution set. */ - if(predicate instanceof SolutionSetStream.SolutionSetStreamPredicate) { - + final IQueryAttributes queryAttributes = getQueryAttributes(namedSetRef.queryId); + + // Resolve the named solution set. + final Object tmp = queryAttributes.get(namedSetRef); + + // Iterator visiting the solution set. + final ICloseableIterator<IBindingSet> src; + + if (tmp != null) { + + if (tmp instanceof IHashJoinUtility) { + + /* + * Reading solutions from an existing hash index. + */ + + final IHashJoinUtility state = (IHashJoinUtility) tmp; + + src = state.indexScan(); + + } else if (tmp instanceof ISimpleIndexAccess) { + + /* + * Reading solutions from a raw BTree, HTree, or Stream. + */ + + src = (ICloseableIterator<IBindingSet>) ((ISimpleIndexAccess) tmp) + .scan(); + + } else { + + /* + * We found something, but we do not know how to turn it into an + * iterator visiting solutions. + */ + + throw new UnsupportedOperationException("namedSetRef=" + + namedSetRef + ", class=" + tmp.getClass()); + + } + + } else { + /* - * Resolve the name of the Stream against the query attributes for - * the running query, obtaining a reference to the Stream. Then - * request the access path from the Stream. + * There is no query attribute for that NamedSolutionSetRef. * - * TODO We might need to also include the UUID of the top-level - * query since that is where any subquery will have to look to find - * the named solution set. + * The query attributes are the first level of resolution. Since + * nothing was found there, we will now look for an index (BTree, + * HTree, Stream, etc) having the specified name. + * + * The search order is CACHE, local Journal, federation. + * + * TODO The name of the desired solution set might need to be paired + * with the NamedSolutionSetRef or modeled by a different type of + * object for the NAMED_SET_REF annotation, otherwise we might not + * be able to clearly specify the name of a stream and the name of + * an index over that stream. */ - - @SuppressWarnings("unchecked") - final SolutionSetStreamPredicate<IBindingSet> p = (SolutionSetStreamPredicate<IBindingSet>) predicate; - final String attributeName = p.getOnlyRelationName(); + // The name of a solution set. + final String name = namedSetRef.namedSet; - final SolutionSetStream tmp = (SolutionSetStream) getQueryAttributes().get( - attributeName); + // Resolve the object which will give us access to the named + // solution set. + final ISparqlCache sparqlCache = SparqlCacheFactory + .getExistingSparqlCache(getRunningQuery().getQueryEngine()); - if (tmp == null) { + if (sparqlCache != null && sparqlCache.existsSolutions(name)) { - /* - * Likely causes include a failure to attach the solution set to - * the query attributes when setting up the query or attaching - * and/or resolving the solution set against the wrong running - * query (especially when the queries are nested). - */ - throw new RuntimeException( - "Could not resolve Stream: predicate=" + predicate); - + return sparqlCache.getSolutions(name); + } + + /* + * FIXME Provide local and perhaps federation-wide access to a + * durable named index, returning the index scan. [It appears that I + * am not finished yet with the abstraction for Journal to support + * non-BTree named indices.] + * + * TODO Consider specifying the index using NT to specify both the + * name and the timestamp. + */ + + // getIndexManager().getIndex(name, timestamp) + + throw new RuntimeException("Not found: name=" + name + + ", namedSetRef=" + namedSetRef); + + } - return tmp.getAccessPath(predicate); + return new Chunkerator<IBindingSet>(src, op.getChunkCapacity(), + IBindingSet.class); - } - - throw new UnsupportedOperationException(); - } - + /** * Return the {@link IMemoryManager} associated with the specified query. * Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContextBase.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContextBase.java 2012-08-06 19:03:39 UTC (rev 6420) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContextBase.java 2012-08-07 19:26:40 UTC (rev 6421) @@ -65,8 +65,8 @@ /** * The <strong>local</strong> {@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 + * 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() { Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpUtility.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpUtility.java 2012-08-06 19:03:39 UTC (rev 6420) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpUtility.java 2012-08-07 19:26:40 UTC (rev 6421) @@ -47,7 +47,6 @@ import com.bigdata.bop.solutions.IGroupByRewriteState; import com.bigdata.rdf.sparql.ast.GroupNodeBase; import com.bigdata.rdf.sparql.ast.IGroupMemberNode; -import com.bigdata.rdf.sparql.ast.SolutionSetStatserator; import com.bigdata.relation.accesspath.IBlockingBuffer; import com.bigdata.striterator.CloseableIteratorWrapper; import com.bigdata.striterator.ICloseableIterator; @@ -1182,6 +1181,12 @@ /** * Copy binding sets from the source to the sink(s). + * <p> + * Note: You MUST use {@link IBlockingBuffer#flush()} to flush the sink(s) + * in order for the last chunk in the sink(s) to be pushed to the downstream + * operator for that sink. However, do NOT use flush() if the operator + * evaluation fails since you do not want to push outputs from a failed + * operator to downstream operators. * * @param source * The source. Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/controller/NamedSetAnnotations.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/controller/NamedSetAnnotations.java 2012-08-06 19:03:39 UTC (rev 6420) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/controller/NamedSetAnnotations.java 2012-08-07 19:26:40 UTC (rev 6421) @@ -27,8 +27,11 @@ package com.bigdata.bop.controller; +import com.bigdata.bop.BOpContext; import com.bigdata.bop.IQueryAttributes; +import com.bigdata.bop.PipelineOp; import com.bigdata.bop.engine.IRunningQuery; +import com.bigdata.bop.join.IHashJoinUtility; /** * Attributes for named solution set processing. @@ -42,7 +45,9 @@ * The name of {@link IQueryAttributes} attribute under which the * {@link NamedSolutionSetRef}. That {@link NamedSolutionSetRef} may be used * to locate the {@link IHashJoinUtility}, which includes metadata about the - * hash index and encapsulates the hash index state. + * hash index and encapsulates the hash index state. It may also be used to + * identify a named index that will be resolved against the SPARQL CACHE, + * the local index manager, or the federation index manager (on a cluster). * <p> * The attribute name includes the query UUID. The query UUID must be * extracted and used to lookup the {@link IRunningQuery} to which the @@ -52,6 +57,8 @@ * {@link NamedSolutionSetRef}[]. * * @see NamedSolutionSetRef + * + * @see BOpContext#getAlternateSource(PipelineOp, NamedSolutionSetRef) */ final String NAMED_SET_REF = "namedSetRef"; Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/engine/QueryEngine.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/engine/QueryEngine.java 2012-08-06 19:03:39 UTC (rev 6420) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/engine/QueryEngine.java 2012-08-07 19:26:40 UTC (rev 6421) @@ -1140,6 +1140,9 @@ } + /** + * Note: Used only by the test suite. + */ public AbstractRunningQuery eval(final UUID queryId, final BOp op, final IBindingSet bset) throws Exception { @@ -1148,18 +1151,26 @@ } + /** + * Note: Used only by the test suite. + */ public AbstractRunningQuery eval(final UUID queryId, final BOp op, - final IBindingSet[] bset) throws Exception { + final Map<Object, Object> queryAttributes, final IBindingSet[] bset) + throws Exception { - return eval(queryId, (PipelineOp) op, null/* attributes */, + return eval(queryId, (PipelineOp) op, queryAttributes, newLocalChunkMessage(queryId, op, bset)); } + /** + * Note: Used only by the test suite. + */ public AbstractRunningQuery eval(final UUID queryId, final BOp op, + final Map<Object, Object> queryAttributes, final IBindingSet[][] bset) throws Exception { - return eval(queryId, (PipelineOp) op, null/* attributes */, + return eval(queryId, (PipelineOp) op, queryAttributes, newLocalChunkMessage(queryId, op, bset)); } @@ -1294,11 +1305,11 @@ public AbstractRunningQuery eval(// final UUID queryId,// final PipelineOp query,// - final Map<Object,Object> attribs,// + final Map<Object,Object> queryAttributes,// final IChunkMessage<IBindingSet> msg// ) throws Exception { - return startEval(queryId, query, null/* attribs */, msg); + return startEval(queryId, query, queryAttributes, msg); } @@ -1311,7 +1322,7 @@ * The unique identifier for the query. * @param query * The query to evaluate. - * @param attribs + * @param queryAttributes * Attributes to be attached to the query before it begins to * execute (optional). * @param msg @@ -1327,7 +1338,7 @@ private AbstractRunningQuery startEval(// final UUID queryId,// final PipelineOp query,// - final Map<Object, Object> attribs,// + final Map<Object, Object> queryAttributes,// final IChunkMessage<IBindingSet> msg// ) throws Exception { @@ -1352,7 +1363,7 @@ true/* controller */, getProxy()/* queryController */, getServiceUUID(), query, msg/* realSource */); - if (attribs != null) { + if (queryAttributes != null) { /* * Propagate any initial attributes to the query. @@ -1360,7 +1371,7 @@ final IQueryAttributes tmp = runningQuery.getAttributes(); - for (Map.Entry<Object, Object> e : attribs.entrySet()) { + for (Map.Entry<Object, Object> e : queryAttributes.entrySet()) { tmp.put(e.getKey(), e.getValue()); Deleted: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/AbstractHashJoinOp.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/AbstractHashJoinOp.java 2012-08-06 19:03:39 UTC (rev 6420) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/AbstractHashJoinOp.java 2012-08-07 19:26:40 UTC (rev 6421) @@ -1,81 +0,0 @@ -/** - -Copyright (C) SYSTAP, LLC 2006-2011. All rights reserved. - -Contact: - SYSTAP, LLC - 4501 Tower Road - Greensboro, NC 27410 - lic...@bi... - -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 Nov 14, 2011 - */ - -package com.bigdata.bop.join; - -import java.util.Map; - -import com.bigdata.bop.BOp; -import com.bigdata.bop.IShardwisePipelineOp; -import com.bigdata.bop.NV; -import com.bigdata.bop.PipelineOp; -import com.bigdata.bop.controller.NamedSetAnnotations; - -/** - * Abstract base class for both JVM and native memory hash join against a B+Tree - * access path. - * - * @author <a href="mailto:tho...@us...">Bryan Thompson</a> - * @version $Id$ - */ -abstract public class AbstractHashJoinOp<E> extends PipelineOp implements - IShardwisePipelineOp<E> { - - private static final long serialVersionUID = 1L; - - public interface Annotations extends AccessPathJoinAnnotations, - NamedSetAnnotations { - - } - - /** - * @param op - */ - public AbstractHashJoinOp(final AbstractHashJoinOp<E> op) { - - super(op); - - } - - public AbstractHashJoinOp(final BOp[] args, NV... annotations) { - - this(args, NV.asMap(annotations)); - - } - - /** - * @param args - * @param annotations - */ - public AbstractHashJoinOp(final BOp[] args, - final Map<String, Object> annotations) { - - super(args, annotations); - - } - -} Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinOp.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinOp.java 2012-08-06 19:03:39 UTC (rev 6420) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinOp.java 2012-08-07 19:26:40 UTC (rev 6421) @@ -28,28 +28,16 @@ package com.bigdata.bop.join; import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.FutureTask; -import org.apache.log4j.Logger; - import com.bigdata.bop.BOp; import com.bigdata.bop.BOpContext; import com.bigdata.bop.IBindingSet; import com.bigdata.bop.IPredicate; -import com.bigdata.bop.IQueryAttributes; -import com.bigdata.bop.IVariable; import com.bigdata.bop.NV; import com.bigdata.bop.PipelineOp; import com.bigdata.bop.controller.NamedSolutionSetRef; import com.bigdata.htree.HTree; -import com.bigdata.relation.IRelation; -import com.bigdata.relation.accesspath.AbstractUnsynchronizedArrayBuffer; import com.bigdata.relation.accesspath.IAccessPath; -import com.bigdata.relation.accesspath.IBindingSetAccessPath; -import com.bigdata.relation.accesspath.IBlockingBuffer; -import com.bigdata.relation.accesspath.UnsyncLocalOutputBuffer; -import com.bigdata.striterator.ICloseableIterator; /** * A hash join against an {@link IAccessPath} based on the {@link HTree} and @@ -59,7 +47,7 @@ * over the {@link IAccessPath} for the target {@link IPredicate}. For some * queries, this can be more efficient than probing as-bound instances of the * target {@link IPredicate} using a nested indexed join, such as - * {@link PipelineOp}. This can also be more efficient on a cluster where the + * {@link PipelineJoin}. This can also be more efficient on a cluster where the * key range scan of the target {@link IPredicate} will be performed using * predominately sequential IO. * <p> @@ -108,17 +96,14 @@ * @author <a href="mailto:tho...@us...">Bryan Thompson</a> * @version $Id$ */ -public class HTreeHashJoinOp<E> extends AbstractHashJoinOp<E> { - - static private final transient Logger log = Logger - .getLogger(HTreeHashJoinOp.class); +public class HTreeHashJoinOp<E> extends HashJoinOp<E> { /** * */ private static final long serialVersionUID = 1L; - public interface Annotations extends AbstractHashJoinOp.Annotations, + public interface Annotations extends HashJoinOp.Annotations, HTreeHashJoinAnnotations { } @@ -147,17 +132,6 @@ super(args, annotations); - switch (getEvaluationContext()) { - case CONTROLLER: - case SHARDED: - case HASHED: - break; - default: - throw new UnsupportedOperationException( - Annotations.EVALUATION_CONTEXT + "=" - + getEvaluationContext()); - } - if (getMaxParallel() != 1) throw new UnsupportedOperationException(Annotations.MAX_PARALLEL + "=" + getMaxParallel()); @@ -183,24 +157,6 @@ throw new UnsupportedOperationException(Annotations.MAX_MEMORY + "=" + getMaxMemory()); - // Predicate for the access path must be specified. - getPredicate(); - - getRequiredProperty(Annotations.NAMED_SET_REF); - - // Join variables must be specified. - final IVariable<?>[] joinVars = (IVariable[]) getRequiredProperty(Annotations.JOIN_VARS); - -// if (joinVars.length == 0) -// throw new IllegalArgumentException(Annotations.JOIN_VARS); - - for (IVariable<?> var : joinVars) { - - if (var == null) - throw new IllegalArgumentException(Annotations.JOIN_VARS); - - } - if (isOptional() && getMaxMemory() != Long.MAX_VALUE) { /* @@ -217,259 +173,39 @@ } - /** - * {@inheritDoc} - * - * @see Annotations#PREDICATE - */ - @SuppressWarnings("unchecked") - public IPredicate<E> getPredicate() { + @Override + protected IHashJoinUtility newState(final BOpContext<IBindingSet> context, + final NamedSolutionSetRef namedSetRef, final JoinTypeEnum joinType) { - return (IPredicate<E>) getRequiredProperty(Annotations.PREDICATE); - - } + return new HTreeHashJoinUtility(context.getRunningQuery() + .getMemoryManager(), this, joinType); - /** - * Return <code>true</code> iff the predicate associated with the join is - * optional. - * - * @see IPredicate.Annotations#OPTIONAL - */ - private boolean isOptional() { - - return getPredicate().isOptional(); - } - - public BaseJoinStats newStats() { - return new BaseJoinStats(); - - } - - @Override - public FutureTask<Void> eval(final BOpContext<IBindingSet> context) { - - return new FutureTask<Void>(new ChunkTask<E>(context, this)); - - } - /** - * Task executing on the node. + * {@inheritDoc} + * <p> + * The {@link HTreeHashJoinOp} runs the hash join either exactly once + * (at-once evaluation) or once a target memory threshold has been exceeded + * (blocked evaluation). */ - private static class ChunkTask<E> implements Callable<Void> { + @Override + protected boolean runHashJoin(final BOpContext<?> context, + final IHashJoinUtility state) { - private final BOpContext<IBindingSet> context; + final long maxMemory = getMaxMemory(); - private final HTreeHashJoinOp<E> op; + final long usedMemory = ((HTreeHashJoinUtility) state).getStore() + .size(); - private final IRelation<E> relation; - - private final IPredicate<E> pred; - - private final BaseJoinStats stats; + if (context.isLastInvocation() || usedMemory >= maxMemory) { - private final HTreeHashJoinUtility state; - - private final IBlockingBuffer<IBindingSet[]> sink; - - private final IBlockingBuffer<IBindingSet[]> sink2; + return true; - public ChunkTask(final BOpContext<IBindingSet> context, - final HTreeHashJoinOp<E> op) { - - this.context = context; - - this.stats = (BaseJoinStats) context.getStats(); - - this.pred = op.getPredicate(); - - this.relation = context.getRelation(pred); - - this.sink = context.getSink(); - - this.sink2 = context.getSink2(); - - this.op = op; - - { - - /* - * First, see if the map already exists. - * - * Note: Since the operator is not thread-safe, we do not need - * to use a putIfAbsent pattern here. - * - * Note: Publishing the [state] as a query attribute provides - * visiblility into the hash join against the access path. - */ - - final NamedSolutionSetRef namedSetRef = (NamedSolutionSetRef) op - .getRequiredProperty(Annotations.NAMED_SET_REF); - - // Lookup the attributes for the query on which we will hang the - // solution set. - final IQueryAttributes attrs = context - .getQueryAttributes(namedSetRef.queryId); - - HTreeHashJoinUtility state = (HTreeHashJoinUtility) attrs - .get(namedSetRef); - - if (state == null) { - - state = new HTreeHashJoinUtility(context.getRunningQuery() - .getMemoryManager(), op, - op.isOptional() ? JoinTypeEnum.Optional - : JoinTypeEnum.Normal); - - attrs.put(namedSetRef, state); - - } - - this.state = state; - - } - } - public Void call() throws Exception { + return false; - try { - - state.acceptSolutions(context.getSource(), stats); - - final long maxMemory = op.getMaxMemory(); - - final long usedMemory = state.getStore().size(); - - if (context.isLastInvocation() || usedMemory >= maxMemory) { - - doHashJoin(); - - } - - // Done. - return null; - - } finally { - - if (context.isLastInvocation()) { - - state.release(); - - } - - sink.close(); - - if (sink2 != null) - sink2.close(); - - } - - } - - /** - * Return the access path that to be scanned. Solutions read from this - * access path will be used to probe the hash index to identify - * solutions that can join. - */ - private IBindingSetAccessPath<?> getAccessPath() { - - return (IBindingSetAccessPath<?>) context.getAccessPath(relation, - pred); - - } - - /** - * Do a hash join of the buffered solutions with the access path. - */ - private void doHashJoin() { - - if (state.isEmpty()) - return; - - final IBindingSetAccessPath<?> accessPath = getAccessPath(); - - if (log.isInfoEnabled()) - log.info("accessPath=" + accessPath); - - stats.accessPathCount.increment(); - - stats.accessPathRangeCount.add(accessPath - .rangeCount(false/* exact */)); - - final UnsyncLocalOutputBuffer<IBindingSet> unsyncBuffer = new UnsyncLocalOutputBuffer<IBindingSet>( - op.getChunkCapacity(), sink); - - final long cutoffLimit = pred.getProperty( - IPredicate.Annotations.CUTOFF_LIMIT, - IPredicate.Annotations.DEFAULT_CUTOFF_LIMIT); - - // Obtain the iterator for the current join dimension. - final ICloseableIterator<IBindingSet> itr = accessPath - .solutions(cutoffLimit, stats); - - state.hashJoin( - itr,// left - unsyncBuffer// out - ); - - switch (state.getJoinType()) { - case Normal: - /* - * Nothing to do. - */ - break; - case Optional: - case NotExists: { - /* - * Output the optional solutions. - */ - - // where to write the optional solutions. - final AbstractUnsynchronizedArrayBuffer<IBindingSet> unsyncBuffer2 = sink2 == null ? unsyncBuffer - : new UnsyncLocalOutputBuffer<IBindingSet>( - op.getChunkCapacity(), sink2); - - state.outputOptionals(unsyncBuffer2); - - unsyncBuffer2.flush(); - if (sink2 != null) - sink2.flush(); - - break; - } - case Exists: { - /* - * Output the join set. - */ - state.outputJoinSet(unsyncBuffer); - break; - } - default: - throw new AssertionError(); - } - -// if (state.getJoinType().isOptional()) { -// -// // where to write the optional solutions. -// final AbstractUnsynchronizedArrayBuffer<IBindingSet> unsyncBuffer2 = sink2 == null ? unsyncBuffer -// : new UnsyncLocalOutputBuffer<IBindingSet>( -// op.getChunkCapacity(), sink2); -// -// state.outputOptionals(unsyncBuffer2); -// -// unsyncBuffer2.flush(); -// if (sink2 != null) -// sink2.flush(); -// -// } - - unsyncBuffer.flush(); - sink.flush(); - - } - - } // class ChunkTask - + } + } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinUtility.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinUtility.java 2012-08-06 19:03:39 UTC (rev 6420) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HTreeHashJoinUtility.java 2012-08-07 19:26:40 UTC (rev 6421) @@ -43,7 +43,6 @@ import com.bigdata.bop.IBindingSet; import com.bigdata.bop.IConstant; import com.bigdata.bop.IConstraint; -import com.bigdata.bop.IQueryAttributes; import com.bigdata.bop.IVariable; import com.bigdata.bop.IndexAnnotations; import com.bigdata.bop.PipelineOp; @@ -81,6 +80,8 @@ import com.bigdata.util.InnerCause; import cutthecrap.utils.striterators.Expander; +import cutthecrap.utils.striterators.IStriterator; +import cutthecrap.utils.striterators.Resolver; import cutthecrap.utils.striterators.SingleValueIterator; import cutthecrap.utils.striterators.Striterator; import cutthecrap.utils.striterators.Visitor; @@ -1469,43 +1470,136 @@ } // outputOptionals. + @SuppressWarnings("unchecked") @Override - public void outputSolutions(final IBuffer<IBindingSet> out) { + public ICloseableIterator<IBindingSet> indexScan() { - try { + final HTree rightSolutions = getRightSolutions(); - final HTree rightSolutions = getRightSolutions(); + if (log.isInfoEnabled()) { + log.info("rightSolutions: #nnodes=" + + rightSolutions.getNodeCount() + ",#leaves=" + + rightSolutions.getLeafCount() + ",#entries=" + + rightSolutions.getEntryCount()); + } - if (log.isInfoEnabled()) { - log.info("rightSolutions: #nnodes=" - + rightSolutions.getNodeCount() + ",#leaves=" - + rightSolutions.getLeafCount() + ",#entries=" - + rightSolutions.getEntryCount()); - } + // source. + final ITupleIterator<?> solutionsIterator = rightSolutions + .rangeIterator(); - // source. - final ITupleIterator<?> solutionsIterator = rightSolutions - .rangeIterator(); + IStriterator itr = new Striterator(solutionsIterator); - while (solutionsIterator.hasNext()) { + /** + * Add resolution step. + */ + itr = itr.addFilter(new Resolver(){ - final ITuple<?> t = solutionsIterator.next(); + private static final long serialVersionUID = 1L; + @Override + protected Object resolve(Object obj) { + + final ITuple<?> t = ((ITuple<?>) obj); + + // Decode the solution. IBindingSet bset = decodeSolution(t); - if (selectVars != null) { +// if (selectVars != null) { +// +// // Drop variables which are not projected. +// bset = bset.copy(selectVars); +// +// } - // Drop variables which are not projected. - bset = bset.copy(selectVars); + // Resolve ivCache associations. + encoder.resolveCachedValues(bset); + return bset; + + } + + }); + + return (ICloseableIterator<IBindingSet>) itr; + + } + + @Override + public void outputSolutions(final IBuffer<IBindingSet> out) { + + try { + +// if (false) { +// +// /* +// * Striterator pattern. +// */ +// +// final ICloseableIterator<IBindingSet> itr = indexScan(); +// +// try { +// +// while(itr.hasNext()) { +// +// IBindingSet bset = itr.next(); +// +// if (selectVars != null) { +// +// // Drop variables which are not projected. +// bset = bset.copy(selectVars); +// +// } +// out.add(bset); +// +// } +// +// } finally { +// +// itr.close(); +// +// } +// +// +// } else { + + /* + * Simple iterator pattern. + */ + + final HTree rightSolutions = getRightSolutions(); + + if (log.isInfoEnabled()) { + log.info("rightSolutions: #nnodes=" + + rightSolutions.getNodeCount() + ",#leaves=" + + rightSolutions.getLeafCount() + ",#entries=" + + rightSolutions.getEntryCount()); } - encoder.resolveCachedValues(bset); + // source. + final ITupleIterator<?> solutionsIterator = rightSolutions + .rangeIterator(); - out.add(bset); + while (solutionsIterator.hasNext()) { - } + final ITuple<?> t = solutionsIterator.next(); + IBindingSet bset = decodeSolution(t); + + if (selectVars != null) { + + // Drop variables which are not projected. + bset = bset.copy(selectVars); + + } + + encoder.resolveCachedValues(bset); + + out.add(bset); + + } + +// } + } catch (Throwable t) { throw launderThrowable(t); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HashIndexOp.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HashIndexOp.java 2012-08-06 19:03:39 UTC (rev 6420) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HashIndexOp.java 2012-08-07 19:26:40 UTC (rev 6421) @@ -35,6 +35,7 @@ import com.bigdata.bop.BOp; import com.bigdata.bop.BOpContext; import com.bigdata.bop.BOpEvaluationContext; +import com.bigdata.bop.BOpUtility; import com.bigdata.bop.IBindingSet; import com.bigdata.bop.IQueryAttributes; import com.bigdata.bop.IVariable; @@ -46,6 +47,7 @@ import com.bigdata.htree.HTree; import com.bigdata.relation.accesspath.IBlockingBuffer; import com.bigdata.relation.accesspath.UnsyncLocalOutputBuffer; +import com.bigdata.striterator.ICloseableIterator; /** * Operator builds a hash index from the source solutions. Once all source @@ -86,6 +88,17 @@ public interface Annotations extends HashJoinAnnotations, JoinAnnotations, NamedSetAnnotations { + /** + * An optional attribute specifying the <em>source</em> named solution + * set for the index build operation. Normally, the hash index is built + * from the solutions flowing through the pipeline. When this attribute + * is specified, the hash index is instead built from the solutions in + * the specified named solution set. Regardless, the solutions flowing + * through the pipeline are copied to the sink once the hash index has + * been built. + */ + final String NAMED_SET_SOURCE_REF = "namedSetSourceRef"; + } /** @@ -171,7 +184,7 @@ } - public HashIndexOp(final BOp[] args, NV... annotations) { + public HashIndexOp(final BOp[] args, final NV... annotations) { this(args, NV.asMap(annotations)); @@ -198,13 +211,15 @@ * @param joinType * The type of join. */ - abstract protected IHashJoinUtility newState( - BOpContext<IBindingSet> context, - final NamedSolutionSetRef namedSetRef, final JoinTypeEnum joinType); + abstract protected IHashJoinUtility newState(// + final BOpContext<IBindingSet> context,// + final NamedSolutionSetRef namedSetRef, // + final JoinTypeEnum joinType// + ); public FutureTask<Void> eval(final BOpContext<IBindingSet> context) { - return new FutureTask<Void>(new ControllerTask(this, context)); + return new FutureTask<Void>(new ChunkTask(this, context)); } @@ -213,7 +228,7 @@ * operator is interrupted, then the subqueries are cancelled. If a subquery * fails, then all subqueries are cancelled. */ - private static class ControllerTask implements Callable<Void> { + private static class ChunkTask implements Callable<Void> { private final BOpContext<IBindingSet> context; @@ -223,7 +238,21 @@ private final IHashJoinUtility state; - public ControllerTask(final HashIndexOp op, + /** + * <code>true</code> iff this is the first invocation of this operator. + */ + private final boolean first; + + /** + * <code>true</code> iff the hash index will be generated from the + * intermediate solutions arriving from the pipeline. When + * <code>false</code>, the + * {@link HashIndexOp.Annotations#NAMED_SET_SOURCE_REF} identifies the + * source from which the index will be built. + */ + private final boolean sourceIsPipeline; + + public ChunkTask(final HashIndexOp op, final BOpContext<IBindingSet> context) { if (op == null) @@ -241,7 +270,7 @@ // Metadata to identify the named solution set. final NamedSolutionSetRef namedSetRef = (NamedSolutionSetRef) op .getRequiredProperty(Annotations.NAMED_SET_REF); - + { /* @@ -268,35 +297,69 @@ if (attrs.putIfAbsent(namedSetRef, state) != null) throw new AssertionError(); + + first = true; + } else { + + first = false; + } this.state = state; } + // true iff we will build the index from the pipeline. + this.sourceIsPipeline = null == op + .getProperty(Annotations.NAMED_SET_SOURCE_REF); + } /** * Evaluate. */ public Void call() throws Exception { - + try { - // Buffer all source solutions. - acceptSolutions(); - - if(context.isLastInvocation()) { + if (sourceIsPipeline) { - // Checkpoint the solution set. - checkpointSolutionSet(); + // Buffer all source solutions. + acceptSolutions(); + + if (context.isLastInvocation()) { + + // Checkpoint the solution set. + checkpointSolutionSet(); + + // Output the buffered solutions. + outputSolutions(); + + } + + } else { - // Output the buffered solutions. - outputSolutions(); + if(first) { + // Accept ALL solutions. + acceptSolutions(); + + // Checkpoint the generated solution set index. + checkpointSolutionSet(); + + } + + // Copy all solutions from the pipeline to the sink. + BOpUtility.copy(context.getSource(), context.getSink(), + null/* sink2 */, null/* mergeSolution */, + null/* selectVars */, null/* constraints */, stats); + + // Flush solutions to the sink. + context.getSink().flush(); + } - + // Done. return null; @@ -311,12 +374,45 @@ } /** - * Buffer intermediate resources. + * Add solutions to the hash index. The solutions to be indexed will be + * read either from the pipeline or from an "alternate" source + * identified by an annotation. + * + * @see HashIndexOp.Annotations#NAMED_SET_SOURCE_REF */ private void acceptSolutions() { - state.acceptSolutions(context.getSource(), stats); + final ICloseableIterator<IBindingSet[]> src; + if (sourceIsPipeline) { + + src = context.getSource(); + + } else { + + /* + * Metadata to identify the optional *source* solution set. When + * <code>null</code>, the hash index is built from the solutions flowing + * through the pipeline. When non-<code>null</code>, the hash index is + * built from the solutions in the identifier solution set. + */ + final NamedSolutionSetRef namedSetSourceRef = (NamedSolutionSetRef) op + .getRequiredProperty(Annotations.NAMED_SET_SOURCE_REF); + + src = context.getAlternateSource(op, namedSetSourceRef); + + } + + try { + + state.acceptSolutions(src, stats); + + } finally { + + src.close(); + + } + } /** Copied: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HashJoinOp.java (from rev 6406, branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/AbstractHashJoinOp.java) =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HashJoinOp.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/join/HashJoinOp.java 2012-08-07 19:26:40 UTC (rev 6421) @@ -0,0 +1,432 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2011. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 Nov 14, 2011 + */ + +package com.bigdata.bop.join; + +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; + +import org.apache.log4j.Logger; + +import com.bigdata.bop.BOp; +import com.bigdata.bop.BOpContext; +import com.bigdata.bop.BOpEvaluationContext; +import com.bigdata.bop.IBindingSet; +import com.bigdata.bop.IPredicate; +import com.bigdata.bop.IQueryAttributes; +import com.bigdata.bop.IShardwisePipelineOp; +import com.bigdata.bop.IVariable; +import com.bigdata.bop.NV; +import com.bigdata.bop.PipelineOp; +import com.bigdata.bop.controller.NamedSetAnnotations; +import com.bigdata.bop.controller.NamedSolutionSetRef; +import com.bigdata.relation.IRelation; +import com.bigdata.relation.accesspath.AbstractUnsynchronizedArrayBuffer; +import com.bigdata.relation.accesspath.IAccessPath; +import com.bigdata.relation.accesspath.IBindingSetAccessPath; +import com.bigdata.relation.accesspath.IBlockingBuffer; +import com.bigdata.relation.accesspath.UnsyncLocalOutputBuffer; +import com.bigdata.striterator.ICloseableIterator; + +/** + * Abstract base class for both JVM and native memory hash join against an + * {@link IAccessPath}. The source solutions from the pipeline are buffered on a + * hash index. Depending on the implementation, the hash index may have a + * threshold that will trigger an evaluation pass of the hash join. If not, then + * the hash join will run exactly once. When the hash join runs, the access path + * is scanned and the hash index (of intermediate solutions from the pipeline) + * is probed for each solution read from the {@link IAccessPath}. Solutions + * which join are output. + * + * @author <a href="mailto:tho...@us...">... [truncated message content] |
From: <tho...@us...> - 2012-08-08 18:33:52
|
Revision: 6422 http://bigdata.svn.sourceforge.net/bigdata/?rev=6422&view=rev Author: thompsonbry Date: 2012-08-08 18:33:45 +0000 (Wed, 08 Aug 2012) Log Message: ----------- Added a UUID generator to the NSS REST API. This is intended for use by JavaScript graph/GOM API clients that want to generate unique URIs. The UUID should be requested when the client connects to the NSS and then reused as a namespace within which the client can generate unique URLs. The URLs should have the sparql endpoint URL as their prefix. E.g., endpoint/gpo/UUID/localCounter. Removed FIXMEs and TODOs related to the well-known service endpoint. The NSS uses the "as requested" URL to identify the endpoint. This pattern supports proxies (e.g., virtual hosting). Added support for resolution of durable named solution sets on the local index manager to BOpContext. Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContext.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/SparqlCache.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServletContextListener.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/MultiTenancyServlet.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/QueryServlet.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/VoID.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContext.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContext.java 2012-08-07 19:26:40 UTC (rev 6421) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata/src/java/com/bigdata/bop/BOpContext.java 2012-08-08 18:33:45 UTC (rev 6422) @@ -45,6 +45,9 @@ import com.bigdata.bop.join.BaseJoinStats; import com.bigdata.bop.join.IHashJoinUtility; import com.bigdata.btree.ISimpleIndexAccess; +import com.bigdata.journal.AbstractJournal; +import com.bigdata.journal.IIndexManager; +import com.bigdata.journal.ITx; import com.bigdata.rdf.internal.IV; import com.bigdata.rdf.internal.impl.bnode.SidIV; import com.bigdata.rdf.model.BigdataBNode; @@ -58,6 +61,7 @@ import com.bigdata.relation.accesspath.IAccessPath; import com.bigdata.relation.accesspath.IBlockingBuffer; import com.bigdata.rwstore.sector.IMemoryManager; +import com.bigdata.service.IBigdataFederation; import com.bigdata.striterator.ChunkedFilter; import com.bigdata.striterator.Chunkerator; import com.bigdata.striterator.CloseableIteratorWrapper; @@ -621,6 +625,15 @@ * object for the NAMED_SET_REF annotation, otherwise we might not * be able to clearly specify the name of a stream and the name of * an index over that stream. + * + * TODO We might need/want to explicitly identify the conceptual + * location of the named solution set (cache, local index manager, + * federation) when the query is compiled so we only look in the + * right place at when the operator is executing. That could + * decrease latency for operators which execute multiple times, + * report errors early if something can not be resolved, and + * eliminate some overhead with testing remote services during + * operator evaluation (if the cache is non-local). */ // The name of a solution set. @@ -638,20 +651,54 @@ } /* - * FIXME Provide local and perhaps federation-wide access to a - * durable named index, returning the index scan. [It appears that I - * am not finished yet with the abstraction for Journal to support - * non-BTree named indices.] - * - * TODO Consider specifying the index using NT to specify both the - * name and the timestamp. + * FIXME Consider specifying the index using NT to specify both the + * name and the timestamp. Or put the timestamp into the + * NamedSolutionSetRef. */ + final long timestamp = ITx.READ_COMMITTED; - // getIndexManager().getIndex(name, timestamp) + final IIndexManager localIndexManager = getIndexManager(); - throw new RuntimeException("Not found: name=" + name - + ", namedSetRef=" + namedSetRef); + if (localIndexManager instanceof AbstractJournal) { + final ISimpleIndexAccess index = ((AbstractJournal) localIndexManager) + .getIndexLocal(name, timestamp); + + if (index != null) { + + src = (ICloseableIterator<IBindingSet>) index.scan(); + + } else { + + /* + * TODO Provide federation-wide access to a durable named + * index, returning the index scan. + */ + + final IBigdataFederation<?> fed = getFederation(); + + // resolve remote index, obtaining "scan" of solutions. + + src = null; + + } + + } else { + + /* + * This is an odd code path. It is possible that we could hit it + * if the local index manager were null (in unit tests) or some + * wrapped object (such as an IJournal delegate). + */ + + throw new AssertionError(); + + } + + if (src == null) + throw new RuntimeException("Not found: name=" + name + + ", namedSetRef=" + namedSetRef); + } return new Chunkerator<IBindingSet>(src, op.getChunkCapacity(), Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/SparqlCache.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/SparqlCache.java 2012-08-07 19:26:40 UTC (rev 6421) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/SparqlCache.java 2012-08-08 18:33:45 UTC (rev 6422) @@ -282,19 +282,20 @@ properties.setProperty(com.bigdata.journal.Options.BUFFER_MODE, BufferMode.MemStore.name()); + // Start small, grow as required. properties.setProperty(com.bigdata.journal.Options.INITIAL_EXTENT, "" - + (10 * Bytes.megabyte)); + + (1 * Bytes.megabyte)); - properties.setProperty(com.bigdata.journal.Options.CREATE_TEMP_FILE, - "true"); - -// properties.setProperty(Journal.Options.COLLECT_PLATFORM_STATISTICS, -// "false"); +// properties.setProperty(com.bigdata.journal.Options.CREATE_TEMP_FILE, +// "true"); // -// properties.setProperty(Journal.Options.COLLECT_QUEUE_STATISTICS, -// "false"); -// -// properties.setProperty(Journal.Options.HTTPD_PORT, "-1"/* none */); +//// properties.setProperty(Journal.Options.COLLECT_PLATFORM_STATISTICS, +//// "false"); +//// +//// properties.setProperty(Journal.Options.COLLECT_QUEUE_STATISTICS, +//// "false"); +//// +//// properties.setProperty(Journal.Options.HTTPD_PORT, "-1"/* none */); this.cache = new CacheJournal(properties); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServletContextListener.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServletContextListener.java 2012-08-07 19:26:40 UTC (rev 6421) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServletContextListener.java 2012-08-08 18:33:45 UTC (rev 6422) @@ -307,12 +307,6 @@ } - /* - * FIXME We should figure out a default serviceURI here but prefer one - * configured in web.xml. That will be the "official" URI reported out - * for ServiceDescription and VoID. - */ - final SparqlEndpointConfig config = new SparqlEndpointConfig(namespace, timestamp, queryThreadPoolSize, describeEachNamedGraph); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/MultiTenancyServlet.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/MultiTenancyServlet.java 2012-08-07 19:26:40 UTC (rev 6421) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/MultiTenancyServlet.java 2012-08-08 18:33:45 UTC (rev 6422) @@ -499,26 +499,12 @@ /* * Figure out the service end point. * - * FIXME This needs to be an explicitly configured (or intelligently - * defaulted) URL in order for us to get the actual deployment URL - * correct in the generated VoID description. See NanoSparqlServer, - * web.xml, QueryServlet.doServiceDescription(), and - * BigdataRDFServletContext. + * Note: This is just the requestURL as reported. This makes is + * possible to support virtual hosting and similar http proxy + * patterns since the SPARQL end point is just the URL at which the + * service is responding. */ - final String serviceURI; - { - - final StringBuffer sb = req.getRequestURL(); - - final int indexOf = sb.indexOf("?"); - - if (indexOf == -1) { - serviceURI = sb.toString(); - } else { - serviceURI = sb.substring(0, indexOf); - } - - } + final String serviceURI = req.getRequestURL().toString(); final VoID v = new VoID(g, tripleStore, serviceURI, aDataSet); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/QueryServlet.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/QueryServlet.java 2012-08-07 19:26:40 UTC (rev 6421) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/QueryServlet.java 2012-08-08 18:33:45 UTC (rev 6422) @@ -129,6 +129,10 @@ doQuery(req, resp); + } else if (req.getParameter("uuid") != null) { + + doUUID(req, resp); + } else if (req.getParameter("ESTCARD") != null) { doEstCard(req, resp); @@ -148,6 +152,20 @@ } /** + * Generate and send a UUID as a <code>text/plain</code> response entity. + * This is intended for use by JavaScript clients that want to generate new + * URLs locally. JavaScript does not provide an easy means to generate + * UUIDs, so we've added one to the server. + */ + private void doUUID(final HttpServletRequest req, + final HttpServletResponse resp) throws IOException { + + buildResponse(resp, HTTP_OK, MIME_TEXT_PLAIN, UUID.randomUUID() + .toString()); + + } + + /** * Generate a SPARQL 1.1 Service Description for the addressed triple store * or quad store. * Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/VoID.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/VoID.java 2012-08-07 19:26:40 UTC (rev 6421) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/VoID.java 2012-08-08 18:33:45 UTC (rev 6422) @@ -108,8 +108,8 @@ * Where to assemble the description. * @param tripleStore * The KB instance to be described. - * @param serviceURIs - * One or more service end points for that KB instance. + * @param serviceURI + * The SPARQL service end point. * @param aDefaultDataset * The data set identifier that will be used on the description * (the bigdata namespace of the dataset is obtained from the @@ -172,26 +172,8 @@ // Also present the namespace in an unambiguous manner. g.add(aDataset, SD.KB_NAMESPACE, f.createLiteral(namespace)); - /** - * Service end point for this. - * - * - * FIXME Provide the serviceURI for that namespace based on the - * top-level serviceURI plus the namespace. This is not getting the - * correct end point! It winds up as - * - * <pre> - * <sparqlEndpoint rdf:resource="http://192.168.1.134:8080/namespace/kb/sparql"/> - * </pre> - * - * which is Ok, but as - * - * <pre> - * <sparqlEndpoint rdf:resource="http://192.168.1.134:8080/sparql/kb"/> - * </pre> - * - * when using the ServiceDescription (which is totally wrong as the - * "namespace" component is not in the path). + /* + * Service end point for this namespace. */ g.add(aDataset, VoidVocabularyDecl.sparqlEndpoint, f.createURI(serviceURI + "/" + namespace + "/sparql")); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tho...@us...> - 2012-08-09 15:24:28
|
Revision: 6428 http://bigdata.svn.sourceforge.net/bigdata/?rev=6428&view=rev Author: thompsonbry Date: 2012-08-09 15:24:19 +0000 (Thu, 09 Aug 2012) Log Message: ----------- - Dropped GOMListener. The existing NSS can be used as is. The ObjectManagerModel now generates a UUID in its constructor. GOMWebUtil was modified to attach the OM instance as a request attribute so the OM is now scoped to the page. I have not yet factored the global object cache out of the OM. It is Ok if the OM has a local object cache (Resource => IGPO), but the global cache needs to be something that can be distributed and must notice invalidation messages from updates using a change log listener. - Test suites were modified to use a base class where possible, to NOT use System.out, to use om.close(), etc. I noticed that many of the tests are not really testing anything. They are more like utility programs to explore the data. Tests need to use assert() and actually test pre-/post- conditions for the API. The test suites were running with truth maintenance enabled due to a spelling error. I have simplified the Journal configuration and turned off TM. - Dropped GOMServlet. It was unused. - Coining new URLs. Use endpoint/gpo/clientUUID/<ID>. This works for each KB instance. Use req.getRequestURL() to get the endpoint URL as actually requested. This should work with virtual hosting. The remote OM version always has the SPARQL endpoint, but we need to have this for the embedded version as well - at least when used from a JSP page. That can be handled by GOMWebUtil since it has the request parameter. The test suites however do not so we need to mock the endpoint URI there. - All classes should declare their own private logger using the class name, not an interface name. - Improper synchronization for the native transaction identifier. I have added an explicit lock for this, but the whole concept of native transactions needs to be reconsidered. I think that we just want to let the Sail handle the buffering.... - Added genId(String:scope) to make it easier to embed some non-opaque information into unique identifiers. @see https://sourceforge.net/apps/trac/bigdata/ticket/560 (Graph API/RDF-GOM) Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/Alchemist.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/owl/OWLClassSkin.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/owl/OWLOntologySkin.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/owl/OWLPropertySkin.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/owl/OWLSkins.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/gpo/BasicSkin.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/gpo/GPO.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/gpo/LinkSet.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/IIDGenerator.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/IObjectManager.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/NanoSparqlObjectManager.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/ObjectManager.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/ObjectMgrModel.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/web/GOMWebUtil.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/test/com/bigdata/gom/TestAll.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/test/com/bigdata/gom/TestGOM.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/test/com/bigdata/gom/TestOWLSkin.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/test/com/bigdata/gom/TestOwlGOM.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/test/com/bigdata/gom/TestRemoteGOM.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServlet.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServletContextListener.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataServlet.java branches/BIGDATA_RELEASE_1_2_0/build.xml Added Paths: ----------- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/IDGenerator.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/test/com/bigdata/gom/LocalGOMTestCase.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/test/com/bigdata/gom/TestJavaScriptGOM.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/test/com/bigdata/gom/univ-bench.owl Removed Paths: ------------- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/web/GOMListener.java branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/web/GOMServlet.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/Alchemist.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/Alchemist.java 2012-08-09 11:56:37 UTC (rev 6427) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/Alchemist.java 2012-08-09 15:24:19 UTC (rev 6428) @@ -1,3 +1,26 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ package com.bigdata.gom.alchemy; /** Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/owl/OWLClassSkin.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/owl/OWLClassSkin.java 2012-08-09 11:56:37 UTC (rev 6427) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/owl/OWLClassSkin.java 2012-08-09 15:24:19 UTC (rev 6428) @@ -1,3 +1,26 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ package com.bigdata.gom.alchemy.owl; import java.util.Iterator; @@ -2,4 +25,2 @@ -import org.openrdf.model.vocabulary.OWL; -import org.openrdf.model.vocabulary.RDF; import org.openrdf.model.vocabulary.RDFS; @@ -10,7 +31,6 @@ import com.bigdata.gom.gpo.GPO; import com.bigdata.gom.gpo.IGPO; import com.bigdata.gom.gpo.IGenericSkin; -import com.bigdata.gom.om.IObjectManager; public class OWLClassSkin extends BasicSkin implements IGenericSkin { Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/owl/OWLOntologySkin.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/owl/OWLOntologySkin.java 2012-08-09 11:56:37 UTC (rev 6427) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/owl/OWLOntologySkin.java 2012-08-09 15:24:19 UTC (rev 6428) @@ -1,3 +1,26 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ package com.bigdata.gom.alchemy.owl; import java.util.Iterator; @@ -4,7 +27,6 @@ import org.openrdf.model.vocabulary.OWL; import org.openrdf.model.vocabulary.RDF; -import org.openrdf.model.vocabulary.RDFS; import com.bigdata.gom.gpo.BasicSkin; import com.bigdata.gom.gpo.GPO; Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/owl/OWLPropertySkin.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/owl/OWLPropertySkin.java 2012-08-09 11:56:37 UTC (rev 6427) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/owl/OWLPropertySkin.java 2012-08-09 15:24:19 UTC (rev 6428) @@ -1,3 +1,26 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ package com.bigdata.gom.alchemy.owl; import org.openrdf.model.vocabulary.OWL; Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/owl/OWLSkins.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/owl/OWLSkins.java 2012-08-09 11:56:37 UTC (rev 6427) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/alchemy/owl/OWLSkins.java 2012-08-09 15:24:19 UTC (rev 6428) @@ -1,10 +1,28 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ package com.bigdata.gom.alchemy.owl; -import org.openrdf.model.vocabulary.OWL; - -import com.bigdata.gom.gpo.GPO; -import com.bigdata.gom.gpo.IGPO; -import com.bigdata.gom.om.IObjectManager; import com.bigdata.gom.skin.GenericSkinRegistry; /** Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/gpo/BasicSkin.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/gpo/BasicSkin.java 2012-08-09 11:56:37 UTC (rev 6427) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/gpo/BasicSkin.java 2012-08-09 15:24:19 UTC (rev 6428) @@ -10,8 +10,8 @@ /** * The BasicSkin provides standard type wrappers to help with conversions + * * @author Martyn Cutcher - * */ public class BasicSkin implements IGenericSkin { Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/gpo/GPO.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/gpo/GPO.java 2012-08-09 11:56:37 UTC (rev 6427) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/gpo/GPO.java 2012-08-09 15:24:19 UTC (rev 6428) @@ -7,17 +7,12 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; import org.apache.log4j.Logger; import org.openrdf.model.Resource; import org.openrdf.model.Statement; import org.openrdf.model.URI; import org.openrdf.model.Value; -import org.openrdf.model.ValueFactory; import org.openrdf.model.impl.URIImpl; import org.openrdf.query.BindingSet; import org.openrdf.repository.RepositoryException; @@ -25,15 +20,7 @@ import com.bigdata.gom.om.IObjectManager; import com.bigdata.gom.om.ObjectMgrModel; import com.bigdata.gom.skin.GenericSkinRegistry; -import com.bigdata.rdf.internal.IV; import com.bigdata.rdf.model.BigdataLiteralImpl; -import com.bigdata.rdf.model.BigdataResource; -import com.bigdata.rdf.model.BigdataStatement; -import com.bigdata.rdf.model.BigdataStatementImpl; -import com.bigdata.rdf.model.BigdataURI; -import com.bigdata.rdf.model.BigdataValue; -import com.bigdata.rdf.model.BigdataValueFactoryImpl; -import com.bigdata.rdf.model.StatementEnum; import com.bigdata.striterator.ICloseableIterator; /** @@ -80,29 +67,45 @@ private static final Logger log = Logger.getLogger(GPO.class); - final ObjectMgrModel m_om; - final Resource m_id; + /** + * The owning {@link IObjectManager}. + */ + private final ObjectMgrModel m_om; - boolean m_materialized = false; + /** + * The identifier for this {@link IGPO}. + */ + private final Resource m_id; - boolean m_clean = true; + private boolean m_materialized = false; - ArrayList<IGenericSkin> m_skins = null; + private boolean m_clean = true; + private GPOEntry m_headEntry = null; + private GPOEntry m_tailEntry = null; + + private ArrayList<IGenericSkin> m_skins = null; + static class LinkValue { - final Value m_value; - LinkValue m_next; + + final Value m_value; - LinkValue(Value value) { - m_value = value; + LinkValue m_next; + + LinkValue(final Value value) { + + m_value = value; + } + } - /** - * The GPOEntry retains the state necessary for providing delta updates to the underlying - * triple data. It supports multi-values against the same property and records values - * removed and added. - */ - static class GPOEntry { + + /** + * The GPOEntry retains the state necessary for providing delta updates to + * the underlying triple data. It supports multi-values against the same + * property and records values removed and added. + */ + static class GPOEntry { final URI m_key; GPOEntry m_next; @@ -269,8 +272,6 @@ return m_values != null || m_addedValues != null; } } - GPOEntry m_headEntry = null; - GPOEntry m_tailEntry = null; GPOEntry establishEntry(final URI key) { final URI fkey = m_om.internKey(key); Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/gpo/LinkSet.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/gpo/LinkSet.java 2012-08-09 11:56:37 UTC (rev 6427) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/gpo/LinkSet.java 2012-08-09 15:24:19 UTC (rev 6428) @@ -8,7 +8,6 @@ import org.openrdf.model.Resource; import org.openrdf.model.URI; import org.openrdf.model.Value; -import org.openrdf.model.impl.URIImpl; import org.openrdf.query.BindingSet; import com.bigdata.gom.om.IObjectManager; Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/IDGenerator.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/IDGenerator.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/IDGenerator.java 2012-08-09 15:24:19 UTC (rev 6428) @@ -0,0 +1,100 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 9, 2012 + */ +package com.bigdata.gom.om; + +import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; + +import org.openrdf.model.URI; +import org.openrdf.model.ValueFactory; + +/** + * Generator for globally unique URIs. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ +public class IDGenerator implements IIDGenerator { + + private final ValueFactory valueFactory; + + private final String prefix; + + private final AtomicInteger nextId = new AtomicInteger(0); + + /** + * + * @param endpoint + * The SPARQL endpoint. + * @param uuid + * The {@link UUID} for the {@link IObjectManager}. This is used + * to avoid collisions between different {@link IObjectManager}s. + * @param valueFactory + * The {@link ValueFactory} that will be used when new + * {@link URI}s are generated. + */ + public IDGenerator(final String endpoint, final UUID uuid, + final ValueFactory valueFactory) { + + if(endpoint == null) + throw new IllegalArgumentException(); + + if(uuid == null) + throw new IllegalArgumentException(); + + if(valueFactory == null) + throw new IllegalArgumentException(); + + this.valueFactory = valueFactory; + + // Setup the prefix that we will reuse for each new URI. + this.prefix = endpoint + "/gpo/" + uuid + "/"; + + } + + @Override + public URI genId() { + + return valueFactory.createURI(prefix + nextId.incrementAndGet()); + + } + + @Override + public URI genId(final String scope) { + + return valueFactory.createURI(prefix + scope + "/" + + nextId.incrementAndGet()); + + } + + @Override + public void rollback() { + + nextId.set(0); + + } + +} Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/IIDGenerator.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/IIDGenerator.java 2012-08-09 11:56:37 UTC (rev 6427) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/IIDGenerator.java 2012-08-09 15:24:19 UTC (rev 6428) @@ -1,3 +1,26 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ package com.bigdata.gom.om; import org.openrdf.model.URI; @@ -13,12 +36,30 @@ * */ public interface IIDGenerator { - - URI genId(); - /** - * A rollback hook is required - */ + /** + * Generate a globally unique URI. + * + * @return The URI. + */ + URI genId(); + + /** + * Generate a globally unique URI. + * + * @param scope + * The scope will be incorporated into the URI. This is not + * necessary to make the URI globally unique, but it can make it + * easier to embed some non-opaque semantics into a globally + * unique URI. + * + * @return The URI. + */ + URI genId(final String scope); + + /** + * A rollback hook is required + */ void rollback(); } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/IObjectManager.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/IObjectManager.java 2012-08-09 11:56:37 UTC (rev 6427) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/IObjectManager.java 2012-08-09 15:24:19 UTC (rev 6428) @@ -36,7 +36,6 @@ import org.openrdf.model.Value; import org.openrdf.model.ValueFactory; import org.openrdf.query.BindingSet; -import org.openrdf.repository.RepositoryException; import com.bigdata.gom.gpo.IGPO; import com.bigdata.striterator.ICloseableIterator; @@ -45,13 +44,16 @@ * The object manager is the abstraction for a connection the back end. */ public interface IObjectManager extends INativeTransaction { - - /** - * @return the UUID that identifies this ObjectManager - */ - UUID getID(); /** + * @return the UUID that identifies this ObjectManager + * + * @deprecated Why do we need this? It should be hidden in how we generate + * URIs, not part of the public API. + */ + UUID getID(); + + /** * Return a canonical {@link IGPO} for the {@link Resource} (canonical * within the scope of this object manager) and never <code>null</code>. * @@ -95,6 +97,8 @@ */ boolean isPersistent(); + ValueFactory getValueFactory(); + /** * */ @@ -105,6 +109,8 @@ */ void execute(String updateStr); + ICloseableIterator<Statement> evaluateGraph(String query); + URI internKey(URI key); /** @@ -119,12 +125,14 @@ * Simple save/recall interface that the ObjectManager provides to simplify * other pattern implementations. Internally it uses a NameManager GPO */ + @Deprecated // Just use the URI directly... void save(URI key, Value value); /** * Simple save/recall interface that the ObjectManager provides to simplify * other pattern implementations. Internally it uses a NameManager GPO */ + @Deprecated // Just use the URI directly... Value recall(URI key); IGPO recallAsGPO(URI key); @@ -133,13 +141,12 @@ * Return the list of names that have been used to save references. These * are the properties of the internal NameManager. */ + @Deprecated // Just use URIs directly... Iterator<URI> getNames(); + /** + * Remove all assertions involving the specified object. + */ void remove(IGPO gpo); - ICloseableIterator<Statement> evaluateGraph(String query); - - ValueFactory getValueFactory(); - - void checkValue(Value newValue); } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/NanoSparqlObjectManager.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/NanoSparqlObjectManager.java 2012-08-09 11:56:37 UTC (rev 6427) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/NanoSparqlObjectManager.java 2012-08-09 15:24:19 UTC (rev 6428) @@ -1,3 +1,29 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 19, 2012 + */ package com.bigdata.gom.om; import java.util.ArrayList; @@ -2,16 +28,12 @@ import java.util.Iterator; -import java.util.UUID; +import org.apache.log4j.Logger; import org.openrdf.model.Resource; import org.openrdf.model.Statement; import org.openrdf.model.URI; import org.openrdf.model.Value; -import org.openrdf.model.ValueFactory; import org.openrdf.query.BindingSet; -import org.openrdf.query.GraphQuery; import org.openrdf.query.GraphQueryResult; import org.openrdf.query.MalformedQueryException; import org.openrdf.query.QueryEvaluationException; -import org.openrdf.query.QueryLanguage; -import org.openrdf.query.TupleQuery; import org.openrdf.query.TupleQueryResult; @@ -21,34 +43,41 @@ import com.bigdata.gom.gpo.GPO; import com.bigdata.gom.gpo.IGPO; -import com.bigdata.rdf.model.BigdataResource; -import com.bigdata.rdf.model.BigdataStatementImpl; -import com.bigdata.rdf.model.BigdataURI; -import com.bigdata.rdf.model.BigdataValue; import com.bigdata.rdf.model.BigdataValueFactoryImpl; -import com.bigdata.rdf.model.StatementEnum; import com.bigdata.rdf.sail.webapp.client.IPreparedGraphQuery; import com.bigdata.rdf.sail.webapp.client.IPreparedTupleQuery; -import com.bigdata.rdf.sail.webapp.client.IRemoteRepository; import com.bigdata.rdf.sail.webapp.client.RemoteRepository; import com.bigdata.rdf.sail.webapp.client.RemoteRepository.AddOp; import com.bigdata.rdf.sail.webapp.client.RemoteRepository.RemoveOp; -import com.bigdata.rdf.spo.ISPO; -import com.bigdata.rdf.spo.SPO; import com.bigdata.striterator.CloseableIteratorWrapper; import com.bigdata.striterator.ICloseableIterator; +/** + * Remote {@link IObjectManager} using the <a href= + * "https://sourceforge.net/apps/mediawiki/bigdata/index.php?title=NanoSparqlServer" + * > NanoSparqlServer REST API </a> to communicate with the database. + * + * @author <a href="mailto:mar...@us...">Martyn Cutcher</a> + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ public class NanoSparqlObjectManager extends ObjectMgrModel { - final RemoteRepository m_repo; + + private static final Logger log = Logger + .getLogger(NanoSparqlObjectManager.class); + + private final RemoteRepository m_repo; - public NanoSparqlObjectManager(final UUID uuid, final RemoteRepository repo, final String namespace) { - super(uuid, BigdataValueFactoryImpl.getInstance(namespace)); + public NanoSparqlObjectManager(final RemoteRepository repo, final String namespace) { + super(repo.getSparqlEndPoint(), BigdataValueFactoryImpl + .getInstance(namespace)); + m_repo = repo; } @Override public void close() { + super.close(); // m_repo.close(); } @@ -163,14 +192,14 @@ } @Override - void doCommit() { + protected void doCommit() { // FIXME: The current NanoSparqlServer commits each update. This // needs to change to associate with an IsolatedTransaction with // an additional commit/rollback protocol } @Override - void doRollback() { + protected void doRollback() { // FIXME: see comment above for doCommit() } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/ObjectManager.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/ObjectManager.java 2012-08-09 11:56:37 UTC (rev 6427) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/ObjectManager.java 2012-08-09 15:24:19 UTC (rev 6428) @@ -1,3 +1,29 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 19, 2012 + */ package com.bigdata.gom.om; import java.util.Iterator; @@ -2,3 +28,2 @@ import java.util.List; -import java.util.UUID; @@ -9,7 +34,6 @@ import org.openrdf.model.Statement; import org.openrdf.model.URI; import org.openrdf.model.Value; -import org.openrdf.model.ValueFactory; import org.openrdf.query.BindingSet; import org.openrdf.query.GraphQuery; import org.openrdf.query.GraphQueryResult; @@ -35,16 +59,35 @@ import com.bigdata.striterator.CloseableIteratorWrapper; import com.bigdata.striterator.ICloseableIterator; +/** + * An {@link IObjectManager} for use with an embedded database, including JSP + * pages running in the same webapp as the NanoSparqlServer and applications + * that do not expose a public web interface. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ public class ObjectManager extends ObjectMgrModel { - private static final Logger log = Logger.getLogger(IObjectManager.class); + + private static final Logger log = Logger.getLogger(ObjectManager.class); - final BigdataSailRepository m_repo; - BigdataSailRepositoryConnection m_cxn = null; + final private BigdataSailRepository m_repo; + private BigdataSailRepositoryConnection m_cxn; - public ObjectManager(final UUID uuid, final BigdataSailRepository cxn) { - super(uuid, cxn.getValueFactory()); - m_repo = cxn; - } + /** + * + * @param endpoint + * A SPARQL endpoint that may be used to communicate with the + * database. + * @param cxn + * A connection to the database. + */ + public ObjectManager(final String endpoint, final BigdataSailRepository cxn) { + + super(endpoint, cxn.getValueFactory()); + + m_repo = cxn; + + } /** * @return direct repository connection @@ -56,30 +99,18 @@ @Override public void close() { try { - m_repo.shutDown(); + if (m_repo.getSail().isOpen()) + m_repo.shutDown(); } catch (RepositoryException e) { - log.warn("Problem with close", e); + log.error("Problem with close", e); } - m_dict.clear(); + super.close(); } - public BigdataSailRepositoryConnection establishUnisolatedConnection() { - if (m_cxn == null) { - try { - m_cxn = m_repo.getUnisolatedConnection(); - m_cxn.setAutoCommit(false); - } catch (RepositoryException e) { - throw new RuntimeException("Unable to establish unisolated connection", e); - } - } - - return m_cxn; - } - @Override public ICloseableIterator<BindingSet> evaluate(final String query) { try { - final TupleQuery q = establishUnisolatedConnection().prepareTupleQuery(QueryLanguage.SPARQL, query); + final TupleQuery q = getUnisolatedConnection().prepareTupleQuery(QueryLanguage.SPARQL, query); final TupleQueryResult res = q.evaluate(); return new CloseableIteratorWrapper<BindingSet>(new Iterator<BindingSet>() { @@ -120,7 +151,7 @@ public ICloseableIterator<Statement> evaluateGraph(final String query) { try { - final GraphQuery q = establishUnisolatedConnection().prepareGraphQuery(QueryLanguage.SPARQL, query); + final GraphQuery q = getUnisolatedConnection().prepareGraphQuery(QueryLanguage.SPARQL, query); final GraphQueryResult res = q.evaluate(); return new CloseableIteratorWrapper<Statement>(new Iterator<Statement>() { @@ -223,13 +254,13 @@ // experiment with adding using batch syntax if (false) { // m_cxn.getTripleStore().addStatement(id, key, val); - establishUnisolatedConnection().add(id, key, val); + getUnisolatedConnection().add(id, key, val); } else { final ISPO spo = new BigdataStatementImpl((BigdataResource) id, (BigdataURI) key, (BigdataValue) val, null, StatementEnum.Explicit, false); - establishUnisolatedConnection().getTripleStore().addStatements(new ISPO[] {spo}, 1); + getUnisolatedConnection().getTripleStore().addStatements(new ISPO[] {spo}, 1); } } @@ -237,12 +268,25 @@ public void retract(Resource id, URI key, Value val) throws RepositoryException { if (log.isTraceEnabled()) log.trace("Removing statement: " + id.stringValue() + " " + key.stringValue() + " " + val.stringValue()); - establishUnisolatedConnection().remove(id, key, val); + getUnisolatedConnection().remove(id, key, val); } + private BigdataSailRepositoryConnection getUnisolatedConnection() { + if (m_cxn == null) { + try { + m_cxn = m_repo.getUnisolatedConnection(); + m_cxn.setAutoCommit(false); + } catch (RepositoryException e) { + throw new RuntimeException("Unable to establish unisolated connection", e); + } + } + + return m_cxn; + } + @Override - void doCommit() { - establishUnisolatedConnection().getTripleStore().commit(); + protected void doCommit() { + getUnisolatedConnection().getTripleStore().commit(); try { m_cxn.close(); } catch (RepositoryException e) { @@ -252,13 +296,13 @@ } } - /** - * doRollback handles the "partial" updates written to maintain referential integrity and also - * incremental updates of "dirty" objects. - */ - @Override - void doRollback() { - establishUnisolatedConnection().getTripleStore().abort(); + /** + * doRollback handles the "partial" updates written to maintain referential + * integrity and also incremental updates of "dirty" objects. + */ + @Override + protected void doRollback() { + getUnisolatedConnection().getTripleStore().abort(); try { m_cxn.close(); } catch (RepositoryException e) { @@ -268,30 +312,27 @@ } } - @Override - public void remove(IGPO gpo) { - try { - // Removes all references - establishUnisolatedConnection().remove(gpo.getId(), null, null); - establishUnisolatedConnection().remove((Resource) null, null, gpo.getId()); - } catch (RepositoryException e) { - throw new RuntimeException("Unable to remove object", e); - } - } + @Override + public void remove(final IGPO gpo) { + try { + // Removes all references + final BigdataSailRepositoryConnection cxn = getUnisolatedConnection(); + cxn.remove(gpo.getId(), null, null); + cxn.remove((Resource) null, null, gpo.getId()); + // TODO This is not marking the IGPO as removed? + } catch (RepositoryException e) { + throw new RuntimeException("Unable to remove object", e); + } + } @Override - public ValueFactory getValueFactory() { - return m_valueFactory; - } - - @Override void flushTerms() { if (m_terms.size() > 0) { final BigdataValue[] terms = new BigdataValue[m_terms.size()]; m_terms.toArray(terms); m_terms.clear(); final long start = System.currentTimeMillis(); - establishUnisolatedConnection().getTripleStore().addTerms(terms); + getUnisolatedConnection().getTripleStore().addTerms(terms); if (log.isTraceEnabled()) log.trace("Added " + terms.length + " terms: " + (System.currentTimeMillis()-start) + "ms"); } @@ -303,31 +344,45 @@ if (m_removes.size() > 0) { final ISPO[] spos = statementsToSPO(m_removes); m_removes.clear(); - establishUnisolatedConnection().getTripleStore().removeStatements(spos, spos.length); + getUnisolatedConnection().getTripleStore().removeStatements(spos, spos.length); + } + + // handle batch inserts + if (m_inserts.size() > 0) { + + final ISPO[] spos = statementsToSPO(m_inserts); + + m_inserts.clear(); + + getUnisolatedConnection().getTripleStore().addStatements( + spos, spos.length); + } - - // handle batch inserts - if (m_inserts.size() > 0) { - final ISPO[] spos = statementsToSPO(m_inserts); - m_inserts.clear(); - establishUnisolatedConnection().getTripleStore().addStatements(spos, spos.length); - - } + } - SPO[] statementsToSPO(List<Statement> statements) { - final int size = statements.size(); - SPO[] ret = new SPO[size]; - - for (int i = 0; i < size; i++) { - final BigdataStatement s = (BigdataStatement) statements.get(i); - ret[i] = new SPO(s.getSubject().getIV(), s.getPredicate().getIV(), s.getObject().getIV(), StatementEnum.Explicit); - if (ret[i].s == null || ret[i].p == null || ret[i].o == null) { - throw new IllegalStateException("Values must be bound"); - } - } - - return ret; - } + SPO[] statementsToSPO(final List<Statement> statements) { + final int size = statements.size(); + final SPO[] ret = new SPO[size]; + + for (int i = 0; i < size; i++) { + + final BigdataStatement s = (BigdataStatement) statements.get(i); + + ret[i] = new SPO(s.getSubject().getIV(), s.getPredicate().getIV(), + s.getObject().getIV(), StatementEnum.Explicit); + + if (ret[i].s == null || ret[i].p == null || ret[i].o == null) { + + throw new IllegalStateException("Values must be bound"); + + } + + } + + return ret; + + } + } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/ObjectMgrModel.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/ObjectMgrModel.java 2012-08-09 11:56:37 UTC (rev 6427) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/om/ObjectMgrModel.java 2012-08-09 15:24:19 UTC (rev 6428) @@ -1,3 +1,29 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 19, 2012 + */ package com.bigdata.gom.om; import java.util.ArrayList; @@ -2,5 +28,8 @@ import java.util.Iterator; +import java.util.List; import java.util.UUID; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; @@ -12,98 +41,167 @@ import org.openrdf.model.URI; import org.openrdf.model.Value; import org.openrdf.model.ValueFactory; -import org.openrdf.model.impl.URIImpl; import org.openrdf.repository.RepositoryException; -import com.bigdata.gom.gpo.BasicSkin; import com.bigdata.gom.gpo.GPO; import com.bigdata.gom.gpo.IGPO; -import com.bigdata.rdf.internal.IV; -import com.bigdata.rdf.model.BigdataResource; import com.bigdata.rdf.model.BigdataURI; import com.bigdata.rdf.model.BigdataValue; import com.bigdata.rdf.model.BigdataValueFactory; -import com.bigdata.rdf.model.StatementEnum; -import com.bigdata.rdf.sail.webapp.client.RemoteRepository.AddOp; -import com.bigdata.rdf.spo.SPO; +/** + * Base class for {@link IObjectManager} implementations. This class handles + * {@link IObjectManager} protocol for maintaining an transaction edit list. + * Concrete implementations need to provide for communication with the database + * (either remote or embedded) and the DESCRIBE (aka Object) cache. + * + * @author <a href="mailto:mar...@us...">Martyn + * Cutcher</a> + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ public abstract class ObjectMgrModel implements IObjectManager { - protected static final Logger log = Logger.getLogger(IObjectManager.class); + private static final Logger log = Logger.getLogger(ObjectMgrModel.class); - final WeakHashMap<Resource, IGPO> m_dict = new WeakHashMap<Resource, IGPO>(); + /** + * The {@link UUID} for this object manager instance. + */ + private final UUID m_uuid; + + // TODO Should this be a BigdataValueFactory? + protected final ValueFactory m_valueFactory; + + /** Object Creation and ID Management patterns. */ + private final IIDGenerator m_idGenerator; + + /** + * Local cache. + */ + private final WeakHashMap<Resource, IGPO> m_dict = new WeakHashMap<Resource, IGPO>(); - final ConcurrentHashMap<URI, URI> m_internedKeys = new ConcurrentHashMap<URI, URI>(); - - final ValueFactory m_valueFactory; - - final UUID m_uuid; - + /** + * TODO The {@link BigdataValueFactory} handles this with + * {@link BigdataValueFactory#asValue(Value)}. Use that instead? + */ + private final ConcurrentHashMap<URI, URI> m_internedKeys = new ConcurrentHashMap<URI, URI>(); + + /* + * We need to maintain a dirty list in order to pin object references that + * are dirty. On commit, we need to send the retracts and the asserts in a + * single operation, which is why these things are tracked on separate + * lists. + * + * FIXME The OM should not be tracking the terms. The StatementBuffer or + * Sail will handle this. + */ // new terms cache to enable batch term registration on update/flush - final ArrayList<BigdataValue> m_terms = new ArrayList<BigdataValue>(); - final ArrayList<Statement> m_inserts = new ArrayList<Statement>(); - final ArrayList<Statement> m_removes = new ArrayList<Statement>(); + protected final List<BigdataValue> m_terms = new ArrayList<BigdataValue>(); + protected final List<Statement> m_inserts = new ArrayList<Statement>(); + protected final List<Statement> m_removes = new ArrayList<Statement>(); - final URI s_nmeMgr; + private final ArrayList<GPO> m_dirtyGPOs = new ArrayList<GPO>(); + + private final int m_maxDirtyListSize = 1000; // 5000; // FIXME: Init from property file - // Object Creation and ID Management patterns for default idGenerator - IIDGenerator m_idGenerator = null; + private final URI s_nmeMgr; - int m_transactionCounter = 0; + /** + * A lock for things which need to be serialized, initially just the native + * transaction stuff. Avoid using "synchronized(this)" or the synchronized + * keyword as that forces everything to contend for the same lock. If you + * can use different locks for different types of things then you have + * better concurrency (but, of course, only as appropriate). + */ + private final Lock lock = new ReentrantLock(); - ObjectMgrModel(final UUID uuid, final ValueFactory valueFactory) { + /** + * The native transaction counter. + */ + private int m_transactionCounter = 0; + + /** + * + * @param endpoint + * The SPARQL endpoint that can be used to communicate with the + * database. + * @param valueFactory + * The value factory. + */ + public ObjectMgrModel( + final String endpoint, + final ValueFactory valueFactory) { + m_valueFactory = valueFactory; - m_uuid = uuid; + m_uuid = UUID.randomUUID(); + + m_idGenerator = new IDGenerator(endpoint, m_uuid, m_valueFactory); + + /* + * FIXME UUIG COINING. Plus this needs to be global if we have a + * "name manager" object. Frankly, I do not see any reason to have + * "named roots" in RDF GOM. Any URI can be a named root - you just need + * to use the URI! + */ s_nmeMgr = m_valueFactory.createURI("gpo:nmeMgr/"+m_uuid); - addNewTerm((BigdataValue) s_nmeMgr); + + addNewTerm((BigdataValue) s_nmeMgr); + } public IGPO getDefaultNameMgr() { - return getGPO(s_nmeMgr); + + return getGPO(s_nmeMgr); + } - public void setIDGenerator(final IIDGenerator idgenerator) { - m_idGenerator = idgenerator; - } - public UUID getID() { - return m_uuid; + + return m_uuid; + } - class DefaultIDGenerator implements IIDGenerator { - final URI s_idMgr; - final URI s_idMgrNextId; - BasicSkin m_idMgr; - - DefaultIDGenerator() { - s_idMgr = m_valueFactory.createURI("gpo:idMgr/"+m_uuid); - s_idMgrNextId = m_valueFactory.createURI("gpo:idMgr/"+m_uuid + "#nextId"); - - m_idMgr = new BasicSkin(getGPO(s_idMgr)); + @Override + final public ValueFactory getValueFactory() { - addNewTerm((BigdataValue) s_idMgr); - addNewTerm((BigdataValue) s_idMgrNextId ); - } - - /** - * Default IIDGenerator implementation for ObjectManagers. - */ - public URI genId() { - if (m_idMgr == null) { - m_idMgr = new BasicSkin(getGPO(s_idMgr)); - } - - int nxtId = m_idMgr.getIntValue(s_idMgrNextId)+1; - m_idMgr.setValue(s_idMgrNextId, nxtId); - - return getValueFactory().createURI("gpo:" + m_uuid + "/" + nxtId); - } + return m_valueFactory; - public void rollback() { - m_idMgr = null; // force reload to committed state on next access - } - } + } + +// class DefaultIDGenerator implements IIDGenerator { +// final URI s_idMgr; +// final URI s_idMgrNextId; +// BasicSkin m_idMgr; +// +// DefaultIDGenerator() { +// s_idMgr = m_valueFactory.createURI("gpo:idMgr/"+m_uuid); +// s_idMgrNextId = m_valueFactory.createURI("gpo:idMgr/"+m_uuid + "#nextId"); +// +// m_idMgr = new BasicSkin(getGPO(s_idMgr)); +// +// addNewTerm((BigdataValue) s_idMgr); +// addNewTerm((BigdataValue) s_idMgrNextId ); +// } +// +// /** +// * Default IIDGenerator implementation for ObjectManagers. +// */ +// public URI genId() { +// if (m_idMgr == null) { +// m_idMgr = new BasicSkin(getGPO(s_idMgr)); +// } +// +// final int nxtId = m_idMgr.getIntValue(s_idMgrNextId) + 1; +// +// m_idMgr.setValue(s_idMgrNextId, nxtId); +// +// return getValueFactory().createURI("gpo:" + m_uuid + "/" + nxtId); +// } +// +// public void rollback() { +// m_idMgr = null; // force reload to committed state on next access +// } +// } @Override public URI internKey(final URI key) { @@ -118,10 +216,6 @@ return uri; } - final ArrayList<GPO> m_dirtyGPOs = new ArrayList<GPO>(); - - final int m_maxDirtyListSize = 1000; // 5000; // FIXME: Init from property file - /** * GPOs are added to the dirty list when initially modified. * @@ -143,7 +237,7 @@ private void flushDirtyObjects() { // prepare values - Iterator<GPO> newValues = m_dirtyGPOs.iterator(); + final Iterator<GPO> newValues = m_dirtyGPOs.iterator(); while (newValues.hasNext()) { final GPO gpo = newValues.next(); gpo.prepareBatchTerms(); @@ -156,7 +250,7 @@ final long count = m_dirtyGPOs.size(); if (true) { - Iterator<GPO> updates = m_dirtyGPOs.iterator(); + final Iterator<GPO> updates = m_dirtyGPOs.iterator(); while (updates.hasNext()) { updates.next().prepareBatchUpdate(); } @@ -164,7 +258,7 @@ flushStatements(); } else { // update dirty objects - is it worth while batching SPO[]? - Iterator<GPO> updates = m_dirtyGPOs.iterator(); + final Iterator<GPO> updates = m_dirtyGPOs.iterator(); while (updates.hasNext()) { try { updates.next().update(); @@ -174,8 +268,9 @@ } } m_dirtyGPOs.clear(); - if (log.isTraceEnabled()) - log.trace("Flush took " + (System.currentTimeMillis()-start) + "ms for " + count + " objects"); + if (log.isTraceEnabled()) + log.trace("Flush took " + (System.currentTimeMillis() - start) + + "ms for " + count + " objects"); } abstract void flushStatements(); @@ -193,53 +288,74 @@ } @Override - public synchronized int beginNativeTransaction() { - return m_transactionCounter++; - } + public int beginNativeTransaction() { + lock.lock(); + try { + return m_transactionCounter++; + } finally { + lock.unlock(); + } + } - @Override - public int commitNativeTransaction(final int expectedCounter) { - final int ret = --m_transactionCounter; - if (ret != expectedCounter) { - throw new IllegalArgumentException("Unexpected transaction counter"); - } - - if (ret == 0) { - flushDirtyObjects(); - } - - doCommit(); - - return ret; + @Override + public int commitNativeTransaction(final int expectedCounter) { + lock.lock(); + try { + final int ret = --m_transactionCounter; + if (ret != expectedCounter) { + throw new IllegalArgumentException( + "Unexpected transaction counter"); + } + + if (ret == 0) { + flushDirtyObjects(); + } + + doCommit(); + + return ret; + } finally { + lock.unlock(); + } } - abstract void doCommit(); + /** + * Hook for extended commit processing. + */ + protected abstract void doCommit(); - @Override - public int getNativeTransactionCounter() { - return m_transactionCounter; + @Override + public int getNativeTransactionCounter() { + /* + * Note: You must obtain the lock for visibility of the current value + * unless the transaction counter is either volatile or an + * AtomicInteger. + */ + lock.lock(); + try { + return m_transactionCounter; + } finally { + lock.unlock(); + } } @Override - public void rollbackNativeTransaction() { - // just clear the cache for now - m_dict.clear(); - m_dirtyGPOs.clear(); - m_transactionCounter = 0; - if (m_idGenerator != null) { - m_idGenerator.rollback(); - } - - doRollback(); + public void rollbackNativeTransaction() { + clearCache(); + m_transactionCounter = 0; + if (m_idGenerator != null) { + m_idGenerator.rollback(); + } + doRollback(); } - abstract void doRollback(); + /** + * Hook for extended rollback processing. + */ + abstract protected void doRollback(); @Override public IGPO createGPO() { - if (m_idGenerator == null) { - m_idGenerator = new DefaultIDGenerator(); - } final Resource uri = m_idGenerator.genId(); addNewTerm((BigdataValue) uri); @@ -249,13 +365,19 @@ return ret; } - + + @Deprecated // Let the BigdataSail handle this. protected void addNewTerm(final BigdataValue uri) { - if (uri.isRealIV()) - throw new IllegalArgumentException("IV already available: " + uri.stringValue()); - System.out.println("Adding term: " + uri); - m_terms.add(uri); + if (uri.isRealIV()) + throw new IllegalArgumentException("IV already available: " + + uri.stringValue()); + + if (log.isDebugEnabled()) + log.debug("Adding term: " + uri); + + m_terms.add(uri); + } @@ -263,6 +385,7 @@ * Simple save/recall interface that the ObjectManager provides to simplify * other pattern implementations. Internally it uses a NameManager GPO */ + @Deprecated // no need for explicit save/recall. public void save(final URI key, Value value) { getGPO(s_nmeMgr).setValue(key, value); } @@ -271,13 +394,16 @@ * Simple save/recall interface that the ObjectManager provides to simplify * other pattern implementations. Internally it uses a NameManager GPO */ + @Deprecated // no need for explicit recall. public Value recall(final URI key) { return getGPO(s_nmeMgr).getValue(key); } + @Deprecated // no need for explicit recall. public IGPO recallAsGPO(final URI key) { - Value val = recall(key); + final Value val = recall(key); + if (val instanceof Resource) { return getGPO((Resource) val); } else { @@ -290,11 +416,13 @@ * are the properties of the internal NameManager. */ public Iterator<URI> getNames() { - final GPO nmgr = (GPO) getGPO(s_nmeMgr); + + final GPO nmgr = (GPO) getGPO(s_nmeMgr); return nmgr.getPropertyURIs(); } + @Deprecated // The OM should not be worrying about IVs like this. public void checkValue(Value newValue) { final BigdataValue v = (BigdataValue) newValue; if (!v.isRealIV()) { @@ -302,26 +430,32 @@ } } + @Override + public void close() { + + clearCache(); + + } + public void clearCache() { m_dict.clear(); m_dirtyGPOs.clear(); } - abstract public void insert(final Resource id, final URI key, final Value val) throws RepositoryException; + abstract public void insert(final Resource id, final URI key, + final Value val) throws RepositoryException; - abstract public void retract(final Resource id, final URI key, final Value val) throws RepositoryException; + abstract public void retract(final Resource id, final URI key, + final Value val) throws RepositoryException; - public void insertBatch(final Resource m_id, final URI bigdataURI, final Value v) { - m_inserts.add(m_valueFactory.createStatement(m_id, bigdataURI, v)); - } + public void insertBatch(final Resource m_id, final URI bigdataURI, + final Value v) { + m_inserts.add(m_valueFactory.createStatement(m_id, bigdataURI, v)); + } - public void removeBatch(final Resource m_id, final URI bigdataURI, final Value v) { - m_removes.add(m_valueFactory.createStatement(m_id, bigdataURI, v)); - } + public void removeBatch(final Resource m_id, final URI bigdataURI, + final Value v) { + m_removes.add(m_valueFactory.createStatement(m_id, bigdataURI, v)); + } - @Override - public ValueFactory getValueFactory() { - return m_valueFactory; - } - } Deleted: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/web/GOMListener.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/web/GOMListener.java 2012-08-09 11:56:37 UTC (rev 6427) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/web/GOMListener.java 2012-08-09 15:24:19 UTC (rev 6428) @@ -1,71 +0,0 @@ -package com.bigdata.gom.web; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.Properties; -import java.util.UUID; - -import javax.servlet.ServletContext; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; - -import org.openrdf.repository.RepositoryException; -import org.openrdf.sail.SailException; - -import com.bigdata.gom.om.IObjectManager; -import com.bigdata.gom.om.ObjectManager; -import com.bigdata.journal.ITx; -import com.bigdata.rdf.sail.BigdataSail; -import com.bigdata.rdf.sail.BigdataSailRepository; -import com.bigdata.rdf.sail.BigdataSailRepositoryConnection; -import com.bigdata.rdf.sail.webapp.BigdataRDFServletContextListener; -import com.bigdata.rdf.sail.webapp.ConfigParams; -import com.bigdata.rdf.store.AbstractTripleStore; - -/** - * Extends the BigdataRDFServletContextListener to add a local ObjectManager - * initialization. - * - * @author Martyn Cutcher - * - */ -public class GOMListener extends BigdataRDFServletContextListener { - @Override - public void contextDestroyed(ServletContextEvent ev) { - super.contextDestroyed(ev); - } - - @Override - public void contextInitialized(ServletContextEvent ev) { - super.contextInitialized(ev); - - final ServletContext context = ev.getServletContext(); - - final UUID uuid = UUID.fromString(context.getInitParameter("om-uuid")); - - final String namespace = getBigdataRDFContext().getConfig().namespace; - try { - final AbstractTripleStore tripleStore = (AbstractTripleStore) getBigdataRDFContext().getIndexManager() - .getResourceLocator().locate(namespace, ITx.UNISOLATED); - - if (tripleStore == null) { - throw new RuntimeException("Not found: namespace=" + namespace); - } - - // Wrap with SAIL. - final BigdataSail sail = new BigdataSail(tripleStore); - - final BigdataSailRepository repo = new BigdataSailRepository(sail); - - repo.initialize(); - - final ObjectManager om = new ObjectManager(uuid, repo); - context.setAttribute(ObjectManager.class.getName(), om); - } catch (RepositoryException e) { - throw new RuntimeException(e); - } - } - -} Deleted: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/web/GOMServlet.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/web/GOMServlet.java 2012-08-09 11:56:37 UTC (rev 6427) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/web/GOMServlet.java 2012-08-09 15:24:19 UTC (rev 6428) @@ -1,7 +0,0 @@ -package com.bigdata.gom.web; - -import com.bigdata.rdf.sail.webapp.BigdataServlet; - -public class GOMServlet extends BigdataServlet { - -} Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/web/GOMWebUtil.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/web/GOMWebUtil.java 2012-08-09 11:56:37 UTC (rev 6427) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-gom/src/java/com/bigdata/gom/web/GOMWebUtil.java 2012-08-09 15:24:19 UTC (rev 6428) @@ -1,28 +1,119 @@ package com.bigdata.gom.web; +import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; +import org.openrdf.reposit... [truncated message content] |
From: <tho...@us...> - 2012-08-14 17:57:44
|
Revision: 6440 http://bigdata.svn.sourceforge.net/bigdata/?rev=6440&view=rev Author: thompsonbry Date: 2012-08-14 17:57:33 +0000 (Tue, 14 Aug 2012) Log Message: ----------- I've added a basic describe cache. A linked data GET against a URL that is an extension of the SPARQL end point will now hit the cache. If there is a cache miss, it will turn the request into a SPARQL DESCRIBE. The result of the DESCRIBE will then be injected into the cache. The cache must be explicitly enabled through QueryHints.DESCRIBE_CACHE (edit the default value). This is all alpha and is expected to evolve significantly. I had to modify the ASTDescribeOptimizer and ASTConstructOptimizer in order to pass through the original ProjectionNode for a DESCRIBE query when the DESCRIBE cache is being maintained. We need to know the original projection in order to identify the resources that are being described by the solutions to the as-run query. Those correlations are picked up by a DescribeBindingsCollector that observes the generated solutions and then translated into updates for the DESCRIBE cache by a DescribeCacheUpdater. I broke out the DESCRIBE and CONSTRUCT unit tests from the TestBasicQuery class into their own test suites. I have modified the (new) TestDescribe suite to also verify that the cache is being maintained. Note that this assumes that cache inserts occur lazily when resources are described and are invalidated when a resource is updated. If we work with an eagerly materialized DESCRIBE cache then we would not have the invalidation logic, we would update the cache synchronously as part of insert/remove, and we would not have the logic that monitors the results of a DESCRIBE query to update the cache. See https://sourceforge.net/apps/trac/bigdata/ticket/584 (Maintained DESCRIBE cache) Modified Paths: -------------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/QueryHints.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/ISparqlCache.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/SparqlCache.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpContext.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ASTEvalHelper.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/IEvaluationContext.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTConstructOptimizer.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTDescribeOptimizer.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/TestAll.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/cache/TestAll.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/AbstractDataDrivenSPARQLTestCase.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/TestAll.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/TestBasicQuery.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestASTDescribeOptimizer.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/QueryServlet.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/RESTServlet.java Added Paths: ----------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/DescribeBindingsCollector.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/DescribeCache.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/DescribeCacheUpdater.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/DescribeServiceFactory.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/IDescribeCache.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/TestConstruct.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/eval/TestDescribe.java branches/BIGDATA_RELEASE_1_2_0/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/DescribeCacheServlet.java Removed Paths: ------------- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/CacheHit.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/ICacheHit.java branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/cache/TestSparqlCache.java Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/QueryHints.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/QueryHints.java 2012-08-14 13:36:17 UTC (rev 6439) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/QueryHints.java 2012-08-14 17:57:33 UTC (rev 6440) @@ -400,7 +400,12 @@ boolean DEFAULT_SOLUTION_SET_CACHE = true; /** - * When <code>true</code> a DESCRIBE cache will be maintained. + * When <code>true</code> a DESCRIBE cache will be maintained. This can + * DESCRIBE queries, linked data queries (which are mapped to a DESCRIBE + * query by the NSS), and potentially accelerate star-joins (if the query + * plan is rewritten to hit the DESCRIBE cache and obtain the materialized + * joins from it, but this is best done with a fully materialized and + * synchronously maintained DESCRIBE cache). * * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/584"> * DESCRIBE CACHE </a> Deleted: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/CacheHit.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/CacheHit.java 2012-08-14 13:36:17 UTC (rev 6439) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/CacheHit.java 2012-08-14 17:57:33 UTC (rev 6440) @@ -1,67 +0,0 @@ -/** - -Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. - -Contact: - SYSTAP, LLC - 4501 Tower Road - Greensboro, NC 27410 - lic...@bi... - -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 26, 2012 - */ - -package com.bigdata.rdf.sparql.ast.cache; - -import org.openrdf.query.BindingSet; - -import com.bigdata.striterator.ICloseableIterator; - -/** - * A cache hit. - * - * @author <a href="mailto:tho...@us...">Bryan Thompson</a> - * @version $Id$ - */ -public class CacheHit implements ICacheHit { - - /** - * The timestamp when the cache entry was created / last updated. - */ - private long lastModified; - - @Override - public long getLastModified() { - - return lastModified; - - } - - @Override - public ICloseableIterator<BindingSet> getSolutions() { - - throw new UnsupportedOperationException(); - - } - - public CacheHit() { - - this.lastModified = System.currentTimeMillis(); - - } - -} Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/DescribeBindingsCollector.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/DescribeBindingsCollector.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/DescribeBindingsCollector.java 2012-08-14 17:57:33 UTC (rev 6440) @@ -0,0 +1,160 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2011. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 14, 2012 + */ +package com.bigdata.rdf.sparql.ast.cache; + +import info.aduna.iteration.CloseableIteration; + +import java.util.Set; + +import org.apache.log4j.Logger; +import org.eclipse.jetty.util.ConcurrentHashSet; +import org.openrdf.query.Binding; +import org.openrdf.query.BindingSet; +import org.openrdf.query.QueryEvaluationException; + +import com.bigdata.bop.IVariable; +import com.bigdata.rdf.model.BigdataValue; + +/** + * Collects and reports the distinct bindings observed on some set of variables. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ +public class DescribeBindingsCollector implements + CloseableIteration<BindingSet, QueryEvaluationException> { + + private static final transient Logger log = Logger + .getLogger(DescribeBindingsCollector.class); + + private final IVariable<?>[] originalVars; + private final ConcurrentHashSet<BigdataValue> describedResources; + private final CloseableIteration<BindingSet, QueryEvaluationException> src; + private boolean open = true; + + /** + * + * @param originalVars + * The set of variables whose distinct bound values will be + * reported. + * @param describedResources + * The set of distinct bound values for those variables. + * @param src + * The source iterator. + */ + public DescribeBindingsCollector(final Set<IVariable<?>> originalVars, + final ConcurrentHashSet<BigdataValue> describedResources, + final CloseableIteration<BindingSet, QueryEvaluationException> src) { + + if (originalVars == null) + throw new IllegalArgumentException(); + + if (originalVars.isEmpty()) + throw new IllegalArgumentException(); + + if (describedResources == null) + throw new IllegalArgumentException(); + + if (src == null) + throw new IllegalArgumentException(); + + this.originalVars = originalVars.toArray(new IVariable[originalVars + .size()]); + + this.describedResources = describedResources; + + this.src = src; + + } + + @Override + public void close() throws QueryEvaluationException { + + open = false; + + } + + @Override + public boolean hasNext() throws QueryEvaluationException { + + if (!src.hasNext()) { + + close(); + + return false; + + } + + return true; + + } + + @Override + public BindingSet next() throws QueryEvaluationException { + + if (!open) + throw new QueryEvaluationException("Closed"); + + final BindingSet bs = src.next(); + + for (IVariable<?> var : originalVars) { + + final Binding binding = bs.getBinding(var.getName()); + + if (binding == null) + continue; + + final BigdataValue boundValue = (BigdataValue) binding.getValue(); + + if (boundValue != null) { + + if(describedResources.add(boundValue)) { + + if(log.isInfoEnabled()) { + + log.info("Will describe: var=" + var + ",boundValue=" + + boundValue); + + } + + } + + } + + } + + return bs; + + } + + @Override + public void remove() throws QueryEvaluationException { + + throw new UnsupportedOperationException(); + + } + +} \ No newline at end of file Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/DescribeCache.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/DescribeCache.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/DescribeCache.java 2012-08-14 17:57:33 UTC (rev 6440) @@ -0,0 +1,191 @@ +package com.bigdata.rdf.sparql.ast.cache; + +import java.util.Arrays; +import java.util.Set; + +import org.apache.log4j.Logger; +import org.openrdf.model.Graph; + +import com.bigdata.btree.keys.IKeyBuilder; +import com.bigdata.htree.HTree; +import com.bigdata.io.SerializerUtil; +import com.bigdata.rdf.internal.IV; +import com.bigdata.rdf.model.BigdataURI; +import com.bigdata.rdf.store.AbstractTripleStore; + +/** + * An interface providing a maintained DESCRIBE cache for some + * {@link AbstractTripleStore}. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + * + * FIXME MVCC VIEWS: The same integration issue also needs to be + * addressed for the {@link SparqlCache} for named solution sets. + * + * TODO Support hash partitioned and remove DESCRIBE cache instances. + * These will need access to a service that resolves {@link BigdataURI} + * s to {@link IV}s efficiently. That service can be exposed using the + * NSS or using jini/River. + */ +public class DescribeCache implements IDescribeCache { + + static private transient final Logger log = Logger + .getLogger(SparqlCache.class); + + // /** + // * The KB instance for which the cache is being maintained. + // */ + // private final AbstractTripleStore tripleStore; + + /** + * The cache. The keys are {@link IV}s. The values are the {@link Graph} s + * describing those {@link IV}s. + */ + private HTree cache; + + public DescribeCache(// final AbstractTripleStore tripleStore, + final HTree cache) { + + // if(tripleStore == null) + // throw new IllegalArgumentException(); + + if (cache == null) + throw new IllegalArgumentException(); + + // this.tripleStore = tripleStore; + + this.cache = cache; + + } + + public void close() { + + this.cache.close(); + + } + + /** + * Return a thread-local instance. + * + */ + private IKeyBuilder getKeyBuilder() { + + return cache.getIndexMetadata().getKeyBuilder(); + + } + + /** + * Returns the sort key for the URI. + * + * @param uri + * The URI. + * + * @return The sort key. + */ + private byte[] iv2key(final IKeyBuilder keyBuilder, final IV<?, ?> iv) { + + if (keyBuilder == null) + throw new IllegalArgumentException(); + + if (iv == null) + throw new IllegalArgumentException(); + + keyBuilder.reset(); + + return iv.encode(keyBuilder).getKey(); + + } + + /** + * {@inheritDoc} + * + * TODO Compute the sketch and use an efficient representation for the + * describe graph. The insert should be vectored, scalable, and page + * oriented (blob stream API). + * + * TODO If we explicit manage the raw records then we need to change how the + * metadata is declared. We would have a fixed length value (the addr on the + * backing store - either 4 or 8 bytes). We would also have to manage the + * storage explicitly. + */ + public void insert(final IV<?, ?> iv, final Graph g) { + + final byte[] key = iv2key(getKeyBuilder(), iv); + + final byte[] val = SerializerUtil.serialize(g); + + synchronized (cache) { + + cache.remove(key); + + cache.insert(key, val); + + } + + } + + public Graph lookup(final IV<?, ?> iv) { + + final byte[] key = iv2key(getKeyBuilder(), iv); + + final byte[] val = cache.lookupFirst(key); + + if (val == null) + return null; + + final Graph x = (Graph) SerializerUtil.deserialize(val); + + return x; + + } + + /** + * {@inheritDoc} + * + * TODO If we explicitly manage raw records (rather than transparently) then + * this MUST release the backing raw record for each cache entry. + * + * TODO Invalidation should probably for lastCommitTime+1 (that is, anything + * after the most current lastCommitTime). However, there is still a race + * condition when something is invalidated while there is a concurrent + * request to describe that thing. This can probably be solved by passing + * along the timestamp that the DESCRIBE query is reading on to the + * {@link DescribeCacheUpdater} and from there to the DESCRIBE cache. We + * always should prefer the description of a resource associated with the + * most current view of the database. + */ + public void invalidate(final Set<IV<?, ?>> ivs) { + + if (ivs == null) + throw new IllegalArgumentException(); + + final int size = ivs.size(); + + if (size == 0) + return; + + final IV<?, ?>[] a = ivs.toArray(new IV[size]); + + // Sort 1st for better locality of updates. + Arrays.sort(a); + + final IKeyBuilder keyBuilder = getKeyBuilder(); + + synchronized (cache) { + + for (IV<?, ?> iv : a) { + + final byte[] key = iv2key(keyBuilder, iv); + + cache.remove(key); + + } + + if (log.isTraceEnabled()) + log.trace("Invalidated cache entries: n=" + size); + + } + + } + +} \ No newline at end of file Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/DescribeCacheUpdater.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/DescribeCacheUpdater.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/DescribeCacheUpdater.java 2012-08-14 17:57:33 UTC (rev 6440) @@ -0,0 +1,270 @@ +package com.bigdata.rdf.sparql.ast.cache; + +import info.aduna.iteration.CloseableIteration; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.eclipse.jetty.util.ConcurrentHashSet; +import org.openrdf.model.Graph; +import org.openrdf.model.Resource; +import org.openrdf.model.Value; +import org.openrdf.model.impl.GraphImpl; +import org.openrdf.query.QueryEvaluationException; +import org.openrdf.rio.RDFWriter; + +import com.bigdata.rdf.internal.IV; +import com.bigdata.rdf.model.BigdataStatement; +import com.bigdata.rdf.model.BigdataValue; +import com.bigdata.rdf.sparql.ast.ProjectionNode; +import com.bigdata.rdf.sparql.ast.eval.ASTConstructIterator; +import com.bigdata.rdf.store.TempTripleStore; + +/** + * Collects statements written onto the {@link RDFWriter} interface and + * adds/replaces the DESCRIBE of the {@link Resource} specified to the + * constructor. + * + * @author <a href="mailto:tho...@us...">Bryan + * Thompson</a> + */ +public class DescribeCacheUpdater implements + CloseableIteration<BigdataStatement, QueryEvaluationException> { + + static private transient final Logger log = Logger + .getLogger(DescribeCacheUpdater.class); + + /** + * The cache to be updated. + */ + private final IDescribeCache cache; + + /** + * The {@link BigdataValue}s that become bound for the projection of the + * original DESCRIBE query. We will collect all statements having a + * described resource as either a subject or an object. + * <p> + * Note: This set is populated as the solutions are observed before they + * are fed into the {@link ASTConstructIterator}. It is a + * {@link ConcurrentHashSet} in order to ensure the visibility of the + * updates to this class. + */ + private final ConcurrentHashSet<BigdataValue> describedResources; + + /** + * The source iterator visiting the statements that are the description + * of the projected resources. + */ + private final CloseableIteration<BigdataStatement, QueryEvaluationException> src; + + /** + * The statements to be inserted into the cache as the description of + * that {@link IV}. + * + * TODO This is not scalable to very large numbers of described + * resources nor to resources with very large numbers of statements in + * their descriptions. Try {@link TempTripleStore} with ONE (1) access + * path on SPO. However, we want to have the {@link BigdataStatement} + * with its {@link IV}s and its {@link Value}s, so the + * {@link TempTripleStore} will not work. Something more custom? + */ + final private HashMap<BigdataValue, Graph> graphs = new HashMap<BigdataValue, Graph>(); + + private boolean open = true; + + /** + * + * @param cache + * The cache to be updated. + * @param describedResources + * The {@link BigdataValue}s that become bound for the + * projection of the original DESCRIBE query. We will collect + * all statements having a described resource as either a + * subject or an object. + * @param src + * The source iterator, visiting the statements that are the + * description of the resource(s) identified in the + * {@link ProjectionNode}. + */ + public DescribeCacheUpdater( + final IDescribeCache cache, + final ConcurrentHashSet<BigdataValue> describedResources, + final CloseableIteration<BigdataStatement, QueryEvaluationException> src) { + + if (cache == null) + throw new IllegalArgumentException(); + + if (describedResources == null) + throw new IllegalArgumentException(); + + if (src == null) + throw new IllegalArgumentException(); + + this.cache = cache; + + this.describedResources = describedResources; + + this.src = src; + + } + + @Override + public boolean hasNext() throws QueryEvaluationException { + + if (src.hasNext()) + return true; + + if (open) { + + try { + + /* + * Update the DESCRIBE cache IFF the iterator is exhausted + * by normal means (versus a thrown exception from the + * source iterator). + */ + + updateCache(); + + } finally { + + // Close the iterator regardless. + close(); + + } + + } + + return false; + + } + + /** + * TODO In order to support CBD, we will also have to recognize + * statements that describe blank nodes that are part of the description + * of a described resource as belonging to that described resource. This + * is necessary in order to capture the transitive closure of the + * resource description specified by CBD. The code in this method only + * recognizes statements that directly have a described resource as a + * subject or object. We probably need a reverse map that will allow us + * to navigate from a BigdataValue (or perhaps just a BigdataBNode) to + * all described resources for which that value was observed. That map + * might only need to contain the blank nodes since the description can + * never expand beyond a statement having a blank node in the subject + * (or object) position and a non-blank node in the object (or subject) + * position. + * + * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/578"> + * Concise Bounded Description </a> + */ + @Override + public BigdataStatement next() throws QueryEvaluationException { + + // A statement produced by the CONSTRUCT iterator. + final BigdataStatement stmt = src.next(); + + // Check the Subject. + { + + final BigdataValue s = stmt.getSubject(); + + // Is the subject one of the described resources? + if (describedResources.contains(s)) { + + record(s, stmt); + + } + + } + + // Check the Object. + { + final BigdataValue o = stmt.getObject(); + + // Is the object one of the described resources? + if (describedResources.contains(o)) { + + record(o, stmt); + + } + + } + + return stmt; + + } + + /** + * Associate the statement with the resource. It is part of the + * description of that resource. + * + * @param describedResource + * A resource that is being described. + * @param stmt + * A statement having that resource as either the subject or + * object. + */ + private void record(final BigdataValue describedResource, + final BigdataStatement stmt) { + + Graph g = graphs.get(describedResource); + + if(g == null) { + + graphs.put(describedResource, g = new GraphImpl()); + + } + + g.add(stmt); + + if (log.isDebugEnabled()) + log.debug("DESCRIBE: describedResource=" + describedResource + + ", statement=" + stmt); + + } + + private void updateCache() { + + for (Map.Entry<BigdataValue, Graph> e : graphs.entrySet()) { + + final BigdataValue describedResource = e.getKey(); + + final IV<?, ?> iv = describedResource.getIV(); + + if (iv == null) + throw new AssertionError("IV not set: " + describedResource); + + final Graph graph = e.getValue(); + + cache.insert(iv, graph); + + if (log.isInfoEnabled()) + log.info("DESCRIBE UPDARTE: describedResource=" + + describedResource + ", graph=" + graph); + + } + + } + + @Override + public void close() throws QueryEvaluationException { + + if(open) { + + src.close(); + + open = false; + + } + + } + + @Override + public void remove() throws QueryEvaluationException { + + throw new UnsupportedOperationException(); + + } + +} \ No newline at end of file Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/DescribeServiceFactory.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/DescribeServiceFactory.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/DescribeServiceFactory.java 2012-08-14 17:57:33 UTC (rev 6440) @@ -0,0 +1,224 @@ +package com.bigdata.rdf.sparql.ast.cache; + +import java.util.LinkedHashSet; +import java.util.Set; + +import org.apache.log4j.Logger; + +import com.bigdata.rdf.changesets.IChangeLog; +import com.bigdata.rdf.changesets.IChangeRecord; +import com.bigdata.rdf.changesets.IChangeRecord.ChangeAction; +import com.bigdata.rdf.internal.IV; +import com.bigdata.rdf.sail.BigdataSail.BigdataSailConnection; +import com.bigdata.rdf.sparql.ast.service.BigdataNativeServiceOptions; +import com.bigdata.rdf.sparql.ast.service.CustomServiceFactory; +import com.bigdata.rdf.sparql.ast.service.IServiceOptions; +import com.bigdata.rdf.sparql.ast.service.ServiceCall; +import com.bigdata.rdf.sparql.ast.service.ServiceCallCreateParams; +import com.bigdata.rdf.spo.ISPO; +import com.bigdata.rdf.store.AbstractTripleStore; + +/** + * This service tracks KB updates via an {@link IChangeLog} and is responsible + * for DESCRIBE cache invalidation for resources for which an update has been + * observed. +* + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + */ +public class DescribeServiceFactory implements CustomServiceFactory { + + static private transient final Logger log = Logger + .getLogger(DescribeServiceFactory.class); + + private final IServiceOptions serviceOptions; + + public DescribeServiceFactory() { + + this.serviceOptions = new BigdataNativeServiceOptions(); + + } + + @Override + public IServiceOptions getServiceOptions() { + + return serviceOptions; + + } + + /** + * TODO Implement: The {@link DescribeServiceFactory} COULD be integrated + * into query processing using a rewrite of a DESCRIBE or a star-join into + * an invocation of this service. + */ + @Override + public ServiceCall<?> create(final ServiceCallCreateParams params) { + + throw new UnsupportedOperationException(); + + } + + /** + * Register an {@link IChangeLog} listener that will manage the maintenance + * of the describe cache. + */ + @Override + public void startConnection(final BigdataSailConnection conn) { + + final ISparqlCache sparqlCache = SparqlCacheFactory + .getExistingSparqlCache(conn.getBigdataSail().getQueryEngine()); + + if (sparqlCache == null) { + + // SPARQL cache is not enabled. + return; + + } + + final AbstractTripleStore tripleStore = conn.getTripleStore(); + + final IDescribeCache describeCache = sparqlCache.getDescribeCache( + tripleStore.getNamespace(), tripleStore.getTimestamp()); + + if (describeCache == null) { + + // DESCRIBE cache is not enabled. + return; + + } + + conn.addChangeLog(new DescribeCacheChangeLogListener(describeCache)); + + } + + /** + * Handles cache maintenance/invalidation. + * <p> + * There are several very different scenarios for cache maintenance: + * <dl> + * <dt>Invalidation only.</dt> + * <dd>Changes for resources in the subject or object position cause the + * resource to be invalidated in the cache.</dd> + * <dt>Maintenance</dt> + * <dd>The cache is actually a fully populated and maintained index. All + * updates are propagated into the cache so it remains consistent with the + * statement indices.</dd> + * </dl> + * In addition to these strategies, we could treat the cache as a partial + * representation of the linked data available on the open web for the + * resources and track metadata about the age of the resource description + * for each linked data authority. + * <p> + * Another twist for invalidation would be to bound the cache capacity. That + * would require us to also maintain metadata to support an eviction policy. + * The easiest way to do that is to manage the raw journal entries on the + * store and a LIRS/LRU eviction policy on the {@link IV}s, together with + * the address of the raw record (Blob/Stream). + * + * @author <a href="mailto:tho...@us...">Bryan + * Thompson</a> + */ + static private class DescribeCacheChangeLogListener implements IChangeLog { + + /** The vector size for updates. */ + private static final int threshold = 10000; + /** An updatable view of the cache. */ + private final IDescribeCache cache; + /** The set of IVs to be invalidated (lazily instantiated). */ + private Set<IV<?, ?>> ivs; + /** The size of that set (tracked). */ + private int size = 0; + + DescribeCacheChangeLogListener(final IDescribeCache cache) { + + if (cache == null) + throw new IllegalArgumentException(); + + this.cache = cache; + + } + + /** + * Vectors updates against the DESCRIBE cache. + */ + @Override + public void changeEvent(final IChangeRecord record) { + + if (record.getChangeAction() == ChangeAction.UPDATED) { + + /* + * This state change does not matter for cache maintenance + * unless we also plan to note the {Axiom, Inference, Explicit} + * state on the statements in the cache. + */ + + return; + + } + + if (ivs == null) { + + // Lazy instantiation. + ivs = new LinkedHashSet<IV<?, ?>>(); + + size = 0; + + } + + final ISPO spo = record.getStatement(); + + if (log.isTraceEnabled()) + log.trace("Invalidation notice: spo=" + spo); + + if (ivs.add(spo.s())) + size++; + + if (ivs.add(spo.o())) + size++; + + if (size > threshold) { + flush(); + } + + } + + @Override + public void transactionCommited(long commitTime) { + + flush(); + + } + + @Override + public void transactionAborted() { + + reset(); + + } + + /** + * Incremental flush (vectored cache invalidation notices). + */ + private void flush() { + + if (ivs != null) { + + cache.invalidate(ivs); + + reset(); + + } + + } + + /** Reset the buffer. */ + private void reset() { + + ivs = null; + + size = 0; + + } + + } // class DescribeCacheChangeLogListener + +} // class DescribeServiceFactory Deleted: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/ICacheHit.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/ICacheHit.java 2012-08-14 13:36:17 UTC (rev 6439) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/ICacheHit.java 2012-08-14 17:57:33 UTC (rev 6440) @@ -1,50 +0,0 @@ -/** - -Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved. - -Contact: - SYSTAP, LLC - 4501 Tower Road - Greensboro, NC 27410 - lic...@bi... - -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 26, 2012 - */ - -package com.bigdata.rdf.sparql.ast.cache; - -import org.openrdf.query.BindingSet; - -import com.bigdata.striterator.ICloseableIterator; - -/** - * @author <a href="mailto:tho...@us...">Bryan Thompson</a> - * @version $Id$ - */ -public interface ICacheHit { - - /** - * Return the timestamp when the cache entry was created / last updated. - */ - long getLastModified(); - - /** - * Visit the cached solutions. - */ - ICloseableIterator<BindingSet> getSolutions(); - -} \ No newline at end of file Added: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/IDescribeCache.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/IDescribeCache.java (rev 0) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/IDescribeCache.java 2012-08-14 17:57:33 UTC (rev 6440) @@ -0,0 +1,58 @@ +package com.bigdata.rdf.sparql.ast.cache; + +import java.util.Set; + +import org.openrdf.model.Graph; + +import com.bigdata.rdf.internal.IV; + +/** + * A maintained cache for the DESCRIBE of RDF resources. + * + * @author <a href="mailto:tho...@us...">Bryan Thompson</a> + * + * TODO When has partitioned, each NSS instance (or DESCRIBE cache + * partition) should directly handle the describe of IVs that are + * directed to that partition. + */ +public interface IDescribeCache { + + /** + * Invalidate the identified cache entries. + * + * @param ivs + * The {@link IV}s for the cache entries to be invalidated. + */ + void invalidate(final Set<IV<?, ?>> ivs); + + /** + * Lookup and return the cache entry. + * + * @param iv + * The {@link IV}. + * + * @return The cache entry -or- <code>null</code> if there is no entry for + * that {@link IV}. + * + * TODO Vector lookups for query. We will need to use that to + * support a star-join against the DESCRIBE cache (leveraging + * materialized joins). + */ + Graph lookup(final IV<?, ?> iv); + + /** + * Insert/update the cache entry for an {@link IV}. + * + * @param iv + * The {@link IV}. + * @param g + * The {@link Graph} that describes that {@link IV}. + * + * TODO Vector inserts. + * + * TODO We probably need to include the timestamp of the database + * view from which the resource description was constructed. + */ + void insert(final IV<?, ?> iv, final Graph g); + +} Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/ISparqlCache.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/ISparqlCache.java 2012-08-14 13:36:17 UTC (rev 6439) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/ISparqlCache.java 2012-08-14 17:57:33 UTC (rev 6440) @@ -34,11 +34,23 @@ import com.bigdata.striterator.ICloseableIterator; /** - * A SPARQL solution set cache or a connection to a remove SPARQL cache or cache + * A SPARQL solution set cache or a connection to a remote SPARQL cache or cache * fabric. * * @author <a href="mailto:tho...@us...">Bryan Thompson</a> * @version $Id$ + * + * FIXME MVCC VIEWS: This is not MVCC aware. Just like the + * {@link IDescribeCache}, the instances of this interface need to know + * the namespace and timestamp with which they are associated. Also, + * {@link ISparqlCache} and {@link IDescribeCache} should probably + * extend a common (remote) interface rather than having the + * {@link #getDescribeCache(String, long)} method on this interface. An + * ISparqlCacheService abstraction should be a factory for an interface + * providing a view of a cache fabric as of for a specific namespace + * and timestamp. The remote service will need to have the life cycle + * of the cache associated with a given namespace linked to that + * namespace. */ public interface ISparqlCache { @@ -127,6 +139,19 @@ */ boolean existsSolutions(String solutionSet); + /** + * Return a view of a maintained DESCRIBE cache. + * + * @param namespace + * The KB namespace. + * @param timestamp + * The timestamp of the view. + * + * @return The view of the maintained DESCRIBE cache -or- <code>null</code> + * if no cache is available for that KB. + */ + IDescribeCache getDescribeCache(final String namespace, final long timestamp); + // /** // * Return the result from the cache -or- <code>null</code> if there is a // * cache miss. Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/SparqlCache.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/SparqlCache.java 2012-08-14 13:36:17 UTC (rev 6439) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/cache/SparqlCache.java 2012-08-14 17:57:33 UTC (rev 6440) @@ -27,6 +27,7 @@ package com.bigdata.rdf.sparql.ast.cache; + import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -44,8 +45,10 @@ import com.bigdata.bop.IBindingSet; import com.bigdata.bop.engine.QueryEngine; import com.bigdata.bop.solutions.SolutionSetStream; +import com.bigdata.btree.HTreeIndexMetadata; import com.bigdata.btree.IndexMetadata; import com.bigdata.btree.view.FusedView; +import com.bigdata.htree.HTree; import com.bigdata.journal.AbstractJournal; import com.bigdata.journal.AbstractLocalTransactionManager; import com.bigdata.journal.BufferMode; @@ -55,11 +58,13 @@ import com.bigdata.journal.IRootBlockView; import com.bigdata.journal.Journal; import com.bigdata.journal.TemporaryStore; +import com.bigdata.journal.TimestampUtility; import com.bigdata.rawstore.Bytes; import com.bigdata.rdf.changesets.IChangeLog; import com.bigdata.rdf.sail.BigdataSail; import com.bigdata.rdf.sail.webapp.ConfigParams; import com.bigdata.rdf.sparql.ast.ISolutionSetStats; +import com.bigdata.rdf.sparql.ast.QueryHints; import com.bigdata.rdf.sparql.ast.eval.IEvaluationContext; import com.bigdata.rdf.spo.ISPO; import com.bigdata.relation.locator.DefaultResourceLocator; @@ -123,7 +128,7 @@ */ public class SparqlCache implements ISparqlCache { - private static final Logger log = Logger.getLogger(SparqlCache.class); + static private transient final Logger log = Logger.getLogger(SparqlCache.class); // public interface Options { // @@ -164,16 +169,17 @@ * presumes a circular hash function such as is common in distributed row * stores, etc. */ - private final CacheJournal cache; + private final CacheJournal cacheStore; /** - * FIXME Convert over to Name2Addr and layered resolution with appropriate - * concurrency control at each layer. The problem with layering the MemStore - * journal mode over the RWStore journal mode is that we wind up with two - * journals. There should be one journal with layered addressing (that is, - * with a solution set cache in front of the Journal). That might mean using - * a concurrent hash map for the resolution and named locks to provide - * concurrency control. We could name the solution sets within a scope: + * FIXME FIXME MVCC VIEWS: Convert over to Name2Addr and layered resolution + * with appropriate concurrency control at each layer. The problem with + * layering the MemStore journal mode over the RWStore journal mode is that + * we wind up with two journals. There should be one journal with layered + * addressing (that is, with a solution set cache in front of the Journal). + * That might mean using a concurrent hash map for the resolution and named + * locks to provide concurrency control. We could name the solution sets + * within a scope: * * <pre> * (cache|query|database)[.queryUUID].namespace[.joinVars] @@ -198,9 +204,42 @@ * <p> * 4. We need to have metadata about solution sets on hand for explicit * CREATEs (e.g., supporting declared join variables). + * + * FIXME MVCC VIEWS: Does this permit bleeding between the solution set + * caches for distinct KB instances?!? (It is lacking the KB namespace). */ private final ConcurrentHashMap<String/*name*/,SolutionSetStream> cacheMap; // private final ConcurrentWeakValueCacheWithTimeout<String/* name */, IMemoryManager /* allocationContext */> cacheMap; + + /** + * The {@link DescribeServiceFactory} tracks changes via an + * {@link IChangeLog} registered with each update connection and is + * responsible for cache invalidation. + */ + private DescribeServiceFactory describeServiceFactory; + +// /** +// * TODO Hack enables the DESCRIBE cache. Remove this method? +// */ +// public void setDescribeCache(boolean enableDescribeCache) { +// +// this.enableDescribeCache = enableDescribeCache; +// +// } + +// /** +// * Return <code>true</code> iff the DESCRIBE cache is enabled. +// */ +// public boolean isDescribeCache() { +// +// return enableDescribeCache; +// +// } + + /** + * TODO Hack enables the DESCRIBE cache. + */ + private boolean enableDescribeCache = QueryHints.DEFAULT_DESCRIBE_CACHE; // /** // * The performance counters for the {@link IBufferStrategy} backing the @@ -297,7 +336,7 @@ //// //// properties.setProperty(Journal.Options.HTTPD_PORT, "-1"/* none */); - this.cache = new CacheJournal(properties); + this.cacheStore = new CacheJournal(properties); // /* // * TODO The expire should be per cached object, not global. We would @@ -313,7 +352,13 @@ @Override public void init() { - + + if (enableDescribeCache) { + + describeServiceFactory = new DescribeServiceFactory(); + + } + } /** @@ -336,7 +381,7 @@ cacheMap.clear(); - cache.destroy(); + cacheStore.destroy(); } @@ -347,7 +392,7 @@ */ protected IRWStrategy getStore() { - return (IRWStrategy) cache.getBufferStrategy(); + return (IRWStrategy) cacheStore.getBufferStrategy(); } @@ -466,14 +511,15 @@ emptySolutionSet.iterator()); // write the solutions. - writeSolutions(sset,src); + writeSolutions(sset, src); } - private void writeSolutions(final SolutionSetStream sset, final ICloseableIterator<IBindingSet[]> src) { - + private void writeSolutions(final SolutionSetStream sset, + final ICloseableIterator<IBindingSet[]> src) { + sset.put(src); - + } public ISolutionSetStats getSolutionSetStats(final String solutionSet) { @@ -568,117 +614,70 @@ } -// @Override -// public ICacheHit get(final AST2BOpContext ctx, -// final QueryBase queryOrSubquery) { -// -// /* -// * FIXME Implement. Start with a simple DESCRIBE <uri> cache. -// */ -// -// return null; -// -// } -// -// /* -// * TODO When caching a solution set, make sure that we do so before we apply -// * the solution modifiers (ORDER BY, GROUP BY/HAVING, OFFSET/LIMIT) and -// * perhaps before we evaluate DISTINCT. -// * -// * TODO It will be especially easy if the solution set has been pushed into -// * a hash index, which we can then just pour into the cache. -// * -// * TODO We need a hash code to get started with query matching. However, it -// * can not be the hash code of the query string or we will not be able to -// * parameterize the solution modifiers. This suggests computing a hash -// * function over the AST which knows to leave off the solution modifiers. -// */ -// @Override -// public ICacheHit put(final AST2BOpContext ctx, -// final QueryBase queryOrSubquery, -// final ICloseableIterator<IBindingSet> src) { -// // TODO Auto-generated method stub -// return null; -// } + /** + * + * @return The DESCRIBE cache for that view -or- <code>null</code> if the + * DESCRIBE cache is not enabled. + * + * @see QueryHints#DESCRIBE_CACHE + */ + public IDescribeCache getDescribeCache(final String namespace, + final long timestamp) { -// /** -// * Cache invalidation / cache update protocol. -// * -// * FIXME This listener needs to build up a "transaction" of change events -// * which will cause invalidation of cache entries. Those change events need -// * to be processed once we have committed the change set, but they MUST be -// * processed before another operation can read against the new commit point. -// * <P> -// * In order to close that gap, we can either invalidate the cache as we go -// * (this will cause the query engine to regenerate the cache before the -// * cached results are actually wrong) -or- we need to have a low level -// * callback from the {@link Journal} where we get notice of the -// * {@link IChangeLog} commit (including the timestamp) before the -// * {@link Journal} actually finishes the commit process, but probably after -// * it check points the various indices. E.g., hooked right into the middle -// * of the commit protocol. For a tightly integrated cache, this can be fast -// * enough. -// * <p> -// * Another possibility is to permit reads against the cache for any cached -// * solution for which we have not yet received an invalidation notice. Once -// * we get an invalidation notice, the cache will only respond for that -// * cached solution set up to the lastCommitTime before the -// * {@link IChangeRecord} event (so the cache needs to listen to commit -// * times, which is easy). This will allow read-only operations against -// * historical commit points to proceed but will not allow reads against the -// * cache for cached solution sets which MIGHT be invalidated. -// * <p> -// * Each cache entry needs to have the createTime (commit time against which -// * it was created, which needs to be the actually commit point if the reader -// * is isolated by a transaction). That is the first commit point for which -// * the cache entry is valid. It also needs to know the last commit time for -// * which the cache entry is valid, which is the point at which it was -// * expired. When a cache invalidation notice ({@link IChangeRecord}) has -// * been received, but we have not yet observed the commit for that change -// * record, we need to flag the cache entry as possibly invalid after the -// * then most current last commit time. Queries which hit that window must be -// * passed through to the database. -// * <p> -// * We need one {@link IChangeLog} listener per update connection. There can -// * be multiple such listeners concurrently when the database is using full -// * read/write transactions and/or when there are updates against different -// * triple/quad store instances. -// * -// * TODO Each Change log event indicates an {@link ISPO} which was added to -// * (or removed from) the database. Cache entries which depend on statement -// * patterns which cover those {@link ISPO}s must be invalidated (or updated) -// * when the database update is committed. Obviously, the cache entries need -// * to be indexed for rapid discovery for invalidation purposes (in addition -// * to the discovery for cache hits). -// * -// * TODO Cache entries need to be chained together so we can have hits for -// * the same query for different commit points. The backing solution set for -// * a given commit time needs to be expired no later than when we recycle -// * that commit point. This is yet another place where a low-level -// * integration with the {@link AbstractTransactionService} is required. -// */ -// private class CacheChangeLogListener implements IChangeLog { -// -// @Override -// public void changeEvent(IChangeRecord record) { -// // TODO Auto-generated method stub -// -// } -// -// @Override -// public void transactionCommited(final long commitTime) { -// // TODO Auto-generated method stub -// -// } -// -// @Override -// public void transactionAborted() { -// // TODO Auto-generated method stub -// -// } -// -// } + if (!enableDescribeCache) { + // Not enabled. + return null; + + } + + if (namespace == null) + throw new IllegalArgumentException(); + + /* + * Resolve the DESCRIBE cache for this KB namespace using ATOMIC pattern + * (locking). + */ + + HTree htree; + synchronized (this) { + + final String name = namespace + ".describeCache"; + + htree = cacheStore.getHTree(name); + + if (htree == null) { + + if (TimestampUtility.isReadOnly(timestamp)) { + + // Cache is not pre-existing. + return null; + + } + + final HTreeIndexMetadata metadata = new HTreeIndexMetadata( + name, UUID.randomUUID()); + + metadata.setRawRecords(true/* rawRecords */); + + metadata.setMaxRecLen(0/* maxRecLen */); + + cacheStore.registerIndex(metadata); + + } + + htree = cacheStore.getHTree(name); + + } + + return new DescribeCache(htree); + + } + + /* + * END OF DESCRIBE CACHE SUPPORT + */ + /** * The {@link CacheJournal} provides the backing store for transient named * solution sets. @@ -775,6 +774,7 @@ } + @SuppressWarnings("rawtypes") public DefaultResourceLocator getResourceLocator() { return (DefaultResourceLocator) getLocalIndexManager() Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpContext.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpContext.java 2012-08-14 13:36:17 UTC (rev 6439) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/AST2BOpContext.java 2012-08-14 17:57:33 UTC (rev 6440) @@ -30,6 +30,7 @@ import com.bigdata.rdf.sparql.ast.ISolutionSetStats; import com.bigdata.rdf.sparql.ast.QueryHints; import com.bigdata.rdf.sparql.ast.StaticAnalysis; +import com.bigdata.rdf.sparql.ast.cache.IDescribeCache; import com.bigdata.rdf.sparql.ast.cache.ISparqlCache; import com.bigdata.rdf.sparql.ast.cache.SparqlCache; import com.bigdata.rdf.sparql.ast.cache.SparqlCacheFactory; @@ -383,10 +384,10 @@ * Cache for SPARQL named solution sets. * * TODO Define a query hint for enabling or disabling the SPARQL cache - * for an operation. + * for an operation? */ { - final boolean enable = queryHints == null ? QueryHints.DEFAULT_SOLUTION_SET_CACHE + final boolean enableSparqlCache = queryHints == null ? QueryHints.DEFAULT_SOLUTION_SET_CACHE : Boolean .valueOf(queryHints .getProperty( @@ -394,12 +395,33 @@ QueryHints.DEFAULT_SOLUTION_SET_CACHE ? Boolean.TRUE .toString() : Boolean.FALSE .toString())); - if (enable) { + +// final boolean enableDescribeCache = queryHints == null ? QueryHints.DEFAULT_DESCRIBE_CACHE +// : Boolean.valueOf(queryHints.getProperty( +// QueryHints.DESCRIBE_CACHE, +// QueryHints.DEFAULT_DESCRIBE_CACHE ? Boolean.TRUE +// .toString() : Boolean.FALSE.toString())); + + if (enableSparqlCache) { + + /* + * Note: This will create the cache if it does not exist. At all + * other places in the code we use getExistingSparqlCache() to + * access the cache IFF it exists. Here is where we create it. + */ + this.sparqlCache = SparqlCacheFactory .getSparqlCache(queryEngine); + +// ((SparqlCache) sparqlCache) +// .setDescribeCache(enableDescribeCache); + } else { + this.sparqlCache = null; + } + } this.context = new BOpContextBase(queryEngine); @@ -509,5 +531,12 @@ return sparqlCache; } - + + public IDescribeCache getDescribeCache() { + + return getSparqlCache().getDescribeCache(db.getNamespace(), + db.getTimestamp()); + + } + } Modified: branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ASTEvalHelper.java =================================================================== --- branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ASTEvalHelper.java 2012-08-14 13:36:17 UTC (rev 6439) +++ branches/BIGDATA_RELEASE_1_2_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/eval/ASTEvalHelper.java 2012-08-14 17:57:33 UTC (rev 6440) @@ -30,12 +30,15 @@ import info.aduna.iteration.CloseableIteration; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.log4j.Logger; import org.apache.log4j.MDC; +import org.eclipse.jetty.util.ConcurrentHashSet; import org.openrdf.model.Value; import org.openrdf.query.Binding; import org.openrdf.query.BindingSet; @@ -62,6 +65,7 @@ import com.bigdata.journal.TimestampUtility; import com.bigdata.rdf.internal.IV; import com.bigdata.rdf.internal.IVCache; +import com.bigdata.rdf.model.BigdataStatement; import com.bigdata.rdf.model.BigdataValue; import com.bigdata.rdf.sail.Bigdata2Sesame2BindingSetIterator; import com.bigdata.rdf.sail.BigdataSailRepositoryConnection; @@ -73,8 +77,12 @@ import com.bigdata.rdf.sparql.ast.DeleteInsertGraph; import com.bigdata.rdf.sparql.ast.IDataSetNode; import com.bigdata.rdf.sparql.ast.QueryRoot; +import com.bigdata.rdf.sparql.ast.QueryType; import com.bigdata.rdf.sparql.ast.Update; import com.bigdata.rdf.sparql.ast.UpdateRoot; +import com.bigdata.rdf.sparql.ast.cache.DescribeBindingsCollector; +import com.bigdata.rdf.sparql.ast.cache.DescribeCacheUpdater; +import com.bigdata.rdf.sparql.ast.cache.IDescribeCache; import com.bigdata.rdf.store.AbstractTripleStore; import com.bigdata.rdf.store.BigdataBindingSetResolverator; import com.bigdata.striterator.ChunkedWrappedIterator; @@ -376,6 +384,8 @@ /** * Evaluate a CONSTRUCT/DESCRIBE query. + * <p> + * Note: For a DESCRIBE query, this also updates the DESCRIBE cache. * * @param store * The {@link AbstractTripleStore} having the data. @@ -385,6 +395,9 @@ * The initial solution... [truncated message content] |