[Mulgara-svn] r621 - in branches/mgr-73: . src/jar/resolver src/jar/resolver/java/org/mulgara/resolver
andrae at mulgara.org
andrae at mulgara.org
Tue Jan 22 02:17:42 UTC 2008
Author: andrae
Date: 2008-01-10 07:02:00 -0800 (Thu, 10 Jan 2008)
New Revision: 621
Added:
branches/mgr-73/src/jar/resolver/java/org/mulgara/resolver/JotmTransactionStandaloneTest.java
Modified:
branches/mgr-73/common.xml
branches/mgr-73/src/jar/resolver/build.xml
branches/mgr-73/src/jar/resolver/java/org/mulgara/resolver/MulgaraXAResourceContext.java
Log:
With this update the tests are integrated with the rest of the unit-test
framework. This was the last thing that needed doing before the JTA branch went
to beta - so I will bring it up todate with trunk and announce it ready for
wider testing.
Modified: branches/mgr-73/common.xml
===================================================================
--- branches/mgr-73/common.xml 2008-01-04 21:51:34 UTC (rev 620)
+++ branches/mgr-73/common.xml 2008-01-10 15:02:00 UTC (rev 621)
@@ -280,12 +280,76 @@
<batchtest todir="${junit.results.tmpdir}">
<fileset dir="${dir}/java" includes="**/*Test.java"
excludes="**/*AbstractTest.java, **/*LoadTest.java,
- **/*StressTest.java"/>
+ **/*StressTest.java, **/*StandaloneTest.java"/>
</batchtest>
</junit>
</target>
<!-- =================================================================== -->
+ <!-- Run JUnit regression tests requiring a standalone instance -->
+ <!-- -->
+ <!-- Required parameters: $classpath.id, $dir, $jar -->
+ <!-- =================================================================== -->
+ <target name="standalone-test"
+ depends="uri, dtd-jar, host.name, dist"
+ description="run regression tests requiring a standalone instance">
+
+ <copy file="${conf.dir}/log4j-template.xml"
+ tofile="${basedir}/log4j-conf.xml"/>
+
+ <mkdir dir="${junit.results.tmpdir}"/>
+
+ <!-- stop and start the server -->
+ <ant target="stop"/>
+ <ant target="start"/>
+
+ <junit fork="yes" haltonfailure="no" printsummary="on"
+ jvm="${java.home}/bin/java" dir="${basedir}">
+
+ <jvmarg value="${arch.bits}"/>
+ <jvmarg value="-ea"/>
+ <jvmarg value="${jvm.args}"/>
+
+ <sysproperty key="java.io.tmpdir" value="${tmp.dir}"/>
+ <sysproperty key="test.dir" value="${test.dir}"/>
+ <sysproperty key="admin" value=""/>
+ <sysproperty key="itql.command.log" value="${tmp.dir}/itql.log"/>
+ <sysproperty key="org.mulgara.xml.ResourceDocumentBuilderFactory"
+ value="org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"/>
+ <sysproperty key="java.naming.factory.initial"
+ value="com.sun.jndi.rmi.registry.RegistryContextFactory"/>
+ <sysproperty key="java.naming.provider.url" value="rmi://localhost"/>
+ <sysproperty key="java.rmi.server.codebase"
+ value="${bin.uri}/${rmi.base.jar}"/>
+ <sysproperty key="java.security.manager" value=""/>
+ <sysproperty key="java.security.policy"
+ value="${basedir}/conf/mulgara-test.policy"/>
+ <sysproperty key="host.name" value="${host.name}"/>
+
+ <!-- The cvs.root property allows tests to find CVS'ed test data -->
+ <sysproperty key="cvs.root" value="${basedir}"/>
+ <sysproperty key="mulgara.jar" value="${mulgara.jar}"/>
+ <sysproperty key="log4j.configuration" value="${baseuri}/log4j-conf.xml"/>
+ <sysproperty key="basedir" value="${basedir}"/>
+ <sysproperty key="org.mulgara.test" value="${org.mulgara.test}"/>
+
+ <classpath>
+ <fileset dir="${dist.dir}" includes="${mulgara.jar}"/>
+ </classpath>
+
+ <formatter type="xml"/>
+
+ <batchtest todir="${junit.results.tmpdir}">
+ <fileset dir="${dir}/java" includes="**/*StandaloneTest.java"/>
+ </batchtest>
+ </junit>
+
+ <!-- stop the server -->
+ <ant target="stop"/>
+
+ </target>
+
+ <!-- =================================================================== -->
<!-- Run JUnit load tests on a JAR component -->
<!-- -->
<!-- Required parameters: $classpath.id, $dir, $jar -->
Modified: branches/mgr-73/src/jar/resolver/build.xml
===================================================================
--- branches/mgr-73/src/jar/resolver/build.xml 2008-01-04 21:51:34 UTC (rev 620)
+++ branches/mgr-73/src/jar/resolver/build.xml 2008-01-10 15:02:00 UTC (rev 621)
@@ -32,6 +32,7 @@
<fileset file="${resolver-jar.dist.dir}/${resolver-jar.jar}"/>
<fileset file="${resolver-url.dist.dir}/${resolver-url.jar}"/>
<fileset file="${content-rdfxml.dist.dir}/${content-rdfxml.jar}"/>
+ <fileset file="${driver.dist.dir}/${driver.jar}"/>
</path>
<path id="resolver-test-classpath">
@@ -81,7 +82,7 @@
depends="-resolver-prepare, resolver-spi-jar, rules-jar,
resolver-http-jar, resolver-file-jar, resolver-url-jar,
resolver-jar-jar, content-rdfxml-jar, content-rdfxml-jar,
- client-jrdf-jar, jrdf-jar, resolver-xsd-jar"
+ client-jrdf-jar, jrdf-jar, resolver-xsd-jar, driver-jar"
description="Compiles all resolver related files included generated
source code">
@@ -128,14 +129,21 @@
resolver-jar, resolver-memory-jar, resolver-xsd-jar,
store-nodepool-xa-jar, store-stringpool-xa-jar, resolver-store-jar,
resolver-url-jar, store-stringpool-memory-jar, tuples-hybrid-jar,
- util-jar, util-xa-jar">
+ util-jar, util-xa-jar, driver-jar">
+<!--
<antcall target="component-test">
<param name="classpath.id" value="resolver-test-classpath"/>
<param name="dir" value="${resolver.src.dir}"/>
<param name="jar" value="${resolver.jar}"/>
</antcall>
+-->
+ <antcall target="standalone-test">
+ <param name="classpath.id" value="resolver-test-classpath"/>
+ <param name="dir" value="${resolver.src.dir}"/>
+ <param name="jar" value="${resolver.jar}"/>
+ </antcall>
</target>
<target name="resolver-javadoc"
Added: branches/mgr-73/src/jar/resolver/java/org/mulgara/resolver/JotmTransactionStandaloneTest.java
===================================================================
--- branches/mgr-73/src/jar/resolver/java/org/mulgara/resolver/JotmTransactionStandaloneTest.java (rev 0)
+++ branches/mgr-73/src/jar/resolver/java/org/mulgara/resolver/JotmTransactionStandaloneTest.java 2008-01-10 15:02:00 UTC (rev 621)
@@ -0,0 +1,2088 @@
+package org.mulgara.resolver;
+
+// Java 2 standard packages
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.RollbackException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+// Third party packages
+import junit.framework.*; // JUnit
+import org.apache.log4j.Logger; // Log4J
+import org.jrdf.graph.ObjectNode;
+import org.jrdf.graph.PredicateNode;
+import org.jrdf.graph.SubjectNode;
+import org.objectweb.jotm.Jotm;
+import org.objectweb.transaction.jta.TMService;
+
+// Locally written packages
+import org.mulgara.query.*;
+import org.mulgara.query.rdf.Mulgara;
+import org.mulgara.query.rdf.URIReferenceImpl;
+import org.mulgara.query.rdf.TripleImpl;
+import org.mulgara.server.Session;
+import org.mulgara.server.SessionFactory;
+import org.mulgara.server.driver.SessionFactoryFinder;
+import org.mulgara.util.FileUtil;
+
+import org.mulgara.query.QueryException;
+import org.mulgara.server.JRDFSession;
+import org.mulgara.server.SessionFactory;
+import org.mulgara.server.driver.SessionFactoryFinder;
+
+public class JotmTransactionStandaloneTest extends TestCase
+{
+ /** Logger. */
+ private static Logger logger =
+ Logger.getLogger(JotmTransactionStandaloneTest.class.getName());
+
+ private static final URI databaseURI;
+
+ private static final URI systemModelURI;
+
+ private static final URI modelURI;
+ private static final URI model2URI;
+ private static final URI model3URI;
+ private static final URI model4URI;
+ private static final URI model5URI;
+
+ static {
+ try {
+ databaseURI = new URI("rmi://localhost/server1");
+ systemModelURI = new URI("rmi://localhost/server1#");
+ modelURI = new URI("rmi://localhost/server1#model");
+ model2URI = new URI("rmi://localhost/server1#model2");
+ model3URI = new URI("rmi://localhost/server1#model3");
+ model4URI = new URI("rmi://localhost/server1#model4");
+ model5URI = new URI("rmi://localhost/server1#model5");
+ } catch (URISyntaxException e) {
+ throw new Error("Bad hardcoded URI", e);
+ }
+ }
+
+ private static SessionFactory sessionFactory;
+ private static TMService txService;
+ private static TransactionManager txManager;
+
+ public JotmTransactionStandaloneTest(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTest(new JotmTransactionStandaloneTest("setup"));
+ suite.addTest(new JotmTransactionStandaloneTest("testTrivalExplicit"));
+ suite.addTest(new JotmTransactionStandaloneTest("testSessionCloseRollback"));
+ suite.addTest(new JotmTransactionStandaloneTest("testTrivialExplicitAgain"));
+ suite.addTest(new JotmTransactionStandaloneTest("testBasicQuery"));
+ suite.addTest(new JotmTransactionStandaloneTest("testMultipleEnlist"));
+ suite.addTest(new JotmTransactionStandaloneTest("testMultipleQuery"));
+ suite.addTest(new JotmTransactionStandaloneTest("testBasicReadOnlyQuery"));
+ suite.addTest(new JotmTransactionStandaloneTest("testConcurrentQuery"));
+ suite.addTest(new JotmTransactionStandaloneTest("testRepeatGetXAQuery"));
+ suite.addTest(new JotmTransactionStandaloneTest("testConcurrentReadWrite"));
+ suite.addTest(new JotmTransactionStandaloneTest("testSubqueryQuery"));
+ suite.addTest(new JotmTransactionStandaloneTest("testTrivalImplicit"));
+ suite.addTest(new JotmTransactionStandaloneTest("cleanup"));
+
+ return suite;
+ }
+
+
+ public void setup() throws Exception {
+ logger.info("Doing setup");
+ sessionFactory = SessionFactoryFinder.newSessionFactory(databaseURI);
+ txService = new Jotm(true, false); // local, unbound.
+ txManager = txService.getTransactionManager();
+ }
+
+ public void cleanup() throws Exception {
+ logger.info("Doing cleanup");
+ txService.stop();
+ }
+
+ //
+ // Test cases
+ //
+
+ private static class TestXid implements Xid {
+ private int xid;
+ public TestXid(int xid) {
+ this.xid = xid;
+ }
+
+ public int getFormatId() {
+ return 'X';
+ }
+
+ public byte[] getBranchQualifier() {
+ return new byte[] {
+ (byte)(xid >> 0x00),
+ (byte)(xid >> 0x08)
+ };
+ }
+
+ public byte[] getGlobalTransactionId() {
+ return new byte[] {
+ (byte)(xid >> 0x10),
+ (byte)(xid >> 0x18)
+ };
+ }
+ }
+
+ /**
+ * Test the {@link DatabaseSession#create} method.
+ * As a side-effect, creates the model required by the next tests.
+ */
+ public void testTrivalExplicit() throws URISyntaxException {
+ logger.info("testTrivalExplicit");
+ try {
+ txManager.begin();
+ Session session = sessionFactory.newSession();
+ txManager.getTransaction().enlistResource(session.getXAResource());
+
+ try {
+ session.createModel(modelURI, null);
+ txManager.commit();
+ } finally {
+ session.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+
+ public void testSessionCloseRollback() throws URISyntaxException {
+ logger.info("testSessionCloseRollback");
+ try {
+ URI fileURI = new File("data/xatest-model1.rdf").toURI();
+ txManager.begin();
+ Session session = sessionFactory.newSession();
+ txManager.getTransaction().enlistResource(session.getXAResource());
+
+ try {
+ try {
+ session.setModel(modelURI, new ModelResource(fileURI));
+ } finally {
+ session.close();
+ }
+ } finally {
+ try {
+ txManager.commit();
+ } catch (HeuristicRollbackException eh) { // This is my expectation.
+ logger.warn("HeuristicRollback detected successfully", eh);
+ } catch (RollbackException er) { // This would also meet the spec.
+ logger.warn("Rollback detected successfully", er);
+ } catch (Exception e) {
+ logger.warn("Exception from Jotm", e);
+ throw e;
+ }
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+ public void testTrivialExplicitAgain() throws URISyntaxException {
+ logger.info("testTrivialExplicitAgain");
+ try {
+ URI fileURI = new File("data/xatest-model1.rdf").toURI();
+ txManager.begin();
+ Session session = sessionFactory.newSession();
+ txManager.getTransaction().enlistResource(session.getXAResource());
+
+ try {
+ session.setModel(modelURI, new ModelResource(fileURI));
+ txManager.commit();
+ } finally {
+ session.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+ public void testBasicQuery() throws URISyntaxException {
+ logger.info("testBasicQuery");
+
+ try {
+ txManager.begin();
+ Session session = sessionFactory.newSession();
+ try {
+ txManager.getTransaction().enlistResource(session.getXAResource());
+
+ Variable subjectVariable = new Variable("subject");
+ Variable predicateVariable = new Variable("predicate");
+ Variable objectVariable = new Variable("object");
+
+ List selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(predicateVariable);
+ selectList.add(objectVariable);
+
+ // Evaluate the query
+ Answer answer = session.query(new Query(
+ selectList, // SELECT
+ new ModelResource(modelURI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Arrays.asList(new Order[] { // ORDER BY
+ new Order(subjectVariable, true),
+ new Order(predicateVariable, true),
+ new Order(objectVariable, true)
+ }),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+ String[][] results = {
+ { "test:s01", "test:p01", "test:o01" },
+ { "test:s01", "test:p02", "test:o01" },
+ { "test:s01", "test:p02", "test:o02" },
+ { "test:s01", "test:p03", "test:o02" },
+ { "test:s02", "test:p03", "test:o02" },
+ { "test:s02", "test:p04", "test:o02" },
+ { "test:s02", "test:p04", "test:o03" },
+ { "test:s02", "test:p05", "test:o03" },
+ { "test:s03", "test:p01", "test:o01" },
+ { "test:s03", "test:p05", "test:o03" },
+ { "test:s03", "test:p06", "test:o01" },
+ { "test:s03", "test:p06", "test:o03" },
+ };
+ compareResults(results, answer);
+ answer.close();
+
+ txManager.commit();
+ } finally {
+ session.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+
+ public void testMultipleEnlist() throws URISyntaxException {
+ logger.info("testMultipleEnlist");
+
+ try {
+ txManager.begin();
+ Session session = sessionFactory.newSession();
+ try {
+ txManager.getTransaction().enlistResource(session.getXAResource());
+ txManager.getTransaction().enlistResource(session.getXAResource());
+ txManager.getTransaction().enlistResource(session.getXAResource());
+
+ Variable subjectVariable = new Variable("subject");
+ Variable predicateVariable = new Variable("predicate");
+ Variable objectVariable = new Variable("object");
+
+ List selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(predicateVariable);
+ selectList.add(objectVariable);
+
+ // Evaluate the query
+ Answer answer = session.query(new Query(
+ selectList, // SELECT
+ new ModelResource(modelURI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Arrays.asList(new Order[] { // ORDER BY
+ new Order(subjectVariable, true),
+ new Order(predicateVariable, true),
+ new Order(objectVariable, true)
+ }),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+ String[][] results = {
+ { "test:s01", "test:p01", "test:o01" },
+ { "test:s01", "test:p02", "test:o01" },
+ { "test:s01", "test:p02", "test:o02" },
+ { "test:s01", "test:p03", "test:o02" },
+ { "test:s02", "test:p03", "test:o02" },
+ { "test:s02", "test:p04", "test:o02" },
+ { "test:s02", "test:p04", "test:o03" },
+ { "test:s02", "test:p05", "test:o03" },
+ { "test:s03", "test:p01", "test:o01" },
+ { "test:s03", "test:p05", "test:o03" },
+ { "test:s03", "test:p06", "test:o01" },
+ { "test:s03", "test:p06", "test:o03" },
+ };
+ compareResults(results, answer);
+ answer.close();
+
+ txManager.commit();
+ } finally {
+ session.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+
+ public void testMultipleQuery() throws URISyntaxException {
+ logger.info("testMultipleQuery");
+
+ try {
+ txManager.begin();
+ Session session = sessionFactory.newSession();
+ txManager.getTransaction().enlistResource(session.getXAResource());
+ try {
+ Variable subjectVariable = new Variable("subject");
+ Variable predicateVariable = new Variable("predicate");
+ Variable objectVariable = new Variable("object");
+
+ List selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(predicateVariable);
+ selectList.add(objectVariable);
+
+ // Evaluate the query
+ Answer answer1 = session.query(new Query(
+ selectList, // SELECT
+ new ModelResource(modelURI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Collections.singletonList( // ORDER BY
+ new Order(subjectVariable, true)
+ ),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+
+ Answer answer2 = session.query(new Query(
+ selectList, // SELECT
+ new ModelResource(modelURI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Collections.singletonList( // ORDER BY
+ new Order(subjectVariable, true)
+ ),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+
+ compareResults(answer1, answer2);
+
+ answer1.close();
+ answer2.close();
+
+ txManager.commit();
+ } finally {
+ session.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+ public void testBasicReadOnlyQuery() throws URISyntaxException {
+ logger.info("testBasicReadOnlyQuery");
+
+ try {
+ txManager.begin();
+ Session session = sessionFactory.newSession();
+ try {
+ txManager.getTransaction().enlistResource(session.getReadOnlyXAResource());
+
+ Variable subjectVariable = new Variable("subject");
+ Variable predicateVariable = new Variable("predicate");
+ Variable objectVariable = new Variable("object");
+
+ List selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(predicateVariable);
+ selectList.add(objectVariable);
+
+ // Evaluate the query
+ Answer answer = session.query(new Query(
+ selectList, // SELECT
+ new ModelResource(modelURI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Arrays.asList(new Order[] { // ORDER BY
+ new Order(subjectVariable, true),
+ new Order(predicateVariable, true),
+ new Order(objectVariable, true)
+ }),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+ String[][] results = {
+ { "test:s01", "test:p01", "test:o01" },
+ { "test:s01", "test:p02", "test:o01" },
+ { "test:s01", "test:p02", "test:o02" },
+ { "test:s01", "test:p03", "test:o02" },
+ { "test:s02", "test:p03", "test:o02" },
+ { "test:s02", "test:p04", "test:o02" },
+ { "test:s02", "test:p04", "test:o03" },
+ { "test:s02", "test:p05", "test:o03" },
+ { "test:s03", "test:p01", "test:o01" },
+ { "test:s03", "test:p05", "test:o03" },
+ { "test:s03", "test:p06", "test:o01" },
+ { "test:s03", "test:p06", "test:o03" },
+ };
+ compareResults(results, answer);
+ answer.close();
+
+ txManager.commit();
+ } finally {
+ session.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+ public void testConcurrentQuery() throws URISyntaxException {
+ logger.info("testConcurrentQuery");
+
+ try {
+ txManager.begin();
+ Session session = sessionFactory.newSession();
+ XAResource roResource = session.getReadOnlyXAResource();
+ Transaction tx1 = txManager.getTransaction();
+ tx1.enlistResource(roResource);
+
+ try {
+ Variable subjectVariable = new Variable("subject");
+ Variable predicateVariable = new Variable("predicate");
+ Variable objectVariable = new Variable("object");
+
+ List selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(predicateVariable);
+ selectList.add(objectVariable);
+
+ // Evaluate the query
+ Answer answer1 = session.query(new Query(
+ selectList, // SELECT
+ new ModelResource(modelURI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Collections.singletonList( // ORDER BY
+ new Order(subjectVariable, true)
+ ),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+
+ tx1 = txManager.suspend();
+
+ txManager.begin();
+ Transaction tx2 = txManager.getTransaction();
+ tx2.enlistResource(roResource);
+
+ Answer answer2 = session.query(new Query(
+ selectList, // SELECT
+ new ModelResource(modelURI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Collections.singletonList( // ORDER BY
+ new Order(subjectVariable, true)
+ ),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+
+ tx2 = txManager.suspend();
+
+ compareResults(answer1, answer2);
+
+ answer1.close();
+ answer2.close();
+
+ txManager.resume(tx1);
+ txManager.commit();
+ // I believe JTA requires me to call end here - our implementation doesn't care.
+ tx2.commit();
+ } finally {
+ session.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+ public void testRepeatGetXAQuery() throws URISyntaxException {
+ logger.info("testRepeatGetXAQuery");
+
+ try {
+ txManager.begin();
+ Session session = sessionFactory.newSession();
+ Transaction tx1 = txManager.getTransaction();
+ tx1.enlistResource(session.getReadOnlyXAResource());
+
+ try {
+ Variable subjectVariable = new Variable("subject");
+ Variable predicateVariable = new Variable("predicate");
+ Variable objectVariable = new Variable("object");
+
+ List selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(predicateVariable);
+ selectList.add(objectVariable);
+
+ // Evaluate the query
+ Answer answer1 = session.query(new Query(
+ selectList, // SELECT
+ new ModelResource(modelURI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Collections.singletonList( // ORDER BY
+ new Order(subjectVariable, true)
+ ),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+
+ tx1 = txManager.suspend();
+
+ txManager.begin();
+ Transaction tx2 = txManager.getTransaction();
+ tx2.enlistResource(session.getReadOnlyXAResource());
+
+ Answer answer2 = session.query(new Query(
+ selectList, // SELECT
+ new ModelResource(modelURI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Collections.singletonList( // ORDER BY
+ new Order(subjectVariable, true)
+ ),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+
+ tx2 = txManager.suspend();
+
+ compareResults(answer1, answer2);
+
+ answer1.close();
+ answer2.close();
+
+ txManager.resume(tx1);
+ txManager.commit();
+ // I believe JTA requires me to call end here - our implementation doesn't care.
+ tx2.commit();
+ } finally {
+ session.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+ //
+ // Note: What this test does is a really bad idea - there is no
+ // isolation provided as each operation is within its own
+ // transaction. It does however provide a good test.
+ //
+ public void testConcurrentReadWrite() throws URISyntaxException {
+ logger.info("testConcurrentReadWrite");
+
+ try {
+ txManager.begin();
+ Session session = sessionFactory.newSession();
+ XAResource roResource = session.getReadOnlyXAResource();
+ XAResource rwResource = session.getXAResource();
+
+ txManager.getTransaction().enlistResource(rwResource);
+ session.createModel(model2URI, null);
+ Transaction tx1 = txManager.suspend();
+
+ try {
+ Variable subjectVariable = new Variable("subject");
+ Variable predicateVariable = new Variable("predicate");
+ Variable objectVariable = new Variable("object");
+
+ List selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(predicateVariable);
+ selectList.add(objectVariable);
+
+ txManager.begin();
+ txManager.getTransaction().enlistResource(roResource);
+
+ // Evaluate the query
+ Answer answer = session.query(new Query(
+ selectList, // SELECT
+ new ModelResource(modelURI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Arrays.asList(new Order[] { // ORDER BY
+ new Order(subjectVariable, true),
+ new Order(predicateVariable, true),
+ new Order(objectVariable, true)
+ }),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+
+ Transaction tx2 = txManager.suspend();
+
+ answer.beforeFirst();
+ while (answer.next()) {
+ txManager.resume(tx1);
+ session.insert(model2URI, Collections.singleton(new TripleImpl(
+ (SubjectNode)answer.getObject(0),
+ (PredicateNode)answer.getObject(1),
+ (ObjectNode)answer.getObject(2))));
+ tx1 = txManager.suspend();
+ }
+ answer.close();
+
+ txManager.resume(tx1);
+ txManager.commit();
+
+ txManager.begin();
+ txManager.getTransaction().enlistResource(roResource);
+
+ Answer answer2 = session.query(new Query(
+ selectList, // SELECT
+ new ModelResource(model2URI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Arrays.asList(new Order[] { // ORDER BY
+ new Order(subjectVariable, true),
+ new Order(predicateVariable, true),
+ new Order(objectVariable, true)
+ }),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+
+ Transaction tx3 = txManager.suspend();
+
+ String[][] results = {
+ { "test:s01", "test:p01", "test:o01" },
+ { "test:s01", "test:p02", "test:o01" },
+ { "test:s01", "test:p02", "test:o02" },
+ { "test:s01", "test:p03", "test:o02" },
+ { "test:s02", "test:p03", "test:o02" },
+ { "test:s02", "test:p04", "test:o02" },
+ { "test:s02", "test:p04", "test:o03" },
+ { "test:s02", "test:p05", "test:o03" },
+ { "test:s03", "test:p01", "test:o01" },
+ { "test:s03", "test:p05", "test:o03" },
+ { "test:s03", "test:p06", "test:o01" },
+ { "test:s03", "test:p06", "test:o03" },
+ };
+ compareResults(results, answer2);
+ answer2.close();
+
+ txManager.begin();
+ txManager.getTransaction().enlistResource(rwResource);
+ session.removeModel(model2URI);
+ txManager.commit();
+
+ txManager.resume(tx2);
+ txManager.commit();
+ txManager.resume(tx3);
+ txManager.commit();
+ } finally {
+ session.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+ public void testSubqueryQuery() throws URISyntaxException {
+ logger.info("testSubqueryQuery");
+
+ try {
+ txManager.begin();
+ Session session = sessionFactory.newSession();
+ txManager.getTransaction().enlistResource(session.getReadOnlyXAResource());
+
+ try {
+ Variable subjectVariable = new Variable("subject");
+ Variable predicateVariable = new Variable("predicate");
+ Variable objectVariable = new Variable("object");
+
+ List selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(new Subquery(new Variable("k0"), new Query(
+ Collections.singletonList(objectVariable),
+ new ModelResource(modelURI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Collections.singletonList( // ORDER BY
+ new Order(objectVariable, true)
+ ),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ )));
+
+
+ // Evaluate the query
+ Answer answer = session.query(new Query(
+ selectList, // SELECT
+ new ModelResource(modelURI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ new URIReferenceImpl(new URI("test:p03")),
+ objectVariable),
+ null, // HAVING
+ Collections.singletonList( // ORDER BY
+ new Order(subjectVariable, true)
+ ),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+
+ Transaction tx1 = txManager.suspend();
+
+ answer.beforeFirst();
+
+ assertTrue(answer.next());
+ assertEquals(new URIReferenceImpl(new URI("test:s01")),
+ answer.getObject(0));
+ Answer sub1 = (Answer)answer.getObject(1);
+ compareResults(new String[][] { new String[] { "test:o01" },
+ new String[] { "test:o02" } }, sub1);
+ sub1.close();
+
+ assertTrue(answer.next());
+ assertEquals(new URIReferenceImpl(new URI("test:s02")),
+ answer.getObject(0));
+ Answer sub2 = (Answer)answer.getObject(1);
+ compareResults(new String[][] { new String[] { "test:o02" },
+ new String[] { "test:o03" } }, sub2);
+ // Leave sub2 open.
+
+ assertFalse(answer.next());
+ answer.close();
+ sub2.close();
+
+ // Leave transaction to be closed on session close.
+ } finally {
+ session.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+/*
+
+ public void testConcurrentSubqueryQuery() throws URISyntaxException {
+ logger.info("testConcurrentSubqueryQuery");
+
+ try {
+ Session session = database.newSession();
+ XAResource rwResource = session.getXAResource();
+ Xid xid1 = new TestXid(1);
+ rwResource.start(xid1, XAResource.TMNOFLAGS);
+
+ try {
+ Variable subjectVariable = new Variable("subject");
+ Variable predicateVariable = new Variable("predicate");
+ Variable objectVariable = new Variable("object");
+
+ List selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(new Subquery(new Variable("k0"), new Query(
+ Collections.singletonList(objectVariable),
+ new ModelResource(modelURI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Collections.singletonList( // ORDER BY
+ new Order(objectVariable, true)
+ ),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ )));
+
+
+ // Evaluate the query
+ Answer answer = session.query(new Query(
+ selectList, // SELECT
+ new ModelResource(modelURI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ new URIReferenceImpl(new URI("test:p03")),
+ objectVariable),
+ null, // HAVING
+ Collections.singletonList( // ORDER BY
+ new Order(subjectVariable, true)
+ ),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+
+ answer.beforeFirst();
+
+ assertTrue(answer.next());
+ assertEquals(new URIReferenceImpl(new URI("test:s01")),
+ answer.getObject(0));
+ Answer sub1 = (Answer)answer.getObject(1);
+ assertTrue(answer.next());
+ assertEquals(new URIReferenceImpl(new URI("test:s02")),
+ answer.getObject(0));
+ Answer sub2 = (Answer)answer.getObject(1);
+ assertFalse(answer.next());
+
+ assertEquals(1, sub1.getNumberOfVariables());
+ assertEquals(1, sub2.getNumberOfVariables());
+ sub1.beforeFirst();
+ sub2.beforeFirst();
+ assertTrue(sub1.next());
+ assertTrue(sub2.next());
+ assertEquals(new URIReferenceImpl(new URI("test:o01")), sub1.getObject(0));
+ assertEquals(new URIReferenceImpl(new URI("test:o02")), sub2.getObject(0));
+
+ rwResource.end(xid1, XAResource.TMSUSPEND);
+
+ assertTrue(sub1.next());
+ assertTrue(sub2.next());
+ assertEquals(new URIReferenceImpl(new URI("test:o02")), sub1.getObject(0));
+ assertEquals(new URIReferenceImpl(new URI("test:o03")), sub2.getObject(0));
+ assertFalse(sub1.next());
+ assertFalse(sub2.next());
+
+ answer.close();
+
+ rwResource.end(xid1, XAResource.TMSUCCESS);
+ rwResource.commit(xid1, true);
+ } finally {
+ session.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+ public void testExplicitIsolationQuerySingleSession() throws URISyntaxException
+ {
+ logger.info("testExplicitIsolationQuery");
+ URI fileURI = new File("data/xatest-model1.rdf").toURI();
+
+ try {
+ Session session = database.newSession();
+ try {
+ XAResource roResource = session.getReadOnlyXAResource();
+ XAResource rwResource = session.getXAResource();
+ Xid xid1 = new TestXid(1); // Initial create model.
+ Xid xid2 = new TestXid(2); // Started before setModel.
+ Xid xid3 = new TestXid(3); // setModel.
+ Xid xid4 = new TestXid(4); // Started before setModel prepares
+ Xid xid5 = new TestXid(5); // Started before setModel commits
+ Xid xid6 = new TestXid(6); // Started after setModel commits
+ Xid xid7 = new TestXid(7); // Final remove model.
+
+ rwResource.start(xid1, XAResource.TMNOFLAGS);
+ session.createModel(model3URI, null);
+ rwResource.end(xid1, XAResource.TMSUCCESS);
+ rwResource.commit(xid1, true);
+
+ // Nothing visible.
+ roResource.start(xid2, XAResource.TMNOFLAGS);
+ assertChangeNotVisible(session);
+ roResource.end(xid2, XAResource.TMSUSPEND);
+
+ // Perform update
+ rwResource.start(xid3, XAResource.TMNOFLAGS);
+ session.setModel(model3URI, new ModelResource(fileURI));
+ rwResource.end(xid3, XAResource.TMSUSPEND);
+
+ // Check uncommitted change not visible
+ roResource.start(xid4, XAResource.TMNOFLAGS);
+ assertChangeNotVisible(session);
+ roResource.end(xid4, XAResource.TMSUSPEND);
+
+ // Check original phase unaffected.
+ roResource.start(xid2, XAResource.TMRESUME);
+ assertChangeNotVisible(session);
+ roResource.end(xid2, XAResource.TMSUSPEND);
+
+ // Check micro-commit visible to current-phase
+ rwResource.start(xid3, XAResource.TMRESUME);
+ assertChangeVisible(session);
+ // Perform prepare
+ rwResource.end(xid3, XAResource.TMSUCCESS);
+ rwResource.prepare(xid3);
+
+ // Check original phase unaffected
+ roResource.start(xid2, XAResource.TMRESUME);
+ assertChangeNotVisible(session);
+ roResource.end(xid2, XAResource.TMSUSPEND);
+
+ // Check pre-prepare phase unaffected
+ roResource.start(xid4, XAResource.TMRESUME);
+ assertChangeNotVisible(session);
+ roResource.end(xid4, XAResource.TMSUSPEND);
+
+ // Check committed phase unaffected.
+ roResource.start(xid5, XAResource.TMNOFLAGS);
+ assertChangeNotVisible(session);
+ roResource.end(xid5, XAResource.TMSUSPEND);
+
+ // Do commit
+ rwResource.commit(xid3, false);
+
+ // Check original phase
+ roResource.start(xid2, XAResource.TMRESUME);
+ assertChangeNotVisible(session);
+ roResource.end(xid2, XAResource.TMSUSPEND);
+
+ // Check pre-prepare
+ roResource.start(xid4, XAResource.TMRESUME);
+ assertChangeNotVisible(session);
+ roResource.end(xid4, XAResource.TMSUSPEND);
+
+ // Check pre-commit
+ roResource.start(xid5, XAResource.TMRESUME);
+ assertChangeNotVisible(session);
+ roResource.end(xid5, XAResource.TMSUSPEND);
+
+ // Check committed phase is now updated
+ roResource.start(xid6, XAResource.TMNOFLAGS);
+ assertChangeVisible(session);
+
+ // Cleanup transactions.
+ roResource.end(xid6, XAResource.TMSUCCESS);
+ roResource.end(xid2, XAResource.TMSUCCESS);
+ roResource.end(xid4, XAResource.TMSUCCESS);
+ roResource.end(xid5, XAResource.TMSUCCESS);
+ roResource.commit(xid2, true);
+ roResource.commit(xid4, true);
+ roResource.commit(xid5, true);
+ roResource.commit(xid6, true);
+
+ // Cleanup database
+ rwResource.start(xid7, XAResource.TMNOFLAGS);
+ session.removeModel(model3URI);
+ rwResource.end(xid7, XAResource.TMSUCCESS);
+ rwResource.commit(xid7, true);
+ } finally {
+ session.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+ public void testExternalInternalIsolation() throws URISyntaxException
+ {
+ logger.info("testExplicitIsolationQuery");
+ URI fileURI = new File("data/xatest-model1.rdf").toURI();
+
+ try {
+ Session session1 = database.newSession();
+ try {
+ Session session2 = database.newSession();
+ try {
+ XAResource roResource = session1.getReadOnlyXAResource();
+ XAResource rwResource = session1.getXAResource();
+ Xid xid1 = new TestXid(1); // Initial create model.
+ Xid xid2 = new TestXid(2); // Main Test.
+ Xid xid3 = new TestXid(3); // Cleanup test.
+
+ rwResource.start(xid1, XAResource.TMNOFLAGS);
+ session1.createModel(model3URI, null);
+ rwResource.end(xid1, XAResource.TMSUCCESS);
+ rwResource.commit(xid1, true);
+
+ // Nothing visible.
+ assertChangeNotVisible(session2);
+
+ // Perform update
+ rwResource.start(xid2, XAResource.TMNOFLAGS);
+ session1.setModel(model3URI, new ModelResource(fileURI));
+ rwResource.end(xid2, XAResource.TMSUSPEND);
+
+ // Check uncommitted change not visible
+ assertChangeNotVisible(session2);
+
+ // Check micro-commit visible to current-phase
+ rwResource.start(xid2, XAResource.TMRESUME);
+ assertChangeVisible(session1);
+ // Perform prepare
+ rwResource.end(xid2, XAResource.TMSUCCESS);
+ rwResource.prepare(xid2);
+
+ // Check original phase unaffected
+ assertChangeNotVisible(session2);
+
+ // Do commit
+ rwResource.commit(xid2, false);
+
+ // Check committed phase is now updated
+ assertChangeVisible(session2);
+
+ // Cleanup database
+ session2.removeModel(model3URI);
+ } finally {
+ session2.close();
+ }
+ } finally {
+ session1.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+ public void testInternalExternalIsolation() throws URISyntaxException
+ {
+ logger.info("testExplicitIsolationQuery");
+ URI fileURI = new File("data/xatest-model1.rdf").toURI();
+
+ try {
+ Session session1 = database.newSession();
+ try {
+ Session session2 = database.newSession();
+ try {
+ XAResource roResource = session2.getReadOnlyXAResource();
+ XAResource rwResource = session2.getXAResource();
+ Xid xid1 = new TestXid(1); // Pre-update
+ Xid xid2 = new TestXid(2); // Post-update/Pre-commit
+ Xid xid3 = new TestXid(3); // Post-commit
+
+ session1.createModel(model3URI, null);
+
+ // Nothing visible.
+ roResource.start(xid1, XAResource.TMNOFLAGS);
+ assertChangeNotVisible(session2);
+ roResource.end(xid1, XAResource.TMSUSPEND);
+
+ // Perform update with autocommit off
+ session1.setAutoCommit(false);
+ session1.setModel(model3URI, new ModelResource(fileURI));
+
+ // Check uncommitted change not visible
+ roResource.start(xid2, XAResource.TMNOFLAGS);
+ assertChangeNotVisible(session2);
+ roResource.end(xid2, XAResource.TMSUSPEND);
+
+ // Check original phase unaffected.
+ roResource.start(xid1, XAResource.TMRESUME);
+ assertChangeNotVisible(session2);
+ roResource.end(xid1, XAResource.TMSUSPEND);
+
+ // Check micro-commit visible to current-phase
+ assertChangeVisible(session1);
+ session1.setAutoCommit(true);
+
+ // Check original phase unaffected
+ roResource.start(xid1, XAResource.TMRESUME);
+ assertChangeNotVisible(session2);
+ roResource.end(xid1, XAResource.TMSUSPEND);
+
+ // Check pre-commit phase unaffected
+ roResource.start(xid2, XAResource.TMRESUME);
+ assertChangeNotVisible(session2);
+ roResource.end(xid2, XAResource.TMSUSPEND);
+
+ // Check committed phase is now updated and write-lock available
+ rwResource.start(xid3, XAResource.TMNOFLAGS);
+ assertChangeVisible(session2);
+
+ // Check internal transaction read-only
+ assertChangeVisible(session1);
+
+ // Cleanup transactions.
+ rwResource.end(xid3, XAResource.TMSUCCESS);
+ roResource.end(xid2, XAResource.TMSUCCESS);
+ roResource.end(xid1, XAResource.TMSUCCESS);
+ roResource.commit(xid1, true);
+ roResource.commit(xid2, true);
+ rwResource.commit(xid3, true);
+
+ // Cleanup database (check write-lock available again)
+ session1.removeModel(model3URI);
+ } finally {
+ session2.close();
+ }
+ } finally {
+ session1.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+ private void assertChangeVisible(Session session) throws Exception {
+ Variable subjectVariable = new Variable("subject");
+ Variable predicateVariable = new Variable("predicate");
+ Variable objectVariable = new Variable("object");
+
+ List selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(predicateVariable);
+ selectList.add(objectVariable);
+
+ // Evaluate the query
+ Answer answer = session.query(new Query(
+ selectList, // SELECT
+ new ModelResource(model3URI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Arrays.asList(new Order[] { // ORDER BY
+ new Order(subjectVariable, true),
+ new Order(predicateVariable, true),
+ new Order(objectVariable, true)
+ }),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+
+ String[][] results = {
+ { "test:s01", "test:p01", "test:o01" },
+ { "test:s01", "test:p02", "test:o01" },
+ { "test:s01", "test:p02", "test:o02" },
+ { "test:s01", "test:p03", "test:o02" },
+ { "test:s02", "test:p03", "test:o02" },
+ { "test:s02", "test:p04", "test:o02" },
+ { "test:s02", "test:p04", "test:o03" },
+ { "test:s02", "test:p05", "test:o03" },
+ { "test:s03", "test:p01", "test:o01" },
+ { "test:s03", "test:p05", "test:o03" },
+ { "test:s03", "test:p06", "test:o01" },
+ { "test:s03", "test:p06", "test:o03" },
+ };
+ compareResults(results, answer);
+ answer.close();
+ }
+
+ private void assertChangeNotVisible(Session session) throws Exception {
+ Variable subjectVariable = new Variable("subject");
+ Variable predicateVariable = new Variable("predicate");
+ Variable objectVariable = new Variable("object");
+
+ List selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(predicateVariable);
+ selectList.add(objectVariable);
+
+ // Evaluate the query
+ Answer answer = session.query(new Query(
+ selectList, // SELECT
+ new ModelResource(model3URI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Arrays.asList(new Order[] { // ORDER BY
+ new Order(subjectVariable, true),
+ new Order(predicateVariable, true),
+ new Order(objectVariable, true)
+ }),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+ answer.beforeFirst();
+ assertFalse(answer.next());
+ answer.close();
+ }
+
+ //
+ // Test two simultaneous, explicit transactions, in two threads. The second one should block
+ // until the first one sets auto-commit back to true.
+ //
+ public void testConcurrentExplicitTxn() throws URISyntaxException
+ {
+ logger.info("testConcurrentExplicitTxn");
+ URI fileURI = new File("data/xatest-model1.rdf").toURI();
+
+ try {
+ Session session1 = database.newSession();
+ try {
+ XAResource resource1 = session1.getXAResource();
+ resource1.start(new TestXid(1), XAResource.TMNOFLAGS);
+ session1.createModel(model3URI, null);
+ resource1.end(new TestXid(1), XAResource.TMSUCCESS);
+ resource1.commit(new TestXid(1), true);
+
+ resource1.start(new TestXid(2), XAResource.TMNOFLAGS);
+ session1.setModel(model3URI, new ModelResource(fileURI));
+
+ final boolean[] tx2Started = new boolean[] { false };
+
+ Thread t2 = new Thread("tx2Test") {
+ public void run() {
+ try {
+ Session session2 = database.newSession();
+ XAResource resource2 = session2.getXAResource();
+ try {
+ resource2.start(new TestXid(3), XAResource.TMNOFLAGS);
+
+ synchronized (tx2Started) {
+ tx2Started[0] = true;
+ tx2Started.notify();
+ }
+
+ Variable subjectVariable = new Variable("subject");
+ Variable predicateVariable = new Variable("predicate");
+ Variable objectVariable = new Variable("object");
+
+ List selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(predicateVariable);
+ selectList.add(objectVariable);
+
+ // Evaluate the query
+ Answer answer = session2.query(new Query(
+ selectList, // SELECT
+ new ModelResource(model3URI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Arrays.asList(new Order[] { // ORDER BY
+ new Order(subjectVariable, true),
+ new Order(predicateVariable, true),
+ new Order(objectVariable, true)
+ }),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+
+ String[][] results = {
+ { "test:s01", "test:p01", "test:o01" },
+ { "test:s01", "test:p02", "test:o01" },
+ { "test:s01", "test:p02", "test:o02" },
+ { "test:s01", "test:p03", "test:o02" },
+ { "test:s02", "test:p03", "test:o02" },
+ { "test:s02", "test:p04", "test:o02" },
+ { "test:s02", "test:p04", "test:o03" },
+ { "test:s02", "test:p05", "test:o03" },
+ { "test:s03", "test:p01", "test:o01" },
+ { "test:s03", "test:p05", "test:o03" },
+ { "test:s03", "test:p06", "test:o01" },
+ { "test:s03", "test:p06", "test:o03" },
+ };
+ compareResults(results, answer);
+ answer.close();
+
+ resource2.end(new TestXid(3), XAResource.TMSUCCESS);
+ resource2.commit(new TestXid(3), true);
+ } finally {
+ session2.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+ };
+ t2.start();
+
+ synchronized (tx2Started) {
+ if (!tx2Started[0]) {
+ try {
+ tx2Started.wait(2000L);
+ } catch (InterruptedException ie) {
+ logger.error("wait for tx2-started interrupted", ie);
+ fail(ie);
+ }
+ }
+ assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+ }
+
+ resource1.commit(new TestXid(2), true);
+
+ synchronized (tx2Started) {
+ if (!tx2Started[0]) {
+ try {
+ tx2Started.wait(2000L);
+ } catch (InterruptedException ie) {
+ logger.error("wait for tx2-started interrupted", ie);
+ fail(ie);
+ }
+ assertTrue("second transaction should've started", tx2Started[0]);
+ }
+ }
+
+ try {
+ t2.join(2000L);
+ } catch (InterruptedException ie) {
+ logger.error("wait for tx2-terminated interrupted", ie);
+ fail(ie);
+ }
+ assertFalse("second transaction should've terminated", t2.isAlive());
+
+ resource1.start(new TestXid(4), XAResource.TMNOFLAGS);
+ session1.removeModel(model3URI);
+ resource1.end(new TestXid(4), XAResource.TMSUCCESS);
+ resource1.commit(new TestXid(4), true);
+
+ } finally {
+ session1.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+ //*
+ // Test two simultaneous transactions, in two threads. The second one should block
+ // until the first one sets auto-commit back to true.
+ ///
+ public void testExternalInternalConcurrentTxn() throws URISyntaxException
+ {
+ logger.info("testExternalInternalConcurrentTxn");
+ URI fileURI = new File("data/xatest-model1.rdf").toURI();
+
+ try {
+ Session session1 = database.newSession();
+ try {
+ XAResource resource1 = session1.getXAResource();
+ resource1.start(new TestXid(1), XAResource.TMNOFLAGS);
+ session1.createModel(model3URI, null);
+ resource1.end(new TestXid(1), XAResource.TMSUCCESS);
+ resource1.commit(new TestXid(1), true);
+
+ resource1.start(new TestXid(2), XAResource.TMNOFLAGS);
+ session1.setModel(model3URI, new ModelResource(fileURI));
+
+ final boolean[] tx2Started = new boolean[] { false };
+
+ Thread t2 = new Thread("tx2Test") {
+ public void run() {
+ try {
+ Session session2 = database.newSession();
+ try {
+ session2.setAutoCommit(false);
+
+ synchronized (tx2Started) {
+ tx2Started[0] = true;
+ tx2Started.notify();
+ }
+
+ Variable subjectVariable = new Variable("subject");
+ Variable predicateVariable = new Variable("predicate");
+ Variable objectVariable = new Variable("object");
+
+ List selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(predicateVariable);
+ selectList.add(objectVariable);
+
+ // Evaluate the query
+ Answer answer = session2.query(new Query(
+ selectList, // SELECT
+ new ModelResource(model3URI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Arrays.asList(new Order[] { // ORDER BY
+ new Order(subjectVariable, true),
+ new Order(predicateVariable, true),
+ new Order(objectVariable, true)
+ }),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+
+ String[][] results = {
+ { "test:s01", "test:p01", "test:o01" },
+ { "test:s01", "test:p02", "test:o01" },
+ { "test:s01", "test:p02", "test:o02" },
+ { "test:s01", "test:p03", "test:o02" },
+ { "test:s02", "test:p03", "test:o02" },
+ { "test:s02", "test:p04", "test:o02" },
+ { "test:s02", "test:p04", "test:o03" },
+ { "test:s02", "test:p05", "test:o03" },
+ { "test:s03", "test:p01", "test:o01" },
+ { "test:s03", "test:p05", "test:o03" },
+ { "test:s03", "test:p06", "test:o01" },
+ { "test:s03", "test:p06", "test:o03" },
+ };
+ compareResults(results, answer);
+ answer.close();
+
+ session2.setAutoCommit(true);
+ } finally {
+ session2.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+ };
+ t2.start();
+
+ synchronized (tx2Started) {
+ if (!tx2Started[0]) {
+ try {
+ tx2Started.wait(2000L);
+ } catch (InterruptedException ie) {
+ logger.error("wait for tx2-started interrupted", ie);
+ fail(ie);
+ }
+ }
+ assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+ }
+
+ resource1.commit(new TestXid(2), true);
+
+ synchronized (tx2Started) {
+ if (!tx2Started[0]) {
+ try {
+ tx2Started.wait(2000L);
+ } catch (InterruptedException ie) {
+ logger.error("wait for tx2-started interrupted", ie);
+ fail(ie);
+ }
+ assertTrue("second transaction should've started", tx2Started[0]);
+ }
+ }
+
+ try {
+ t2.join(2000L);
+ } catch (InterruptedException ie) {
+ logger.error("wait for tx2-terminated interrupted", ie);
+ fail(ie);
+ }
+ assertFalse("second transaction should've terminated", t2.isAlive());
+
+ resource1.start(new TestXid(4), XAResource.TMNOFLAGS);
+ session1.removeModel(model3URI);
+ resource1.end(new TestXid(4), XAResource.TMSUCCESS);
+ resource1.commit(new TestXid(4), true);
+
+ } finally {
+ session1.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+
+ //*
+ // Test two simultaneous transactions, in two threads. The second one should block
+ // until the first one sets auto-commit back to true.
+ ///
+ public void testInternalExternalConcurrentTxn() throws URISyntaxException
+ {
+ logger.info("testInternalExternalConcurrentTxn");
+ URI fileURI = new File("data/xatest-model1.rdf").toURI();
+
+ try {
+ Session session1 = database.newSession();
+ try {
+ session1.createModel(model3URI, null);
+
+ session1.setAutoCommit(false);
+ session1.setModel(model3URI, new ModelResource(fileURI));
+
+ final boolean[] tx2Started = new boolean[] { false };
+
+ Thread t2 = new Thread("tx2Test") {
+ public void run() {
+ try {
+ Session session2 = database.newSession();
+ try {
+ XAResource resource = session2.getXAResource();
+ resource.start(new TestXid(1), XAResource.TMNOFLAGS);
+
+ synchronized (tx2Started) {
+ tx2Started[0] = true;
+ tx2Started.notify();
+ }
+
+ Variable subjectVariable = new Variable("subject");
+ Variable predicateVariable = new Variable("predicate");
+ Variable objectVariable = new Variable("object");
+
+ List selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(predicateVariable);
+ selectList.add(objectVariable);
+
+ // Evaluate the query
+ Answer answer = session2.query(new Query(
+ selectList, // SELECT
+ new ModelResource(model3URI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Arrays.asList(new Order[] { // ORDER BY
+ new Order(subjectVariable, true),
+ new Order(predicateVariable, true),
+ new Order(objectVariable, true)
+ }),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+
+ String[][] results = {
+ { "test:s01", "test:p01", "test:o01" },
+ { "test:s01", "test:p02", "test:o01" },
+ { "test:s01", "test:p02", "test:o02" },
+ { "test:s01", "test:p03", "test:o02" },
+ { "test:s02", "test:p03", "test:o02" },
+ { "test:s02", "test:p04", "test:o02" },
+ { "test:s02", "test:p04", "test:o03" },
+ { "test:s02", "test:p05", "test:o03" },
+ { "test:s03", "test:p01", "test:o01" },
+ { "test:s03", "test:p05", "test:o03" },
+ { "test:s03", "test:p06", "test:o01" },
+ { "test:s03", "test:p06", "test:o03" },
+ };
+ compareResults(results, answer);
+ answer.close();
+
+ resource.end(new TestXid(1), XAResource.TMSUCCESS);
+ resource.rollback(new TestXid(1));
+ } finally {
+ session2.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+ };
+ t2.start();
+
+ synchronized (tx2Started) {
+ if (!tx2Started[0]) {
+ try {
+ tx2Started.wait(2000L);
+ } catch (InterruptedException ie) {
+ logger.error("wait for tx2-started interrupted", ie);
+ fail(ie);
+ }
+ }
+ assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+ }
+
+ session1.commit();
+
+ synchronized (tx2Started) {
+ if (!tx2Started[0]) {
+ try {
+ tx2Started.wait(2000L);
+ } catch (InterruptedException ie) {
+ logger.error("wait for tx2-started interrupted", ie);
+ fail(ie);
+ }
+ }
+ assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+ }
+
+ session1.setAutoCommit(true);
+
+ synchronized (tx2Started) {
+ if (!tx2Started[0]) {
+ try {
+ tx2Started.wait(2000L);
+ } catch (InterruptedException ie) {
+ logger.error("wait for tx2-started interrupted", ie);
+ fail(ie);
+ }
+ assertTrue("second transaction should've started", tx2Started[0]);
+ }
+ }
+
+ try {
+ t2.join(2000L);
+ } catch (InterruptedException ie) {
+ logger.error("wait for tx2-terminated interrupted", ie);
+ fail(ie);
+ }
+ assertFalse("second transaction should've terminated", t2.isAlive());
+
+ session1.removeModel(model3URI);
+ } finally {
+ session1.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+ //*
+ // Test two simultaneous transactions, in two threads. The second one should block
+ // until the first one sets auto-commit back to true.
+ ///
+ public void testExternalInternalConcurrentTxnRollback() throws URISyntaxException
+ {
+ logger.info("testExternalInternalConcurrentTxnRollback");
+ URI fileURI = new File("data/xatest-model1.rdf").toURI();
+
+ try {
+ Session session1 = database.newSession();
+ try {
+ XAResource resource1 = session1.getXAResource();
+ resource1.start(new TestXid(1), XAResource.TMNOFLAGS);
+ session1.createModel(model3URI, null);
+ resource1.end(new TestXid(1), XAResource.TMSUCCESS);
+ resource1.commit(new TestXid(1), true);
+
+ resource1.start(new TestXid(2), XAResource.TMNOFLAGS);
+ session1.setModel(model3URI, new ModelResource(fileURI));
+
+ final boolean[] tx2Started = new boolean[] { false };
+
+ Thread t2 = new Thread("tx2Test") {
+ public void run() {
+ try {
+ Session session2 = database.newSession();
+ try {
+ session2.setAutoCommit(false);
+
+ synchronized (tx2Started) {
+ tx2Started[0] = true;
+ tx2Started.notify();
+ }
+
+ Variable subjectVariable = new Variable("subject");
+ Variable predicateVariable = new Variable("predicate");
+ Variable objectVariable = new Variable("object");
+
+ List selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(predicateVariable);
+ selectList.add(objectVariable);
+
+ // Evaluate the query
+ Answer answer = session2.query(new Query(
+ selectList, // SELECT
+ new ModelResource(model3URI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Arrays.asList(new Order[] { // ORDER BY
+ new Order(subjectVariable, true),
+ new Order(predicateVariable, true),
+ new Order(objectVariable, true)
+ }),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+
+ answer.beforeFirst();
+ assertFalse(answer.next());
+ answer.close();
+
+ session2.setAutoCommit(true);
+ } finally {
+ session2.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+ };
+ t2.start();
+
+ synchronized (tx2Started) {
+ if (!tx2Started[0]) {
+ try {
+ tx2Started.wait(2000L);
+ } catch (InterruptedException ie) {
+ logger.error("wait for tx2-started interrupted", ie);
+ fail(ie);
+ }
+ }
+ assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+ }
+
+ resource1.rollback(new TestXid(2));
+
+ synchronized (tx2Started) {
+ if (!tx2Started[0]) {
+ try {
+ tx2Started.wait(2000L);
+ } catch (InterruptedException ie) {
+ logger.error("wait for tx2-started interrupted", ie);
+ fail(ie);
+ }
+ assertTrue("second transaction should've started", tx2Started[0]);
+ }
+ }
+
+ try {
+ t2.join(2000L);
+ } catch (InterruptedException ie) {
+ logger.error("wait for tx2-terminated interrupted", ie);
+ fail(ie);
+ }
+ assertFalse("second transaction should've terminated", t2.isAlive());
+
+ resource1.start(new TestXid(4), XAResource.TMNOFLAGS);
+ session1.removeModel(model3URI);
+ resource1.end(new TestXid(4), XAResource.TMSUCCESS);
+ resource1.commit(new TestXid(4), true);
+
+ } finally {
+ session1.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+
+ //*
+ // Test two simultaneous transactions, in two threads. The second one should block
+ // until the first one sets auto-commit back to true.
+ ///
+ public void testInternalExternalConcurrentTxnRollback() throws URISyntaxException
+ {
+ logger.info("testInternalExternalConcurrentTxnRollback");
+ URI fileURI = new File("data/xatest-model1.rdf").toURI();
+
+ try {
+ Session session1 = database.newSession();
+ try {
+ session1.createModel(model3URI, null);
+
+ session1.setAutoCommit(false);
+ session1.setModel(model3URI, new ModelResource(fileURI));
+
+ final boolean[] tx2Started = new boolean[] { false };
+
+ Thread t2 = new Thread("tx2Test") {
+ public void run() {
+ try {
+ Session session2 = database.newSession();
+ try {
+ XAResource resource = session2.getXAResource();
+ resource.start(new TestXid(1), XAResource.TMNOFLAGS);
+
+ synchronized (tx2Started) {
+ tx2Started[0] = true;
+ tx2Started.notify();
+ }
+
+ Variable subjectVariable = new Variable("subject");
+ Variable predicateVariable = new Variable("predicate");
+ Variable objectVariable = new Variable("object");
+
+ List selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(predicateVariable);
+ selectList.add(objectVariable);
+
+ // Evaluate the query
+ Answer answer = session2.query(new Query(
+ selectList, // SELECT
+ new ModelResource(model3URI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Arrays.asList(new Order[] { // ORDER BY
+ new Order(subjectVariable, true),
+ new Order(predicateVariable, true),
+ new Order(objectVariable, true)
+ }),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+
+ answer.beforeFirst();
+ assertFalse(answer.next());
+ answer.close();
+
+ resource.end(new TestXid(1), XAResource.TMFAIL);
+ resource.rollback(new TestXid(1));
+ } finally {
+ session2.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+ };
+ t2.start();
+
+ synchronized (tx2Started) {
+ if (!tx2Started[0]) {
+ try {
+ tx2Started.wait(2000L);
+ } catch (InterruptedException ie) {
+ logger.error("wait for tx2-started interrupted", ie);
+ fail(ie);
+ }
+ }
+ assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+ }
+
+ session1.rollback();
+
+ synchronized (tx2Started) {
+ if (!tx2Started[0]) {
+ try {
+ tx2Started.wait(2000L);
+ } catch (InterruptedException ie) {
+ logger.error("wait for tx2-started interrupted", ie);
+ fail(ie);
+ }
+ }
+ assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+ }
+
+ session1.setAutoCommit(true);
+
+ synchronized (tx2Started) {
+ if (!tx2Started[0]) {
+ try {
+ tx2Started.wait(2000L);
+ } catch (InterruptedException ie) {
+ logger.error("wait for tx2-started interrupted", ie);
+ fail(ie);
+ }
+ assertTrue("second transaction should've started", tx2Started[0]);
+ }
+ }
+
+ try {
+ t2.join(2000L);
+ } catch (InterruptedException ie) {
+ logger.error("wait for tx2-terminated interrupted", ie);
+ fail(ie);
+ }
+ assertFalse("second transaction should've terminated", t2.isAlive());
+
+ session1.removeModel(model3URI);
+ } finally {
+ session1.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+
+ public void testExplicitRollbackIsolationQuery() throws URISyntaxException {
+ logger.info("testExplicitRollbackIsolationQuery");
+ URI fileURI = new File("data/xatest-model1.rdf").toURI();
+
+ try {
+ Session session = database.newSession();
+ XAResource roResource = session.getReadOnlyXAResource();
+ XAResource rwResource = session.getXAResource();
+ try {
+ rwResource.start(new TestXid(1), XAResource.TMNOFLAGS);
+ session.createModel(model3URI, null);
+ rwResource.end(new TestXid(1), XAResource.TMSUCCESS);
+ rwResource.commit(new TestXid(1), true);
+
+ rwResource.start(new TestXid(2), XAResource.TMNOFLAGS);
+ session.setModel(model3URI, new ModelResource(fileURI));
+ rwResource.end(new TestXid(2), XAResource.TMSUSPEND);
+
+ roResource.start(new TestXid(3), XAResource.TMNOFLAGS);
+
+ Variable subjectVariable = new Variable("subject");
+ Variable predicateVariable = new Variable("predicate");
+ Variable objectVariable = new Variable("object");
+
+ List selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(predicateVariable);
+ selectList.add(objectVariable);
+
+ // Evaluate the query
+ Answer answer = session.query(new Query(
+ selectList, // SELECT
+ new ModelResource(model3URI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Arrays.asList(new Order[] { // ORDER BY
+ new Order(subjectVariable, true),
+ new Order(predicateVariable, true),
+ new Order(objectVariable, true)
+ }),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+ answer.beforeFirst();
+ assertFalse(answer.next());
+ answer.close();
+
+ roResource.end(new TestXid(3), XAResource.TMSUCCESS);
+ roResource.commit(new TestXid(3), true);
+
+ rwResource.end(new TestXid(2), XAResource.TMFAIL);
+ rwResource.rollback(new TestXid(2));
+
+ roResource.start(new TestXid(4), XAResource.TMNOFLAGS);
+ selectList = new ArrayList(3);
+ selectList.add(subjectVariable);
+ selectList.add(predicateVariable);
+ selectList.add(objectVariable);
+
+ // Evaluate the query
+ answer = session.query(new Query(
+ selectList, // SELECT
+ new ModelResource(model3URI), // FROM
+ new ConstraintImpl(subjectVariable, // WHERE
+ predicateVariable,
+ objectVariable),
+ null, // HAVING
+ Arrays.asList(new Order[] { // ORDER BY
+ new Order(subjectVariable, true),
+ new Order(predicateVariable, true),
+ new Order(objectVariable, true)
+ }),
+ null, // LIMIT
+ 0, // OFFSET
+ new UnconstrainedAnswer() // GIVEN
+ ));
+
+ answer.beforeFirst();
+ assertFalse(answer.next());
+ answer.close();
+
+ roResource.end(new TestXid(4), XAResource.TMFAIL);
+ roResource.rollback(new TestXid(4));
+ } finally {
+ session.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+*/
+
+ public void testTrivalImplicit() throws URISyntaxException
+ {
+ logger.info("testTrivialImplicit");
+ try {
+ Session session = sessionFactory.newSession();
+
+ try {
+ session.removeModel(modelURI);
+ } finally {
+ session.close();
+ }
+ } catch (Exception e) {
+ fail(e);
+ }
+ }
+
+ //
+ // Internal methods
+ //
+
+ private void compareResults(String[][] expected, Answer answer) throws Exception {
+ try {
+ answer.beforeFirst();
+ for (int i = 0; i < expected.length; i++) {
+ assertTrue("Answer short at row " + i, answer.next());
+ assertEquals(expected[i].length, answer.getNumberOfVariables());
+ for (int j = 0; j < expected[i].length; j++) {
+ URIReferenceImpl uri = new URIReferenceImpl(new URI(expected[i][j]));
+ assertEquals(uri, answer.getObject(j));
+ }
+ }
+ assertFalse(answer.next());
+ } catch (Exception e) {
+ logger.info("Failed test - " + answer);
+ answer.close();
+ throw e;
+ }
+ }
+
+ private void compareResults(Answer answer1, Answer answer2) throws Exception {
+ answer1.beforeFirst();
+ answer2.beforeFirst();
+ assertEquals(answer1.getNumberOfVariables(), answer2.getNumberOfVariables());
+ while (answer1.next()) {
+ assertTrue(answer2.next());
+ for (int i = 0; i < answer1.getNumberOfVariables(); i++) {
+ assertEquals(answer1.getObject(i), answer2.getObject(i));
+ }
+ }
+ assertFalse(answer2.next());
+ }
+
+ /**
+ * Fail with an unexpected exception
+ */
+ private void fail(Throwable throwable)
+ {
+ StringWriter stringWriter = new StringWriter();
+ throwable.printStackTrace(new PrintWriter(stringWriter));
+ fail(stringWriter.toString());
+ }
+
+ private static class DummyXAResource implements XAResource {
+ public void end(Xid xid, int flags) throws XAException {}
+ public void forget(Xid xid) throws XAException {}
+ public int getTransactionTimeout() throws XAException { return 0; }
+ public int prepare(Xid xid) throws XAException { return 0; }
+ public Xid[] recover(int flag) throws XAException { return new Xid[] {}; }
+ public void rollback(Xid xid) throws XAException {}
+ public boolean setTransactionTimeout(int seconds) throws XAException { return false; }
+ public void start(Xid xid, int flags) throws XAException {}
+ public void commit(Xid xid, boolean twophase) throws XAException {}
+ public boolean isSameRM(XAResource xa) { return xa == this; }
+ }
+}
Modified: branches/mgr-73/src/jar/resolver/java/org/mulgara/resolver/MulgaraXAResourceContext.java
===================================================================
--- branches/mgr-73/src/jar/resolver/java/org/mulgara/resolver/MulgaraXAResourceContext.java 2008-01-04 21:51:34 UTC (rev 620)
+++ branches/mgr-73/src/jar/resolver/java/org/mulgara/resolver/MulgaraXAResourceContext.java 2008-01-10 15:02:00 UTC (rev 621)
@@ -122,7 +122,10 @@
if (xa == null) {
throw new XAException(XAException.XAER_NOTA);
} else if (xa.isHeuristicallyRollbacked()) {
- throw new XAException(XAException.XA_HEURRB);
+ // HEURRB causes difficulties with JOTM - so throw the less precise
+ // but still correct RBROLLBACK.
+// throw new XAException(XAException.XA_HEURRB);
+ throw new XAException(XAException.XA_RBROLLBACK);
} else if (xa.isHeuristicallyCommitted()) {
throw new XAException(XAException.XA_HEURCOM);
}
More information about the Mulgara-svn
mailing list