redb

Enum Durability

Source
#[non_exhaustive]
pub enum Durability { None, Eventual, Immediate, Paranoid, }

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

None

Commits with this durability level will not be persisted to disk unless followed by a commit with a higher durability level.

Note: Pages are only freed during commits with higher durability levels. Exclusively using this durability level will result in rapid growth of the database file.

§

Eventual

Commits with this durability level have been queued for persitance to disk, and should be persistent some time after WriteTransaction::commit returns.

§

Immediate

Commits with this durability level are guaranteed to be persistent as soon as WriteTransaction::commit returns.

Data is written with checksums, with the following commit algorithm:

  1. Update the inactive commit slot with the new database state
  2. Flip the god byte primary bit to activate the newly updated commit slot
  3. Call fsync to ensure all writes have been persisted to disk

When opening the database after a crash, the most recent of the two commit slots with a valid checksum is used.

Security considerations: The checksum used is xxhash, a fast, non-cryptographic hash function with close to perfect collision resistance when used with non-malicious input. An attacker with an extremely high degree of control over the database’s workload, including the ability to cause the database process to crash, can cause invalid data to be written with a valid checksum, leaving the database in an invalid, attacker-controlled state.

§

Paranoid

Commits with this durability level have the same gaurantees as Durability::Immediate

Additionally, aata is written with the following 2-phase commit algorithm:

  1. Update the inactive commit slot with the new database state
  2. Call fsync to ensure the database slate and commit slot update have been persisted
  3. Flip the god byte primary bit to activate the newly updated commit slot
  4. Call fsync to ensure the write to the god byte has been persisted

This mitigates a theoretical attack where an attacker who

  1. can control the order in which pages are flushed to disk
  2. can introduce crashes during fsync(),
  3. has knowledge of the database file contents, and
  4. can include arbitrary data in a write transaction could cause a transaction to partially commit (some but not all of the data is written). This is described in the design doc in futher detail.

Security considerations: Many hard disk drives and SSDs do not actually guarantee that data has been persisted to disk after calling fsync. Even with this commit level, an attacker with a high degree of control over the database’s workload, including the ability to cause the database process to crash, can cause the database to crash with the god byte primary bit pointing to an invalid commit slot, leaving the database in an invalid, potentially attacker-controlled state.

Trait Implementations§

Source§

impl Clone for Durability

Source§

fn clone(&self) -> Durability

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Durability

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Copy for Durability

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dst: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.

Layout§

Note: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...) attributes. Please see the Rust Reference's “Type Layout” chapter for details on type layout guarantees.

Size: 1 byte

Size for each variant:

  • None: 0 bytes
  • Eventual: 0 bytes
  • Immediate: 0 bytes
  • Paranoid: 0 bytes