updb 0.1.0

An embedded, immutable, in-memory, key-value database engine
Documentation
#![deny(unsafe_code)]

use std::sync::Arc;

use arc_swap::ArcSwap;
use imbl::OrdMap;
use tokio::sync::OwnedMutexGuard;

use crate::error::Error;

pub struct Tx<K, V> {
    pub(crate) closed: bool,
    pub(crate) writable: bool,
    pub(crate) imm_data: OrdMap<K, V>,
    pub(crate) lst_data: Arc<ArcSwap<OrdMap<K, V>>>,
    pub(crate) writ_mux: Option<OwnedMutexGuard<()>>,
}

impl<K, V> Tx<K, V>
where
    K: Ord + Clone,
    V: Eq + Clone,
{
    pub(crate) fn new(
        data_ptr: Arc<ArcSwap<OrdMap<K, V>>>,
        writable: bool,
        guard: Option<OwnedMutexGuard<()>>,
    ) -> Tx<K, V> {
        Tx {
            writable,
            closed: false,
            imm_data: (*(*data_ptr.load())).clone(),
            lst_data: data_ptr.clone(),
            writ_mux: guard,
        }
    }

    pub fn closed(&self) -> bool {
        self.closed
    }

    pub fn rollback(&mut self) -> Result<(), Error> {
        if self.closed {
            return Err(Error::TxClosed);
        }

        self.closed = true;

        if let Some(lock) = &self.writ_mux.take() {
            drop(lock);
        }

        Ok(())
    }

    pub fn commit(&mut self) -> Result<(), Error> {
        if self.closed {
            return Err(Error::TxClosed);
        }

        if !self.writable {
            return Err(Error::TxNotWritable);
        }

        self.closed = true;

        self.lst_data.store(Arc::new(self.imm_data.clone()));

        if let Some(lock) = &self.writ_mux.take() {
            drop(lock);
        }

        Ok(())
    }

    pub fn exists(&self, key: K) -> Result<bool, Error> {
        if self.closed {
            return Err(Error::TxClosed);
        }

        Ok(self.imm_data.contains_key(&key))
    }

    pub fn get(&self, key: K) -> Result<Option<V>, Error> {
        if self.closed {
            return Err(Error::TxClosed);
        }

        Ok(self.imm_data.get(&key).cloned())
    }

    pub fn set(&mut self, key: K, value: V) -> Result<(), Error> {
        if self.closed {
            return Err(Error::TxClosed);
        }

        if !self.writable {
            return Err(Error::TxNotWritable);
        }

        self.imm_data.insert(key, value);

        Ok(())
    }

    pub fn del(&mut self, key: K) -> Result<(), Error> {
        if self.closed {
            return Err(Error::TxClosed);
        }

        if !self.writable {
            return Err(Error::TxNotWritable);
        }

        self.imm_data.remove(&key);

        Ok(())
    }
}