ledb 0.4.0

Lightweight embedded database built over LMDB
Documentation
use std::{
    collections::HashMap,
    path::{Path, PathBuf},
    sync::{Arc, Once, RwLock, Weak},
};

use super::{Result, ResultWrap, StorageData};

type Storages = Arc<RwLock<HashMap<PathBuf, Weak<StorageData>>>>;

static mut STORAGES: Option<Storages> = None;
static INITIALIZE_STORAGES: Once = Once::new();

#[inline]
fn init_storages() {
    INITIALIZE_STORAGES.call_once(|| unsafe {
        STORAGES = Some(Arc::new(RwLock::new(HashMap::new())));
    });
}

fn get_storages() -> Storages {
    init_storages();

    if let Some(storages) = unsafe { &STORAGES } {
        storages.clone()
    } else {
        unreachable!();
    }
}

pub(crate) struct Pool;

impl Pool {
    #[inline]
    pub(crate) fn get<P: AsRef<Path>>(path: P) -> Result<Option<Arc<StorageData>>> {
        let path = path.as_ref();
        let storages = get_storages();
        let map = storages.read().wrap_err()?;
        Ok(map.get(path).and_then(|env| env.upgrade()))
    }

    #[inline]
    pub(crate) fn put(path: PathBuf, storage: &Arc<StorageData>) -> Result<()> {
        let storages = get_storages();
        let mut map = storages.write().wrap_err()?;
        map.insert(path, Arc::downgrade(storage));
        Ok(())
    }

    #[inline]
    pub(crate) fn del<P: AsRef<Path>>(path: P) -> Result<()> {
        let path = path.as_ref();
        let storages = get_storages();
        let mut map = storages.write().wrap_err()?;
        map.remove(path);
        Ok(())
    }

    #[inline]
    pub(crate) fn lst() -> Result<Vec<PathBuf>> {
        let storages = get_storages();
        let map = storages.read().wrap_err()?;
        Ok(map.keys().cloned().collect())
    }
}