package com.bigdata.rdf.sail;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import junit.framework.TestCase;
import org.apache.log4j.Logger;
import org.openrdf.model.Literal;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.ValueFactory;
import org.openrdf.query.Binding;
import org.openrdf.query.BindingSet;
import org.openrdf.query.QueryEvaluationException;
import org.openrdf.query.QueryLanguage;
import org.openrdf.query.TupleQuery;
import org.openrdf.query.TupleQueryResult;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.openrdf.repository.RepositoryResult;
public class StressTest_ClosedByInterrupt_RW extends TestCase {
private static final Logger log = Logger
.getLogger(StressTest_ClosedByInterrupt_RW.class);
public StressTest_ClosedByInterrupt_RW() {
super();
}
public StressTest_ClosedByInterrupt_RW(String name) {
super(name);
}
private static final int NUM_INSERT_DELETE_LOOPS = 10;
private static final int NUM_INSERTS_PER_LOOP = 200000;
private static final int NUM_DELETES_PER_LOOP = 23000;
private static final long MILLIS_BETWEEN_INSERTS = -1;
private static final long MILLIS_BETWEEN_DELETES = -1;
private static final int NUM_STATEMENTS_PER_INSERT = 50;
private static final int NUM_SELECTS = 5000;
private static final int NUM_STATEMENTS_PER_SELECT = 23000;
private static final long MILLIS_BETWEEN_QUERY_BURSTS = 1000;
private static boolean HALT_ON_ERROR = true;
private volatile boolean stopRequested = false;
private void snooze(final long millis) throws InterruptedException {
if (millis > 0) {
Thread.sleep(millis);
}
}
// @Test
public void test() throws RepositoryException, InterruptedException {
final File jnlFile = new File("interrupted.jnl");
if (jnlFile.exists()) {
jnlFile.delete();
}
final Properties props = new Properties();
props.setProperty("com.bigdata.rdf.sail.namespace", "emc.srm.topology.kb");
props.setProperty("com.bigdata.journal.AbstractJournal.bufferMode", "DiskRW");
props.setProperty("com.bigdata.btree.writeRetentionQueue.capacity", "4000");
props.setProperty("com.bigdata.btree.BTree.branchingFactor", "128");
props.setProperty("com.bigdata.service.AbstractTransactionService.minReleaseAge", "1");
props.setProperty("com.bigdata.rdf.store.AbstractTripleStore.textIndex", "false");
props.setProperty(
"com.bigdata.rdf.rules.InferenceEngine.forwardChainOwlTransitiveProperty", "false");
props.setProperty("com.bigdata.rdf.rules.InferenceEngine.forwardChainOwlSameAsClosure",
"false");
props.setProperty("com.bigdata.rdf.rules.InferenceEngine.forwardChainOwlSameAsProperties",
"false");
props.setProperty("com.bigdata.rdf.rules.InferenceEngine.forwardChainOwlInverseOf", "false");
props.setProperty("com.bigdata.rdf.rules.InferenceEngine.forwardChainOwlEquivalentClass",
"false");
props.setProperty(
"com.bigdata.rdf.rules.InferenceEngine.forwardChainOwlEquivalentProperty", "false");
props.setProperty("com.bigdata.rdf.rules.InferenceEngine.forwardChainOwlHasValue", "false");
props.setProperty("com.bigdata.rdf.rules.InferenceEngine.forwardChainRdfTypeRdfsResource",
"false");
props.setProperty("com.bigdata.rdf.store.AbstractTripleStore.axiomsClass",
"com.bigdata.rdf.axioms.NoAxioms");
props.setProperty("com.bigdata.rdf.sail.truthMaintenance", "false");
props.setProperty("com.bigdata.rdf.store.AbstractTripleStore.justify", "false");
props.setProperty("com.bigdata.rdf.store.AbstractTripleStore.statementIdentifiers", "false");
props.setProperty("com.bigdata.rdf.store.AbstractTripleStore.quadsMode", "true");
props.setProperty("com.bigdata.journal.AbstractJournal.maximumExtent", "209715200");
props.setProperty("com.bigdata.service.IBigdataClient.collectPlatformStatistics", "false");
props.setProperty("com.bigdata.service.IBigdataClient.httpdPort", "-1");
props.setProperty("com.bigdata.rdf.sail.bufferCapacity", "100000");
props.setProperty("com.bigdata.rdf.store.AbstractTripleStore.bloomFilter", "false");
props.setProperty(BigdataSail.Options.CREATE_TEMP_FILE, Boolean.FALSE.toString());
props.setProperty(BigdataSail.Options.FILE, jnlFile.toString());
final BigdataSail sail = new BigdataSail(props);
final BigdataSailRepository repo = new BigdataSailRepository(sail);
repo.initialize();
final InsertDeleteRunner mapper = new InsertDeleteRunner(repo);
final ReadOnlyRunner mdp = new ReadOnlyRunner(repo);
final Thread mapperThread = new Thread(mapper);
final Thread mdpThread = new Thread(mdp);
mapperThread.start();
mdpThread.start();
mapperThread.join();
System.out.println("Mapper is done");
stopRequested = true;
mdpThread.join();
System.out.println("MDP is done");
repo.shutDown();
System.out.println("Repository has shut down");
}
private class InsertDeleteRunner implements Runnable {
private final BigdataSailRepository repo;
public InsertDeleteRunner(final BigdataSailRepository repo) {
this.repo = repo;
}
@Override
public void run() {
for (int loop = 0; loop < NUM_INSERT_DELETE_LOOPS; ++loop) {
System.out.println("[Read/Write] enter loop " + loop);
RepositoryConnection conn = null;
try {
System.out.println("[Read/Write] inserting ...");
conn = repo.getConnection();
conn.setAutoCommit(false);
for (int index = 0; index < NUM_INSERTS_PER_LOOP; ++index) {
doInsert(conn, loop, index);
snooze(MILLIS_BETWEEN_INSERTS);
}
conn.commit();
conn.close();
conn = null;
} catch (Throwable t) {
printError("Read/Write threw on insert in loop " + loop, t);
} finally {
closeNoException(conn);
}
try {
System.out.println("[Read/Write] deleting ...");
conn = repo.getConnection();
conn.setAutoCommit(false);
for (int index = 0; index < NUM_DELETES_PER_LOOP; ++index) {
doDelete(conn, loop, index);
snooze(MILLIS_BETWEEN_DELETES);
}
conn.commit();
conn.close();
conn = null;
} catch (Throwable t) {
printError("Read/Write threw on delete in loop " + loop, t);
} finally {
closeNoException(conn);
}
System.out.println("[Read/Write] leave loop " + loop);
}
}
private void doInsert(final RepositoryConnection conn, final int loop, final int index)
throws RepositoryException {
final ValueFactory vf = conn.getValueFactory();
final URI c = vf.createURI("context:loop:" + loop + ":item:" + index);
final URI s = vf.createURI("subject:loop:" + loop + ":item:" + index);
for (int x = 0; x < NUM_STATEMENTS_PER_INSERT; ++x) {
final URI p = vf.createURI("predicate:" + x);
final Literal o = vf.createLiteral("SomeValue");
conn.add(s, p, o, c);
}
}
private void doDelete(final RepositoryConnection conn, final int loop, final int index)
throws RepositoryException {
final ValueFactory vf = conn.getValueFactory();
final URI context = vf.createURI("context:loop:" + loop + ":item:" + index);
final Collection<Statement> statements = getStatementsForContext(conn, context);
for (Statement statement : statements) {
conn.remove(statement, context);
}
}
private Collection<Statement> getStatementsForContext(final RepositoryConnection conn,
final URI context) throws RepositoryException {
RepositoryResult<Statement> res = null;
final Collection<Statement> statements = new ArrayList<Statement>();
try {
res = conn.getStatements(null, null, null, false, context);
while (res.hasNext()) {
statements.add(res.next());
}
} finally {
res.close();
}
return statements;
}
}
private class ReadOnlyRunner implements Runnable {
private final BigdataSailRepository repo;
public ReadOnlyRunner(final BigdataSailRepository repo) {
this.repo = repo;
}
@Override
public void run() {
RepositoryConnection conn = null;
TupleQueryResult result = null;
int loop = 0;
while (stopRequested == false) {
try {
System.out.println("[Read ] snooze");
snooze(MILLIS_BETWEEN_QUERY_BURSTS);
System.out.println("[Read ] enter loop " + loop);
for (int invocation = 0; invocation < NUM_SELECTS; ++invocation) {
conn = repo.getReadOnlyConnection();
conn.setAutoCommit(false);
final String sparql = "SELECT ?s WHERE { ?s ?p ?o } LIMIT "
+ NUM_STATEMENTS_PER_SELECT;
final TupleQuery query = conn.prepareTupleQuery(QueryLanguage.SPARQL, sparql);
result = query.evaluate();
final List<String> duds = new ArrayList<String>();
while (result.hasNext()) {
final BindingSet bindingSet = result.next();
for (final Iterator<Binding> i = bindingSet.iterator(); i.hasNext();) {
final Binding b = i.next();
if (b.getValue() != null) {
duds.add(b.getValue().stringValue());
}
}
}
result.close();
result = null;
conn.close();
conn = null;
}
} catch (Throwable t) {
printError("Read Only threw in loop " + loop, t);
} finally {
closeNoException(result);
closeNoException(conn);
}
System.out.println("[Read ] leave loop " + loop);
++loop;
}
}
}
private void closeNoException(RepositoryConnection conn) {
if (conn != null) {
try {
conn.close();
} catch (RepositoryException e) {
log.error("closeNoException(conn)", e);
}
}
}
private void closeNoException(TupleQueryResult result) {
if (result != null) {
try {
result.close();
} catch (QueryEvaluationException e) {
log.error("closeNoException(result)", e);
}
}
}
private void printError(final String message, final Throwable cause) {
log.error(message, cause);
// Exception e = new Exception(message, cause);
// e.printStackTrace();
if (HALT_ON_ERROR) {
System.exit(123);
}
}
}