#![allow(dead_code)]
use chunk_store::ChunkStore;
use routing_types::*;
pub struct PmidNode {
chunk_store_ : ChunkStore
}
impl PmidNode {
pub fn new() -> PmidNode {
PmidNode { chunk_store_: ChunkStore::with_max_disk_usage(1073741824), } }
pub fn handle_get(&self, name: NameType) ->Result<Vec<MethodCall>, ResponseError> {
info!("pmid_node getting {:?}", name);
let data = self.chunk_store_.get(name);
if data.len() == 0 {
return Err(ResponseError::Abort);
}
let sd : ImmutableData = try!(::routing::utils::decode(&data));
info!("pmid_node returning {:?}", name);
Ok(vec![MethodCall::Reply { data: Data::ImmutableData(sd) }])
}
pub fn handle_put(&mut self, incoming_data : Data) ->Result<Vec<MethodCall>, ResponseError> {
info!("pmid_node storing {:?}", incoming_data.name());
let immutable_data = match incoming_data.clone() {
Data::ImmutableData(data) => { data }
_ => { return Err(ResponseError::InvalidRequest(incoming_data)); }
};
let data = try!(::routing::utils::encode(&immutable_data));
let data_name_and_remove_sacrificial = match *immutable_data.get_type_tag() {
ImmutableDataType::Normal => (immutable_data.name(), true),
_ => (immutable_data.name(), false),
};
if self.chunk_store_.has_disk_space(data.len()) {
self.chunk_store_.put(data_name_and_remove_sacrificial.0, data);
return Ok(vec![]);
}
if !data_name_and_remove_sacrificial.1 {
return Err(ResponseError::InvalidRequest(incoming_data))
}
let required_space = data.len() - (self.chunk_store_.max_disk_usage() - self.chunk_store_.current_disk_usage());
let names = self.chunk_store_.names();
for name in names.iter() {
let fetched_data = self.chunk_store_.get(name.clone());
let parsed_data : ImmutableData = try!(::routing::utils::decode(&fetched_data));
match *parsed_data.get_type_tag() {
ImmutableDataType::Sacrificial => {
if fetched_data.len() > required_space {
self.chunk_store_.delete(name.clone());
self.chunk_store_.put(data_name_and_remove_sacrificial.0, data);
return Err(ResponseError::FailedRequestForData(Data::ImmutableData(immutable_data)));
}
},
_ => {}
}
}
Err(ResponseError::InvalidRequest(incoming_data))
}
}
#[cfg(test)]
mod test {
use super::*;
use routing_types::*;
#[test]
fn handle_put_get() {
let mut pmid_node = PmidNode::new();
let value = generate_random_vec_u8(1024);
let im_data = ImmutableData::new(ImmutableDataType::Normal, value);
{
let put_result = pmid_node.handle_put(Data::ImmutableData(im_data.clone()));
assert_eq!(put_result.is_ok(), true);
let calls = put_result.ok().unwrap();
assert_eq!(calls.len(), 0);
}
{
let get_result = pmid_node.handle_get(im_data.name());
assert_eq!(get_result.is_err(), false);
let mut calls = get_result.ok().unwrap();
assert_eq!(calls.len(), 1);
match calls.remove(0) {
MethodCall::Reply { data } => {
match data {
Data::ImmutableData(fetched_im_data) => {
assert_eq!(fetched_im_data, im_data);
}
_ => panic!("Unexpected"),
}
}
_ => panic!("Unexpected"),
}
}
}
}