|
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.
|