use core::fmt;
use std::collections::HashMap;
use std::fmt::Debug;
use std::hash::{BuildHasher, BuildHasherDefault, DefaultHasher, Hasher};
use crate::circularbtreemap::CircularBTreeMap;
use crate::Transaction;
pub trait Identifier {
fn identify(&self) -> usize;
}
#[derive(Debug)]
pub enum LdbError {
NodeDoesNotExist,
NodeAlreadyExists,
NoInstances,
}
impl fmt::Display for LdbError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}
impl std::error::Error for LdbError {}
pub struct LDB {
hash_tree: CircularBTreeMap<u128>,
hash_nodes_map: HashMap<u128, u128>,
hash_replicas_map: Vec<(u128, Vec<u128>)>,
hasher_builder: Box<dyn BuildHasher<Hasher = DefaultHasher> + Send + Sync>,
hash_bit_count: u128,
hash_max: u128,
virtual_instances: usize,
}
unsafe impl Send for LDB {}
unsafe impl Sync for LDB {}
impl LDB {
pub fn new(hash_bit_count: u128, virtual_instances: usize) -> Self {
Self {
hash_tree: CircularBTreeMap::new(),
hash_nodes_map: HashMap::new(),
hash_replicas_map: Vec::new(),
hasher_builder: Box::new(BuildHasherDefault::<DefaultHasher>::default()),
hash_bit_count,
hash_max: 1 << hash_bit_count,
virtual_instances,
}
}
pub fn node_exists<Q: Identifier>(&self, identifier: &Q) -> bool
{
let identifier = &(identifier.identify() as u128);
for (k,_) in &self.hash_replicas_map
{
if k==identifier
{
return true;
}
}
return false;
}
fn rev_hash_node(&self,hash: &u128)->u128
{
self.hash_nodes_map.get(hash).unwrap().clone()
}
pub fn set_hasher<BH>(&mut self, hasher_builder: BH)
where
BH: BuildHasher<Hasher = DefaultHasher> + Send + Sync + 'static,
{
self.hasher_builder = Box::new(hasher_builder);
}
pub fn add_node<Q: Identifier>(&mut self, node: Q) -> Result<Option<Vec<Transaction<u128>>>,LdbError>
{
let value = node.identify() as u128;
if self.node_exists(&node)
{
return Err(LdbError::NodeAlreadyExists);
}
let mut vec = Vec::new();
let mut carriers = Vec::new();
for i in 0..self.virtual_instances {
let mut hasher = self.hasher_builder.build_hasher();
hasher.write_u128(value as u128);
hasher.write_u128(i as u128);
let hashed_value = hasher.finish() as u128 % self.hash_max;
if !self.hash_nodes_map.contains_key(&hashed_value){
vec.push(hashed_value);
self.hash_nodes_map.insert( hashed_value,value);
}
else {continue;}
match self.hash_tree.insert_node(hashed_value)
{
Ok((x,y))=>
{
if self.rev_hash_node(&x)==value
{
continue;
}
let x = Transaction::new( self.rev_hash_node(&x),
value,
y,
hashed_value);
carriers.push(x);
},
Err(_)=>()
}
}
self.hash_replicas_map.push((value,vec));
Ok(Some(carriers))
}
pub fn key(&mut self,key: &str) ->Result<(u128,u128),LdbError>
{
let mut hasher = self.hasher_builder.build_hasher();
hasher.write(key.as_bytes());
let hashed_value = hasher.finish() as u128 % self.hash_max;
match self.hash_tree.val_in_node(&hashed_value)
{
Ok(x)=>
{
Ok((self.rev_hash_node(&x),hashed_value))
},
Err(_)=>{
Err(LdbError::NoInstances)
}
}
}
pub fn delete_node<Q:Identifier>(&mut self,node: Q) ->Result<Option<Vec<Transaction<u128>>>,LdbError>
{
let value = node.identify() as u128;
if !self.node_exists(&node)
{
return Err(LdbError::NodeDoesNotExist)
}
let mut replicas= Vec::new();
let mut vec = Vec::new();
for i in 0..self.virtual_instances
{
if self.hash_replicas_map[i].0 == value
{
replicas = self.hash_replicas_map.remove(i).1;
break;
}
}
if replicas.is_empty()
{
return Ok(None);
}
for replica in replicas
{
match self.hash_tree.delete_node(&replica)
{
Ok((x,y))=> {
if self.rev_hash_node(&y)!=value
{
vec.push(Transaction::new(value,self.rev_hash_node(&y),x,replica));
}},
Err(_) =>()
}
self.hash_nodes_map.remove(&replica);
}
if vec.is_empty(){return Ok(None);}
Ok(Some(vec))
}
fn add_instances(&mut self,count:usize) ->Vec<Transaction<u128>>
{
let mut vec = Vec::new();
for node in &mut self.hash_replicas_map
{
for i in self.virtual_instances..count
{
let mut hasher = self.hasher_builder.build_hasher();
hasher.write_u128(node.0);
hasher.write_u128(i as u128);
let hashed_value = hasher.finish() as u128 % self.hash_max;
if !self.hash_nodes_map.contains_key(&hashed_value){
node.1.push(hashed_value);
self.hash_nodes_map.insert(hashed_value, node.0);
}
else {continue;}
match self.hash_tree.insert_node(hashed_value)
{
Ok((x,y))=>
{
if self.hash_nodes_map.get(&x).unwrap().clone()==node.0 {continue;}
let x = Transaction::new( self.hash_nodes_map.get(&x).unwrap().clone(),
node.0,
y,
hashed_value);
vec.push(x);
},
Err(_) => ()
}
}
}
vec
}
fn remove_intances(&mut self,count:usize)->Vec<Transaction<u128>>
{
let mut vec = Vec::new();
for node in &mut self.hash_replicas_map
{
if node.1.len()<2
{
continue;
}
for i in (count)..self.virtual_instances
{
let value = node.1.pop().unwrap();
match self.hash_tree.delete_node(&value)
{
Ok((x,y))=>
{
if self.hash_nodes_map.get(&y).unwrap().clone()==node.0
{
continue;
}
vec.push(Transaction::new(node.0,self.hash_nodes_map.get(&y).unwrap().clone(),x,value));
},
Err(_) => ()
}
self.hash_nodes_map.remove(&value);
}
}
vec
}
pub fn set_virtual_instances(&mut self,count: usize) -> Option<Vec<Transaction<u128>>>
{
if (count == self.virtual_instances) | (count == 0)
{
return None;
}
let mut vec= Vec::new();
if count > self.virtual_instances
{
vec = self.add_instances(count);
}
else {
vec = self.remove_intances(count);
}
self.virtual_instances = count;
if vec.is_empty() {return None;}
return Some(vec);
}
pub fn print(&self)
{
println!("*******************************************************************************************************************************************************************************************************************************************************************************************************");
println!("\nLDB:\n");
println!("\n\nhash-tree:");
self.hash_tree.print();
println!("\n\nhash-nodes-map:");
for (key, value) in &self.hash_nodes_map {
println!("{:?}: {:?}", key, value);
}
println!("\n\nhash_replicas_map:");
for (key, values) in &self.hash_replicas_map {
println!("{:?}: {:?}", key, values);
}
println!("*******************************************************************************************************************************************************************************************************************************************************************************************************");
}
}