1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
//! Structs and traits for dealing with distributed transactions.
//!
//! This crate is an attempt to provide a reasonable rust language binding for
//! XA Distributed Transactions.
//!
//! So far there is no support for asynchronous operations in resource managers.
//!
//!
//! ## Example
//!
//! Let's assume we have two (or more) different database connections,
//! most likely to different database installations,
//! and we want to use two-phase-commit to ensure that all our changes to these
//! connections are stored consistently (i.e. all or nothing).
//!
//! **Precondition**: both connections (i.e. both drivers) have to be prepared for
//! working with `dist_tx`, and both are not using automatic commit.
//!
//! ```rust,ignore
//! let mut conn_a = ...;
//! let mut conn_b = ...;
//! ```
//!
//! First instantiate a `SimpleTransactionManager`:
//!
//! ```rust
//! # use dist_tx::tm::SimpleTransactionManager;
//! let mut tm = SimpleTransactionManager::new("XA Demo".to_owned());
//! ```
//!
//! Then retrieve a `ResourceManager` implementation from each connection,
//! and register it at the transaction manager.
//! Every registered resource manager is registered with a distinct ID.
//! In the example below we tell the transaction manager to cleanup eventually
//! existing open transaction left-overs from previous runs for the two ids.
//!
//! This makes already clear that the IDs (of type `u64`) should be chosen in a way
//! that minimizes undesired collision probabilities, and maximizes intended "collisions".
//!
//! ```rust,ignore
//! tm.register(conn_a.get_resource_manager(), id_1, true)?;
//! tm.register(conn_b.get_resource_manager(), id_2, true)?;
//! ```
//!
//! Now we start a distributed transaction
//!
//! ```rust,ignore
//! tm.start_transaction()?;
//! ```
//!
//! and then we're ready
//! to do all required updates via the two database connections:
//!
//! ```rust,ignore
//! ...
//! conn_a.dml(&insert_stmt(1, "foo"))?;
//! conn_b.dml(&insert_stmt(2, "bar"))?;
//! ...
//! ```
//!
//! At this point nothing is committed yet, which we could verify with additional connections
//! to the two databases that are not registered to `tm`.
//!
//! Finally, when all updates were done successfully, we commit the transaction:
//!
//! ```rust,ignore
//! tm.commit_transaction()?;
//! ```
//!
//! Now all updates are committed and visible, which we could again verify with
//! additional connections.
//!
//!
//! ## Implementation
//!
//! Database drivers etc, who want to enable their users to take part in distributed
//! transactions that are managed via `dist_tx`, can either implement
//! [`rm::ResourceManager`](rm/trait.ResourceManager.html), which is a more
//! rust-idiomatic interpretation of the XA resource manager,
//! or they implement [`rm::CResourceManager`](rm/trait.CResourceManager.html),
//! which is more C-ish, and wrap it into a [`rm::CRmWrapper`](rm/struct.CRmWrapper.html)
//! (which implements `rm::ResourceManager`).
//!
#![warn(missing_docs)]
#[macro_use]
extern crate bitflags;
extern crate byteorder;
#[macro_use]
extern crate log;
pub mod rm;
pub mod tm;