mycelium_core 0.1.1

Library for Mycelium DDM
Documentation
use std::collections::HashMap;
use std::fs;
use std::path::PathBuf;

use crate::ephemeral::{Data, Tag};
use crate::persistence::SaveScope;
use crate::Db;
use mycelium_command::node::Node;

use rayon::prelude::*;

pub(crate) fn add(
    stew: &Db,
    item: &[u8],
    tag: &str,
) -> Result<[u8; 16], Box<dyn std::error::Error>> {
    let node = Node::new(stew.system.db_id, item);
    p_append(stew, tag, node)
}

pub(crate) fn p_append(
    stew: &Db,
    tag: &str,
    node: Node,
) -> Result<[u8; 16], Box<dyn std::error::Error>> {
    validate_tag(stew, tag)?;
    match stew.primary.write() {
        Ok(mut lock) => {
            let tag = match lock.get_mut(tag) {
                Some(tag_table) => tag_table,
                None => panic!("Failed to create container"),
            };

            let id = tag.get_append_page(node.get_size()).add(node.clone());
            tag.add_index(node.get_id(), id);
            Ok(node.get_id())
        }
        Err(e) => panic!(format!("Poison RwLock core::p_append(): {:?}", e)),
    }
}

pub(crate) fn validate_tag(stew: &Db, tag: &str) -> Result<(), Box<dyn std::error::Error>> {
    // Get tag structure or create a new one. It is valid if it
    // exists.
    let mut new_tag = false;
    match stew.primary.read() {
        Ok(lock) => {
            if !lock.contains_key(tag) {
                new_tag = true;
            }
        }
        Err(e) => panic!(format!("Poison mutex core::p_append(): {:?}", e)),
    }
    if new_tag {
        create_tag(stew, tag)?
    }
    Ok(())
}

pub(crate) fn create_tag(db: &Db, tag: &str) -> Result<(), Box<dyn std::error::Error>> {
    match db.primary.write() {
        Ok(mut tag_map) => {
            let mut tag_working_dir = db.working_dir.to_path_buf();
            tag_working_dir.push(tag);
            tag_map.insert(
                tag.to_string(),
                Tag::new(tag, tag_working_dir, db.config.get_max_page_size()),
            );
        }
        Err(e) => panic!("Poison mutex core::create_tag: {:?}", e),
    }

    Ok(())
}

pub(crate) fn load_tag_containers(
    working_dir: &PathBuf,
    max_page_size: usize,
) -> Result<Data, std::io::Error> {
    let mut map = HashMap::new();

    if working_dir.exists() {
        let directories = fs::read_dir(working_dir)?;
        for item in directories {
            let item = item?;
            let path = item.path();

            if path.is_dir() {
                let parts = path.components();
                let tag = parts.last().unwrap().as_os_str().to_str().unwrap();

                map.insert(String::from(tag), Tag::new(tag, item.path(), max_page_size));
            }
        }
    }

    Ok(std::sync::RwLock::new(map))
}

pub(crate) fn save_all(db: &Db) -> Result<(), std::io::Error> {
    save_pages(db, SaveScope::All);
    Ok(())
}

fn save_pages(db: &Db, scope: SaveScope) {
    match scope {
        SaveScope::All => {
            let primary = db.primary.read().expect("core::save_pages::All lock()");
            primary.par_iter().for_each(|x| match x.1.save_all() {
                Ok(_) => (),
                Err(e) => error!("Error: {:?}", e),
            });
        }
        SaveScope::One(_item) => unimplemented!(),
        SaveScope::Some(_items) => unimplemented!(),
        SaveScope::Tag(_tag) => unimplemented!(),
    }
}