<p>If the GTM fails, it must first recover its local state. Assuming the
GTM uses Berkeley DB tables to maintain state, it should run the <ahref="../api_reference/C/db_recover.html"class="olink">db_recover</a> utility (or the DB_RECOVER option to <ahref="../api_reference/C/envopen.html"class="olink">DB_ENV->open()</a>) upon startup. Once the GTM is back up and running, it needs to review all its outstanding global transactions, that is, all transactions that are recorded but not yet completed.</p>
<p>
The global transactions that have not yet reached the prepare phase should be aborted. For each global transaction that has not yet prepared, the GTM should send a message to each participant telling it to abort its transaction.</p>
<p>Next the GTM should review its log to identify all participating environments that have transactions in the preparing, aborting, or committing states. For each such participant, the GTM should issue a <ahref="../api_reference/C/txnrecover.html"class="olink">DB_ENV->txn_recover()</a> call. Upon receiving responses from each participant, the GTM must decide the fate of each transaction and issue appropriate calls. The correct behavior is defined as follows:</p>
<divclass="variablelist">
<dl>
<dt>
<spanclass="term">preparing</span>
</dt>
<dd>if all participating environments return the transaction in the list of prepared but not yet completed transactions, then the GTM should commit the transaction. If any participating environment fails to return the transaction in this list, then the GTM must issue an abort to all environments participating in that global transaction.</dd>
<dt>
<spanclass="term">committing</span>
</dt>
<dd>the GTM should send a commit to any environment that returned this
transaction in its list of prepared but not yet completed
transactions.</dd>
<dt>
<spanclass="term">aborting</span>
</dt>
<dd>the GTM should send an abort to any environment that returned this
transaction in its list of prepared but not yet completed
<p>In addition to knowing which local environments participate in each
global transaction, the GTM must also know the state of each active
global transaction. As soon as a transaction becomes distributed (that
is, a second environment participates), the GTM must record the
existence of the global transaction and all participants (whether this
must reside on stable storage or not depends on the exact configuration
of the system). As new environments participate, the GTM must keep this
information up to date.</p>
<p>When the GTM is ready to begin commit processing, it should issue
<ahref="../api_reference/C/txnprepare.html"class="olink">DB_TXN->prepare()</a> calls to each participating environment, indicating
the GID of the global transaction. Once all the participants have
successfully prepared, then the GTM must record that the global
transaction will be committed. This record should go to stable
storage. Once written to stable storage, the GTM can send
<ahref="../api_reference/C/txncommit.html"class="olink">DB_TXN->commit()</a> requests to each participating environment. Once
all environments have successfully completed the commit, the GTM can
either record the successful commit or can somehow "forget" the global
transaction.</p>
<p>
If an application uses nested transactions (that is, the
parent parameter is non-NULL in a call to <ahref="../api_reference/C/txnbegin.html"class="olink">DB_ENV->txn_begin()</a>)
then, only the parent transaction should call <ahref="../api_reference/C/txnprepare.html"class="olink">DB_TXN->prepare()</a>, not any of the child transactions.
</p>
<p>Should any participant fail to prepare, then the GTM must abort the
global transaction. The fact that the transaction is going to be
aborted should be written to stable storage. Once written, the GTM can
then issue <ahref="../api_reference/C/txnabort.html"class="olink">DB_TXN->abort()</a> requests to each environment. When all
aborts have returned successfully, the GTM can either record the
successful abort or "forget" the global transaction.</p>
<p>In summary, for each transaction, the GTM must maintain the following:</p>
<divclass="itemizedlist">
<ultype="disc">
<li>A list of participating environments</li>
<li>The current state of each transaction (pre-prepare, preparing,
<p>If a single environment fails, there is no need to bring down or recover other environments (the only exception to this is if all environments are managed in the same application address space and there is a risk that the failure of the environment corrupted other environments). Instead, once the failing environment comes back up, it should be recovered (that is, conventional recovery, via the <ahref="../api_reference/C/db_recover.html"class="olink">db_recover</a> utility or by specifying the <ahref="../api_reference/C/envopen.html#envopen_DB_RECOVER"class="olink">DB_RECOVER</a> flag to <ahref="../api_reference/C/envopen.html"class="olink">DB_ENV->open()</a> should be run). If the <ahref="../api_reference/C/db_recover.html"class="olink">db_recover</a> utility is used, then the -e option must be specified. In this case, the application will almost certainly want to specify environmental parameters via a <aclass="xref"href="env_db_config.html"title="DB_CONFIG configuration file">DB_CONFIG configuration file</a> in the environment's home directory, so that the <ahref="../api_reference/C/db_recover.html"class="olink">db_recover</a> utility can create an appropriately configured environment.
If the <ahref="../api_reference/C/db_recover.html"class="olink">db_recover</a> utility is not used, then the GTM should call <ahref="../api_reference/C/envopen.html"class="olink">DB_ENV->open()</a> specifying the <ahref="../api_reference/C/envopen.html#envopen_DB_RECOVER"class="olink">DB_RECOVER</a> flag. It should then call <ahref="../api_reference/C/txnrecover.html"class="olink">DB_ENV->txn_recover()</a>, which will return an array of DB_TXN handles for the set of prepared, but not yet completed transactions. For each transaction, the GTM should combine this knowledge with its transaction state table and call either <ahref="../api_reference/C/txncommit.html"class="olink">DB_TXN->commit()</a> or <ahref="../api_reference/C/txnabort.html"class="olink">DB_TXN->abort()</a>. After that process is complete, the environment is ready to participate in new transactions.
</p>
<p>If the GTM is running in a system with multiple GTMs, it is possible that some of the transactions returned via <ahref="../api_reference/C/txnrecover.html"class="olink">DB_ENV->txn_recover()</a> do not belong to the current environment. The GTM should detect this and call <ahref="../api_reference/C/txndiscard.html"class="olink">DB_TXN->discard()</a> on each such transaction handle. Furthermore, it is important to note the environment does not retain information about which GTM has issued <ahref="../api_reference/C/txnrecover.html"class="olink">DB_ENV->txn_recover()</a> operations. Therefore, each GTM should issue all its <ahref="../api_reference/C/txnrecover.html"class="olink">DB_ENV->txn_recover()</a> calls before another GTM issues its calls. If the calls are interleaved, each GTM may not get a complete and consistent set of transactions. The simplest way to enforce this is for each GTM to make sure it can receive all its outstanding transactions in a single <ahref="../api_reference/C/txnrecover.html"class="olink">DB_ENV->txn_recover()</a> call. The maximum number of possible outstanding transactions is roughly the maximum number of active transactions in the environment (whose value can be obtained using the <ahref="../api_reference/C/db_stat.html"class="olink">db_stat</a> utility). To simplify this procedure, the caller should allocate an array large enough to hold the list of transactions (for example, allocate an array able to hold three times the maximum number of transactions). If that is not possible, callers should check that the array was not completely filled in when <ahref="../api_reference/C/txnrecover.html"class="olink">DB_ENV->txn_recover()</a> returns. If the array was completely filled in, each transaction should be explicitly discarded, and the call repeated with a larger array.</p>
<p>The newly recovered environment will forbid any new transactions from being started until the prepared but not yet completed transactions have been resolved. In the multiple GTM case, this means that all GTMs must recover before any GTM can begin issuing new transactions.</p>
<p>
The GTM must determine how long it needs to retain global transaction commit and abort records. If the participating environments are following a DB_TXN_SYNC policy, that is, they are forcing commit and abort records to disk before replying to the GTM, then once the GTM has heard from all participants, it need not retain its persistent log records. However, if participating environments are running at weaker durability levels, such as <ahref="../api_reference/C/envset_flags.html#set_flags_DB_TXN_WRITE_NOSYNC"class="olink">DB_TXN_WRITE_NOSYNC</a> or <ahref="../api_reference/C/envset_flags.html#envset_flags_DB_TXN_NOSYNC"class="olink">DB_TXN_NOSYNC</a>, then the GTM must retain all commit and abort records until all participants have completed a checkpoint following the completion of a transaction.
<p>If the GTM fails, it must first recover its local state. Assuming the
GTM uses Berkeley DB tables to maintain state, it should run the <ahref="../api_reference/C/db_recover.html"class="olink">db_recover</a> utility (or the DB_RECOVER option to <ahref="../api_reference/C/envopen.html"class="olink">DB_ENV->open()</a>) upon startup. Once the GTM is back up and running, it needs to review all its outstanding global transactions, that is, all transactions that are recorded but not yet completed.</p>
<p>
The global transactions that have not yet reached the prepare phase should be aborted. For each global transaction that has not yet prepared, the GTM should send a message to each participant telling it to abort its transaction.</p>
<p>Next the GTM should review its log to identify all participating environments that have transactions in the preparing, aborting, or committing states. For each such participant, the GTM should issue a <ahref="../api_reference/C/txnrecover.html"class="olink">DB_ENV->txn_recover()</a> call. Upon receiving responses from each participant, the GTM must decide the fate of each transaction and issue appropriate calls. The correct behavior is defined as follows:</p>
<divclass="variablelist">
<dl>
<dt>
<spanclass="term">preparing</span>
</dt>
<dd>if all participating environments return the transaction in the list of prepared but not yet completed transactions, then the GTM should commit the transaction. If any participating environment fails to return the transaction in this list, then the GTM must issue an abort to all environments participating in that global transaction.</dd>
<dt>
<spanclass="term">committing</span>
</dt>
<dd>the GTM should send a commit to any environment that returned this
transaction in its list of prepared but not yet completed
transactions.</dd>
<dt>
<spanclass="term">aborting</span>
</dt>
<dd>the GTM should send an abort to any environment that returned this
transaction in its list of prepared but not yet completed