Garage v0.9 #473
2 changed files with 64 additions and 81 deletions
|
@ -195,8 +195,8 @@ impl ClusterLayout {
|
||||||
.collect::<Vec<(String, usize)>>();
|
.collect::<Vec<(String, usize)>>();
|
||||||
//We create an indexing of the zones
|
//We create an indexing of the zones
|
||||||
let mut zone_id = HashMap::<String, usize>::new();
|
let mut zone_id = HashMap::<String, usize>::new();
|
||||||
for i in 0..part_per_zone_vec.len() {
|
for (i, ppz) in part_per_zone_vec.iter().enumerate() {
|
||||||
zone_id.insert(part_per_zone_vec[i].0.clone(), i);
|
zone_id.insert(ppz.0.clone(), i);
|
||||||
}
|
}
|
||||||
|
|
||||||
//We compute a candidate for the new partition to zone
|
//We compute a candidate for the new partition to zone
|
||||||
|
@ -212,7 +212,7 @@ impl ClusterLayout {
|
||||||
let mut node_assignation = vec![vec![None; self.replication_factor]; nb_partitions];
|
let mut node_assignation = vec![vec![None; self.replication_factor]; nb_partitions];
|
||||||
//We will decrement part_per_nod to keep track of the number
|
//We will decrement part_per_nod to keep track of the number
|
||||||
//of partitions that we still have to associate.
|
//of partitions that we still have to associate.
|
||||||
let mut part_per_nod = part_per_nod.clone();
|
let mut part_per_nod = part_per_nod;
|
||||||
|
|
||||||
//We minimize the distance to the former assignation(if any)
|
//We minimize the distance to the former assignation(if any)
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ impl ClusterLayout {
|
||||||
&& part_per_nod[*id] > 0
|
&& part_per_nod[*id] > 0
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
assert!(possible_nodes.len() > 0);
|
assert!(!possible_nodes.is_empty());
|
||||||
//We randomly pick a node
|
//We randomly pick a node
|
||||||
if let Some(nod) = possible_nodes.choose(&mut rng) {
|
if let Some(nod) = possible_nodes.choose(&mut rng) {
|
||||||
node_assignation[i][j] = Some(*nod);
|
node_assignation[i][j] = Some(*nod);
|
||||||
|
@ -277,12 +277,12 @@ impl ClusterLayout {
|
||||||
|
|
||||||
//We write the assignation in the 1D table
|
//We write the assignation in the 1D table
|
||||||
self.ring_assignation_data = Vec::<CompactNodeType>::new();
|
self.ring_assignation_data = Vec::<CompactNodeType>::new();
|
||||||
for i in 0..nb_partitions {
|
for ass in node_assignation {
|
||||||
for j in 0..self.replication_factor {
|
for nod in ass {
|
||||||
if let Some(id) = node_assignation[i][j] {
|
if let Some(id) = nod {
|
||||||
self.ring_assignation_data.push(id as CompactNodeType);
|
self.ring_assignation_data.push(id as CompactNodeType);
|
||||||
} else {
|
} else {
|
||||||
assert!(false)
|
panic!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -318,7 +318,7 @@ impl ClusterLayout {
|
||||||
|
|
||||||
self.node_id_vec = new_node_id_vec;
|
self.node_id_vec = new_node_id_vec;
|
||||||
self.ring_assignation_data = vec![];
|
self.ring_assignation_data = vec![];
|
||||||
return node_assignation;
|
node_assignation
|
||||||
}
|
}
|
||||||
|
|
||||||
///This function compute the number of partition to assign to
|
///This function compute the number of partition to assign to
|
||||||
|
@ -345,7 +345,7 @@ impl ClusterLayout {
|
||||||
//Compute the optimal number of partitions per zone
|
//Compute the optimal number of partitions per zone
|
||||||
let sum_capacities: u32 = zone_capacity.values().sum();
|
let sum_capacities: u32 = zone_capacity.values().sum();
|
||||||
|
|
||||||
if sum_capacities <= 0 {
|
if sum_capacities == 0 {
|
||||||
println!("No storage capacity in the network.");
|
println!("No storage capacity in the network.");
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -493,14 +493,10 @@ impl ClusterLayout {
|
||||||
.map(|id_nod| match self.node_role(id_nod) {
|
.map(|id_nod| match self.node_role(id_nod) {
|
||||||
Some(NodeRole {
|
Some(NodeRole {
|
||||||
zone: _,
|
zone: _,
|
||||||
capacity,
|
capacity: Some(c),
|
||||||
tags: _,
|
tags: _,
|
||||||
}) => {
|
}) => {
|
||||||
if let Some(c) = capacity {
|
|
||||||
*c
|
*c
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => 0,
|
_ => 0,
|
||||||
})
|
})
|
||||||
|
|
|
@ -31,8 +31,8 @@ struct WeightedEdge {
|
||||||
* as possible to old_match.
|
* as possible to old_match.
|
||||||
* */
|
* */
|
||||||
pub fn optimize_matching(
|
pub fn optimize_matching(
|
||||||
old_match: &Vec<Vec<usize>>,
|
old_match: &[Vec<usize>],
|
||||||
new_match: &Vec<Vec<usize>>,
|
new_match: &[Vec<usize>],
|
||||||
nb_right: usize,
|
nb_right: usize,
|
||||||
) -> Vec<Vec<usize>> {
|
) -> Vec<Vec<usize>> {
|
||||||
let nb_left = old_match.len();
|
let nb_left = old_match.len();
|
||||||
|
@ -72,17 +72,12 @@ pub fn optimize_matching(
|
||||||
//Discovering and flipping a cycle with positive weight in this
|
//Discovering and flipping a cycle with positive weight in this
|
||||||
//graph will make the matching closer to old_match.
|
//graph will make the matching closer to old_match.
|
||||||
//We use Bellman Ford algorithm to discover positive cycles
|
//We use Bellman Ford algorithm to discover positive cycles
|
||||||
loop {
|
while let Some(cycle) = positive_cycle(&edge_vec, nb_left, nb_right) {
|
||||||
if let Some(cycle) = positive_cycle(&edge_vec, nb_left, nb_right) {
|
|
||||||
for i in cycle {
|
for i in cycle {
|
||||||
//We flip the edges of the cycle.
|
//We flip the edges of the cycle.
|
||||||
(edge_vec[i].u, edge_vec[i].v) = (edge_vec[i].v, edge_vec[i].u);
|
(edge_vec[i].u, edge_vec[i].v) = (edge_vec[i].v, edge_vec[i].u);
|
||||||
edge_vec[i].w *= -1;
|
edge_vec[i].w *= -1;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
//If there is no cycle, we return the optimal matching.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//The optimal matching is build from the graph structure.
|
//The optimal matching is build from the graph structure.
|
||||||
|
@ -97,7 +92,7 @@ pub fn optimize_matching(
|
||||||
|
|
||||||
//This function finds a positive cycle in a bipartite wieghted graph.
|
//This function finds a positive cycle in a bipartite wieghted graph.
|
||||||
fn positive_cycle(
|
fn positive_cycle(
|
||||||
edge_vec: &Vec<WeightedEdge>,
|
edge_vec: &[WeightedEdge],
|
||||||
nb_left: usize,
|
nb_left: usize,
|
||||||
nb_right: usize,
|
nb_right: usize,
|
||||||
) -> Option<Vec<usize>> {
|
) -> Option<Vec<usize>> {
|
||||||
|
@ -122,8 +117,7 @@ fn positive_cycle(
|
||||||
//the number of partitions can be much larger than the
|
//the number of partitions can be much larger than the
|
||||||
//number of nodes, we optimize that.
|
//number of nodes, we optimize that.
|
||||||
for _ in 0..(2 * nb_side_min) {
|
for _ in 0..(2 * nb_side_min) {
|
||||||
for j in 0..edge_vec.len() {
|
for (j, e) in edge_vec.iter().enumerate() {
|
||||||
let e = edge_vec[j];
|
|
||||||
if weight[e.v] < weight[e.u] + e.w {
|
if weight[e.v] < weight[e.u] + e.w {
|
||||||
weight[e.v] = weight[e.u] + e.w;
|
weight[e.v] = weight[e.u] + e.w;
|
||||||
prev[e.v] = j;
|
prev[e.v] = j;
|
||||||
|
@ -148,8 +142,7 @@ fn positive_cycle(
|
||||||
curr = edge_vec[prev[curr]].u;
|
curr = edge_vec[prev[curr]].u;
|
||||||
}
|
}
|
||||||
//Now curr is on the cycle. We collect the edges ids.
|
//Now curr is on the cycle. We collect the edges ids.
|
||||||
let mut cycle = Vec::<usize>::new();
|
let mut cycle = vec![prev[curr]];
|
||||||
cycle.push(prev[curr]);
|
|
||||||
let mut cycle_vert = edge_vec[prev[curr]].u;
|
let mut cycle_vert = edge_vec[prev[curr]].u;
|
||||||
while cycle_vert != curr {
|
while cycle_vert != curr {
|
||||||
cycle.push(prev[cycle_vert]);
|
cycle.push(prev[cycle_vert]);
|
||||||
|
@ -180,16 +173,16 @@ pub fn dinic_compute_matching(left_cap_vec: Vec<u32>, right_cap_vec: Vec<u32>) -
|
||||||
|
|
||||||
// 0 will be the source
|
// 0 will be the source
|
||||||
graph.push(vec![ed; left_cap_vec.len()]);
|
graph.push(vec![ed; left_cap_vec.len()]);
|
||||||
for i in 0..left_cap_vec.len() {
|
for (i, c) in left_cap_vec.iter().enumerate() {
|
||||||
graph[0][i].c = left_cap_vec[i] as i32;
|
graph[0][i].c = *c as i32;
|
||||||
graph[0][i].v = i + 2;
|
graph[0][i].v = i + 2;
|
||||||
graph[0][i].rev = 0;
|
graph[0][i].rev = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//1 will be the sink
|
//1 will be the sink
|
||||||
graph.push(vec![ed; right_cap_vec.len()]);
|
graph.push(vec![ed; right_cap_vec.len()]);
|
||||||
for i in 0..right_cap_vec.len() {
|
for (i, c) in right_cap_vec.iter().enumerate() {
|
||||||
graph[1][i].c = right_cap_vec[i] as i32;
|
graph[1][i].c = *c as i32;
|
||||||
graph[1][i].v = i + 2 + left_cap_vec.len();
|
graph[1][i].v = i + 2 + left_cap_vec.len();
|
||||||
graph[1][i].rev = 0;
|
graph[1][i].rev = 0;
|
||||||
}
|
}
|
||||||
|
@ -267,18 +260,15 @@ pub fn dinic_compute_matching(left_cap_vec: Vec<u32>, right_cap_vec: Vec<u32>) -
|
||||||
let mut next_nbd = vec![0; nb_vertices];
|
let mut next_nbd = vec![0; nb_vertices];
|
||||||
let mut lifo = VecDeque::new();
|
let mut lifo = VecDeque::new();
|
||||||
|
|
||||||
let flow_upper_bound;
|
let flow_upper_bound = if let Some(x) = left_cap_vec.iter().max() {
|
||||||
if let Some(x) = left_cap_vec.iter().max() {
|
*x as i32
|
||||||
flow_upper_bound = *x as i32;
|
|
||||||
} else {
|
} else {
|
||||||
flow_upper_bound = 0;
|
panic!();
|
||||||
assert!(false);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
lifo.push_back((0, flow_upper_bound));
|
lifo.push_back((0, flow_upper_bound));
|
||||||
|
|
||||||
loop {
|
while let Some((id_tmp, f_tmp)) = lifo.back() {
|
||||||
if let Some((id_tmp, f_tmp)) = lifo.back() {
|
|
||||||
let id = *id_tmp;
|
let id = *id_tmp;
|
||||||
let f = *f_tmp;
|
let f = *f_tmp;
|
||||||
if id == 1 {
|
if id == 1 {
|
||||||
|
@ -316,9 +306,6 @@ pub fn dinic_compute_matching(left_cap_vec: Vec<u32>, right_cap_vec: Vec<u32>) -
|
||||||
}
|
}
|
||||||
//otherwise, we send flow to nbd.
|
//otherwise, we send flow to nbd.
|
||||||
lifo.push_back((graph[id][nbd].v, new_flow));
|
lifo.push_back((graph[id][nbd].v, new_flow));
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue