checkpoint
This commit is contained in:
		@@ -32,6 +32,8 @@ struct RouteSpecDetail {
 | 
				
			|||||||
    last_checked_ts: Option<u64>,
 | 
					    last_checked_ts: Option<u64>,
 | 
				
			||||||
    /// Directions this route is guaranteed to work in
 | 
					    /// Directions this route is guaranteed to work in
 | 
				
			||||||
    directions: DirectionSet,
 | 
					    directions: DirectionSet,
 | 
				
			||||||
 | 
					    /// Reliability
 | 
				
			||||||
 | 
					    reliable: bool,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// The core representation of the RouteSpecStore that can be serialized
 | 
					/// The core representation of the RouteSpecStore that can be serialized
 | 
				
			||||||
@@ -60,10 +62,19 @@ pub struct RouteSpecStore {
 | 
				
			|||||||
    cache: RouteSpecStoreCache,
 | 
					    cache: RouteSpecStoreCache,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn route_spec_to_hop_cache(spec: Arc<RouteSpec>) -> Vec<u8> {
 | 
					fn route_hops_to_hop_cache(hops: &[DHTKey]) -> Vec<u8> {
 | 
				
			||||||
    let mut cache: Vec<u8> = Vec::with_capacity(spec.hops.len() * DHT_KEY_LENGTH);
 | 
					    let mut cache: Vec<u8> = Vec::with_capacity(hops.len() * DHT_KEY_LENGTH);
 | 
				
			||||||
    for hop in spec.hops {
 | 
					    for hop in hops {
 | 
				
			||||||
        cache.extend_from_slice(&hop.dial_info.node_id.key.bytes);
 | 
					        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
 | 
					    cache
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -104,7 +115,7 @@ where
 | 
				
			|||||||
        return f(&permutation);
 | 
					        return f(&permutation);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // heaps algorithm
 | 
					    // heaps algorithm, but skipping the first element
 | 
				
			||||||
    fn heaps_permutation<F>(permutation: &mut [usize], size: usize, f: F) -> bool
 | 
					    fn heaps_permutation<F>(permutation: &mut [usize], size: usize, f: F) -> bool
 | 
				
			||||||
    where
 | 
					    where
 | 
				
			||||||
        F: FnMut(&[usize]) -> bool,
 | 
					        F: FnMut(&[usize]) -> bool,
 | 
				
			||||||
@@ -133,15 +144,6 @@ where
 | 
				
			|||||||
    heaps_permutation(&mut permutation, hop_count - 1, f)
 | 
					    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 {
 | 
					impl RouteSpecStore {
 | 
				
			||||||
    pub fn new() -> Self {
 | 
					    pub fn new() -> Self {
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
@@ -329,15 +331,16 @@ impl RouteSpecStore {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Now go through nodes and try to build a route we haven't seen yet
 | 
					        // 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) {
 | 
					        for start in 0..(nodes.len() - hop_count) {
 | 
				
			||||||
            // Try the permutations available starting with 'start'
 | 
					            // Try the permutations available starting with 'start'
 | 
				
			||||||
            let done = with_route_permutations(hop_count, start, |permutation: &[usize]| {
 | 
					            let done = with_route_permutations(hop_count, start, |permutation: &[usize]| {
 | 
				
			||||||
                // Get the route cache key
 | 
					                // 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
 | 
					                // Skip routes we have already seen
 | 
				
			||||||
                if self.cache.hop_cache.contains(&key) {
 | 
					                if self.cache.hop_cache.contains(&cache_key) {
 | 
				
			||||||
                    return false;
 | 
					                    return false;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -417,18 +420,89 @@ impl RouteSpecStore {
 | 
				
			|||||||
            created_ts: cur_ts,
 | 
					            created_ts: cur_ts,
 | 
				
			||||||
            last_checked_ts: None,
 | 
					            last_checked_ts: None,
 | 
				
			||||||
            directions,
 | 
					            directions,
 | 
				
			||||||
 | 
					            reliable,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Keep route in spec store
 | 
				
			||||||
        self.content.details.insert(public_key, rsd);
 | 
					        self.content.details.insert(public_key, rsd);
 | 
				
			||||||
 | 
					        if !self.cache.hop_cache.insert(cache_key) {
 | 
				
			||||||
        // xxx insert into cache too
 | 
					            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)
 | 
					        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
 | 
					    /// Mark route as published
 | 
				
			||||||
    /// When first deserialized, routes must be re-published in order to ensure they remain
 | 
					    /// When first deserialized, routes must be re-published in order to ensure they remain
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user