[jboss-svn-commits] JBL Code SVN: r36243 - in labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US: extras and 1 other directory.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Tue Dec 7 20:09:31 EST 2010
Author: misty at redhat.com
Date: 2010-12-07 20:09:30 -0500 (Tue, 07 Dec 2010)
New Revision: 36243
Added:
labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/Failure_Recovery.xml
labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/ExpiryScanner-properties.xml
labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/RecoveryManager-properties.xml
labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/XAConnectionRecovery.java
labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/default-RecoveryExtension-settings.xml
labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/orportability-properties.xml
Modified:
labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/ArjunaJTS_Development_Guide.xml
Log:
Converted Failure_Recovery.xml
Modified: labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/ArjunaJTS_Development_Guide.xml
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/ArjunaJTS_Development_Guide.xml 2010-12-07 20:43:05 UTC (rev 36242)
+++ labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/ArjunaJTS_Development_Guide.xml 2010-12-08 01:09:30 UTC (rev 36243)
@@ -13,6 +13,8 @@
<xi:include href="Constructing_An_OTS_Application.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="JBossTS_Interface.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="Example.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="Failure_Recovery.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+
<xi:include href="JTA_And_JTS.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="Tools.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="ORB_Specific_Configurations.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
Added: labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/Failure_Recovery.xml
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/Failure_Recovery.xml (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/Failure_Recovery.xml 2010-12-08 01:09:30 UTC (rev 36243)
@@ -0,0 +1,569 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "ArjunaJTS_Development_Guide.ent">
+%BOOK_ENTITIES;
+]>
+<chapter>
+ <title>Failure Recovery</title>
+ <para>
+ The failure recovery subsystem of JBossTS ensure that results of a transaction are applied consistently to all
+ resources affected by the transaction, even if any of the application processes or the hardware hosting them crash
+ or lose network connectivity. In the case of hardware crashes or network failures, the recovery does not take place
+ until the system or network are restored, but the original application does not need to be restarted. Recovery is
+ handled by the Recovery Manager process. For recover to take place, information about the transaction and the
+ resources involved needs to survive the failure and be accessible afterward. This information is held in the
+ <classname>ActionStore</classname>, which is part of the <classname>ObjectStore</classname>. If the
+ <classname>ObjectStore</classname> is destroyed or modified, recovery may not be possible.
+ </para>
+ <para>
+ Until the recovery procedures are complete, resources affected by a transaction which was in progress at the time of
+ the failure may be inaccessible. Database resources may report this as as tables or rows held by <phrase>in-doubt
+ transactions</phrase>. For TXOJ resources, an attempt to activate the Transactional Object, such as when trying to
+ get a lock, fails.
+ </para>
+ <!-- Surely JDK 1.3 is no longer supported
+ <note>
+ <para>
+ Because of limitations in the ORB which ships with the JDK 1.3, it is not possible to provide crash recovery. We
+ therefore do not recommend using this ORB for mission critical applications.
+ </para>
+ </note>
+ -->
+
+ <section>
+ <title>Configuring the failure recovery subsystem for your ORB</title>
+ <para>
+ Although some ORB-specific configuration is necessary to configure the ORB sub-system, the basic settings are ORB-independent.
+ The configuration which applies to JBossTS is in the <filename>RecoveryManager-properties.xml</filename> file and
+ the <filename>orportability-properties.xml</filename> file. Contents of each file are below.
+ </para>
+ <example>
+ <title>RecoverManager-properties.xml</title>
+ <programlisting language="XML" role="XML"><xi:include href="extras/RecoveryManager-properties.xml" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
+ </example>
+ <example>
+ <title>orportability-properties.xml</title>
+ <programlisting language="XML" role="XML"><xi:include href="extras/orportability-properties.xml" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
+ </example>
+ <para>
+ These entries cause instances of the named classes to be loaded. The named classes then load the ORB-specific
+ classes needed and perform other initialization. This enables failure recovery for transactions initiated by or
+ involving applications using this property file. The default <filename>RecoveryManager-properties.xml</filename>
+ file and <filename>orportability-properties.xml</filename> with the distribution include these entries.
+ </para>
+ <important>
+ <para>
+ Failure recovery is NOT supported with the JavaIDL ORB that is part of JDK. Failure recovery is supported for
+ JacOrb only.
+ </para>
+ </important>
+ <para>
+ To disable recovery, remove or comment out the <literal>RecoveryEnablement</literal> line in the property file.
+ </para>
+ </section>
+
+ <section>
+ <title>The recovery manager</title>
+ <para>
+ The failure recovery subsystem of JBossTS requires the stand-alone Recovery Manager process to be running for
+ each <systemitem>ObjectStore</systemitem>. Typically, there is one <systemitem>ObjectStore</systemitem> for each
+ node on the network that is running JBossTS applications. The
+ RecoveryManager file is located in the <filename>arjuna.jar</filename> file within the package
+ <package>com.arjuna.ats.arjuna.recovery.RecoveryManager</package>. To start the Recovery Manager issue the following
+ command:
+ </para>
+ <example>
+ <title>Starting the recovery manager</title>
+ <screen>
+ java com.arjuna.ats.arjuna.recovery.RecoveryManager
+ </screen>
+ </example>
+ <para>
+ If the <option>-test</option> flag is used with the Recovery Manager, it displays a “Ready” message when you
+ start it.
+ </para>
+ <important>
+ <para>
+ If you are using JacORB, the Recovery Manager is started to allow successful registration of
+ <classname>Resource</classname> objects.
+ </para>
+ </important>
+
+ <section>
+ <title>Configuring the RecoveryManager</title>
+ <para>
+ The <classname>RecoveryManager</classname> reads the properties defined in the
+ <filename>jbossts-properties.xml</filename> file and then the property file
+ <filename>RecoveryManager-properties.xml</filename>, from the same directory as it found the <filename>arjuna
+ properties</filename> file. An entry for a property in the <filename>RecoveryManager-properties.xml</filename>
+ file overrides an entry for the same property in the main <filename>TransactionService-properties.xml</filename>
+ file. Most of the entries are specific to the <classname>RecoveryManager</classname>.
+ </para>
+ <para>
+ A default version of <filename>RecoveryManager-properties.xml</filename> is supplied with the distribution. You
+ can use this file without modification, unless you want to modify the debug tracing fields as outlined in <xref
+ linkend="recovery-manager-output" />.
+ </para>
+
+ <section id="recovery-manager-output">
+ <title>Output</title>
+ <para>
+ You will likely need output from the <classname>RecoveryManager</classname>, to provide a record of what
+ recovery activity has taken place. <classname>RecoveryManager</classname> uses the logging tracing mechanism
+ provided by the <firstterm>Arjuna Common Logging Framework (CLF)</firstterm>, which provides a high level
+ interface that hides differences that exist between existing logging APIs such as Jakarta log4j or the JDK
+ logging API.
+ </para>
+ <para>
+ With the CLF, applications make logging calls on <classname>commonLogger</classname> objects. These
+ <classname>commonLogger</classname> objects pass log messages to <classname>Handler</classname> for
+ publication. Both <classname>commonLoggers</classname> and <classname>Handlers</classname> filter log messages
+ by level. Each log message has an associated log Level that gives the importance and urgency of a log message.
+ </para>
+ <orderedlist>
+ <title>Logging levels, from most to least verbose</title>
+ <listitem>
+ <para>
+ DEBUG
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ INFO
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ WARN
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ ERROR
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ FATAL
+ </para>
+ </listitem>
+ </orderedlist>
+ <para>
+ The choice of the underlying logging infrastructure is defined by the property
+ <varname>LoggingEnvironmentBean.loggingFactory</varname>, which is set by default to
+ <literal>log4j</literal>. Possible values are described in the <classname>LoggingEnvironmentBean</classname>
+ javadoc.
+ </para>
+ <para>
+ The properties of the underlying log system are configured in a manner specific to that log system. For log4j,
+ a <filename>log4j.properties</filename> file is used.
+ </para>
+ <example>
+ <title>Default log4j configuration file used by JBossTS</title>
+ <screen>
+# Default LOG4J Configuration
+# Arjuna Technologies Ltd.
+# $Id: log4j.properties,v 1.1 2003/09/28 11:38:24 rbegg Exp $
+log4j.rootLogger=WARN, stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
+ </screen>
+ </example>
+ <para>
+ To set the logging level to <literal>DEBUG</literal>, set the <varname>log4j.rootLogger</varname> to
+ <literal>DEBUG</literal>.
+ </para>
+ <para>
+ Messages describing the start and the periodical behavior of the <classname>RecoveryManager</classname> are
+ set the <literal>INFO</literal> level. To see them, set the logging level to <literal>INFO</literal>. Setting
+ the normal recovery messages to the <literal>INFO</literal> level produces a moderate level of reporting from
+ the <classname>RecoveryManager</classname>. If no recovery needs to take place, the only thing reported is the
+ entry into each module for each periodic pass. To disable the <literal>INFO</literal> messages produced by the
+ <classname>RecoveryManager</classname>, set the logging level to <literal>ERROR</literal>.
+ </para>
+ <note>
+ <para>
+ Set the Logging level at least to the <literal>WARN</literal> value to enable the report of warning
+ messages.
+ </para>
+ </note>
+ </section>
+
+ </section>
+
+ <section>
+ <title>Periodic recovery</title>
+ <para>
+ The <classname>RecoveryManager</classname> scans the <classname>ObjectStore</classname> and other locations of
+ information, looking for transactions and resources that may require recovery. The scans and recovery processing
+ are performed by recovery modules, which are instances of classes that implement the
+ <interfacename>com.arjuna.ats.arjuna.recovery.RecoveryModule</interfacename> interface. Each module is
+ responsible for a particular category of transaction or resource.The set of recovery modules is dynamically
+ loaded, using properties found in the <filename>RecoveryManager-properties.xml</filename> file.
+ </para>
+ <para>
+ The interface has two methods: <methodname>periodicWorkFirstPass</methodname> and
+ <methodname>periodicWorkSecondPass</methodname>. At an interval defined by property
+ <varname>PERIODIC_RECOVERY_PERIOD</varname>, the <classname>RecoveryManager</classname> calls the
+ <methodname>periodicWorkFirstPass</methodname> method on each property. It then waits for a brief period,
+ defined by <varname>RECOVERY_BACKOFF_PERIOD</varname>, before calling the
+ <methodname>periodicWorkSecondPass</methodname> method. Typically, in the first pass, the module scans the
+ relevant part of the ObjectStore to find transactions or resources that are in-doubt, or part of the way through
+ the commitment process. On the second pass, if any of the same items are still in-doubt, the original
+ application process may have crashed and the item may need recovery.
+ </para>
+ <para>
+ If the <classname>RecoveryManager</classname> attempts to recover a transaction that is still progressing in the
+ original process, it is likely to break the consistency. Accordingly, the recovery modules use a mechanism,
+ implemented in the <package>com.arjuna.ats.internal.jts.recovery.contact</package> package, to check whether the
+ original process is still alive, and whether the transaction is still in progress. The
+ <classname>RecoveryManager</classname> only proceeds with recovery if the original process has disappeared or
+ the transaction is completed. If a server process or machine crashes, but the transaction-initiating process
+ survives, the transaction complete, usually generating a warning. Recovery of such a transaction is the
+ responsibility of the <classname>RecoveryManager</classname>.
+ </para>
+ <para>
+ It is important to set the interval periods appropriately. The total iteration time is the sum of
+ <varname>PERIODIC_RECOVERY_PERIOD</varname>, <varname>RECOVERY_BACKOFF_PERIOD</varname>, and the length of time it takes to scan the stores and to
+ attempt recovery of any in-doubt transactions, for all the recovery modules. The recovery attempt time may
+ include connection timeouts while trying to use the ORB to communicate with processes or machines that have
+ crashed or are inaccessible. This is why the recovery system includes mechanisms to avoid trying to recover
+ the same transaction infinitely. The total iteration time affects how long a resource remains
+ inaccessible after a failure.
+ </para>
+ <para>
+ Set <varname>PERIODIC_RECOVERY_PERIOD</varname> accordingly. It defaults to 120 seconds. The
+ <varname>RECOVERY_BACKOFF_PERIOD</varname> can be comparatively short, and defaults to 10 seconds. Its purpose
+ is to reduce the number of transactions that are candidates for recovery, and which require a contact call to
+ the original process to check whether they are still in progress.
+ </para>
+ <!-- Taking this out because it is ancient history
+ <note>
+ <para>
+ In JBossTS 2.0, there was no contact mechanism, and the backoff period had to be long enough to avoid catching
+ transactions in flight at all. From 2.1, there is no such risk.
+ </para>
+ </note>
+ -->
+ <para>
+ JBossTS includes several recovery modules, supporting various aspects of transaction recovery including JDBC
+ recovery. You can create your own recovery modules and register them with the
+ <classname>RecoveryManager</classname> using the
+ <classname>RecoveryEnvironmentBean.recoveryExtensions</classname> property. These recovery modules are invoked
+ on each pass of the periodic recovery in the order they appear. You can predict the order in which they run, but
+ a failure in an application process might occur while a periodic recovery pass is in progress. The default
+ <classname>RecoveryExtension</classname> settings are below.
+ </para>
+ <example>
+ <title>Default RecoveryExtension settings</title>
+ <programlisting language="XML" role="XML"><xi:include href="extras/default-RecoveryExtension-settings.xml" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
+ </example>
+ </section>
+
+ <section>
+ <title>XA resource recovery</title>
+ <para>
+ Recovery of XA resources accessed via JDBC is handled by the <classname>XARecoveryModule</classname>. This
+ module includes both <phrase>transaction-initiated</phrase> and <phrase>resource-initiated</phrase> recovery.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Transaction-initiated recovery is possible where the particular transaction branch progressed far enough for
+ a <systemitem>JTA_ResourceRecord</systemitem> to be written in the ObjectStore. The record contains the
+ information needed to link the transaction to information known by the rest of JBossTS in the database.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Resource-initiated recovery is necessary for branches where a failure occurred after the database made a
+ persistent record of the transaction, but before the <systemitem>JTA_ResourceRecord</systemitem> was
+ written. Resource-initiated recovery is also necessary for datasources for which it is impossible to hold
+ information in the <systemitem>JTA_ResourceRecord</systemitem> that allows the recreation in the
+ RecoveryManager of the <classname>XAConnection</classname> or <classname>XAResource</classname> used in the
+ original application.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Transaction-initiated recovery is automatic. The <classname>XARecoveryModule</classname> finds the
+ <systemitem>JTA_ResourceRecord</systemitem> which needs recovery, using the two-pass mechanism described
+ above. It then uses the normal recovery mechanisms to find the status of the transaction the resource was
+ involved in, by running <methodname>replay_completion</methodname> on the
+ <classname>RecoveryCoordinator</classname> for the transaction branch. Next, it creates or recreates the
+ appropriate <classname>XAResource</classname> and issues <methodname>commit</methodname> or
+ <methodname>rollback</methodname> on it as appropriate. The <classname>XAResource</classname> creation uses the
+ same database name, username, password, and other information as the application.
+ </para>
+ <para>
+ Resource-initiated recovery must be specifically configured, by supplying the
+ <classname>RecoveryManager</classname> with the appropriate information for it to interrogate all the
+ <classname>XADataSources</classname> accessed by any JBossTS application. The access to each
+ <classname>XADataSource</classname> is handled by a class that implements the
+ <interfacename>com.arjuna.ats.jta.recovery.XAResourceRecovery</interfacename> interface. Instances of this class
+ are dynamically loaded, as controlled by property
+ <varname>JTAEnvironmentBean.xaResourceRecoveryInstances</varname>.
+ </para>
+ <para>
+ The <classname>XARecoveryModule</classname> uses the <classname>XAResourceRecovery</classname> implementation to
+ get an <classname>XAResource</classname> to the target datasource. On each invocation of
+ <methodname>periodicWorkSecondPass</methodname>, the recovery module issues an
+ <methodname>XAResource.recover</methodname> request. This request returns a list of the transaction identifiers
+ that are known to the datasource and are in an in-doubt state. The list of these in-doubt Xids is compared
+ across multiple passes, using <methodname>periodicWorkSecondPass-es</methodname>. Any Xid that appears in both
+ lists, and for which no <systemitem>JTA_ResourceRecord</systemitem> is found by the intervening
+ transaction-initiated recovery, is assumed to belong to a transaction involved in a crash before any
+ <systemitem>JTA_Resource_Record</systemitem> was written, and a <methodname>rollback</methodname> is issued for
+ that transaction on the <classname>XAResource</classname>.
+ </para>
+ <para>
+ This double-scan mechanism is used because it is possible the Xid was obtained from the datasource just as the
+ original application process was about to create the corresponding JTA_ResourceRecord. The interval between the
+ scans should allow time for the record to be written unless the application crashes (and if it does, rollback is
+ the right answer).
+ </para>
+ <para>
+ An <classname>XAResourceRecovery</classname> implementation class can contain all the information needed to
+ perform recovery to a specific datasource. Alternatively, a single class can handle multiple datasources which
+ have some similar features. The constructor of the implementation class must have an empty parameter list,
+ because it is loaded dynamically. The interface includes an <methodname>initialise</methodname> method, which
+ passes in further information as a <type>string</type>. The content of the string is taken from the property
+ value that provides the class name. Everything after the first semi-colon is passed as the value of the
+ string. The <classname>XAResourceRecovery</classname> implementation class determins how to use the string.
+ </para>
+ <para>
+ An <classname>XAResourceRecovery</classname> implementation class, <classname>com.arjuna.ats.internal.jdbc.recovery.BasicXARecovery</classname>, supports resource-initiated recovery for any XADataSource. For this class, the string
+ received in method <methodname>initialise</methodname> is assumed to contain the number of connections to recover, and the name of the
+ properties file containing the dynamic class name, the database username, the database password and the database
+ connection URL. The following example is for an Oracle 8.1.6 database accessed via the Sequelink 5.1 driver:
+ </para>
+ <screen>
+XAConnectionRecoveryEmpay=com.arjuna.ats.internal.jdbc.recovery.BasicXARecovery;2;OraRecoveryInfo
+ </screen>
+ <para>
+ This implementation is only meant as an example, because it relies upon usernames and passwords appearing in
+ plain text properties files. You can create your own implementations of
+ <classname>XAConnectionRecovery</classname>. See the javadocs and the example
+ <package>com.arjuna.ats.internal.jdbc.recovery.BasicXARecovery</package>.
+ </para>
+
+ <example>
+ <title>XAConnectionRecovery implementation</title>
+ <programlisting role="JAVA" language="Java"><xi:include href="extras/XAConnectionRecovery.java" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
+ </example>
+ <!-- Removed as ancient
+ <note>
+ <title>Oracle usernames for Oracle 8.0 to 8.1.4</title>
+ <para>
+ it is necessary for any database user that will use distributed transactions (e.g., JBossTS and JDBC) to have
+ select privilege on the SYS via DBA_PENDING_TRANSACTIONS. For 8.1.5 and higher, this is not (apparently)
+ necessary for normal transaction access. However, this privilege is needed for the database user given when
+ creating an XAConnection that provides an XAResource that is then used for
+ XAResource.recover. (XAResource.commit, rollback etc. do not require the privilege). Accordingly,
+ administrators may wish to create a special database username for the JBossTS RecoveryManager, which has this
+ privilege, which need not be granted to users in general. An implication of this is that access to the
+ RecoveryManager_2_2.properties file needs to be appropriately controlled, if the password for the
+ RecoveryManager user is contained in it.
+ </para>
+ </note>
+ -->
+ <note>
+ <title>Multiple recovery domains and resource-initiated recovery</title>
+ <para>
+ <methodname>XAResource.recover</methodname> returns the list of all transactions that are in-doubt with in the
+ datasource. If multiple recovery domains are used with a single datasource, resource-initiated recovery sees
+ transactions from other domains. Since it does not have a <systemitem>JTA_ResourceRecord</systemitem>
+ available, it rolls back the transaction in the database, if the Xid appears in successive recover calls. To
+ suppress resource-initiated recovery, do not supply an <varname>XAConnectionRecovery</varname> property, or
+ confine it to one recovery domain.
+ </para>
+ </note>
+ </section>
+
+ <section>
+ <title>Recovery behavior</title>
+ <para>
+ Property <varname>OTS_ISSUE_RECOVERY_ROLLBACK</varname> controls whether the
+ <classname>RecoveryManager</classname> explicitly issues a rollback request when
+ <methodname>replay_completion</methodname> asks for the status of a transaction that is unknown. According to
+ the <systemitem>presume-abort</systemitem> mechanism used by OTS and JTS, the transaction can be assumed to have
+ rolled back, and this is the response that is returned to the <classname>Resource</classname>, including a
+ subordinate coordinator, in this case. The <classname>Resource</classname> should then apply that result to the
+ underlying resources. However, it is also legitimate for the superior to issue a rollback, if
+ <varname>OTS_ISSUE_RECOVERY_ROLLBACK</varname> is set to <literal>YES</literal>.
+ </para>
+ <para>
+ The OTS transaction identification mechanism makes it possible for a transaction coordinator to hold a
+ <classname>Resource</classname> reference that will never be usable. This can occur in two cases:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ The process holding the <classname>Resource</classname> crashes before receiving the commit or rollback
+ request from the coordinator.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The <classname>Resource</classname> receives the commit or rollback, and responds. However, the message is
+ lost or the coordinator process has crashed.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ In the first case, the <classname>RecoveryManager</classname> for the <classname>Resource</classname>
+ <classname>ObjectStore</classname> eventually reconstructs a new <classname>Resource</classname> (with a
+ different CORBA object reference (IOR), and issues a <methodname>replay_completion</methodname> request
+ containing the new <classname>Resource</classname> IOR. The <classname>RecoveryManager</classname> for the
+ coordinator substitutes this in place of the original, useless one, and issues <methodname>commit</methodname>
+ to the new reconstructed <classname>Resource</classname>. The <classname>Resource</classname> has to have been
+ in a commit state, or there would be no transaction intention list. Until the
+ <methodname>replay_completion</methodname> is received, the <classname>RecoveryManager</classname> tries to send
+ <methodname>commit</methodname> to its <classname>Resource</classname> reference.–This will fail with a CORBA
+ System Exception. Which exception depends on the ORB and other details.
+ </para>
+ <para>
+ In the second case, the <classname>Resource</classname> no longer exists. The
+ <classname>RecoveryManager</classname> at the coordinator will never get through, and will receive System
+ Exceptions forever.
+ </para>
+ <para>
+ The <classname>RecoveryManager</classname> cannot distinguish these two cases by any protocol mechanism. There
+ is a perceptible cost in repeatedly attempting to send the commit to an inaccessible
+ <classname>Resource</classname>. In particular, the timeouts involved will extend the recovery iteration time,
+ and thus potentially leave resources inaccessible for longer.
+ </para>
+ <para>
+ To avoid this, the <classname>RecoveryManager</classname> only attempts to send <methodname>commit</methodname>
+ to a <classname>Resource</classname> a limited number of times. After that, it considers the transaction
+ <phrase>assumed complete</phrase>. It retains the information about the transaction, by changing the object type
+ in the <classname>ActionStore</classname>, and if the <classname>Resource</classname> eventually does wake up
+ and a <methodname>replay_completion</methodname> request is received, the <classname>RecoveryManager</classname>
+ activates the transaction and issues the commit request to the new Resource IOR. The number of times the
+ <classname>RecoveryManager</classname> attempts to issue <methodname>commit</methodname> as part of the periodic
+ recovery is controlled by the property variable <varname>COMMITTED_TRANSACTION_RETRY_LIMIT</varname>, and
+ defaults to <literal>3</literal>.
+ </para>
+ </section>
+
+ <section>
+ <title>Expired entry removal</title>
+ <para>
+ The operation of the recovery subsystem causes some entries to be made in the <classname>ObjectStore</classname>
+ that are not removed in normal progress. The <classname>RecoveryManager</classname> has a facility for scanning
+ for these and removing items that are very old. Scans and removals are performed by implementations of the
+ <interfacename>>com.arjuna.ats.arjuna.recovery.ExpiryScanner</interfacename>. Implementations of this interface
+ are loaded by giving the class names as the value of the property
+ <varname>RecoveryEnvironmentBean.expiryScanners</varname>. The <classname>RecoveryManager</classname> calls the
+ <methodname>scan</methodname> method on each loaded <classname>ExpiryScanner</classname> implementation at an
+ interval determined by the property <varname>RecoveryEnvironmentBean.expiryScanInterval</varname>. This value is
+ given in hours, and defaults to <literal>12</literal>. A property value of <literal>0</literal> disables any
+ expiry scanning. If the value as supplied is positive, the first scan is performed when
+ <classname>RecoveryManager</classname> starts. If the value is negative, the first scan is delayed until after
+ the first interval, using the absolute value.
+ </para>
+ <para>
+ There are two kinds of item that are scanned for expiry:
+ </para>
+ <informaltable>
+ <tgroup cols="3">
+ <tbody>
+ <row>
+ <entry>Contact items</entry>
+ <entry>
+ <para>
+ One contact item is created by every application process that uses JBossTS. They contain the
+ information that allows the <classname>RecoveryManager</classname> to determine if the process that
+ initiated the transaction is still alive, and what the transaction status is. The expiry time for
+ these is set by the property
+ <varname>RecoveryEnvironmentBean.transactionStatusManagerExpiryTime</varname>, which is expressed in
+ hours. The default is <literal>12</literal>, and <literal>0</literal> suppresses the expiration. This
+ is the interval after which a process that cannot be contacted is considered to be dead. It should be
+ long enough to avoid accidentally removing valid entries due to short-lived transient errors such as
+ network downtime.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>Assumed complete transactions</entry>
+ <entry>
+ <para>
+ The expiry time is counted from when the transactions were assumed to be complete. A
+ <methodname>replay_completion</methodname> request resets the clock. The risk with removing assumed
+ complete transactions it that a prolonged communication outage meansthat a remote
+ <classname>Resource</classname> cannot connect to the <classname>RecoveryManager</classname> for the
+ parent transaction. If the assumed complete transaction entry is expired before the communications are
+ recovered, the eventual <methodname>replay_completion</methodname> will find no information and the
+ <classname>Resource</classname> will be rolled back, although the transaction committed. Consequently,
+ the expiry time for assumed complete transactions should be set to a value that exceeds any
+ anticipated network outage. The parameter is <varname>ASSUMED_COMPLETE_EXPIRY_TIME</varname>. It is
+ expressed in hours, with <literal>240</literal> being the default, and <literal>0</literal> meaning
+ never to expire.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <example>
+ <title>ExpiryScanner properties</title>
+ <programlisting language="XML" role="XML"><xi:include href="extras/ExpiryScanner-properties.xml" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
+ </example>
+ <para>
+ There are two <classname>ExpiryScannner</classname>s for the assumed complete transactions, because there are
+ different types in the ActionStore.
+ </para>
+ </section>
+
+ <section>
+ <title>Recovery domains</title>
+ <para>
+ A key part of the recovery subsystem is that the <classname>RecoveryManager</classname> hosts the OTS
+ <classname>RecoveryCoordinator</classname> objects that handle recovery for transactions initiated in
+ application processes. Information passes between the application process and the
+ <classname>RecoveryManager</classname> in one of three ways:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <classname>RecoveryCoordinator</classname> object references (IORs) are created in the application
+ process. They contain information identifying the transaction in the object key. They pass the object key to
+ the <classname>Resource</classname> objects, and the <classname>RecoveryManager</classname> receives it.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The application process and the <classname>RecoveryManager</classname> access the same
+ <filename>jbossts-properties.xml</filename>, and therefore use the same <classname>ObjectStore</classname>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The <classname>RecoveryCoordinator</classname> invokes CORBA directly in the application, using information
+ in the contact items. Contact items are kept in the <classname>ObjectStore</classname>.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Multiple recovery domains may useful if you are doing a migration, and separate
+ <classname>ObjectStores</classname> are useful. However, multiple RecoveryManagers can cause problems with XA
+ datasources if resource-initiated recovery is active on any of them.
+ </para>
+ </section>
+ </section>
+
+ <section>
+ <title>Transaction status and <methodname>replay_comparison</methodname></title>
+ <para>
+ When a transaction successfully commits, the transaction log is removed from the system. The log is no longer
+ required, since all registered Resources have responded successfully to the two-phase commit sequence. However, if
+ a <classname>Resource</classname> calls <methodname>replay_completion</methodname> on the
+ <classname>RecoveryCoordinator</classname> after the transaction it represents commits, the status returned is
+ <classname>StatusRolledback</classname>. The transaction system does not keep a record of committed transactions,
+ and assumes that in the absence of a transaction log, the transaction must have rolled back. This is in line with
+ the <systemitem>presumed abort protocol</systemitem> used by the OTS.
+ </para>
+ </section>
+</chapter>
+
Added: labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/ExpiryScanner-properties.xml
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/ExpiryScanner-properties.xml (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/ExpiryScanner-properties.xml 2010-12-08 01:09:30 UTC (rev 36243)
@@ -0,0 +1,6 @@
+<entry key="RecoveryEnvironmentBean.expiryScanners">
+ com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionStatusManagerScanner
+ com.arjuna.ats.internal.jts.recovery.contact.ExpiredContactScanner
+ com.arjuna.ats.internal.jts.recovery.transactions.ExpiredToplevelScanner
+ com.arjuna.ats.internal.jts.recovery.transactions.ExpiredServerScanner
+</entry>
\ No newline at end of file
Added: labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/RecoveryManager-properties.xml
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/RecoveryManager-properties.xml (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/RecoveryManager-properties.xml 2010-12-08 01:09:30 UTC (rev 36243)
@@ -0,0 +1,3 @@
+<entry key="RecoveryEnvironmentBean.recoveryActivators">
+ com.arjuna.ats.internal.jts.orbspecific.recovery.RecoveryEnablement
+</entry>
\ No newline at end of file
Added: labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/XAConnectionRecovery.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/XAConnectionRecovery.java (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/XAConnectionRecovery.java 2010-12-08 01:09:30 UTC (rev 36243)
@@ -0,0 +1,224 @@
+
+/*
+ * Copyright (C) 2000, 2001,
+ *
+ * Hewlett-Packard,
+ * Arjuna Labs,
+ * Newcastle upon Tyne,
+ * Tyne and Wear,
+ * UK.
+ *
+ */
+package com.arjuna.ats.internal.jdbc.recovery;
+
+import com.arjuna.ats.jdbc.TransactionalDriver;
+import com.arjuna.ats.jdbc.common.jdbcPropertyManager;
+import com.arjuna.ats.jdbc.logging.jdbcLogger;
+
+import com.arjuna.ats.internal.jdbc.*;
+import com.arjuna.ats.jta.recovery.XAConnectionRecovery;
+import com.arjuna.ats.arjuna.common.*;
+import com.arjuna.common.util.logging.*;
+
+import java.sql.*;
+import javax.sql.*;
+import javax.transaction.*;
+import javax.transaction.xa.*;
+import java.util.*;
+
+import java.lang.NumberFormatException;
+
+/**
+ * This class implements the XAConnectionRecovery interface for XAResources.
+ * The parameter supplied in setParameters can contain arbitrary information
+ * necessary to initialise the class once created. In this instance it contains
+ * the name of the property file in which the db connection information is
+ * specified, as well as the number of connections that this file contains
+ * information on (separated by ;).
+ *
+ * IMPORTANT: this is only an *example* of the sorts of things an
+ * XAConnectionRecovery implementor could do. This implementation uses
+ * a property file which is assumed to contain sufficient information to
+ * recreate connections used during the normal run of an application so that
+ * we can perform recovery on them. It is not recommended that information such
+ * as user name and password appear in such a raw text format as it opens up
+ * a potential security hole.
+ *
+ * The db parameters specified in the property file are assumed to be
+ * in the format:
+ *
+ * DB_x_DatabaseURL=
+ * DB_x_DatabaseUser=
+ * DB_x_DatabasePassword=
+ * DB_x_DatabaseDynamicClass=
+ *
+ * DB_JNDI_x_DatabaseURL=
+ * DB_JNDI_x_DatabaseUser=
+ * DB_JNDI_x_DatabasePassword=
+ *
+ * where x is the number of the connection information.
+ *
+ * @since JTS 2.1.
+ */
+
+public class BasicXARecovery implements XAConnectionRecovery
+{
+ /*
+ * Some XAConnectionRecovery implementations will do their startup work
+ * here, and then do little or nothing in setDetails. Since this one needs
+ * to know dynamic class name, the constructor does nothing.
+ */
+ public BasicXARecovery () throws SQLException
+ {
+ numberOfConnections = 1;
+ connectionIndex = 0;
+ props = null;
+ }
+
+ /**
+ * The recovery module will have chopped off this class name already.
+ * The parameter should specify a property file from which the url,
+ * user name, password, etc. can be read.
+ */
+
+ public boolean initialise (String parameter) throws SQLException
+ {
+ int breakPosition = parameter.indexOf(BREAKCHARACTER);
+ String fileName = parameter;
+
+ if (breakPosition != -1)
+ {
+ fileName = parameter.substring(0, breakPosition -1);
+
+ try
+ {
+ numberOfConnections = Integer.parseInt(parameter.substring(breakPosition +1));
+ }
+ catch (NumberFormatException e)
+ {
+ //Produce a Warning Message
+ return false;
+ }
+ }
+
+ PropertyManager.addPropertiesFile(fileName);
+
+ try
+ {
+ PropertyManager.loadProperties(true);
+
+ props = PropertyManager.getProperties();
+ }
+ catch (Exception e)
+ {
+ //Produce a Warning Message
+
+ return false;
+ }
+
+ return true;
+ }
+
+ public synchronized XAConnection getConnection () throws SQLException
+ {
+ JDBC2RecoveryConnection conn = null;
+
+ if (hasMoreConnections())
+ {
+ connectionIndex++;
+
+ conn = getStandardConnection();
+
+ if (conn == null)
+ conn = getJNDIConnection();
+
+ if (conn == null)
+ //Produce a Warning message
+ }
+
+ return conn;
+ }
+
+ public synchronized boolean hasMoreConnections ()
+ {
+ if (connectionIndex == numberOfConnections)
+ return false;
+ else
+ return true;
+ }
+
+ private final JDBC2RecoveryConnection getStandardConnection () throws SQLException
+ {
+ String number = new String(""+connectionIndex);
+ String url = new String(dbTag+number+urlTag);
+ String password = new String(dbTag+number+passwordTag);
+ String user = new String(dbTag+number+userTag);
+ String dynamicClass = new String(dbTag+number+dynamicClassTag);
+ Properties dbProperties = new Properties();
+ String theUser = props.getProperty(user);
+ String thePassword = props.getProperty(password);
+
+ if (theUser != null)
+ {
+ dbProperties.put(ArjunaJDBC2Driver.userName, theUser);
+ dbProperties.put(ArjunaJDBC2Driver.password, thePassword);
+
+ String dc = props.getProperty(dynamicClass);
+
+ if (dc != null)
+ dbProperties.put(ArjunaJDBC2Driver.dynamicClass, dc);
+
+ return new JDBC2RecoveryConnection(url, dbProperties);
+ }
+ else
+ return null;
+ }
+
+ private final JDBC2RecoveryConnection getJNDIConnection () throws SQLException
+ {
+ String number = new String(""+connectionIndex);
+ String url = new String(dbTag+jndiTag+number+urlTag);
+ String password = new String(dbTag+jndiTag+number+passwordTag);
+ String user = new String(dbTag+jndiTag+number+userTag);
+ Properties dbProperties = new Properties();
+ String theUser = props.getProperty(user);
+ String thePassword = props.getProperty(password);
+
+ if (theUser != null)
+ {
+ dbProperties.put(ArjunaJDBC2Driver.userName, theUser);
+ dbProperties.put(ArjunaJDBC2Driver.password, thePassword);
+ return new JDBC2RecoveryConnection(url, dbProperties);
+ }
+ else
+ return null;
+ }
+ private int numberOfConnections;
+ private int connectionIndex;
+ private Properties props;
+ private static final String dbTag = "DB_";
+ private static final String urlTag = "_DatabaseURL";
+ private static final String passwordTag = "_DatabasePassword";
+ private static final String userTag = "_DatabaseUser";
+ private static final String dynamicClassTag = "_DatabaseDynamicClass";
+ private static final String jndiTag = "JNDI_";
+
+ /*
+ * Example:
+ *
+ * DB2_DatabaseURL=jdbc\:arjuna\:sequelink\://qa02\:20001
+ * DB2_DatabaseUser=tester2
+ * DB2_DatabasePassword=tester
+ * DB2_DatabaseDynamicClass=
+ * com.arjuna.ats.internal.jdbc.drivers.sequelink_5_1
+ *
+ * DB_JNDI_DatabaseURL=jdbc\:arjuna\:jndi
+ * DB_JNDI_DatabaseUser=tester1
+ * DB_JNDI_DatabasePassword=tester
+ * DB_JNDI_DatabaseName=empay
+ * DB_JNDI_Host=qa02
+ * DB_JNDI_Port=20000
+ */
+
+ private static final char BREAKCHARACTER = ';'; // delimiter for parameters
+}
\ No newline at end of file
Added: labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/default-RecoveryExtension-settings.xml
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/default-RecoveryExtension-settings.xml (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/default-RecoveryExtension-settings.xml 2010-12-08 01:09:30 UTC (rev 36243)
@@ -0,0 +1,7 @@
+<entry key="RecoveryEnvironmentBean.recoveryExtensions">
+ com.arjuna.ats.internal.arjuna.recovery.AtomicActionRecoveryModule
+ com.arjuna.ats.internal.txoj.recovery.TORecoveryModule
+ com.arjuna.ats.internal.jts.recovery.transactions.TopLevelTransactionRecoveryModule
+ com.arjuna.ats.internal.jts.recovery.transactions.ServerTransactionRecoveryModule
+ com.arjuna.ats.internal.jta.recovery.jts.XARecoveryModule
+</entry>
\ No newline at end of file
Added: labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/orportability-properties.xml
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/orportability-properties.xml (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTS/docs/ArjunaJTS_Development_Guide/en-US/extras/orportability-properties.xml 2010-12-08 01:09:30 UTC (rev 36243)
@@ -0,0 +1 @@
+<entry key="com.arjuna.orbportability.orb.PostInit2">com.arjuna.ats.internal.jts.recovery.RecoveryInit</entry>
\ No newline at end of file
More information about the jboss-svn-commits
mailing list