checkpoint
This commit is contained in:
parent
f7f166741b
commit
9c59507ea0
@ -32,6 +32,8 @@ struct RouteSpecDetail {
|
||||
last_checked_ts: Option<u64>,
|
||||
/// Directions this route is guaranteed to work in
|
||||
directions: DirectionSet,
|
||||
/// Reliability
|
||||
reliable: bool,
|
||||
}
|
||||
|
||||
/// The core representation of the RouteSpecStore that can be serialized
|
||||
@ -60,10 +62,19 @@ pub struct RouteSpecStore {
|
||||
cache: RouteSpecStoreCache,
|
||||
}
|
||||
|
||||
fn route_spec_to_hop_cache(spec: Arc<RouteSpec>) -> Vec<u8> {
|
||||
let mut cache: Vec<u8> = Vec::with_capacity(spec.hops.len() * DHT_KEY_LENGTH);
|
||||
for hop in spec.hops {
|
||||
cache.extend_from_slice(&hop.dial_info.node_id.key.bytes);
|
||||
fn route_hops_to_hop_cache(hops: &[DHTKey]) -> Vec<u8> {
|
||||
let mut cache: Vec<u8> = Vec::with_capacity(hops.len() * DHT_KEY_LENGTH);
|
||||
for hop in hops {
|
||||
cache.extend_from_slice(&hop.bytes);
|
||||
}
|
||||
cache
|
||||
}
|
||||
|
||||
/// get the hop cache key for a particular route permutation
|
||||
fn route_permutation_to_hop_cache(nodes: &[(DHTKey, NodeInfo)], perm: &[usize]) -> Vec<u8> {
|
||||
let mut cache: Vec<u8> = Vec::with_capacity(perm.len() * DHT_KEY_LENGTH);
|
||||
for n in perm {
|
||||
cache.extend_from_slice(&nodes[*n].0.bytes)
|
||||
}
|
||||
cache
|
||||
}
|
||||
@ -104,7 +115,7 @@ where
|
||||
return f(&permutation);
|
||||
}
|
||||
|
||||
// heaps algorithm
|
||||
// heaps algorithm, but skipping the first element
|
||||
fn heaps_permutation<F>(permutation: &mut [usize], size: usize, f: F) -> bool
|
||||
where
|
||||
F: FnMut(&[usize]) -> bool,
|
||||
@ -133,15 +144,6 @@ where
|
||||
heaps_permutation(&mut permutation, hop_count - 1, f)
|
||||
}
|
||||
|
||||
/// get the hop cache key for a particular route permutation
|
||||
fn route_permutation_to_hop_cache(nodes: &[(DHTKey, NodeInfo)], perm: &[usize]) -> Vec<u8> {
|
||||
let mut cache: Vec<u8> = Vec::with_capacity(perm.len() * DHT_KEY_LENGTH);
|
||||
for n in perm {
|
||||
cache.extend_from_slice(&nodes[*n].0.bytes)
|
||||
}
|
||||
cache
|
||||
}
|
||||
|
||||
impl RouteSpecStore {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
@ -329,15 +331,16 @@ impl RouteSpecStore {
|
||||
}
|
||||
|
||||
// Now go through nodes and try to build a route we haven't seen yet
|
||||
let mut route_nodes: Vec<usize> = Vec::with_capacity(hop_count);
|
||||
let mut route_nodes: Vec<usize> = Vec::new();
|
||||
let mut cache_key: Vec<u8> = Vec::new();
|
||||
for start in 0..(nodes.len() - hop_count) {
|
||||
// Try the permutations available starting with 'start'
|
||||
let done = with_route_permutations(hop_count, start, |permutation: &[usize]| {
|
||||
// Get the route cache key
|
||||
let key = route_permutation_to_hop_cache(&nodes, permutation);
|
||||
cache_key = route_permutation_to_hop_cache(&nodes, permutation);
|
||||
|
||||
// Skip routes we have already seen
|
||||
if self.cache.hop_cache.contains(&key) {
|
||||
if self.cache.hop_cache.contains(&cache_key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -417,18 +420,89 @@ impl RouteSpecStore {
|
||||
created_ts: cur_ts,
|
||||
last_checked_ts: None,
|
||||
directions,
|
||||
reliable,
|
||||
};
|
||||
|
||||
// Keep route in spec store
|
||||
self.content.details.insert(public_key, rsd);
|
||||
|
||||
// xxx insert into cache too
|
||||
if !self.cache.hop_cache.insert(cache_key) {
|
||||
panic!("route should never be inserted twice");
|
||||
}
|
||||
for h in &hops {
|
||||
self.cache
|
||||
.used_nodes
|
||||
.entry(*h)
|
||||
.and_modify(|e| *e += 1)
|
||||
.or_insert(1);
|
||||
}
|
||||
self.cache
|
||||
.used_end_nodes
|
||||
.entry(*hops.last().unwrap())
|
||||
.and_modify(|e| *e += 1)
|
||||
.or_insert(1);
|
||||
|
||||
Some(public_key)
|
||||
}
|
||||
|
||||
pub fn release_route(&mut self, spec: Arc<RouteSpec>) {}
|
||||
pub fn release_route(&mut self, public_key: DHTKey) {
|
||||
if let Some(detail) = self.content.details.remove(&public_key) {
|
||||
// Remove from hop cache
|
||||
let cache_key = route_hops_to_hop_cache(&detail.hops);
|
||||
if !self.cache.hop_cache.remove(&cache_key) {
|
||||
panic!("hop cache should have contained cache key");
|
||||
}
|
||||
// Remove from used nodes cache
|
||||
for h in &detail.hops {
|
||||
match self.cache.used_nodes.entry(*h) {
|
||||
std::collections::hash_map::Entry::Occupied(o) => {
|
||||
*o.get_mut() -= 1;
|
||||
if *o.get() == 0 {
|
||||
o.remove();
|
||||
}
|
||||
}
|
||||
std::collections::hash_map::Entry::Vacant(_) => {
|
||||
panic!("used_nodes cache should have contained hop");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove from end nodes cache
|
||||
match self.cache.used_nodes.entry(*detail.hops.last().unwrap()) {
|
||||
std::collections::hash_map::Entry::Occupied(o) => {
|
||||
*o.get_mut() -= 1;
|
||||
if *o.get() == 0 {
|
||||
o.remove();
|
||||
}
|
||||
}
|
||||
std::collections::hash_map::Entry::Vacant(_) => {
|
||||
panic!("used_nodes cache should have contained hop");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic!("can't release route that was never allocated");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn best_route(&mut self, reliable: bool) -> Arc<RouteSpec> {}
|
||||
pub fn best_route(
|
||||
&mut self,
|
||||
reliable: bool,
|
||||
min_hop_count: usize,
|
||||
max_hop_count: usize,
|
||||
directions: DirectionSet,
|
||||
) -> Option<DHTKey> {
|
||||
for detail in &self.content.details {
|
||||
if detail.1.reliable == reliable
|
||||
&& detail.1.hops.len() >= min_hop_count
|
||||
&& detail.1.hops.len() <= max_hop_count
|
||||
&& detail.1.directions.is_subset(directions)
|
||||
{
|
||||
return Some(*detail.0);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// xxx add route compiler here
|
||||
///
|
||||
|
||||
/// Mark route as published
|
||||
/// When first deserialized, routes must be re-published in order to ensure they remain
|
||||
|
Loading…
Reference in New Issue
Block a user