/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com 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; import java.util.Properties; import org.openrdf.model.BNode; 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.BNodeImpl; import org.openrdf.model.impl.ContextStatementImpl; import org.openrdf.model.impl.StatementImpl; import org.openrdf.model.impl.URIImpl; import org.openrdf.repository.RepositoryConnection; import org.openrdf.repository.RepositoryResult; import com.bigdata.rdf.axioms.NoAxioms; import com.bigdata.rdf.model.BigdataStatement; import com.bigdata.rdf.store.BD; import com.bigdata.rdf.vocab.NoVocabulary; /** * @author <a href="mailto:mrpersonick@users.sourceforge.net">Mike Personick</a> * @version $Id$ */ public class TestReadWriteTransactions extends ProxyBigdataSailTestCase { /** * */ public TestReadWriteTransactions() { } /** * @param arg0 */ public TestReadWriteTransactions(String arg0) { super(arg0); } @Override public Properties getProperties() { Properties props = super.getProperties(); props.setProperty(BigdataSail.Options.ISOLATABLE_INDICES, "true"); props.setProperty(BigdataSail.Options.TRUTH_MAINTENANCE, "false"); props.setProperty(BigdataSail.Options.AXIOMS_CLASS, NoAxioms.class.getName()); props.setProperty(BigdataSail.Options.VOCABULARY_CLASS, NoVocabulary.class.getName()); props.setProperty(BigdataSail.Options.JUSTIFY, "false"); props.setProperty(BigdataSail.Options.TEXT_INDEX, "false"); return props; } private URI uri(String s) { return new URIImpl(BD.NAMESPACE + s); } private BNode bnode(String id) { return new BNodeImpl(id); } private Statement stmt(Resource s, URI p, Value o) { return new StatementImpl(s, p, o); } private Statement stmt(Resource s, URI p, Value o, Resource c) { return new ContextStatementImpl(s, p, o, c); } /** * Test the commit semantics in the context of a read-committed view of the * database. */ public void test_commit() throws Exception { // final LocalTripleStore store = (LocalTripleStore) getStore(); final BigdataSail sail = getSail(); try { sail.initialize(); final BigdataSailRepository repo = new BigdataSailRepository(sail); final BigdataSailRepositoryConnection isolated = (BigdataSailRepositoryConnection) repo.getReadWriteConnection(); isolated.setAutoCommit(false); // final BigdataSailRepositoryConnection unisolated = // (BigdataSailRepositoryConnection) repo.getUnisolatedConnection(); // unisolated.setAutoCommit(false); // read-committed view of the same database. // final AbstractTripleStore view = store.asReadCommittedView(); RepositoryConnection readView = (BigdataSailRepositoryConnection) repo.getReadOnlyConnection(); try { // final long s = 1, p = 2, o = 3; final URI s = uri("a"), p = uri("b"), o = uri("c"); // add the statement. // store.addStatements(new SPO[] { // // new SPO(s, p, o, StatementEnum.Explicit) // // },// // 1); isolated.add(stmt(s, p, o)); // final boolean stmtInUnisolated = unisolated.hasStatement(s, p, o, true); // // if(log.isInfoEnabled()) log.info("stmtInUnisolated: " + stmtInUnisolated); final boolean stmtInIsolated = isolated.hasStatement(s, p, o, true); if(log.isInfoEnabled()) log.info("stmtInIsolated: " + stmtInIsolated); final boolean stmtInView = readView.hasStatement(s, p, o, true); if(log.isInfoEnabled()) log.info("stmtInView: " + stmtInView); // // not visible in the repo. // assertFalse(stmtInUnisolated); // not visible in the view. assertFalse(stmtInView); // visible in the transaction. assertTrue(stmtInIsolated); // commit the transaction. isolated.commit(); // verify that the write was published. readView = repo.getReadOnlyConnection(); // now visible in the view /* * Note: this will fail if the Journal#getIndex(name,timestamp) does * not return an index view with read-committed (vs read-consistent) * semantics. For the index view to have read-committed semantics * the view MUST update if there is an intervening commit. This is * currently handled by returning a ReadCommittedView for this case * rather than a BTree. */ assertTrue(readView.hasStatement(s, p, o, true)); } finally { readView.close(); isolated.close(); // unisolated.close(); } } finally { sail.__tearDownUnitTest(); } } /** * Test of abort semantics. */ public void test_abort() throws Exception { class AbortException extends RuntimeException { private static final long serialVersionUID = 1L; } // final LocalTripleStore store = (LocalTripleStore) getStore(); final BigdataSail sail = getSail(); try { sail.initialize(); final BigdataSailRepository repo = new BigdataSailRepository(sail); final RepositoryConnection store = repo.getReadWriteConnection(); store.setAutoCommit(false); // Should be a nop. store.rollback(); // final long s = 1, p = 2, o = 3; final URI s = uri("a"), p = uri("b"), o = uri("c"); try { // add the statement. // store.addStatements(new SPO[] { // // new SPO(s, p, o, StatementEnum.Explicit) // // },// // 1); store.add(stmt(s, p, o)); // visible in the repo. assertTrue(store.hasStatement(s, p, o, true)); // discard the write set. store.rollback(); // no longer visible in the repo. assertFalse(store.hasStatement(s, p, o, true)); } finally { store.close(); } } finally { sail.__tearDownUnitTest(); } } public void test_multiple_transaction() throws Exception { // final LocalTripleStore store = (LocalTripleStore) getStore(); final BigdataSail sail = getSail(); try { sail.initialize(); final BigdataSailRepository repo = new BigdataSailRepository(sail); final RepositoryConnection tx1 = repo.getReadWriteConnection(); tx1.setAutoCommit(false); final RepositoryConnection tx2 = repo.getReadWriteConnection(); tx2.setAutoCommit(false); try { // final long s = 1, p = 2, o = 3; final URI s = uri("a"), p = uri("b"), o = uri("c"); final BNode sid1 = bnode("1"), sid2 = bnode("2"); final URI author = uri("author"), mike = uri("mike"), bryan = uri("bryan"); // add the statement. // store.addStatements(new SPO[] { // // new SPO(s, p, o, StatementEnum.Explicit) // // },// // 1); tx1.add(stmt(s, p, o, sid1)); tx1.add(stmt(sid1, author, mike)); tx1.commit(); assertTrue(tx1.hasStatement(s, p, o, true)); assertFalse(tx2.hasStatement(s, p, o, true)); tx2.add(stmt(s, p, o, sid2)); tx2.add(stmt(sid2, author, bryan)); tx2.commit(); assertTrue(tx2.hasStatement(s, p, o, true)); RepositoryConnection view = repo.getReadOnlyConnection(); assertTrue(view.hasStatement(s, p, o, true)); RepositoryResult<Statement> it = view.getStatements(s, p, o, false); BigdataStatement stmt = (BigdataStatement) it.next(); Resource sid = stmt.getContext(); assertTrue(view.hasStatement(sid, author, mike, true)); assertTrue(view.hasStatement(sid, author, bryan, true)); view.close(); } finally { tx1.close(); tx2.close(); } } finally { sail.__tearDownUnitTest(); } } // /** // * @todo Need to test how the system reacts to concurrent reads and writes. // * Simulate real work load. Incremental writes, outnumbered by reads by // * some factor, say somewhere between 10 to 100. Write size will vary, say // * from 1 to 10000 statements. // * <p> // * How should we generate the data? // * N write tasks // * each write tasks update information about one "entity" // * each "entity" has P properties // * each property has A chance of being an attribute and (1-A) chance of being a link to another "entity" // * attribute predicate and link predicate can be constants // * attribute value is a randomly assigned literal // * link value is randomly chosen from pool of already created "entities" // * // * @throws Exception // */ // public void test_stress() throws Exception { // // final BigdataSail sail = getSail(); // sail.initialize(); // final BigdataSailRepository repo = new BigdataSailRepository(sail); // // try { // // // // } finally { // // sail.__tearDownUnitTest(); // // } // // } }