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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
use crate::TransactionId;
use std::time::Duration;
/// Concurrent Modification Strategy for resolution of conflict on commit.
///
#[derive(PartialEq, Clone, Debug, Eq, Default)]
pub enum TxStrategy {
///
/// Last modification received override all the previous modifications
///
#[default]
LastWin,
///
/// prepare_commit will fail if the persistent version is more recent of the version when
/// the [`update`] or [`delete`] is executed
///
/// [`update`]: struct.Transaction.html#method.update
/// [`delete`]: struct.Transaction.html#method.delete
///
VersionOnWrite,
///
/// prepare_commit will fail if the persistent version is more recent of the version of the
/// last [`read`] on the tx, if no [`read`] on the tx was called will follow the same behavior of
/// VersionOnWrite
///
/// [`read`]: struct.Transaction.html#method.read
///
VersionOnRead,
}
impl TxStrategy {
pub fn value(&self) -> u8 {
match *self {
TxStrategy::LastWin => 1,
TxStrategy::VersionOnWrite => 2,
TxStrategy::VersionOnRead => 3,
}
}
pub fn from_value(val: u8) -> TxStrategy {
match val {
1 => TxStrategy::LastWin,
2 => TxStrategy::VersionOnWrite,
3 => TxStrategy::VersionOnRead,
_ => panic!("something went wrong in tx strategy serialization: {}", val),
}
}
}
/// Persy configuration structure.
///
/// Lock are taken in order, should never go in deadlock so the default timeout is huge.
/// Current default values:
///
/// cache_size = 32M
/// cache_age_limit = 1 Day
/// transaction_lock_timeout = 1 Day
/// concurrent_modification_strategy = LastWin
///
#[derive(Debug, Clone)]
pub struct Config {
cache_size: u64,
cache_age_limit: Duration,
transaction_lock_timeout: Duration,
tx_strategy: TxStrategy,
}
impl Config {
pub fn new() -> Config {
Config {
cache_size: 32 * 1024 * 1024,
transaction_lock_timeout: Duration::new(24 * 60 * 60, 0),
cache_age_limit: Duration::from_secs(60 * 60 * 24),
tx_strategy: TxStrategy::LastWin,
}
}
pub fn cache_size(&self) -> u64 {
self.cache_size
}
pub fn cache_age_limit(&self) -> Duration {
self.cache_age_limit
}
pub fn transaction_lock_timeout(&self) -> &Duration {
&self.transaction_lock_timeout
}
pub fn change_cache_size(&mut self, cache_size: u64) {
self.cache_size = cache_size;
}
pub fn change_cache_age_limit(&mut self, cache_age_limit: Duration) {
self.cache_age_limit = cache_age_limit;
}
pub fn change_transaction_lock_timeout(&mut self, transaction_lock_timeout: Duration) {
self.transaction_lock_timeout = transaction_lock_timeout;
}
pub fn tx_strategy(&self) -> &TxStrategy {
&self.tx_strategy
}
pub fn change_tx_strategy(&mut self, strategy: TxStrategy) {
self.tx_strategy = strategy;
}
}
impl Default for Config {
fn default() -> Self {
Self::new()
}
}
/// Configure the parameters for the transaction on the begin of a new transaction.
#[derive(Clone, Default)]
pub struct TransactionConfig {
pub(crate) tx_strategy: Option<TxStrategy>,
pub(crate) background_sync: Option<bool>,
pub(crate) transaction_id: Option<TransactionId>,
}
impl TransactionConfig {
pub fn new() -> Self {
Self {
tx_strategy: None,
background_sync: None,
transaction_id: None,
}
}
/// Set the transaction concurrency checks, **experimental** use carefully
pub fn set_strategy(mut self, strategy: TxStrategy) -> Self {
self.tx_strategy = Some(strategy);
self
}
/// Set if the transaction will be fsync-ed in background or on the current thread
/// this option is available only if the "background_ops" feature is enabled
#[cfg(feature = "background_ops")]
pub fn set_background_sync(mut self, background: bool) -> Self {
self.background_sync = Some(background);
self
}
/// Set the transaction id to be used in case of crash recovery.
///
/// The id must be maximum 512 bytes of length
pub fn set_transaction_id(mut self, transaction_id: TransactionId) -> Self {
self.transaction_id = Some(transaction_id);
self
}
}