[jboss-svn-commits] JBL Code SVN: r33141 - in labs/jbosstm/trunk/txbridge: docs and 9 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Fri May 28 10:50:02 EDT 2010
Author: jhalliday
Date: 2010-05-28 10:50:01 -0400 (Fri, 28 May 2010)
New Revision: 33141
Added:
labs/jbosstm/trunk/txbridge/tests/dd/outbound/jboss-beans.xml
labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/inbound/junit/CrashRecoveryTests.java
labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/junit/CrashRecoveryTests.java
labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/utility/TestRecoveryModule.java
Modified:
labs/jbosstm/trunk/txbridge/build.xml
labs/jbosstm/trunk/txbridge/docs/TransactionBridgingGuide.odt
labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridgeRecoveryManager.java
labs/jbosstm/trunk/txbridge/tests/build.xml
labs/jbosstm/trunk/txbridge/tests/dd/inbound/jboss-beans.xml
labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/inbound/utility/TestXAResourceRecoveryHelper.java
labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/service/TestServiceImpl.java
labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/utility/TestDurableParticipant.java
Log:
Added initial prototype crash recovery tests to the txbridge. JBTM-44
Modified: labs/jbosstm/trunk/txbridge/build.xml
===================================================================
--- labs/jbosstm/trunk/txbridge/build.xml 2010-05-28 14:27:47 UTC (rev 33140)
+++ labs/jbosstm/trunk/txbridge/build.xml 2010-05-28 14:50:01 UTC (rev 33141)
@@ -145,6 +145,7 @@
<report>
<fileset dir="${build.dir}" includes="metadata.emma"/>
<fileset dir="${jbossas.home}" includes="coverage.ec"/>
+ <fileset dir="${jbossas.home}/bin" includes="coverage.ec"/>
<sourcepath>
<dirset dir="${src.dir}"/>
</sourcepath>
Modified: labs/jbosstm/trunk/txbridge/docs/TransactionBridgingGuide.odt
===================================================================
(Binary files differ)
Modified: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridgeRecoveryManager.java
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridgeRecoveryManager.java 2010-05-28 14:27:47 UTC (rev 33140)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridgeRecoveryManager.java 2010-05-28 14:50:01 UTC (rev 33141)
@@ -75,10 +75,18 @@
@Override
public void periodicWorkSecondPass()
{
+ // by the time we are called, the JTA tx recovery module has already been called, as it is registered
+ // and hence ordered before us. Therefore by the time we get here any BridgeWrappers belonging to
+ // a parent that was logged, will have been resolved top down. Anything left at this point can therefore
+ // be assumed orphaned and hence we apply presumed abort.
+
log.trace("periodicWorkSecondPass()");
BridgeWrapper[] bridgeWrappers = BridgeWrapper.scan(OutboundBridgeManager.BRIDGEWRAPPER_PREFIX);
- // TODO: do something useful with the results.
+ for(BridgeWrapper bridgeWrapper : bridgeWrappers) {
+ log.info("rolling back orphaned subordinate BridgeWrapper "+bridgeWrapper.getIdentifier());
+ bridgeWrapper.rollback();
+ }
}
}
Modified: labs/jbosstm/trunk/txbridge/tests/build.xml
===================================================================
--- labs/jbosstm/trunk/txbridge/tests/build.xml 2010-05-28 14:27:47 UTC (rev 33140)
+++ labs/jbosstm/trunk/txbridge/tests/build.xml 2010-05-28 14:50:01 UTC (rev 33141)
@@ -43,6 +43,9 @@
<include name="commons-httpclient.jar"/>
<include name="commons-logging.jar"/>
<include name="commons-codec.jar"/>
+ <include name="jboss-server-manager.jar"/>
+ <include name="jboss-logging-spi.jar"/>
+ <include name="jnp-client.jar"/>
<!--<include name="byteman.jar"/>-->
</fileset>
@@ -60,6 +63,7 @@
<pathelement location="/home/jhalli/IdeaProjects/jboss/byteman_trunk/install/lib/byteman.jar"/>
<pathelement location="/home/jhalli/IdeaProjects/jboss/byteman_trunk/contrib/dtest/build/lib/byteman-dtest.jar"/>
+ <pathelement location="/home/jhalli/IdeaProjects/jboss/jbossas_trunk/build/target/jboss-6.0.0-SNAPSHOT/client/jboss-system-client.jar"/>
</path>
@@ -108,6 +112,9 @@
<include name="org/jboss/jbossts/txbridge/tests/outbound/service/*"/>
<include name="org/jboss/jbossts/txbridge/tests/outbound/utility/*"/>
</classes>
+ <webinf dir="dd/outbound">
+ <include name="jboss-beans.xml"/>
+ </webinf>
</war>
<war warfile="${build.dir}/txbridge-outbound-tests-client.war" webxml="${dd}/outbound/web.xml">
@@ -141,6 +148,15 @@
</run.tests.macro>
</target>
+ <target name="run-inbound-crashrec-tests" depends="compile">
+ <run.tests.macro>
+ <tests>
+ <fileset dir="src" includes="**/inbound/**/CrashRecoveryTests.java">
+ </fileset>
+ </tests>
+ </run.tests.macro>
+ </target>
+
<target name="run-outbound-tests" depends="compile">
<run.tests.macro>
<tests>
@@ -150,10 +166,18 @@
</run.tests.macro>
</target>
+ <target name="run-outbound-crashrec-tests" depends="compile">
+ <run.tests.macro>
+ <tests>
+ <fileset dir="src" includes="**/outbound/**/CrashRecoveryTests.java">
+ </fileset>
+ </tests>
+ </run.tests.macro>
+ </target>
<macrodef name="run.tests.macro">
- <attribute name="showoutput" default="false"/>
+ <attribute name="showoutput" default="true"/>
<element name="tests"/>
<element name="additional.classpath" optional="true"/>
<element name="additional.jvmargs" optional="true"/>
@@ -174,8 +198,8 @@
</batchtest>
<jvmarg value="-Djava.rmi.server.codebase=file://build/classes/"/>
- <!--<jvmarg value="-Xdebug"/>-->
- <!--<jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"/>-->
+ <jvmarg value="-Xdebug"/>
+ <jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"/>
<additional.jvmargs/>
</junit>
</sequential>
Modified: labs/jbosstm/trunk/txbridge/tests/dd/inbound/jboss-beans.xml
===================================================================
--- labs/jbosstm/trunk/txbridge/tests/dd/inbound/jboss-beans.xml 2010-05-28 14:27:47 UTC (rev 33140)
+++ labs/jbosstm/trunk/txbridge/tests/dd/inbound/jboss-beans.xml 2010-05-28 14:50:01 UTC (rev 33141)
@@ -23,7 +23,7 @@
<deployment xmlns="urn:jboss:bean-deployer:2.0">
- <bean name="TxBridgeTests" class="org.jboss.jbossts.txbridge.tests.inbound.utility.TestXAResourceRecoveryHelper">
+ <bean name="TxBridgeInboundTests" class="org.jboss.jbossts.txbridge.tests.inbound.utility.TestXAResourceRecoveryHelper">
<constructor factoryClass="org.jboss.jbossts.txbridge.tests.inbound.utility.TestXAResourceRecoveryHelper" factoryMethod="getInstance"/>
Added: labs/jbosstm/trunk/txbridge/tests/dd/outbound/jboss-beans.xml
===================================================================
--- labs/jbosstm/trunk/txbridge/tests/dd/outbound/jboss-beans.xml (rev 0)
+++ labs/jbosstm/trunk/txbridge/tests/dd/outbound/jboss-beans.xml 2010-05-28 14:50:01 UTC (rev 33141)
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and/or its affiliates,
+ * and individual contributors as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * (C) 2010
+ * @author JBoss, by Red Hat.
+-->
+
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+
+ <bean name="TxBridgeOutboundTests" class="org.jboss.jbossts.txbridge.tests.outbound.utility.TestRecoveryModule">
+
+ <depends>jboss.xts:service=XTSService</depends>
+
+ <depends>jboss:service=TransactionManager</depends>
+
+ </bean>
+
+</deployment>
\ No newline at end of file
Added: labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/inbound/junit/CrashRecoveryTests.java
===================================================================
--- labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/inbound/junit/CrashRecoveryTests.java (rev 0)
+++ labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/inbound/junit/CrashRecoveryTests.java 2010-05-28 14:50:01 UTC (rev 33141)
@@ -0,0 +1,365 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and/or its affiliates,
+ * and individual contributors as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * (C) 2010,
+ * @author JBoss, by Red Hat.
+ */
+package org.jboss.jbossts.txbridge.tests.inbound.junit;
+
+import com.arjuna.ats.arjuna.common.recoveryPropertyManager;
+import org.apache.commons.httpclient.HttpMethodBase;
+import org.jboss.jbossas.servermanager.Argument;
+import org.jboss.jbossas.servermanager.Property;
+import org.jboss.jbossas.servermanager.Server;
+import org.jboss.jbossas.servermanager.ServerManager;
+import org.jboss.jbossts.txbridge.inbound.BridgeDurableParticipant;
+import org.jboss.jbossts.txbridge.tests.inbound.client.TestClient;
+import org.jboss.jbossts.txbridge.tests.inbound.service.TestServiceImpl;
+import org.jboss.jbossts.txbridge.tests.inbound.utility.TestSynchronization;
+import org.jboss.jbossts.txbridge.tests.inbound.utility.TestXAResource;
+
+import org.jboss.jbossts.txbridge.tests.inbound.utility.TestXAResourceRecovered;
+import org.junit.*;
+import static org.junit.Assert.*;
+
+import org.jboss.byteman.agent.submit.Submit;
+import org.jboss.byteman.contrib.dtest.*;
+
+import com.arjuna.qa.junit.HttpUtils;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.net.Socket;
+import java.net.URL;
+import java.net.ConnectException;
+
+/**
+ * Crash Recovery test cases for the inbound side of the transaction bridge.
+ *
+ * @author Jonathan Halliday (jonathan.halliday at redhat.com) 2010-05
+ */
+public class CrashRecoveryTests
+{
+ private static final String baseURL = "http://localhost:8080/txbridge-inbound-tests-client/testclient";
+
+ private static Instrumentor instrumentor;
+ private InstrumentedClass instrumentedTestSynchronization;
+ private InstrumentedClass instrumentedTestXAResource;
+
+
+ private static final ServerManager manager = new ServerManager(); // ASTestConfig.java/ServerTask.java
+ private static final Argument bytemanArgument = new Argument();
+
+ /*
+-Xdebug
+-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5006
+-Xmx1024m
+-javaagent:/home/jhalli/IdeaProjects/jboss/byteman_trunk/install/lib/byteman.jar=port:9091,listener:true
+-Dorg.jboss.byteman.debug=true
+-Dorg.jboss.byteman.verbose=true
+-Dorg.jboss.byteman.dump.generated.classes=true
+-Dorg.jboss.byteman.dump.generated.classes.dir=dump
+-Demma.exit.delay=10
+ */
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ instrumentor = new Instrumentor(new Submit(), 1199);
+
+ manager.setJbossHome("/home/jhalli/IdeaProjects/jboss/jbossas_trunk/build/target/jboss-6.0.0-SNAPSHOT/");
+ manager.setJavaHome("/usr/local/jdk1.6.0_20/");
+
+// byteman.jar=script:$SCRIPT_HOME/HeuristicSaveAndRecover.txt
+
+
+ Server server = new Server();
+ server.setName("default");
+
+ server.addJvmArg(bytemanArgument);
+ Argument arg2 = new Argument();
+ arg2.setValue("-Xmx1024m");
+ server.addJvmArg(arg2);
+
+ Argument arg3 = new Argument();
+ arg3.setValue("-Xdebug");
+ server.addJvmArg(arg3);
+ Argument arg4 = new Argument();
+ arg4.setValue("-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5006");
+ server.addJvmArg(arg4);
+
+ Property property1 = new Property();
+ property1.setKey("org.jboss.byteman.debug");
+ property1.setValue("true");
+ server.addSysProperty(property1);
+ Property property2 = new Property();
+ property2.setKey(BytemanTestHelper.RMIREGISTRY_PORT_PROPERTY_NAME);
+ property2.setValue("1199");
+ server.addSysProperty(property2);
+
+ Property property3 = new Property();
+ property3.setKey("emma.exit.delay");
+ property3.setValue("10");
+ server.addSysProperty(property3);
+
+ manager.addServer(server);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+
+ bytemanArgument.setValue("-javaagent:/home/jhalli/IdeaProjects/jboss/byteman_trunk/install/lib/byteman.jar=port:9091,listener:true,sys:/home/jhalli/IdeaProjects/jboss/byteman_trunk/contrib/dtest/build/lib/byteman-dtest.jar");
+ removeContents(new File("/home/jhalli/IdeaProjects/jboss/jbossas_trunk/build/target/jboss-6.0.0-SNAPSHOT/server/default/data/tx-object-store/"));
+
+
+ // TODO: fix JMXAdapter leak.
+ manager.getServer("default").setServerConnection(null);
+ manager.startServer("default");
+
+ //instrumentor.installHelperJar("/home/jhalli/IdeaProjects/jboss/byteman_trunk/contrib/dtest/build/lib/byteman-dtest.jar");
+ instrumentor.setRedirectedSubmissionsFile(null);
+
+ instrumentedTestSynchronization = instrumentor.instrumentClass(TestSynchronization.class);
+ instrumentedTestXAResource = instrumentor.instrumentClass(TestXAResource.class);
+
+ instrumentor.injectOnCall(TestServiceImpl.class, "doNothing", "$0.enlistSynchronization(1), $0.enlistXAResource(1)");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ instrumentor.removeAllInstrumentation();
+
+ manager.stopServer("default");
+ }
+
+ private void execute(boolean expectResponse) throws Exception {
+
+ HttpMethodBase request = null;
+
+ try {
+ request = HttpUtils.accessURL(new URL(baseURL));
+ } catch(ConnectException e) {
+ if(expectResponse) {
+ throw e;
+ }
+ }
+
+ if(expectResponse) {
+ String response = request.getResponseBodyAsString().trim();
+ assertEquals("finished", response);
+ }
+ }
+
+ private void rebootServer() throws Exception {
+
+ instrumentor.removeLocalState();
+ File rulesFile = new File("/tmp/bar3");
+ rulesFile.delete();
+ instrumentor.setRedirectedSubmissionsFile(rulesFile);
+ bytemanArgument.setValue(bytemanArgument.getValue()+",script:"+rulesFile.getCanonicalPath());
+
+ instrumentedTestSynchronization = instrumentor.instrumentClass(TestSynchronization.class);
+ instrumentedTestXAResource = instrumentor.instrumentClass(TestXAResourceRecovered.class);
+
+ manager.getServer("default").setServerConnection(null);
+ Thread.sleep(2000);
+ manager.startServer("default");
+ }
+
+ @Test
+ public void testCrashOneLog() throws Exception {
+
+ instrumentor.injectOnCall(TestClient.class, "terminateTransaction", "$2 = true"); // shouldCommit=true
+ instrumentor.crashAtMethodExit(TestXAResource.class, "prepare");
+
+ execute(false);
+
+ instrumentedTestSynchronization.assertKnownInstances(1);
+ instrumentedTestSynchronization.assertMethodCalled("beforeCompletion");
+ instrumentedTestSynchronization.assertMethodNotCalled("afterCompletion");
+
+ instrumentedTestXAResource.assertKnownInstances(1);
+ instrumentedTestXAResource.assertMethodCalled("prepare");
+ instrumentedTestXAResource.assertMethodNotCalled("rollback");
+ instrumentedTestXAResource.assertMethodNotCalled("commit");
+
+ rebootServer();
+
+ doRecovery();
+ doRecovery();
+
+ instrumentedTestXAResource.assertKnownInstances(1);
+ instrumentedTestXAResource.assertMethodCalled("recover");
+ instrumentedTestXAResource.assertMethodCalled("rollback");
+ instrumentedTestXAResource.assertMethodNotCalled("commit");
+ }
+
+ @Test
+ public void testCrashTwoLogs() throws Exception {
+
+ InstrumentedClass durableParticipant = instrumentor.instrumentClass(BridgeDurableParticipant.class);
+
+ instrumentor.injectOnCall(TestClient.class, "terminateTransaction", "$2 = true"); // shouldCommit=true
+ instrumentor.crashAtMethodExit(BridgeDurableParticipant.class, "prepare");
+
+ execute(false);
+
+ durableParticipant.assertMethodCalled("prepare");
+ durableParticipant.assertMethodNotCalled("rollback");
+ durableParticipant.assertMethodNotCalled("commit");
+
+ instrumentedTestSynchronization.assertKnownInstances(1);
+ instrumentedTestSynchronization.assertMethodCalled("beforeCompletion");
+ instrumentedTestSynchronization.assertMethodNotCalled("afterCompletion");
+
+ instrumentedTestXAResource.assertKnownInstances(1);
+ instrumentedTestXAResource.assertMethodCalled("prepare");
+ instrumentedTestXAResource.assertMethodNotCalled("rollback");
+ instrumentedTestXAResource.assertMethodNotCalled("commit");
+
+ rebootServer();
+
+ doRecovery();
+ doRecovery();
+
+ instrumentedTestXAResource.assertKnownInstances(1);
+ instrumentedTestXAResource.assertMethodCalled("recover");
+ instrumentedTestXAResource.assertMethodCalled("rollback");
+ instrumentedTestXAResource.assertMethodNotCalled("commit");
+ }
+
+ @Test
+ public void testCrashThreeLogs() throws Exception {
+
+ InstrumentedClass durableParticipant = instrumentor.instrumentClass(BridgeDurableParticipant.class);
+
+ instrumentor.injectOnCall(TestClient.class, "terminateTransaction", "$2 = true"); // shouldCommit=true
+ instrumentor.crashAtMethodExit("^XTSATRecoveryManager", "writeParticipantRecoveryRecord");
+
+ execute(false);
+
+ durableParticipant.assertMethodCalled("prepare");
+ durableParticipant.assertMethodNotCalled("rollback");
+ durableParticipant.assertMethodNotCalled("commit");
+
+ instrumentedTestSynchronization.assertKnownInstances(1);
+ instrumentedTestSynchronization.assertMethodCalled("beforeCompletion");
+ instrumentedTestSynchronization.assertMethodNotCalled("afterCompletion");
+
+ instrumentedTestXAResource.assertKnownInstances(1);
+ instrumentedTestXAResource.assertMethodCalled("prepare");
+ instrumentedTestXAResource.assertMethodNotCalled("rollback");
+ instrumentedTestXAResource.assertMethodNotCalled("commit");
+
+ rebootServer();
+
+ doRecovery();
+ doRecovery();
+
+ instrumentedTestXAResource.assertKnownInstances(1);
+ instrumentedTestXAResource.assertMethodCalled("recover");
+ instrumentedTestXAResource.assertMethodCalled("rollback");
+ instrumentedTestXAResource.assertMethodNotCalled("commit");
+ }
+
+ // TODO: add test for 4log case i.e. commit
+
+ /////////////////
+
+ // stolen from CrashRecoveryDelays - should probably just add that to the classpath?
+ // prod the recovery manager via its socket. This avoid any sleep delay.
+ private static void doRecovery() throws InterruptedException
+ {
+ int port = recoveryPropertyManager.getRecoveryEnvironmentBean().getRecoveryPort();
+ String host = recoveryPropertyManager.getRecoveryEnvironmentBean().getRecoveryAddress();
+
+ BufferedReader in = null;
+ PrintStream out = null;
+ Socket sckt = null;
+
+ try
+ {
+ sckt = new Socket(host,port);
+
+ in = new BufferedReader(new InputStreamReader(sckt.getInputStream()));
+ out = new PrintStream(sckt.getOutputStream());
+
+ // Output ping message
+ out.println("SCAN");
+ out.flush();
+
+ // Receive pong message
+ String inMessage = in.readLine();
+
+ if(!inMessage.equals("DONE")) {
+ System.err.println("Recovery failed with message: "+inMessage);
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ finally
+ {
+ try {
+ if ( in != null )
+ {
+ in.close();
+ }
+
+ if ( out != null )
+ {
+ out.close();
+ }
+
+ sckt.close();
+ } catch(Exception e) {}
+ }
+ }
+
+ // stolen from EmptyObjectStore.java
+ public static void removeContents(File directory)
+ {
+ if ((directory != null) &&
+ directory.isDirectory() &&
+ (!directory.getName().equals("")) &&
+ (!directory.getName().equals("/")) &&
+ (!directory.getName().equals("\\")) &&
+ (!directory.getName().equals(".")) &&
+ (!directory.getName().equals("..")))
+ {
+ File[] contents = directory.listFiles();
+
+ for (int index = 0; index < contents.length; index++)
+ {
+ if (contents[index].isDirectory())
+ {
+ removeContents(contents[index]);
+
+ //System.err.println("Deleted: " + contents[index]);
+ contents[index].delete();
+ }
+ else
+ {
+ System.err.println("Deleted: " + contents[index]);
+ contents[index].delete();
+ }
+ }
+ }
+ }
+}
Modified: labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/inbound/utility/TestXAResourceRecoveryHelper.java
===================================================================
--- labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/inbound/utility/TestXAResourceRecoveryHelper.java 2010-05-28 14:27:47 UTC (rev 33140)
+++ labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/inbound/utility/TestXAResourceRecoveryHelper.java 2010-05-28 14:50:01 UTC (rev 33141)
@@ -46,6 +46,7 @@
private static Logger log = Logger.getLogger(TestXAResourceRecoveryHelper.class);
private static final TestXAResourceRecoveryHelper instance = new TestXAResourceRecoveryHelper();
+ private static final TestXAResourceRecovered xaResourceInstance = new TestXAResourceRecovered();
private final Set<Xid> preparedXids = new HashSet<Xid>();
@@ -102,7 +103,7 @@
log.trace("getXAResources()");
XAResource values[] = new XAResource[1];
- values[0] = new TestXAResourceRecovered();
+ values[0] = xaResourceInstance;
return values;
}
Added: labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/junit/CrashRecoveryTests.java
===================================================================
--- labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/junit/CrashRecoveryTests.java (rev 0)
+++ labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/junit/CrashRecoveryTests.java 2010-05-28 14:50:01 UTC (rev 33141)
@@ -0,0 +1,361 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and/or its affiliates,
+ * and individual contributors as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * (C) 2010,
+ * @author JBoss, by Red Hat.
+ */
+package org.jboss.jbossts.txbridge.tests.outbound.junit;
+
+import com.arjuna.ats.arjuna.common.recoveryPropertyManager;
+import org.apache.commons.httpclient.HttpMethodBase;
+import org.jboss.jbossas.servermanager.Argument;
+import org.jboss.jbossas.servermanager.Property;
+import org.jboss.jbossas.servermanager.Server;
+import org.jboss.jbossas.servermanager.ServerManager;
+import org.jboss.jbossts.txbridge.outbound.BridgeXAResource;
+import org.jboss.jbossts.txbridge.tests.outbound.client.TestClient;
+import org.jboss.jbossts.txbridge.tests.outbound.service.TestServiceImpl;
+import org.jboss.jbossts.txbridge.tests.outbound.utility.TestDurableParticipant;
+import org.jboss.jbossts.txbridge.tests.outbound.utility.TestVolatileParticipant;
+import org.junit.*;
+import static org.junit.Assert.*;
+
+import org.jboss.byteman.agent.submit.Submit;
+import org.jboss.byteman.contrib.dtest.*;
+
+import com.arjuna.qa.junit.HttpUtils;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.URL;
+import java.net.ConnectException;
+
+/**
+ * Crash Recovery test cases for the outbound side of the transaction bridge.
+ *
+ * @author Jonathan Halliday (jonathan.halliday at redhat.com) 2010-05
+ */
+
+public class CrashRecoveryTests
+{
+ private static final String baseURL = "http://localhost:8080/txbridge-outbound-tests-client/testclient";
+
+ private static Instrumentor instrumentor;
+ private InstrumentedClass instrumentedTestVolatileParticipant;
+ private InstrumentedClass instrumentedTestDurableParticipant;
+
+ private static final ServerManager manager = new ServerManager(); // ASTestConfig.java/ServerTask.java
+ private static final Argument bytemanArgument = new Argument();
+
+ /*
+-Xdebug
+-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5006
+-Xmx1024m
+-javaagent:/home/jhalli/IdeaProjects/jboss/byteman_trunk/install/lib/byteman.jar=port:9091,listener:true
+-Dorg.jboss.byteman.debug=true
+-Dorg.jboss.byteman.verbose=true
+-Dorg.jboss.byteman.dump.generated.classes=true
+-Dorg.jboss.byteman.dump.generated.classes.dir=dump
+-Demma.exit.delay=10
+ */
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ instrumentor = new Instrumentor(new Submit(), 1199);
+
+ manager.setJbossHome("/home/jhalli/IdeaProjects/jboss/jbossas_trunk/build/target/jboss-6.0.0-SNAPSHOT/");
+ manager.setJavaHome("/usr/local/jdk1.6.0_20/");
+
+// byteman.jar=script:$SCRIPT_HOME/HeuristicSaveAndRecover.txt
+
+
+ Server server = new Server();
+ server.setName("default");
+
+ server.addJvmArg(bytemanArgument);
+ Argument arg2 = new Argument();
+ arg2.setValue("-Xmx1024m");
+ server.addJvmArg(arg2);
+
+ Argument arg3 = new Argument();
+ arg3.setValue("-Xdebug");
+ server.addJvmArg(arg3);
+ Argument arg4 = new Argument();
+ arg4.setValue("-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5006");
+ server.addJvmArg(arg4);
+
+ Property property1 = new Property();
+ property1.setKey("org.jboss.byteman.debug");
+ property1.setValue("true");
+ server.addSysProperty(property1);
+ Property property2 = new Property();
+ property2.setKey(BytemanTestHelper.RMIREGISTRY_PORT_PROPERTY_NAME);
+ property2.setValue("1199");
+ server.addSysProperty(property2);
+
+ Property property3 = new Property();
+ property3.setKey("emma.exit.delay");
+ property3.setValue("10");
+ server.addSysProperty(property3);
+
+ manager.addServer(server);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+
+ bytemanArgument.setValue("-javaagent:/home/jhalli/IdeaProjects/jboss/byteman_trunk/install/lib/byteman.jar=port:9091,listener:true,sys:/home/jhalli/IdeaProjects/jboss/byteman_trunk/contrib/dtest/build/lib/byteman-dtest.jar");
+ removeContents(new File("/home/jhalli/IdeaProjects/jboss/jbossas_trunk/build/target/jboss-6.0.0-SNAPSHOT/server/default/data/tx-object-store/"));
+
+
+ // TODO: fix JMXAdapter leak.
+ manager.getServer("default").setServerConnection(null);
+ manager.startServer("default");
+
+ //instrumentor.installHelperJar("/home/jhalli/IdeaProjects/jboss/byteman_trunk/contrib/dtest/build/lib/byteman-dtest.jar");
+ instrumentor.setRedirectedSubmissionsFile(null);
+
+ instrumentedTestVolatileParticipant = instrumentor.instrumentClass(TestVolatileParticipant.class);
+ instrumentedTestDurableParticipant = instrumentor.instrumentClass(TestDurableParticipant.class);
+
+ instrumentor.injectOnCall(TestServiceImpl.class, "doNothing", "$0.enlistVolatileParticipant(1), $0.enlistDurableParticipant(1)");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ instrumentor.removeAllInstrumentation();
+
+ manager.stopServer("default");
+ }
+
+ private void execute(boolean expectResponse) throws Exception {
+
+ HttpMethodBase request = null;
+
+ try {
+ request = HttpUtils.accessURL(new URL(baseURL));
+ } catch(ConnectException e) {
+ if(expectResponse) {
+ throw e;
+ }
+ } catch(SocketException e) {
+ if(expectResponse) {
+ throw e;
+ }
+ }
+
+ if(expectResponse) {
+ String response = request.getResponseBodyAsString().trim();
+ assertEquals("finished", response);
+ }
+ }
+
+ private void rebootServer() throws Exception {
+
+ instrumentor.removeLocalState();
+ File rulesFile = new File("/tmp/bar3");
+ rulesFile.delete();
+ instrumentor.setRedirectedSubmissionsFile(rulesFile);
+ bytemanArgument.setValue(bytemanArgument.getValue()+",script:"+rulesFile.getCanonicalPath());
+
+ instrumentedTestVolatileParticipant = instrumentor.instrumentClass(TestVolatileParticipant.class);
+ instrumentedTestDurableParticipant = instrumentor.instrumentClass(TestDurableParticipant.class);
+
+ manager.getServer("default").setServerConnection(null);
+ Thread.sleep(2000);
+ manager.startServer("default");
+ }
+
+ //@Test
+ public void testCrashOneLog() throws Exception {
+
+ instrumentor.injectOnCall(TestClient.class, "terminateTransaction", "$1 = true"); // shouldCommit=true
+
+ instrumentor.crashAtMethodExit("^XTSATRecoveryManager", "writeParticipantRecoveryRecord");
+
+ execute(false);
+
+ instrumentedTestVolatileParticipant.assertKnownInstances(1);
+ instrumentedTestVolatileParticipant.assertMethodCalled("prepare");
+ instrumentedTestVolatileParticipant.assertMethodNotCalled("commit");
+ instrumentedTestVolatileParticipant.assertMethodNotCalled("rollback");
+
+ instrumentedTestDurableParticipant.assertKnownInstances(1);
+ instrumentedTestDurableParticipant.assertMethodCalled("prepare");
+ instrumentedTestDurableParticipant.assertMethodNotCalled("commit");
+ instrumentedTestDurableParticipant.assertMethodNotCalled("rollback");
+
+ rebootServer();
+
+ doRecovery();
+ doRecovery();
+
+ instrumentedTestDurableParticipant.assertKnownInstances(1);
+ instrumentedTestDurableParticipant.assertMethodNotCalled("prepare");
+ instrumentedTestDurableParticipant.assertMethodCalled("rollback");
+ instrumentedTestDurableParticipant.assertMethodNotCalled("commit");
+ }
+
+ @Test
+ public void testCrashTwoLogs() throws Exception {
+
+ instrumentor.injectOnCall(TestClient.class, "terminateTransaction", "$1 = true"); // shouldCommit=true
+
+ instrumentor.crashAtMethodExit(BridgeXAResource.class, "prepare");
+
+ execute(false);
+
+ instrumentedTestVolatileParticipant.assertKnownInstances(1);
+ instrumentedTestVolatileParticipant.assertMethodCalled("prepare");
+ instrumentedTestVolatileParticipant.assertMethodNotCalled("commit");
+ instrumentedTestVolatileParticipant.assertMethodNotCalled("rollback");
+
+ instrumentedTestDurableParticipant.assertKnownInstances(1);
+ instrumentedTestDurableParticipant.assertMethodCalled("prepare");
+ instrumentedTestDurableParticipant.assertMethodNotCalled("commit");
+ instrumentedTestDurableParticipant.assertMethodNotCalled("rollback");
+
+ rebootServer();
+
+ doRecovery();
+ doRecovery();
+
+ instrumentedTestDurableParticipant.assertKnownInstances(1);
+ instrumentedTestDurableParticipant.assertMethodNotCalled("prepare");
+ instrumentedTestDurableParticipant.assertMethodCalled("rollback");
+ instrumentedTestDurableParticipant.assertMethodNotCalled("commit");
+ }
+
+ // this one requires <property name="commitOnePhase">false</property> on CoordinatorEnvironmentBean
+ //@Test
+ public void testCrashThreeLogs() throws Exception {
+
+ instrumentor.injectOnCall(TestClient.class, "terminateTransaction", "$1 = true"); // shouldCommit=true
+
+ instrumentor.crashAtMethodEntry(BridgeXAResource.class, "commit");
+
+ execute(false);
+
+ instrumentedTestVolatileParticipant.assertKnownInstances(1);
+ instrumentedTestVolatileParticipant.assertMethodCalled("prepare");
+ instrumentedTestVolatileParticipant.assertMethodNotCalled("commit");
+ instrumentedTestVolatileParticipant.assertMethodNotCalled("rollback");
+
+ instrumentedTestDurableParticipant.assertKnownInstances(1);
+ instrumentedTestDurableParticipant.assertMethodCalled("prepare");
+ instrumentedTestDurableParticipant.assertMethodNotCalled("commit");
+ instrumentedTestDurableParticipant.assertMethodNotCalled("rollback");
+
+ rebootServer();
+
+ doRecovery();
+ doRecovery();
+
+ instrumentedTestDurableParticipant.assertKnownInstances(1);
+ instrumentedTestDurableParticipant.assertMethodNotCalled("prepare");
+ instrumentedTestDurableParticipant.assertMethodNotCalled("rollback");
+ instrumentedTestDurableParticipant.assertMethodCalled("commit");
+ }
+
+ /////////////////
+
+ // stolen from CrashRecoveryDelays - should probably just add that to the classpath?
+ // prod the recovery manager via its socket. This avoid any sleep delay.
+ private static void doRecovery() throws InterruptedException
+ {
+ int port = recoveryPropertyManager.getRecoveryEnvironmentBean().getRecoveryPort();
+ String host = recoveryPropertyManager.getRecoveryEnvironmentBean().getRecoveryAddress();
+
+ BufferedReader in = null;
+ PrintStream out = null;
+ Socket sckt = null;
+
+ try
+ {
+ sckt = new Socket(host,port);
+
+ in = new BufferedReader(new InputStreamReader(sckt.getInputStream()));
+ out = new PrintStream(sckt.getOutputStream());
+
+ // Output ping message
+ out.println("SCAN");
+ out.flush();
+
+ // Receive pong message
+ String inMessage = in.readLine();
+
+ if(!inMessage.equals("DONE")) {
+ System.err.println("Recovery failed with message: "+inMessage);
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ finally
+ {
+ try {
+ if ( in != null )
+ {
+ in.close();
+ }
+
+ if ( out != null )
+ {
+ out.close();
+ }
+
+ sckt.close();
+ } catch(Exception e) {}
+ }
+ }
+
+ // stolen from EmptyObjectStore.java
+ public static void removeContents(File directory)
+ {
+ if ((directory != null) &&
+ directory.isDirectory() &&
+ (!directory.getName().equals("")) &&
+ (!directory.getName().equals("/")) &&
+ (!directory.getName().equals("\\")) &&
+ (!directory.getName().equals(".")) &&
+ (!directory.getName().equals("..")))
+ {
+ File[] contents = directory.listFiles();
+
+ for (int index = 0; index < contents.length; index++)
+ {
+ if (contents[index].isDirectory())
+ {
+ removeContents(contents[index]);
+
+ //System.err.println("Deleted: " + contents[index]);
+ contents[index].delete();
+ }
+ else
+ {
+ System.err.println("Deleted: " + contents[index]);
+ contents[index].delete();
+ }
+ }
+ }
+ }
+}
Modified: labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/service/TestServiceImpl.java
===================================================================
--- labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/service/TestServiceImpl.java 2010-05-28 14:27:47 UTC (rev 33140)
+++ labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/service/TestServiceImpl.java 2010-05-28 14:50:01 UTC (rev 33141)
@@ -70,7 +70,7 @@
try {
for(int i = 0; i < count; i++) {
TestDurableParticipant durableParticipant = new TestDurableParticipant();
- tm.enlistForDurableTwoPhase(durableParticipant, "org.jboss.jbossts.txbridge.tests.outbound.Durable:" + new Uid().toString());
+ tm.enlistForDurableTwoPhase(durableParticipant, TestDurableParticipant.TYPE_IDENTIFIER + new Uid().toString());
}
} catch(Exception e) {
log.error("could not enlist", e);
Modified: labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/utility/TestDurableParticipant.java
===================================================================
--- labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/utility/TestDurableParticipant.java 2010-05-28 14:27:47 UTC (rev 33140)
+++ labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/utility/TestDurableParticipant.java 2010-05-28 14:50:01 UTC (rev 33141)
@@ -34,6 +34,12 @@
{
private static Logger log = Logger.getLogger(TestDurableParticipant.class);
+ /*
+ * Uniq String used to prefix ids at participant registration,
+ * so that the recovery module can identify relevant instances.
+ */
+ public static final String TYPE_IDENTIFIER = "TestDurableParticipant_";
+
private String prepareOutcome = "prepared";
/**
Added: labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/utility/TestRecoveryModule.java
===================================================================
--- labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/utility/TestRecoveryModule.java (rev 0)
+++ labs/jbosstm/trunk/txbridge/tests/src/org/jboss/jbossts/txbridge/tests/outbound/utility/TestRecoveryModule.java 2010-05-28 14:50:01 UTC (rev 33141)
@@ -0,0 +1,98 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and/or its affiliates,
+ * and individual contributors as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * (C) 2010,
+ * @author JBoss, by Red Hat.
+ */
+package org.jboss.jbossts.txbridge.tests.outbound.utility;
+
+import com.arjuna.wst.Durable2PCParticipant;
+import org.apache.log4j.Logger;
+import org.jboss.jbossts.xts.recovery.participant.at.XTSATRecoveryManager;
+import org.jboss.jbossts.xts.recovery.participant.at.XTSATRecoveryModule;
+
+import java.io.ObjectInputStream;
+
+/**
+ * Implementation of XTSATRecoveryModule for deserializing TestDurableParticipant instances in tx test cases.
+ *
+ * @author Jonathan Halliday (jonathan.halliday at redhat.com) 2010-05
+ */
+public class TestRecoveryModule implements XTSATRecoveryModule
+{
+ private static final Logger log = Logger.getLogger(TestRecoveryModule.class);
+
+ private final XTSATRecoveryManager xtsATRecoveryManager = XTSATRecoveryManager.getRecoveryManager();
+
+ /**
+ * MC lifecycle callback, used to register components with the recovery manager.
+ */
+ public void start()
+ {
+ log.info("TestRecoveryModule starting");
+
+ xtsATRecoveryManager.registerRecoveryModule(this);
+ }
+
+ /**
+ * MC lifecycle callback, used to unregister components from the recovery manager.
+ */
+ public void stop()
+ {
+ log.info("TestRecoveryModule stopping");
+
+ xtsATRecoveryManager.unregisterRecoveryModule(this);
+ }
+
+ /**
+ * called during recovery processing to allow an application to identify a participant id
+ * belonging to one of its participants and recreate the participant by deserializing
+ * it from the supplied object input stream. n.b. this is only appropriate in case the
+ * participant was originally saved using serialization.
+ *
+ * @param id the id used when the participant was created
+ * @param objectInputStream a stream from which the application should deserialise the participant
+ * if it recognises that the id belongs to the module's application
+ * @return
+ * @throws Exception if an error occurs deserializing the durable participant
+ */
+ @Override
+ public Durable2PCParticipant deserialize(String id, ObjectInputStream objectInputStream) throws Exception
+ {
+ log.trace("deserialize(id="+id+")");
+
+ if(id.startsWith(TestDurableParticipant.TYPE_IDENTIFIER))
+ {
+ Object participant = objectInputStream.readObject();
+ TestDurableParticipant testDurableParticipant = (TestDurableParticipant)participant;
+ return testDurableParticipant;
+ }
+ else
+ {
+ return null; // it belongs to some other XTS app, ignore it.
+ }
+ }
+
+ /**
+ * Unused recovery callback. We use serialization instead, so this method will always throw an exception if called.
+ */
+ @Override
+ public Durable2PCParticipant recreate(String id, byte[] recoveryState) throws Exception
+ {
+ throw new Exception("recreation not supported - should use deserialization instead.");
+ }
+}
More information about the jboss-svn-commits
mailing list