From: <mrp...@us...> - 2010-09-28 18:21:11
|
Revision: 3668 http://bigdata.svn.sourceforge.net/bigdata/?rev=3668&view=rev Author: mrpersonick Date: 2010-09-28 18:21:04 +0000 (Tue, 28 Sep 2010) Log Message: ----------- API and test case skeleton for change sets Modified Paths: -------------- branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/BigdataSail.java branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/BigdataSailRepositoryConnection.java Added Paths: ----------- branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/changesets/ branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/changesets/ChangeRecord.java branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/changesets/IChangeLog.java branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/changesets/IChangeRecord.java branches/CHANGE_SET_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/TestChangeSets.java Modified: branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/BigdataSail.java =================================================================== --- branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/BigdataSail.java 2010-09-28 18:10:39 UTC (rev 3667) +++ branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/BigdataSail.java 2010-09-28 18:21:04 UTC (rev 3668) @@ -57,6 +57,7 @@ package com.bigdata.rdf.sail; +import info.aduna.collections.iterators.EmptyIterator; import info.aduna.iteration.CloseableIteration; import java.io.IOException; @@ -128,6 +129,8 @@ import com.bigdata.rdf.rio.StatementBuffer; import com.bigdata.rdf.rules.BackchainAccessPath; import com.bigdata.rdf.rules.InferenceEngine; +import com.bigdata.rdf.sail.changesets.IChangeLog; +import com.bigdata.rdf.sail.changesets.IChangeRecord; import com.bigdata.rdf.spo.ExplicitSPOFilter; import com.bigdata.rdf.spo.ISPO; import com.bigdata.rdf.spo.InferredSPOFilter; @@ -1066,6 +1069,7 @@ * @todo many of the stores can support concurrent writers, but there is a * requirement to serialize writers when truth maintenance is enabled. */ + @Override protected NotifyingSailConnection getConnectionInternal() throws SailException { @@ -2441,6 +2445,21 @@ database.commit(); } + +// /** +// * Commit the write set, providing detailed feedback on the change set +// * that occurred as a result of this commit. +// * +// * @return +// * an iterator over a set of {@link IChangeRecord}s. +// */ +// public synchronized Iterator<IChangeRecord> commit2() throws SailException { +// +// commit(); +// +// return new EmptyIterator<IChangeRecord>(); +// +// } final public boolean isOpen() throws SailException { @@ -3300,6 +3319,16 @@ return new Object[] { dataset, bindings }; } + + /** + * Set the change log on the SAIL connection. See {@link IChangeLog} + * and {@link IChangeRecord}. + * + * @param log + * the change log + */ + public void setChangeLog(final IChangeLog log) { + } } Modified: branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/BigdataSailRepositoryConnection.java =================================================================== --- branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/BigdataSailRepositoryConnection.java 2010-09-28 18:10:39 UTC (rev 3667) +++ branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/BigdataSailRepositoryConnection.java 2010-09-28 18:21:04 UTC (rev 3668) @@ -1,5 +1,6 @@ package com.bigdata.rdf.sail; +import java.util.Iterator; import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; @@ -25,6 +26,8 @@ import com.bigdata.rdf.sail.BigdataSail.BigdataSailConnection; import com.bigdata.rdf.sail.bench.NanoSparqlClient; import com.bigdata.rdf.sail.bench.NanoSparqlClient.QueryType; +import com.bigdata.rdf.sail.changesets.IChangeLog; +import com.bigdata.rdf.sail.changesets.IChangeRecord; import com.bigdata.rdf.sail.sparql.BaseDeclProcessor; import com.bigdata.rdf.sail.sparql.PrefixDeclProcessor; import com.bigdata.rdf.sail.sparql.StringEscapesProcessor; @@ -47,6 +50,11 @@ return (BigdataSailRepository)super.getRepository(); } + @Override + public BigdataSailConnection getSailConnection() { + return (BigdataSailConnection)super.getSailConnection(); + } + /** * {@inheritDoc} * <p> @@ -156,6 +164,34 @@ } +// /** +// * Commit any changes made in the connection, providing detailed feedback +// * on the change set that occurred as a result of this commit. +// * <p> +// * Note: auto-commit is an EXTREMELY bad idea. Performance will be terrible. +// * The database will swell to an outrageous size. TURN OFF AUTO COMMIT. +// * +// * @see BigdataSail.Options#ALLOW_AUTO_COMMIT +// */ +// public Iterator<IChangeRecord> commit2() throws RepositoryException { +// +// // auto-commit is heinously inefficient +// if (isAutoCommit() && +// !((BigdataSailConnection) getSailConnection()).getAllowAutoCommit()) { +// +// throw new RepositoryException("please set autoCommit to false"); +// +// } +// +// try { +// return getSailConnection().commit2(); +// } +// catch (SailException e) { +// throw new RepositoryException(e); +// } +// +// } + /** * Flush the statement buffers. The {@link BigdataSailConnection} heavily * buffers assertions and retractions. Either a {@link #flush()} or a @@ -298,5 +334,18 @@ throw new MalformedQueryException(e.getMessage(), e); } } + + /** + * Set the change log on the SAIL connection. See {@link IChangeLog} and + * {@link IChangeRecord}. + * + * @param log + * the change log + */ + public void setChangeLog(final IChangeLog log) { + + getSailConnection().setChangeLog(log); + + } } Added: branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/changesets/ChangeRecord.java =================================================================== --- branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/changesets/ChangeRecord.java (rev 0) +++ branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/changesets/ChangeRecord.java 2010-09-28 18:21:04 UTC (rev 3668) @@ -0,0 +1,47 @@ +package com.bigdata.rdf.sail.changesets; + +import com.bigdata.rdf.model.BigdataStatement; +import com.bigdata.rdf.model.StatementEnum; + +public class ChangeRecord implements IChangeRecord { + + private final BigdataStatement stmt; + + private final ChangeAction action; + + private final StatementEnum oldType; + + public ChangeRecord(final BigdataStatement stmt, + final ChangeAction action) { + + this(stmt, action, null); + + } + + public ChangeRecord(final BigdataStatement stmt, final ChangeAction action, + final StatementEnum oldType) { + + this.stmt = stmt; + this.action = action; + this.oldType = oldType; + + } + + public ChangeAction getChangeAction() { + + return action; + + } + + public StatementEnum getOldStatementType() { + + return oldType; + + } + + public BigdataStatement getStatement() { + + return stmt; + + } +} Added: branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/changesets/IChangeLog.java =================================================================== --- branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/changesets/IChangeLog.java (rev 0) +++ branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/changesets/IChangeLog.java 2010-09-28 18:21:04 UTC (rev 3668) @@ -0,0 +1,38 @@ +package com.bigdata.rdf.sail.changesets; + +/** + * Provides detailed information on changes made to statements in the database. + * Change records are generated for any statements that are used in + * addStatement() or removeStatements() operations on the SAIL connection, as + * well as any inferred statements that are added or removed as a result of + * truth maintenance when the database has inference enabled. Change records + * will be sent to an instance of this class via the + * {@link #changeEvent(IChangeRecord)} method. These events will + * occur on an ongoing basis as statements are added to or removed from the + * indices. It is the change log's responsibility to collect change records. + * When the transaction is actually committed (or aborted), the change log will + * receive notification via {@link #transactionCommited()} or + * {@link #transactionAborted()}. + */ +public interface IChangeLog { + + /** + * Occurs when a statement add or remove is flushed to the indices (but + * not yet committed). + * + * @param record + * the {@link IChangeRecord} + */ + void changeEvent(final IChangeRecord record); + + /** + * Occurs when the current SAIL transaction is committed. + */ + void transactionCommited(); + + /** + * Occurs if the current SAIL transaction is aborted. + */ + void transactionAborted(); + +} Added: branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/changesets/IChangeRecord.java =================================================================== --- branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/changesets/IChangeRecord.java (rev 0) +++ branches/CHANGE_SET_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/changesets/IChangeRecord.java 2010-09-28 18:21:04 UTC (rev 3668) @@ -0,0 +1,119 @@ +package com.bigdata.rdf.sail.changesets; + +import com.bigdata.rdf.model.BigdataStatement; +import com.bigdata.rdf.model.StatementEnum; + +/** + * Provides detailed information on changes made to statements in the database. + * Change records are generated for any statements that are used in + * addStatement() or removeStatements() operations on the SAIL connection, as + * well as any inferred statements that are added or removed as a result of + * truth maintenance when the database has inference enabled. + * <p> + * See {@link IChangeLog}. + */ +public interface IChangeRecord { + + /** + * Attempting to add or remove statements can have a number of different + * effects. This enum captures the different actions that can take place as + * a result of trying to add or remove a statement from the database. + */ + public enum ChangeAction { + + /** + * The focus statement was not in the database before and will be + * in the database after the commit. This can be the result of either + * explicit addStatement() operations on the SAIL connection, or from + * new inferences being generated via truth maintenance when the + * database has inference enabled. If the focus statement has a + * statement type of explicit then it was added via an addStatement() + * operation. If the focus statement has a statement type of inferred + * then it was added via truth maintenance. + */ + ADDED, + + /** + * The focus statement was in the database before and will not + * be in the database after the commit. When the database has inference + * and truth maintenance enabled, the statement that is the focus of + * this change record was either an explicit statement that was the + * subject of a removeStatements() operation on the connection, or it + * was an inferred statement that was removed as a result of truth + * maintenance. Either way, the statement is no longer provable as an + * inference using other statements still in the database after the + * commit. If it were still provable, the explicit statement would have + * had its type changed to inferred, and the inferred statement would + * have remained untouched by truth maintenance. If an inferred + * statement was the subject of a removeStatement() operation on the + * connection it would have resulted in a no-op, since inferences can + * only be removed via truth maintenance. + */ + REMOVED, + + /** + * This change action can only occur when inference and truth + * maintenance are enabled on the database. Sometimes an attempt at + * statement addition or removal via an addStatement() or + * removeStatements() operation on the connection will result in a type + * change rather than an actual assertion or deletion. When in + * inference mode, statements can have one of three statement types: + * explicit, inferred, or axiom (see {@link StatementEnum}). There are + * several reasons why a statement will change type rather than be + * asserted or deleted: + * <p> + * <ul> + * <li> A statement is asserted, but already exists in the database as + * an inference or an axiom. The existing statement will have its type + * changed from inference or axiom to explicit. </li> + * <li> An explicit statement is retracted, but is still provable by + * other means. It will have its type changed from explicit to + * inference. </li> + * <li> An explicit statement is retracted, but is one of the axioms + * needed for inference. It will have its type changed from explicit to + * axiom. </li> + * </ul> + */ + TYPE_CHANGE, + +// /** +// * This change action can occur for one of two reasons: +// * <p> +// * <ul> +// * <li> A statement is asserted, but already exists in the database as +// * an explicit statement. </li> +// * <li> An inferred statement or an axiom is retracted. Only explicit +// * statements can be retracted via removeStatements() operations. </li> +// * </ul> +// */ +// NO_OP + + } + + /** + * Return the statement that is the focus of this change record. + * + * @return + * the {@link BigdataStatement} + */ + BigdataStatement getStatement(); + + /** + * Return the change action for this change record. + * + * @return + * the {@link ChangeAction} + */ + ChangeAction getChangeAction(); + + /** + * If the change action is {@link ChangeAction#TYPE_CHANGE}, this method + * will return the old statement type of the focus statement. The + * new statement type is available on the focus statement itself. + * + * @return + * the old statement type of the focus statement + */ + StatementEnum getOldStatementType(); + +} Added: branches/CHANGE_SET_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/TestChangeSets.java =================================================================== --- branches/CHANGE_SET_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/TestChangeSets.java (rev 0) +++ branches/CHANGE_SET_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/TestChangeSets.java 2010-09-28 18:21:04 UTC (rev 3668) @@ -0,0 +1,196 @@ +/** +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 Sep 16, 2009 + */ + +package com.bigdata.rdf.sail; + +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import org.apache.log4j.Logger; +import org.openrdf.model.URI; +import org.openrdf.model.vocabulary.RDF; +import org.openrdf.model.vocabulary.RDFS; +import com.bigdata.rdf.model.BigdataStatement; +import com.bigdata.rdf.model.BigdataValueFactory; +import com.bigdata.rdf.sail.changesets.ChangeRecord; +import com.bigdata.rdf.sail.changesets.IChangeLog; +import com.bigdata.rdf.sail.changesets.IChangeRecord; +import com.bigdata.rdf.sail.changesets.IChangeRecord.ChangeAction; +import com.bigdata.rdf.store.BD; + +/** + * @author <a href="mailto:mrp...@us...">Mike Personick</a> + * @version $Id$ + */ +public class TestChangeSets extends ProxyBigdataSailTestCase { + + protected static final Logger log = Logger.getLogger(TestChangeSets.class); + + /** + * + */ + public TestChangeSets() { + } + + /** + * @param arg0 + */ + public TestChangeSets(String arg0) { + super(arg0); + } + + public void testChangeSets() throws Exception { + + final BigdataSail sail = getSail(); + sail.initialize(); + final BigdataSailRepository repo = new BigdataSailRepository(sail); + final BigdataSailRepositoryConnection cxn = + (BigdataSailRepositoryConnection) repo.getConnection(); + cxn.setAutoCommit(false); + + final TestChangeLog changeLog = new TestChangeLog(); + cxn.setChangeLog(changeLog); + + try { + + final BigdataValueFactory vf = (BigdataValueFactory) sail.getValueFactory(); + + final String ns = BD.NAMESPACE; + + final URI a = vf.createURI(ns+"A"); + final URI b = vf.createURI(ns+"B"); + final URI c = vf.createURI(ns+"C"); + + final BigdataStatement[] explicit = new BigdataStatement[] { + vf.createStatement(a, RDFS.SUBCLASSOF, b), + vf.createStatement(b, RDFS.SUBCLASSOF, c), + }; + + final BigdataStatement[] inferred = new BigdataStatement[] { + vf.createStatement(a, RDF.TYPE, RDFS.CLASS), + vf.createStatement(a, RDFS.SUBCLASSOF, RDFS.RESOURCE), + vf.createStatement(a, RDFS.SUBCLASSOF, a), + vf.createStatement(a, RDFS.SUBCLASSOF, c), + vf.createStatement(b, RDF.TYPE, RDFS.CLASS), + vf.createStatement(b, RDFS.SUBCLASSOF, RDFS.RESOURCE), + vf.createStatement(b, RDFS.SUBCLASSOF, b), + vf.createStatement(c, RDF.TYPE, RDFS.CLASS), + vf.createStatement(c, RDFS.SUBCLASSOF, RDFS.RESOURCE), + vf.createStatement(c, RDFS.SUBCLASSOF, c), + }; + +/**/ + cxn.setNamespace("ns", ns); + + for (BigdataStatement stmt : explicit) { + cxn.add(stmt); + } + + cxn.commit();// + + if (log.isDebugEnabled()) { + log.debug("\n" + sail.getDatabase().dumpStore(true, true, false)); + } + + final Collection<IChangeRecord> expected = + new LinkedList<IChangeRecord>(); + for (BigdataStatement stmt : explicit) { + expected.add(new ChangeRecord(stmt, ChangeAction.ADDED)); + } + for (BigdataStatement stmt : inferred) { + expected.add(new ChangeRecord(stmt, ChangeAction.ADDED)); + } + + compare(expected, changeLog.getChangeSet()); + + } finally { + cxn.close(); + sail.__tearDownUnitTest(); + } + + } + + private void compare(final Collection<IChangeRecord> expected, + final Collection<IChangeRecord> actual) { + + fail(); + + } + + /** + * This is a very simple implementation of a change log. NOTE: This is not + * a particularly great implementation. First of all it ends up storing + * two copies of the change set. Secondly it needs to be smarter about + * concurrency, or maybe we can be smart about it when we do the + * implementation on the other side (the SAIL connection can just write + * change events to a buffer and then the buffer can be drained by + * another thread that doesn't block the actual read/write operations, + * although then we need to be careful not to issue the committed() + * notification before the buffer is drained). + * + * @author mike + * + */ + public class TestChangeLog implements IChangeLog { + + private final Map<BigdataStatement,IChangeRecord> uncommitted = + new HashMap<BigdataStatement, IChangeRecord>(); + + private final Map<BigdataStatement,IChangeRecord> committed = + new HashMap<BigdataStatement, IChangeRecord>(); + + public synchronized void changeEvent(final IChangeRecord record) { + + uncommitted.put(record.getStatement(), record); + + } + + public synchronized void transactionCommited() { + + committed.clear(); + + committed.putAll(uncommitted); + + uncommitted.clear(); + + } + + public synchronized void transactionAborted() { + + uncommitted.clear(); + + } + + public Collection<IChangeRecord> getChangeSet() { + + return committed.values(); + + } + + } + +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |