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
use crate::rm::ResourceManager;
use crate::tm::XaResult;
/// A transaction manager for distributed transactions.
///
/// Use register()/unregister() to define the set of resource managers
/// you want to (potentially) take part in subsequent transactions.
///
/// Then use `start_transaction()` to start a transaction. The rest is done on the
/// application interfaces of the resource manager and on the transaction object.
///
///
pub trait TransactionManager {
/// Register a ResourceManager.
///
/// Note that `Box<CResourceManager>` also implements `ResourceManager`, so you can hand in
/// here a `Box<Box<ResourceManagerImpl>>`.
/// Note that each registration must use a different rm_id - overwrites will not be allowed.
fn register(&mut self, rm: Box<ResourceManager>, rm_id: u64, cleanup: bool) -> XaResult<()>;
/// Unregister a ResourceManager.
fn unregister(&mut self, rm_id: u64) -> XaResult<()>;
/// Starts a new transaction with a fresh global TA ID and one branch per registered RM.
///
/// The method fails if the last transaction is not yet completed.
fn start_transaction(&mut self) -> XaResult<()>;
// /// Obtains a list of open Transactions-IDs from the registered resource managers.
// fn recover() -> XaResult<Vec<T>>;
// FIXME we'll need a function to continue with one of these XaTransactions.
// /// Sets a non-default timeout value for transactions being started subsequently with
// /// `start_transaction()`.
// ///
// /// By default, the transaction manager uses some default value for the transaction timeout.
// /// If seconds is set to 0, the default value is restored.
// ///
// fn set_transaction_timeout(seconds: u32);
// Internally, does commit_one_phase if only a single RM is involved, otherwise does
// 2PC: (end_success(), preprare(), commit() on all participating RMs)
/// Completes the transaction, if it is in state `TmStatus::Active`.
///
/// If successful, the transaction is set to state `TmStatus::Committed`, otherwise to
/// `TmStatus::Failed` or `TmStatus::RolledBack`.
fn commit_transaction(&mut self) -> XaResult<()>;
/// Rolls the transaction back, discarding all changes, and setting the status to
/// `TmStatus::RolledBack`.
fn rollback_transaction(&mut self) -> XaResult<()>;
/// Mark the transaction that its only possible outcome is to be rolled back.
fn set_transaction_rollbackonly(&mut self) -> XaResult<()>;
/// Returns the status of the transaction.
fn get_status(&mut self) -> XaResult<TmStatus>;
}
bitflags! {
/// States of a `TransactionManager`.
#[derive(Default)]
pub struct TmStatus: u32 {
/// No transaction in use.
const IDLE = 0x00_00_00_01;
/// New Transaction is currently being started.
const ACTIVATING = 0x00_00_00_02;
/// Current transaction can be used for changes.
const ACTIVE = 0x00_00_00_04;
/// Current transaction is currently being prepared.
const PREPARING = 0x00_00_00_08;
/// Current transaction is ready to be committed and can no more be used for changes.
const PREPARED = 0x00_00_01_00;
/// An attempt to commit the current transaction is ongoing.
const COMMITTING = 0x00_00_02_00;
/// Current transaction was successfully committed.
const COMMITTED = 0x00_00_04_00;
/// Current transaction has failed or was marked as RollbackOnly and cannot be committed.
const ROLLBACK_ONLY = 0x00_00_08_00;
/// Current transaction is currently being rolled back.
const ROLLINGBACK = 0x00_01_00_00;
/// Current transaction is rolled back.
const ROLLEDBACK = 0x00_02_00_00;
}
}