GdaXaTransaction

## GdaXaTransaction GdaXaTransaction — Distributed transaction manager |

## Synopsis

                        GdaXaTransaction;
    enum                GdaXaTransactionError;
                        GdaXaTransactionId;
    GdaXaTransaction *  gda_xa_transaction_new              (guint32 format,
                                                             const gchar *global_transaction_id);
    gboolean            gda_xa_transaction_register_connection
                                                            (GdaXaTransaction *xa_trans,
                                                             GdaConnection *cnc,
                                                             const gchar *branch,
                                                             GError **error);
    void                gda_xa_transaction_unregister_connection
                                                            (GdaXaTransaction *xa_trans,
                                                             GdaConnection *cnc);
    gboolean            gda_xa_transaction_begin            (GdaXaTransaction *xa_trans,
                                                             GError **error);
    gboolean            gda_xa_transaction_commit           (GdaXaTransaction *xa_trans,
                                                             GSList **cnc_to_recover,
                                                             GError **error);
    gboolean            gda_xa_transaction_rollback         (GdaXaTransaction *xa_trans,
                                                             GError **error);
    gboolean            gda_xa_transaction_commit_recovered (GdaXaTransaction *xa_trans,
                                                             GSList **cnc_to_recover,
                                                             GError **error);

    gchar *             gda_xa_transaction_id_to_string     (const GdaXaTransactionId *xid);
    GdaXaTransactionId * gda_xa_transaction_string_to_id    (const gchar *str);

## Description

The GdaXaTransaction object acts as a distributed transaction manager: to make sure local transactions on several connections (to possibly different databases and database types) either all succeed or all fail. For more information, see the X/Open CAE document Distributed Transaction Processing: The XA Specification. This document is published by The Open Group and available at http://www.opengroup.org/public/pubs/catalog/c193.htm.

The two phases commit protocol is implemented during the execution of a distributed transaction: modifications made on any connection are first prepared (which means that they are store in the database), and if that phase succeeded for all the involved connections, then the commit phase is executed (where all the data previously stored during the prepare phase are actually committed). That second phase may actually fail, but the distributed transaction will still be considered as sucessfull as the data stored during the prepare phase can be committed afterwards.

A distributed transaction involves the following steps:

1. Create a GdaXaTransaction object

2. Register the connections which will be part of the distributed transaction with that object using `gda_xa_transaction_register_connection()`

3. Beging the distributed transaction using `gda_xa_transaction_begin()`

4. Work individually on each connection as normally (make modifications)

5. Commit the distributed transaction using `gda_xa_transaction_commit()`

6. Discard the GdaXaTransaction object using `g_object_unref()`

## Details

### GdaXaTransaction

    typedef struct {
    	GObject                  object;
    	GdaXaTransactionPrivate *priv;
    } GdaXaTransaction;

### enum GdaXaTransactionError

    typedef enum
    {
            GDA_XA_TRANSACTION_ALREADY_REGISTERED_ERROR,
    	GDA_XA_TRANSACTION_DTP_NOT_SUPPORTED_ERROR
    } GdaXaTransactionError;

### GdaXaTransactionId

    typedef struct {
    	guint32  format;       /* any number */
    	gushort  gtrid_length; /* 1-64 */
    	gushort  bqual_length; /* 1-64 */
    	char     data [128];
    } GdaXaTransactionId;

Distributed transaction identification, composed of a global format identifier, a global transaction identifier, and a branch qualifier. For any connection participating in the global transactio, the format and global transaction identifier should be the same, and the branch qualifier should vary between the connections.

guint32 `format`; | Format ID, should be 0 if OSI CCR naming is used, otherwise any positive integer
gushort `gtrid_length`; | length of the global transaction ID (1-64)
gushort `bqual_length`; | length of the branch qualification (1-64)
char `data`[128]; | concatenated global transaction ID (bytes 0 to (`gtrid_length` -1) included) and branch qualification (bytes `gtrid_length` to (`gtrid_length`+`bqual_length` - 1) included)

### gda_xa_transaction_new ()

    GdaXaTransaction *  gda_xa_transaction_new              (guint32 format,
                                                             const gchar *global_transaction_id);

Creates a new GdaXaTransaction object, which will control the processus of performing a distributed transaction across several connections.

`format` : | a format ID
`global_transaction_id` : | the global transaction ID
Returns : | the newly created object.

### gda_xa_transaction_register_connection ()

    gboolean            gda_xa_transaction_register_connection
                                                            (GdaXaTransaction *xa_trans,
                                                             GdaConnection *cnc,
                                                             const gchar *branch,
                                                             GError **error);

Registers `cnc` to be used by `xa_trans` to create a distributed transaction.

Note: any GdaConnection object can only be registered with at most one GdaXaTransaction object; also some connections may not be registered at all with a GdaXaTransaction object because the database provider being used does not support it.

`xa_trans` : | a GdaXaTransaction object
`cnc` : | the connection to add to `xa_trans`
`branch` : | the branch qualifier
`error` : | a place to store errors, or `NULL`
Returns : | TRUE if no error occurred

### gda_xa_transaction_unregister_connection ()

    void                gda_xa_transaction_unregister_connection
                                                            (GdaXaTransaction *xa_trans,
                                                             GdaConnection *cnc);

Unregisters `cnc` to be used by `xa_trans` to create a distributed transaction. This is the opposite of `gda_xa_transaction_register_connection()`.

`xa_trans` : | a GdaXaTransaction object
`cnc` : | the connection to add to `xa_trans`

### gda_xa_transaction_begin ()

    gboolean            gda_xa_transaction_begin            (GdaXaTransaction *xa_trans,
                                                             GError **error);

Begins a distributed transaction (managed by `xa_trans`). Please note that this phase may fail for some connections if a (normal) transaction is already started (this depends on the database provider being used), so it's better to avoid starting any (normal) transaction on any of the connections registered with `xa_trans`.

`xa_trans` : | a GdaXaTransaction object
`error` : | a place to store errors, or `NULL`
Returns : | TRUE if no error occurred

### gda_xa_transaction_commit ()

    gboolean            gda_xa_transaction_commit           (GdaXaTransaction *xa_trans,
                                                             GSList **cnc_to_recover,
                                                             GError **error);

Commits a distributed transaction (managed by `xa_trans`). The commit is composed of two phases:

- a PREPARE phase where all the connections are required to store their transaction data to a permanent place (to be able to complete the commit should a problem occur afterwards)

- a COMMIT phase where the transaction data is actually written to the database

If the PREPARE phase fails for any of the connection registered with `xa_trans`, then the distributed commit fails and FALSE is returned. During the COMMIT phase, some commit may actually fail but the transaction can still be completed because the PREPARE phase succeeded (through the recover method).

`xa_trans` : | a GdaXaTransaction object
`cnc_to_recover` : | a place to store the list of connections for which the commit phase failed, or `NULL`
`error` : | a place to store errors, or `NULL`
Returns : | TRUE if no error occurred (there may be some connections to recover, though)

### gda_xa_transaction_rollback ()

    gboolean            gda_xa_transaction_rollback         (GdaXaTransaction *xa_trans,
                                                             GError **error);

Cancels a distributed transaction (managed by `xa_trans`).

`xa_trans` : | a GdaXaTransaction object
`error` : | a place to store errors, or `NULL`
Returns : | TRUE if no error occurred

### gda_xa_transaction_commit_recovered ()

    gboolean            gda_xa_transaction_commit_recovered (GdaXaTransaction *xa_trans,
                                                             GSList **cnc_to_recover,
                                                             GError **error);

Tries to commit the data prepared but which failed to commit (see `gda_xa_transaction_commit()`). This method allows one to terminate a distributed transaction which succedded but for which some connections needed to be recovered.

`xa_trans` : | a GdaXaTransaction object
`cnc_to_recover` : | a place to store the list of connections for which the there were data to recover and which failed to be actually committed, or `NULL`
`error` : | a place to store errors, or `NULL`
Returns : | TRUE if all the data which was still uncommitted has been committed

### gda_xa_transaction_id_to_string ()

    gchar *             gda_xa_transaction_id_to_string     (const GdaXaTransactionId *xid);

Creates a string representation of `xid`, in the format <gtrid>,<bqual>,<formatID> the <gtrid> and <bqual> strings contain alphanumeric characters, and non alphanumeric characters are converted to "`ab`" where ab is the hexadecimal representation of the character.

`xid` : | a GdaXaTransactionId pointer
Returns : | a new string representation of `xid`

### gda_xa_transaction_string_to_id ()

    GdaXaTransactionId * gda_xa_transaction_string_to_id    (const gchar *str);

Creates a new GdaXaTransactionId structure from its string representation, it's the opposite of `gda_xa_transaction_id_to_string()`.

`str` : | a string representation of a GdaXaTransactionId, in the "gtrid,bqual,formatID" format
Returns : | a new GdaXaTransactionId structure, or `NULL` in `str` has a wrong format