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>> {
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!(),
}
}