#![allow(dead_code)]
use cbor;
use rustc_serialize::Encodable;
use std::collections::HashMap;
use routing_types::*;
use transfer_parser::transfer_tags::DATA_MANAGER_ACCOUNT_TAG;
type Identity = NameType; type PmidNode = NameType;
pub type PmidNodes = Vec<PmidNode>;
#[derive(RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Clone)]
pub struct DataManagerSendable {
name: NameType,
data_holders: PmidNodes,
preserialised_content: Vec<u8>,
has_preserialised_content: bool,
}
impl DataManagerSendable {
pub fn new(name: NameType, data_holders: PmidNodes) -> DataManagerSendable {
DataManagerSendable {
name: name,
data_holders: data_holders,
preserialised_content: Vec::new(),
has_preserialised_content: false,
}
}
pub fn with_content(name: NameType, preserialised_content: Vec<u8>) -> DataManagerSendable {
DataManagerSendable {
name: name,
data_holders: PmidNodes::new(),
preserialised_content: preserialised_content,
has_preserialised_content: true,
}
}
pub fn get_data_holders(&self) -> PmidNodes {
self.data_holders.clone()
}
}
impl Sendable for DataManagerSendable {
fn name(&self) -> NameType {
self.name.clone()
}
fn type_tag(&self) -> u64 {
DATA_MANAGER_ACCOUNT_TAG
}
fn serialised_contents(&self) -> Vec<u8> {
if self.has_preserialised_content {
self.preserialised_content.clone()
} else {
match ::routing::utils::encode(&self) {
Ok(result) => result,
Err(_) => Vec::new()
}
}
}
fn refresh(&self)->bool {
true
}
fn merge(&self, responses: Vec<Box<Sendable>>) -> Option<Box<Sendable>> {
if responses.len() == GROUP_SIZE - 1 {
return None;
}
let mut stats = Vec::<(PmidNodes, u64)>::new();
for it in responses.iter() {
let wrapper =
match ::routing::utils::decode::<DataManagerSendable>(&it.serialised_contents()) {
Ok(result) => result,
Err(_) => { continue }
};
let push_in_vec = match stats.iter_mut().find(|a| a.0 == wrapper.get_data_holders()) {
Some(find_res) => { find_res.1 += 1; false }
None => { true }
};
if push_in_vec {
stats.push((wrapper.get_data_holders(), 1));
}
}
stats.sort_by(|a, b| b.1.cmp(&a.1));
let (pmids, count) = stats[0].clone();
if count < (GROUP_SIZE as u64 + 1) / 2 {
return Some(Box::new(DataManagerSendable::new(self.name.clone(), pmids)));
}
None
}
}
pub struct DataManagerDatabase {
storage : HashMap<Identity, PmidNodes>,
pub close_grp_from_churn: Vec<NameType>,
pub temp_storage_after_churn: HashMap<NameType, PmidNodes>,
}
impl DataManagerDatabase {
pub fn new () -> DataManagerDatabase {
DataManagerDatabase {
storage: HashMap::with_capacity(10000),
close_grp_from_churn: Vec::new(),
temp_storage_after_churn: HashMap::new(),
}
}
pub fn exist(&mut self, name : &Identity) -> bool {
self.storage.contains_key(name)
}
pub fn put_pmid_nodes(&mut self, name : &Identity, pmid_nodes: PmidNodes) {
let _ = self.storage.entry(name.clone()).or_insert(pmid_nodes.clone());
}
pub fn add_pmid_node(&mut self, name : &Identity, pmid_node: PmidNode) {
let nodes = self.storage.entry(name.clone()).or_insert(vec![pmid_node.clone()]);
if !nodes.contains(&pmid_node) {
nodes.push(pmid_node);
}
}
pub fn remove_pmid_node(&mut self, name : &Identity, pmid_node: PmidNode) {
if !self.storage.contains_key(name) {
return;
}
let nodes = self.storage.entry(name.clone()).or_insert(vec![]);
for i in 0..nodes.len() {
if nodes[i] == pmid_node {
let _ = nodes.remove(i);
break;
}
}
}
pub fn get_pmid_nodes(&mut self, name : &Identity) -> PmidNodes {
match self.storage.get(&name) {
Some(entry) => entry.clone(),
None => Vec::<PmidNode>::new()
}
}
pub fn handle_account_transfer(&mut self, account_wrapper : &DataManagerSendable) {
let _ = self.storage.remove(&account_wrapper.name());
let _ = self.storage.insert(account_wrapper.name(), account_wrapper.get_data_holders());
}
pub fn retrieve_all_and_reset(&mut self, close_group: &mut Vec<NameType>) -> Vec<MethodCall> {
self.temp_storage_after_churn = self.storage.clone();
let mut close_grp_already_stored = false;
for it in self.storage.iter_mut() {
let mut new_pmid_nodes = Vec::<NameType>::with_capacity(it.1.len());
for vec_it in it.1.iter() {
if close_group.iter().find(|a| **a == *vec_it).is_some() {
new_pmid_nodes.push(vec_it.clone());
}
}
if new_pmid_nodes.len() < 3 && !close_grp_already_stored {
self.close_grp_from_churn = close_group.clone();
close_grp_already_stored = true;
}
*it.1 = new_pmid_nodes;
}
let mut actions = Vec::<MethodCall>::new();
for (key, value) in self.storage.iter() {
match self.temp_storage_after_churn.get(key) {
Some(result) => { if result.len() < 3 {
actions.push(MethodCall::Get {
location: Authority::ManagedNode((*key).clone()),
data_request: DataRequest::ImmutableData((*key).clone(), ImmutableDataType::Normal)
});
}}
None => continue
}
let data_manager_sendable = DataManagerSendable::new((*key).clone(), (*value).clone());
let mut encoder = cbor::Encoder::from_memory();
if encoder.encode(&[data_manager_sendable.clone()]).is_ok() {
actions.push(MethodCall::Refresh {
type_tag: DATA_MANAGER_ACCOUNT_TAG,
from_group: data_manager_sendable.name(),
payload: encoder.as_bytes().to_vec()
});
}
}
self.storage.clear();
actions
}
}
#[cfg(test)]
mod test {
use super::*;
use routing_types::*;
#[test]
fn exist() {
let mut db = DataManagerDatabase::new();
let value = generate_random_vec_u8(1024);
let data = ImmutableData::new(ImmutableDataType::Normal, value);
let mut pmid_nodes : Vec<NameType> = vec![];
for _ in 0..4 {
pmid_nodes.push(NameType(vector_as_u8_64_array(generate_random_vec_u8(64))));
}
let data_name = data.name();
assert_eq!(db.exist(&data_name), false);
db.put_pmid_nodes(&data_name, pmid_nodes);
assert_eq!(db.exist(&data_name), true);
}
#[test]
fn put() {
let mut db = DataManagerDatabase::new();
let value = generate_random_vec_u8(1024);
let data = ImmutableData::new(ImmutableDataType::Normal, value);
let data_name = data.name();
let mut pmid_nodes : Vec<NameType> = vec![];
for _ in 0..4 {
pmid_nodes.push(NameType(vector_as_u8_64_array(generate_random_vec_u8(64))));
}
let result = db.get_pmid_nodes(&data_name);
assert_eq!(result.len(), 0);
db.put_pmid_nodes(&data_name, pmid_nodes.clone());
let result = db.get_pmid_nodes(&data_name);
assert_eq!(result.len(), pmid_nodes.len());
}
#[test]
fn remove_pmid() {
let mut db = DataManagerDatabase::new();
let value = generate_random_vec_u8(1024);
let data = ImmutableData::new(ImmutableDataType::Normal, value);
let data_name = data.name();
let mut pmid_nodes : Vec<NameType> = vec![];
for _ in 0..4 {
pmid_nodes.push(NameType(vector_as_u8_64_array(generate_random_vec_u8(64))));
}
db.put_pmid_nodes(&data_name, pmid_nodes.clone());
let result = db.get_pmid_nodes(&data_name);
assert_eq!(result, pmid_nodes);
db.remove_pmid_node(&data_name, pmid_nodes[0].clone());
let result = db.get_pmid_nodes(&data_name);
assert_eq!(result.len(), 3);
for index in 0..result.len() {
assert!(result[index] != pmid_nodes[0]);
}
}
#[test]
fn replace_pmids() {
let mut db = DataManagerDatabase::new();
let value = generate_random_vec_u8(1024);
let data = ImmutableData::new(ImmutableDataType::Normal, value);
let data_name = data.name();
let mut pmid_nodes : Vec<NameType> = vec![];
let mut new_pmid_nodes : Vec<NameType> = vec![];
for _ in 0..4 {
pmid_nodes.push(NameType(vector_as_u8_64_array(generate_random_vec_u8(64))));
new_pmid_nodes.push(NameType(vector_as_u8_64_array(generate_random_vec_u8(64))));
}
db.put_pmid_nodes(&data_name, pmid_nodes.clone());
let result = db.get_pmid_nodes(&data_name);
assert_eq!(result, pmid_nodes);
assert!(result != new_pmid_nodes);
for index in 0..4 {
db.remove_pmid_node(&data_name, pmid_nodes[index].clone());
db.add_pmid_node(&data_name, new_pmid_nodes[index].clone());
}
let result = db.get_pmid_nodes(&data_name);
assert_eq!(result, new_pmid_nodes);
assert!(result != pmid_nodes);
}
#[test]
fn handle_account_transfer() {
let mut db = DataManagerDatabase::new();
let value = generate_random_vec_u8(1024);
let data = ImmutableData::new(ImmutableDataType::Normal, value);
let data_name = data.name();
let mut pmid_nodes : Vec<NameType> = vec![];
for _ in 0..4 {
pmid_nodes.push(NameType(vector_as_u8_64_array(generate_random_vec_u8(64))));
}
db.put_pmid_nodes(&data_name, pmid_nodes.clone());
assert_eq!(db.get_pmid_nodes(&data_name).len(), pmid_nodes.len());
db.handle_account_transfer(&DataManagerSendable::new(data_name.clone(), vec![]));
assert_eq!(db.get_pmid_nodes(&data_name).len(), 0);
}
}